Difference between revisions of "Extension:Workflow.php"
(Comments added for proposed changes to workflow categorization) |
(new dev) |
||
Line 1: | Line 1: | ||
− | |||
− | |||
<?php | <?php | ||
− | + | /** | |
− | + | * Extension:Workflow | |
− | + | *{{Category:Extensions|Workflow}}{{php}}{{Category:Extensions created with Template:Extension}} | |
− | + | * @package MediaWiki | |
+ | * @subpackage Extensions | ||
+ | * @author Aran Dunkley [http://www.organicdesign.co.nz/nad User:Nad] | ||
+ | * @licence GNU General Public Licence 2.0 or later | ||
+ | * Started: 2007-10-06 | ||
+ | */ | ||
+ | if (!defined('MEDIAWIKI')) die("Not an entry point."); | ||
− | + | define('WORKFLOW_VERSION', "0.1.0, 2008-11-07"); | |
− | |||
− | define('WORKFLOW_VERSION', | ||
$wgWorkflowUpdateDelay = 1000; # Delay in milliseconds after clicking state before Ajax update is made | $wgWorkflowUpdateDelay = 1000; # Delay in milliseconds after clicking state before Ajax update is made | ||
$wgExtensionCredits['parserhook'][] = $wgExtensionCredits['specialpage'][] = array( | $wgExtensionCredits['parserhook'][] = $wgExtensionCredits['specialpage'][] = array( | ||
− | 'name' => | + | 'name' => "Workflow", |
− | 'author' => | + | 'author' => "[http://www.organicdesign.co.nz/nad User:Nad]", |
− | 'description' => | + | 'description' => "Adds the ability for articles to be part of workflow sequences and easily moved |
− | dynamically between phases in the sequence using AJAX. | + | dynamically between phases in the sequence using AJAX.", |
− | 'url' => | + | 'url' => "http://www.mediawiki.org/wiki/Extension:Workflow", |
'version' => WORKFLOW_VERSION | 'version' => WORKFLOW_VERSION | ||
); | ); | ||
− | + | /** | |
+ | * Define a new specialpage for displaying a list of workflows | ||
+ | */ | ||
require_once "$IP/includes/SpecialPage.php"; | require_once "$IP/includes/SpecialPage.php"; | ||
class SpecialWorkflow extends SpecialPage { | class SpecialWorkflow extends SpecialPage { | ||
Line 35: | Line 39: | ||
$wgParser->disableCache(); | $wgParser->disableCache(); | ||
$this->setHeaders(); | $this->setHeaders(); | ||
− | $wgOut->addWikiText( | + | $wgOut->addWikiText("Not done yet... discussion at [[Extension talk:Workflow.php]]", true); |
} | } | ||
} | } | ||
− | + | /** | |
+ | * Define main workflow class containing all the functionality | ||
+ | */ | ||
class Workflow { | class Workflow { | ||
Line 46: | Line 52: | ||
var $name; # name of the workflow to update | var $name; # name of the workflow to update | ||
var $pagename; # the name of the current page (in which the workflows reside) | var $pagename; # the name of the current page (in which the workflows reside) | ||
+ | var $cat; # lcoal lang name for "Category" | ||
var $title; | var $title; | ||
var $workflowData = array(); | var $workflowData = array(); | ||
− | + | /** | |
+ | * Constructor | ||
+ | */ | ||
function Workflow() { | function Workflow() { | ||
− | global $wgHooks, $wgSiteNotice, $wgExtensionFunctions, $wgWorkflowMagic, $wgExtraNamespaces; | + | global $wgHooks, $wgSiteNotice, $wgExtensionFunctions, $wgWorkflowMagic, $wgExtraNamespaces, $wgAjaxExportList; |
# 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 | ||
if (!defined('NS_WORKFLOW')) { | if (!defined('NS_WORKFLOW')) { | ||
− | $wgSiteNotice .= | + | $wgSiteNotice .= "<div class='usermessage'>The NS_WORKFLOW namespace must be defined. Extension is disabled.</div>"; |
return; | return; | ||
} | } | ||
Line 62: | Line 71: | ||
#$this->magic = $wgContLang->getNsText(NS_WORKFLOW); | #$this->magic = $wgContLang->getNsText(NS_WORKFLOW); | ||
$this->magic = $wgExtraNamespaces[NS_WORKFLOW]; # $wgContLang doesn't exist yet | $this->magic = $wgExtraNamespaces[NS_WORKFLOW]; # $wgContLang doesn't exist yet | ||
+ | |||
+ | $wgAjaxExportList[] = $this->magic; | ||
# Reserve the magic word for use as a parser-function | # Reserve the magic word for use as a parser-function | ||
Line 74: | Line 85: | ||
} | } | ||
− | + | /** | |
+ | * Extension setup | ||
+ | */ | ||
function setup() { | function setup() { | ||
global $wgParser, $wgLanguageCode, $wgMessageCache, $wgContLang; | global $wgParser, $wgLanguageCode, $wgMessageCache, $wgContLang; | ||
− | |||
+ | $this->cat = $wgContLang->getNsText(NS_CATEGORY); | ||
+ | |||
# Add the messages used (todo: move into i18n) | # Add the messages used (todo: move into i18n) | ||
if ($wgLanguageCode == 'en') { | if ($wgLanguageCode == 'en') { | ||
$wgMessageCache->addMessages(array( | $wgMessageCache->addMessages(array( | ||
'workflow' => $this->magic, # NOTE: the parser-function, special-page and link-rendering all use this word | 'workflow' => $this->magic, # NOTE: the parser-function, special-page and link-rendering all use this word | ||
− | 'workflowStateUpdated' => "[[{$this->magic}:$1|$1 {$this->magic}]] state set to [[$cat:$2|$2]]." | + | 'workflowStateUpdated' => "[[{$this->magic}:$1|$1 {$this->magic}]] state set to [[{$this->cat}:$2|$2]]." |
)); | )); | ||
} | } | ||
Line 97: | Line 111: | ||
} | } | ||
− | + | /** | |
− | + | * 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) { | 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); | ||
− | |||
$wf = $this->magic; | $wf = $this->magic; | ||
Line 116: | Line 131: | ||
foreach (func_get_args() as $arg) if (!is_object($arg)) { | foreach (func_get_args() as $arg) if (!is_object($arg)) { | ||
$args .= "|$arg"; | $args .= "|$arg"; | ||
− | if (preg_match( | + | if (preg_match("%^(.+?)\\s*=\\s*(.+)$%", $arg, $match)) $argv[$match[1]] = $match[2]; else $argv[] = $arg; |
} | } | ||
$name = $argv[0]; | $name = $argv[0]; | ||
Line 128: | Line 143: | ||
# Get the list of workflow states from the Workflow article | # 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 | # NOTE: this method of using the parser to get the links corrupts the order, so a preg_match_all may be preferable | ||
− | $states = | + | $states = $this->loadStates($name); |
− | $title = Title::newFromtext($name,NS_WORKFLOW); | + | $title = Title::newFromtext($name, NS_WORKFLOW); |
$edit = $title->userCan('edit'); | $edit = $title->userCan('edit'); | ||
$url = $title->getLocalUrl(); | $url = $title->getLocalUrl(); | ||
Line 135: | Line 150: | ||
$anchor = "$wf:$name"; | $anchor = "$wf:$name"; | ||
if (is_object($title) && $title->exists()) { | if (is_object($title) && $title->exists()) { | ||
− | + | if (count($states)<1) $anchor .= " (".wfMsg('workflowMissingContent').")"; | |
− | if ( | + | } else $href .= " class='new'"; |
− | |||
− | } | ||
− | |||
$html = "<a $href title='$anchor'>$anchor</a>"; | $html = "<a $href title='$anchor'>$anchor</a>"; | ||
Line 150: | Line 162: | ||
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'>"; | ||
− | $data = | + | $data = ""; |
$ci = 0; | $ci = 0; | ||
− | foreach ($states as $i => $ | + | foreach ($states as $i => $state) { |
$i++; | $i++; | ||
− | $stitle = Title::newFromText($ | + | $stitle = Title::newFromText($state, NS_TEMPLATE); |
$surl = $stitle->getLocalUrl(); | $surl = $stitle->getLocalUrl(); | ||
− | |||
− | |||
$data .= ",'$state'"; | $data .= ",'$state'"; | ||
− | $style = | + | $style = "display:none"; |
$p =& $psr; # use local parser by default | $p =& $psr; # use local parser by default | ||
+ | $p =& $parser; # use local parser by default | ||
$this->workflowData[$name][] = $state; | $this->workflowData[$name][] = $state; | ||
if ($current === false) $current = $state; # make current default to first item name | 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 | $wikitext = $stitle->exists() ? '{'.'{'."$state|state=$state$args}".'}' : "[[$tmpl:$state]]"; # transclude or render a red-link | ||
− | + | if (0&&$state == $current) { | |
− | + | $wikitext .= "[[{$this->cat}:$state]]"; # if state is current, add a category link | |
− | + | $style = ""; | |
− | |||
− | 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 | $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(); |
# Append the menu to the state | # Append the menu to the state | ||
Line 189: | Line 196: | ||
} | } | ||
− | + | /** | |
− | + | * Load states into workflowData property for passed workflow name | |
− | + | */ | |
+ | function loadStates($name) { | ||
+ | $states = array(); | ||
+ | $title = Title::newFromText($name, NS_WORKFLOW); | ||
+ | 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 = $this->workflowData[$name] = $match[2]; | ||
+ | } | ||
+ | } | ||
+ | return $states; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Update the current state of a workflow item in the requested article | ||
+ | * - the actual article edit is done in returnCatlinks after all parsing finished | ||
+ | * - this disables the parser-cache | ||
+ | */ | ||
function updateState(&$parser, &$text) { | function updateState(&$parser, &$text) { | ||
− | $ | + | $this->loadStates($this->name); |
− | + | static $i = 0; | |
− | + | if ($i++ < 1 && isset($this->workflowData[$this->name]) && count($this->workflowData[$this->name]) > 1) { | |
− | $text, | + | $cats = $this->workflowData[$this->name]; |
− | + | $cats = join('|', $cats); | |
− | $ | + | #print "xxxx$text"; #preg_replace("%\[\[{$this->cat}:($cats)\]\]%", "", $text); |
− | + | $parser->disableCache(); | |
− | + | $this->text .= $text."\n\n"; | |
− | + | } | |
return true; | return true; | ||
} | } | ||
− | + | /** | |
− | + | * Extend catlinks information to include workflows | |
− | + | */ | |
− | |||
− | |||
− | |||
− | |||
− | |||
function extendCatlinks() { | function extendCatlinks() { | ||
static $done = 0; | static $done = 0; | ||
Line 233: | Line 252: | ||
} | } | ||
− | + | /** | |
+ | * Render the workflow info which appears in the catlinks area | ||
+ | */ | ||
function renderWorkflowInfo(&$catlinks) { | function renderWorkflowInfo(&$catlinks) { | ||
if (count($this->workflowData)) { | if (count($this->workflowData)) { | ||
Line 243: | Line 264: | ||
$catlinks .= "$table<a href='{$title->getLocalURL()}'>$name</a>: </td><td>"; | $catlinks .= "$table<a href='{$title->getLocalURL()}'>$name</a>: </td><td>"; | ||
$current = 0; | $current = 0; | ||
− | $sep = | + | $sep = " "; |
foreach ($states as $i => $state) { | foreach ($states as $i => $state) { | ||
if ($current) { | if ($current) { | ||
Line 250: | Line 271: | ||
$class .= $title->exists() ? '' : ' new'; | $class .= $title->exists() ? '' : ' new'; | ||
$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; | ||
Line 261: | Line 282: | ||
} | } | ||
− | + | /** | |
− | + | * Return just the catlinks to the client after updating a tag state | |
− | function returnCatlinks() { | + | * - the article is updated here if replacement text has been set |
+ | */ | ||
+ | function returnCatlinks(&$out, &$text) { | ||
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() : | + | $catlinks = is_object($skin) ? $skin->getCategories() : "Error: no skin!"; |
$wgOut->disable(); | $wgOut->disable(); | ||
wfResetOutputBuffers(); | wfResetOutputBuffers(); | ||
header("Cache-Control: no-cache, must-revalidate"); | header("Cache-Control: no-cache, must-revalidate"); | ||
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); | header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); | ||
− | + | print "<pre>text\n{$this->text}</pre>"; | |
+ | print $catlinks; | ||
return false; | return false; | ||
} | } | ||
− | + | /** | |
+ | * Make necessary Javascript functions available to the page | ||
+ | */ | ||
function addJS() { | function addJS() { | ||
global $wgOut, $wgJsMimeType, $wgWorkflowUpdateDelay; | global $wgOut, $wgJsMimeType, $wgWorkflowUpdateDelay; | ||
Line 306: | Line 332: | ||
} | } | ||
− | + | /** | |
− | + | * 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() { | function bypassAjaxDispatcher() { | ||
− | global $wgUseAjax,$wgHooks; | + | global $wgUseAjax, $wgHooks; |
− | if ($wgUseAjax && $ | + | if ($wgUseAjax |
− | list($ | + | && isset($_GET['action']) |
− | $wgHooks['ParserBeforeStrip'][] = array($this, 'updateState'); | + | && $_GET['action'] == 'ajax' |
+ | && isset($_GET['rs']) | ||
+ | && $_GET['rs'] == $this->magic | ||
+ | && isset($_GET['rsargs']) | ||
+ | && is_array($_GET['rsargs']) | ||
+ | ) { | ||
+ | list($title, $this->name, $this->state) = $_GET['rsargs']; | ||
+ | $wgHooks['ParserBeforeStrip'][] = array($this, 'updateState'); | ||
$wgHooks['OutputPageBeforeHTML'][] = array($this, 'returnCatlinks'); | $wgHooks['OutputPageBeforeHTML'][] = array($this, 'returnCatlinks'); | ||
− | $_REQUEST | + | $_GET = $_REQUEST = array('title' => $title, 'action' => 'view'); |
} | } | ||
− | $this->pagename = $_REQUEST['title']; | + | $this->pagename = isset($_REQUEST['title']) ? $_REQUEST['title'] : ''; |
$this->text = ''; | $this->text = ''; | ||
} | } | ||
− | + | /** | |
+ | * Needed in some versions to prevent Special:Version from breaking | ||
+ | */ | ||
function __toString() { return 'Workflow'; } | function __toString() { return 'Workflow'; } | ||
− | + | /** | |
+ | * Set up the magic words | ||
+ | */ | ||
function languageGetMagic(&$magicWords, $langCode = 0) { | function languageGetMagic(&$magicWords, $langCode = 0) { | ||
$magicWords[$this->magic] = array($langCode, $this->magic); | $magicWords[$this->magic] = array($langCode, $this->magic); | ||
return true; | return true; | ||
} | } | ||
− | |||
} | } | ||
$wgWorkflow = new Workflow(); | $wgWorkflow = new Workflow(); | ||
− | |||
− |
Revision as of 09:06, 7 November 2008
<?php /**
* Extension:Workflow *
Template:PhpCategory:Extensions created with Template:Extension
* @package MediaWiki * @subpackage Extensions * @author Aran Dunkley User:Nad * @licence GNU General Public Licence 2.0 or later * Started: 2007-10-06 */
if (!defined('MEDIAWIKI')) die("Not an entry point.");
define('WORKFLOW_VERSION', "0.1.0, 2008-11-07");
$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 $cat; # lcoal lang name for "Category" var $title; var $workflowData = array();
/** * Constructor */ function Workflow() { global $wgHooks, $wgSiteNotice, $wgExtensionFunctions, $wgWorkflowMagic, $wgExtraNamespaces, $wgAjaxExportList;
# 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
$wgAjaxExportList[] = $this->magic;
# 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'); }
/** * Extension setup */ function setup() { global $wgParser, $wgLanguageCode, $wgMessageCache, $wgContLang;
$this->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 'workflowStateUpdated' => "[[{$this->magic}:$1|$1 {$this->magic}]] state set to [[{$this->cat}:$2|$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); $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 = $this->loadStates($name); $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()) { if (count($states)<1) $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 => $state) { $i++; $stitle = Title::newFromText($state, NS_TEMPLATE); $surl = $stitle->getLocalUrl(); $data .= ",'$state'"; $style = "display:none"; $p =& $psr; # use local parser by default $p =& $parser; # 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 (0&&$state == $current) { $wikitext .= "[[{$this->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); }
/** * Load states into workflowData property for passed workflow name */ function loadStates($name) { $states = array(); $title = Title::newFromText($name, NS_WORKFLOW); 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 = $this->workflowData[$name] = $match[2]; } } return $states; }
/** * Update the current state of a workflow item in the requested article * - the actual article edit is done in returnCatlinks after all parsing finished * - this disables the parser-cache */ function updateState(&$parser, &$text) { $this->loadStates($this->name); static $i = 0; if ($i++ < 1 && isset($this->workflowData[$this->name]) && count($this->workflowData[$this->name]) > 1) { $cats = $this->workflowData[$this->name]; $cats = join('|', $cats); #print "xxxx$text"; #preg_replace("%\[\[{$this->cat}:($cats)\]\]%", "", $text); $parser->disableCache(); $this->text .= $text."\n\n"; } return true; }
/** * 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(&$out, &$text) { 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"); print "text\n{$this->text}"; print $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 && isset($_GET['action']) && $_GET['action'] == 'ajax' && isset($_GET['rs']) && $_GET['rs'] == $this->magic && isset($_GET['rsargs']) && is_array($_GET['rsargs']) ) { list($title, $this->name, $this->state) = $_GET['rsargs']; $wgHooks['ParserBeforeStrip'][] = array($this, 'updateState'); $wgHooks['OutputPageBeforeHTML'][] = array($this, 'returnCatlinks'); $_GET = $_REQUEST = array('title' => $title, 'action' => 'view'); } $this->pagename = isset($_REQUEST['title']) ? $_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(); |