Problem/Motivation
GroupActionBase::buildConfigurationForm() upgrades the group_id element from a textfield to an entity_autocomplete for every modeler except bpmn_io, but it leaves #default_value as the raw stored string:
'#default_value' => $this->configuration['group_id'] ?? '',
'#required' => TRUE,
];
if (!self::isBpmnIoModeller()) {
$form['group_id']['#type'] = 'entity_autocomplete';
$form['group_id']['#target_type'] = 'group';entity_autocomplete requires an entity object. Building the form therefore throws:
The #default_value property has to be an entity object or an array of entity objects.Because group_id is #required, it is never empty on a configured action, so this fires whenever the form is built outside bpmn_io. The two cases that cannot work at all are:
- a token, for example
[target_group], which is the documented way to make the action reusable. The field description itself says "This field supports tokens". An autocomplete element can never represent a token. - a stale ID, where the group has since been deleted.
Steps to reproduce
- Configure "Group: add content" with
group_idset to a token, or to the ID of a group that is later deleted. - Build the action configuration form anywhere other than bpmn_io. Rendering it server side is enough, no browser needed.
- The exception above is thrown.
Found while exporting an ECA model for the ECA Guide library: the model exports fine, but its config form is skipped and the published documentation silently loses that one form.
Proposed resolution
Only upgrade to entity_autocomplete when the stored value is empty or resolves to a group, and hand the element the loaded entity. GroupActionBase::loadGroup() already does the resolution, including UUIDs, and already returns NULL for a token because it token-replaces with clear => TRUE.
$default_group = $this->loadGroup();
if (($default_group !== NULL || ($this->configuration['group_id'] ?? '') === '') && !self::isBpmnIoModeller()) {
$form['group_id']['#type'] = 'entity_autocomplete';
$form['group_id']['#target_type'] = 'group';
$form['group_id']['#default_value'] = $default_group;The empty case keeps the autocomplete for normal authoring. A token or an unresolvable ID keeps the textfield, which is the only widget able to represent a token anyway. Patch attached, tested against 1.2.2.
Remaining tasks
Review the patch. entity_id needs the same treatment if it ever gets the same autocomplete upgrade.
User interface changes
None for values that already worked. A group_id holding a token, or an ID whose group no longer exists, now renders as a plain textfield instead of throwing.
API changes
None.
Data model changes
None.
A related observation
isBpmnIoModeller() makes a widget choice based on which modeler is in use. The practical effect is that the same action renders one way in bpmn_io and throws everywhere else, including during server-side rendering where there is no modeler at all. The patch above fixes the crash without touching that, but the widget choice arguably should not depend on the modeler.
Issue fork group_action-3619954
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
jurgenhaasComment #4
nitinkumar_7 commentedThe fix looks correct and the handling of empty, valid group, token, and deleted-group values makes sense.
One minor improvement: could we move loadGroup() inside the !self::isBpmnIoModeller() branch? As written, loadGroup() is now called for BPMN actions even though the result is never used. keeping it inside the existing condition would avoid unnecessary work and preserve the previous BPMN behavior more closely.
Comment #5
nitinkumar_7 commentedi mean move
$this->loadGroup()inside the!self::isBpmnIoModeller()check to avoid unnecessary loading for BPMN actions and preserve the previous behavior.