Index: modules/filter/filter.install =================================================================== RCS file: /cvs/drupal/drupal/modules/filter/filter.install,v retrieving revision 1.9 diff -u -r1.9 filter.install --- modules/filter/filter.install 14 Apr 2008 17:48:37 -0000 1.9 +++ modules/filter/filter.install 2 May 2008 00:53:18 -0000 @@ -64,13 +64,6 @@ 'default' => '', 'description' => t('Name of the input format (Filtered HTML).'), ), - 'roles' => array( - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - 'description' => t('A comma-separated string of roles; references {role}.rid.'), // This is bad since you can't use joins, nor index. - ), 'cache' => array( 'type' => 'int', 'not null' => TRUE, @@ -99,6 +92,11 @@ } /** + * @defgroup updates-6.x-to-7.x Filter updates from 6.x to 7.x + * @{ + */ + +/** * Add a weight column to the filter formats table. */ function filter_update_7000() { @@ -122,3 +120,34 @@ } return $ret; } + +/** + * Move filter format access to the user permissions handler. + */ +function filter_update_7002() { + $ret = array(); + // Get list of roles to work with. + $result = db_query("SELECT rid FROM {role}"); + while ($role = db_result($result)) { + $roles[$role] = $role; + } + + // Move role data from filter_formats to user permissions. + $result = db_query("SELECT name, roles FROM {filter_formats}"); + while ($format = db_fetch_object($result)) { + $format_roles = explode(',', $format->roles); + foreach ($format_roles as $format_role) { + if (in_array($format_role, $roles)) { + $ret[] = update_sql("UPDATE {permission} SET perm = CONCAT(perm, ', use " . db_escape_string(check_plain($format->name)) . "') WHERE rid = " . $format_role); + } + } + } + // Finally, drop the roles field from filter_formats. + db_drop_field($ret, 'filter_formats', 'roles'); + return $ret; +} + +/** + * @} End of "defgroup updates-6.x-to-7.x" + * The next series of updates should start at 8000. + */ Index: modules/filter/filter.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/filter/filter.admin.inc,v retrieving revision 1.11 diff -u -r1.11 filter.admin.inc --- modules/filter/filter.admin.inc 14 Apr 2008 17:48:37 -0000 1.11 +++ modules/filter/filter.admin.inc 2 May 2008 00:53:18 -0000 @@ -21,13 +21,7 @@ $form = array('#tree' => TRUE); foreach ($formats as $id => $format) { - $roles = array(); - foreach (user_roles() as $rid => $name) { - // Prepare a roles array with roles that may access the filter. - if (strstr($format->roles, ",$rid,")) { - $roles[] = $name; - } - } + $roles = user_roles(FALSE, 'use ' . check_plain($format->name)); $default = ($id == variable_get('filter_default_format', 1)); $options[$id] = ''; $form[$id]['name'] = array('#value' => $format->name); @@ -95,7 +89,7 @@ function filter_admin_format_page($format = NULL) { if (!isset($format->name)) { drupal_set_title(t("Add input format")); - $format = (object)array('name' => '', 'roles' => '', 'format' => ''); + $format = (object)array('name' => '', 'format' => ''); } return drupal_get_form('filter_admin_format_form', $format); } @@ -108,9 +102,7 @@ * @see filter_admin_format_form_submit() */ function filter_admin_format_form(&$form_state, $format) { - $default = ($format->format == variable_get('filter_default_format', 1)); - if ($default) { - $help = t('All roles for the default format must be enabled and cannot be changed.'); + if ($format->format == variable_get('filter_default_format', 1)) { $form['default_format'] = array('#type' => 'hidden', '#value' => 1); } @@ -121,23 +113,6 @@ '#required' => TRUE, ); - // Add a row of checkboxes for form group. - $form['roles'] = array('#type' => 'fieldset', - '#title' => t('Roles'), - '#description' => $default ? $help : t('Choose which roles may use this filter format. Note that roles with the "administer filters" permission can always use all the filter formats.'), - '#tree' => TRUE, - ); - - foreach (user_roles() as $rid => $name) { - $checked = strstr($format->roles, ",$rid,"); - $form['roles'][$rid] = array('#type' => 'checkbox', - '#title' => $name, - '#default_value' => ($default || $checked), - ); - if ($default) { - $form['roles'][$rid]['#disabled'] = TRUE; - } - } // Table with filters $all = filter_list_all(); $enabled = filter_list_format($format->format); @@ -156,6 +131,7 @@ } if (!empty($format->format)) { $form['format'] = array('#type' => 'hidden', '#value' => $format->format); + $form['previous_name'] = array('#type' => 'hidden', '#value' => $format->name); // Composition tips (guidelines) $tips = _filter_tips($format->format, FALSE); @@ -195,7 +171,7 @@ $name = trim($form_state['values']['name']); $cache = TRUE; - // Add a new filter format. + // Add a new input format. if (!$format) { $new = TRUE; db_query("INSERT INTO {filter_formats} (name) VALUES ('%s')", $name); @@ -203,6 +179,8 @@ drupal_set_message(t('Added input format %format.', array('%format' => $name))); } else { + // Update the name of affected permission. + user_rename_permission('use '. check_plain($form_state['values']['previous_name']), 'use '. check_plain($name)); drupal_set_message(t('The input format settings have been updated.')); } @@ -219,25 +197,7 @@ } } - // We store the roles as a string for ease of use. - // We should always set all roles to TRUE when saving a default role. - // We use leading and trailing comma's to allow easy substring matching. - $roles = array(); - if (isset($form_state['values']['roles'])) { - foreach ($form_state['values']['roles'] as $id => $checked) { - if ($checked) { - $roles[] = $id; - } - } - } - if (!empty($form_state['values']['default_format'])) { - $roles = ',' . implode(',', array_keys(user_roles())) . ','; - } - else { - $roles = ',' . implode(',', $roles) . ','; - } - - db_query("UPDATE {filter_formats} SET cache = %d, name='%s', roles = '%s' WHERE format = %d", $cache, $name, $roles, $format); + db_query("UPDATE {filter_formats} SET cache = %d, name='%s' WHERE format = %d", $cache, $name, $format); cache_clear_all($format . ':', 'cache_filter', TRUE); @@ -256,14 +216,14 @@ * @ingroup forms * @see filter_admin_delete_submit() */ -function filter_admin_delete() { - $format = arg(4); +function filter_admin_delete($form_state, $format) { $format = db_fetch_object(db_query('SELECT * FROM {filter_formats} WHERE format = %d', $format)); if ($format) { if ($format->format != variable_get('filter_default_format', 1)) { $form['format'] = array('#type' => 'hidden', '#value' => $format->format); $form['name'] = array('#type' => 'hidden', '#value' => $format->name); + $form['destination'] = array('#type' => 'hidden', '#value' => 'admin/settings/filters'); return confirm_form($form, t('Are you sure you want to delete the input format %format?', array('%format' => $format->name)), 'admin/settings/filters', t('If you have any content left in this input format, it will be switched to the default input format. This action cannot be undone.'), t('Delete'), t('Cancel')); } Index: modules/filter/filter.module =================================================================== RCS file: /cvs/drupal/drupal/modules/filter/filter.module,v retrieving revision 1.210 diff -u -r1.210 filter.module --- modules/filter/filter.module 23 Apr 2008 20:01:50 -0000 1.210 +++ modules/filter/filter.module 2 May 2008 00:53:19 -0000 @@ -154,9 +154,20 @@ * Implementation of hook_perm(). */ function filter_perm() { - return array( + $default_format = variable_get('filter_default_format', 1); + $perms = array( 'administer filters' => t('Manage input formats and filters, and select which roles may use them. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))), ); + + // Generate permissions for each input format. + $result = db_query('SELECT * FROM {filter_formats} ORDER BY weight'); + while ($format = db_fetch_object($result)) { + $perms['use '. check_plain($format->name)] = t('Use %input_format in forms when entering or editing content.', array('%input_format' => $format->name)); + if ($format->format == $default_format) { + $perms['use '. check_plain($format->name)] .= ' ' . theme('placeholder', t('The default input format must be available to all users')); + } + } + return $perms; } /** @@ -289,35 +300,45 @@ } /** - * Retrieve a list of input formats. + * Implementation of hook_form_alter(). + */ +function filter_form_alter(&$form, &$form_state, $form_id) { + if ($form_id == 'user_admin_perm') { + // Disable the checkboxes for the default format permissions. + $default_format = filter_formats(variable_get('filter_default_format', 1)); + foreach (user_roles() as $rid => $role) { + $form['checkboxes'][$rid]['use ' . check_plain($default_format->name)] = array( + '#type' => 'checkbox', + '#value' => 1, + '#disabled' => TRUE, + ); + } + } +} + +/** + * Retrieve a list of input formats the current user can use. + * + * @param $index + * Optional format identifier. If provided, only this format object will be + * returned. Otherwise all format objects in an array keyed by format ID. */ function filter_formats($index = NULL) { - global $user; static $formats; // Administrators can always use all input formats. - $all = user_access('administer filters'); + $access_all = user_access('administer filters'); + $default_format = variable_get('filter_default_format', 1); if (!isset($formats)) { $formats = array(); - - $query = 'SELECT * FROM {filter_formats}'; - - // Build query for selecting the format(s) based on the user's roles. - $args = array(); - if (!$all) { - $where = array(); - foreach ($user->roles as $rid => $role) { - $where[] = "roles LIKE '%%,%d,%%'"; - $args[] = $rid; - } - $query .= ' WHERE ' . implode(' OR ', $where) . ' OR format = %d'; - $args[] = variable_get('filter_default_format', 1); - } - - $result = db_query($query . ' ORDER by weight', $args); + $result = db_query('SELECT * FROM {filter_formats} ORDER BY weight'); while ($format = db_fetch_object($result)) { - $formats[$format->format] = $format; + if ($access_all || ($format->format == $default_format) || user_access('use '. check_plain($format->name))) { + // Always add the default input format, otherwise add the format if + // the user has access to it. + $formats[$format->format] = $format; + } } } if (isset($index)) { Index: modules/user/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.module,v retrieving revision 1.904 diff -u -r1.904 user.module --- modules/user/user.module 23 Apr 2008 20:01:56 -0000 1.904 +++ modules/user/user.module 2 May 2008 00:53:21 -0000 @@ -1635,6 +1635,69 @@ } /** + * Retreive a list of permissions for a role. + * + * @param $rid + * Optional. The role whose permissions are to be retreived. + * @param $reset + * Reset the internal cache of user permissions. + * @return + * An associative array of all the permissions for a role. + */ +function user_permissions($rid = NULL, $reset = FALSE) { + static $permissions = array(); + + if (empty($permissions[$rid]) || $reset) { + $all_permissions = module_invoke_all('perm'); + $result = db_query('SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid ORDER BY name'); + while ($role = db_fetch_object($result)) { + // Set all permissions to false by default. + foreach ($all_permissions as $permission => $description) { + $permissions[$role->rid][$permission] = FALSE; + } + // Specify the allowed permission as true. + foreach (explode(', ', $role->perm) as $permission) { + $permissions[$role->rid][$permission] = TRUE; + } + } + } + + return is_numeric($rid) ? $permissions[$rid] : $permissions; +} + +/** + * Rename a permission. + * + * @param $old_perm + * The current name of the permissions to renamed. May be a single string + * permission or an array of permissions. + * @param $new_perm + * The new name of the permissions. May be a single string permission or an + * array of permissions. The type for $old_perm and $new_perm must match. + */ +function user_rename_permission($old_perm, $new_perm) { + // Convert parameters to arrays if they're not already. + if (!is_array($old_perm) && !is_array($new_perm)) { + $old_perm = array($old_perm); + $new_perm = array($new_perm); + } + + $result = db_query('SELECT * FROM {permission}'); + while ($permission = db_fetch_object($result)) { + // Create an associative array for easy mapping. + $permissions = drupal_map_assoc(explode(', ', $permission->perm)); + foreach ($old_perm as $index => $name) { + // Give the permission the new name. + if (isset($permissions[$name]) && isset($new_perm[$index])) { + $permissions[$name] = $new_perm[$index]; + } + } + $permission->perm = implode(', ', $permissions); + db_query("UPDATE {permission} SET perm = '%s' WHERE pid = %d", $permission->perm, $permission->pid); + } +} + +/** * Implementation of hook_user_operations(). */ function user_user_operations($form_state = array()) { Index: modules/user/user.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.admin.inc,v retrieving revision 1.21 diff -u -r1.21 user.admin.inc --- modules/user/user.admin.inc 14 Apr 2008 17:48:43 -0000 1.21 +++ modules/user/user.admin.inc 2 May 2008 00:53:20 -0000 @@ -493,20 +493,8 @@ * @see theme_user_admin_perm() */ function user_admin_perm($form_state, $rid = NULL) { - if (is_numeric($rid)) { - $result = db_query('SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid WHERE r.rid = %d', $rid); - } - else { - $result = db_query('SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid ORDER BY name'); - } - - // Compile role array: - // Add a comma at the end so when searching for a permission, we can - // always search for "$perm," to make sure we do not confuse - // permissions that are substrings of each other. - while ($role = db_fetch_object($result)) { - $role_permissions[$role->rid] = $role->perm . ','; - } + // Retrieve role permissions. + $role_permissions = user_permissions(); // Retrieve role names for columns. $role_names = user_roles(); @@ -537,7 +525,7 @@ ); foreach ($role_names as $rid => $name) { // Builds arrays for checked boxes for each role - if (strpos($role_permissions[$rid], $perm . ',') !== FALSE) { + if ($role_permissions[$rid][$perm]) { $status[$rid][] = $perm; } } Index: modules/system/system.install =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.install,v retrieving revision 1.250 diff -u -r1.250 system.install --- modules/system/system.install 16 Apr 2008 11:35:52 -0000 1.250 +++ modules/system/system.install 2 May 2008 00:53:20 -0000 @@ -369,8 +369,8 @@ db_query("INSERT INTO {role} (name) VALUES ('%s')", 'anonymous user'); db_query("INSERT INTO {role} (name) VALUES ('%s')", 'authenticated user'); - db_query("INSERT INTO {permission} (rid, perm, tid) VALUES (%d, '%s', %d)", 1, 'access content', 0); - db_query("INSERT INTO {permission} (rid, perm, tid) VALUES (%d, '%s', %d)", 2, 'access comments, access content, post comments, post comments without approval', 0); + db_query("INSERT INTO {permission} (rid, perm, tid) VALUES (%d, '%s', %d)", 1, 'access content, use Filtered HTML', 0); + db_query("INSERT INTO {permission} (rid, perm, tid) VALUES (%d, '%s', %d)", 2, 'access comments, access content, post comments, post comments without approval, use Filtered HTML', 0); db_query("INSERT INTO {variable} (name, value) VALUES ('%s', '%s')", 'theme_default', 's:7:"garland";'); db_query("UPDATE {system} SET status = %d WHERE type = '%s' AND name = '%s'", 1, 'theme', 'garland'); @@ -381,8 +381,8 @@ db_query("INSERT INTO {node_access} (nid, gid, realm, grant_view, grant_update, grant_delete) VALUES (%d, %d, '%s', %d, %d, %d)", 0, 0, 'all', 1, 0, 0); // Add input formats. - db_query("INSERT INTO {filter_formats} (name, roles, cache) VALUES ('%s', '%s', %d)", 'Filtered HTML', ',1,2,', 1); - db_query("INSERT INTO {filter_formats} (name, roles, cache) VALUES ('%s', '%s', %d)", 'Full HTML', '', 1); + db_query("INSERT INTO {filter_formats} (name, cache) VALUES ('%s', %d)", 'Filtered HTML', 1); + db_query("INSERT INTO {filter_formats} (name, cache) VALUES ('%s', %d)", 'Full HTML', 1); // Enable filters for each input format.