Hook
The Hook task lets you run custom PHP code at a point in the workflow. It can call external APIs, auto-fill forms, push data to Google Sheets, send Teams messages, or make routing decisions too complex for the Condition task. Critically, it is the only automatic task that can change the direction of the workflow — rejecting a submission, pausing it, or jumping to a different step.
Hook code requires a PHP developer to write and maintain. If you are a workflow designer without a development background, bring in a developer for the plugin code. You configure the hook task in the workflow — the developer writes the hook itself.
When to Use a Hook
Before reaching for a Hook, check whether a simpler task covers the need:
| Need | Use instead |
|---|---|
| Route based on a field value | Condition task |
| Calculate a total or format a string | Transform task |
| Send a standard email notification | Notification task |
| Generate a document | Document task |
| Push to a list for dropdown use | Output task |
Use a Hook for things none of the above can do: external API calls, complex multi-step logic, form auto-fill, or dynamic workflow routing based on fetched data.
Built-in Plugins
OSPROV provides five built-in hook plugins. You select one as the base, then customise the code if needed.
| Plugin | What it does |
|---|---|
| Microsoft Teams Notification | Sends a message to a Teams channel via incoming webhook |
| Google Sheet | Appends a data row to a Google Sheets spreadsheet |
| OSPROV Populate Initial Form | Pre-fills the initial form with computed or fetched data |
| OSPROV Populate Subsequent Form | Auto-fills a supplementary form automatically |
| Formbuilder Generator | Dynamically generates a new form based on submission content |
For Teams and Google Sheets, basic use only requires filling in the parameters — webhook URL, spreadsheet ID, and so on. No code changes needed.
For the OSPROV populate plugins, you customise the code to define exactly what gets filled into which fields.
The execute() Interface
Every hook, regardless of plugin, must follow the same structure — a class with an execute() method that receives two parameters and returns a state array.
public function execute($params, $data)
{
// your code here
return [
'state' => 'continue',
'payload' => $payload,
];
}
$params — the configured parameters for this hook (URLs, credentials, settings), with all [fieldKey] placeholders already substituted with real submission values. Also includes $params['miscData']['workflowSubmission'] for full access to the submission object.
$data — the full submission data: main form fields, supplementary form data, and derived values.
Return States
The state key in the return array determines what the workflow does next:
| State | What happens |
|---|---|
'continue' | Workflow proceeds to the next task. Use this for success — all built-in plugins return 'continue'. ('completed' also works at runtime but use 'continue' by convention.) |
'reject' | Workflow is rejected. Nothing after this runs. The submission is typically returned to the applicant. |
'on-hold' | Workflow pauses. Nothing proceeds until an administrator manually resumes it. |
Integer (e.g. 3) | Workflow jumps to that step number. Use to skip tasks or loop back. |
'failure' (thrown exception) | PHP exception or parse error. Workflow stops. |
'invalid' | Hook returned an unrecognised state, or returned an integer matching the current step number. |
If the integer you return matches the step the hook is currently running on, OSPROV detects the infinite loop and marks the hook invalid. Always verify step numbers after modifying the workflow — sequence numbers change when tasks are added or removed.
Placeholder Substitution in Parameters
Hook parameter fields support the same [fieldKey] placeholder syntax as the Transform task. OSPROV substitutes the values before passing them to the hook code — so $params['message'] inside the code already contains the resolved value.
Example Teams message parameter:
New request [submissionId] submitted by [user-name] for [leaveType].
Adding a Hook Task to Your Workflow
- Drag the Hook task from the task palette onto the canvas
- Click the task to open its configuration panel
- Configure:
- Hook (required) — select which hook to run
- Title for process — label shown in submission history
- Label for status (optional) — override the default status label
The Hide from submission history setting does not currently work for hook tasks. Hook execution always appears in the submission history regardless of this setting.
Deployment Requirement
Hook code is stored in the database but must also exist as a PHP file on the server to execute. After deploying OSPROV to a new server, or after restoring from a backup, run:
php artisan osprov:init-hooks
Without this, all hook tasks will fail at runtime because the PHP class file does not exist on disk. Add this to your deployment and restore checklist.
Performance
Hooks run on the shared workflow queue alongside other tasks. A hook that makes slow external API calls can delay other workflows in the queue. If a hook consistently takes a long time, this appears in the submission history — the remark shows execution time in milliseconds. Work with your developer to optimise slow hooks or move heavy operations off the critical path.
Troubleshooting
| Problem | Likely cause |
|---|---|
Hook marked failure | PHP exception or parse error. Check system logs. Workflow stops at this point. |
Hook marked invalid | Hook returned an unrecognised state, or returned the current step number (infinite loop). Review the return value. |
Workflow stuck after reject or on-hold | These are intentional terminal/pause states. on-hold requires admin intervention to resume. reject is final. |
| Hook code changes not taking effect | Run php artisan osprov:init-hooks on the server to regenerate PHP files from the database. |
| Task jump going to wrong step | Sequence numbers change when the workflow is edited. Verify step numbers after any workflow modification. |
| Teams / Google Sheet hook not sending | Check the webhook URL or credentials in the hook parameters. Verify the environment allows outbound calls to external services. |
| Hide from history not working | Known bug — hook execution always appears in submission history regardless of this setting. |