I've been using workflow extensively in a project, and I have found that prograramtically changing states using sids becomes quickly unreadable and unmaintainable, not to mention error-prone.

I have been using the following helper functions to enhance code readability.

/**
 * Return the sid of a state by node type
 *
 * Each node type has a workflow (wid) associated with it, and each wid has
 * states associated with it. Do the matching and return the relevant sid.
 * NOTE: this function is case sensitive. It might be sensible to relax this
 *       requirement if it is a problem.
 *
 * @param $type
 *   The node type
 * @param $state
 *   The state textual description
 * @return
 *   The state ID - sid
 */
function workflow_get_sid($type, $state) {
  static $states;

  if (!isset($states)) {
    $states[] = array();
    $result = db_query("SELECT wtm.type type, ws.state state, ws.sid sid FROM {workflow_states} ws NATURAL JOIN {workflow_type_map} wtm");
    while ($row = db_fetch_object($result)) {
      $states[$row->type][$row->state] = $row->sid;
    }
  }

  return $states[$type][$state];
}

/**
 * like workflow_get_sid() but for arrays
 *
 * @param $t_states
 *   an array of the form:
 *   array(
 *     'node type1' => array('state1', 'state2', ...),
 *     'node type2' => array('state1', 'state2', ...)
 *   );
 * @return
 *   a flat array of sids
 */
function workflow_get_sids($t_states) {
  $sids = array();
  foreach ($t_states as $type => $states) {
    foreach ($states as $state) {
      $sids[] = workflow_get_sid($type, $state);
    }
  }
  return $sids;
}

Example usages are:

  • check state:
      $state = module_invoke('workflow', 'node_current_state', $node);
      if ($state == workflow_get_sid('product', 'Pending')) {
        // do something
      }
    
  • execute a transition:
      module_invoke('workflow', 'execute_transition', $node, workflow_get_sid('product', 'Shipped'), 'Product was shipped');
    
  • look for nodes with specified states:
      $states = array(
        'product' => array('In Progress', 'Pending'),
        'blog' => array('Active', 'Rejected'),
        'article' => array('Pending')
      );
      $sids = workflow_get_sids($states);
      $result = db_query('SELECT nid FROM {workflow_node} WHERE sid IN ('. implode(',', $sids)  .')');
      while ($obj = db_fetch_object($result)) {
        // do something
      }
    

After a little while, this became so convenient, that I didn't care about the extra typing.

If you like this idea, let me know, I'll make a proper patch out of it.

Note: the above code was written for the D5.x version. I have not adapted this to D6 yet - if there are any changes, I'll incorporate them in the patch

Comments

yhager’s picture

Status: Active » Needs review

Marking as 'needs review', hopefully to get more attention to this

deekayen’s picture

Status: Needs review » Patch (to be ported)

Even though this is marked for 6.x, the code is 5.x.

I'm not a fan of having both functions. Whatever is doing the calling can do the looping rather than the workflow function. Moreover, what happens when you rename the workflow state? You break all the code that refers to it? Don't get me wrong, I like the idea of coming up with a more readable solution other than commenting what the sid is in the code.

As-is this seems like a better candidate for something like a separate module (workflow_devel, workflow_custom, workflow_advanced?) module for things where the user can be sure to be aware of the consequences of its use. Perhaps a more proper solution would be an intermediary identifier like CCK does with fields (workflow title vs workflow machine readable name that doesn't change).

yhager’s picture

Thank you for the review.

All your points are valid. The code I used this with was a complex state machine, and with numerical state ids was impossible to debug and read. I agree that having a CCK style "machine name" is better for developers, but I did not want to modify anything drastic in the module itself.

Anyhow, this helped me a lot in a couple of project, so I wanted to share with everyone.

Let me know how you want me to assist.

deekayen’s picture

Perhaps throw the first function into the start of a workflow_advanced module for 6.x and send that back?

Bastlynn’s picture

Status: Patch (to be ported) » Closed (won't fix)

Since this request is over 2 years old, I'm going to assume a solution was found or you've moved on. If not, please get updated to the latest versions of all modules and roll a patch against Drupal 7 and I'll be glad to take a look at it.

johnv’s picture

Status: Closed (won't fix) » Closed (duplicate)
Related issues: +#2196247: [EXPORTING] Add machine names to workflow states

ITMTmachine names have been introduced for Workflows and Transitions. An open issue still exists for States:
#2196247: [EXPORTING] Add machine names to workflow states

johnv’s picture

Title: Allow state name to state id conversion » [EXPORTING] Allow state name to state id conversion