You are here

workflow_extensions.module in Workflow Extensions 6

Same filename and directory in other branches
  1. 7 workflow_extensions.module

UI-related improvements to the Workflow module and tokens for Rules.

1a) Replaces the traditional workflow radio-buttons by either a drop-down or single-action buttons featuring context-sensitive labels (using replacement tokens) for a more intuitive user experience. See also the discussion on intelligent buttons at drupal.org/node/282122. All three UI styles (radio, dropw-down or single-action) are available as a block. 1b) Suppresses the workflow schedule transition form if not selected by the user. 2) The module also defines tokens which when used with Rules allow you to more easily invoke actions when something did NOT happen for some time.

Re 1a) Let's say we have a basic workflow with states "draft", "review" and "live". Traditionally authors and moderators must select the next state by pressing the correct radio-button and clicking submit. Experience from the field suggests that not everybody finds this intuitive. Rather than having to think in terms of state transitions, users prefer to press a button with a an explanatory label that clearly expresses what is going to happen. Using this module authors will find on the edit form a couple of clearly labeled buttons: "Save as draft, don't submit" and "Submit for publication". In old workflow-speak the latter action is represented by radio buttons plus a submit button and read less intuitively as: transition workflow state from "draft" to "review". Similarly, with this module a moderator will see on their edit form buttons like "Reject and return to author John" (i.e. "review -> draft") and "Publish this" ("review -> live"). The alternative buttons appear on: a) the node edit form (node/%/edit) b) the comment edit form, if enabled c) the workflow tab, if enabled (node/%/workflow)

Re 2) This module defines a replacement token [node:workflow-state-age], which when used in a scheduled rule set, make it easier to invoke actions when a workflow state was NOT changed after a specified elapsed time. See drupal.org/project/workflow_extensions for full instructions on how to do this using Rules.

File

workflow_extensions.module
View source
<?php

/**
 *  @file
 *  UI-related improvements to the Workflow module and tokens for Rules.
 *
 *  1a) Replaces the traditional workflow radio-buttons by either a drop-down or
 *  single-action buttons featuring context-sensitive labels (using replacement
 *  tokens) for a more intuitive user experience.
 *  See also the discussion on intelligent buttons at drupal.org/node/282122.
 *  All three UI styles (radio, dropw-down or single-action) are available as a
 *  block.
 *  1b) Suppresses the workflow schedule transition form if not selected by the
 *  user.
 *  2) The module also defines tokens which when used with Rules allow you to
 *  more easily invoke actions when something did NOT happen for some time.
 *
 *  Re 1a)
 *  Let's say we have a basic workflow with states "draft", "review" and "live".
 *  Traditionally authors and moderators must select the next state by pressing
 *  the correct radio-button and clicking submit. Experience from the field
 *  suggests that not everybody finds this intuitive. Rather than having to
 *  think in terms of state transitions, users prefer to press a button with a
 *  an explanatory label that clearly expresses what is going to happen.
 *  Using this module authors will find on the edit form a couple of clearly
 *  labeled buttons: "Save as draft, don't submit" and "Submit for publication".
 *  In old workflow-speak the latter action is represented by radio buttons plus
 *  a submit button and read less intuitively as: transition workflow state
 *  from "draft" to "review".
 *  Similarly, with this module a moderator will see on their edit form buttons
 *  like "Reject and return to author John" (i.e. "review -> draft") and
 *  "Publish this" ("review -> live").
 *  The alternative buttons appear on:
 *  a) the node edit form (node/%/edit)
 *  b) the comment edit form, if enabled
 *  c) the workflow tab, if enabled (node/%/workflow)
 *
 *  Re 2)
 *  This module defines a replacement token [node:workflow-state-age], which
 *  when used in a scheduled rule set, make it easier to invoke actions when
 *  a workflow state was NOT changed after a specified elapsed time.
 *  See drupal.org/project/workflow_extensions for full instructions on
 *  how to do this using Rules.
 */
define('WORKFLOW_EXTENSIONS_UI_RADIOS', 1);

