rid] = $role->perm .','; } $role_names = user_roles(); if (is_numeric($rid)) { $role_names = array($rid => $role_names[$rid]); } // Render role/permission overview: $options = array(); foreach (module_list(FALSE, FALSE, TRUE) as $module) { if ($permissions = module_invoke($module, 'perm')) { $form['permission'][] = array( '#value' => $module, // the module label. ); foreach ($permissions as $perm) { $matches = array(); // Get only the perms we care about. preg_match("/^($action_prefixes_regexp) (.+) ($content_suffixes_regexp)\$/", $perm, $matches); if ($matches) { // have (whole string, action, content type). //dsm($matches); $action = $matches[1]; $content = $matches[2]; // autovivify so we don't clobber in another loop iteration $form['permission'][$content]['#value'] = $content; // the content type label // the last one of these to be stashed end up in form_values... but never mind. $form['permission'][$content]['perms']['#type'] = 'value'; $form['permission'][$content]['perms']['#value'][] = $perm; $content_types[$content] = $content; $options[$perm] = ''; if (strpos($role_permissions[$rid], $perm .',') !== FALSE) { $status[$rid][] = $perm; } } // if matches else { $other_permissions[] = $perm; } } // foreach perm if (is_numeric(key(array_slice($form['permission'], -1, 1, TRUE)))) { // if the last key in the permissions array is numeric, then it's a module label // and that means that this module gave us no interesting permissions // so remove it. array_pop($form['permission']); } } } // 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' => isset($status[$rid]) ? $status[$rid] : array()); $form['role_names'][$rid] = array('#value' => $name, '#tree' => TRUE); $form['other_perms'][$rid] = array( '#type' => 'value', '#tree' => TRUE, ); foreach ($other_permissions as $perm) { // a perm we don't care about. stash its current value anyway for merging on submit. if (strpos($role_permissions[$rid], $perm .',') !== FALSE) { $form['other_perms'][$rid][$perm]['#type'] = 'value'; $form['other_perms'][$rid][$perm]['#value'] = $perm; } } } foreach ($action_prefixes as $action) { $form['action_names'][$action] = array('#value' => $action, '#tree' => TRUE); } $form['submit'] = array('#type' => 'submit', '#value' => t('Save permissions')); return $form; } /** * Theme the administer permissions page. */ function theme_node_permissions_grid_admin_content_perm($form) { /* $form['permission'] is either: - numeric keys that are module name values - content type keys that hold: - numeric is the content type label */ #dsm($form['permission']); $action_prefixes = action_prefixes(); $roles = user_roles(); foreach (element_children($form['role_names']) as $rid) { $output .= '

Content permissions for ' . drupal_render($form['role_names'][$rid]) . '

'; foreach (element_children($form['permission']) as $key) { // Don't take form control structures // We are going through an array whose keys are either: // - numeric, and represents a label for a module // - a string, which is the content name for one or more permissions, eg 'blog', 'story' #dsm($key); if (is_array($form['permission'][$key])) { $row = array(); if (is_numeric($key)) { // Module name: make a row for this module. $module_name = $form['permission'][$key]['#value']; #dsm($module_name); $row[] = array('data' => t('@module module', array('@module' => drupal_render($form['permission'][$key]))), 'class' => 'module', 'id' => 'module-'. $module_name, 'colspan' => 6); } else { // The content name: this begins the row. $content_name = $form['permission'][$key]['#value']; #dsm($content_suffix); $row[] = array('data' => drupal_render($form['permission'][$key]), 'class' => 'permission'); // The perms are stored. Get them to match up with the right checkbox item, then render it. // These come in the order the module defined them (probably?) // We want them in the same order as the $action_prefixes array. $perms_ordered = array(); foreach ($form['permission'][$key]['perms']['#value'] as $perm) { // create an arrray that looks like //action string => full perm name $pos = strpos($perm, $content_name); $action_prefix = substr($perm, 0, $pos-1); $perms_by_prefix[$action_prefix] = $perm; } #dsm($perms_by_prefix); // Iterate over this array to get the right order. foreach ($action_prefixes as $action_prefix) { $perm = $perms_by_prefix[$action_prefix]; if (is_array($form['checkboxes'][$rid][$perm])) { $row[] = array('data' => drupal_render($form['checkboxes'][$rid][$perm]), 'class' => 'checkbox', 'title' => $roles[$rid] .' : '. t($perm)); } else { $row[] = ''; } } } $rows[] = $row; } } } $header[] = (t('Content')); foreach ($action_prefixes as $action) { $header[] = array('data' => drupal_render($form['action_names'][$action]), 'class' => 'checkbox'); } $output .= theme('table', $header, $rows, array('id' => 'permissions')); $output .= drupal_render($form); return $output; } /** * Submit the form. */ function node_permissions_grid_admin_content_perm_submit($form, &$form_state) { // Save permissions: #dsm($form_state); $result = db_query('SELECT * FROM {role}'); while ($role = db_fetch_object($result)) { if (isset($form_state['values'][$role->rid])) { $form_state['values'][$role->rid] = array_filter($form_state['values'][$role->rid]); // This contains the permissions featured on the form as well as all the others the role had set. // eg, 'access content'. #dsm($form_state['values'][$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); $form_state['values'][$role->rid] = array_filter($form_state['values'][$role->rid]); if (count($form_state['values'][$role->rid])) { db_query("INSERT INTO {permission} (rid, perm) VALUES (%d, '%s')", $role->rid, implode(', ', array_keys($form_state['values'][$role->rid]))); } } } drupal_set_message(t('The changes have been saved.')); // Clear the cached pages cache_clear_all(); } /** * Output for main page: role list. * * Switching the form's theme function to bring us here is kinda hacky. * If core provided a role_load we could switch to using that in hook_menu. */ function theme_node_permissions_grid_admin_roles($form) { $header = array(t('Name'), array('data' => t('Operations'), 'colspan' => 2)); foreach (user_roles() as $rid => $name) { $edit_permissions = l(t('edit node permissions'), 'admin/user/node_permissions/'. $rid); if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) { $rows[] = array($name, l(t('edit role'), 'admin/user/roles/edit/'. $rid), $edit_permissions); } else { $rows[] = array($name, t('locked'), $edit_permissions); } } $output = drupal_render($form); $output .= theme('table', $header, $rows); return $output; }