Problem/Motivation

If the workflow transition is not permitted for the given transition and FORCE is false, the state of the workflow field should not be changed.

Proposed resolution

This method should first check if the transition was allowed before changing the value of the workflow field if FORCE = false.

CommentFileSizeAuthor
#14 workflow_2724199_13.patch1.11 KBjohnv
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

bohemier created an issue. See original summary.

bohemier’s picture

It seems that the call to workflow_entity_field_save takes care of the transition and field value. Not sure if the fix should be in workflow_entity_field_save or workflow_execute_transition. But something like this could be done in workflow_execute_transition:

function workflow_execute_transition($entity_type, $entity, $field_name, $transition, $force = FALSE) {
  // $todo D8: Remove first 3 parameters - they can be extracted from $transition.

  // Make sure $force is set in the transition, too.
  if ($force) {
    $transition->force($force);
  }

  if ($field_name) {
    // @todo: use $new_sid = $transition->execute() without generating infinite loops.

--->
  $new_sid = $transition->execute($force);
  if(!$force and ($new_sid != $transition->sid)) {
      // Transition was not valid. Return without changing the field value.
      return $new_sid;
    }
  }
<---
    // Do a separate update to update the field (Workflow Field API)
    // This will call hook_field_update() and WorkflowFieldDefaultWidget::submit().
    $langcode = $transition->language;
-->
// Remove the following since transition was executed above
//    $entity->{$field_name}[$langcode][0]['transition'] = $transition;
<--
    $entity->{$field_name}[$langcode][0]['value'] = $transition->new_sid;
    // Save ony the field, not the complete entity.
    workflow_entity_field_save($entity_type, $entity, $field_name, $langcode, FALSE);

    $new_sid = workflow_node_current_state($entity, $entity_type, $field_name);
  }
  else {
    // For Node API, the node is not saved, since all fields are custom.
    $new_sid = $transition->execute($force = TRUE);
  }

  return $new_sid;
}
johnv’s picture

If the workflow transition is not permitted for the given transition, how do you try to make the transition? The widgets will hide the transition. Do you try to do this programmatically?

It seems you are right. At some point, workflow_entity_field_save was introduced, but the checks are not copied.

bohemier’s picture

Hello Johnv

Yes this is done programmatically, through action/triggers. The state change of one workflow field will change the workflow field state of other nodes in my use case.

Thanks!

johnv’s picture

You would want to use the WorkflowState::getOptions function to get the valid options upfront.

bohemier’s picture

OK thanks for the info. What do you think about this fix though? Passing the $force boolean leads to think that this method will properly handle the transition which is not the case if force is FALSE...

johnv’s picture

There is a problem to fix. The problem with the fix is that it tries to execute the transition. I prefer to isolate the checks and apply them.
I need to refind the commit which lost the functionality. Not sure how to do that without scanning through all commits.. any help is appreciated.

bohemier’s picture

I would be glad to help... If I understand you, I should not rely on $transition->execute($force) to validate the transition but should call WorkflowState::getOptions beforehand to check the validity? Is that what the commit you're looking for was about?

johnv’s picture

Indeed. It is a semantic thing. $transition->execute($force) implies that you are actually changing the transition. But you merely want to test it.

OTOH, after a second look I think the proposed solution is OK. Because you ARE executing the transition. But I need to check the old code.

bohemier’s picture

I think this function presumes that the transition is going to be executed. The proposed change is to bail out if the transition does not go through.

johnv’s picture

Title: workflow_execute_transition will always change the state of the workflow field even if FORCE is false » workflow_execute_transition() does not respect FORCE parameter

  • johnv committed 29dd14c on 7.x-2.x
    Issue #2724199: workflow_execute_transition() does not respect FORCE...
johnv’s picture

Status: Active » Needs review
FileSize
1.11 KB

I created a proper patch for your solution.
The FORCE parameter is not respected, due to the backwards compatibility with 7.x-1.2. But that is only for workflow_node.

However, that is not a valid reason for workflow_field, which does not use transaction->execute(). Apparently I had some problems, looking at the comment : // @todo: use $new_sid = $transition->execute() without generating infinite loops.

It could be those problems have been resolved already. But I do not have the time to test all situations (Gosh, I wish I created automated tests....)

johnv’s picture

It could be possible to re-use or isolate the testing code from transition->execute(). Both Transition and ScheduledTransition should be tested.

johnv’s picture

Status: Needs review » Needs work