// the original Workflow style
define('WORKFLOW_EXTENSIONS_UI_BUTTONS', 2);

// single-action buttons
define('WORKFLOW_EXTENSIONS_UI_DROPDOWN', 3);

// dropdown selector + update

/**
 * Implementation of hook_perm().
 */
function workflow_extensions_perm() {
  return array(
    'change workflow state via node edit form',
    'edit workflow log',
    'view workflow state change block even when state cannot be changed',
  );
}

/**
 * Implementation of hook_menu().
 */
function workflow_extensions_menu() {
  $items = array();
  $items['workflow-log/%workflow_state_transition_record'] = array(
    // maps to function workflow_state_transition_record_load()
    'title' => 'Edit workflow log comment',
    'description' => 'Edit workflow state transition comment.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'workflow_extensions_workflow_comment_edit_form',
      1,
    ),
    'access arguments' => array(
      'edit workflow log',
    ),
  );
  $items['admin/settings/workflow_extensions'] = array(
    'title' => 'Workflow extensions',
    'description' => 'Configure workflow form style (buttons and labels).',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'workflow_extensions_admin_configure',
    ),
    'access arguments' => array(
      'administer site configuration',
    ),
    'file' => 'workflow_extensions.admin.inc',
  );
  return $items;
}

/**
 * Load function belonging to the above menu option 'workflow-log/%workflow-state-transition-record'.
 * Maps to this function just like 'node/%node' maps to node_load().
 *
 * @param $hid
 *   The ID of the workflow state transition record to load.
 * @return
 *   object representing one row from the {workflow_node_history} table
 */
function workflow_state_transition_record_load($hid) {
  $workflow_state_transition_record = db_fetch_object(db_query('SELECT * FROM {workflow_node_history} WHERE hid = %d', $hid));
  return $workflow_state_transition_record;
}

/**
 * Display a text area populated with the selected workflow log comment and
 * allow the user to modify and save it.
 */
function workflow_extensions_workflow_comment_edit_form($form_state, $workflow_state_transition_record) {
  $form = array();
  $form['hid'] = array(
    '#type' => 'value',
    '#value' => $workflow_state_transition_record->hid,
  );
  $form['nid'] = array(
    '#type' => 'value',
    '#value' => $workflow_state_transition_record->nid,
  );
  $form['workflow']['workflow_comment'] = array(
    '#type' => 'textarea',
    '#title' => t('Comment'),
    '#description' => t('Modify this workflow state transition comment and press submit.'),
    '#default_value' => $workflow_state_transition_record->comment,
    '#rows' => 2,
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
  );
  return $form;
}

/**
 * Submit handler for the workflow transition comment edit form.
 *
 * @see workflow_extensions_workflow_comment_edit_form()
 */
function workflow_extensions_workflow_comment_edit_form_submit($form, &$form_state) {
  $hid = $form_state['values']['hid'];
  $comment = $form_state['values']['workflow_comment'];
  db_query("UPDATE {workflow_node_history} SET comment = '%s' WHERE hid = %d", $comment, $hid);
  $nid = $form_state['values']['nid'];

  // Whatever is set here, is overriden by the "?destination=..." parameter, if present
  $form_state['redirect'] = module_exists('views') && views_get_view('workflow_history') ? "workflow-history/{$nid}" : (workflow_node_tab_access(node_load($nid)) ? "node/{$nid}/workflow" : "node/{$nid}");
}

/**
 * Implementation of hook_form_alter().
 *
 * 1) Remove the Workflow radio buttons and replace each state transition by a
 * submit button with a configurable, explanatory label.
 * To allow saving of edits to the node without a state transition, display
 * an additional button "Save, don't submit" (or similar).
 * 2) If on the create/edit form suppress the workflow fieldset if the user
 * does not have the relevant permission
 * 3) If the schedule state transition form is enabled, suppress it until the
 * user clicks the radio button to reveal it.
 * 4) Add an (extra) form validator
 */
