diff --git a/lib/Drupal/profile2/Plugin/Core/Entity/Profile.php b/lib/Drupal/profile2/Plugin/Core/Entity/Profile.php index 67addf4..294e7e8 100644 --- a/lib/Drupal/profile2/Plugin/Core/Entity/Profile.php +++ b/lib/Drupal/profile2/Plugin/Core/Entity/Profile.php @@ -20,6 +20,7 @@ use Drupal\Core\Annotation\Translation; * label = @Translation("Profile"), * module = "profile2", * controller_class = "Drupal\profile2\ProfileStorageController", + * access_controller_class = "Drupal\profile2\ProfileAccessController", * form_controller_class = { * "default" = "Drupal\profile2\ProfileFormController" * }, diff --git a/lib/Drupal/profile2/ProfileAccessController.php b/lib/Drupal/profile2/ProfileAccessController.php new file mode 100644 index 0000000..1308d2f --- /dev/null +++ b/lib/Drupal/profile2/ProfileAccessController.php @@ -0,0 +1,127 @@ +access($profile, 'view', $account); + } + + /** + * Implements EntityAccessControllerInterface::createAccess(). + */ + public function createAccess(EntityInterface $profile, $langcode = LANGUAGE_DEFAULT, User $account = NULL) { + // Map to 'edit' access. + return $this->editAccess($profile, $langcode, $account); + } + + /** + * Implements EntityAccessControllerInterface::updateAccess(). + */ + public function updateAccess(EntityInterface $profile, $langcode = LANGUAGE_DEFAULT, User $account = NULL) { + // Map to 'edit' access. + return $this->editAccess($profile, $langcode, $account); + } + + /** + * Implements EntityAccessControllerInterface::deleteAccess(). + */ + public function deleteAccess(EntityInterface $profile, $langcode = LANGUAGE_DEFAULT, User $account = NULL) { + return $this->access($profile, 'delete', $account); + } + + /** + * Checks 'edit' access for a profile. + * + * @param \Drupal\Core\Entity\EntityInterface $profile + * The profile for which to check 'edit' access. + * @param string $langcode + * (optional) The language code for which to check access. Defaults to + * LANGUAGE_DEFAULT. + * @param \Drupal\user\Plugin\Core\Entity\User $account + * (optional) The user for which to check access, or NULL to check access + * for the current user. Defaults to NULL. + * + * @return bool + * TRUE if access was granted, FALSE otherwise. + */ + public function editAccess(EntityInterface $profile, $langcode = LANGUAGE_DEFAULT, User $account = NULL) { + return $this->access($profile, 'edit', $account); + } + + /** + * Determines whether the given user has access to a profile. + * + * @param \Drupal\Core\Entity\EntityInterface $profile + * (optional) A profile to check access for. If nothing is given, access for + * all profiles is determined. + * @param string $operation + * The operation being performed. One of 'view', 'update', 'create', + * 'delete' or just 'edit' (being the same as 'create' or 'update'). + * @param \Drupal\user\Plugin\Core\Entity\User $account + * The user to check for. Leave it to NULL to check for the global user. + * @return boolean + * TRUE if access was granted, FALSE otherwise. + * + * @see hook_profile2_access() + * @see profile2_profile2_access() + */ + protected function access(EntityInterface $profile, $operation, User $account = NULL) { + if (!isset($account)) { + $account = $GLOBALS['user']; + } + + // Try to retrieve from cache first. + $cid = $account->uid . ':' . $operation . ':' . $profile->id(); + if (isset($this->accessCache[$cid])) { + return $this->accessCache[$cid]; + } + + // Administrators can access any profile. + if (user_access('administer profiles', $account)) { + $this->accessCache[$cid] = TRUE; + return TRUE; + } + + $access = NULL; + // Allow modules to grant / deny access. + foreach (module_implements('profile2_access', $operation, $profile, $account) as $module) { + $return = module_invoke($module, 'profile2_access', $operation, $profile, $account); + if ($return === FALSE) { + // Directly return FALSE if a module denies access. + $this->accessCache[$cid] = FALSE; + return FALSE; + } + if ($return === TRUE) { + $access = TRUE; + } + } + + $this->accessCache[$cid] = $access === TRUE ?: FALSE; + return $this->accessCache[$cid]; + } + +} diff --git a/lib/Drupal/profile2/ProfileFormController.php b/lib/Drupal/profile2/ProfileFormController.php index 0913f6a..41681ad 100644 --- a/lib/Drupal/profile2/ProfileFormController.php +++ b/lib/Drupal/profile2/ProfileFormController.php @@ -20,7 +20,7 @@ class ProfileFormController extends EntityFormController { protected function actionsElement(array $form, array &$form_state) { $element = parent::actionsElement($form, $form_state); - if (!profile2_access('delete', $this->getEntity($form_state))) { + if (!$this->getEntity($form_state)->access('delete')) { unset($element['delete']); } diff --git a/profile2.module b/profile2.module index 6b73ed9..5df23de 100644 --- a/profile2.module +++ b/profile2.module @@ -108,8 +108,8 @@ function profile2_menu() { 'title' => 'Edit profile', 'title callback' => 'profile2_menu_title_profile', 'title arguments' => array(3), - 'access callback' => 'profile2_profile_edit_access', - 'access arguments' => array(3), + 'access callback' => 'profile2_access', + 'access arguments' => array('edit', 3), 'page callback' => 'profile2_profile_edit', 'page arguments' => array(3), 'type' => MENU_LOCAL_TASK, @@ -326,8 +326,8 @@ function profile2_user_predelete($account) { */ function profile2_user_view($account, $view_mode, $langcode) { foreach (entity_load_multiple('profile2_type') as $id => $type) { - if ($type->userView && $profile = profile2_load_by_user($account, $id)) { - if (profile2_access('view', $profile)) { + if ($profile = profile2_load_by_user($account, $id)) { + if ($profile->access('view')) { $account->content['profile_' . $id] = array( '#type' => 'user_profile_category', '#title' => $profile->label(), @@ -363,20 +363,6 @@ function profile2_form_user_register_form_alter(&$form, &$form_state) { } /** - * Menu access callback; Determines edit access for a requested profile. - * - * @param Drupal\profile2\Plugin\Core\Entity\Profile $profile - * The profile to check for edit access. - * - * @return bool - * - * @see profile2_access() - */ -function profile2_profile_edit_access(Profile $profile) { - return profile2_access('edit', $profile); -} - -/** * Page callback; Presents the form to edit a profile of a user. * * @param Drupal\profile2\Plugin\Core\Entity\Profile $profile @@ -503,57 +489,29 @@ function profile2_form_submit_cleanup(&$form, &$form_state) { } /** - * Determines whether the given user has access to a profile. - * - * @param $op - * The operation being performed. One of 'view', 'update', 'create', 'delete' - * or just 'edit' (being the same as 'create' or 'update'). - * @param $profile - * (optional) A profile to check access for. If nothing is given, access for - * all profiles is determined. - * @param $account - * The user to check for. Leave it to NULL to check for the global user. - * @return boolean - * Whether access is allowed or not. + * Helper function for checking profile access. * - * @see hook_profile2_access() - * @see profile2_profile2_access() + * @todo Remove once the routes are converted to the new routing system. */ -function profile2_access($op, Profile $profile = NULL, User $account = NULL) { - if (user_access('administer profiles', $account)) { - return TRUE; - } - if ($op == 'create' || $op == 'update') { - $op = 'edit'; - } - // Allow modules to grant / deny access. - $access = module_invoke_all('profile2_access', $op, $profile, $account); - - // Only grant access if at least one module granted access and no one denied - // access. - if (in_array(FALSE, $access, TRUE)) { - return FALSE; - } - elseif (in_array(TRUE, $access, TRUE)) { - return TRUE; - } - return FALSE; +function profile2_access($op, Profile $profile, User $account = NULL) { + return $profile->access($op, $account); } /** * Implements hook_profile2_access(). */ -function profile2_profile2_access($op, Profile $profile = NULL, User $account = NULL) { +function profile2_profile2_access($op, Profile $profile, User $account) { // Don't grant access for users to delete their profile. - if (isset($profile) && ($type_name = $profile->type) && $op != 'delete') { - if (user_access("$op any $type_name profile", $account)) { - return TRUE; - } - $account = isset($account) ? $account : $GLOBALS['user']; + if ($op == 'delete') { + return; + } - if (isset($profile->uid) && $profile->uid == $account->uid && user_access("$op own $type_name profile", $account)) { - return TRUE; - } + if (user_access("$op any $profile->type profile", $account)) { + return TRUE; + } + + if (isset($profile->uid) && $profile->uid == $account->uid && user_access("$op own $profile->type profile", $account)) { + return TRUE; } // Do not explicitly deny access so others may still grant access. }