Extension talk:Workflow.php

From Organic Design wiki

Overview

The Workflow extension is the intended to eventually operate in accord with the wiki workflow article. Currently is has an automated mechanism behind being able to move articles through categories contained within a workflow without the need to have to manually edit and change the categorisation accordingly. Additionally the number of articles within each category in the workflow should be identified so people can instantly recognise where potential bottlenecks are occurring for any instance of a workflow.

To do this a parser function called {{#Workflow:Article|...}} has been created which allows the article to become part of a specified sequence of "states" which can be quickly cycled through without needing to edit the containing article. Client side Javascript is used to update the parser function automatically and log the event in the Special:RecentChanges once a new state has been selected for more than a split second. Articles which are part of one or more such sequences (workflows) will exhibit extended catlinks information to show their current position within each workflow.

This extension code consists of four main aspects which are described in more detail below:

  • the parser-function rendering which includes the javascript for switching between states when clicked, and for making the AJAX requests to update the state after a split second delay.
  • updating one of the workflow's parser-function statements in the article
  • extending the catlinks content with workflow position information
  • returning just an article's catlinks information minimizing communications

Version 1.0.0 redesign

Previously the state was stored in the wikitext of a page as a parameter to the #workflow parser-function call. See this diff for an example. The problem with this is that usually many items sharing the same set of workflow phases will all share a template designating them as being of a particular class. It makes sense for this template to be the one containing the workflow parser-function call so that all the members inherit it automatically. But having the current workflow state encoded as one of the parser-function parameters, means the parser-function must stay within the article to which its state applies.

Further more there is actually little benefit to having the state stored in the wikitext since it doesn't inherently related to the page categorization, so workflow states would not survive the export/import or link rebuilding processes. So it's best to have the AJAX actually add/remove actual category links or adjust a parameter in the template call (another method would be to maintain workflow states in a dedicated database table for efficiency, but we've decided against that).

When thinking in more detail about the way that we use templates and parameters to classify articles and assign properties to them, it becomes clear that another useful way for the workflow parser-function to operate is to update a specified parameter within the specified template.

Additionally, there seems no point in having dedicated articles in the NS_WORKFLOW namespace if the workflow syntax is now allowed to be inside templates. The syntax may as well directly contain each state's content.

{{#workflow:Document
 | template  = Document
 | parameter = state
 | Stub      = [[Image:Stub.png]]
 | Structure = [[Image:Structure.png]]
 | Editor    = [[Image:Editor.png]]
 | Publisher = [[Image:Publisher.png]]
}}

This example would be used within in the definition of Template:Document and would update the state by adjusting the state parameter in the Document template syntax of the current article. The content for each of the states it cycles through (designated by a sequence of named parameters) are inline content, but could easily refer to templates as follows:

{{#workflow:Document
 | template  = Document
 | parameter = state
 | Stub      = {{Stub}}
 | Structure = {{Structure}}
 | Editor    = {{Editor}}
 | Publisher = {{Publisher}}
}}

Parameter names

All the parameters passed to the parser-function are treated as being part of the workflow state list except for the first parameter which is used to give the workflow a name, and the optional template and parameter parameters which are used if the workflow directive is being used within a template (which is assumed to also be handling the categorisation aspect).

The workflow state parameters need to be named, because categorisation is expected to be using those same names.

Special page

The extension also comes with a special page (Special:Workflow), which I didn't really know what it would be used for exactly. But today Peder reminded me of the fact that we need to be able to perform simple operations such as categorisation or changing workflow-state on a selection of articles at once. That sounds like a good job for the workflow extension! Discussion specifically about Special:Workflow is at Special talk:Workflow.

Old Syntax

The idea with the syntax is to enforce a solid convention for the way workflow is approached as an overall system rather than offer flexibility od syntax to suit many diverse uses. The general syntax is as follows:

{{#Workflow:Job}}

The parameter represents the current state from the sequence specified in Workflow:Job, if it is not supplied, the first state in the list is assumed. This parameter is updated by the AJAX requests when the state is changed by the client-side JavaScript.

The article Workflow:Job contains a sequential bullet list of article titles each of which forms a specific phase in the workflow. The workflow extension is hard-wired to categorise the article into Category:Title (where "Title" is the currently selected state in the cycle), and to transclude Template:Title. Using the Category and Template name-spaces here is not optional, it is designed to enforce a consistent method usage of the workflow system which is extremely important when using a wiki for organisation. In the example above, the content of Workflow:Job might be as follows:

*[[Lead]]
*[[Quote]]
*[[In progress]]
*[[Complete]]
*[[Invoiced]]
*[[Paid]]

Each of the titles in the list should have a corresponding article in the Category and Template namespaces, if they're missing, they'll show up as red links in the catlinks information so they can easily be created. Also they should have an article in the Main namespace (which will show as red links in the Workflow article if not) which talks about that workflow phase as a concept.

By using the Workflow namespace, and enforcing the strict use of Category and Template with that title (in a similar way to how the MediaWiki software uses the Talk namespace in specific way) it allows us to later extend the way other namespaces are used with workflow items, for example to allow phases to contain automation scripts, unit tests or other context-specific meta-data.

Format

We should have a few formats, not just the container (default) but also image:x (clickable image, no container), template:x (custom layout), dropdown-list

Location

Should be able to be located not only in-place (default), but also in catlinks or page-title

Extending Category Info

The category links information below the article content can be thought of in a more general sense as the information about the current article's relationships to other articles.

Semantic MediaWiki's "facts" section below the article is in the same place, except that it is rendered as part of the article's content which we feel is wrong because it's conceptually outside the content not part of it. Another way to look at it is that information about the article which is not explicitly part of the article's content should not be returned by a request which uses the render action. SMW may have avoided adding their facts to the catlinks area because their is no official hook, but here at Organic Design we're willing to break out the voodoo at the drop of a hat!

$skin = $wgUser->mSkin;
$class = get_class($skin);
eval("class WorkflowSkin extends {$class} ".'{
	function getCategories() {
		return parent::getCategories() . "...extended info here...";
		}
	}');
$wgUser->mSkin = new WorkflowSkin();
foreach (array_keys(get_class_vars($class)) as $k) $wgUser->mSkin->$k = $skin->$k;

The workflow sequences that an article is a part of is also a very important aspect of its relationships, and the extension should add this information to the catlinks area using the following syntax (except that the namespaces wouldn't be displayed):

Workflow:Job: Category:LeadCategory:QuoteCategory:In progressCategory:CompleteCategory:InvoicedCategory:Paid

The catlinks can be extended by overriding the getCategoryLinks method of the user's skin object if one exists.

To extend the workflow area rendered within <div class="catlinks">...</div>, an optional parameter should be allowed which would use template information to render alternative workflows, e.g.

{{#workflow:Job|In progress|Template=MyWorkflow}}

The article template:MyWorkflow visually renders a workflow where the input parameters are either unnamed parameters relating to the sequence in Workflow:Job, or named parameters relating to the articles contained within Workflow:Job. Note they do not have to be complete, which allows the ability of two separate paths in a complex workflow to be accessed and updated from two separate parser functions.

Parser-Function Expansion

Switching Visible State

Making the Update State Request

The AJAX Response

The response to the AJAX requests requires a tag in the article to have its state updated, and for the category-links part of the rendered page to be returned to the client. To get the properly rendered category links, the parser needs to be instantiated and the page rendered, so the normal AJAX dispatcher must be bypassed since it is used to return data before instantiating the main article environment. The following code is called at start-up to achieve this. As can be seen it enables the two other aspects of the code, which are handled in their own functions described below.

if ($wgUseAjax && $_REQUEST['action'] == 'ajax' && $_REQUEST['rs'] == 'wfWorkflowUpdateTag' && is_array($_REQUEST['rsargs'])) {
	list($_REQUEST['title'],$wgWorkflowTagID,$wgWorkflowTagState) = $_REQUEST['rsargs'];
	$wgHooks['OutputPageBeforeHTML'][] = 'wfWorkflowReturnCatlinks';
	$wgWorkflowUpdateTag = true;
	$_REQUEST['action'] = 'render';
	} else $wgWorkflowUpdateTag = false;

Updating Current State

Returning Catlinks

Returning the catlinks is trivial and has already been tested using the following method similar to the render action.

function wfWorkflowReturnCatlinks() {
	global $wgUser,$wgOut;
	$skin = $wgUser->getSkin();
	$catlinks = is_object($skin) ? $skin->getCategories() : 'Error: no skin!';
	$wgOut->disable();
	wfResetOutputBuffers();
	header("Cache-Control: no-cache, must-revalidate");
	header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
	echo($catlinks);
	return false;
	}

Future Plans

Cone.png *Category counts within workflow
  • Make sure updates are minor edits since Recent changes will have many changes occuring with this extension

Parameters

Extra named parameters should be made available for specific templates used for catlinks info or for changing the default rendering format (for example to allow the parser-function to expand into the catlinks area next to its workflow entry).

Recursion

We want to head for future directions is to be able to build up complex processes by combining articles from the Workflow namespace recursively. This would be done by allowing titles in a Workflow article's bullet list to themselves be of the Workflow namespace rather than the Main namespace. Such workflows could be rendered as a proper graph in the catlinks area.

Scheduling

Another area for the future would be to integrate the workflows with more specific scheduling information so that workflow phases can adjust themselves automatically.

Automation and Testing

And another is to use more namespaces with the workflow-phase titles to allow more information to be available for each, such as testing information, performance monitoring, and automated scripts for various software environments to carry out the tasks instead of just people.

Pre-loads and Red-links

The red-links are very good at guiding the initial setup of things, but this can be extended further by creating preloads

Several bugfixes for your extension

Hi there!

I (User:VitaliyFilippov) just modified (fixed) the Workflow.php source code. We now use your extension in our corporate mediawiki. But initially, it contained several bugs I've fixed:

  1. You didn't use preg_quote. So any of the characters special to PCRE regular expression engine caused non-removal of old workflow item category. New workflow item category was, instead, added to the article;
  2. Also, the inability of Workflow.php to find workflow item category in the article source caused incorrect article indexing, for example, incorrect values of 'categorylinks.sortkey' field;
  3. Setting of innerHTML of 'catlinks' div caused creating inner divs with category links generated by AJAX instead of replacing outer div;
  4. onOutputPageBeforeHTML did not output content-type header, so categorylinks divs with non-latin1 letters were double-utf8-encoded;
Thanks a lot for that :-) you might also be interested in MW:Extension:RecordAdmin which we've been using for our complete workflow solution over the last year or so. --nad 21:52, 8 July 2009 (UTC)