function workflow_extensions_form_alter(&$form, &$form_state, $form_id) {

  // If there's no Workflow fieldset, then we have nothing further to do.
  if (!isset($form['#wf'])) {

    // was $form['workflow'] but need to exclude content type edit form
    return;
  }

  // 4) Add form validator
  if (empty($form['#validate'])) {
    $form['#validate'] = array();
  }
  elseif (!is_array($form['#validate'])) {
    $form['#validate'] = array(
      $form['#validate'],
    );
  }
  $form['#validate'][] = 'workflow_extensions_workflow_form_validate';

  // 2) Suppress Workflow fieldset on the create/edit form if not permitted.
  if (isset($form['#id']) && $form['#id'] == 'node-form' && !user_access('change workflow state via node edit form')) {
    unset($form['workflow']);
    return;
  }

  // The next if-statement implements point 3) above
  if (variable_get('workflow_extensions_display_schedule_toggle', TRUE)) {
    $path = drupal_get_path('module', 'workflow_extensions');
    drupal_add_js($path . '/workflow_schedule.js', 'module');
  }

  // The rest of this function implements point 1)
  $workflow_name = workflow_extensions_extract_workflow_name($form);
  $workflow_radios = $form['workflow'][$workflow_name];
  if (is_array($workflow_radios) && isset($workflow_radios['#options'])) {

    // Use the form to work out the potential state transitions for this user.
    $states = $workflow_radios['#options'];

    // $states will be empty when creating node
    if (!empty($states)) {
      $title = variable_get('workflow_extensions_change_state_form_title', '');
      if (!empty($title)) {
        if (trim($title) == '<none>') {
          unset($form['workflow'][$workflow_name]['#title']);
        }
        else {
          $form['workflow'][$workflow_name]['#title'] = workflow_extensions_replace_tokens_raw($title);
        }
      }
      if (empty($form['#submit'])) {

        // This seems to happen as a side-effect of using hook_forms(), i.e
        // the case where workflow_extensions_change_state_form() is called,
        // for instance when the state change form appears in a block or View.
        // In the latter case, we also create ourselves an option to redirect
        // to page different from the default (which is node/%), as set in
        // workflow_tab_form_submit().
        $form['#submit'] = array(
          'workflow_tab_form_submit',
          'workflow_extensions_form_redirect',
        );
      }
      switch (variable_get('workflow_extensions_ui_style', WORKFLOW_EXTENSIONS_UI_BUTTONS)) {
        case WORKFLOW_EXTENSIONS_UI_BUTTONS:
          if (count($states) > 1) {
            _workflow_extensions_replace_with_buttons($form, $workflow_name);
          }
          break;
        case WORKFLOW_EXTENSIONS_UI_DROPDOWN:
          _workflow_extensions_replace_with_dropdown($form, $workflow_name);

        // no break;
        default:

          // radios
          if (isset($form['submit'])) {
            $submit_label = variable_get('workflow_extensions_change_state_button_label', '');
            if (!empty($submit_label)) {
              $form['submit']['#value'] = workflow_extensions_replace_tokens_raw($submit_label);
            }
          }
          break;
      }
    }
  }
}

/**
 * Implementation of hook_forms();
 *
 * Called as a result of the fact that there are no form handlers for the
 * unique form_id's generated in workflow_extensions_change_state_form().
 * Here we map these form_id's back to the same 'workflow_tab_form'. This
 * allows us to have multiple copies of the same form on the same page.
 * Note: first of the args is typically the node object.
 */
function workflow_extensions_forms($form_id, $args) {
  if (strpos($form_id, 'workflow_tab_form_nid') === 0) {
    $form = array(
      $form_id => array(
        'callback' => 'workflow_tab_form',
        'callback arguments' => array(),
      ),
    );
    return $form;
  }
}

/**
 * Validate the workflow form, in particular the state transition comment and
 * the scheduled state transition time (the date is a drop-down so requires no
 * validation).
 */
