Problem/Motivation

We are using https://www.drupal.org/project/webform_content_creator to take a webform submission and automatically create a 'case' node that is put into a workflow using this (awesome!) module. However, when the node is created the field value on the node for the case state is not set. I believe this may be similar to #2724107: State is not saved for Entity Field with 'Hidden' widget but with an alternate method to get there.

Steps to reproduce

  1. Add a workflow
  2. Add some state
  3. Adjust transition and access
  4. Add a field 'state' to your content type 'case'
  5. Enable webform and webform_content_creator
  6. Create a basic webform with one field
  7. Create a mapping from your form to the 'case' content-type in webform content creator
  8. Select test at the top of your webform and submit

Result: Node field 'state' will not be set to any value.

In debugging this I thought it may be fairly easy to fix, but was wrong. Here is what I attempted:

In WorkflowManager.php:

161         if ((!$new_sid) && $wid = $field_info->getSetting('workflow_type')) {
162           /** @var Workflow $workflow */
163           $workflow = Workflow::load($wid);
164           $new_sid = $workflow->getFirstSid($entity, $field_name, $user);
165           $entity->{$field_name}->setValue($new_sid);   // Added this line to set the value
166         }

The problem with this change is that this code is getting called by hook_entity_insert and not hook_entity_presave, so any changes to the entity are not saved. And, then I progressed down the rabbit hole testing whether it would work to execute the transition on a new node via presave in workflow.module:

/**
 * Implements hook_entity_insert().
 *
 * @param \Drupal\Core\Entity\EntityInterface $entity
 *   An Entity.
 */
function workflow_entity_insert(EntityInterface $entity) {
  // Execute updates in hook_presave() to revert executions,
  // Execute inserts in hook_insert, to have the Entity ID determined.
  //_workflow_execute_transitions($entity);  // Removed this
}
  
/**
 * Implements hook_entity_presave().
 *
 * @param \Drupal\Core\Entity\EntityInterface $entity
 *   An EntityInterface object.
 */
function workflow_entity_presave(EntityInterface $entity) {
  //if (!$entity->isNew()) { // Removed this
    //Avoid a double call by hook_entity_presave and hook_entity_insert.
    _workflow_execute_transitions($entity);
  //}
}

And, unsurprisingly that bombed... on line 208 of WorkflowTransition.php:

198   public function save() {
 199     // Set Target Entity, to be used by Rules.
 200     $reference = $this->get('entity_id')->first();
 201     $reference->set('entity', $this->getTargetEntity());

The interesting part is that if I comment out lines 200, 201 then "everything" works fine! Except of course rules, since from the comment that is required. I assume it would mess up other things as well. At which point I rolled back my changes and just added my own presave to workaround the issue until people with better knowledge of this code can provide some guidance.

Here is the presave that I am using as a workaround:

/**
 * Implements hook_entity_presave().
 *
 * @param \Drupal\Core\Entity\EntityInterface $entity
 *   An EntityInterface object.
 */
function mymodule_entity_presave(EntityInterface $entity) {
  if ($entity->isNew() && $entity->bundle() == 'case') {
    if (WorkflowManager::isWorkflowEntityType($entity->getEntityTypeId())) {
      return;
    }

    foreach (workflow_get_workflow_field_names($entity) as $field_name) {
      $field_info = FieldStorageConfig::loadByName($entity->getEntityTypeId(), $field_name);
      if ($wid = $field_info->getSetting('workflow_type')) {
        $user = workflow_current_user();
        /** @var Workflow $workflow */
        $workflow = Workflow::load($wid);
        $new_sid = $workflow->getFirstSid($entity, $field_name, $user);
        $entity->{$field_name}->setValue($new_sid);
      }
    }
  }
}

Comments

joel_osc created an issue. See original summary.

johnv’s picture

Thanks for the exhaustive description.
I need to think about a solution.
BTW, did you notice that the Workflow Module itself invokes both hooks:
- function workflow_entity_presave()
- function workflow_entity_insert()
[EDIT] Ofcourse you did, it is mentioned in above post...

  • johnv committed 7aad940 on 8.x-1.x
    Issue #3188734: Initial state not saved on node when created...
johnv’s picture

Status: Active » Postponed (maintainer needs more info)

Please check if latest dev-version (or above patch) solves your problem.
It is taken from #3015900-8: Add Migrate support for the Workflow system on D8.

Please reopen if not.

johnv’s picture

Please check #3167341: Revision id is NULL on node edit if revision enabled, which also has problems with workflow_entity_presave().

johnv’s picture

Status: Postponed (maintainer needs more info) » Closed (outdated)

I guess this is not relevant anymore.