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
- Add a workflow
- Add some state
- Adjust transition and access
- Add a field 'state' to your content type 'case'
- Enable webform and webform_content_creator
- Create a basic webform with one field
- Create a mapping from your form to the 'case' content-type in webform content creator
- 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
Comment #2
johnvThanks 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...
Comment #4
johnvPlease 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.
Comment #5
johnvPlease check #3167341: Revision id is NULL on node edit if revision enabled, which also has problems with workflow_entity_presave().
Comment #6
johnvI guess this is not relevant anymore.