function workflow_extensions_workflow_form_validate($form, &$form_state) {
  $nid = substr($form['#id'], strrpos($form['#id'], '-') + 1);
  $title = isset($form_state['values']['title']) ? $form_state['values']['title'] : $form_state['values']['node']->title;
  if (!empty($form_state['values']['workflow_scheduled_hour'])) {
    if (!strtotime($form_state['values']['workflow_scheduled_hour'])) {
      form_set_error(is_numeric($nid) ? "workflow_scheduled_hour_{$nid}" : 'workflow_scheduled_hour', t('%title: scheduled time is not in the correct format.', array(
        '%title' => $title,
      )));
    }
  }
  if (!variable_get('workflow_extensions_allow_blank_comments', TRUE)) {
    if (!isset($form_state['values']['nid']) && !isset($form_state['values']['node'])) {

      // Bypass node creation
      return;
    }
    $comment = $form_state['values']['workflow_comment'];
    if (!trim($comment)) {
      form_set_error(is_numeric($nid) ? "workflow_comment_{$nid}" : 'workflow_comment', t('%title: please enter a non-blank comment for the workflow log.', array(
        '%title' => $title,
      )));
    }
  }
}

/**
 * Handler for the single-action submit buttons on the edit form.
 * Does NOT get called when radio buttons or drop-down are used.
 */
function workflow_extensions_form_submit($form, &$form_state) {

  // In the original form_submit handler that we pass control to next, the
  // selected workflow state is taken from form_state['values']['workflow']. So
  // that's the entry we need to set here in accordance with the clicked button.
  // See node_form_submit() -> node_submit() for the edit form.
  // See workflow_tab_form_submit() for the Workflow tab.
  $form_state['values']['workflow'] = $form_state['clicked_button']['#to_state'];

  // ... now proceed to next handler, e.g. node_form_submit for a normal save
}

/**
 * If the workflow state was not transitioned via either the node edit form or
 * the Workflow tab, then redirect to a configurable page, e.g. some View.
 */
function workflow_extensions_form_redirect($form, &$form_state) {
  if (arg(0) != 'node') {
    $path = variable_get('workflow_extensions_redirect_page', '');

    // @todo: make this a UI config option
    $form_state['redirect'] = empty($path) ? $_GET['q'] : $path;

    // @todo: save query-string too (Views pager)
  }
}
function _workflow_extensions_replace_with_buttons(&$form, $workflow_name) {
  $current_sid = $form['workflow'][$workflow_name]['#default_value'];
  if (function_exists('workflow_get_state_name')) {
    $current_state_name = workflow_get_state_name($current_sid);
  }
  else {
    $current_state = workflow_get_state($current_sid);
    $current_state_name = $current_state['state'];
  }

  // We need a node-context for token replacement. When on the Workflow tab
  // form, the node object will already have been loaded on the form.
  // When creating content (node/add/<type>) we only have limited data. In
  // the remaining cases we load the node from the cache based on the nid
  // found on the form.
  $form_id = $form['form_id']['#value'];
  if (strpos($form_id, 'workflow_tab_form') === 0) {
    $node = $form['node']['#value'];
  }
  elseif (is_numeric($nid = $form['nid']['#value'])) {
    $node = node_load($nid);
  }
  else {

    // Creating new content, nid not yet known
    $node = $form['#node'];
  }
  $states = $form['workflow'][$workflow_name]['#options'];
  $submit_handlers = _workflow_extensions_assign_handlers($form);
  foreach ($states as $sid => $to_state_name) {
    if ($sid != $current_sid) {

      // Create button for transition from current_sid to destination state.
      $button = array();
      $button['#value'] = workflow_extensions_get_transition_label($form['#wf']->wid, $current_state_name, workflow_get_state_name($sid), $node);
      $button['#type'] = 'submit';
      $button['#to_state'] = $sid;
      if (isset($form['buttons']['submit']['#weight'])) {

        // node form
        $button['#weight'] = $form['buttons']['submit']['#weight'] + 1;
      }
      elseif (isset($form['submit']['#weight'])) {

        // comment form
        $button['#weight'] = $form['submit']['#weight'];
      }
      $button['#submit'] = $submit_handlers;
      $form['buttons']["submit_to_{$to_state_name}"] = $button;
    }
  }

  // Get rid of workflow radio buttons that live inside the fieldset
  unset($form['workflow'][$workflow_name]);

  // If after this the fieldset is empty, remove it altogher
  if (!isset($form['workflow']['workflow_scheduled']) && (!isset($form['workflow']['workflow_comment']) || $form['workflow']['workflow_comment']['#type'] == 'hidden')) {
    unset($form['workflow']);
  }

  // With the existing Save button now impotent to submit a workflow
  // transition, we can re-purpose it for saving all other edits to the
  // node without changing the workflow state.
  // This does not make sense for the Workflow tab form though, as there is
  // nothing to save but a state change. In this case we simply remove the
  // Save button.
  if ($form_id == 'comment_form') {
    $form['buttons']['submit'] = $form['submit'];
    $form['buttons']['submit']['#submit'] = $form['#submit'];
    $form['buttons']['submit']['#weight']--;

    // left-most
  }
  if (strpos($form_id, 'workflow_tab_form') !== 0 && ($label = variable_get('workflow_extensions_default_save_button_label', ''))) {
    $form['buttons']['submit']['#value'] = workflow_extensions_replace_state_name_tokens($label, $current_state_name);
  }
  unset($form['submit']);

  // the button

  //unset($form['#submit']); // don't remove handler, [#1097328]
}
function _workflow_extensions_replace_with_dropdown(&$form, $workflow_name) {
  $form['workflow'][$workflow_name]['#type'] = 'select';
  $form['workflow'][$workflow_name]['#name'] = 'workflow';
}

