Webform integration¶
orchestra_interaction_webform turns a Webform
into a workflow touch point. A form can trigger a workflow (submitting it
starts a run) and it can be a step the workflow reopens (collect more input,
show a read-only review, or let someone edit an earlier submission). This page
is the full configuration reference; for the concepts see
External interaction.
What the module ships¶
- A
webforminteraction plugin, chosen on a wait node's External interaction feature, so the node parks and dispatches the party to a form. - An Orchestra interaction Webform element (the "binding element"): one
hidden field that ties a submission to a specific workflow step. It lives in
the hidden
orchestra_webformmodule, which both webform modules require, so a form on a site without the engine uses the same element. - One Orchestra: start or resume on submit Webform handler.
The binding element¶
The binding element is a single hidden field (its own element type) that carries the workflow resume handle. When the workflow parks a wait node and dispatches the party to the form, the interaction prepopulates this element with the handle for that step; on submit, the handler reads it to know which parked step to resume. On a fresh submission the element is empty, which is how the handler recognizes a first submission and starts a run instead.
When you need it¶
Add the binding element only when the form is reopened by the workflow as a step. Use this rule:
| The form's role | Binding element? |
|---|---|
| Only triggers a workflow, never revisited | No |
| Reopened by the workflow as a step: collect, review, or edit/update the submission | Yes |
| Both (one form starts a run, then is reopened to modify) | Yes |
| Submission only ever changed by backend code, never through the form | No (for that update) |
A trigger-only form needs no binding element: the handler treats "no binding element" as "every submission is a fresh start", and it binds the submission to the new instance itself (as the Webform source entity), so the submission is still linked to its run.
The element's value is a bearer resume handle, so it is stripped from any
captured value map (see values_variable below) and never lands in a process
variable.
The handler¶
There is a single handler, Orchestra: start or resume on submit, that does both jobs, keyed on the binding element:
- No handle (empty or absent binding element) and a workflow is configured: the submission is a fresh start. It starts the workflow, binds the submission to the new instance as its source entity, and seeds the variables. When the engine refuses the start - the workflow was deleted since the handler was pointed at it, or disabled, or has no valid start node, or is not available in the tenant the submission acts in - the answers stay saved, the submitter is told the request could not be started, and the refusal is logged with the engine's own reason beside the form, the workflow and the submission. The submission is left unbound, so saving it again once the workflow can run picks it up without a second record.
- Handle present (the form was reopened by the workflow): the submission is a step. It resumes the bound instance's parked token with the configured outcome, and refreshes the submission id and value map.
A step is resumed only when the form is submitted: by the person, on the final page of a multi-page form, or by code submitting the form's values, such as a REST resource. Another save of the submission resumes nothing, for example an administrator toggling its sticky flag or editing its notes. In a modify loop the same step is parked again, waiting for new answers, and such a save would otherwise complete it with the old ones. A start has no such rule: saving the submission again never starts a second instance.
Whichever it is, the form asks at build time whether submitting it could do anything, and when it could not it says so and disables the submit button rather than taking the answers first: a start whose workflow the engine would refuse, a step this actor may see but not complete, a step whose branch has already moved on, or a handle that resolves to nothing at all because it expired or was tampered with. The escape-outcome buttons stay usable, because leaving the step by a path the author defined is still valid, and the step's context stays readable. A step the actor may not see at all is refused outright instead. What the answer was read from is declared on the form, so a form refused while its workflow was retired starts offering a submit again as soon as the workflow runs, with no cache to flush by hand.
That is not the enforcement. The bind and the resume are still gated on submit, and a refusal that only becomes true between opening the form and submitting it (cover revoked in between) is still reported afterwards, because no build-time question can know it.
Because one handler holds one set of settings, the start and resume sides cannot drift apart (for example capturing the value map on start but not on resume).
Settings¶
| Setting | Applies to | Meaning |
|---|---|---|
| Start workflow | start | The workflow to start when a fresh submission completes. Leave as None for a form that only ever resumes a step. |
| Store submitter user id in variable | start | Optional process variable for the submitter's uid, so a step can route work back to the poster (the "By variable" assignment reads it). |
| Set variables on start | start | Optional, one name\|value per line (name: value works too, as in every pairs field). Tokens in the value are replaced against the submission and its webform when the instance starts, so form_name\|[webform:title] records which form started it and priority\|[webform_submission:values:priority] copies one answer. A token with nothing to replace it with becomes empty, and every value is written as text. A name may not be reserved (__), repeated, or one of the id, submitter or values variables. |
Resume outcome (default submitted) |
resume | The outcome the parked step is resumed with, for the outgoing flows to route on. |
Submission id and values scope (instance or token) |
resume | Whether the stored id and values are instance-wide or local to this branch. A start always seeds at instance scope. |
| Store submission id in variable | both | Optional process variable for this submission id, so a later step can address the exact submission. |
| Store submission values in variable | both | Optional process variable for the whole value map: seeded on start and refreshed on every resume (the modify loop), so a flow condition can route on a field and a step can read any answer. |
| Store each value in its own variable | both | Shown once a values variable is named. Writes each answer to a variable named after the values variable and the element key (submission.manager_email) instead of the map. See Answers in their own variables. |
| Split composite elements into their parts | both | Shown while the above is checked. A composite holding one value, such as an address, is written part by part (submission.address.city). |
| Split multiple values by position | both | Shown while the above is checked. An element holding several answers, such as checkboxes, is written answer by answer from position 0 (submission.colors.0; with composites split, submission.addresses.0.city). |
| Return to the workflow after submit | both | After starting or resuming, send the link holder to the workflow's next step instead of the webform's own confirmation (see Chaining). Off by default. |
Configuring a webform¶
A form that only triggers a workflow¶
- Build the Webform.
- Add the handler and set Start workflow; optionally set the variables to seed.
No binding element needed.
A form the workflow reopens as a step¶
- Build the Webform.
- Add one Orchestra interaction (binding) element (its key is free; the handler and interaction find it by type).
- Add the handler; set Resume outcome. Leave Start workflow as None if the form is resume-only.
- On the wait node, set External interaction to Webform, pick the form, and choose the mode (below).
One form that both starts and is modified (the modify loop)¶
Add the binding element and the handler with both a Start workflow and a
Resume outcome set. On the first (unbound) submission the handler starts the
run; when the workflow later reopens the form for editing, the submission carries
a handle and the same handler resumes it. Because it is one handler, the captured
values_variable is seeded on the start and refreshed on every modify (each a
resume), so the stored data always matches the latest submission.
Answers in their own variables¶
By default the answers are one map in the values variable, and a workflow reads
one of them with a dotted name: submission.manager_email walks into the
submission map. Store each value in its own variable writes each answer
under that same name instead, so nothing changes for the workflow: a dotted
name reads the variable of exactly that name first, and a path into a map
otherwise. Flow conditions, [orchestra:var:submission.manager_email], the
context lines, the Views variable column and the "by variable" assignments all
read it that way. Storing the answers separately is what lets a Views filter
match one answer, and it keeps the variable list readable one answer per row.
So a review step is assigned to the manager the requester named with a Users
by variable assignment on submission.manager_email, whichever way the form
stores its answers.
The submission id and every answer are written in one batch, on the start and on every resume: one audit record, whatever the number of fields.
An element holding several answers stays one list, which a "by variable"
assignment reads as several people (a list of email addresses assigns the step
to each of them), unless Split multiple values by position is checked.
Positions move when an answer is removed. Nothing deletes a
variable the form no longer writes, such as the one of a removed element or the
last position of a shortened list: to start from clean names, store the values
under another variable name, for example submission2.
A subprocess that reopens the parent's submission¶
The submission stays bound to the run that started on it, and a subprocess of
that run may still show and amend it. Store the submission id in a variable on
the start form's handler (Store submission id in variable, e.g.
submission_id), hand it down through the subprocess node's input map
(submission_id|submission_id), and give the child's step the same variable as
its Submission id variable. Submitting the form through that step resumes
the child's step, and Return to the workflow after submit takes the link
holder to the child's next step, or back to the parent run once the child has
ended.
The answers of that submit are stored in the child, the run the step belongs
to, under the handler's values variable. The parent keeps the values it started
with; to see the amended answers there, pass them back through the subprocess
node's output map: submission|submission when the answers are one map, or one
line per answer when each is stored on its own, such as
submission.manager_email|submission.manager_email.
A step of any other run cannot be resumed with that submission: the answers are saved, the step stays where it is, and the link holder is told.
One workflow for several forms¶
A step can leave its form on The form of the submission in the variable. It then uses the form of the submission its Submission id variable names, so one workflow (review, request changes, edit, process) serves every form that starts it. Give every such step the same variable, and on each form set the handler's Store submission id in variable to that name.
The workflow cannot check a form it does not name, so the handler of each form checks it when it is saved. A variable name that no step of the workflow reads, which is a mistyped name, is refused. Storing no id at all is accepted, since the form may only start the workflow, but warned about when no step names the form, since then no step can show its submissions. For the steps that read the form's variable, a missing binding element (collect or editable steps) or a secure-token setting that is off (editable steps) is warned about. When such a step is shown and its form cannot serve it, the link holder is told the step is not set up yet, and the log says what to change.
Wait-node interaction modes¶
On the wait node's External interaction = Webform, the form renders in one of three modes:
- Collect input (default): show the empty form to fill.
- Review (read-only): render an existing submission as a read-only summary, for a step that inspects what was submitted without changing it.
- Review (editable): reopen an existing submission for editing, for a step that revises it (the poster amending after a request for changes).
The review modes read the submission to show through a configured submission
variable (the same variable the handler wrote the id into), so the right
submission always reopens. A step can also display context: each
context_display entry names a process variable (dotted paths reach into a
structured value, e.g. validation.comment), a label and an optional severity
(status, warning or error; when omitted, the severity of the outcome the value
came with, else status), and its current value is posted as a Drupal
message wherever the step surfaces: on a review rendered in place, and on
every page of the form the actor is redirected to. The value is read live
from the instance each time, never stored into the submission, so a later
viewer can never mistake an old note for the current one.
Two groups of settings apply to some modes only, and the settings form shows each only while the matching mode is selected:
- Outcomes requiring a comment, Comment field description and Store comment in variable belong to Review (read-only), whose decision is a comment form under the summary.
- Escape outcomes (with their labels) belong to Collect input and Review (editable): each becomes a button beside Submit on the form, which resumes the step with that outcome.
Chaining¶
By default a Webform shows its own confirmation page after submit. Turn on Return to the workflow after submit to instead send the link holder to the workflow's next step (the interaction dispatcher, or the inbox for a task), which is what lets one workflow chain several forms.
The handler disables this option for the inline and modal confirmation types, because those re-render the form in place instead of redirecting and would cancel the return. Set the form's confirmation type to one that redirects (for example Page) to use chaining.
A webform on a site without the engine¶
A form can live on a site that has no workflow engine of its own, and talk to a
remote Orchestra instead. Take a forms site
that hosts a leave request, while the workflows run on an intranet: enable
orchestra_client_webform on the forms site, and add the handler
Orchestra: start or resume on a remote Orchestra to the form.
It behaves like the local handler, keyed on the same binding element:
- No handle: a fresh submission starts the chosen workflow over there, with the submission id and answers as variables. The submission's uuid goes with the start, so saving the submission again is answered with the instance its first save started, not a second one.
- Handle present: the form was opened from a step's link. Submitting it completes that step with the configured outcome, and tells the engine which form and submission did it, so the handle of another step cannot be used here. As on the local handler, only submitting the form does this: another save of the submission completes nothing.
Before the form is shown, the handler asks the remote whether this person may complete the step. When they may not, they are told and the submit button is hidden, before they type anything. A remote that cannot be reached at that moment does not keep the form from being filled in: the step is checked again when the form is sent.
A form whose remote has been disabled or deleted is refused the same way: its answers could be sent nowhere. If that happens between showing the form and sending it, the answers are saved, the person is told they were not sent, and the reason is logged.
The form's URL carries the step's resume handle, so the page is sent with a no-referrer policy, as on the engine site: an off-site resource on it never receives the handle.
Steps that show the form over there¶
A workflow on the engine site reaches such a form through a webform step whose Form location is The site that started the workflow. Name the form by its machine name on that site, or leave it empty and set the step's submission id variable to use the form of that submission, as for a form on this site.
The engine site cannot list the other site's forms, so it checks nothing about the form when the workflow is saved: the forms site checks it when its handler is saved, and again when the step opens it.
When the person opens the step, from a link or from the inbox, the engine site sends them to the forms site, with what the step needs signed by the secret the two sites agreed when they shook hands. The forms site reads it once, keeps it for the person, and moves them to an address that carries neither the step's handle nor the signature. It then asks the engine site whether the person may see the step, and with which submission, and shows it by its mode:
- Collect: the form, to fill in. Submitting it completes the step.
- Editable review: the submission the step names, reopened through its secure token, on the form. The engine site is asked first whether the step shows that submission, so a handle copied from another step cannot open it. The form on the forms site needs its Allow users to update a submission using a secure token setting on. Without it the step says it is not set up, and the reason is logged.
- Read-only review: the submission as Webform renders it, wizard pages included, with the step's decision under it: one button per outcome, and a comment field for the outcomes that need one. A step without outcomes gets a single Complete button, as on the engine site. Deciding completes the step on the engine site, with the comment.
Once a step is completed on the forms site, by a decision or by a form sent, the person goes back to the engine site: to the page they opened the step from, such as the inbox, else to the step that comes next, as on the engine site's own pages.
Whichever the mode, the forms site shows what the engine site's own pages show with the step: its title, its description, its context messages and its outcomes, read from the engine site each time the page is shown. A review reopened after the workflow changed offers the outcomes the step has now. The context messages follow the person through every page of the form, and each escape outcome of the step is a button beside the submit.
An instance remembers which site started it, and a subprocess the site its parents were started by. A step on an instance this site started itself has no such site to send the person to: it says it is not set up, and the reason is logged.
Who the person is, over there¶
The remote is told who submitted through an identity proof. When the remote proves people by presence, a signed-in person needs a presence key, which only the workflow site can hand out. So a person without a key is sent to the workflow site to confirm who they are, and brought back to the form, before they fill it in. The key is extended while they use the form.
A key can still expire between opening the form and sending it. The answers are then saved, and the message after submitting links to the workflow site, to confirm who they are once more. Coming back, the answers are sent without being typed again. It is a link rather than a redirect, so it works whatever the form's confirmation type, inline and modal included. What waits is kept in the person's own private store, so nobody else can send it, and it is sent at most once. An anonymous person, or a remote that takes this site's word, needs no key.
Settings¶
The settings are those of the local handler, shared with it: the instance label, the outcome, and the variables the submission's id and answers are stored in. One setting is added, and the workflow list comes from the remote:
| Setting | Meaning |
|---|---|
| Remote Orchestra | The remote to talk to. Leave on the default remote unless the site calls several. A remote disabled or deleted since stays listed, marked, so the settings still show what the form names. |
| Start workflow | Listed from the workflows the remote lets this site start. A workflow the chosen remote does not offer is refused on save: after changing the remote, save with None, then open the settings again to pick one of its workflows. |
Three settings of the local handler are not offered. The submitter user id means nothing on the other site. The return to the workflow would send the person to a step that runs elsewhere. For a value set on start, put it in the form, as an answer. Re-editing a submission after its link has expired completes nothing.
Gotchas¶
- Return to the workflow needs a redirecting confirmation type (not inline or modal), as above.
- The binding element is required to reopen or edit a submission as a step. Without it a form can only ever start; a started submission is bound to its instance, but it cannot be reopened as a step. A collect or editable step that names such a form is refused when the workflow is saved.
- A re-edit after the run has moved on resumes nothing. A stale submission can only ever complete the step it was bound to: if the branch looped back and re-parked on that same form step, the re-edit resumes the fresh token (the modify loop); if the branch is anywhere else, on a later step, finished, or merged, the submission is saved but nothing is resumed and no process variable changes.
- A bearer submission cannot complete a step assigned to an operator. If the parked step declares assignments (an operator task), the handler refuses to resume it from a bearer webform submission: that step is completed only through the task route under the inbox's authorization check. The submission is saved but the run stays parked and no process variable changes, so a party holding a binding token cannot approve, or feed values into, the operator's step. The submitter is told so, and the refusal is logged: answers that were saved without completing anything are never reported as a success.
Worked example¶
orchestra_interaction_webform_examples wires all of this into a runnable
request validation flow. Its Submission form carries the binding element
and the single handler, configured with Start workflow request_validation,
Resume outcome modified, and seeding request_sid (submission id),
poster_uid (submitter), and request (the value map). The
request_validation workflow forks a validate step (review, read-only) and, on
a request for changes, a modify step (review, editable) routed back to the
poster, who edits and resubmits. That editable step reopens the poster's own
submission through Webform's secure token, which the form allows: editable
review needs the form's Allow users to update a submission using a secure
token setting on, and the step refuses to be configured against a form that
does not have it. See the module's README for the full walkthrough.