=== modified file 'modules/system/system.install' --- modules/system/system.install +++ modules/system/system.install @@ -208,10 +208,16 @@ function system_install() { ) /*!40100 DEFAULT CHARACTER SET UTF8 */ "); db_query("CREATE TABLE {permission} ( - rid int(10) unsigned NOT NULL default '0', - perm longtext, - tid int(10) unsigned NOT NULL default '0', - KEY rid (rid) + pid int(10) unsigned NOT NULL default '0', + perm varchar(255) NOT NULL default '', + PRIMARY KEY (pid), + UNIQUE KEY perm (perm) + ) /*!40100 DEFAULT CHARACTER SET UTF8 */ "); + + db_query("CREATE TABLE {permission_role} ( + pid int(10) unsigned NOT NULL, + rid int(10) unsigned NOT NULL, + PRIMARY KEY (pid,rid) ) /*!40100 DEFAULT CHARACTER SET UTF8 */ "); db_query("CREATE TABLE {role} ( @@ -395,8 +401,12 @@ function system_install() { db_query("INSERT INTO {role} (name) VALUES ('anonymous user')"); db_query("INSERT INTO {role} (name) VALUES ('authenticated user')"); - db_query("INSERT INTO {permission} VALUES (1,'access content',0)"); - db_query("INSERT INTO {permission} VALUES (2,'access comments, access content, post comments, post comments without approval',0)"); + foreach (array(1 => 'access comments', 'access content', 'post comments', 'post comments without approval') as $pid => $perm) { + db_query("INSERT INTO {permission} VALUES (%d, '%s')", $pid, $perm); + db_query("INSERT INTO {permission_role} (rid, pid) VALUES (2, %d), $pid"); + } + db_query("INSERT INTO {permission_role} (rid, pid) VALUES (1, 2)"); + db_query("INSERT INTO {sequences} (name, value) VALUES ('{permission}_pid', 4)"); db_query("INSERT INTO {variable} (name,value) VALUES('theme_default', 's:10:\"bluemarine\";')"); === modified file 'modules/user/user.module' --- modules/user/user.module +++ modules/user/user.module @@ -340,7 +340,7 @@ function user_password($length = 10) { */ function user_access($string, $account = NULL) { global $user; - static $perm = array(); + static $perm = array(), $role_string = array(); if (is_null($account)) { $account = $user; @@ -350,23 +350,17 @@ function user_access($string, $account = if ($account->uid == 1) { return TRUE; } + if (!isset($role_string[$account->uid])) { + $role_string[$account->uid] = implode(',', array_keys($account->roles)); + } // To reduce the number of SQL queries, we cache the user's permissions // in a static variable. - if (!isset($perm[$account->uid])) { - $result = db_query("SELECT DISTINCT(p.perm) FROM {role} r INNER JOIN {permission} p ON p.rid = r.rid WHERE r.rid IN (%s)", implode(',', array_keys($account->roles))); - - $perm[$account->uid] = ''; - while ($row = db_fetch_object($result)) { - $perm[$account->uid] .= "$row->perm, "; - } - } - - if (isset($perm[$account->uid])) { - return strpos($perm[$account->uid], "$string, ") !== FALSE; + if (!isset($perm[$account->uid][$string])) { + $perm[$account->uid][$string] = db_num_rows(db_query_range("SELECT p.pid FROM {permission_role} pr INNER JOIN {permission} p ON pr.pid = p.pid WHERE perm = '%s' AND rid IN (%s)", $string, $role_string[$account->uid], 0, 1)); } - return FALSE; + return isset($perm[$account->uid][$string]) && $perm[$account->uid][$string]; } /** @@ -1679,7 +1673,7 @@ function user_roles($membersonly = 0, $p $roles = array(); if ($permission) { - $result = db_query("SELECT r.* FROM {role} r INNER JOIN {permission} p ON r.rid = p.rid WHERE p.perm LIKE '%%%s%%' ORDER BY r.name", $permission); + $result = db_query("SELECT r.* FROM {role} r INNER JOIN {permission_role} pr ON r.rid = pr.rid INNER JOIN {permission} p ON pr.pid = p.pid WHERE p.perm = '%s' ORDER BY r.name", $permission); } else { $result = db_query('SELECT * FROM {role} ORDER BY name'); @@ -1701,23 +1695,24 @@ function user_admin_perm($str_rids = NUL $rids = preg_split('/[+ ]/', $str_rids); } - if($rids) { + if ($rids) { $breadcrumbs = drupal_get_breadcrumb(); $breadcrumbs[] = l(t('all roles'), 'admin/access'); drupal_set_breadcrumb($breadcrumbs); - $result = db_query('SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid WHERE r.rid IN (%s) ORDER BY name', implode(', ', $rids)); + $result = db_query('SELECT * FROM {permission_role} WHERE rid IN (%s)', implode(', ', $rids)); } else { - $result = db_query('SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid ORDER BY name'); + $result = db_query('SELECT * FROM {permission_role}'); } - // Compile role array: + // Builds arrays for checked boxes for each role $roles = array(); while ($role = db_fetch_object($result)) { - $role_permissions[$role->rid] = $role->perm; + $status[$role->rid][] = $role->pid; } - if($rids) { + // Compile role array: + if ($rids) { $result = db_query('SELECT rid, name FROM {role} r WHERE r.rid IN (%s) ORDER BY name', implode(', ', $rids)); } else { @@ -1728,24 +1723,40 @@ function user_admin_perm($str_rids = NUL $role_names[$role->rid] = $role->name; } + $stored_permissions = array(); + $result = db_query('SELECT pid, perm FROM {permission} ORDER BY perm ASC'); + while ($permission = db_fetch_object($result)) { + $stored_permissions[$permission->perm] = $permission->pid; + } + $new_permissions = array(); + // Render role/permission overview: $options = array(); foreach (module_list(FALSE, FALSE, TRUE) as $module) { if ($permissions = module_invoke($module, 'perm')) { - $form['permission'][] = array('#type' => 'markup', '#value' => t('%module module', array('%module' => $module))); + $form['permission'][$module] = array('#type' => 'markup', '#value' => t('%module module', array('%module' => $module))); asort($permissions); foreach ($permissions as $perm) { - $options[$perm] = ''; - $form['permission'][$perm] = array('#type' => 'markup', '#value' => t($perm)); - foreach ($role_names as $rid => $name) { - // Builds arrays for checked boxes for each role - if (strstr($role_permissions[$rid], $perm)) { - $status[$rid][] = $perm; - } + if (!isset($stored_permissions[$perm])) { + $pid = db_next_id('{permission}_pid'); + } + else { + $pid = $stored_permissions[$perm]; } + $new_permissions[$perm] = $pid; + $options[$pid] = ''; + $form['permission'][$pid] = array('#type' => 'markup', '#value' => t($perm)); } } } + ksort($new_permissions); + if (array_keys($stored_permissions) != array_keys($new_permissions)) { + db_query('DELETE FROM {permission}'); + foreach($new_permissions as $perm => $pid) { + db_query("INSERT INTO {permission} (pid, perm) VALUES (%d, '%s')", $pid, $perm); + } + } + // Have to build checkboxes here after checkbox arrays are built foreach ($role_names as $rid => $name) { $form['checkboxes'][$rid] = array('#type' => 'checkboxes', '#options' => $options, '#default_value' => $status[$rid]); @@ -1761,12 +1772,8 @@ function theme_user_admin_perm($form) { // Don't take form control structures if (is_array($form['permission'][$key])) { $row = array(); - // Module name - if (is_numeric($key)) { - $row[] = array('data' => form_render($form['permission'][$key]), 'class' => 'module', 'colspan' => count($form['role_names']) + 1); // Permissions - } - else { + if (is_numeric($key)) { $row[] = array('data' => form_render($form['permission'][$key]), 'class' => 'permission'); foreach (element_children($form['checkboxes']) as $rid) { if (is_array($form['checkboxes'][$rid])) { @@ -1774,6 +1781,10 @@ function theme_user_admin_perm($form) { } } } + // Module name + else { + $row[] = array('data' => form_render($form['permission'][$key]), 'class' => 'module', 'colspan' => count($form['role_names']) + 1); + } $rows[] = $row; } } @@ -1792,17 +1803,12 @@ function user_admin_perm_submit($form_id // Save permissions: $result = db_query('SELECT * FROM {role}'); while ($role = db_fetch_object($result)) { - if(isset($edit[$role->rid])) { + if (isset($edit[$role->rid])) { // Delete, so if we clear every checkbox we reset that role; // otherwise permissions are active and denied everywhere. - db_query('DELETE FROM {permission} WHERE rid = %d', $role->rid); - foreach ($edit[$role->rid] as $key => $value) { - if (!$value) { - unset($edit[$role->rid][$key]); - } - } - if (count($edit[$role->rid])) { - db_query("INSERT INTO {permission} (rid, perm) VALUES (%d, '%s')", $role->rid, implode(', ', array_keys($edit[$role->rid]))); + db_query('DELETE FROM {permission_role} WHERE rid = %d', $role->rid); + foreach (array_keys(array_filter($edit[$role->rid])) as $pid) { + db_query("INSERT INTO {permission_role} (rid, pid) VALUES (%d, '%s')", $role->rid, $pid); } } } @@ -1834,19 +1840,8 @@ function user_admin_role() { } else if ($op == t('Delete role')) { db_query('DELETE FROM {role} WHERE rid = %d', $id); - db_query('DELETE FROM {permission} WHERE rid = %d', $id); - - // Update the users who have this role set: - $result = db_query('SELECT DISTINCT(ur1.uid) FROM {users_roles} ur1 LEFT JOIN {users_roles} ur2 ON ur2.uid = ur1.uid WHERE ur1.rid = %d AND ur2.rid != ur1.rid', $id); - $uid = array(); - - while ($u = db_fetch_object($result)) { - $uid[] = $u->uid; - } - - if ($uid) { - db_query('DELETE FROM {users_roles} WHERE rid = %d AND uid IN (%s)', $id, implode(', ', $uid)); - } + db_query('DELETE FROM {permission_role} WHERE rid = %d', $id); + db_query('DELETE FROM {users_roles} WHERE rid = %d', $id); drupal_set_message(t('The role has been deleted.')); drupal_goto('admin/access/roles');