This document describes the workflow API calls necessary to apply a simple workflow to a content item.
Most publishers wish to follow some variation of the following workflow:
State | Task | Description |
---|---|---|
Created | Authoring | The publisher has created the item. |
Authored | Editing | The author has written the item. |
Edited | Publishing | The editor has approved the item. |
Published | None | The publisher has approved the item. |
At any point in the workflow, an assigned user should be able to check out an item, such that other users are advised that someone is working on it. When checking an item in, a user should have up to three options:
This simple workflow is defined in sql/workflows/author-edit-publish.sql.
Production of a content item frequently begins with a concept which is initiated by the publisher and then executed by the staff. In this scenario, the publisher creates the workflow and then assigns each task in the workflow to one or more people. The API calls to initialize a new workflow are as follows:
declare v_case_id integer; sample_object_id integer := 9; sample_user_id integer := 10; begin v_case_id := workflow_case.new( workflow_key => 'publishing_wf', context_key => NULL, object_id => sample_object_id); workflow_case.add_manual_assignment(v_case_id, 'authoring', sample_user_id); workflow_case.add_manual_assignment(v_case_id, 'editing', sample_user_id); workflow_case.add_manual_assignment(v_case_id,'approval', sample_user_id); workflow_case.start_case(case_id => v_case_id, msg => 'Here we go.'); end; /
In this case, only one assignment is made per task. You can make as many assignments per task as desired. There is currently no workflow API to set deadlines, so you must write your own DML to insert a row into wf_case_deadlines if you wish to allow the publisher to set deadlines ahead of time.
The above workflow is created in the Default context. In practice, you may wish to create one or more contexts in which to create your workflows. Contexts may be used to represent different departments within an organization.
The start_case enables the first task in the workflow, in this case Authoring.
If multiple persons are assigned to the same task, it is useful to allow a single person to "check out" or lock an item while they are working. This is accomplished with the following API calls:
declare v_journal_id integer; sample_task_id := 1000; sample_user_id := 10; sample_ip := '127.0.0.1'; begin v_journal_id := workflow_case.begin_task_action(sample_task_id, 'start', sample_ip, sample_user_id, 'Checking it out'); workflow_case.end_task_action(v_journal_id, 'start', sample_task_id); end; /
A minimum of two calls are required to perform any action related to a task. In this case we are simply notifying the workflow engine that someone has started the task. You may specify NULL for the journal message if the user does not wish to comment on the check out.
Unless given a timeout period, a lock on a content item will persist until the holding user checks the item back in. This involves notifying the workflow engine that the user has finished the task:
declare v_journal_id integer; sample_task_id integer := 1000; sample_user_id integer := 10; sample_ip := '127.0.0.1'; begin v_journal_id := workflow_case.begin_task_action(sample_task_id, 'finish', sample_ip, sample_user_id, 'Done for now'); workflow_case.set_attribute_value(v_journal_id, 'next_place', 'start'); workflow_case.end_task_action(v_journal_id, 'finish', sample_task_id); end; /
Upon finishing a task, you must notify the workflow engine where to go next. In this case, an author wishes to simply check an item back in without actually completing the authoring task. The set_attribute_value procedure must thus be used to set next_place to the starting place of the workflow.
The process to finish a task varies slightly depending on whether the user has previously checked out the item out or not. If the user has not already checked it out (has been working on the item without locking it, the code looks like this:
declare v_journal_id integer; sample_task_id integer := 1002; sample_user_id integer := 10; sample_ip := '127.0.0.1'; begin -- start the task v_journal_id := workflow_case.begin_task_action(sample_task_id, 'start', sample_ip, sample_user_id, NULL); workflow_case.end_task_action(v_journal_id, 'start', sample_task_id); -- finish the task v_journal_id := workflow_case.begin_task_action(sample_task_id, 'finish', sample_ip, sample_user_id, 'Authoring complete'); workflow_case.set_attribute_value(v_journal_id, 'next_place', 'authored'); workflow_case.end_task_action(v_journal_id, 'finish', sample_task_id); end; /
In this case an author is finishing the Authoring task, upon which the workflow engine will move the workflow to the Authored state (as indicated by the next_place attribute). If the author had previously checked out the item, then only the second step is required.
Approval steps more commonly do not involve an explicit check-out process. The code is thus virtually identical to that above:
declare v_journal_id integer; sample_task_id integer := 1003; sample_user_id integer := 10; sample_ip := '127.0.0.1'; begin v_journal_id := workflow_case.begin_task_action(sample_task_id, 'start', sample_ip, sample_user_id, NULL); workflow_case.end_task_action(v_journal_id, 'start', sample_task_id); v_journal_id := workflow_case.begin_task_action(sample_task_id, 'finish', sample_ip, sample_user_id, 'Authoring complete'); workflow_case.set_attribute_value(v_journal_id, 'next_place', 'edited'); workflow_case.end_task_action(v_journal_id, 'finish', sample_task_id); end; /
Note the distinction between approval or rejection is determined solely by the value of the next_place attribute.