From aa86a33ff51d182737971475e4ec38708da2adbb Mon Sep 17 00:00:00 2001
From: Hugo Wetterberg <hugo@wetterberg.nu>
Date: Fri, 24 Aug 2012 15:24:43 +0200
Subject: [PATCH] Hopefully fixes the last of the test failures.

---
 core/includes/session.inc                          |   8 +-
 core/modules/block/block.admin.inc                 |   2 +-
 core/modules/user/config/user.roles.yml            |   6 ++
 .../user/lib/Drupal/user/AccountFormController.php |   2 +-
 .../lib/Drupal/user/Tests/UserRoleAdminTest.php    |   2 +-
 .../user/lib/Drupal/user/UserStorageController.php |   5 +-
 core/modules/user/user.admin.inc                   |  33 +++---
 core/modules/user/user.install                     |  60 ++++-------
 core/modules/user/user.module                      | 116 +++++++++++++++------
 9 files changed, 135 insertions(+), 99 deletions(-)
 create mode 100644 core/modules/user/config/user.roles.yml

diff --git a/core/includes/session.inc b/core/includes/session.inc
index 5761dc9..25b4b4a 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] = 'authenticated user';
-    $user->roles += db_query("SELECT r.rid, r.name FROM {role} r INNER JOIN {users_roles} ur ON ur.rid = r.rid WHERE ur.uid = :uid", array(':uid' => $user->uid))->fetchAllKeyed(0, 1);
+
+    $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 aa018da..7110e70 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/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 31ca843..0e94e13 100644
--- a/core/modules/user/lib/Drupal/user/AccountFormController.php
+++ b/core/modules/user/lib/Drupal/user/AccountFormController.php
@@ -125,7 +125,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 3e2ac68..92d2b82 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 fac9723..6ed6ed3 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();
@@ -282,7 +282,7 @@ function user_admin_settings() {
 
   // 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');
@@ -653,7 +653,7 @@ function user_admin_settings() {
 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]);
   }
@@ -754,7 +754,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
@@ -823,25 +823,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',
@@ -849,15 +844,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 abb985b..322812f 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(
@@ -326,13 +293,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();
 }
 
 /**
@@ -475,5 +435,25 @@ function user_update_8003() {
 }
 
 /**
+ * Replace the role table with configuration system as a beckend for storing roles.
+ */
+function user_update_8004() {
+  $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 44cb266..9330bf5 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -2344,6 +2344,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__);
 
@@ -2356,26 +2375,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;
 }
 
 /**
@@ -2389,11 +2424,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;
 }
 
 /**
@@ -2409,34 +2451,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');
@@ -2454,9 +2501,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();
@@ -2616,7 +2664,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();
@@ -2701,7 +2749,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':
@@ -2837,7 +2885,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(
-- 
1.7.11.1