/**
 * Implementation of hook_block().
 */
function workflow_extensions_block($op = 'list', $delta = 0) {
  if (!module_exists('workflow')) {
    return;
  }
  if ($op == 'list') {
    $block[0]['info'] = t('Workflow state change form');
    return $block;
  }
  elseif ($op == 'view' && arg(0) == 'node') {
    $node = node_load(arg(1));
    $block['content'] = workflow_extensions_change_state_form($node);
    $block['subject'] = '';
    return $block;
  }
}

/**
 * Use this function in a code-snippet to output a workflow state change form
 * on any page. May be used multiple times on the same page (for different
 * nodes), e.g. using the 'Views PHP' module, as a unique form_id is generated
 * for each occurrence of the form.
 *
 * @param $node
 */
function workflow_extensions_change_state_form($node) {
  if (!$node || !($wid = workflow_get_workflow_for_type($node->type))) {
    return '';
  }
  $choices = workflow_field_choices($node);
  if (count($choices) == 1) {
    if (user_access('view workflow state change block even when state cannot be changed')) {

      // Generate single-option form without Submit button
      return drupal_get_form('workflow_extensions_single_state_form', workflow_get_name($wid), $choices);
    }
    return '';

    // not allowed to view state
  }
  $result = db_query("SELECT sid, state FROM {workflow_states} WHERE status = 1 ORDER BY sid");
  while ($row = db_fetch_object($result)) {
    $workflow_states[$row->sid] = check_plain(t($row->state));
  }
  $sid_current = workflow_node_current_state($node);
  require_once drupal_get_path('module', 'workflow') . '/workflow.pages.inc';
  $output = drupal_get_form('workflow_tab_form_nid_' . $node->nid, $node, $wid, $workflow_states, $sid_current);
  return $output;
}

/**
 * Form used to display the current state, without a submit button to change it.
 * @param $form_state
 * @param $workflow_name
 * @param $current_state, an array of one element, indexed by its sid
 */
