From OrganicDesign
<?php
# Extension:Workflow
# - Licenced under LGPL (http://www.gnu.org/copyleft/lesser.html)
# - Author: [http://www.organicdesign.co.nz/nad User:Nad]
# - Started: 2007-11-04
define('PACKAGES_VERSION','0.0.6, 2007-11-13');
$wgExtensionCredits['parserhook'][] = $wgExtensionCredits['specialpage'][] = array(
'name' => 'Packages',
'author' => '[http://www.organicdesign.co.nz/nad User:Nad]',
'description' => 'Create packages of templates and other articles from remote wiki\'s. The resulting packages are PHP files which can be added or removed like a normal extension without affecting the database.',
'url' => 'http://www.mediawiki.org/wiki/Extension:Packages',
'version' => PACKAGES_VERSION
);
$wgPackageList = array();
$wgPackagesDir = dirname(__FILE__);
# Special page for managing list of packages
if (defined('MEDIAWIKI')) {
require_once "$IP/includes/SpecialPage.php";
class SpecialPackages extends SpecialPage {
function SpecialPackages() {
SpecialPage::SpecialPage('Packages','',true,false,false,false);
}
# Render list
function execute($param) {
global $wgParser,$wgOut,$wgScriptPath,$wgPackagesDir;
$wgParser->disableCache();
$this->setHeaders();
$wgOut->addWikiText("== Packages available ==\nThese packages of templates are defined in [[MediaWiki:Packages]],
and can be built by running this extension from the command line.\n\n",true);
$wgOut->addWikiText("== Installed packages ==\nThe following packages have been included from LocalSettings.php\n\n",true);
$wgOut->addWikiText("== Download packages ==\nThe following packages have been built and are available for download.\n\n",true);
foreach (glob("$wgPackagesDir/pkg_*") as $package) $wgOut->addWikiText("*[http://www.organicdesign.co.nz/$wgScriptPath/extensions/$package $package]\n");
}
}
}
# Not called from index.php, include commandLine.inc or die if called from web directly
else {
if (isset($_SERVER) && array_key_exists('REQUEST_METHOD',$_SERVER)) die("Not an entry point");
$IP = ereg_replace('.extensions.?','',$argv[1]);
$cli = "$IP/maintenance/commandLine.inc";
if (!file_exists($cli)) die("Couldn't find \"$cli\"! Syntax: php Packages.php path/to/extensions\n");
include($cli);
}
# Define main Packages class which expands the included magic words
class Packages {
# Constructor
function Packages() {
global $wgHooks,$wgExtensionFunctions,$wgPackageList,$wgCommandLineMode;
if ($wgCommandLineMode) $this->build();
# Reserve the magic word for use as a parser-function
$wgHooks['LanguageGetMagic'][] = array($this,'languageGetMagic');
# 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,$wgPackageList;
# Add the messages used (todo: move into i18n)
if ($wgLanguageCode == 'en') {
$wgMessageCache->addMessages(array(
));
}
# Add the specialpage to the environment
SpecialPage::addPage(new SpecialPackages());
# Add a parser-function hook for each package which returns the package content with variables replaced
foreach (array_keys($wgPackageList) as $package) {
$wgParser->setFunctionHook($package,create_function('','
global $wgPackageList;
$args = func_get_args();
$parser = array_shift($args);
$text = $wgPackageList["'.$package.'"][$args[0]];
# todo: if package item doesn\'t exist, try falling back to article
return $parser->replaceVariables($text,$args,true);
'),SFH_NO_HASH);
}
}
# Needed in some versions to prevent Special:Version from breaking
function __toString() { return 'Packages'; }
# Reserve a magic word for each package
function languageGetMagic(&$magicWords,$langCode = 0) {
global $wgPackageList;
foreach (array_keys($wgPackageList) as $package) $magicWords[$package] = array(0,$package);
return true;
}
# Used to find dependencies within template content
function examineBraces(&$content) {
$braces = array();
$depths = array();
$depth = 1;
$index = 0;
while (preg_match('/\\{\\{\\s*([#a-z0-9_]*)|\\}\\}/is',$content,$match,PREG_OFFSET_CAPTURE,$index)) {
$index = $match[0][1]+2;
if ($match[0][0] == '}}') {
$brace =& $braces[$depths[$depth-1]];
$brace['LENGTH'] = $match[0][1]-$brace['OFFSET']+2;
$brace['DEPTH'] = $depth--;
}
else {
$depths[$depth++] = count($braces);
$braces[] = array(
'NAME' => $match[1][0],
'OFFSET' => $match[0][1]
);
}
}
return $braces;
}
# Build the packages defined in the MediaWiki:Packages article
function build() {
global $wgEnableScaryTranscluding,$wgPackagesDir;
$wgEnableScaryTranscluding = true;
$parser = new Parser;
# Read in the package definitions from MediaWiki:Packages
$packages = 'Packages';
$title = Title::newFromText($packages,NS_MEDIAWIKI);
if (!is_object($title) || !$title->exists()) die("No MediaWiki:$packages article!\n");
$article = new Article($title);
$text = $article->getContent();
# Extract the package sections in the definitions article and loop through them building a file for each
# NOTE: there is an existing function to do with this that we should checkout and/or test called extractSections() in Parser.php
# Extension:Selenium is using preg_match_all |^={2,}\s*(.+?)\s*={2,}(.+?</selenium>)|ms
preg_match_all('/=+\\s*(.+?)\\s*=+([^=]+)/',$text,$m1);
while (count($m1[1])) {
# Initialise current package data
$package = array_shift($m1[1]);
$content = "<?\n# $package built by Extension:Packages.php\n";
# Extract the articles listed for this package and loop through them (as a reducing stack)
preg_match_all('/\\[{2}(.+?)(\\|(.+?))?\\]{2}/',array_shift($m1[2]),$m2);
$links = array();
while (count($m2[1])) {
# Get the content of the current article (local or interwiki)
$anchor = array_shift($m2[3]);
$title = array_shift($m2[1]);
if ($anchor == '') $anchor = $title;
$title = Title::newFromText($title);
$article = new Article($title);
$text = $title->isLocal() ? $article->getContent() : $parser->interwikiTransclude($title,'raw');
# Push any valid dependency templates found in this article's content onto the end of the currently reducing stack
if (0) foreach ($this->examineBraces($text) as $template) {
$anchor = 'foo'; # todo: rename the dependency according to the package and namespace etc
if ($anchor) {
$m2[1][] = $template;
$m2[3][] = $anchor;
# todo: must change references in content to transformed name
}
}
# Append content to the current package data
$text = str_replace("'","\\'",$text);
$content .= "\$wgPackageList['$package']['$anchor']='$text';\n";
}
# Write the built package data to file in same dir as script
file_put_contents("$wgPackagesDir/pkg_$package.php",$content);
print "pkg_$package.php built\n";
}
}
}
$wgPackages = new Packages();