Difference between revisions of "Extension:Workflow.php"
m |
(standardise whitespace) |
||
Line 27: | Line 27: | ||
function SpecialWorkflow() { | function SpecialWorkflow() { | ||
− | SpecialPage::SpecialPage(wfMsg('workflow'),'',true,false,false,false); | + | SpecialPage::SpecialPage(wfMsg('workflow'), '', true, false, false, false); |
− | + | } | |
# Render list | # Render list | ||
function execute($param) { | function execute($param) { | ||
− | global $wgParser,$wgOut; | + | global $wgParser, $wgOut; |
$wgParser->disableCache(); | $wgParser->disableCache(); | ||
$this->setHeaders(); | $this->setHeaders(); | ||
− | $wgOut->addWikiText('Not done yet... discussion at [[Extension talk:Workflow.php]]',true); | + | $wgOut->addWikiText('Not done yet... discussion at [[Extension talk:Workflow.php]]', true); |
− | |||
} | } | ||
+ | } | ||
# Define main workflow class containing all the functionality | # Define main workflow class containing all the functionality | ||
Line 51: | Line 51: | ||
# Constructor | # Constructor | ||
function Workflow() { | function Workflow() { | ||
− | global $wgHooks,$wgSiteNotice,$wgExtensionFunctions,$wgWorkflowMagic,$wgExtraNamespaces; | + | global $wgHooks, $wgSiteNotice, $wgExtensionFunctions, $wgWorkflowMagic, $wgExtraNamespaces; |
# Require NS_WORKFLOW to be defined before installing parser-function or javascript etc | # Require NS_WORKFLOW to be defined before installing parser-function or javascript etc | ||
Line 57: | Line 57: | ||
$wgSiteNotice .= '<div class="usermessage">'.wfMsg('workflowMissingNamespace').'</div>'; | $wgSiteNotice .= '<div class="usermessage">'.wfMsg('workflowMissingNamespace').'</div>'; | ||
return; | return; | ||
− | + | } | |
# The parser-function name, special-page name and links all use the word defined in $wgExtraNamespaces[NS_WORKFLOW] | # The parser-function name, special-page name and links all use the word defined in $wgExtraNamespaces[NS_WORKFLOW] | ||
Line 64: | Line 64: | ||
# Reserve the magic word for use as a parser-function | # Reserve the magic word for use as a parser-function | ||
− | $wgHooks['LanguageGetMagic'][] = array($this,'languageGetMagic'); | + | $wgHooks['LanguageGetMagic'][] = array($this, 'languageGetMagic'); |
# If it's a workflow-related ajax call, don't use dispatcher (because we need the catlinks generated by normal page render) | # If it's a workflow-related ajax call, don't use dispatcher (because we need the catlinks generated by normal page render) | ||
Line 71: | Line 71: | ||
# Add the extension's setup function to the list to be called after the environment is up and running | # Add the extension's setup function to the list to be called after the environment is up and running | ||
− | $wgExtensionFunctions[] = array($this,'setup'); | + | $wgExtensionFunctions[] = array($this, 'setup'); |
− | + | } | |
# Setup | # Setup | ||
function setup() { | function setup() { | ||
− | global $wgParser,$wgLanguageCode,$wgMessageCache,$wgContLang; | + | global $wgParser, $wgLanguageCode, $wgMessageCache, $wgContLang; |
$cat = $wgContLang->getNsText(NS_CATEGORY); | $cat = $wgContLang->getNsText(NS_CATEGORY); | ||
Line 85: | Line 85: | ||
'workflowMissingNamespace' => 'The NS_WORKFLOW namespace must be defined. The workflow extension is disabled.', | 'workflowMissingNamespace' => 'The NS_WORKFLOW namespace must be defined. The workflow extension is disabled.', | ||
'workflowStateUpdated' => "[[{$this->magic}:$1|$1 {$this->magic}]] state set to [[$cat:$2|$2]]." | 'workflowStateUpdated' => "[[{$this->magic}:$1|$1 {$this->magic}]] state set to [[$cat:$2|$2]]." | ||
− | + | )); | |
− | + | } | |
# Add the specialpage to the environment | # Add the specialpage to the environment | ||
Line 92: | Line 92: | ||
# Add the parser-function hook | # Add the parser-function hook | ||
− | $wgParser->setFunctionHook($this->magic,array($this,'expandMagic')); | + | $wgParser->setFunctionHook($this->magic, array($this, 'expandMagic')); |
# Add the client-side scripts for changing states | # Add the client-side scripts for changing states | ||
$this->addJS(); | $this->addJS(); | ||
− | + | } | |
# Expand the #workflow to reveal the current state and hide the others and add javascript | # Expand the #workflow to reveal the current state and hide the others and add javascript | ||
# - note the hidden states mustn't be rendered because they contain categorisation links which shouldn't be processed | # - note the hidden states mustn't be rendered because they contain categorisation links which shouldn't be processed | ||
function expandMagic(&$parser) { | function expandMagic(&$parser) { | ||
− | global $wgUser,$wgJsMimeType,$wgContLang; | + | global $wgUser, $wgJsMimeType, $wgContLang; |
$parser->disableCache(); | $parser->disableCache(); | ||
$tmpl = $wgContLang->getNsText(NS_TEMPLATE); | $tmpl = $wgContLang->getNsText(NS_TEMPLATE); | ||
Line 118: | Line 118: | ||
$args .= "|$arg"; | $args .= "|$arg"; | ||
if (preg_match('/^(.+?)\\s*=\\s*(.+)$/',$arg,$match)) $argv[$match[1]] = $match[2]; else $argv[] = $arg; | if (preg_match('/^(.+?)\\s*=\\s*(.+)$/',$arg,$match)) $argv[$match[1]] = $match[2]; else $argv[] = $arg; | ||
− | + | } | |
$name = $argv[0]; | $name = $argv[0]; | ||
$this->workflowData[$name] = array(0); | $this->workflowData[$name] = array(0); | ||
Line 137: | Line 137: | ||
if (is_object($title) && $title->exists()) { | if (is_object($title) && $title->exists()) { | ||
$article = new Article($title); | $article = new Article($title); | ||
− | if (preg_match_all('/^\\*\\s*\\[{2}\\s*(.+?:)?\\s*(.+?)\\s*\\]{2}/m',$article->getContent(),$match)) $states = $match[2]; | + | if (preg_match_all('/^\\*\\s*\\[{2}\\s*(.+?:)?\\s*(.+?)\\s*\\]{2}/m', $article->getContent(), $match)) $states = $match[2]; |
else $anchor .= " (".wfMsg('workflowMissingContent').")"; | else $anchor .= " (".wfMsg('workflowMissingContent').")"; | ||
− | + | } | |
else $href .= " class='new'"; | else $href .= " class='new'"; | ||
$html = "<a $href title='$anchor'>$anchor</a>"; | $html = "<a $href title='$anchor'>$anchor</a>"; | ||
Line 148: | Line 148: | ||
$left = "<td class='menu' id='left' onClick='workflowSwitchState(\"$name\",-1)'><a href='javascript:;'><</a></td>"; | $left = "<td class='menu' id='left' onClick='workflowSwitchState(\"$name\",-1)'><a href='javascript:;'><</a></td>"; | ||
$right = "<td class='menu' id='right' onClick='workflowSwitchState(\"$name\",1)'><a href='javascript:;'>></a></td>"; | $right = "<td class='menu' id='right' onClick='workflowSwitchState(\"$name\",1)'><a href='javascript:;'>></a></td>"; | ||
− | + | } | |
else $left = $right = "<td></td>"; # no menu buttons if not allowed to edit | else $left = $right = "<td></td>"; # no menu buttons if not allowed to edit | ||
$html = "<div class='workflow' id='workflow-$name'>"; | $html = "<div class='workflow' id='workflow-$name'>"; | ||
Line 155: | Line 155: | ||
foreach ($states as $i => $dbk) { | foreach ($states as $i => $dbk) { | ||
$i++; | $i++; | ||
− | $stitle = Title::newFromText($dbk,NS_TEMPLATE); | + | $stitle = Title::newFromText($dbk, NS_TEMPLATE); |
$surl = $stitle->getLocalUrl(); | $surl = $stitle->getLocalUrl(); | ||
$state = $stitle->getText(); | $state = $stitle->getText(); | ||
Line 170: | Line 170: | ||
$p =& $parser; # use the global parser so catlinks are updated | $p =& $parser; # use the global parser so catlinks are updated | ||
$ci = $i; | $ci = $i; | ||
− | + | } | |
$content = $p->parse($wikitext,$title,$opt,false,$state != $current)->getText(); | $content = $p->parse($wikitext,$title,$opt,false,$state != $current)->getText(); | ||
Line 178: | Line 178: | ||
<td class='menu' id='title'><a href='$surl' title='$tmpl:$state'>$anchor</a></td>$right | <td class='menu' id='title'><a href='$surl' title='$tmpl:$state'>$anchor</a></td>$right | ||
</tr></table></div>\n"; | </tr></table></div>\n"; | ||
− | + | } | |
$html .= "</div><script type='$wgJsMimeType'>workflowData['$name']=[$ci$data];</script>\n"; | $html .= "</div><script type='$wgJsMimeType'>workflowData['$name']=[$ci$data];</script>\n"; | ||
$this->workflowData[$name][0] = $ci; | $this->workflowData[$name][0] = $ci; | ||
− | + | } | |
− | return array($html,'isHTML' => true,'noparse' => true); | + | return array($html, 'isHTML' => true, 'noparse' => true); |
− | + | } | |
# Update the current state of a workflow item in the requested article | # Update the current state of a workflow item in the requested article | ||
# - the actual article edit is done in returnCatlinks after all parsin finished | # - the actual article edit is done in returnCatlinks after all parsin finished | ||
# - this disables the parser-cache if the content has changed | # - this disables the parser-cache if the content has changed | ||
− | function updateState(&$parser,&$text) { | + | function updateState(&$parser, &$text) { |
− | $result = preg_replace_callback("/\\{\\{\\s*#\\s*{$this->magic}\\s*:\\s*{$this->name}\\s*(.*?)\\s*\\}\\}/is",array($this,'updateStateCallback'),$text,1,$count); | + | $result = preg_replace_callback( |
+ | "/\\{\\{\\s*#\\s*{$this->magic}\\s*:\\s*{$this->name}\\s*(.*?)\\s*\\}\\}/is", | ||
+ | array($this, 'updateStateCallback'), | ||
+ | $text, | ||
+ | 1, | ||
+ | $count | ||
+ | ); | ||
if ($count) $this->text = $text = $result; | if ($count) $this->text = $text = $result; | ||
$parser->disableCache(); | $parser->disableCache(); | ||
return true; | return true; | ||
− | + | } | |
# Replacement callback for updating tag state | # Replacement callback for updating tag state | ||
function updateStateCallback($match) { | function updateStateCallback($match) { | ||
− | $result = preg_replace("/(state\\s*=\\s*['\"]?)[^'\"\]\|]+/","$1{$this->state}",$match[1],1,$count); | + | $result = preg_replace("/(state\\s*=\\s*['\"]?)[^'\"\]\|]+/", "$1{$this->state}", $match[1], 1, $count); |
if ($count < 1) $result = "|state={$this->state}".$match[1]; | if ($count < 1) $result = "|state={$this->state}".$match[1]; | ||
return '{'.'{'."#{$this->magic}:{$this->name}$result".'}'.'}'; | return '{'.'{'."#{$this->magic}:{$this->name}$result".'}'.'}'; | ||
− | + | } | |
# Extend catlinks information to include workflows | # Extend catlinks information to include workflows | ||
Line 216: | Line 222: | ||
global $wgWorkflow; | global $wgWorkflow; | ||
return $wgWorkflow->renderWorkflowInfo(parent::getCategories()); | return $wgWorkflow->renderWorkflowInfo(parent::getCategories()); | ||
− | + | } | |
− | + | }'); | |
# Replace user's skin with a WorkflowSkin replica | # Replace user's skin with a WorkflowSkin replica | ||
$wgUser->mSkin = new WorkflowSkin(); | $wgUser->mSkin = new WorkflowSkin(); | ||
foreach (array_keys(get_class_vars($class)) as $k) $wgUser->mSkin->$k = $skin->$k; | foreach (array_keys(get_class_vars($class)) as $k) $wgUser->mSkin->$k = $skin->$k; | ||
− | + | } | |
# Render the workflow info which appears in the catlinks area | # Render the workflow info which appears in the catlinks area | ||
Line 231: | Line 237: | ||
$table = "<table cellpadding='0' cellspacing='0'><tr><td></td><td align='right'>"; | $table = "<table cellpadding='0' cellspacing='0'><tr><td></td><td align='right'>"; | ||
foreach ($this->workflowData as $name => $states) { | foreach ($this->workflowData as $name => $states) { | ||
− | $title = Title::makeTitle(NS_WORKFLOW,$name); | + | $title = Title::makeTitle(NS_WORKFLOW, $name); |
$catlinks .= "$table<a href='{$title->getLocalURL()}'>$name</a>: </td><td>"; | $catlinks .= "$table<a href='{$title->getLocalURL()}'>$name</a>: </td><td>"; | ||
$current = 0; | $current = 0; | ||
Line 242: | Line 248: | ||
$catlinks .= "$sep<a class='$class' href='{$title->getLocalURL()}'>$state</a>"; | $catlinks .= "$sep<a class='$class' href='{$title->getLocalURL()}'>$state</a>"; | ||
$sep = ' → '; | $sep = ' → '; | ||
− | + | } | |
else $current = $state; | else $current = $state; | ||
− | + | } | |
$table = "</td></tr><tr><td></td><td align='right'>"; | $table = "</td></tr><tr><td></td><td align='right'>"; | ||
− | + | } | |
$catlinks .= "</td></tr></table>\n"; | $catlinks .= "</td></tr></table>\n"; | ||
− | + | } | |
return $catlinks; | return $catlinks; | ||
− | + | } | |
# Return just the catlinks to the client after updating a tag state | # Return just the catlinks to the client after updating a tag state | ||
# - the article is updated here if replacement text has been set | # - the article is updated here if replacement text has been set | ||
function returnCatlinks() { | function returnCatlinks() { | ||
− | global $wgUser,$wgOut,$wgTitle; | + | global $wgUser, $wgOut, $wgTitle; |
if ($this->text) { | if ($this->text) { | ||
$article = new Article($wgTitle); | $article = new Article($wgTitle); | ||
− | $article->doEdit($this->text,wfMsg('workflowStateUpdated',$this->name,$this->state),EDIT_UPDATE); | + | $article->doEdit($this->text, wfMsg('workflowStateUpdated', $this->name, $this->state), EDIT_UPDATE); |
− | + | } | |
$skin = $wgUser->getSkin(); | $skin = $wgUser->getSkin(); | ||
$catlinks = is_object($skin) ? $skin->getCategories() : 'Error: no skin!'; | $catlinks = is_object($skin) ? $skin->getCategories() : 'Error: no skin!'; | ||
Line 268: | Line 274: | ||
echo($catlinks); | echo($catlinks); | ||
return false; | return false; | ||
− | + | } | |
# Make necessary Javascript functions available to the page | # Make necessary Javascript functions available to the page | ||
function addJS() { | function addJS() { | ||
− | global $wgOut,$wgJsMimeType,$wgWorkflowUpdateDelay; | + | global $wgOut, $wgJsMimeType, $wgWorkflowUpdateDelay; |
$wgOut->addScript("<script type='$wgJsMimeType'> | $wgOut->addScript("<script type='$wgJsMimeType'> | ||
var workflowData = []; | var workflowData = []; | ||
Line 282: | Line 288: | ||
var state = workflowData[name][workflowLastState]; | var state = workflowData[name][workflowLastState]; | ||
sajax_do_call('{$this->magic}',[wgPageName,name,state],document.getElementById('catlinks')); | sajax_do_call('{$this->magic}',[wgPageName,name,state],document.getElementById('catlinks')); | ||
− | + | } | |
function workflowSwitchState(name,dir) { | function workflowSwitchState(name,dir) { | ||
clearTimeout(workflowUpdate); | clearTimeout(workflowUpdate); | ||
Line 293: | Line 299: | ||
document.getElementById('workflow-'+name+'-'+state).setAttribute('style',''); | document.getElementById('workflow-'+name+'-'+state).setAttribute('style',''); | ||
if (workflowLastState != state) workflowUpdate = setTimeout('workflowUpdateState(\"'+name+'\")',$wgWorkflowUpdateDelay); | if (workflowLastState != state) workflowUpdate = setTimeout('workflowUpdateState(\"'+name+'\")',$wgWorkflowUpdateDelay); | ||
− | + | } | |
</script>"); | </script>"); | ||
− | + | } | |
# If it's a workflow-related ajax call, don't use dispatcher (because we need the catlinks generated by normal page render) | # If it's a workflow-related ajax call, don't use dispatcher (because we need the catlinks generated by normal page render) | ||
Line 302: | Line 308: | ||
global $wgUseAjax,$wgHooks; | global $wgUseAjax,$wgHooks; | ||
if ($wgUseAjax && $_REQUEST['action'] == 'ajax' && $_REQUEST['rs'] == $this->magic && is_array($_REQUEST['rsargs'])) { | if ($wgUseAjax && $_REQUEST['action'] == 'ajax' && $_REQUEST['rs'] == $this->magic && is_array($_REQUEST['rsargs'])) { | ||
− | list($_REQUEST['title'],$this->name,$this->state) = $_REQUEST['rsargs']; | + | list($_REQUEST['title'], $this->name,$this->state) = $_REQUEST['rsargs']; |
− | $wgHooks['ParserBeforeStrip'][] = array($this,'updateState'); | + | $wgHooks['ParserBeforeStrip'][] = array($this, 'updateState'); |
− | $wgHooks['OutputPageBeforeHTML'][] = array($this,'returnCatlinks'); | + | $wgHooks['OutputPageBeforeHTML'][] = array($this, 'returnCatlinks'); |
$_REQUEST['action'] = 'render'; | $_REQUEST['action'] = 'render'; | ||
− | + | } | |
$this->pagename = $_REQUEST['title']; | $this->pagename = $_REQUEST['title']; | ||
$this->text = ''; | $this->text = ''; | ||
− | + | } | |
# Needed in some versions to prevent Special:Version from breaking | # Needed in some versions to prevent Special:Version from breaking | ||
Line 315: | Line 321: | ||
# Set up the magic words | # Set up the magic words | ||
− | function languageGetMagic(&$magicWords,$langCode = 0) { | + | function languageGetMagic(&$magicWords, $langCode = 0) { |
− | $magicWords[$this->magic] = array( | + | $magicWords[$this->magic] = array($langCode, $this->magic); |
return true; | return true; | ||
− | + | } | |
− | + | } | |
$wgWorkflow = new Workflow(); | $wgWorkflow = new Workflow(); | ||
</php> | </php> |
Revision as of 11:27, 23 July 2008
<php> <?php
- Extension:Workflow
- - Licenced under LGPL (http://www.gnu.org/copyleft/lesser.html)
- - Author: User:Nad
- - Started: 2007-10-06
if (!defined('MEDIAWIKI')) die('Not an entry point.');
define('WORKFLOW_VERSION','0.0.12, 2007-10-27');
$wgWorkflowUpdateDelay = 1000; # Delay in milliseconds after clicking state before Ajax update is made
$wgExtensionCredits['parserhook'][] = $wgExtensionCredits['specialpage'][] = array( 'name' => 'Workflow', 'author' => 'User:Nad', 'description' => 'Adds the ability for articles to be part of workflow sequences and easily moved dynamically between phases in the sequence using AJAX.', 'url' => 'http://www.mediawiki.org/wiki/Extension:Workflow', 'version' => WORKFLOW_VERSION );
- Define a new specialpage for displaying a list of workflows
require_once "$IP/includes/SpecialPage.php"; class SpecialWorkflow extends SpecialPage {
function SpecialWorkflow() { SpecialPage::SpecialPage(wfMsg('workflow'), , true, false, false, false); }
# Render list function execute($param) { global $wgParser, $wgOut; $wgParser->disableCache(); $this->setHeaders(); $wgOut->addWikiText('Not done yet... discussion at Extension talk:Workflow.php', true); } }
- Define main workflow class containing all the functionality
class Workflow {
var $magic; # magic word used for the workflow parser-function (set from messages) var $state; # state to update a workflow to in an ajax update request var $name; # name of the workflow to update var $pagename; # the name of the current page (in which the workflows reside) var $title; var $workflowData = array();
# Constructor function Workflow() { global $wgHooks, $wgSiteNotice, $wgExtensionFunctions, $wgWorkflowMagic, $wgExtraNamespaces;
# Require NS_WORKFLOW to be defined before installing parser-function or javascript etc if (!defined('NS_WORKFLOW')) {
$wgSiteNotice .= '
';
return; }
# The parser-function name, special-page name and links all use the word defined in $wgExtraNamespaces[NS_WORKFLOW] #$this->magic = $wgContLang->getNsText(NS_WORKFLOW); $this->magic = $wgExtraNamespaces[NS_WORKFLOW]; # $wgContLang doesn't exist yet
# Reserve the magic word for use as a parser-function $wgHooks['LanguageGetMagic'][] = array($this, 'languageGetMagic');
# If it's a workflow-related ajax call, don't use dispatcher (because we need the catlinks generated by normal page render) # - this sets the state, name, pagename and update properties $this->bypassAjaxDispatcher();
# Add the extension's setup function to the list to be called after the environment is up and running $wgExtensionFunctions[] = array($this, 'setup'); }
# Setup function setup() { global $wgParser, $wgLanguageCode, $wgMessageCache, $wgContLang; $cat = $wgContLang->getNsText(NS_CATEGORY);
# Add the messages used (todo: move into i18n) if ($wgLanguageCode == 'en') { $wgMessageCache->addMessages(array( 'workflow' => $this->magic, # NOTE: the parser-function, special-page and link-rendering all use this word 'workflowMissingNamespace' => 'The NS_WORKFLOW namespace must be defined. The workflow extension is disabled.', 'workflowStateUpdated' => "[[{$this->magic}:$1|$1 {$this->magic}]] state set to $2." )); }
# Add the specialpage to the environment SpecialPage::addPage(new SpecialWorkflow());
# Add the parser-function hook $wgParser->setFunctionHook($this->magic, array($this, 'expandMagic'));
# Add the client-side scripts for changing states $this->addJS(); }
# Expand the #workflow to reveal the current state and hide the others and add javascript # - note the hidden states mustn't be rendered because they contain categorisation links which shouldn't be processed function expandMagic(&$parser) { global $wgUser, $wgJsMimeType, $wgContLang; $parser->disableCache(); $tmpl = $wgContLang->getNsText(NS_TEMPLATE); $cat = $wgContLang->getNsText(NS_CATEGORY); $wf = $this->magic;
# Extend catlinks information to include workflows $this->extendCatlinks();
# Populate $argv with both named and numeric parameters $args =; $argv = array(); $items = array(); $name = 'Untitled'; foreach (func_get_args() as $arg) if (!is_object($arg)) { $args .= "|$arg"; if (preg_match('/^(.+?)\\s*=\\s*(.+)$/',$arg,$match)) $argv[$match[1]] = $match[2]; else $argv[] = $arg; } $name = $argv[0]; $this->workflowData[$name] = array(0); $current = isset($argv['state']) ? $argv['state'] : false;
# Make a clone of the parser for parsing without affecting LinkHolder or catlinks arrays $psr = new parser; $opt = ParserOptions::newFromUser($wgUser);
# Get the list of workflow states from the Workflow article # NOTE: this method of using the parser to get the links corrupts the order, so a preg_match_all may be preferable $states = array(); $title = Title::newFromtext($name,NS_WORKFLOW); $edit = $title->userCan('edit'); $url = $title->getLocalUrl(); $href = "href='$url'"; $anchor = "$wf:$name"; if (is_object($title) && $title->exists()) { $article = new Article($title); if (preg_match_all('/^\\*\\s*\\[{2}\\s*(.+?:)?\\s*(.+?)\\s*\\]{2}/m', $article->getContent(), $match)) $states = $match[2]; else $anchor .= " (".wfMsg('workflowMissingContent').")"; } else $href .= " class='new'"; $html = "<a $href title='$anchor'>$anchor</a>";
# Transclude each (use a parser clone for the ones which aren't current to avoid categorisation) if (count($states)) { if ($edit) {
$left = "<a href='javascript:;'><</a>"; $right = "<a href='javascript:;'>></a>";
}
else $left = $right = ""; # no menu buttons if not allowed to edit $html = "
$data = ; $ci = 0; foreach ($states as $i => $dbk) { $i++; $stitle = Title::newFromText($dbk, NS_TEMPLATE); $surl = $stitle->getLocalUrl(); $state = $stitle->getText(); $anchor = preg_replace('|^.+/|',,$state); $data .= ",'$state'"; $style = 'display:none'; $p =& $psr; # use local parser by default $this->workflowData[$name][] = $state; if ($current === false) $current = $state; # make current default to first item name $wikitext = $stitle->exists() ? '{'.'{'."$state|state=$state$args}".'}' : "$tmpl:$state"; # transclude or render a red-link if ($state == $current) { $wikitext .= "$cat:$state"; # if state is current, add a category link $style = ; $p =& $parser; # use the global parser so catlinks are updated $ci = $i; } $content = $p->parse($wikitext,$title,$opt,false,$state != $current)->getText();
# Append the menu to the state
$html .= "$content | ||
<a href='$surl' title='$tmpl:$state'>$anchor</a> |
}
$html .= "<script type='$wgJsMimeType'>workflowData['$name']=[$ci$data];</script>\n";
$this->workflowData[$name][0] = $ci; }
return array($html, 'isHTML' => true, 'noparse' => true); }
# Update the current state of a workflow item in the requested article # - the actual article edit is done in returnCatlinks after all parsin finished # - this disables the parser-cache if the content has changed function updateState(&$parser, &$text) { $result = preg_replace_callback( "/\\{\\{\\s*#\\s*{$this->magic}\\s*:\\s*{$this->name}\\s*(.*?)\\s*\\}\\}/is", array($this, 'updateStateCallback'), $text, 1, $count ); if ($count) $this->text = $text = $result; $parser->disableCache(); return true; }
# Replacement callback for updating tag state function updateStateCallback($match) { $result = preg_replace("/(state\\s*=\\s*['\"]?)[^'\"\]\|]+/", "$1{$this->state}", $match[1], 1, $count); if ($count < 1) $result = "|state={$this->state}".$match[1]; return '{'.'{'."#{$this->magic}:{$this->name}$result".'}'.'}'; }
# Extend catlinks information to include workflows function extendCatlinks() { static $done = 0; if ($done++) return; global $wgUser; $skin = $wgUser->getSkin();
# Create a new Skin class (WorkflowSkin) by extending the existing one with overridden getCategoryLinks method $class = get_class($skin); eval("class WorkflowSkin extends {$class} ".'{ function getCategories() { global $wgWorkflow; return $wgWorkflow->renderWorkflowInfo(parent::getCategories()); } }');
# Replace user's skin with a WorkflowSkin replica $wgUser->mSkin = new WorkflowSkin(); foreach (array_keys(get_class_vars($class)) as $k) $wgUser->mSkin->$k = $skin->$k; }
# Render the workflow info which appears in the catlinks area function renderWorkflowInfo(&$catlinks) { if (count($this->workflowData)) { //$title = Title::makeTitle(NS_SPECIAL,wfMsg('workflow'));
//$table = "
<a href='{$title->getLocalURL()}'>".wfMsg('workflow')."</a>: | ";
$table = "
} return $catlinks; } # Return just the catlinks to the client after updating a tag state # - the article is updated here if replacement text has been set function returnCatlinks() { global $wgUser, $wgOut, $wgTitle; if ($this->text) { $article = new Article($wgTitle); $article->doEdit($this->text, wfMsg('workflowStateUpdated', $this->name, $this->state), EDIT_UPDATE); } $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; } # Make necessary Javascript functions available to the page function addJS() { global $wgOut, $wgJsMimeType, $wgWorkflowUpdateDelay; $wgOut->addScript("<script type='$wgJsMimeType'> var workflowData = []; var workflowUpdate = 0; var workflowLastState = 0; function workflowUpdateState(name) { clearTimeout(workflowUpdate); workflowLastState = workflowData[name][0]; var state = workflowData[name][workflowLastState]; sajax_do_call('{$this->magic}',[wgPageName,name,state],document.getElementById('catlinks')); } function workflowSwitchState(name,dir) { clearTimeout(workflowUpdate); document.getElementById('workflow-'+name+'-'+workflowData[name][0]).setAttribute('style','display:none'); if (workflowLastState == 0) workflowLastState = workflowData[name][0]; workflowData[name][0] += dir; if (workflowData[name][0] < 1) workflowData[name][0] = workflowData[name].length-1; if (workflowData[name][0] > workflowData[name].length-1) workflowData[name][0] = 1; var state = workflowData[name][0]; document.getElementById('workflow-'+name+'-'+state).setAttribute('style',); if (workflowLastState != state) workflowUpdate = setTimeout('workflowUpdateState(\"'+name+'\")',$wgWorkflowUpdateDelay); } </script>"); } # If it's a workflow-related ajax call, don't use dispatcher (because we need the catlinks generated by normal page render) # - this sets the state, name, pagename and update properties function bypassAjaxDispatcher() { global $wgUseAjax,$wgHooks; if ($wgUseAjax && $_REQUEST['action'] == 'ajax' && $_REQUEST['rs'] == $this->magic && is_array($_REQUEST['rsargs'])) { list($_REQUEST['title'], $this->name,$this->state) = $_REQUEST['rsargs']; $wgHooks['ParserBeforeStrip'][] = array($this, 'updateState'); $wgHooks['OutputPageBeforeHTML'][] = array($this, 'returnCatlinks'); $_REQUEST['action'] = 'render'; } $this->pagename = $_REQUEST['title']; $this->text = ; } # Needed in some versions to prevent Special:Version from breaking function __toString() { return 'Workflow'; } # Set up the magic words function languageGetMagic(&$magicWords, $langCode = 0) { $magicWords[$this->magic] = array($langCode, $this->magic); return true; } } $wgWorkflow = new Workflow(); </php> |