function workflow_extensions_single_state_form($form_state, $workflow_name, $current_state) {
  $sids = array_keys($current_state);
  $form['workflow']['#title'] = $workflow_name;
  $form['workflow'][$workflow_name] = array(
    '#type' => 'radios',
    // may be overridden by workflow_extensions_form_alter()
    '#options' => $current_state,
    '#default_value' => $sids[0],
  );
  return $form;
}
function workflow_extensions_extract_workflow_name($form) {

  // Current and allowed next states for this user and node live in
  // $form['workflow'][$workflow_name]['#options].
  // At the time of writing, the workflow.module (6.x.1-4) contained a bug that
  // resulted in the $workflow_name being passed as blank. Luckily we can work
  // around this and also be compatible with later versions that don't have the
  // bug.
  if (isset($form['workflow'][''])) {
    return '';
  }
  return isset($form['#wf']->name) ? $form['#wf']->name : $form['workflow']['#title'];
}
function _workflow_extensions_assign_handlers($form) {
  $original_handlers = $form['#submit'];

  // e.g. 'workflow_tab_form_submit' or 'menu_node_form_submit'
  return $form['#id'] == 'node-form' ? array(
    'workflow_extensions_form_submit',
    'node_form_submit',
  ) : array_merge(array(
    'workflow_extensions_form_submit',
  ), $original_handlers);

  // [#1346078] ?

  //$original_handlers = array_merge($original_handlers, $form['buttons']['submit']['#submit']);

  //  return array_merge(array('workflow_extensions_form_submit'), $original_handlers);
}

/**
 * Implementation of hook_token_list().
 *
 * Note: [workflow-new-state-name] is in fact a pseudo-token, but the user
 * doesn't have to know that!
 */
function workflow_extensions_token_list($context = 'all') {
  if (module_exists('workflow') && in_array($context, array(
    'workflow',
    'node',
    'all',
  ))) {
    $tokens['workflow']['workflow-new-state-name'] = 'New state of content';
    $tokens['workflow']['workflow-state-age'] = 'Seconds elapsed since last state change';
  }
  if ($context == 'node' || $context == 'all') {
    $tokens['node']['mod-since-seconds'] = 'Seconds elapsed since last modification';
  }
  return $tokens;
}

/**
 * Implementation of hook_token_values().
 *
 * Returning [workflow-state-age] for both node and workflow contexts as there
 * seems to be an issue with using Workflow state as the data type argument in
 * a Rule set. Such a Rule set won't show as available in a scheduled triggered
 * rule. The Content (ie node) data type must be used instead.
 */
function workflow_extensions_token_values($context, $object = NULL) {
  $values = array();
  switch ($context) {
    case 'node':
    case 'workflow':
      if (isset($object)) {
        $node = (object) $object;
        if (module_exists('workflow')) {
          $stamp = db_result(db_query_range("SELECT stamp FROM {workflow_node_history} WHERE nid = %d ORDER BY stamp DESC", $node->nid, 0, 1));
          $values['workflow-state-age'] = $stamp ? time() - $stamp : 0;
        }
        $values['mod-since-seconds'] = $node->changed ? time() - $node->changed : 0;
      }
      break;
  }
  return $values;
}

/**
 * Return the name for the workflow transition identified by the supplied
 * from-state and to-state names.
 *
 * @param int $wid, workflow identifier, maybe NULL (but then the combination
 *  of $from_state_name and $to_state_name must be unique across all workflows)
 * @param string $from_state_name
 * @param string $to_state_name
 * @param object $node, context for token replacement; if omitted an attempt
 *   will be made to load the node based on the nid in the URL. This will fail
 *   when creating new content, in which case a partial node must be supplied.
 */
