Tuesday, October 4, 2011

Add Permissions to Workbench Moderation States in Drupal

I've been attempting to implement a workflow solution for my Drupal 7 project, and at this time the best option to me is the Workbench module:

http://drupal.org/project/workbench

Props to those guys for what I see as a good implementation.  The breakout of functionality into separate modules is quite nice.  It helps keep down on the bloat you might experience when all you might need is a few simple options.

Now I needed to implement a pretty simple workflow with a few states and various roles for the users who will be interacting with the content in those states.  My needs were almost met entirely with the Workbench and Workbench Moderation modules.  My Achilles heel lied with a basic requirement of limiting the permissions of some roles depending on what state the node was in.

The answer wasn't too hard, but I thought it would be useful for someone out there in what would be a common scenario.  What I like about this approach is that it makes the permission settings easy to export via the Features module and takes advantage of the existing permissions interface to get setup.  The biggest drawback is that it potentially adds to permissions sprawl.

All of my code is included in my own custom module so you don't need to modify any of the code within the Workbench modules.  The first step is to implement hook_permissions to add a permission setting for each state in your workflow:


function mymodule_permission() {
  $permissions = array();
  
  // Per state permissions.  Used by workbench_moderation_node_access().
  $states = workbench_moderation_states();
  foreach($states as $state) {
    $permissions['edit all content in ' . $state->name] = array(
        'title' => t('Edit all content in @state', array('@state' => $state->label)),
    );
    if (variable_get('workbench_moderation_per_node_type', FALSE)) {
      foreach ($node_types as $node_type) {
        $permissions["edit $node_type in " . $state->name] = array(
          'title' => t('Edit @node_type in @state', array('@node_type' => node_type_get_name($node_type), '@state' => $state->label)),
        );
      }
    }
  }
  return $permissions;
}

Note the extra code that supports the functionality that opens up different worfklow settings in Workbench for your content types.  Your implementation might not need this, but I wanted to be thorough.

Next we need to implement hook_node_access to potentially deny access to update operations on a node based on these access settings, again taking into account the per content type variable:


function mymodule_permission() {
  if(isset($node->workbench_moderation) && $op == 'update') {
    if(variable_get('workbench_moderation_per_node_type', FALSE) &&
          !user_access('edit ' . $node->type . ' in '.$node->workbench_moderation['current']->state, $account)) {
      return NODE_ACCESS_DENY;
    }
    else if(!variable_get('workbench_moderation_per_node_type', FALSE) &&
          !user_access('edit all content in '.$node->workbench_moderation['current']->state, $account)) {
      return NODE_ACCESS_DENY;
    }
  }  
  return NODE_ACCESS_IGNORE;
}

Here we make sure to return NODE_ACCESS_IGNORE if none of our cases match so we don't accidentally grant access or deny access for other modules are able to jump in and have their say.

That's all for this post and as always feel free to leave any questions!

No comments:

Post a Comment