Workflows provide a mechanism to allow plugins to hook into common workflows and provide alternative user workflows to achieve the same result. They are available from Totara 12 onward.

There are two main concepts:

  • Workflow managers: Define the specific type of workflow. Workflow managers are including in core code, which provides the mechanism for offering several options.

    An example of a workflow manager is the 'coursecreate' workflow manager, which is responsible for controlling the course creation workflows.

  • Workflows: The workflows themselves must always extend a workflow class defined by a workflow manager. They define a name and other metadata, access control and activation logic, and use one of two mechanisms to define the user's path once the workflow is selected:
    • Provide a URL the user should be taken to
    • Provide Totara form definition and processing methods

An example of a workflow might be a 'seminar' workflow, designed to extend the 'coursecreate' manager to make it easy to create seminar specific courses.

Implementing a workflow

To implement a workflow create a namespaced class \[component]\workflow\[manager_component]\[manager]\[workflowname] in the following location:


Your class must extend an abstract workflow class defined by the workflow code (\totara_workflow\workflow\base).

You should implement the metadata methods get_name(), get_description() and get_image() to describe your workflow.

If you want to redirect to a URL then you should also implement get_workflow_url().

If you want to provide a form then you should also implement define_form(\totara_form\model $model) and process_form(\stdClass $data, array $files=[])

If you want to limit access to the workflow to certain users, you can implement the can_access() method.

New workflows are not automatically enabled. To enable a workflow, you need to trigger it in install.php or upgrade.php:

// Example of enabling a workflow programmatically:
$workflow = contentmarketplace_goone\workflow\core_course\coursecreate\contentmarketplace::instance();

Implementing a workflow manager

If you want to define a new workflow manager you need to implement two classes, the workflow_manager class and an abstract workflow class:

Workflow manager class

You must implement get_name() and get_all_workflow_classes(). The later should return an array of valid workflow classes of this type. See existing workflow_manager classes for an example (e.g. /course/classes/workflow_manager/coursecreate.php).

You can also choose to implement can_access() if you require per-user control over the type of workflow.

Note that both workflow managers and workflows support the can_access() method, but they serve different purposes.

The workflow manager can_access() method should be used to restrict access to the entire workflow, i.e. prevent the user from taking the action that the workflow is designed to perform. For example, if a user is not allowed to create courses, the coursecreate workflow manager should prevent it.

The workflow can_access() method should be used to restrict access to a single workflow of that manager. For example, if there is a workflow that supports course creation via a plugin that has been disabled, the overall workflow manager may allow access but the specific workflow might not.

Workflow parameters

In some cases there will be state-specific data that you want to pass through from where the workflow is triggered into the workflow or beyond. For example courses can be created in the context of a specific category, so it's reasonable to pass the category to the workflow, which can then decide whether to make use of that information (by for example, creating the course in that category). Data can be passed and used via the set_params() and get_params() methods. Params are set against the workflow manager but available in both the manager and the workflow itself.

There are helper methods get_workflow_manager_data() and add_workflow_manager_form_elements() which can be used to pass data through the generic workflow form so it's available at the processing stage. You can also pass data as parameters by defining them in get_workflow_url(). Params can also be used in other methods such as can_access().

Triggering a workflow

Responsibility for any action that occurs during or after a workflow should be managed by the component implementing the workflow. You are free to do whatever you want, but we encourage workflows to consider the behaviour of any existing workflows and act in accordance with user expectations.

Workflow administration

Workflow access can be controlled at a site level by a Site Administrator via Site Administration > Appearance > Manage workflows. Individual workflows can be disabled, which overrides any local access control implemented by the manager or workflow. If only one workflow is available to a specific user (because only one exists in code, only one is enabled by an admin, or only one is available to them due to access rules, or a combination) the user is transparently redirected straight to that workflow.

If no workflows are available, the interface will hide the option to perform that action completely.