TRUE, ); // List existing states. $states = workbench_moderation_states(); foreach ($states as $state) { $form['states'][$state->name]['state'] = array( '#type' => 'value', '#value' => $state, ); $form['states'][$state->name]['name'] = array( '#type' => 'value', '#value' => $state->name, ); $form['states'][$state->name]['label'] = array( '#type' => 'textfield', '#default_value' => $state->label, '#maxlength' => 255, '#size' => 30, ); $form['states'][$state->name]['machine_name'] = array( '#markup' => check_plain($state->name), ); $form['states'][$state->name]['description'] = array( '#type' => 'textfield', '#default_value' => $state->description, ); $form['states'][$state->name]['weight'] = array( '#type' => 'weight', '#default_value' => $state->weight, ); $form['states'][$state->name]['delete'] = array( '#type' => 'checkbox', '#title' => t('Delete'), '#title_display' => 'invisible', '#default_value' => FALSE, ); if ($state->name == workbench_moderation_state_published() || $state == workbench_moderation_state_none()) { $form['states'][$state->name]['delete']['#disabled'] = TRUE; } } // Provide fields to create a new state. $new_state['label'] = array( '#title' => t('New state'), '#type' => 'textfield', '#description' => t('Enter a name for the new state.'), '#maxlength' => 255, '#size' => 30, ); $new_state['name'] = array( '#type' => 'machine_name', '#maxlength' => 255, '#size' => 30, '#required' => FALSE, '#machine_name' => array( 'exists' => 'workbench_moderation_state_load', 'source' => array('states', '0', 'label'), ), ); $new_state['description'] = array( '#type' => 'textfield', '#maxlength' => 255, '#title' => ' ', '#description' => t('Enter a description of the new state.') ); $new_state['weight'] = array( '#type' => 'weight', ); $form['states'][] = $new_state; $form['submit'] = array( '#type' => 'submit', '#value' => t('Save'), ); return $form; } /** * Transforms the states administration form into a reorderable table. */ function theme_workbench_moderation_admin_states_form($variables) { $form = $variables['form']; drupal_add_tabledrag('workbench-moderation-states', 'order', 'sibling', 'workbench-moderation-state-weight'); $header = array( t('Name'), t('Machine name'), t('Description'), array('data' => t('Delete'), 'class' => array('checkbox')), t('Weight'), ); $rows = array(); foreach (element_children($form['states']) as $key) { $element = &$form['states'][$key]; $row = array( 'data' => array(), 'class' => array('draggable'), ); $row['data']['label'] = drupal_render($element['label']); $row['data']['name'] = drupal_render($element['name']) . drupal_render($element['machine_name']); $row['data']['description'] = drupal_render($element['description']); $row['data']['delete'] = drupal_render($element['delete']); $element['weight']['#attributes']['class'] = array('workbench-moderation-state-weight'); $row['data']['weight'] = drupal_render($element['weight']); $rows[] = $row; } $output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'workbench-moderation-states'))); $output .= drupal_render_children($form); return $output; } /** * Form submit handler for moderation state administration. */ function workbench_moderation_admin_states_form_submit($form, &$form_state) { foreach ($form_state['values']['states'] as $key => $info) { if (!empty($info['delete'])) { workbench_moderation_state_delete($info['state']); drupal_set_message(t('Moderation state %label (%name) has been deleted.', array('%label' => $info['label'], '%name' => $info['name']))); } elseif (!empty($info['name'])) { $state = (object) array( 'name' => $info['name'], 'label' => $info['label'], 'description' => $info['description'], 'weight' => $info['weight'], ); workbench_moderation_state_save($state); } } drupal_set_message(t('Your settings have been saved.')); // Warn users that changes here may need require reconfiguring Views that use Workbench. $views_message = t('Depending on the changes you have made it may be necessary to reconfigure Views that leverage Workbench Moderation such as workbench_moderation', array('@views' => url('admin/structure/views'), '@workbench_moderation' => url('admin/structure/views/edit/workbench_moderation'))); drupal_set_message($views_message, $type = 'warning', $repeat = FALSE); } /** * Administration form to create and delete moderation transitions. * * Transition ordering is based on state ordering. */ function workbench_moderation_admin_transitions_form($form, &$form_state) { $form['transitions'] = array( '#tree' => TRUE, ); // List existing states. $transitions = workbench_moderation_transitions(); foreach ($transitions as $transition) { $element = array(); $element['transition'] = array( '#type' => 'value', '#value' => $transition, ); $element['from_name'] = array( '#markup' => check_plain(workbench_moderation_state_label($transition->from_name)), ); $element['to_name'] = array( '#markup' => check_plain(workbench_moderation_state_label($transition->to_name)), ); $element['delete'] = array( '#type' => 'checkbox', '#title' => t('Delete'), '#title_display' => 'invisible', '#default_value' => FALSE, ); $form['transitions'][] = $element; } // Provide fields to create a new transition. $options = workbench_moderation_state_labels(); array_unshift($options, t('- Choose state -')); $element = array(); $element['from_name'] = array( '#type' => 'select', '#title' => t('New transition'), '#options' => $options, ); $element['to_name'] = array( '#type' => 'select', '#title' => ' ', '#options' => $options, ); $form['transitions']['new'] = $element; $form['submit'] = array( '#type' => 'submit', '#value' => t('Save'), ); return $form; } /** * Transforms the transitions administration form into a table. */ function theme_workbench_moderation_admin_transitions_form($variables) { $form = $variables['form']; $header = array( t('From'), '', t('To'), array('data' => t('Delete'), 'class' => array('checkbox')), ); $rows = array(); foreach (element_children($form['transitions']) as $key) { $element = &$form['transitions'][$key]; $row = array('data' => array()); $row['data']['from'] = drupal_render($element['from_name']); $row['data'][] = '-->'; $row['data']['to'] = drupal_render($element['to_name']); $row['data']['delete'] = drupal_render($element['delete']); $rows[] = $row; } // @TODO: change this css call. drupal_add_css(drupal_get_path('module', 'workbench_moderation') . '/css/workbench_moderation.css'); $output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('class' => array('width-auto')))); $output .= drupal_render_children($form); return $output; } /** * Form validation handler for the transitions form. */ function workbench_moderation_admin_transitions_form_validate($form, &$form_state) { $new = $form_state['values']['transitions']['new']; if (!empty($new['from_name']) && !empty($new['to_name'])) { if ($new['from_name'] == $new['to_name']) { form_set_error('transitions][new', t('To and from states of a new transition must be different.')); } else { foreach (workbench_moderation_transitions() as $t) { if ($new['from_name'] == $t->from_name && $new['to_name'] == $t->to_name) { form_set_error('transitions][new', t('This transition already exists.')); break; } } } } } /** * Form submit handler for moderation transitions. */ function workbench_moderation_admin_transitions_form_submit($form, &$form_state) { foreach ($form_state['values']['transitions'] as $transition) { if (!empty($transition['delete'])) { workbench_moderation_transition_delete($transition['transition']); drupal_set_message(t('%from --> %to has been deleted.', array('%from' => workbench_moderation_state_label($transition['transition']->from_name), '%to' => workbench_moderation_state_label($transition['transition']->to_name)))); } elseif (!empty($transition['from_name']) && !empty($transition['to_name'])) { $new_transition = (object) array( 'from_name' => $transition['from_name'], 'to_name' => $transition['to_name'], ); workbench_moderation_transition_save($new_transition); drupal_set_message(t('%from --> %to has been created.',array('%from' => workbench_moderation_state_label($new_transition->from_name), '%to' => workbench_moderation_state_label($new_transition->to_name)))); } } } /** * Check proper permissions for moderation roles. * * This helper administration form checks whether roles have the appropriate * permissions to use moderation as intended. */ function workbench_moderation_admin_check_role_form($form, &$form_state) { $form = array(); $roles = user_roles(); $form['role'] = array( '#type' => 'select', '#title' => t('Drupal role:'), '#description' => t('Select a role to check.'), '#options' => $roles, ); $form['moderation_task'] = array( '#type' => 'select', '#title' => t('Moderation task:'), '#description' => t('Select a moderation task that the role should be able to perform.'), '#options' => array( 'author' => t('Author moderated content'), 'editor' => t('Edit moderated content'), 'moderator' => t('Moderate content'), 'publisher' => t('Publish moderated content'), ), ); $types = drupal_map_assoc(workbench_moderation_moderate_node_types()); $all_types = node_type_get_types(); foreach ($types as $type) { $types[$type] = $all_types[$type]->name; } $form['types'] = array( '#type' => 'checkboxes', '#title' => t('Content types:'), '#description' => t('Select any content types on which the user should have the ability to perform the moderation task.'), '#options' => $types, ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Check'), ); if (empty($types)) { drupal_set_message(t('Moderation is not enabled for any content types. Visit the content type administration page to enable moderation for one or more types.', array('@content_type_administration_page' => url('admin/structure/types'))), 'warning'); $form['#disabled'] = TRUE; } return $form; } /** * Form submit handler for moderation role tests. */ function workbench_moderation_admin_check_role_form_submit($form, &$form_state) { $rid = $form_state['values']['role']; $role = user_role_load($rid); $types = array_filter($form_state['values']['types']); $moderation_task = $form_state['values']['moderation_task']; $recommended_permissions = workbench_moderation_recommended_permissions($types); $recommended_permissions = $recommended_permissions[$moderation_task]; // Get a full list of this role's permissions. $actual_permissions = user_role_permissions(array_filter(array( $rid => TRUE, DRUPAL_AUTHENTICATED_RID => ($rid != DRUPAL_ANONYMOUS_RID), ))); // The results of user_role_permissions() are in a nested array: // array(rid => array("permission name" => TRUE)) // Check each for our recommended permissions. foreach ($actual_permissions as $permissions) { $recommended_permissions = array_diff($recommended_permissions, array_keys(array_filter($permissions))); } if (empty($recommended_permissions)) { // All of the recommended permissions were accounted for. drupal_set_message(t('The @role role should be a qualified @moderation_task.', array( '@role' => $role->name, '@moderation_task' => $moderation_task, )), 'status'); } else { // The specified role didn't have some of the recommended permissions. Print a list for the user. $all_permissions = module_invoke_all('permission'); foreach ($recommended_permissions as $permission) { drupal_set_message(t('The @role role may need the "!permission_label" permission in order to be a qualified @moderation_task of @types content.', array( '@role' => $role->name, '@moderation_task' => $moderation_task, '@types' => implode(' and ', array(implode(', ', array_slice($types, 0, -1)), end($types))), '!permission_label' => $all_permissions[$permission]['title'], )), 'error'); } // Provide links to node and moderation permissions. drupal_set_message(t('View node permissions or moderation permissions for the @role role.', array( '@node_permissions' => url('admin/people/permissions/' . $rid, array('fragment' => 'module-node')), '@moderation_permissions' => url('admin/people/permissions/' . $rid, array('fragment' => 'module-workbench_moderation')), '@role' => $role->name, )), 'error'); // Note that we don't cover all configurations. drupal_set_message(t('The @role role may be a qualified @moderation_task regardless of these notices if it has liberal overall node and moderation permissions, like "Administer content" and "Bypass moderation restrictions".', array( '@role' => $role->name, '@moderation_task' => $moderation_task, )), 'warning'); } // Note that we don't cover all configurations. drupal_set_message(t('You must check manually that this role has the appropriate transition permissions for your workflow. View moderation permissions for this role.', array('@moderation_permissions_link' => url('admin/people/permissions/' . $rid, array('fragment' => 'module-workbench_moderation')))), 'warning'); // Repopulate the form with the submitted values. $form_state['rebuild'] = TRUE; } /** * Recommended permissions for typical moderation roles. */ function workbench_moderation_recommended_permissions($types = array()) { $states = workbench_moderation_states(); $draft = workbench_moderation_state_none(); $published = workbench_moderation_state_published(); $permissions = array( 'author' => array( // node "access content", "view own unpublished content", "view revisions", // workbench_moderation "view moderation messages", "use workbench_moderation my drafts tab", ), 'editor' => array( // node "access content", "view revisions", "revert revisions", // workbench "view all unpublished content", // workbench_moderation "view moderation messages", "view moderation history", "use workbench_moderation my drafts tab", "use workbench_moderation needs review tab", ), 'moderator' => array( // node "access content", "view revisions", // workbench "view all unpublished content", // workbench_moderation "view moderation messages", "view moderation history", "use workbench_moderation needs review tab", ), 'publisher' => array( // node "access content", "view revisions", "revert revisions", // workbench "view all unpublished content", // workbench_moderation "view moderation messages", "view moderation history", "use workbench_moderation needs review tab", ), ); foreach ($types as $type) { $permissions['author'][] = "create $type content"; $permissions['author'][] = "edit own $type content"; $permissions['editor'][] = "edit any $type content"; $permissions['moderator'][] = "edit any $type content"; $permissions['publisher'][] = "edit any $type content"; } return $permissions; }