diff --git a/lib/Drupal/profile2/Plugin/Core/Entity/Profile.php b/lib/Drupal/profile2/Plugin/Core/Entity/Profile.php index fd569b8..033a559 100644 --- a/lib/Drupal/profile2/Plugin/Core/Entity/Profile.php +++ b/lib/Drupal/profile2/Plugin/Core/Entity/Profile.php @@ -113,6 +113,8 @@ class Profile extends Entity implements ContentEntityInterface { * Overrides Entity::label(). */ public function label($langcode = NULL) { + // If this profile has a custom label, use it. Otherwise, use the label of + // the profile type. if (isset($this->label) && $this->label !== '') { return $this->label; } diff --git a/lib/Drupal/profile2/ProfileAccessController.php b/lib/Drupal/profile2/ProfileAccessController.php index c80824b..1bd1cb7 100644 --- a/lib/Drupal/profile2/ProfileAccessController.php +++ b/lib/Drupal/profile2/ProfileAccessController.php @@ -7,9 +7,9 @@ namespace Drupal\profile2; -use Drupal\user\Plugin\Core\Entity\User; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityAccessControllerInterface; +use Drupal\user\Plugin\Core\Entity\User; /** * Access controller for profiles. @@ -27,7 +27,7 @@ class ProfileAccessController implements EntityAccessControllerInterface { * Implements EntityAccessControllerInterface::viewAccess(). */ public function viewAccess(EntityInterface $profile, $langcode = LANGUAGE_DEFAULT, User $account = NULL) { - return $this->access($profile, 'view', $account); + return $this->access($profile, 'view', $langcode, $account); } /** @@ -35,7 +35,7 @@ class ProfileAccessController implements EntityAccessControllerInterface { */ public function createAccess(EntityInterface $profile, $langcode = LANGUAGE_DEFAULT, User $account = NULL) { // Map to 'edit' access. - return $this->editAccess($profile, $langcode, $account); + return $this->access($profile, 'edit', $langcode, $account); } /** @@ -43,86 +43,69 @@ class ProfileAccessController implements EntityAccessControllerInterface { */ public function updateAccess(EntityInterface $profile, $langcode = LANGUAGE_DEFAULT, User $account = NULL) { // Map to 'edit' access. - return $this->editAccess($profile, $langcode, $account); + return $this->access($profile, 'edit', $langcode, $account); } /** * Implements EntityAccessControllerInterface::deleteAccess(). */ public function deleteAccess(EntityInterface $profile, $langcode = LANGUAGE_DEFAULT, User $account = NULL) { - return $this->access($profile, 'delete', $account); + return $this->access($profile, 'delete', $langcode, $account); } /** - * Checks 'edit' access for a profile. + * Determines whether the given user has access to a profile. * * @param \Drupal\Core\Entity\EntityInterface $profile - * The profile for which to check 'edit' access. + * A profile to check access for. + * @param string $operation + * The operation being performed. One of 'view', 'create', 'update', or + * 'delete'. * @param string $langcode - * (optional) The language code for which to check access. Defaults to - * LANGUAGE_DEFAULT. + * The language code for which to check access. * @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. + * (optional) The user to check for. Omit to check access for the global + * user. * * @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. + * TRUE if access is allowed, FALSE otherwise. * * @see hook_profile2_access() * @see profile2_profile2_access() */ - protected function access(EntityInterface $profile, $operation, User $account = NULL) { + protected function access(EntityInterface $profile, $operation, $langcode, User $account = NULL) { if (!isset($account)) { $account = entity_load('user', $GLOBALS['user']->uid); } + // Check for the bypass access permission first. No need to cache this, + // since user_access() is cached already. + if (user_access('bypass profile access', $account)) { + return TRUE; + } - // Try to retrieve from cache first. $pid = $profile->id(); $uid = $account->id(); - if (isset($this->accessCache[$uid][$operation][$pid])) { - return $this->accessCache[$uid][$operation][$pid]; - } - - // Administrators can access any profile. - if (user_access('administer profiles', $account)) { - $this->accessCache[$uid][$operation][$pid] = TRUE; - return TRUE; + if (isset($this->accessCache[$uid][$operation][$pid][$langcode])) { + return $this->accessCache[$uid][$operation][$pid][$langcode]; } $access = NULL; - // Allow modules to grant / deny access. + // Ask modules to grant or deny access. foreach (module_implements('profile2_access', $operation, $profile, $account) as $module) { $return = module_invoke($module, 'profile2_access', $operation, $profile, $account); + // If a module denies access, there's no point in asking further. if ($return === FALSE) { - // Directly return FALSE if a module denies access. - $this->accessCache[$uid][$operation][$pid] = FALSE; - return FALSE; + $access = $return; + break; } + // A module may grant access, but others may still deny. if ($return === TRUE) { $access = TRUE; } } + $this->accessCache[$uid][$operation][$pid][$langcode] = ($access === TRUE); - $this->accessCache[$uid][$operation][$pid] = $access === TRUE ?: FALSE; - return $this->accessCache[$uid][$operation][$pid]; + return $this->accessCache[$uid][$operation][$pid][$langcode]; } } diff --git a/lib/Drupal/profile2/ProfileFormController.php b/lib/Drupal/profile2/ProfileFormController.php index ccc4bb0..c717789 100644 --- a/lib/Drupal/profile2/ProfileFormController.php +++ b/lib/Drupal/profile2/ProfileFormController.php @@ -15,15 +15,11 @@ use Drupal\Core\Entity\EntityFormController; class ProfileFormController extends EntityFormController { /** - * Overrides EntityFormController::actionsElement(). + * Overrides EntityFormController::actions(). */ - protected function actionsElement(array $form, array &$form_state) { - $element = parent::actionsElement($form, $form_state); - - if (!$this->getEntity($form_state)->access('delete')) { - unset($element['delete']); - } - + protected function actions(array $form, array &$form_state) { + $element = parent::actions($form, $form_state); + $element['delete']['#access'] = $this->getEntity($form_state)->access('delete'); return $element; } diff --git a/lib/Drupal/profile2/ProfileTypeStorageController.php b/lib/Drupal/profile2/ProfileTypeStorageController.php index 90b4ac8..681882b 100644 --- a/lib/Drupal/profile2/ProfileTypeStorageController.php +++ b/lib/Drupal/profile2/ProfileTypeStorageController.php @@ -33,6 +33,8 @@ class ProfileTypeStorageController extends ConfigStorageController { * Overrides ConfigStorageController::preDelete(). */ protected function preDelete($entities) { + parent::preDelete($entities); + // Delete all profiles of this type. if ($profiles = entity_load_multiple_by_properties('profile2', array('type' => array_keys($entities)))) { entity_get_controller('profile2')->delete($profiles); diff --git a/lib/Drupal/profile2/Tests/ProfileCRUDTest.php b/lib/Drupal/profile2/Tests/ProfileCRUDTest.php index 8cf3e85..1358654 100644 --- a/lib/Drupal/profile2/Tests/ProfileCRUDTest.php +++ b/lib/Drupal/profile2/Tests/ProfileCRUDTest.php @@ -153,9 +153,7 @@ class ProfileCRUDTest extends DrupalUnitTestBase { $user2_profile1->id() => $user2_profile1, )); - // @todo - // Rename a profile type and verify that existing profiles are updated. - // Verify expected behavior of 'uid' => NULL; Profile2 supported this for whatever reason. + // @todo Rename a profile type; verify that existing profiles are updated. } } diff --git a/lib/Drupal/profile2/Tests/ProfileEditTest.php b/lib/Drupal/profile2/Tests/ProfileEditTest.php index 28f220f..4c5f6b1 100644 --- a/lib/Drupal/profile2/Tests/ProfileEditTest.php +++ b/lib/Drupal/profile2/Tests/ProfileEditTest.php @@ -104,7 +104,7 @@ class ProfileEditTest extends WebTestBase { $this->assertEqual($profiles['test2']->pid, $profiles2['test2']->pid, 'Profile successfully updated.'); // Delete a profile type. - profile2_type_load('test')->delete(); + entity_load('profile2_type', 'test')->delete(); // Try deleting multiple profiles by deleting all existing profiles. $pids = array_keys(entity_load_multiple('profile2')); diff --git a/lib/Drupal/profile2/Tests/ProfileFieldAccessTest.php b/lib/Drupal/profile2/Tests/ProfileFieldAccessTest.php new file mode 100644 index 0000000..605ee1d --- /dev/null +++ b/lib/Drupal/profile2/Tests/ProfileFieldAccessTest.php @@ -0,0 +1,101 @@ + 'Field access', + 'description' => 'Tests profile field access functionality.', + 'group' => 'Profile2', + ); + } + + function setUp() { + parent::setUp(); + + $this->type = entity_create('profile2_type', array( + 'id' => 'personal', + 'label' => 'Personal data', + 'weight' => 0, + 'registration' => TRUE, + )); + $this->type->save(); + + $this->checkPermissions(array(), TRUE); + $this->admin_user = $this->drupalCreateUser(array( + 'access user profiles', + 'administer profile types', + 'bypass profile access', + )); + $user_permissions = array( + 'access user profiles', + 'edit own personal profile', + 'view any personal profile', + ); + $this->web_user = $this->drupalCreateUser($user_permissions); + $this->other_user = $this->drupalCreateUser($user_permissions); + } + + /** + * Tests private profile field access. + */ + function testPrivateField() { + $id = $this->type->id(); + + $this->drupalLogin($this->admin_user); + + // Create a private profile field. + $edit = array( + 'fields[_add_new_field][label]' => 'Secret', + 'fields[_add_new_field][field_name]' => 'secret', + 'fields[_add_new_field][type]' => 'text', + 'fields[_add_new_field][widget_type]' => 'text_textfield', + ); + $this->drupalPost("admin/people/profiles/manage/$id/fields", $edit, t('Save')); + + $edit = array( + 'field[settings][profile2_private]' => 1, + ); + $this->drupalPost(NULL, $edit, t('Save field settings')); + + $this->drupalPost(NULL, array(), t('Save settings')); + + // Fill in a field value. + $this->drupalLogin($this->web_user); + $uid = $this->web_user->id(); + $secret = $this->randomName(); + $edit = array( + 'field_secret[und][0][value]' => $secret, + ); + $this->drupalPost("user/$uid/edit/$id", $edit, t('Save')); + + // Verify that the private field value appears for the profile owner. + $this->drupalGet("user/$uid"); + $this->assertText($secret); + + // Verify that the private field value appears for the administrator. + $this->drupalLogin($this->admin_user); + $this->drupalGet("user/$uid"); + $this->assertText($secret); + + // Verify that the private field value does not appear for other users. + $this->drupalLogin($this->other_user); + $this->drupalGet("user/$uid"); + $this->assertNoText($secret); + } + +} diff --git a/profile2.admin.inc b/profile2.admin.inc index 34e4d61..be4f156 100644 --- a/profile2.admin.inc +++ b/profile2.admin.inc @@ -8,6 +8,14 @@ use Drupal\profile2\Plugin\Core\Entity\ProfileType; /** + * Page callback; Lists available ProfileType objects. + */ +function profile2_type_list_page() { + $controller = entity_list_controller('profile2_type'); + return $controller->render(); +} + +/** * Page callback: Presents the form for creating a profile type. * * @return array @@ -43,7 +51,7 @@ function profile2_type_delete_form($form, &$form_state, ProfileType $type) { $form['id'] = array('#type' => 'value', '#value' => $type->id()); return confirm_form($form, - t('Are you sure you want to delete %label', array('%label' => $type->label())), + t('Are you sure you want to delete %label and all of its associated profiles?', array('%label' => $type->label())), 'admin/people/profiles', NULL, t('Delete') @@ -55,5 +63,8 @@ function profile2_type_delete_form($form, &$form_state, ProfileType $type) { */ function profile2_type_delete_form_submit($form, &$form_state) { $form_state['profile2_type']->delete(); + drupal_set_message(t('The profile type %label has been deleted.', array( + '%label' => $form_state['profile2_type']->label(), + ))); $form_state['redirect'] = 'admin/people/profiles'; } diff --git a/profile2.api.php b/profile2.api.php index ffe8a85..d1cbaf6 100644 --- a/profile2.api.php +++ b/profile2.api.php @@ -2,39 +2,38 @@ /** * @file - * This file contains no working PHP code; it exists to provide additional - * documentation for doxygen as well as to document hooks in the standard - * Drupal manner. + * Hooks provided by Profile2 module. */ -use Drupal\profile2\Plugin\Core\Entity\Profile; -use Drupal\user\Plugin\Core\Entity\User; - /** * @addtogroup hooks * @{ */ /** - * Control access to profiles. + * Control access to a user profile. * - * Modules may implement this hook if they want to have a say in whether or not - * a given user has access to perform a given operation on a profile. + * Modules may implement this hook to control whether a user has access to + * perform a certain operation on a profile. * - * @param $op + * @param string $op * The operation being performed. One of 'view', 'edit' (being the same as - * 'create' or 'update') and 'delete'. - * @param $profile + * 'create' or 'update'), or 'delete'. + * @param Drupal\profile2\Plugin\Core\Entity\Profile $profile * A profile to check access for. - * @param $account - * (optional) The user to check for. Defaults to the currently logged in user. - * @return boolean - * Return TRUE to grant access, FALSE to explicitly deny access. Return NULL - * or nothing to not affect the operation. - * Access is granted as soon as a module grants access and no one denies - * access. Thus if no module explicitly grants access, access will be denied. + * @param Drupal\user\Plugin\Core\Entity\User $account + * The user performing the operation; the currently logged in user by default. + * + * @return bool + * Either a Boolean or NULL: + * - FALSE to explicitly deny access. If a module denies access, no other + * module is able to grant access and access is denied. + * - TRUE to grant access. Access is only granted if at least one module + * grants access and no module denies access. + * - NULL or nothing to not affect the operation. If no module explicitly + * grants access, access is denied. */ -function hook_profile2_access($op, Profile $profile, User $account = NULL) { +function hook_profile2_access($op, Drupal\profile2\Plugin\Core\Entity\Profile $profile, Drupal\user\Plugin\Core\Entity\User $account) { // Explicitly deny access for a 'secret' profile type. if ($profile->type == 'secret' && !user_access('custom permission')) { return FALSE; diff --git a/profile2.install b/profile2.install index 1fbb5ae..9a7a3a6 100644 --- a/profile2.install +++ b/profile2.install @@ -37,6 +37,13 @@ function profile2_schema() { 'default' => NULL, 'description' => "The {users}.uid of the associated user.", ), + 'langcode' => array( + 'description' => 'The {language}.langcode of this profile.', + 'type' => 'varchar', + 'length' => 12, + 'not null' => TRUE, + 'default' => '', + ), 'label' => array( 'description' => 'A human-readable label for this profile.', 'type' => 'varchar', diff --git a/profile2.module b/profile2.module index 9cfabae..a3ffb18 100644 --- a/profile2.module +++ b/profile2.module @@ -10,10 +10,9 @@ use Drupal\profile2\Plugin\Core\Entity\ProfileType; use Drupal\user\Plugin\Core\Entity\User; /** - * Implements hook_entity_info_alter(). + * Implements hook_entity_info(). */ -function profile2_entity_info_alter(&$info) { - // Add bundle info but bypass entity_load() as we cannot use it here. +function profile2_entity_info(&$info) { $config_names = config_get_storage_names_with_prefix('profile2.type.'); foreach ($config_names as $config_name) { $config = config($config_name); @@ -23,7 +22,7 @@ function profile2_entity_info_alter(&$info) { 'path' => 'admin/people/profiles/manage/%profile2_type', 'real path' => 'admin/people/profiles/manage/' . $config->get('id'), 'bundle argument' => 4, - 'access arguments' => array('administer profiles'), + 'access arguments' => array('administer profile types'), ), ); } @@ -59,12 +58,13 @@ function profile2_profile_type_uri(ProfileType $profile_type) { function profile2_menu() { $items['admin/people/profiles'] = array( 'title' => 'Profile types', - 'description' => 'Manage profiles, including fields.', + 'description' => 'Manage profile types, including fields.', 'page callback' => 'profile2_type_list_page', 'access arguments' => array('administer profile types'), 'type' => MENU_LOCAL_TASK, // @todo User module: Apply custom/higher weights to Permissions and Roles. 'weight' => -1, + 'file' => 'profile2.admin.inc', ); $items['admin/people/profiles/add'] = array( 'title' => 'Add profile type', @@ -91,7 +91,6 @@ function profile2_menu() { 'page arguments' => array('profile2_type_delete_form', 4), 'access arguments' => array('administer profile types'), 'type' => MENU_LOCAL_TASK, - 'context' => MENU_CONTEXT_INLINE, 'file' => 'profile2.admin.inc', ); @@ -102,21 +101,21 @@ function profile2_menu() { 'weight' => -10, ); $items['user/%user/edit/%profile2_menu'] = array( - 'load arguments' => array('%map', 'edit'), + 'load arguments' => array(1, 'edit'), 'title' => 'Edit profile', - 'title callback' => 'profile2_menu_title_profile', + 'title callback' => 'entity_page_label', 'title arguments' => array(3), 'access callback' => 'profile2_access', - 'access arguments' => array('edit', 3), - 'page callback' => 'profile2_profile_edit', + 'access arguments' => array(3, 'edit'), + 'page callback' => 'entity_get_form', 'page arguments' => array(3), 'type' => MENU_LOCAL_TASK, ); $items['user/%user/edit/%profile2_menu/delete'] = array( - 'load arguments' => array('%map', 'edit'), + 'load arguments' => array(1, 'delete'), 'title' => 'Delete profile', 'access callback' => 'profile2_access', - 'access arguments' => array('delete', 3), + 'access arguments' => array(3, 'delete'), 'page callback' => 'drupal_get_form', 'page arguments' => array('profile2_delete_confirm_form', 3), 'type' => MENU_VISIBLE_IN_BREADCRUMB, @@ -130,9 +129,8 @@ function profile2_menu() { * * @param string $type_id * The profile type ID to load. - * @param array $map - * The menu router argument map. The loaded user account is expected as second - * argument. + * @param Drupal\user\Plugin\Core\Entity\User $account + * The user account for which to load the profile. * @param string $op * (optional) The operation to perform. If 'edit' and if there is no profile * for the user account yet, a new profile entity will be created on the fly. @@ -140,14 +138,10 @@ function profile2_menu() { * @return Drupal\profile2\Plugin\Core\Entity\Profile|false * The profile of type $type_id of the user account, or FALSE. */ -function profile2_menu_load($type_id, $map, $op = '') { - if ($type_id === '') { - return FALSE; - } - if (!isset($map[1]) || !($map[1] instanceof User)) { +function profile2_menu_load($type_id, User $account, $op = '') { + if ($type_id === '' || !$account->id()) { return FALSE; } - $account = $map[1]; $profiles = entity_load_multiple_by_properties('profile2', array( 'uid' => $account->id(), 'type' => $type_id, @@ -155,26 +149,13 @@ function profile2_menu_load($type_id, $map, $op = '') { if ($op == 'edit' && !$profile = reset($profiles)) { $profile = entity_create('profile2', array( 'type' => $type_id, - 'uid' => $account->uid, + 'uid' => $account->id(), )); } return $profile; } /** - * Menu title callback for a profile edit link. - * - * @param Drupal\profile2\Plugin\Core\Entity\Profile $profile - * The profile to return a title for. - * - * @return string - * The unsanitized profile label. - */ -function profile2_menu_title_profile(Profile $profile) { - return $profile->label(); -} - -/** * Implements hook_menu_local_tasks_alter(). */ function profile2_menu_local_tasks_alter(&$data, $router_item, $root_path) { @@ -219,14 +200,6 @@ function profile2_menu_local_tasks_alter(&$data, $router_item, $root_path) { } /** - * Page callback; Lists available ProfileType objects. - */ -function profile2_type_list_page() { - $controller = entity_list_controller('profile2_type'); - return $controller->render(); -} - -/** * Menu argument loader; Load a profile type by string. * * @param string $id @@ -246,34 +219,35 @@ function profile2_permission() { $permissions = array( 'administer profile types' => array( 'title' => t('Administer profile types'), - 'description' => t('Create and delete fields on user profiles and set their permissions.'), + 'restrict access' => TRUE, ), - 'administer profiles' => array( - 'title' => t('Administer profiles'), - 'description' => t('Edit and view all user profiles.'), + 'bypass profile access' => array( + 'title' => t('Bypass profile access'), + 'description' => t('View and edit all user profiles, including private field values.'), + 'restrict access' => TRUE, ), ); // Generate per profile type permissions. foreach (entity_load_multiple('profile2_type') as $type) { - $type_name = $type->id(); + $type_id = $type->id(); $permissions += array( - "edit own $type_name profile" => array( - 'title' => t('%type_name: Edit own profile', array('%type_name' => $type->label())), + "view own $type_id profile" => array( + 'title' => t('%type: View own profile', array('%type' => $type->label())), ), - "edit any $type_name profile" => array( - 'title' => t('%type_name: Edit any profile', array('%type_name' => $type->label())), + "view any $type_id profile" => array( + 'title' => t('%type: View any profile', array('%type' => $type->label())), ), - "view own $type_name profile" => array( - 'title' => t('%type_name: View own profile', array('%type_name' => $type->label())), + "edit own $type_id profile" => array( + 'title' => t('%type: Edit own profile', array('%type' => $type->label())), ), - "view any $type_name profile" => array( - 'title' => t('%type_name: View any profile', array('%type_name' => $type->label())), + "edit any $type_id profile" => array( + 'title' => t('%type: Edit any profile', array('%type' => $type->label())), ), - "delete own $type_name profile" => array( - 'title' => t('%type_name: Delete own profile', array('%type_name' => $type->label())), + "delete own $type_id profile" => array( + 'title' => t('%type: Delete own profile', array('%type' => $type->label())), ), - "delete any $type_name profile" => array( - 'title' => t('%type_name: Delete any profile', array('%type_name' => $type->label())), + "delete any $type_id profile" => array( + 'title' => t('%type: Delete any profile', array('%type' => $type->label())), ), ); } @@ -336,22 +310,6 @@ function profile2_form_user_register_form_alter(&$form, &$form_state) { } /** - * Page callback; Presents the form to edit a profile of a user. - * - * @param Drupal\profile2\Plugin\Core\Entity\Profile $profile - * The user account profile to edit. - * - * @return array - * A form array as expected by drupal_render(). - * - * @see profile2_user_form_validate() - * @see profile2_user_form_submit() - */ -function profile2_profile_edit(Profile $profile) { - return entity_get_form($profile); -} - -/** * Attaches the profile forms of the profiles set in $form_state['profiles']. * * Modules may alter the profile2 entity form regardless to which form it is @@ -363,7 +321,6 @@ function profile2_profile_edit(Profile $profile) { * also adds in a validation and a submit handler caring for the attached * profile forms. * - * @see hook_form_profile2_form_alter() * @see profile2_user_form_validate() * @see profile2_user_form_submit() */ @@ -383,12 +340,11 @@ function profile2_attach_form(&$form, &$form_state) { // Provide a central place for modules to alter the profile forms, but // skip that in case the caller cares about invoking the hooks. - // @see profile2_form(). if (!isset($form_state['profile2_skip_hook'])) { $hooks = array(); - $hooks[] = 'form_profile2_edit_' . $bundle . '_form'; + $hooks[] = 'form_' . $bundle . '_profile2_form'; $hooks[] = 'form_profile2_form'; - drupal_alter($hooks, $form, $form_state); + drupal_alter($hooks, $form['profile_' . $bundle], $form_state); } } } @@ -415,9 +371,6 @@ function profile2_user_form_validate(&$form, &$form_state) { */ function profile2_user_form_submit(&$form, &$form_state) { profile2_form_submit_build_profile($form, $form_state); - // This is needed as some submit callbacks like user_register_submit() rely on - // clean form values. - profile2_form_submit_cleanup($form, $form_state); foreach ($form_state['profiles'] as $bundle => $profile) { // During registration set the uid field of the newly created user. @@ -426,11 +379,6 @@ function profile2_user_form_submit(&$form, &$form_state) { } $profile->save(); } - - // Show message only in profile edit form. - if ($form['#form_id'] == 'profile2_user_form') { - drupal_set_message(t('The changes have been saved.')); - } } /** @@ -451,22 +399,12 @@ function profile2_form_submit_build_profile(&$form, &$form_state) { } /** - * Cleans up the form values as the user modules relies on clean values. - * - * @see profile2_attach_form() - */ -function profile2_form_submit_cleanup(&$form, &$form_state) { - foreach ($form_state['profiles'] as $bundle => $profile) { - unset($form_state['values']['profile_' . $bundle]); - } -} - -/** * Helper function for checking profile access. - * - * @todo Remove once the routes are converted to the new routing system. */ -function profile2_access($op, Profile $profile, User $account = NULL) { +function profile2_access(Profile $profile, $op, User $account = NULL) { + if ($op == 'edit') { + $op = ($profile->isNew() ? 'create' : 'update'); + } return $profile->access($op, $account); } @@ -474,15 +412,9 @@ function profile2_access($op, Profile $profile, User $account = NULL) { * Implements hook_profile2_access(). */ function profile2_profile2_access($op, Profile $profile, User $account) { - // Don't grant access for users to delete their profile. - if ($op == 'delete') { - return; - } - 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; } @@ -560,20 +492,19 @@ function template_preprocess_profile2(&$variables) { * Adds a checkbox for controlling field view access to fields added to * profiles. */ -function profile2_form_field_ui_field_edit_form_alter(&$form, &$form_state) { - if ($form['instance']['entity_type']['#value'] == 'profile2') { +function profile2_form_field_ui_field_settings_form_alter(&$form, &$form_state) { + // Only add the field setting if this field is attached to a profile entity + // bundle. + if (isset($form['#field']['bundles']['profile2'])) { $form['field']['settings']['profile2_private'] = array( '#type' => 'checkbox', - '#title' => t('Make the content of this field private.'), + '#title' => t('Private field'), '#default_value' => !empty($form['#field']['settings']['profile2_private']), - '#description' => t('If checked, the content of this field is only shown to the profile owner and administrators.'), - ); - } - else { - // Add the value to the form so it isn't lost. - $form['field']['settings']['profile2_private'] = array( - '#type' => 'value', - '#value' => !empty($form['#field']['settings']['profile2_private']), + // Only expose the setting when editing the settings for a field attached + // to a profile entity bundle. For other entity types, we just ensure that + // the existing value is retained. + '#access' => $form['#entity_type'] == 'profile2', + '#description' => t('Only show the field content to the profile owner and administrators.'), ); } } @@ -582,7 +513,7 @@ function profile2_form_field_ui_field_edit_form_alter(&$form, &$form_state) { * Implements hook_field_access(). */ function profile2_field_access($op, $field, $entity_type, $profile = NULL, $account = NULL) { - if ($entity_type == 'profile2' && $op == 'view' && !empty($field['settings']['profile2_private']) && !user_access('administer profiles', $account)) { + if ($entity_type == 'profile2' && $op == 'view' && !empty($field['settings']['profile2_private']) && !user_access('bypass profile access', $account)) { // For profiles, deny general view access for private fields. if (!isset($profile)) { return FALSE;