The patch is attached, done against 6.x-1.3.

The normal behavior of workflow is not changed. As long as you dont have any modules implementing this, workflow does the same.

One minor downside is, that you have to give at least a role the right to do a specific transition,as otherwise the transition_table wont get an entry for this transition. You can later anyway e.g. revoke that right with your hook anyway.

Documentation

hook_workflow_transition_allowed($tid)

You have to return a string, which will be the callback method to execute. You can use the $tid to decide, whether you want to define an callback for this transition or not.
Example:

/*
 * Implementation of hook_workflow_transition_allowed
 */
function workflow_workflow_transition_allowed($tid) {
  return '_workflow_transition_allowed_access';
}

Callback for transistion access

Every callback defined by the hook_workflow_transition_allowed hooks are exectuted, there results are merged using AND.
Every callback has to return a boolean.

Example

function _workflow_transition_allowed_access($tid, $role, $user, $node) {
  $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 as no roles, use cant have access
  return FALSE;
}

------

Usecases

Well in my case, i use this extendable api to check for a userrefrence field in the node. According to that selected user, i grant or not grant the right to make the current transition. This way e.g. you can let the right to be able to change a state make relative to a user selected in the workflow before ( in a user reference field e.g. or where yuo like..its PHP :) )

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

EugenMayer’s picture

Title: Add an API for letting other module decide(using a hook), whether a state-change is allowed or not -> Extending flexibility by f » Add an API for letting other modules decide(using a hook / callback), whether a state-change is allowed or not

Correcting title

dawehner’s picture

Title: Add an API for letting other modules decide(using a hook / callback), whether a state-change is allowed or not » Add an API for letting other module decide(using a hook), whether a state-change is allowed or not -> Extending flexibility by f
Status: Needs review » Needs work
+++ workflow.module
@@ -910,7 +910,43 @@ function workflow_transition_delete_role($from, $to, $role) {
+  if(count($access_methods) > 0) {
+    $result = TRUE;
+    foreach($access_methods as $method) {
+      if(function_exists($method)) {
+        $result &=  $method($tid,$role,$user,$node);
+      }
+    }

Codestyle: if ( , foreach ( , two many spaces in $result

+++ workflow.module
@@ -910,7 +910,43 @@ function workflow_transition_delete_role($from, $to, $role) {
+  return false;

codestyle: FALSE

+++ workflow.module
@@ -1215,7 +1253,7 @@ function workflow_transition_delete($tid) {
+function workflow_allowable_transitions($sid, $dir = 'to', $roles = 'ALL', $user = NULL, $node) {

node parameter is required, but some before not. This makes no sense.

The rest looks fine.

EugenMayer’s picture

Title: Add an API for letting other module decide(using a hook), whether a state-change is allowed or not -> Extending flexibility by f » Add an API for letting other modules decide(using a hook / callback), whether a state-change is allowed or not
FileSize
3.04 KB

Optimzing code (thanks to dereine and stbochert), documentation changes:

Documentation

hook_workflow_transition_allowed($tid)

You have to return a boolean, whether to allow or not allow this transition. The results of all hooks are AND`ed together

Example:

/*<br> * Implementation of hook_workflow_transition_allowed<br> */<br>function workflow_workflow_transition_allowed($tid) {<br>&nbsp; return '_workflow_transition_allowed_access';<br>}

Callback for transistion access

dawehner’s picture

+++ workflow.module
@@ -910,7 +910,36 @@ function workflow_transition_delete_role($from, $to, $role) {
+  $permissions = module_invoke_all('workflow_transition_allowed',$tid,$role,$user,$node);

add a space after each parameter

+++ workflow.module
@@ -910,7 +910,36 @@ function workflow_transition_delete_role($from, $to, $role) {
+  if(is_array($permissions)) {

codestyle is still there

+++ workflow.module
@@ -910,7 +910,36 @@ function workflow_transition_delete_role($from, $to, $role) {
+    foreach($permissions as $result) {
+        if($result !== true) {

and here too

+++ workflow.module
@@ -910,7 +910,36 @@ function workflow_transition_delete_role($from, $to, $role) {
+ *  * See if a transition is allowed for a given role.

nitpicking: don't use two * * in a row

Powered by Dreditor.

dawehner’s picture

FileSize
404 bytes

This is a initial workflow.api.php

EugenMayer’s picture

Dereine you used the old API, please have a look at the documentation. This is the current documentatin (wrong example in #3)

Documentation

hook_workflow_transition_allowed($tid)

You have to return a boolean, whether to allow or not allow this transition. The results of all hooks are AND`ed together


Example:

/*
 * Implementation of hook_workflow_transition_allowed
 * See if a transition is allowed for a given role.
 *
 * @param int $tid
 * @param mixed $role
 *   A single role (int or string 'author') or array of roles.
 * @return
 *   TRUE if the role is allowed to do the transition.
 */
function workflow_workflow_transition_allowed($tid, $role, $user, $node) {
  $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 as no roles, use cant have access
  return FALSE;
}
EugenMayer’s picture

Status: Needs work » Reviewed & tested by the community
jvandyk’s picture

Status: Reviewed & tested by the community » Postponed (maintainer needs more info)

Please help me understand how this is different from the current case, where a module responds to the 'transition pre' op of the workflow hook with FALSE if it wants to veto the transition (see workflow_execute_transition()).

iris_passcal’s picture

If I'm reading this correctly, I had written something similar for our institution's website that I was thinking of submitting as a patch, too.

The difference between this and the "transition pre" is that workflow_execute_transition allows a module to veto a particular transition change that is about to happen, but this proposed patch allows a module specify additional users who are allowed to perform a particular transition. The way Workflow is currently written, a module cannot change who can do a transition, only stop or allow a transition that is being requested by a user already allowed to do a transition.

For example:

I have Roles defined for Authors and Editors. Authors can create content and then pass it onto an Editor once that is done, the Author loses permission to the page while the Editor can choose to bounce it back to the Author or publish it. Currently, anyone who is defined as part of the Editors Role can work on the page.

We wanted each page to have additional authors and editors specifically assigned, so only those users had those permissions. So, we created CCK userref fields for Additional Authors and Editors. With a patch similar to the one being proposed here, we can say that the users specified in those selected CCK userref fields are allowed to transition to/from various states, too.

This is a method to additionally expand the circumstances where transitions are allowed (like allowing more users beyond simple Roles).

I hope I'm explaining this well enough, and that I haven't completely misunderstood "transition pre" and "transition post" because I could not find a way to do this without adding an additional API to Workflow.

dawehner’s picture

Status: Postponed (maintainer needs more info) » Needs review

updating status

Bastlynn’s picture

Status: Needs review » Active

I'll dig into this one a little more once I have the queue down to reasonable.

johnv’s picture

Title: Add an API for letting other modules decide(using a hook / callback), whether a state-change is allowed or not » Add a hook to let other modules decide, whether a state-change is allowed or not (D6 only)

FYI, this is fixed in D7, using $result = module_invoke_all('workflow', 'transition permission', ...);
See[#1997242]
The D6-version probably won't be updated anymore.

johnv’s picture

Status: Active » Closed (won't fix)

I wish there was a nicer way to clear the issue queue from 'D6-issues that are fixed in D7' then a "won't fix for D6."