function workflow_extensions_get_transition_label($wid, $from_state_name, $to_state_name, $node = NULL) {
  if (module_exists('workflow_named_transitions')) {
    $transitions = workflow_named_transitions_get_transitions($wid);
    foreach ($transitions as $transition) {
      if ($transition['from_state'] == $from_state_name && $transition['to_state'] == $to_state_name) {
        return workflow_extensions_replace_state_name_tokens($transition['label'], $to_state_name, $node);
      }
    }

    // No label defined, fall through as if module 'workflow_named_transitions'
    // wasn't installed
  }
  $tokenized_label = variable_get('workflow_extensions_change_state_button_label', '');

  // Don't think we need to check_markup(). Only users with 'administer site
  // configuration' permission can set the label pattern, so it's up to them to
  // use or not use HTML and/or javascript.
  return workflow_extensions_replace_state_name_tokens($tokenized_label, $to_state_name, $node);
}
function workflow_extensions_replace_state_name_tokens($tokenized_label, $to_state_name = NULL, $node = NULL) {
  if (empty($tokenized_label)) {
    return t('Move to "@state_name"', array(
      '@state_name' => $to_state_name,
    ));
  }
  $label = workflow_extensions_replace_tokens_raw($tokenized_label, $node);
  if (!empty($to_state_name)) {

    // Once the real tokens have been replaced, replace the pseudo-token
    // [workflow-new-state-name]
    $label = str_replace('[workflow-new-state-name]', $to_state_name, $label);
  }
  return $label;
}
function workflow_extensions_replace_tokens_raw($tokenized_label, $node = NULL) {
  if (module_exists('token')) {
    global $user;
    $objects['global'] = NULL;
    $objects['user'] = $user;
    if ($node == NULL && arg(0) == 'node' && is_numeric(arg(1))) {
      $node = node_load(arg(1));

      // node/%
    }
    $objects['node'] = $objects['workflow'] = $node;
    return token_replace_multiple($tokenized_label, $objects);
  }
  return $tokenized_label;
}

/**
 * Implementation of hook_views_api().
 */
function workflow_extensions_views_api() {
  return array(
    'api' => views_api_version(),
    'path' => drupal_get_path('module', 'workflow_extensions') . '/views',
  );
}

Functions

Namesort descending Description
workflow_extensions_block Implementation of hook_block().
workflow_extensions_change_state_form Use this function in a code-snippet to output a workflow state change form on any page. May be used multiple times on the same page (for different nodes), e.g. using the 'Views PHP' module, as a unique form_id is generated for each…
workflow_extensions_extract_workflow_name
workflow_extensions_forms Implementation of hook_forms();
workflow_extensions_form_alter Implementation of hook_form_alter().
workflow_extensions_form_redirect If the workflow state was not transitioned via either the node edit form or the Workflow tab, then redirect to a configurable page, e.g. some View.
workflow_extensions_form_submit Handler for the single-action submit buttons on the edit form. Does NOT get called when radio buttons or drop-down are used.
workflow_extensions_get_transition_label Return the name for the workflow transition identified by the supplied from-state and to-state names.
workflow_extensions_menu Implementation of hook_menu().
workflow_extensions_perm Implementation of hook_perm().
workflow_extensions_replace_state_name_tokens
workflow_extensions_replace_tokens_raw
workflow_extensions_single_state_form Form used to display the current state, without a submit button to change it.
workflow_extensions_token_list Implementation of hook_token_list().
workflow_extensions_token_values Implementation of hook_token_values().
workflow_extensions_views_api Implementation of hook_views_api().
workflow_extensions_workflow_comment_edit_form Display a text area populated with the selected workflow log comment and allow the user to modify and save it.
workflow_extensions_workflow_comment_edit_form_submit Submit handler for the workflow transition comment edit form.
workflow_extensions_workflow_form_validate Validate the workflow form, in particular the state transition comment and the scheduled state transition time (the date is a drop-down so requires no validation).
workflow_state_transition_record_load Load function belonging to the above menu option 'workflow-log/%workflow-state-transition-record'. Maps to this function just like 'node/%node' maps to node_load().
_workflow_extensions_assign_handlers
_workflow_extensions_replace_with_buttons
_workflow_extensions_replace_with_dropdown

Constants

Namesort descending Description
WORKFLOW_EXTENSIONS_UI_BUTTONS
WORKFLOW_EXTENSIONS_UI_DROPDOWN
WORKFLOW_EXTENSIONS_UI_RADIOS @file UI-related improvements to the Workflow module and tokens for Rules.