Problem
Orchestra has no seam for code to contribute computed process variables at a step. orchestra_eca covers the no-code path, and a bespoke task type covers one-off logic, but there is nothing between them: no way to say "at this step, compute these variables from the process subject, each unit owned by a different module".
Yoyaku built exactly that seam locally: a WorkflowVariableProviderInterface, a WorkflowVariableProducer collecting a yoyaku_orchestra.workflow_variable_provider tag, and a yoyaku_prepare_workflow_variables action that writes the merged result with setVariable(). Nothing in it is booking-specific except the argument type, and every other consumer would have to reinvent it.
A service tag also cannot express per-step selection: every tagged provider runs on every prepare step of every workflow. That is tolerable for one workflow shape and wrong for two.
Proposed
A VariableProvider plugin type in Orchestra core: an attribute with id, label, description and provides (the variable names the provider writes), and VariableProviderInterface::variables(TokenInterface $token, ProcessInstanceInterface $instance): array, argument order matching TaskTypeInterface::execute().
A variables task type: node config holds an ordered list of provider IDs (JSON via FlatConfig, as orchestra_action already does for action_settings) plus a variable scope, following ResultVariableConfigTrait. It instantiates only the selected providers, asks each one before writing anything, and writes the merged result on the instance. The stored list is the run order, so where two providers write the same variable the model shows which one wins.
The editor is a drag-to-reorder table of the providers the step runs, each row naming the variables it declares and carrying a remove checkbox, with a select and an Add button below for the ones not yet on the step. The table holds the step's own providers only, so the form does not grow with the number installed.
Why a task type rather than a Drupal action
A task type receives the instance and token natively, so it needs no OrchestraContextAwareInterface bridge, and it avoids nesting the provider list inside the action's own JSON-encoded settings inside node config.
Why plugins rather than a service tag
Per-step selection, which is the whole point. Plus a label and description for the modeler, a provides declaration the modeler can surface and validate outgoing flow conditions against, instantiation of only what a step selects, and a workflow config that declares a real dependency on the module providing each selected variable.
Scope
Plugin type, manager, task type, kernel test coverage, docs page and French translations.
Issue fork orchestra-3613299
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
mably commentedComment #4
mably commentedComment #6
mably commented