Sandbox
<?php
- Xxx - Xoo Extension Expander
- Part of Xoo (c) 1997-2008 en:User:Zocky, GPL3 applies
-
- An extension registerer with automagic registration for your hooks,
- tags, variables and parser functions
- USAGE:
/* require_once ("Xoo.Xxx.php"); MyExtension::Install( $settings );
class MyExtension extends XxxExtension
{ var $mExtensionCredits = array (...); var $mDefaultSettings = array('foo'=>'bar',...); var $mMessages = array('add-link'=>'Add link'); function setup() { .... if ($success) return true; else return false; }
function var_foo (&$parser) {}; function fn_fpp (&$parser, $arg1, $arg2...) {}; function fl_fqq (&$parser, &$frame, &$args) {}; function fn_frr (&$parser, $arg1, $arg2...) {}; function fl_fss (&$parser, &$frame, &$args) {}; function tag_ftt ($text, $args, &$parser) {}; function hook_fuu (&$parser, ...) {}; }
- /
- Use $this->mSettings to access effective settings.
- TODO:
- function special_foo() for special pages
- XXX_HOOKMAP, and MyExtension->hookMap for hooks and functions with
- names which are not idents in PHP.
-
if ( !defined( 'MEDIAWIKI' ) ) { die( 'This file is a MediaWiki extension, it is not a valid entry point' );} define ('XXX_LATER', false); define ('XXX_UNDEF', null); define ('XXX_FAIL', null);
$wgExtensionFunctions[] = 'wfXxxSetup';
$wgXxxInstaller = new XxxInstaller(); $wgXooInstaller =& $wgXxxInstaller;
$wgXooExtensions = array();
function wfXxxSetup() { #TODO: set credits and stuff global $wgXxxInstaller; $wgXxxInstaller->installExtensions(); }
class Xxx { var $mSettings=array(); var $mDefaultSettings=array(); var $mMessages; function setDefaultSetting($name,$value) { if ($this->mSettings[$name]===XXX_LATER) { $this->mSettings[$name]=$value; } }
function S($name,$value=XXX_UNDEF) { if ($value!==XXX_UNDEF) { $this->mSettings[$name]=$value; return $value; } else { return $this->mSettings[$name]; } }
function normalizeTitle($text) { $t=Title::newFromText($text); if ($t) return $t->getPrefixedDBkey(); else return false; }
static function newExtendedFrame (&$f, &$a=array(), $title=null) { $args = $a; if (isset($f->xvvLocalVariables)) $args = $args + $f->xvvLocalVariables; if ($f->isTemplate()) $args = $args + $f->namedArgs + $f->numberedArgs; elseif (isset($f->args)) $args = $args + $f->args; else $args = $args;
return self::newChildFrame($f,$args,$title); }
static function newChildFrame (&$f, &$a, $title=null) { if (!$title) $title=$f->title; foreach ($a as $k=>$v) { if(!is_object($v)) $a[$k]=(string)$v; } return $f->newCustomChild($a,$f->title); }
static function coallesce() { $args=func_get_args(); foreach($args as $a) { if ($a) return $a; } return false; }
static function extractArgs($args, $unnamedCount=100,$unnamedOffset=1) { $argNames = array_keys(array_splice(func_get_args(),2)); $argNames=$argNames; $ret = array(); $counter=1; for($i=$unnamedOffset;$i<=$args->count;$i++) { if ($args->isNamed($i)) { $key=$args->getKey($i); if (isset($argNames[$key])) $ret[$key]=$args->cropExpandValue($i); elseif ($counter<$unnamedCount) $ret[$counter++]=$args->cropExpand($i); } } return $ret; } static function notFound() { return array('found'=>false); }
static function foundUnlessFail(&$v) { if ($v===XXX_FAIL) return array('found'=>false); else return array($v); }
static function removePrefix(&$v,$prefix) { if (substr($v,0,strlen($prefix))!=$prefix) return false;
$v=substr($v,strlen($prefix)); return true; }
static function dumpVar($v) {
return '
'.var_export($v,true).'
';
}
# TODO: Make configurable
function reportError($t,$where)
{
if ($class)
echo ("ERROR in {$where}): $t
");
else
echo ("ERROR: $t
");
return $t;
}
function makeOrPattern($strings) { $bits=array(); $table=array(); foreach ($strings as $v) { $table[$v]=strlen($v); } arsort($table); foreach ($table as $k=>$v) { $bits[]=preg_quote($k,'/'); } return '(' . join('|',$bits) . ')'; }
function extractStart($regexp, &$text, $which=0, $flags='m') { if (!preg_match('/^'.$regexp.'(.*)$/'.$flags,$text,$m)) return false; if (count($m) < $which) return false;
$rest =& $m[count($m)-1];
if ($which==0) $ret = substr($text,0,strlen($text)-strlen($rest));
else $ret = $m[$which];
$text=$rest;
return $ret;
}
function setupExtension() {}
function _setupExtension() { $varSettings = 'wg'.get_class($this).'Settings';
global $$varSettings;
$this->mSettings = $this->mDefaultSettings;
if (is_array($$varSettings)) { foreach ($$varSettings as $k=>$v) { $this->mSettings[$k]=$v; } } global $wgMessageCache;
if ($this->mMessages) $wgMessageCache->addMessages($this->mMessages);
$this->setupExtension(); return true; } }
class XxxInstaller
{
var $mExtensions=array();
var $mExtensionNames=array();
var $mInstalled=false;
- main entry point
-
public static function Install($classname) { global $wgXxxInstaller; $wgXxxInstaller->registerExtension($classname); }
public static function getExtension($e) { global $wgXooExtensions; return $wgXooExtensions[$e]; }
public function registerExtension ($className)
{
if ($this->mExtensions[$className])
{
warn("Xxx: Extension $className already registered.");
return false;
}
$this->mExtensions[] = $className;
}
public function installExtensions() { if ($this->mInstalled) return true; $this->mInstalled = true; global $wgHooks, $wgParser, $wgXooExtensions;
foreach ($this->mExtensions as $e) { $wgXooExtensions[$e] = new $e; $this->autoRegister($wgXooExtensions[$e]); $wgXooExtensions[$e]->_setupExtension(); }
#register the magic word hook, if needed if (count($this->magicWords)) { $wgHooks['LanguageGetMagic'][] = array( &$this,'hookGetMagicWords'); }
#register variable hooks, if needed if (count($this->customVariables)) { $wgHooks['MagicWordwgVariableIDs'][] = array( &$this,'hookVariableIDs'); $wgHooks['ParserGetVariableValueSwitch'][] = array( &$this,'hookVariableValueSwitch'); };
#register all outstanding hooks foreach($this->hashFunctions as $n=>&$e) { $wgParser->setFunctionHook ( $n, $e ); } foreach($this->parserFunctions as $n=>&$e) { $wgParser->setFunctionHook ( $n, $e, SFH_NO_HASH ); } foreach($this->lazyHashFunctions as $n=>&$e) { $wgParser->setFunctionHook ( $n, $e, SFH_OBJECT_ARGS ); } foreach($this->lazyFunctions as $n=>&$e) { $wgParser->setFunctionHook ( $n, $e, SFH_OBJECT_ARGS | SFH_NO_HASH ); } foreach($this->parserTags as $n=>&$e) { $wgParser->setHook ( $n, $e ); }; }
function autoRegister(&$e) { $methods=get_class_methods($e);
foreach($methods as $m) { $parts=split("_",$m,2); { if (count($parts)==2) { $method = $m; $name=preg_replace('/DOLLAR/','\$',$parts[1]); switch($parts[0]) { case 'var': $this->newVariable($e,$method,$name); break; case 'fn': $this->newHashFunction($e,$method,$name); break; case 'fx': $this->newParserFunction($e,$method,$name); break; case 'fl': $this->newLazyHashFunction($e,$method,$name); break; case 'flx': $this->newLazyFunction($e,$method,$name); break; case 'tag': $this->newParserTag($e,$method,$name); break; case 'hook': $this->newHook($e,$method,$name); } } } } }
# Handle magic words for this extension # --> newMagicWord($word)
var $magicWords=array();
function hookGetMagicWords( &$magicwords) { foreach ($this->magicWords as $w) { $magicwords[$w] = array( 0, $w ); } return true; }
function newMagicWord($word) { $this->magicWords[]=strtolower($word); return strtolower($word); }
# Custom variables # -->newCustomVariable
var $customVariables=array();
function hookVariableIDs(&$wgVariableIDs ) { foreach ($this->customVariables as $k=>$e) { $wgVariableIDs[] = strtolower($k); } return true; }
function hookVariableValueSwitch( &$parser, &$varCache, &$index, &$ret ) { if ($this->customVariables[strtolower($index)]) { $i=strtoupper($index); $ret=$this->customVariables[strtolower($index)][0]->{"var_$i"}($parser,$varCache, $index); return true; } else { return false; }
}
# var_FOO -> FOO function newVariable($e, $method, $name) { $this->customVariables[$this->newMagicWord(strtolower($name))]=array($e,$method); return $name; }
# fn_foo -> {{#foo:}} function var $hashFunctions=array();
function newHashFunction($e,$method,$name) { $name=strtolower($name); $this->hashFunctions[$this->newMagicWord($name)]=array($e,$method); }
# fl_foo {{#foo:}} function, lazy parameters var $lazyHashFunctions=array();
function newLazyHashFunction($e,$method,$name) { $name=strtolower($name); $this->lazyHashFunctions[$this->newMagicWord($name)]=array($e,$method); }
# fnx_foo -> Foo: function var $parserFunctions=array();
function newParserFunction($e,$method,$name) { $name=strtolower($name); $this->parserFunctions[$this->newMagicWord($name)]=array($e,$method); }
# flx_foo Foo:, lazy parameters var $lazyFunctions=array();
function newLazyFunction($e,$method,$name) { $name=strtolower($name); $this->lazyFunctions[$this->newMagicWord($name)]=array($e,$method); }
# tag_ parserTags var $parserTags=array();
function newParserTag($e,$method,$name) { $name=strtolower($name); $this->parserTags[$this->newMagicWord($name)]=array($e,$method); }
# general hooks
function newHook($e,$method,$name)
{
global $wgHooks;
$wgHooks[$name][]=array( &$e, $method );
}
}
- XxxArgs
- Wrapper for preprocessor frame arguments in fl_foo functions.
- usage: $args = new XxxArgs($frame, $args);
-
class XxxArgs
{
var $mFrame = null;
var $mArgs = array();
var $mBits = array();
function __construct(&$frame,&$args)
{
$this->mFrame=&$frame;
$this->mArgs=&$args;
$this->command=$this->trimExpand(0); $this->count=count($this->mArgs)-1; $this->args=array_slice(array_keys($args),1); $this->numbers=$this->args; }
function get($index,$default=null) { if (!$this->exists($index) && $default !== null) return $default; return $this->mArgs[$index]; }
function getRaw($index,$default=) { if (!$this->exists($index)) return $default; return $this->mFrame->expand($this->mArgs[$index], PPFrame::RECOVER_ORIG ); }
function expand($index,$default=)
{
if (!$this->exists($index)) return $default;
return $this->mFrame->expand($this->mArgs[$index]);
}
function cropExpand($index,$default=) { if (!$this->exists($index)) return $default; return $this->cropSpace($this->mFrame->expand($this->mArgs[$index])); }
function trimExpand($index,$default=) { if (!$this->exists($index)) return $default; return trim($this->mFrame->expand($this->mArgs[$index])); }
function cropSpace($text) { $text=preg_replace('/^[\t ]*(\n[ \t]*)?/s',,$text); $text=preg_replace('/[\t ]*(\n[ \t]*)?$/s',,$text); return $text; }
function isNamed($index) { $this->split($index); return $this->mBits[$index]['index']===; }
function isNumbered($index) { $this->split($index); return $this->mBits[$index]['index']!==; }
function getName($index) { return $this->isNamed($index) ? trim($this->mFrame->expand($this->mBits[$index]['name'])) : false; }
function getIndex($index) { return $this->isNumbered($index) ? $this->mBits[$index]['index'] : false; }
function getKey($index) { return $this->isNumbered($index) ? $this->getIndex($index) : $this->getName($index); }
function expandKey($index,$default=) { if (!$this->exists($index)) return $default; return $this->getKey($index); }
function getValue($index,$default=) { if (!$this->exists($index)) return $default; $this->split($index); return $this->mBits[$index]['value']; }
function getRawValue($index,$default=) { if (!$this->exists($index)) return $default; $this->split($index); return $this->mFrame->expand($this->mBits[$index]['value'], PPFrame::RECOVER_ORIG ); }
function expandValue($index,$default=) { if (!$this->exists($index)) return $default; $this->split($index); return $this->mFrame->expand($this->mBits[$index]['value']); }
function cropExpandValue($index,$default=) { if (!$this->exists($index)) return $default; $this->split($index); return $this->cropSpace($this->mFrame->expand($this->mBits[$index]['value'])); }
function trimExpandValue($index,$default=) { if (!$this->exists($index)) return $default; $this->split($index); return trim($this->mFrame->expand($this->mBits[$index]['value'])); }
function exists($index) { return $index <= $this->count; }
function split($index)
{
if (!isset($mBits[$index]))
{
$this->mBits[$index] = $this->mArgs[$index]->splitArg();
}
}
}
function wfCoallesce() { $args = func_get_args(); foreach ($args as $arg) { if ($arg) return $arg; } return false; }