diff --git a/core/lib/Drupal/Core/Session/SessionHandler.php b/core/lib/Drupal/Core/Session/SessionHandler.php index c8d69fb..b71f027 100644 --- a/core/lib/Drupal/Core/Session/SessionHandler.php +++ b/core/lib/Drupal/Core/Session/SessionHandler.php @@ -121,7 +121,7 @@ public function read($sid) { // active user. if ($values && $values['uid'] > 0 && $values['status'] == 1) { // Add roles element to $user. - $rids = $this->connection->query("SELECT ur.rid FROM {users_roles} ur WHERE ur.uid = :uid", array( + $rids = $this->connection->query("SELECT ur.roles_target_id as rid FROM {user__roles} ur WHERE ur.entity_id = :uid", array( ':uid' => $values['uid'], ))->fetchCol(); $values['roles'] = array_merge(array(DRUPAL_AUTHENTICATED_RID), $rids); diff --git a/core/modules/system/src/Tests/Entity/EntityUnitTestBase.php b/core/modules/system/src/Tests/Entity/EntityUnitTestBase.php index ada31f2..0ce5e04 100644 --- a/core/modules/system/src/Tests/Entity/EntityUnitTestBase.php +++ b/core/modules/system/src/Tests/Entity/EntityUnitTestBase.php @@ -56,8 +56,7 @@ protected function setUp() { * @param array $values * (optional) The values used to create the entity. * @param array $permissions - * (optional) Array of permission names to assign to user. The - * users_roles tables must be installed before this can be used. + * (optional) Array of permission names to assign to user. * * @return \Drupal\user\Entity\User * The created user entity. diff --git a/core/modules/user/config/install/views.view.user_admin_people.yml b/core/modules/user/config/install/views.view.user_admin_people.yml index ee79c86..623c960 100644 --- a/core/modules/user/config/install/views.view.user_admin_people.yml +++ b/core/modules/user/config/install/views.view.user_admin_people.yml @@ -296,10 +296,10 @@ display: not: '0' plugin_id: boolean provider: views - rid: - id: rid - table: users_roles - field: rid + roles_target_id: + id: roles_target_id + table: user__roles + field: roles_target_id relationship: none group_type: group admin_label: '' @@ -558,7 +558,7 @@ display: user_bulk_form: '0' name: '0' status: '0' - rid: '0' + roles_target_id: '0' created: '0' access: '0' destination: true @@ -655,10 +655,10 @@ display: name: name mail: mail plugin_id: combine - rid: - id: rid - table: users_roles - field: rid + roles_target_id: + id: roles_target_id + table: user__roles + field: roles_target_id relationship: none group_type: group admin_label: '' @@ -667,11 +667,11 @@ display: group: 1 exposed: true expose: - operator_id: rid_op + operator_id: roles_target_id_op label: Role description: '' use_operator: false - operator: rid_op + operator: roles_target_id_op identifier: role required: false remember: false @@ -698,7 +698,7 @@ display: provider: user permission: id: permission - table: users_roles + table: user__roles field: permission relationship: none group_type: group diff --git a/core/modules/user/config/schema/user.views.schema.yml b/core/modules/user/config/schema/user.views.schema.yml index fc8a7fd..b879285 100644 --- a/core/modules/user/config/schema/user.views.schema.yml +++ b/core/modules/user/config/schema/user.views.schema.yml @@ -23,7 +23,7 @@ views.argument.user_uid: type: views.argument.numeric label: 'User ID' -views.argument.users_roles_rid: +views.argument.user__roles_rid: type: views.argument.many_to_one label: 'Role ID' diff --git a/core/modules/user/src/Entity/User.php b/core/modules/user/src/Entity/User.php index ee75930..b487eeb 100644 --- a/core/modules/user/src/Entity/User.php +++ b/core/modules/user/src/Entity/User.php @@ -74,19 +74,16 @@ public function isNew() { /** * {@inheritdoc} */ - static function preCreate(EntityStorageInterface $storage, array &$values) { - parent::preCreate($storage, $values); - - // Users always have the authenticated user role. - $values['roles'][] = DRUPAL_AUTHENTICATED_RID; - } - - /** - * {@inheritdoc} - */ public function preSave(EntityStorageInterface $storage) { parent::preSave($storage); + // Make sure that the authenticated/anonymous roles are not persisted. + foreach ($this->get('roles') as $index => $item) { + if (in_array($item->target_id, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) { + $this->get('roles')->offsetUnset($index); + } + } + // Update the user password if it has changed. if ($this->isNew() || ($this->pass->value && $this->pass->value != $this->original->pass->value)) { // Allow alternate password hashing schemes. @@ -130,12 +127,6 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) { } } - // Update user roles if changed. - if ($this->getRoles() != $this->original->getRoles()) { - $storage->deleteUserRoles(array($this->id())); - $storage->saveRoles($this); - } - // If the user was blocked, delete the user's sessions to force a logout. if ($this->original->status->value != $this->status->value && $this->status->value == 0) { $session_manager->delete($this->id()); @@ -148,12 +139,6 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) { _user_mail_notify($op, $this); } } - else { - // Save user roles. - if (count($this->getRoles()) > 1) { - $storage->saveRoles($this); - } - } } /** @@ -164,7 +149,6 @@ public static function postDelete(EntityStorageInterface $storage, array $entiti $uids = array_keys($entities); \Drupal::service('user.data')->delete(NULL, $uids); - $storage->deleteUserRoles($uids); } /** @@ -173,8 +157,18 @@ public static function postDelete(EntityStorageInterface $storage, array $entiti public function getRoles($exclude_locked_roles = FALSE) { $roles = array(); + // User with an ID always have the authenticated user role. + if (!$exclude_locked_roles) { + if ($this->isAuthenticated()) { + $roles[] = DRUPAL_AUTHENTICATED_RID; + } + else { + $roles[] = DRUPAL_ANONYMOUS_RID; + } + } + foreach ($this->get('roles') as $role) { - if (!($exclude_locked_roles && in_array($role->target_id, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID)))) { + if ($role->target_id) { $roles[] = $role->target_id; } } @@ -532,7 +526,6 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setDefaultValue(''); $fields['roles'] = BaseFieldDefinition::create('entity_reference') - ->setCustomStorage(TRUE) ->setLabel(t('Roles')) ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED) ->setDescription(t('The roles the user has.')) diff --git a/core/modules/user/src/Plugin/entity_reference/selection/UserSelection.php b/core/modules/user/src/Plugin/entity_reference/selection/UserSelection.php index 3820628..5705fef 100644 --- a/core/modules/user/src/Plugin/entity_reference/selection/UserSelection.php +++ b/core/modules/user/src/Plugin/entity_reference/selection/UserSelection.php @@ -88,6 +88,12 @@ public function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') { $query->condition('name', $match, $match_operator); } + // Filter by role. + $handler_settings = $this->fieldDefinition->getSetting('handler_settings'); + if (!empty($handler_settings['filter']['role'])) { + $query->condition('roles', $handler_settings['filter']['role'], 'IN'); + } + // Adding the permission check is sadly insufficient for users: core // requires us to also know about the concept of 'blocked' and 'active'. if (!\Drupal::currentUser()->hasPermission('administer users')) { @@ -131,16 +137,5 @@ public function entityQueryAlter(SelectInterface $query) { } } } - - // Add the filter by role option. - if (!empty($this->fieldDefinition->getSetting('handler_settings')['filter'])) { - $filter_settings = $this->fieldDefinition->getSetting('handler_settings')['filter']; - if ($filter_settings['type'] == 'role') { - $tables = $query->getTables(); - $base_table = $tables['base_table']['alias']; - $query->join('users_roles', 'ur', $base_table . '.uid = ur.uid'); - $query->condition('ur.rid', $filter_settings['role']); - } - } } } diff --git a/core/modules/user/src/Plugin/views/argument/RolesRid.php b/core/modules/user/src/Plugin/views/argument/RolesRid.php index 8c7fc7f..bbc5ab9 100644 --- a/core/modules/user/src/Plugin/views/argument/RolesRid.php +++ b/core/modules/user/src/Plugin/views/argument/RolesRid.php @@ -17,7 +17,7 @@ * * @ingroup views_argument_handlers * - * @ViewsArgument("users_roles_rid") + * @ViewsArgument("user__roles_rid") */ class RolesRid extends ManyToOne { diff --git a/core/modules/user/src/Plugin/views/field/Roles.php b/core/modules/user/src/Plugin/views/field/Roles.php index 57506a8..3122ab0 100644 --- a/core/modules/user/src/Plugin/views/field/Roles.php +++ b/core/modules/user/src/Plugin/views/field/Roles.php @@ -79,7 +79,7 @@ public function preRender(&$values) { if ($uids) { $roles = user_roles(); - $result = $this->database->query('SELECT u.uid, u.rid FROM {users_roles} u WHERE u.uid IN (:uids) AND u.rid IN (:rids)', array(':uids' => $uids, ':rids' => array_keys($roles))); + $result = $this->database->query('SELECT u.entity_id as uid, u.roles_target_id as rid FROM {user__roles} u WHERE u.entity_id IN (:uids) AND u.roles_target_id IN (:rids)', array(':uids' => $uids, ':rids' => array_keys($roles))); foreach ($result as $role) { $this->items[$role->uid][$role->rid]['role'] = String::checkPlain($roles[$role->rid]->label()); $this->items[$role->uid][$role->rid]['rid'] = $role->rid; diff --git a/core/modules/user/src/RoleStorage.php b/core/modules/user/src/RoleStorage.php index 2afd00e..a3f6d0f 100644 --- a/core/modules/user/src/RoleStorage.php +++ b/core/modules/user/src/RoleStorage.php @@ -34,8 +34,8 @@ public function isPermissionInRoles($permission, array $rids) { */ public function deleteRoleReferences(array $rids) { // Remove the role from all users. - db_delete('users_roles') - ->condition('rid', $rids) + db_delete('user__roles') + ->condition('target_id', $rids) ->execute(); } diff --git a/core/modules/user/src/Tests/UserDeleteTest.php b/core/modules/user/src/Tests/UserDeleteTest.php index 747039e..84bacb1 100644 --- a/core/modules/user/src/Tests/UserDeleteTest.php +++ b/core/modules/user/src/Tests/UserDeleteTest.php @@ -28,10 +28,10 @@ function testUserDeleteMultiple() { $uids = array($user_a->id(), $user_b->id(), $user_c->id()); // These users should have a role - $query = db_select('users_roles', 'r'); + $query = db_select('user__roles', 'r'); $roles_created = $query - ->fields('r', array('uid')) - ->condition('uid', $uids) + ->fields('r', array('entity_id')) + ->condition('entity_id', $uids) ->countQuery() ->execute() ->fetchField(); @@ -42,10 +42,10 @@ function testUserDeleteMultiple() { // Delete the users. user_delete_multiple($uids); // Test if the roles assignments are deleted. - $query = db_select('users_roles', 'r'); + $query = db_select('user__roles', 'r'); $roles_after_deletion = $query - ->fields('r', array('uid')) - ->condition('uid', $uids) + ->fields('r', array('entity_id')) + ->condition('entity_id', $uids) ->countQuery() ->execute() ->fetchField(); diff --git a/core/modules/user/src/Tests/UserEntityReferenceTest.php b/core/modules/user/src/Tests/UserEntityReferenceTest.php index 025aedf..4ee33e9 100644 --- a/core/modules/user/src/Tests/UserEntityReferenceTest.php +++ b/core/modules/user/src/Tests/UserEntityReferenceTest.php @@ -78,10 +78,14 @@ function testUserSelectionByRole() { $user3->addRole($this->role2->id()); $user3->save(); + debug(db_query('SELECT * FROM {users}')->fetchAll()); + debug(db_query('SELECT * FROM {user__roles}')->fetchAll()); + /** @var \Drupal\entity_reference\EntityReferenceAutocomplete $autocomplete */ $autocomplete = \Drupal::service('entity_reference.autocomplete'); $matches = $autocomplete->getMatches($field_definition, 'user', 'user', 'NULL', '', 'aabb'); + debug($matches); $this->assertEqual(count($matches), 2); $users = array(); foreach ($matches as $match) { diff --git a/core/modules/user/src/Tests/UserRolesAssignmentTest.php b/core/modules/user/src/Tests/UserRolesAssignmentTest.php index 124a263..71c9482 100644 --- a/core/modules/user/src/Tests/UserRolesAssignmentTest.php +++ b/core/modules/user/src/Tests/UserRolesAssignmentTest.php @@ -88,10 +88,10 @@ function testCreateUserWithRole() { private function userLoadAndCheckRoleAssigned($account, $rid, $is_assigned = TRUE) { $account = user_load($account->id(), TRUE); if ($is_assigned) { - $this->assertTrue(array_search($rid, $account->getRoles()), 'The role is present in the user object.'); + $this->assertFalse(array_search($rid, $account->getRoles()) === FALSE, 'The role is present in the user object.'); } else { - $this->assertFalse(array_search($rid, $account->getRoles()), 'The role is not present in the user object.'); + $this->assertTrue(array_search($rid, $account->getRoles()) === FALSE, 'The role is not present in the user object.'); } } } diff --git a/core/modules/user/src/Tests/Views/HandlerFieldRoleTest.php b/core/modules/user/src/Tests/Views/HandlerFieldRoleTest.php index 6612ec4..c97624e 100644 --- a/core/modules/user/src/Tests/Views/HandlerFieldRoleTest.php +++ b/core/modules/user/src/Tests/Views/HandlerFieldRoleTest.php @@ -41,11 +41,13 @@ public function testRole() { $user->addRole($rolename_b); $user->save(); + debug(db_query('SELECT * FROM {user__roles}')->fetchAll()); + $view = Views::getView('test_views_handler_field_role'); $this->executeView($view); // The role field is populated during preRender. - $view->field['rid']->preRender($view->result); - $render = $view->field['rid']->advancedRender($view->result[0]); + $view->field['roles_target_id']->preRender($view->result); + $render = $view->field['roles_target_id']->advancedRender($view->result[0]); $this->assertEqual($rolename_b . $rolename_a, $render, 'View test_views_handler_field_role renders role assigned to user in the correct order.'); $this->assertFalse(strpos($render, $rolename_not_assigned), 'View test_views_handler_field_role does not render a role not assigned to a user.'); diff --git a/core/modules/user/src/UserStorage.php b/core/modules/user/src/UserStorage.php index 9aa844e..638dfc7 100644 --- a/core/modules/user/src/UserStorage.php +++ b/core/modules/user/src/UserStorage.php @@ -68,25 +68,6 @@ public static function createInstance(ContainerInterface $container, EntityTypeI /** * {@inheritdoc} */ - function mapFromStorageRecords(array $records) { - foreach ($records as $record) { - $record->roles = array(); - if ($record->uid) { - $record->roles[] = DRUPAL_AUTHENTICATED_RID; - } - else { - $record->roles[] = DRUPAL_ANONYMOUS_RID; - } - } - - // Add any additional roles from the database. - $this->addRoles($records); - return parent::mapFromStorageRecords($records); - } - - /** - * {@inheritdoc} - */ public function save(EntityInterface $entity) { // The anonymous user account is saved with the fixed user ID of 0. // Therefore we need to check for NULL explicitly. @@ -108,43 +89,6 @@ protected function isColumnSerial($table_name, $schema_name) { /** * {@inheritdoc} */ - public function saveRoles(UserInterface $account) { - $query = $this->database->insert('users_roles')->fields(array('uid', 'rid')); - foreach ($account->getRoles() as $rid) { - if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) { - $query->values(array( - 'uid' => $account->id(), - 'rid' => $rid, - )); - } - } - $query->execute(); - } - - /** - * {@inheritdoc} - */ - public function addRoles(array $users) { - if ($users) { - $result = $this->database->query('SELECT rid, uid FROM {users_roles} WHERE uid IN (:uids)', array(':uids' => array_keys($users))); - foreach ($result as $record) { - $users[$record->uid]->roles[] = $record->rid; - } - } - } - - /** - * {@inheritdoc} - */ - public function deleteUserRoles(array $uids) { - $this->database->delete('users_roles') - ->condition('uid', $uids) - ->execute(); - } - - /** - * {@inheritdoc} - */ public function updateLastLoginTimestamp(UserInterface $account) { $this->database->update('users_field_data') ->fields(array('login' => $account->getLastLoginTime())) diff --git a/core/modules/user/src/UserStorageInterface.php b/core/modules/user/src/UserStorageInterface.php index a73b58b..2a114c5 100644 --- a/core/modules/user/src/UserStorageInterface.php +++ b/core/modules/user/src/UserStorageInterface.php @@ -15,27 +15,6 @@ interface UserStorageInterface { /** - * Add any roles from the storage to the user. - * - * @param array $users - */ - public function addRoles(array $users); - - /** - * Save the user's roles. - * - * @param \Drupal\user\UserInterface $account - */ - public function saveRoles(UserInterface $account); - - /** - * Remove the roles of a user. - * - * @param array $uids - */ - public function deleteUserRoles(array $uids); - - /** * Update the last login timestamp of the user. * * @param \Drupal\user\UserInterface $account diff --git a/core/modules/user/src/UserStorageSchema.php b/core/modules/user/src/UserStorageSchema.php index 48690f7..447469d 100644 --- a/core/modules/user/src/UserStorageSchema.php +++ b/core/modules/user/src/UserStorageSchema.php @@ -26,35 +26,6 @@ protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $res 'user__name' => array('name', 'langcode'), ); - $schema['users_roles'] = array( - 'description' => 'Maps users to roles.', - 'fields' => array( - 'uid' => array( - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - 'description' => 'Primary Key: {users}.uid for user.', - ), - 'rid' => array( - 'type' => 'varchar', - 'length' => 64, - 'not null' => TRUE, - 'description' => 'Primary Key: ID for the role.', - ), - ), - 'primary key' => array('uid', 'rid'), - 'indexes' => array( - 'rid' => array('rid'), - ), - 'foreign keys' => array( - 'user' => array( - 'table' => 'users', - 'columns' => array('uid' => 'uid'), - ), - ), - ); - return $schema; } diff --git a/core/modules/user/src/UserViewsData.php b/core/modules/user/src/UserViewsData.php index 0d5e544..30587d0 100644 --- a/core/modules/user/src/UserViewsData.php +++ b/core/modules/user/src/UserViewsData.php @@ -404,17 +404,17 @@ public function getViewsData() { // Define the base group of this table. Fields that don't have a group defined // will go into this field by default. - $data['users_roles']['table']['group'] = t('User'); + $data['user__roles']['table']['group'] = t('User'); // Explain how this table joins to others. - $data['users_roles']['table']['join'] = array( + $data['user__roles']['table']['join'] = array( 'users' => array( 'left_field' => 'uid', - 'field' => 'uid', + 'field' => 'entity_id', ), ); - $data['users_roles']['rid'] = array( + $data['user__roles']['roles_target_id'] = array( 'title' => t('Roles'), 'help' => t('Roles that a user belongs to.'), 'field' => array( @@ -426,7 +426,7 @@ public function getViewsData() { 'allow empty' => TRUE, ), 'argument' => array( - 'id' => 'users_roles_rid', + 'id' => 'user__roles_target_id', 'name table' => 'role', 'name field' => 'name', 'empty field name' => t('No role'), @@ -435,7 +435,7 @@ public function getViewsData() { ), ); - $data['users_roles']['permission'] = array( + $data['user__roles']['permission'] = array( 'title' => t('Permission'), 'help' => t('The user permissions.'), 'field' => array( @@ -444,7 +444,7 @@ public function getViewsData() { ), 'filter' => array( 'id' => 'user_permissions', - 'real field' => 'rid', + 'real field' => 'roles_target_id', ), ); diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_field_permission.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_field_permission.yml index 79ce551..b94e779 100644 --- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_field_permission.yml +++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_field_permission.yml @@ -77,7 +77,7 @@ display: plugin_id: user permission: id: permission - table: users_roles + table: user__roles field: permission relationship: none group_type: group diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_filter_permission.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_filter_permission.yml index 8b62fc7..22909a2 100644 --- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_filter_permission.yml +++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_filter_permission.yml @@ -78,7 +78,7 @@ display: filters: permission: id: permission - table: users_roles + table: user__roles field: permission relationship: none group_type: group diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_views_handler_field_role.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_views_handler_field_role.yml index 7cf5f93..e900f72 100644 --- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_views_handler_field_role.yml +++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_views_handler_field_role.yml @@ -82,10 +82,10 @@ display: format_username: '1' plugin_id: user_name provider: user - rid: - id: rid - table: users_roles - field: rid + roles_target_id: + id: roles_target_id + table: user__roles + field: roles_target_id relationship: none group_type: group admin_label: '' diff --git a/core/modules/user/tests/src/Unit/Views/Argument/RolesRidTest.php b/core/modules/user/tests/src/Unit/Views/Argument/RolesRidTest.php index 4e85059..d6566cc 100644 --- a/core/modules/user/tests/src/Unit/Views/Argument/RolesRidTest.php +++ b/core/modules/user/tests/src/Unit/Views/Argument/RolesRidTest.php @@ -69,7 +69,7 @@ public function testTitleQuery() { $container->set('entity.manager', $entity_manager); \Drupal::setContainer($container); - $roles_rid_argument = new RolesRid(array(), 'users_roles_rid', array(), $entity_manager); + $roles_rid_argument = new RolesRid(array(), 'user__roles_rid', array(), $entity_manager); $roles_rid_argument->value = array(); $titles = $roles_rid_argument->title_query(); diff --git a/core/profiles/standard/standard.install b/core/profiles/standard/standard.install index c2b5582..fdca17c 100644 --- a/core/profiles/standard/standard.install +++ b/core/profiles/standard/standard.install @@ -5,6 +5,7 @@ */ use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; +use Drupal\user\Entity\User; /** * Implements hook_install(). @@ -45,9 +46,9 @@ function standard_install() { $user_settings->set('admin_role', 'administrator')->save(); // Assign user 1 the "administrator" role. - db_insert('users_roles') - ->fields(array('uid' => 1, 'rid' => 'administrator')) - ->execute(); + $user = User::load(1); + $user->roles[] = 'administrator'; + $user->save(); // Enable the Contact link in the footer menu. /** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */