View source
<?php
define('WORKFLOW_CREATION', 1);
define('WORKFLOW_CREATION_DEFAULT_WEIGHT', -50);
define('WORKFLOW_ARROW', '→');
function workflow_help($section) {
switch ($section) {
case strstr($section, 'admin/build/workflow/edit'):
return t('You are currently viewing the possible transitions to and from workflow states. The state is shown in the left column; the state to be moved to is to the right. For each transition, check the box next to the role(s) that may initiate the transition. For example, if only the hulking_editor role may move a node from Review state to the Published state, check the box next to hulking_editor. The author role is built in and refers to the user who authored the node.');
case 'admin/build/workflow/add':
return t('To get started, provide a name for your workflow. This name will be used as a label when the workflow status is shown during node editing.');
case strstr($section, 'admin/build/workflow/state'):
return t('Enter the name for a state in your workflow. For example, if you were doing a meal workflow it may include states like <em>shop</em>, <em>prepare food</em>, <em>eat</em>, and <em>clean up</em>.');
case strstr($section, 'admin/build/workflow/actions') && sizeof($section) == 22:
return t('Use this page to set actions to happen when transitions occur. To <a href="@link">configure actions</a>, use the actions module.', array(
'@link' => url('admin/actions'),
));
}
}
function workflow_perm() {
return array(
'administer workflow',
'schedule workflow transitions',
);
}
function workflow_menu($may_cache) {
$items = array();
$access = user_access('administer workflow');
if ($may_cache) {
$items[] = array(
'path' => 'admin/build/workflow',
'title' => t('Workflow'),
'access' => $access,
'callback' => 'workflow_overview',
'description' => t('Allows the creation and assignment of arbitrary workflows to node types.'),
);
$items[] = array(
'path' => 'admin/build/workflow/edit',
'title' => t('Edit workflow'),
'type' => MENU_CALLBACK,
'callback' => 'workflow_edit_page',
);
$items[] = array(
'path' => 'admin/build/workflow/list',
'title' => t('List'),
'weight' => -10,
'callback' => 'workflow_page',
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items[] = array(
'path' => 'admin/build/workflow/add',
'title' => t('Add workflow'),
'weight' => -8,
'callback' => 'drupal_get_form',
'callback arguments' => array(
'workflow_add_form',
),
'type' => MENU_LOCAL_TASK,
);
$items[] = array(
'path' => 'admin/build/workflow/state',
'title' => t('Add state'),
'type' => MENU_CALLBACK,
'callback' => 'drupal_get_form',
'callback arguments' => array(
'workflow_state_add_form',
),
);
$items[] = array(
'path' => 'admin/build/workflow/state/delete',
'title' => t('Delete State'),
'type' => MENU_CALLBACK,
'callback' => 'drupal_get_form',
'callback arguments' => array(
'workflow_state_delete_form',
),
);
$items[] = array(
'path' => 'admin/build/workflow/delete',
'title' => t('Delete workflow'),
'type' => MENU_CALLBACK,
'callback' => 'drupal_get_form',
'callback arguments' => array(
'workflow_delete_form',
),
);
$items[] = array(
'path' => 'admin/build/workflow/actions',
'title' => t('Workflow actions'),
'type' => MENU_CALLBACK,
'callback' => 'workflow_actions_page',
);
$items[] = array(
'path' => 'admin/build/workflow/actions/remove',
'title' => t('Workflow actions'),
'type' => MENU_CALLBACK,
'callback' => 'drupal_get_form',
'callback arguments' => array(
'workflow_actions_remove_form',
),
);
}
else {
if (arg(0) == 'node' && is_numeric(arg(1))) {
$node = node_load(arg(1));
$wid = workflow_get_workflow_for_type($node->type);
if ($wid) {
global $user;
$roles = array_keys($user->roles);
if ($node->uid == $user->uid) {
$roles = array_merge(array(
'author',
), $roles);
}
$workflow = db_fetch_object(db_query("SELECT * FROM {workflows} WHERE wid = %d", $wid));
$allowed_roles = $workflow->tab_roles ? explode(',', $workflow->tab_roles) : array();
$items[] = array(
'path' => "node/{$node->nid}/workflow",
'title' => t('Workflow'),
'access' => array_intersect($roles, $allowed_roles) || user_access('administer nodes'),
'type' => MENU_LOCAL_TASK,
'weight' => 2,
'callback' => 'workflow_tab_page',
'callback arguments' => arg(1),
);
}
}
}
return $items;
}
function workflow_tab_page($nid) {
$node = node_load($nid);
drupal_set_title(check_plain($node->title));
$wid = workflow_get_workflow_for_type($node->type);
$states_per_page = 20;
$states = workflow_get_states($wid) + array(
t('(creation)'),
);
$current = workflow_node_current_state($node);
$output = '<p>' . t('Current state: @state', array(
'@state' => $states[$current],
)) . "</p>\n";
$output .= drupal_get_form('workflow_tab_form', $node, $wid, $states, $current);
$result = pager_query("SELECT h.*, u.name FROM {workflow_node_history} h LEFT JOIN {users} u ON h.uid = u.uid WHERE nid = %d ORDER BY stamp DESC", $states_per_page, 0, NULL, $nid);
$rows = array();
while ($history = db_fetch_object($result)) {
$rows[] = array(
format_date($history->stamp),
check_plain($states[$history->old_sid]),
check_plain($states[$history->sid]),
theme('username', $history),
check_plain($history->comment),
);
}
$output .= theme('table', array(
t('Date'),
t('Old State'),
t('New State'),
t('By'),
t('Comment'),
), $rows, array(
'class' => 'workflow_history',
), t('Workflow History'));
$output .= theme('pager', $states_per_page);
return $output;
}
function workflow_tab_form(&$node, $wid, $states, $current) {
$form = array();
$choices = workflow_field_choices($node);
$min = $states[$current] == t('(creation)') ? 1 : 2;
if (count($choices) >= $min) {
$wid = workflow_get_workflow_for_type($node->type);
$name = check_plain(workflow_get_name($wid));
if ($node->_workflow_scheduled_timestamp && $node->_workflow_scheduled_sid) {
global $user;
if (variable_get('configurable_timezones', 1) && $user->uid && strlen($user->timezone)) {
$timezone = $user->timezone;
}
else {
$timezone = variable_get('date_default_timezone', 0);
}
$current = $node->_workflow_scheduled_sid;
$timestamp = $node->_workflow_scheduled_timestamp;
$comment = $node->_workflow_scheduled_comment;
}
workflow_node_form($form, t('Change %s state', array(
'%s' => $name,
)), $name, $current, $choices, $timestamp, $comment);
$form['node'] = array(
'#type' => 'value',
'#value' => $node,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
}
return $form;
}
function workflow_tab_form_submit($form_id, $form_values) {
$node = $form_values['node'];
$node->workflow = $form_values['workflow'];
$node->workflow_comment = $form_values['workflow_comment'];
$node->workflow_scheduled = $form_values['workflow_scheduled'];
$node->workflow_scheduled_date = $form_values['workflow_scheduled_date'];
$node->workflow_scheduled_hour = $form_values['workflow_scheduled_hour'];
node_save($node);
return 'node/' . $node->nid;
}
function workflow_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
switch ($op) {
case 'load':
$node->_workflow = workflow_node_current_state($node);
$res = db_query('SELECT * FROM {workflow_scheduled_transition} WHERE nid = %d', $node->nid);
if ($row = db_fetch_object($res)) {
$node->_workflow_scheduled_sid = $row->sid;
$node->_workflow_scheduled_timestamp = $row->scheduled;
$node->_workflow_scheduled_comment = $row->comment;
}
break;
case 'insert':
case 'update':
$wid = workflow_get_workflow_for_type($node->type);
if (!$wid) {
break;
}
$sid = $node->workflow;
if (!$sid && $op == 'insert') {
$choices = workflow_field_choices($node);
$keys = array_keys($choices);
$sid = array_shift($keys);
}
if (array_key_exists($sid, workflow_field_choices($node))) {
if (!$node->workflow_scheduled) {
workflow_execute_transition($node, $sid, $node->workflow_comment);
}
else {
$nid = $node->nid;
$comment = $node->workflow_comment;
$old_sid = workflow_node_current_state($node);
if ($node->workflow_scheduled_date['day'] < 10) {
$node->workflow_scheduled_date['day'] = '0' . $node->workflow_scheduled_date['day'];
}
if ($node->workflow_scheduled_date['month'] < 10) {
$node->workflow_scheduled_date['month'] = '0' . $node->workflow_scheduled_date['month'];
}
if (!$node->workflow_scheduled_hour) {
$node->workflow_scheduled_hour = '00:00';
}
$scheduled = $node->workflow_scheduled_date['year'] . $node->workflow_scheduled_date['month'] . $node->workflow_scheduled_date['day'] . ' ' . $node->workflow_scheduled_hour . 'Z';
if ($scheduled = strtotime($scheduled)) {
global $user;
if (variable_get('configurable_timezones', 1) && $user->uid && strlen($user->timezone)) {
$timezone = $user->timezone;
}
else {
$timezone = variable_get('date_default_timezone', 0);
}
$scheduled = $scheduled - $timezone;
db_query("DELETE FROM {workflow_scheduled_transition} WHERE nid = {$nid}");
db_query('INSERT INTO {workflow_scheduled_transition} VALUES (%d, %d, %d, %d,\'%s\')', $nid, $old_sid, $sid, $scheduled, $comment);
drupal_set_message(t("@node_title is scheduled for state change on !scheduled_date", array(
"@node_title" => $node->title,
"!scheduled_date" => format_date($scheduled),
)));
}
}
}
break;
case 'delete':
db_query("DELETE FROM {workflow_node} WHERE nid = %d", $node->nid);
break;
}
}
function workflow_node_form(&$form, $title, $name, $current, $choices, $timestamp = NULL, $comment = NULL) {
if (sizeof($choices) == 1) {
$form['workflow'][$name] = array(
'#type' => 'hidden',
'#value' => $current,
);
}
else {
$form['workflow'][$name] = array(
'#type' => 'radios',
'#title' => $title,
'#options' => $choices,
'#name' => $name,
'#parents' => array(
'workflow',
),
'#default_value' => $current,
);
if (arg(1) != 'add' && user_access('schedule workflow transitions')) {
$scheduled = $timestamp ? 1 : 0;
$timestamp = $scheduled ? $timestamp : time();
$form['workflow']['workflow_scheduled'] = array(
'#type' => 'radios',
'#title' => t('Schedule'),
'#options' => array(
t('Immediately'),
t('Schedule for state change at:'),
),
'#default_value' => $scheduled,
);
$form['workflow']['workflow_scheduled_date'] = array(
'#type' => 'date',
'#default_value' => array(
'day' => format_date($timestamp, 'custom', 'j'),
'month' => format_date($timestamp, 'custom', 'n'),
'year' => format_date($timestamp, 'custom', 'Y'),
),
);
$hours = format_date($timestamp, 'custom', 'H:i');
$form['workflow']['workflow_scheduled_hour'] = array(
'#type' => 'textfield',
'#description' => t('Please enter a time in 24 hour (eg. HH:MM) format. If no time is included, the default will be midnight on the specified date. The current time is: ') . format_date(time()),
'#default_value' => $scheduled ? $hours : NULL,
);
}
$form['workflow']['workflow_comment'] = array(
'#type' => 'textarea',
'#title' => t('Comment'),
'#description' => t('A comment to put in the workflow log.'),
'#default_value' => $comment,
);
}
}
function workflow_form_alter($form_id, &$form) {
if (isset($form['type']) && $form['#base'] == 'node_form') {
$node = $form['#node'];
$choices = workflow_field_choices($node);
$wid = workflow_get_workflow_for_type($node->type);
$states = workflow_get_states($wid) + array(
t('(creation)'),
);
$current = workflow_node_current_state($node);
$min = $states[$current] == t('(creation)') ? 1 : 2;
if (count($choices) < $min) {
return;
}
$name = check_plain(workflow_get_name($wid));
if (!isset($choices[$current])) {
$array = array_keys($choices);
$current = $array[0];
}
if (sizeof($choices) > 1) {
$form['workflow'] = array(
'#type' => 'fieldset',
'#title' => $name,
'#collapsible' => TRUE,
'#collapsed' => FALSE,
'#weight' => 10,
);
}
if ($node->_workflow_scheduled_timestamp && $node->_workflow_scheduled_sid) {
global $user;
if (variable_get('configurable_timezones', 1) && $user->uid && strlen($user->timezone)) {
$timezone = $user->timezone;
}
else {
$timezone = variable_get('date_default_timezone', 0);
}
$current = $node->_workflow_scheduled_sid;
$timestamp = $node->_workflow_scheduled_timestamp;
$comment = $node->_workflow_scheduled_comment;
}
workflow_node_form($form, $name, $name, $current, $choices, $timestamp, $comment);
}
}
function workflow_execute_transition($node, $sid, $comment = NULL) {
$old_sid = workflow_node_current_state($node);
if ($old_sid == $sid) {
if ($comment && !$node->_workflow_scheduled_comment) {
$node->workflow_stamp = time();
db_query("UPDATE {workflow_node} SET stamp = %d WHERE nid = %d", $node->workflow_stamp, $node->nid);
$result = module_invoke_all('workflow', 'transition pre', $old_sid, $sid, $node);
_workflow_write_history($node, $sid, $comment);
}
$result = module_invoke_all('workflow', 'transition post', $old_sid, $sid, $node);
return;
}
global $user;
if ($user->uid > 1 || $user->uid == 0) {
$tid = workflow_get_transition_id($old_sid, $sid);
if (!$tid) {
watchdog('workflow', t('Attempt to go to nonexistent transition (from %old to %new)', array(
'%old' => $old_sid,
'%new' => $sid,
), WATCHDOG_ERROR));
return;
}
if (!workflow_transition_allowed($tid, array_merge(array_keys($user->roles), array(
'author',
)))) {
watchdog('workflow', t('User %user not allowed to go from state %old to %new)', array(
'%user' => $user->name,
'%old' => $old_sid,
'%new' => $sid,
), WATCHDOG_NOTICE));
return;
}
}
$result = module_invoke_all('workflow', 'transition pre', $old_sid, $sid, $node);
if (in_array(FALSE, $result)) {
return;
}
_workflow_node_to_state($node, $sid, $comment);
$state_name = db_result(db_query("SELECT state FROM {workflow_states} WHERE sid = %d", $sid));
$type = node_get_types('name', $node->type);
watchdog('workflow', t('State of @type %node_title set to @state_name', array(
'@type' => $type,
'%node_title' => $node->title,
'@state_name' => $state_name,
)), WATCHDOG_NOTICE, l('view', 'node/' . $node->nid));
module_invoke_all('workflow', 'transition post', $old_sid, $sid, $node);
db_query('DELETE FROM {workflow_scheduled_transition} WHERE nid = %d', $node->nid);
}
function action_workflow_execute_transition($op, $edit = array(), &$node) {
switch ($op) {
case 'do':
if (!isset($node->workflow) && !isset($node->_workflow)) {
watchdog('workflow', t('Unable to get current workflow state of node %nid.', array(
'%nid' => $node->nid,
)));
return;
}
$current_state = isset($node->workflow) ? $node->workflow : $node->_workflow;
$new_state = '';
if ($new_state == '') {
$choices = workflow_field_choices($node);
foreach ($choices as $sid => $name) {
if (isset($flag)) {
$new_state = $sid;
$new_state_name = $name;
break;
}
if ($sid == $current_state) {
$flag = TRUE;
}
}
}
watchdog('action', t('Changing workflow state of node id %id to %state', array(
'%id' => intval($node->nid),
'%state' => check_plain($new_state_name),
)));
workflow_execute_transition($node, $new_state);
watchdog('action', t('Changed workflow state of node id %id to %state', array(
'%id' => intval($node->nid),
'%state' => check_plain($new_state_name),
)));
break;
case 'metadata':
return array(
'description' => t('Change workflow state of a node to next state'),
'type' => t('Workflow'),
'batchable' => TRUE,
'configurable' => FALSE,
);
case 'form':
return '';
case 'validate':
return TRUE;
case 'submit':
return '';
}
}
function workflow_field_choices($node) {
global $user;
$wid = workflow_get_workflow_for_type($node->type);
if (!$wid) {
return array();
}
$states = workflow_get_states($wid);
$roles = array_keys($user->roles);
$current_sid = workflow_node_current_state($node);
if ($user->uid == $node->uid && $node->uid > 0 || arg(0) == 'node' && arg(1) == 'add') {
$roles += array(
'author' => 'author',
);
}
if ($user->uid == 1) {
$roles = 'ALL';
}
$transitions = workflow_allowable_transitions($current_sid, 'to', $roles);
if ($current_sid == _workflow_creation_state($wid)) {
unset($transitions[$current_sid]);
}
return $transitions;
}
function workflow_node_current_state($node) {
$sid = db_result(db_query("SELECT sid FROM {workflow_node} WHERE nid=%d ", $node->nid));
if (!$sid) {
$wid = workflow_get_workflow_for_type($node->type);
$sid = _workflow_creation_state($wid);
}
return $sid;
}
function _workflow_creation_state($wid) {
static $cache;
if (!isset($cache[$wid])) {
$result = db_result(db_query("SELECT sid FROM {workflow_states} WHERE " . "wid=%d AND sysid=%d", $wid, WORKFLOW_CREATION));
$cache[$wid] = $result;
}
return $cache[$wid];
}
function workflow_workflow($op, $old_state, $new_state, $node) {
switch ($op) {
case 'transition pre':
break;
case 'transition post':
$tid = workflow_get_transition_id($old_state, $new_state);
if ($tid) {
$actions_this_tid = workflow_get_actions($tid);
if ($actions_this_tid && function_exists('actions_do')) {
actions_do(array_keys($actions_this_tid), $node);
}
}
break;
}
}
function workflow_add_form($name = NULL) {
$form = array();
$form['wf_name'] = array(
'#type' => 'textfield',
'#title' => t('Workflow Name'),
'#maxlength' => '254',
'#default_value' => $name,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Add Workflow'),
);
return $form;
}
function workflow_add_form_validate($form_id, $form_values) {
$workflow_name = $form_values['wf_name'];
$workflows = array_flip(workflow_get_all());
if ($workflow_name == '') {
form_set_error('wf_name', t('Please provide a nonblank name for the new workflow.'));
}
if (array_key_exists($workflow_name, $workflows)) {
form_set_error('wf_name', t('A workflow with the name %name already exists. Please enter another name for your new workflow.', array(
'%name' => $workflow_name,
)));
}
}
function workflow_add_form_submit($form_id, $form_values) {
$workflow_name = $form_values['wf_name'];
if (array_key_exists('wf_name', $form_values) && $workflow_name != '') {
workflow_create($workflow_name);
watchdog('workflow', t('Created workflow %name', array(
'%name' => $workflow_name,
)));
drupal_set_message(t('The workflow %name was created. You should now add states to your workflow.', array(
'%name' => $workflow_name,
)), 'warning');
return 'admin/build/workflow';
}
}
function workflow_delete_form($wid, $sid = NULL) {
if (isset($sid)) {
return workflow_state_delete_form($wid, $sid);
}
$form = array();
$form['wid'] = array(
'#type' => 'value',
'#value' => $wid,
);
return confirm_form($form, t('Are you sure you want to delete %title? All nodes that have a workflow state associated with this workflow will have those workflow states removed.', array(
'%title' => workflow_get_name($wid),
)), $_GET['destination'] ? $_GET['destination'] : 'admin/build/workflow', t('This action cannot be undone.'), t('Delete'), t('Cancel'));
}
function workflow_delete_form_submit($form_id, $form_values) {
if ($form_values['confirm'] == 1) {
$workflow_name = workflow_get_name($form_values['wid']);
workflow_deletewf($form_values['wid']);
watchdog('workflow', t('Deleted workflow %name with all its states', array(
'%name' => $workflow_name,
)));
drupal_set_message(t('The workflow %name with all its states was deleted.', array(
'%name' => $workflow_name,
)));
return 'admin/build/workflow';
}
}
function workflow_permissions($wid) {
$name = workflow_get_name($wid);
$all = array();
$roles = array(
'author' => t('author'),
) + user_roles();
foreach ($roles as $role => $value) {
$all[$role]['name'] = $value;
}
$result = db_query("SELECT t.roles, s1.state AS state_name, s2.state AS target_state_name " . "FROM {workflow_transitions} t " . "INNER JOIN {workflow_states} s1 ON s1.sid = t.sid " . "INNER JOIN {workflow_states} s2 ON s2.sid = t.target_sid " . "WHERE s1.wid = %d " . "ORDER BY s1.weight ASC , s1.state ASC , s2.weight ASC , s2.state ASC", $wid);
while ($data = db_fetch_object($result)) {
foreach (explode(',', $data->roles) as $role) {
$all[$role]['transitions'][] = array(
$data->state_name,
WORKFLOW_ARROW,
$data->target_state_name,
);
}
}
$output = '';
$header = array(
t('From'),
'',
t('To'),
);
foreach ($all as $role => $value) {
$output .= '<h3>' . t("%role may do these transitions:", array(
'%role' => $value['name'],
)) . '</h3>';
if ($value['transitions']) {
$output .= theme('table', $header, $value['transitions']) . '<p></p>';
}
else {
$output .= '<table><tbody><tr class="even"><td>' . t('None') . '</td><td></tr></tbody></table><p></p>';
}
}
return $output;
}
function workflow_edit_page($wid) {
$output = drupal_get_form('workflow_edit_form', $wid);
$output .= workflow_permissions($wid);
return $output;
}
function workflow_edit_form($wid) {
$form = array();
$workflow = db_fetch_object(db_query("SELECT * FROM {workflows} WHERE wid = %d", $wid));
$form['wid'] = array(
'#type' => 'value',
'#value' => $workflow->wid,
);
$form['wf_name'] = array(
'#type' => 'textfield',
'#default_value' => $workflow->name,
'#title' => t('Workflow Name'),
'#size' => '16',
'#maxlength' => '254',
);
$form['tab'] = array(
'#type' => 'fieldset',
'#title' => t('Workflow tab permissions'),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
);
$form['tab']['tab_roles'] = array(
'#type' => 'checkboxes',
'#options' => workflow_get_roles(),
'#default_value' => explode(',', $workflow->tab_roles),
'#description' => t('Select any roles that should have access to the workflow tab on nodes that have a workflow.'),
);
$form['transitions'] = workflow_transition_grid_form($workflow->wid);
$form['transitions']['#tree'] = TRUE;
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}
function theme_workflow_edit_form($form) {
$output = drupal_render($form['wf_name']);
$wid = $form['wid']['#value'];
$states = workflow_get_states($wid);
drupal_set_title(t('Edit workflow %name', array(
'%name' => workflow_get_name($wid),
)));
if ($states) {
$roles = workflow_get_roles();
$header = array(
array(
'data' => t('From / To ') . ' ' . WORKFLOW_ARROW,
),
);
$rows = array();
foreach ($states as $state_id => $name) {
if ($name != t('(creation)')) {
$header[] = array(
'data' => t($name),
);
}
$row = array(
array(
'data' => $name,
),
);
foreach ($states as $nested_state_id => $nested_name) {
if ($nested_name == t('(creation)')) {
continue;
}
if ($nested_state_id != $state_id) {
$from = $state_id;
$to = $nested_state_id;
$cell = '';
foreach ($roles as $rid => $role_name) {
$cell .= drupal_render($form['transitions'][$from][$to][$rid]);
}
$row[] = array(
'data' => $cell,
);
}
else {
$row[] = array(
'data' => '',
);
}
}
$rows[] = $row;
}
$output .= theme('table', $header, $rows);
}
else {
$output = 'There are no states defined for this workflow.';
}
$output .= drupal_render($form);
return $output;
}
function workflow_edit_form_validate($form_id, $form_values) {
$wid = $form_values['wid'];
if (array_key_exists('wf_name', $form_values) && $form_values['wf_name'] != '') {
$workflow_name = $form_values['wf_name'];
$workflows = array_flip(workflow_get_all());
if (array_key_exists($workflow_name, $workflows) && $wid != $workflows[$workflow_name]) {
form_set_error('wf_name', t('A workflow with the name %name already exists. Please enter another name for this workflow.', array(
'%name' => $workflow_name,
)));
}
}
else {
form_set_error('wf_name', t('Please provide a nonblank name for this workflow.'));
}
$creation_id = _workflow_creation_state($wid);
if (is_array($form_values['transitions'][$creation_id])) {
foreach ($form_values['transitions'][$creation_id] as $to => $roles) {
if ($roles['author']) {
$author_has_permission = true;
break;
}
}
}
if (!$author_has_permission) {
form_set_error('transitions', t('Please give the author permission to go from %creation to at least one state!', array(
'%creation' => '(creation)',
)));
}
}
function workflow_edit_form_submit($form_id, $form_values) {
workflow_update($form_values['wid'], $form_values['wf_name'], array_filter($form_values['tab_roles']));
workflow_update_transitions($form_values['transitions']);
drupal_set_message(t('The workflow was updated.'));
return 'admin/build/workflow';
}
function workflow_state_add_form($wid, $sid = NULL) {
$form = array();
$form['wid'] = array(
'#type' => 'value',
'#value' => $wid,
);
if (isset($sid)) {
$state = workflow_get_state($sid);
if (isset($state)) {
drupal_set_title(t('Edit workflow state %state', array(
'%state' => $state['state'],
)));
$form['sid'] = array(
'#type' => 'value',
'#value' => $sid,
);
}
}
if (!isset($state) || $state === FALSE) {
$state = array(
'state' => '',
'weight' => 0,
);
drupal_set_title(t('Add a new state to workflow %workflow', array(
'%workflow' => workflow_get_name($wid),
)));
}
$form['state'] = array(
'#type' => 'textfield',
'#title' => t('State name'),
'#default_value' => $state['state'],
'#size' => '16',
'#maxlength' => '254',
'#required' => TRUE,
'#description' => t('Enter the name for a state in your workflow. For example, if you were doing a meal workflow ' . 'it may include states like <em>shop</em>, <em>prepare food</em>, <em>eat</em>, and <em>clean up</em>.'),
);
$form['weight'] = array(
'#type' => 'weight',
'#title' => t('Weight'),
'#default_value' => $state['weight'],
'#description' => t('In listings, the heavier states will sink and the lighter states will be positioned nearer the top.'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}
function workflow_state_add_form_validate($form_id, $form_values) {
$state_name = $form_values['state'];
$wf_states = array_flip(workflow_get_states($form_values['wid']));
if (array_key_exists('sid', $form_values)) {
if ($state_name == '') {
form_set_error('state', t('Please provide a nonblank name for this state.'));
}
if (array_key_exists($state_name, $wf_states) && $form_values['sid'] != $wf_states[$state_name]) {
form_set_error('state', t('A state with the name %state already exists in this workflow. ' . 'Please enter another name for this state.', array(
'%state' => $state_name,
)));
}
}
else {
if ($state_name == '') {
form_set_error('state', t('Please provide a nonblank name for the new state.'));
}
if (array_key_exists($state_name, $wf_states)) {
form_set_error('state', t('A state with the name %state already exists in this workflow. ' . 'Please enter another name for your new state.', array(
'%state' => $state_name,
)));
}
}
}
function workflow_state_add_form_submit($form_id, $form_values) {
workflow_state_save($form_values);
if (array_key_exists('sid', $form_values)) {
drupal_set_message(t('The workflow state was updated.'));
}
else {
watchdog('workflow', t('Created workflow state %name', array(
'%name' => $form_values['state'],
)));
drupal_set_message(t('The workflow state %name was created.', array(
'%name' => $form_values['state'],
)));
}
return 'admin/build/workflow';
}
function workflow_update_transitions($transitions = array()) {
if (!$transitions) {
return;
}
foreach ($transitions as $from => $to_data) {
foreach ($to_data as $to => $role_data) {
foreach ($role_data as $role => $can_do) {
if ($can_do) {
workflow_transition_add_role($from, $to, $role);
}
else {
workflow_transition_delete_role($from, $to, $role);
}
}
}
}
db_query("DELETE FROM {workflow_transitions} WHERE roles=''");
}
function workflow_transition_add_role($from, $to, $role) {
$tid = workflow_get_transition_id($from, $to);
if ($tid) {
$roles = db_result(db_query("SELECT roles FROM {workflow_transitions} WHERE tid=%d", $tid));
$roles = explode(',', $roles);
if (array_search($role, $roles) === FALSE) {
$roles[] = $role;
db_query("UPDATE {workflow_transitions} SET roles='%s' WHERE tid=%d", implode(',', $roles), $tid);
}
}
else {
db_query("INSERT INTO {workflow_transitions} (tid, sid, target_sid, roles) VALUES (%d, %d, %d, '%s')", db_next_id('{workflow_transitions}_tid'), $from, $to, $role);
}
}
function workflow_transition_delete_role($from, $to, $role) {
$tid = workflow_get_transition_id($from, $to);
if ($tid) {
$roles = db_result(db_query("SELECT roles FROM {workflow_transitions} WHERE tid=%d", $tid));
$roles = explode(',', $roles);
if (($i = array_search($role, $roles)) !== FALSE) {
unset($roles[$i]);
db_query("UPDATE {workflow_transitions} SET roles='%s' WHERE tid=%d", implode(',', $roles), $tid);
}
}
}
function workflow_transition_grid_form($wid) {
$form = array();
$roles = workflow_get_roles();
$states = workflow_get_states($wid);
if (!$states) {
$form = array(
'#type' => 'markup',
'#value' => t('There are no states defined for this workflow.'),
);
return $form;
}
foreach ($states as $state_id => $name) {
foreach ($states as $nested_state_id => $nested_name) {
if ($nested_name == t('(creation)')) {
continue;
}
if ($nested_state_id != $state_id) {
$from = $state_id;
$to = $nested_state_id;
foreach ($roles as $rid => $role_name) {
$tid = workflow_get_transition_id($from, $to);
$form[$from][$to][$rid] = array(
'#type' => 'checkbox',
'#title' => $role_name,
'#default_value' => $tid ? workflow_transition_allowed($tid, $rid) : FALSE,
);
}
}
}
}
return $form;
}
function workflow_transition_allowed($tid, $role = null) {
$allowed = db_result(db_query("SELECT roles FROM {workflow_transitions} WHERE tid=%d", $tid));
$allowed = explode(',', $allowed);
if ($role) {
if (!is_array($role)) {
$role = array(
$role,
);
}
return array_intersect($role, $allowed) == TRUE;
}
else {
return $allowed == TRUE;
}
}
function workflow_overview() {
$workflows = workflow_get_all();
$row = array();
foreach ($workflows as $wid => $name) {
$links = array(
'workflow_overview_add_state' => array(
'title' => t('Add state'),
'href' => "admin/build/workflow/state/{$wid}",
),
'workflow_overview_actions' => array(
'title' => t('Actions'),
'href' => "admin/build/workflow/actions/{$wid}",
),
'workflow_overview_edit' => array(
'title' => t('Edit'),
'href' => "admin/build/workflow/edit/{$wid}",
),
'workflow_overview_delete' => array(
'title' => t('Delete'),
'href' => "admin/build/workflow/delete/{$wid}",
),
);
$states = workflow_get_states($wid);
if (!(module_exists('actions') && $states)) {
unset($links['workflow_overview_actions']);
}
$row[] = array(
$name,
theme('links', $links),
);
$subrows = array();
foreach ($states as $sid => $statename) {
if (!workflow_is_system_state(t($statename))) {
$statelinks = array(
'workflow_overview_edit_state' => array(
'title' => t('Edit'),
'href' => "admin/build/workflow/state/{$wid}/{$sid}",
),
'workflow_overview_delete_state' => array(
'title' => t('Delete'),
'href' => "admin/build/workflow/state/delete/{$wid}/{$sid}",
),
);
}
$subrows[] = array(
t($statename),
theme('links', $statelinks),
);
unset($statelinks);
}
$subheader_state = array(
'data' => t('State'),
'style' => 'width: 30%',
);
$subheader_operations = array(
'data' => t('Operations'),
'style' => 'width: 70%',
);
$subheader_style = array(
'style' => 'width: 100%; margin: 3px 20px 20px;',
);
$subtable = theme('table', array(
$subheader_state,
$subheader_operations,
), $subrows, $subheader_style);
$row[] = array(
array(
'data' => $subtable,
'colspan' => '2',
),
);
}
if ($row) {
$output = theme('table', array(
t('Workflow'),
t('Operations'),
), $row);
}
else {
$output = '<p>' . t('No workflows have been added. Would you like to <a href="@link">add a workflow</a>?', array(
'@link' => url('admin/build/workflow/add'),
)) . '</p>';
}
$output .= drupal_get_form('workflow_types_form');
return $output;
}
function workflow_is_system_state($state) {
static $states;
if (!isset($states)) {
$states = array(
t('(creation)') => TRUE,
);
}
return isset($states[$state]);
}
function workflow_state_delete_form($wid, $sid) {
$states = workflow_get_states($wid);
$form = array();
$form['wid'] = array(
'#type' => 'value',
'#value' => $wid,
);
$form['sid'] = array(
'#type' => 'value',
'#value' => $sid,
);
return confirm_form($form, t('Are you sure you want to delete %title (and all its transitions)?', array(
'%title' => $states[$sid],
)), $_GET['destination'] ? $_GET['destination'] : 'admin/build/workflow', t('This action cannot be undone.'), t('Delete'), t('Cancel'));
}
function workflow_state_delete_form_submit($form_id, $form_values) {
$states = workflow_get_states($form_values['wid']);
$state_name = $states[$form_values['sid']];
if ($form_values['confirm'] == 1) {
workflow_state_delete($form_values['sid']);
watchdog('workflow', t('Deleted workflow state %name', array(
'%name' => $state_name,
)));
drupal_set_message(t('The workflow state %name was deleted.', array(
'%name' => $state_name,
)));
}
return 'admin/build/workflow';
}
function workflow_types_form() {
$form = array();
$workflows = array(
'<' . t('None') . '>',
) + workflow_get_all();
if (count($workflows) == 0) {
return $form;
}
$type_map = array();
$result = db_query("SELECT wid, type FROM {workflow_type_map}");
while ($data = db_fetch_object($result)) {
$type_map[$data->type] = $data->wid;
}
$form['#theme'] = 'workflow_types_form';
$form['help'] = array(
'#type' => 'item',
'#value' => t('Each node type may have a separate workflow:'),
);
foreach (node_get_types('names') as $type => $name) {
$form[$type] = array(
'#type' => 'select',
'#title' => $name,
'#options' => $workflows,
'#default_value' => isset($type_map[$type]) ? $type_map[$type] : 0,
);
}
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save Workflow Mapping'),
);
return $form;
}
function theme_workflow_types_form($form) {
$header = array(
t('Node Type'),
t('Workflow'),
);
$row = array();
foreach (element_children($form) as $key) {
if ($form[$key]['#type'] == 'select') {
$name = $form[$key]['#title'];
unset($form[$key]['#title']);
$row[] = array(
$name,
drupal_render($form[$key]),
);
}
}
$output = drupal_render($form['help']);
$output .= theme('table', $header, $row);
return $output . drupal_render($form);
}
function workflow_types_form_submit($form_id, $form_values) {
workflow_types_save($form_values);
drupal_set_message(t('The workflow mapping was saved.'));
return 'admin/build/workflow';
}
function workflow_actions_remove_form($wid, $tid, $aid) {
$form = array();
$form['wid'] = array(
'#type' => 'value',
'#value' => $wid,
);
$form['tid'] = array(
'#type' => 'value',
'#value' => $tid,
);
$form['aid'] = array(
'#type' => 'value',
'#value' => $aid,
);
$actions = actions_get_all_actions();
$output = confirm_form($form, t('Are you sure you want to delete the action %title?', array(
'%title' => $actions[$aid]['description'],
)), $_GET['destination'] ? $_GET['destination'] : 'admin/build/workflow/actions/' . $wid, t('You can add it again later if you wish.'), t('Delete'), t('Cancel'));
return $output;
}
function workflow_actions_remove_confirm_submit($form_id, $form_values) {
if ($form_values['confirm'] == 1) {
$aid = $form_values['aid'];
$actions = actions_actions_map(actions_get_all_actions());
workflow_actions_remove($form_values['tid'], $aid);
watchdog('workflow', t('Action %action deleted', array(
'%action' => check_plain($actions[$aid]),
)));
drupal_set_message(t('Action %action deleted.', array(
'%action' => $actions[$aid],
)));
return 'admin/workflow/actions/' . $form_values['wid'];
}
}
function workflow_actions_page($wid) {
if (!module_exists('actions')) {
drupal_set_message(t('Before you can assign actions you must install and enable the actions module.'), 'error');
drupal_goto('admin/build/workflow');
}
$options = array(
t('None'),
);
foreach (actions_actions_map(actions_get_all_actions()) as $aid => $action) {
$options[$action['type']][$aid] = $action['description'];
}
$header = array(
array(
'data' => t('Transition'),
'colspan' => '3',
),
array(
'data' => t('Actions'),
),
);
$rows = array();
$states = workflow_get_states($wid);
foreach ($states as $sid => $state) {
$allowable_to = workflow_allowable_transitions($sid);
foreach ($allowable_to as $to_sid => $name) {
if ($to_sid == $sid) {
continue;
}
$tid = workflow_get_transition_id($sid, $to_sid);
$rows[] = array(
array(
'data' => $state,
),
array(
'data' => WORKFLOW_ARROW,
),
array(
'data' => $name,
),
array(
'data' => drupal_get_form('workflow_actions_form', $wid, $tid, $options),
),
);
}
}
if (count($rows) == 0) {
$output = t('You must first <a href="@link">set up transitions</a> before you can assign actions.', array(
'@link' => url('admin/build/workflow/edit/' . $wid),
));
}
else {
$output = theme('table', $header, $rows);
}
return $output;
}
function workflow_actions_form($wid, $tid, $available_options) {
$form['tid'] = array(
'#type' => 'hidden',
'#value' => $tid,
);
$form['#multistep'] = true;
$actions_this_tid = workflow_get_actions($tid);
foreach ($actions_this_tid as $aid => $act_name) {
$form['remove'][$aid] = array(
'#type' => 'item',
'#title' => $act_name,
'#value' => l(t('remove'), "admin/build/workflow/actions/remove/{$wid}/{$tid}/{$aid}"),
);
unset($available_options[md5($aid)]);
}
if (count($available_options) > 1) {
$form['action'] = array(
'#type' => 'select',
'#options' => $available_options,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Add'),
);
}
return $form;
}
function theme_workflow_actions_form($form) {
$row = array();
foreach (element_children($form['remove']) as $key) {
$name = $form['remove'][$key]['#title'];
unset($form['remove'][$key]['#title']);
$row[] = array(
$name,
drupal_render($form['remove'][$key]),
);
}
if (isset($form['action'])) {
$row[] = array(
drupal_render($form['action']),
drupal_render($form['submit']),
);
}
$output .= theme('table', array(), $row);
return $output . drupal_render($form);
}
function workflow_actions_form_submit($form, $form_values) {
$tid = $form_values['tid'];
$aid = actions_key_lookup($form_values['action']);
workflow_actions_save($tid, $aid);
$wid = arg(4);
return "admin/build/workflow/actions/{$wid}";
}
function workflow_actions_remove_form_submit($form_id, $form_values) {
if ($form_values['confirm'] == 1) {
$aid = $form_values['aid'];
$actions = actions_get_all_actions();
$action = $actions[$aid]['description'];
workflow_actions_remove($form_values['tid'], $aid);
watchdog('workflow', t('Action %action deleted', array(
'%action' => $action,
)));
drupal_set_message(t('Action %action deleted.', array(
'%action' => $action,
)));
}
return 'admin/build/workflow/actions/' . $form_values['wid'];
}
function workflow_get_name($wid) {
$name = db_result(db_query("SELECT name FROM {workflows} WHERE wid = %d", $wid));
return $name;
}
function workflow_get_workflow_for_type($type) {
static $cache;
if (!isset($cache[$type])) {
$wid = db_result(db_query("SELECT wid FROM {workflow_type_map} WHERE type = '%s'", $type));
$cache[$type] = $wid;
}
else {
$wid = $cache[$type];
}
return $wid > 0 ? $wid : FALSE;
}
function workflow_get_all() {
$workflows = array();
$result = db_query("SELECT wid, name FROM {workflows} ORDER BY name ASC");
while ($data = db_fetch_object($result)) {
$workflows[$data->wid] = $data->name;
}
return $workflows;
}
function workflow_create($name) {
$wid = db_next_id('{workflows}_wid');
db_query("INSERT INTO {workflows} (wid, name) VALUES (%d, '%s')", $wid, $name);
workflow_state_save(array(
'wid' => $wid,
'state' => t('(creation)'),
'sysid' => WORKFLOW_CREATION,
'weight' => WORKFLOW_CREATION_DEFAULT_WEIGHT,
));
return $wid;
}
function workflow_update($wid, $name, $tab_roles) {
db_query("UPDATE {workflows} SET name = '%s', tab_roles = '%s' WHERE wid = %d", $name, implode(',', $tab_roles), $wid);
}
function workflow_deletewf($wid) {
$wf = workflow_get_name($wid);
$result = db_query('SELECT sid FROM {workflow_states} WHERE wid = %d', $wid);
while ($data = db_fetch_object($result)) {
workflow_state_delete($data->sid);
db_query('DELETE FROM {workflow_node} WHERE sid = %d', $data->sid);
}
workflow_types_delete($wid);
db_query('DELETE FROM {workflows} WHERE wid = %d', $wid);
}
function workflow_get_states($wid) {
$states = array();
$result = db_query("SELECT sid, state FROM {workflow_states} WHERE wid = %d ORDER BY weight, state", intval($wid));
while ($data = db_fetch_object($result)) {
$states[$data->sid] = $data->state;
}
return $states;
}
function workflow_get_state($sid) {
$state = array();
$result = db_query('SELECT wid, state, weight, sysid FROM {workflow_states} WHERE sid = %d', intval($sid));
while ($data = db_fetch_object($result)) {
$state['wid'] = $data->wid;
$state['state'] = $data->state;
$state['weight'] = $data->weight;
$state['sysid'] = $data->sysid;
}
return $state;
}
function workflow_state_save($edit) {
$defaults = array(
'weight' => 0,
'sysid' => 0,
);
$edit = array_merge($defaults, $edit);
if (!isset($edit['sid'])) {
$edit['sid'] = db_next_id('{workflow_states}_sid');
db_query("INSERT INTO {workflow_states} (sid, wid, state, sysid, weight) VALUES (%d, %d, '%s', %d, %d)", $edit['sid'], $edit['wid'], $edit['state'], $edit['sysid'], $edit['weight']);
}
else {
db_query("UPDATE {workflow_states} SET wid = %d, state = '%s', sysid = %d, weight = %d WHERE sid = %d", $edit['wid'], $edit['state'], $edit['sysid'], $edit['weight'], $edit['sid']);
}
return $edit['sid'];
}
function workflow_state_create($wid, $name) {
return workflow_state_save(array(
'wid' => $wid,
'state' => $name,
));
}
function workflow_state_delete($sid) {
$preexisting = array();
$result = db_query("SELECT sid, target_sid FROM {workflow_transitions} WHERE sid = %d OR target_sid = %d", $sid, $sid);
while ($data = db_fetch_object($result)) {
$preexisting[$data->sid][$data->target_sid] = TRUE;
}
foreach ($preexisting as $from => $array) {
foreach (array_keys($array) as $target_id) {
$tid = workflow_get_transition_id($from, $target_id);
workflow_transition_delete($tid);
}
}
db_query("DELETE FROM {workflow_states} WHERE sid = %d", intval($sid));
}
function workflow_transition_delete($tid) {
$actions = workflow_get_actions($tid);
foreach (array_keys($actions) as $aid) {
workflow_actions_remove($tid, $aid);
}
db_query("DELETE FROM {workflow_transitions} WHERE tid = %d", $tid);
}
function workflow_allowable_transitions($sid, $dir = 'to', $roles = 'ALL') {
$transitions = array();
$field = $dir == 'to' ? 'target_sid' : 'sid';
$field_where = $dir != 'to' ? 'target_sid' : 'sid';
$result = db_query("(SELECT t.tid, t.%s as state_id, s.state as state_name, s.weight as state_weight FROM " . "{workflow_transitions} t INNER JOIN {workflow_states} s ON s.sid = " . "t.%s WHERE t.%s = %d) " . "UNION " . "(SELECT s.sid as tid, s.sid as state_id, s.state as state_name, s.weight as state_weight FROM " . "{workflow_states} s WHERE s.sid = %d) " . "ORDER BY state_weight", $field, $field, $field_where, $sid, $sid);
while ($t = db_fetch_object($result)) {
if ($roles == 'ALL' || $t->tid == $t->state_id || workflow_transition_allowed($t->tid, $roles)) {
$state_id = $t->state_id;
$transitions[$state_id] = $t->state_name;
}
}
return $transitions;
}
function workflow_types_save($form_values) {
$nodetypes = node_get_types();
db_query("DELETE FROM {workflow_type_map}");
foreach ($nodetypes as $type => $name) {
db_query("INSERT INTO {workflow_type_map} (type, wid) VALUES ('%s', %d)", $type, intval($form_values[$type]));
}
}
function workflow_types_delete($wid) {
db_query("DELETE FROM {workflow_type_map} WHERE wid = %d", $wid);
}
function workflow_get_actions($tid) {
$actions = array();
if (!function_exists('actions_do')) {
return $actions;
}
$result = db_query("SELECT a.aid, a.description FROM {actions} a INNER JOIN {workflow_actions} w ON a.aid = w.aid WHERE w.tid = %d", $tid);
while ($data = db_fetch_object($result)) {
$actions[$data->aid] = $data->description;
}
return $actions;
}
function workflow_get_transition_id($from, $to) {
return db_result(db_query("SELECT tid FROM {workflow_transitions} WHERE sid=%d AND target_sid=%d", $from, $to));
}
function workflow_actions_save($tid, $aid) {
actions_register($aid, 'workflow', $tid);
$data = db_fetch_object(db_query("SELECT tid FROM {workflow_actions} WHERE tid = %d AND aid = '%s'", $tid, $aid));
if ($data) {
return;
}
db_query("INSERT INTO {workflow_actions} (tid, aid, weight) VALUES (%d, '%s', %d)", $tid, $aid, 0);
}
function workflow_actions_remove($tid, $aid) {
actions_unregister($aid, 'workflow', $tid);
db_query("DELETE FROM {workflow_actions} WHERE tid = %d AND aid = '%s'", $tid, $aid);
}
function _workflow_node_to_state($node, $sid, $comment = NULL) {
global $user;
$node->workflow_stamp = time();
if (db_result(db_query("SELECT nid FROM {workflow_node} WHERE nid = %d", $node->nid))) {
db_query("UPDATE {workflow_node} SET sid = %d, uid = %d, stamp = %d WHERE nid = %d", $sid, $user->uid, $node->workflow_stamp, $node->nid);
}
else {
db_query("INSERT INTO {workflow_node} (nid, sid, uid, stamp) VALUES (%d, %d, %d, %d)", $node->nid, $sid, $user->uid, $node->workflow_stamp);
}
_workflow_write_history($node, $sid, $comment);
}
function _workflow_write_history($node, $sid, $comment) {
global $user;
db_query("INSERT INTO {workflow_node_history} (nid, old_sid, sid, uid, comment, stamp) VALUES (%d, %d, %d, %d, '%s', %d)", $node->nid, $node->_workflow, $sid, $user->uid, $comment, $node->workflow_stamp);
}
function workflow_get_roles() {
static $roles = NULL;
if (!$roles) {
$result = db_query('SELECT * FROM {role} ORDER BY name');
$roles = array(
'author' => 'author',
);
while ($data = db_fetch_object($result)) {
$roles[$data->rid] = $data->name;
}
}
return $roles;
}
function workflow_views_tables() {
$table = array(
'name' => 'workflow_node',
'provider' => 'workflow',
'join' => array(
'left' => array(
'table' => 'node',
'field' => 'nid',
),
'right' => array(
'field' => 'nid',
),
),
"filters" => array(
'sid' => array(
'name' => t('Workflow: state'),
'operator' => 'views_handler_operator_andor',
'list' => 'workflow_handler_filter_sid',
'list-type' => 'list',
'value-type' => 'array',
'help' => t('Include only nodes in the selected workflow states.'),
),
),
);
$tables[$table['name']] = $table;
$table = array(
'name' => 'workflow_states',
'provider' => 'workflow',
'join' => array(
'left' => array(
'table' => 'workflow_node',
'field' => 'sid',
),
'right' => array(
'field' => 'sid',
),
),
"sorts" => array(
'weight' => array(
'name' => t('Workflow: state'),
'field' => array(
'weight',
'state',
),
'help' => t('Order nodes by workflow state.'),
),
),
"fields" => array(
'state' => array(
'name' => t('Workflow: state'),
'sortable' => TRUE,
'help' => t('Display the workflow state of the node.'),
),
),
);
$tables[$table['name']] = $table;
$table = array(
'name' => 'workflow_node_history',
'provider' => 'workflow',
'join' => array(
'left' => array(
'table' => 'workflow_node',
'field' => 'nid',
),
'right' => array(
'field' => 'nid',
),
'extra' => array(
'stamp = workflow_node.stamp' => NULL,
),
),
"fields" => array(
'comment' => array(
'name' => t('Workflow: comment'),
'sortable' => false,
'help' => t('Display the most recent workflow comment of the node.'),
),
),
);
$tables[$table['name']] = $table;
return $tables;
}
function workflow_views_arguments() {
$arguments = array(
'workflow_state' => array(
'name' => t('Workflow: state'),
'handler' => 'workflow_handler_arg_sid',
'help' => t('The work flow argument allows users to filter a view by workflow state.'),
),
);
return $arguments;
}
function workflow_handler_filter_sid() {
$result = db_query("SELECT sid, state FROM {workflow_states} ORDER BY weight, state");
while ($data = db_fetch_object($result)) {
$states[$data->sid] = $data->state;
}
return $states;
}
function workflow_handler_arg_sid($op, &$query, $argtype, $arg = '') {
switch ($op) {
case 'summary':
$query
->add_table('workflow_states', TRUE);
$fieldinfo['field'] = "workflow_states.sid";
$query
->add_field('sid', 'workflow_states');
$query
->add_field('state', 'workflow_states');
$query
->add_where('workflow_node.sid IS NOT NULL');
return $fieldinfo;
break;
case 'filter':
$query
->add_table('workflow_states', TRUE);
if (is_numeric($arg)) {
$query
->add_where("workflow_states.sid = %d", $arg);
}
else {
$query
->add_where("workflow_states.state = '%s'", $arg);
}
break;
case 'link':
return l($query->state, "{$arg}/{$query->sid}");
case 'title':
$state = db_fetch_object(db_query("SELECT state FROM {workflow_states} WHERE sid=%d", $query));
return $state->state;
}
}
function workflow_cron() {
$clear_cache = FALSE;
$nodes = db_query('SELECT * FROM {workflow_scheduled_transition} s WHERE s.scheduled > 0 AND s.scheduled < %d', time());
while ($row = db_fetch_object($nodes)) {
$node = node_load($row->nid);
if ($node->_workflow == $row->old_sid) {
workflow_execute_transition($node, $row->sid, $row->comment);
watchdog('content', t('%type: scheduled transition of %title.', array(
'%type' => t($node->type),
'%title' => $node->title,
)), WATCHDOG_NOTICE, l(t('view'), 'node/' . $node->nid));
$clear_cache = TRUE;
}
}
if ($clear_cache) {
cache_clear_all();
}
}
function workflow_token_values($type, $object = NULL) {
$values = array();
switch ($type) {
case "node":
case 'workflow':
$node = (object) $object;
if ($wid = workflow_get_workflow_for_type($node->type)) {
$values['workflow-name'] = workflow_get_name($wid);
$states = workflow_get_states($wid);
}
else {
break;
}
$result = db_query_range("SELECT h.* FROM {workflow_node_history} h WHERE nid = %d ORDER BY stamp DESC", $node->nid, 0, 1);
if ($row = db_fetch_object($result)) {
$account = user_load(array(
'uid' => $row->uid,
));
$comment = $row->comment;
}
$values['workflow-current-state-name'] = $states[$row->sid];
$values['workflow-old-state-name'] = $states[$row->old_sid];
$values['workflow-current-state-date-iso'] = date('Ymdhis', $row->stamp);
$values['workflow-current-state-date-tstamp'] = $row->stamp;
$values['workflow-current-state-date-formatted'] = date('M d, Y h:i:s', $row->stamp);
$values['workflow-current-state-updating-user-name'] = $account->uid ? check_plain($account->name) : variable_get('anonymous', 'Anonymous');
$values['workflow-current-state-updating-user-uid'] = $account->uid;
$values['workflow-current-state-updating-user-mail'] = $account->uid ? check_plain($account->mail) : '';
$values['workflow-current-state-log-entry'] = filter_xss($row->comment, array(
'a',
'em',
'strong',
));
break;
}
return $values;
}
function workflow_token_list($type = 'all') {
if ($type == 'workflow' || $type == 'node' || $type == 'all') {
$tokens['workflow']['workflow-name'] = 'Name of workflow appied to this node';
$tokens['workflow']['workflow-current-state-name'] = 'Current state of content';
$tokens['workflow']['workflow-old-state-name'] = 'Old state of content';
$tokens['workflow']['workflow-current-state-date-iso'] = 'Date of last state change (ISO)';
$tokens['workflow']['workflow-current-state-date-tstamp'] = 'Date of last state change (timestamp)';
$tokens['workflow']['workflow-current-state-date-formatted'] = 'Date of last state change (formated - M d, Y h:i:s)';
$tokens['workflow']['workflow-current-state-updating-user-name'] = 'Username of last state changer';
$tokens['workflow']['workflow-current-state-updating-user-uid'] = 'uid of last state changer';
$tokens['workflow']['workflow-current-state-updating-user-mail'] = 'email of last state changer';
$tokens['workflow']['workflow-current-state-log-entry'] = 'Last workflow comment log';
$tokens['node'] = $tokens['workflow'];
}
return $tokens;
}