fields(array('weight' => 5)) ->condition('name', 'workbench_moderation') ->execute(); } /** * Implements hook_uninstall(). */ function workbench_moderation_uninstall() { // Delete workbench_moderation variables. variable_del('workbench_moderation_nodedraft_disabled'); variable_del('workbench_moderation_per_node_type'); variable_del('workbench_moderation_show_revision_navigation'); // Get all node types. Loop through them and delete workbench-related variables. $types = node_type_get_types(); foreach ($types as $type_object) { $type = $type_object->type; variable_del("workbench_moderation_default_state_$type"); // Get node options that might hold a moderation flag. $node_options = variable_get("node_options_$type", array()); foreach ($node_options as $key => $option) { if ($option === 'moderation') { unset($node_options[$key]); } } variable_set("node_options_$type", $node_options); } } /** * Implements hook_schema(). */ function workbench_moderation_schema() { $schema['workbench_moderation_states'] = array( 'description' => 'Defines all possible states', 'fields' => array( 'name' => array( 'description' => 'The machine name of the moderation state.', 'type' => 'varchar', 'length' => '255', 'not null' => TRUE, ), 'label' => array( 'description' => 'A label for the moderation state.', 'type' => 'varchar', 'length' => '255', 'not null' => FALSE, ), 'description' => array( 'description' => 'A description of the moderation state.', 'type' => 'varchar', 'length' => '255', 'not null' => FALSE, ), 'weight' => array( 'description' => 'Sort weight for the moderation state.', 'type' => 'int', 'default' => 0, ), ), 'primary key' => array('name'), ); $schema['workbench_moderation_transitions'] = array( 'description' => 'Defines the valid transitions for states', 'fields' => array( 'id' => array( 'type' => 'serial', 'not null' => TRUE, 'unsigned' => TRUE, 'description' => 'Primary Key: Unique workbench_moderation transition identifier.', ), 'name' => array( 'description' => 'The machine-readable name of this workbench_moderation transition.', 'type' => 'varchar', 'length' => 255, 'initial' => 'from_name', ), 'from_name' => array( 'description' => 'The starting moderation state.', 'type' => 'varchar', 'length' => '255', 'not null' => FALSE, ), 'to_name' => array( 'description' => 'The ending moderation state.', 'type' => 'varchar', 'length' => '255', 'not null' => FALSE, ), ), 'primary key' => array('id'), ); $schema['workbench_moderation_node_history'] = array( 'fields' => array( 'hid' => array( 'description' => 'Node history entry key.', 'type' => 'serial', 'not null' => TRUE ), 'vid' => array( 'description' => 'Node revision id. Foreign key to {node_revision}', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'nid' => array( 'description' => 'Node id. Foreign key to {node}', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'from_state' => array( 'description' => 'The old moderation state of the node', 'type' => 'varchar', 'length' => '255', 'not null' => FALSE, ), 'state' => array( 'description' => 'The current moderation state of the node.', 'type' => 'varchar', 'length' => '255', 'not null' => FALSE, ), 'uid' => array( 'description' => 'The user id of the moderator who made the change. Foreign key to {users}.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'stamp' => array( 'description' => 'The timestamp of the change.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'published' => array( 'description' => 'Indicated the live revision of a node.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), 'is_current' => array( 'description' => 'Indicated the current revision of a node.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), ), 'primary key' => array('hid'), 'indexes' => array( 'nid' => array('nid'), 'vid' => array('vid'), ), 'foreign_keys' => array( 'nid' => array('node' => 'nid'), 'vid' => array('node_revision' => 'vid'), 'uid' => array('users' => 'uid'), ), ); return $schema; } /** * Adds default data for workflow states */ function _workbench_moderation_insert_values() { // Default states. $states = array( array( 'name' => 'draft', 'label' => 'Draft', 'description' => 'Work in progress', 'weight' => -99, ), array( 'name' => 'needs_review', 'label' => 'Needs Review', 'description' => 'Ready for moderation', 'weight' => 0, ), array( 'name' => 'published', 'label' => 'Published', 'description' => 'Make this version live', 'weight' => 99, ), ); // Save default states to the database. $query = db_insert('workbench_moderation_states') ->fields(array('name', 'label', 'description', 'weight')); foreach ($states as $state) { $query->values($state); } $query->execute(); // Default transitions. $transitions = array( array( 'name' => 'Submit for Review', 'from_name' => 'draft', 'to_name' => 'needs_review', ), array( 'name' => 'Reject', 'from_name' => 'needs_review', 'to_name' => 'draft', ), array( 'name' => 'Publish', 'from_name' => 'needs_review', 'to_name' => 'published', ), ); // Save default transitions to the database. $query = db_insert('workbench_moderation_transitions') ->fields(array('name', 'from_name', 'to_name')); foreach ($transitions as $transition) { $query->values($transition); } $query->execute(); } /** * Update the 'weight' field on {workbench_moderation_states}. * * Accept standard Drupal weight values. */ function workbench_moderation_update_7001() { db_change_field('workbench_moderation_states', 'weight', 'weight', array( 'description' => 'Sort weight for the moderation state.', 'type' => 'int', 'default' => 0, )); return t('Updated the weight field on the moderation states table.'); } /** * Drop the unused 'ntypes' field from workbench_moderation_transitions. */ function workbench_moderation_update_7002() { db_drop_field('workbench_moderation_transitions', 'ntype'); return t('Dropped unused field from the moderation transitions table.'); } /** * Use "revision" instead of "version" when referring to node revisions. */ function workbench_moderation_update_7003() { $old_permission = 'unpublish live version'; $new_permission = 'unpublish live revision'; // Which roles have the old permission? $roles = db_select('role_permission', 'role_permission') ->condition('permission', $old_permission) ->condition('module', 'workbench_moderation') ->fields('role_permission', array('rid')) ->execute() ->fetchCol(); // Grant these roles the new permission. Normally, this would use // user_role_grant_permissions(), but since update hooks run regardless of // whether a module is enabled, we can't guarantee that workbench_moderation // permissions will be available when user.module invokes hook_permission(). foreach ($roles as $rid) { db_merge('role_permission') ->key(array( 'rid' => $rid, 'permission' => $new_permission, )) ->fields(array( 'module' => 'workbench_moderation', )) ->execute(); } // Delete all grants of the old permission. db_delete('role_permission') ->condition('permission', $old_permission) ->condition('module', 'workbench_moderation') ->execute(); return t('The renamed permission was updated for !count roles.', array('!count' => count($roles))); } /** * Use "Published" instead of "Publish" and "Needs Review" instead of "Review" for state names. */ function workbench_moderation_update_7004() { // Update workbench_moderation_states db_update('workbench_moderation_states') ->fields(array( 'description' => 'Draft content is visible only to its author', )) ->condition('Name', 'Draft', '=') ->execute(); db_update('workbench_moderation_states') ->fields(array( 'Name' => 'Needs Review', 'description' => 'Needs Review content is brought to the attention administrators and editors who may then publish it', )) ->condition('Name', 'Review', '=') ->execute(); db_update('workbench_moderation_states') ->fields(array( 'Name' => 'Published', // Normally we would use workbench_moderation_state_published(), but we can't guarantee that workbench_moderation is enabled. 'description' => 'Published content is visible to the world', )) ->condition('Name', 'Publish', '=') ->execute(); // Update workbench_moderation_transitions db_update('workbench_moderation_transitions') ->fields(array( 'from_name' => 'Needs Review', )) ->condition('from_name', 'Review', '=') ->execute(); db_update('workbench_moderation_transitions') ->fields(array( 'to_name' => 'Needs Review', )) ->condition('to_name', 'Review', '=') ->execute(); db_update('workbench_moderation_transitions') ->fields(array( 'from_name' => 'Published', // Normally we would use workbench_moderation_state_published(), but we can't guarantee that workbench_moderation is enabled. )) ->condition('from_name', 'Publish', '=') ->execute(); db_update('workbench_moderation_transitions') ->fields(array( 'to_name' => 'Published', // Normally we would use workbench_moderation_state_published(), but we can't guarantee that workbench_moderation is enabled. )) ->condition('to_name', 'Publish', '=') ->execute(); // Update workbench_moderation_node_history db_update('workbench_moderation_node_history') ->fields(array( 'from_state' => 'Needs Review', )) ->condition('from_state', 'Review', '=') ->execute(); db_update('workbench_moderation_node_history') ->fields(array( 'state' => 'Needs Review', )) ->condition('state', 'Review', '=') ->execute(); db_update('workbench_moderation_node_history') ->fields(array( 'from_state' => 'Published', // Normally we would use workbench_moderation_state_published(), but we can't guarantee that workbench_moderation is enabled. )) ->condition('from_state', 'Publish', '=') ->execute(); db_update('workbench_moderation_node_history') ->fields(array( 'state' => 'Published', // Normally we would use workbench_moderation_state_published(), but we can't guarantee that workbench_moderation is enabled. )) ->condition('state', 'Publish', '=') ->execute(); // Update role_permission table // Grab all of the workbench_moderation permissions $perms = db_select('role_permission', 'rp') ->fields('rp', array('permission')) ->condition('permission', '%moderate content from %', 'LIKE') ->execute() ->fetchCol(); // This function doesn't need duplicates $perms = array_unique($perms); foreach ($perms as $key => $perm) { $new_perm = $perm; // Check that this permission hasn't had this change already if (!strpos($perm, 'Published')) { $new_perm = str_replace('Publish', 'Published', $perm); } // Check that this permission hasn't had this change already if (!strpos($new_perm, 'Needs Review')) { $new_perm = str_replace('Review', 'Needs Review', $new_perm); } //Update the records db_update('role_permission') ->fields(array( 'permission' => $new_perm, )) ->condition('permission', $perm, '=') ->execute(); } return t("Updated state names and transitions."); } /** * Shorten descriptions for default states */ function workbench_moderation_update_7005() { // Update workbench_moderation_states db_update('workbench_moderation_states') ->fields(array( 'description' => 'Visible only to the author', )) ->condition('Name', 'Draft', '=') // Normally we would use workbench_moderation_state_none(), but we can't guarantee that workbench_moderation is enabled. ->execute(); db_update('workbench_moderation_states') ->fields(array( 'description' => 'Visible to the author and editors', )) ->condition('Name', 'Needs Review', '=') ->execute(); db_update('workbench_moderation_states') ->fields(array( 'description' => 'Visible to the world', )) ->condition('Name', 'Published', '=') // Normally we would use workbench_moderation_state_published(), but we can't guarantee that workbench_moderation is enabled. ->execute(); return t("Updated state descriptions."); } /** * Add machine names to moderation states. */ function workbench_moderation_update_7006() { // Drop the unique key on name which will be converted to label. db_drop_unique_key('workbench_moderation_states', 'name'); // Add the new field. $spec = array( 'description' => 'A label for the moderation state.', 'type' => 'varchar', 'length' => '255', 'not null' => FALSE, ); db_add_field('workbench_moderation_states', 'label', $spec); // Transform names into machine_names, saving the original name into the new // 'label' field. $states = db_select('workbench_moderation_states', 'states') ->fields('states', array('name', 'label', 'description', 'weight')) ->orderBy('states.weight', 'ASC') ->execute() ->fetchAllAssoc('name'); foreach ($states as $state) { $machine_name = preg_replace('/[^a-z]+/', '_', strtolower($state->name)); db_update('workbench_moderation_states') ->fields(array( 'name' => $machine_name, 'label' => $state->name, )) ->condition('name', $state->name) ->execute(); db_update('workbench_moderation_transitions') ->fields(array('from_name' => $machine_name)) ->condition('from_name', $state->name) ->execute(); db_update('workbench_moderation_transitions') ->fields(array('to_name' => $machine_name)) ->condition('to_name', $state->name) ->execute(); db_update('workbench_moderation_node_history') ->fields(array('from_state' => $machine_name)) ->condition('from_state', $state->name) ->execute(); db_update('workbench_moderation_node_history') ->fields(array('state' => $machine_name)) ->condition('state', $state->name) ->execute(); } // Add a primary key on {workbench_moderation_states}. db_add_primary_key('workbench_moderation_states', array('name')); // Get content types where moderation is enabled and update // 'workbench_moderation_default_state_TYPE_NAME' variables $entity_info = entity_get_info('node'); foreach (array_keys($entity_info['bundles']) as $content_type) { $options = variable_get("node_options_$content_type", array()); if (in_array('revision', $options) && in_array('moderation', $options)) { $orig_name = variable_get('workbench_moderation_default_state_' . $content_type, 'Draft'); $machine_name = preg_replace('/[^a-z]+/', '_', strtolower($orig_name)); variable_set('workbench_moderation_default_state_' . $content_type, $machine_name); } } // Update transition permissions with new permission strings // Normally we would use workbench_moderation_states(), but we can't guarantee that workbench_moderation is enabled. $states = db_select('workbench_moderation_states', 'states') ->fields('states', array('name', 'label', 'description', 'weight')) ->orderBy('states.weight', 'ASC') ->execute() ->fetchAllAssoc('name'); // Normally we would use workbench_moderation_transitions(), but we can't guarantee that workbench_moderation is enabled. $query = db_select('workbench_moderation_transitions', 't') ->fields('t', array('from_name', 'to_name')); $alias_from = $query->addJoin('INNER', 'workbench_moderation_states', NULL, 't.from_name = %alias.name'); $alias_to = $query->addJoin('INNER', 'workbench_moderation_states', NULL, 't.to_name = %alias.name'); $query ->orderBy("$alias_from.weight", 'ASC') ->orderBy("$alias_to.weight", 'ASC'); $transitions = $query->execute()->fetchAll(); foreach ($transitions as $transition) { $old_perm = "moderate content from {$states[$transition->from_name]->label} to {$states[$transition->to_name]->label}"; $new_perm = "moderate content from {$transition->from_name} to {$transition->to_name}"; db_update('role_permission') ->fields(array('permission' => $new_perm)) ->condition('permission', $old_perm) ->execute(); } return t("Added column to store moderation state labels."); } /** * Replace the "Unpublish the current live revision" permission with a transition. */ function workbench_moderation_update_7007() { // Normally we would use workbench_moderation_states(), but we can't guarantee that workbench_moderation is enabled. $states = db_select('workbench_moderation_states', 'states') ->fields('states', array('name', 'label', 'description', 'weight')) ->orderBy('states.weight', 'ASC') ->execute() ->fetchAllAssoc('name'); // Add an unpublish transition from published to draft. The 'published' state // currently can't be deleted, but the draft state may or may not be present. $transition = (object) array( 'from_name' => 'published', 'to_name' => (isset($states['draft']) ? 'draft' : key($states)), ); // Normally we would use workbench_moderation_transition_save(), but we can't guarantee that workbench_moderation is enabled. db_merge('workbench_moderation_transitions') ->key(array('from_name' => $transition->from_name, 'to_name' => $transition->to_name)) ->fields((array) $transition) ->execute(); // Change permission grants from the deprecated unpublish permission to the // new transition permission. $roles = user_roles(FALSE, 'unpublish live revision'); $permissions = array( 'unpublish live revision' => FALSE, "moderate content from {$transition->from_name} to {$transition->to_name}" => TRUE, ); foreach ($roles as $rid => $role) { user_role_change_permissions($rid, $permissions); } return t("Added a new transition from %from to %to and updated unpublish permissions. Unpublishing content is now controlled by transition permissions, and roles with the 'Bypass moderation restrictions' permission may unpublish content.", array( '%from' => $transition->from_name, '%to' => $transition->to_name, )); } /** * Fix the not null column schema for {workbench_moderation_states}.name. */ function workbench_moderation_update_7008() { db_drop_primary_key('workbench_moderation_states'); db_change_field('workbench_moderation_states', 'name', 'name', array( 'description' => 'The machine name of the moderation state.', 'type' => 'varchar', 'length' => '255', 'not null' => TRUE, )); db_add_primary_key('workbench_moderation_states', array('name')); } /** * Add new fields to workbench_moderation_transitions table. */ function workbench_moderation_update_7009() { $fields = array( 'id' => array( 'type' => 'serial', 'not null' => TRUE, 'unsigned' => TRUE, 'description' => 'Primary Key: Unique workbench_moderation transition identifier.', ), 'name' => array( 'description' => 'The machine-readable name of this workbench_moderation transition.', 'type' => 'varchar', 'length' => 255, 'initial' => 'from_name', ), ); // Add index too. $index = array( 'primary key' => array('id'), ); db_add_field('workbench_moderation_transitions', 'id', $fields['id'], $index); db_add_field('workbench_moderation_transitions', 'name', $fields['name']); // Fill in the blanks. db_update('workbench_moderation_transitions') ->expression('name', "CONCAT(from_name, '-', to_name)") ->execute(); } /** * Comply with SQL-99: Rename the 'current' column to 'is_current'. */ function workbench_moderation_update_7010() { $table = 'workbench_moderation_node_history'; $field = 'current'; $field_new = 'is_current'; $spec = array( 'description' => 'Indicated the current revision of a node.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ); db_change_field($table, $field, $field_new, $spec); return t("Renamed 'current' column in node_history table"); } /** * Enable the Drafty module, a new dependency. */ function workbench_moderation_update_7300() { if (module_enable(array('drafty'))) { drupal_set_message(t('The Drafty module has been enabled.')); } else { throw new DrupalUpdateException('Unable to enable the Drafty module, it is a new dependency that must be downloaded.'); } }