diff --git a/core/includes/session.inc b/core/includes/session.inc index b9b8fbc..7a92864 100644 --- a/core/includes/session.inc +++ b/core/includes/session.inc @@ -111,7 +111,13 @@ function _drupal_session_read($sid) { // Add roles element to $user. $user->roles = array(); $user->roles[DRUPAL_AUTHENTICATED_RID] = DRUPAL_AUTHENTICATED_RID; - $user->roles += db_query("SELECT ur.rid FROM {users_roles} ur WHERE ur.uid = :uid", array(':uid' => $user->uid))->fetchAllKeyed(0, 0); + + $role_config = config('user.roles'); + $rids = db_query("SELECT ur.rid FROM {users_roles} ur WHERE ur.uid = :uid", array(':uid' => $user->uid))->fetchCol(); + foreach ($rids as $rid) { + $role = $role_config->get($rid); + $user->roles[$rid] = $role['name']; + } } elseif ($user) { // The user is anonymous or blocked. Only preserve two fields from the diff --git a/core/modules/block/block.admin.inc b/core/modules/block/block.admin.inc index 848298f..48a8d22 100644 --- a/core/modules/block/block.admin.inc +++ b/core/modules/block/block.admin.inc @@ -462,7 +462,7 @@ function block_admin_configure($form, &$form_state, $module, $delta) { ':module' => $block->module, ':delta' => $block->delta, ))->fetchCol(); - $role_options = array_map('check_plain', user_roles()); + $role_options = array_map('check_plain', user_role_names()); $form['visibility']['role'] = array( '#type' => 'fieldset', '#title' => t('Roles'), diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index bd9c107..119d617 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -1825,7 +1825,7 @@ function theme_comment_post_forbidden($variables) { if (!isset($authenticated_post_comments)) { // We only output a link if we are certain that users will get permission // to post comments by logging in. - $comment_roles = user_roles(TRUE, 'post comments'); + $comment_roles = user_role_names(TRUE, 'post comments'); $authenticated_post_comments = isset($comment_roles[DRUPAL_AUTHENTICATED_RID]); } diff --git a/core/modules/filter/filter.admin.inc b/core/modules/filter/filter.admin.inc index 044fe58..39617a8 100644 --- a/core/modules/filter/filter.admin.inc +++ b/core/modules/filter/filter.admin.inc @@ -178,7 +178,7 @@ function filter_admin_format_form($form, &$form_state, $format) { $form['roles'] = array( '#type' => 'checkboxes', '#title' => t('Roles'), - '#options' => array_map('check_plain', user_roles()), + '#options' => array_map('check_plain', user_role_names()), '#disabled' => $is_fallback, ); if ($is_fallback) { diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module index 6c54fae..3e3c3a2 100644 --- a/core/modules/filter/filter.module +++ b/core/modules/filter/filter.module @@ -480,11 +480,11 @@ function filter_formats_reset() { function filter_get_roles_by_format($format) { // Handle the fallback format upfront (all roles have access to this format). if ($format->format == filter_fallback_format()) { - return user_roles(); + return user_role_names(); } // Do not list any roles if the permission does not exist. $permission = filter_permission_name($format); - return !empty($permission) ? user_roles(FALSE, $permission) : array(); + return !empty($permission) ? user_role_names(FALSE, $permission) : array(); } /** diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterFormatAccessTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterFormatAccessTest.php index 40991b6..d200080 100644 --- a/core/modules/filter/lib/Drupal/filter/Tests/FilterFormatAccessTest.php +++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterFormatAccessTest.php @@ -147,7 +147,7 @@ class FilterFormatAccessTest extends WebTestBase { $this->assertFalse(in_array($this->disallowed_format->format, array_keys(filter_get_formats_by_role($rid))), t('A text format which a role does not have access to does not appear in the list of formats available to that role.')); // Check that the fallback format is always allowed. - $this->assertEqual(filter_get_roles_by_format(filter_format_load(filter_fallback_format())), user_roles(), t('All roles have access to the fallback format.')); + $this->assertEqual(filter_get_roles_by_format(filter_format_load(filter_fallback_format())), user_role_names(), t('All roles have access to the fallback format.')); $this->assertTrue(in_array(filter_fallback_format(), array_keys(filter_get_formats_by_role($rid))), t('The fallback format appears in the list of allowed formats for any role.')); } diff --git a/core/modules/user/config/user.roles.yml b/core/modules/user/config/user.roles.yml new file mode 100644 index 0000000..189ef36 --- /dev/null +++ b/core/modules/user/config/user.roles.yml @@ -0,0 +1,6 @@ +anonymous: + name: Anonymous user + weight: 0 +authenticated: + name: Authenticated user + weight: 1 diff --git a/core/modules/user/lib/Drupal/user/AccountFormController.php b/core/modules/user/lib/Drupal/user/AccountFormController.php index a5545f4..09cabf6 100644 --- a/core/modules/user/lib/Drupal/user/AccountFormController.php +++ b/core/modules/user/lib/Drupal/user/AccountFormController.php @@ -126,7 +126,7 @@ abstract class AccountFormController extends EntityFormController { '#access' => $admin, ); - $roles = array_map('check_plain', user_roles(TRUE)); + $roles = array_map('check_plain', user_role_names(TRUE)); // The disabled checkbox subelement for the 'authenticated user' role // must be generated separately and added to the checkboxes element, // because of a limitation in Form API not supporting a single disabled diff --git a/core/modules/user/lib/Drupal/user/Tests/UserRoleAdminTest.php b/core/modules/user/lib/Drupal/user/Tests/UserRoleAdminTest.php index 6e0153c..857116f 100644 --- a/core/modules/user/lib/Drupal/user/Tests/UserRoleAdminTest.php +++ b/core/modules/user/lib/Drupal/user/Tests/UserRoleAdminTest.php @@ -80,7 +80,7 @@ class UserRoleAdminTest extends WebTestBase { $this->drupalLogin($this->admin_user); // Pick up a random role and get its weight. - $rid = array_rand(user_roles()); + $rid = array_rand(user_role_names()); $role = user_role_load($rid); $old_weight = $role->weight; diff --git a/core/modules/user/lib/Drupal/user/UserStorageController.php b/core/modules/user/lib/Drupal/user/UserStorageController.php index 2660300..55f65cf 100644 --- a/core/modules/user/lib/Drupal/user/UserStorageController.php +++ b/core/modules/user/lib/Drupal/user/UserStorageController.php @@ -40,9 +40,10 @@ class UserStorageController extends DatabaseStorageController { } // Add any additional roles from the database. - $result = db_query('SELECT r.rid, r.name, ur.uid FROM {role} r INNER JOIN {users_roles} ur ON ur.rid = r.rid WHERE ur.uid IN (:uids)', array(':uids' => array_keys($queried_users))); + $result = db_query('SELECT ur.rid, ur.uid FROM {users_roles} ur WHERE ur.uid IN (:uids)', array(':uids' => array_keys($queried_users))); foreach ($result as $record) { - $queried_users[$record->uid]->roles[$record->rid] = $record->name; + $role = user_role_load($record->rid); + $queried_users[$record->uid]->roles[$record->rid] = $role->name; } // Add the full file objects for user pictures if enabled. diff --git a/core/modules/user/user.admin.inc b/core/modules/user/user.admin.inc index f9b1c23..4d7bf8c 100644 --- a/core/modules/user/user.admin.inc +++ b/core/modules/user/user.admin.inc @@ -194,7 +194,7 @@ function user_admin_account() { $destination = drupal_get_destination(); $status = array(t('blocked'), t('active')); - $roles = array_map('check_plain', user_roles(TRUE)); + $roles = array_map('check_plain', user_role_names(TRUE)); $accounts = array(); foreach ($result as $account) { $users_roles = array(); @@ -285,7 +285,7 @@ function user_admin_settings($form, &$form_state) { // Do not allow users to set the anonymous or authenticated user roles as the // administrator role. - $roles = user_roles(); + $roles = user_role_names(); unset($roles[DRUPAL_ANONYMOUS_RID]); unset($roles[DRUPAL_AUTHENTICATED_RID]); $roles[0] = t('disabled'); @@ -690,7 +690,7 @@ function user_admin_settings_submit($form, &$form_state) { function user_admin_permissions($form, $form_state, $rid = NULL) { // Retrieve role names for columns. - $role_names = user_roles(); + $role_names = user_role_names(); if (isset($rid)) { $role_names = array($rid => $role_names[$rid]); } @@ -791,7 +791,7 @@ function user_admin_permissions_submit($form, &$form_state) { function theme_user_admin_permissions($variables) { $form = $variables['form']; - $roles = user_roles(); + $roles = user_role_names(); foreach (element_children($form['permission']) as $key) { $row = array(); // Module name @@ -860,25 +860,20 @@ function theme_user_permission_description($variables) { * @see theme_user_admin_roles() */ function user_admin_roles($form, $form_state) { - $roles = db_select('role', 'r') - ->addTag('translatable') - ->fields('r') - ->orderBy('weight') - ->orderBy('name') - ->execute(); + $roles = user_roles(); $form['roles'] = array( '#tree' => TRUE, ); $max_weight = 0; - foreach ($roles as $role) { + foreach ($roles as $rid => $role) { $max_weight = max($max_weight, $role->weight); - $form['roles'][$role->rid]['#role'] = $role; - $form['roles'][$role->rid]['#weight'] = $role->weight; - $form['roles'][$role->rid]['name'] = array( + $form['roles'][$rid]['#role'] = $role; + $form['roles'][$rid]['#weight'] = intval($role->weight); + $form['roles'][$rid]['name'] = array( '#markup' => check_plain($role->name), ); - $form['roles'][$role->rid]['weight'] = array( + $form['roles'][$rid]['weight'] = array( '#type' => 'textfield', '#title' => t('Weight for @title', array('@title' => $role->name)), '#title_display' => 'invisible', @@ -886,15 +881,15 @@ function user_admin_roles($form, $form_state) { '#default_value' => $role->weight, '#attributes' => array('class' => array('role-weight')), ); - $form['roles'][$role->rid]['edit'] = array( + $form['roles'][$rid]['edit'] = array( '#type' => 'link', '#title' => t('edit role'), - '#href' => 'admin/people/roles/edit/' . $role->rid, + '#href' => 'admin/people/roles/edit/' . $rid, ); - $form['roles'][$role->rid]['permissions'] = array( + $form['roles'][$rid]['permissions'] = array( '#type' => 'link', '#title' => t('edit permissions'), - '#href' => 'admin/people/permissions/' . $role->rid, + '#href' => 'admin/people/permissions/' . $rid, ); } diff --git a/core/modules/user/user.install b/core/modules/user/user.install index f05d9b5..50953f0 100644 --- a/core/modules/user/user.install +++ b/core/modules/user/user.install @@ -87,39 +87,6 @@ function user_schema() { ), ); - $schema['role'] = array( - 'description' => 'Stores user roles.', - 'fields' => array( - 'rid' => array( - 'type' => 'varchar', - // The role ID is often used as part of a compound index; at least MySQL - // has a maximum index length of 1000 characters (333 on utf8), so we - // limit the maximum length. - 'length' => 64, - 'not null' => TRUE, - 'description' => 'Primary Key: Unique role ID.', - ), - 'name' => array( - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - 'description' => 'Role label.', - 'translatable' => TRUE, - ), - 'weight' => array( - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'description' => 'The weight of this role in listings and the user interface.', - ), - ), - 'primary key' => array('rid'), - 'indexes' => array( - 'name_weight' => array('name', 'weight'), - ), - ); - // The table name here is plural, despite Drupal table naming standards, // because "user" is a reserved word in many databases. $schema['users'] = array( @@ -333,13 +300,6 @@ function user_install() { 'data' => NULL, )) ->execute(); - - // Insert built-in roles. - db_insert('role') - ->fields(array('rid', 'name', 'weight')) - ->values(array(DRUPAL_ANONYMOUS_RID, 'Anonymous user', 0)) - ->values(array(DRUPAL_AUTHENTICATED_RID, 'Authenticated user', 1)) - ->execute(); } /** @@ -551,6 +511,26 @@ function user_update_8006() { 'status_canceled_body' => 'status_canceled.body', )); } + + /** + * Replace the role table with configuration system as a backend for storing roles. + */ +function user_update_8007() { + $config = config('user.roles'); + + $roles = db_select('role', 'r')->fields('r') + ->execute()->fetchAll(); + + foreach ($roles as $role) { + $config->set($role->rid, array( + 'name' => $role->name, + 'weight' => $role->weight, + )); + } + + $config->save(); + db_drop_table('role'); +} /** * @} End of "addtogroup updates-7.x-to-8.x". */ diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 3b69966..7f3f13b 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -2161,6 +2161,25 @@ function user_mail_tokens(&$replacements, $data, $options) { * An associative array with the role id as the key and the role name as * value. */ +function user_role_names($membersonly = FALSE, $permission = NULL) { + return array_map(function($item) { + return $item->name; + }, user_roles($membersonly, $permission)); +} + +/** + * Retrieve an array of roles matching specified conditions. + * + * @param $membersonly + * Set this to TRUE to exclude the 'anonymous' role. + * @param $permission + * A string containing a permission. If set, only roles containing that + * permission are returned. + * + * @return + * An associative array with the role id as the key and the role object as + * value. + */ function user_roles($membersonly = FALSE, $permission = NULL) { $user_roles = &drupal_static(__FUNCTION__); @@ -2173,26 +2192,42 @@ function user_roles($membersonly = FALSE, $permission = NULL) { } } - $query = db_select('role', 'r'); - $query->addTag('translatable'); - $query->fields('r', array('rid', 'name')); - $query->orderBy('weight'); - $query->orderBy('name'); + $config = config('user.roles'); + $roles = $config->get(); + + if ($membersonly) { + unset($roles[DRUPAL_ANONYMOUS_RID]); + } + if (!empty($permission)) { - $query->innerJoin('role_permission', 'p', 'r.rid = p.rid'); + $filtered = array(); + $query = db_select('role_permission', 'p'); + $query->fields('p', array('rid')); $query->condition('p.permission', $permission); + $rids = $query->execute()->fetchCol(); + + foreach ($rids as $rid) { + $filtered[$rid] = $roles[$rid]; + } + $roles = $filtered; } - if ($membersonly) { - $query->condition('r.rid', DRUPAL_ANONYMOUS_RID, '!='); + + uksort($roles, function($a, $b) { + return $a['weight'] - $b['weight']; + }); + + $result = array(); + foreach ($roles as $rid => $role) { + $role = (object)$role; + $role->rid = $rid; + $result[$rid] = $role; } - $roles = $query->execute()->fetchAllKeyed(); if (empty($permission)) { - $user_roles[$cid] = $roles; - return $user_roles[$cid]; + $user_roles[$cid] = $result; } - return $roles; + return $result; } /** @@ -2206,11 +2241,18 @@ function user_roles($membersonly = FALSE, $permission = NULL) { * otherwise. */ function user_role_load($rid) { - return db_select('role', 'r') - ->fields('r') - ->condition('rid', $rid) - ->execute() - ->fetchObject(); + $config = config('user.roles'); + $role = $config->get($rid); + + if ($role) { + $role = (object)$role; + $role->rid = $rid; + } + else { + $role = FALSE; + } + + return $role; } /** @@ -2226,34 +2268,39 @@ function user_role_load($rid) { * performed. */ function user_role_save($role) { + $config = config('user.roles'); + $roles = $config->get(); + if ($role->name) { // Prevent leading and trailing spaces in role names. $role->name = trim($role->name); } if (!isset($role->weight)) { // Set a role weight to make this new role last. - $query = db_select('role'); - $query->addExpression('MAX(weight)'); - $role->weight = $query->execute()->fetchField() + 1; + $max = array_reduce($roles, function($max, $role) { + return $max > $role['weight'] ? $max : $role['weight']; + }); + $role->weight = $max + 1; } // Let modules modify the user role before it is saved to the database. module_invoke_all('user_role_presave', $role); - $exists = db_select('role', 'r') - ->fields('r', array('rid')) - ->condition('rid', $role->rid) - ->execute() - ->fetchAll(); + $exists = isset($roles[$role->rid]); + $config->set($role->rid, array( + 'name' => $role->name, + 'weight' => $role->weight, + )); - if (empty($exists)) { - $status = drupal_write_record('role', $role); + if (!$exists) { + $status = SAVED_NEW; module_invoke_all('user_role_insert', $role); } else { - $status = drupal_write_record('role', $role, 'rid'); + $status = SAVED_UPDATED; module_invoke_all('user_role_update', $role); } + $config->save(); // Clear the user access cache. drupal_static_reset('user_access'); @@ -2271,9 +2318,10 @@ function user_role_save($role) { function user_role_delete($role) { $role = user_role_load($role); - db_delete('role') - ->condition('rid', $role->rid) - ->execute(); + $config = config('user.roles'); + $config->clear($role->rid); + $config->save(); + db_delete('role_permission') ->condition('rid', $role->rid) ->execute(); @@ -2433,7 +2481,7 @@ function user_user_operations($form = array(), $form_state = array()) { ); if (user_access('administer permissions')) { - $roles = user_roles(TRUE); + $roles = user_role_names(TRUE); unset($roles[DRUPAL_AUTHENTICATED_RID]); // Can't edit authenticated role. $add_roles = array(); @@ -2518,7 +2566,7 @@ function user_user_operations_block($accounts) { * Callback function for admin mass adding/deleting a user role. */ function user_multiple_role_edit($accounts, $operation, $rid) { - $role_name = db_query('SELECT name FROM {role} WHERE rid = :rid', array(':rid' => $rid))->fetchField(); + $role_name = user_role_load($rid)->name; switch ($operation) { case 'add_role': @@ -2654,7 +2702,7 @@ function user_multiple_cancel_confirm_submit($form, &$form_state) { function user_filters() { // Regular filters $filters = array(); - $roles = user_roles(TRUE); + $roles = user_role_names(TRUE); unset($roles[DRUPAL_AUTHENTICATED_RID]); // Don't list authorized role. if (count($roles)) { $filters['role'] = array(