r105680 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r105679‎ | r105680 | r105681 >
Date:17:20, 9 December 2011
Author:danwe
Status:deferred
Tags:
Comment:
Version 0.2 alpha, new variable/parser function 'CALLER' introduced
Modified paths:
  • /trunk/extensions/ParserFun/PFun_Caller.php (added) (history)
  • /trunk/extensions/ParserFun/PFun_Parse.php (modified) (history)
  • /trunk/extensions/ParserFun/ParserFun.i18n.magic.php (modified) (history)
  • /trunk/extensions/ParserFun/ParserFun.i18n.php (modified) (history)
  • /trunk/extensions/ParserFun/ParserFun.php (modified) (history)
  • /trunk/extensions/ParserFun/ParserFun_Settings.php (modified) (history)
  • /trunk/extensions/ParserFun/RELEASE-NOTES (modified) (history)

Diff [purge]

Index: trunk/extensions/ParserFun/PFun_Caller.php
@@ -0,0 +1,267 @@
 2+<?php
 3+
 4+/**
 5+ * Class for the 'CALLER' variable-style parser function.
 6+ *
 7+ * @since 0.2
 8+ *
 9+ * @file PFun_Caller.php
 10+ * @ingroup ParserFun
 11+ *
 12+ * @author Daniel Werner
 13+ */
 14+class ParserFunCaller extends ParserHook {
 15+
 16+ public function __construct() {
 17+ // make this a parser function extension (no tag extension) only:
 18+ parent::__construct( false, true, ParserHook::FH_NO_HASH );
 19+ }
 20+
 21+ /**
 22+ * No LSB in pre-5.3 PHP, to be refactored later
 23+ */
 24+ public static function staticMagic( array &$magicWords, $langCode ) {
 25+ $instance = new self;
 26+ return $instance->magic( $magicWords, $langCode );
 27+ }
 28+
 29+ /**
 30+ * No LSB in pre-5.3 PHP, to be refactored later
 31+ */
 32+ public static function staticInit( Parser &$parser ) {
 33+ global $egParserFunEnabledFunctions;
 34+ if( in_array( ExtParserFun::MAG_CALLER, $egParserFunEnabledFunctions ) ) {
 35+ // only register function if not disabled by configuration
 36+ $instance = new self;
 37+ $instance->init( $parser );
 38+ }
 39+ return true;
 40+ }
 41+
 42+ /**
 43+ * Gets the name of the parser hook.
 44+ * @see ParserHook::getName
 45+ *
 46+ * @return string
 47+ */
 48+ protected function getName() {
 49+ return 'CALLER';
 50+ }
 51+
 52+ /**
 53+ * Returns an array containing the parameter info.
 54+ * @see ParserHook::getParameterInfo
 55+ *
 56+ * @return array
 57+ */
 58+ protected function getParameterInfo( $type ) {
 59+ $params = array();
 60+
 61+ # what to get, index (any number) or certain mode (count, list)
 62+ # since 0.2
 63+ $params['mode'] = new Parameter( 'mode', Parameter::TYPE_STRING );
 64+ $params['mode']->addAliases( 'index' );
 65+
 66+ # where in the stack to start returning.
 67+ # negative value will return that many elements from the top-level caller
 68+ # since 0.2
 69+ $params['offset'] = new Parameter( 'offset', Parameter::TYPE_INTEGER );
 70+ $params['offset']->setDefault( false, false );
 71+
 72+ # max return, if negative stop that many elements from end
 73+ # since 0.2
 74+ $params['limit'] = new Parameter( 'limit', Parameter::TYPE_INTEGER );
 75+ $params['limit']->setDefault( false, false );
 76+ $params['limit']->addAliases( 'len', 'length' );
 77+
 78+ # whether to link the page names
 79+ # since 0.2
 80+ $params['linked'] = new Parameter( 'linked', Parameter::TYPE_BOOLEAN );
 81+ $params['linked']->setDefault( false );
 82+
 83+ # separator between list items
 84+ # since 0.2
 85+ $params['sep'] = new Parameter( 'sep', Parameter::TYPE_STRING );
 86+ $params['sep']->setDefault( ', ', false );
 87+
 88+ return $params;
 89+ }
 90+
 91+ /**
 92+ * Returns the list of default parameters.
 93+ * @see ParserHook::getDefaultParameters
 94+ *
 95+ * @return array
 96+ */
 97+ protected function getDefaultParameters( $type ) {
 98+ return array(
 99+ array( 'mode' ),
 100+ );
 101+ }
 102+
 103+ /**
 104+ * Renders and returns the output.
 105+ * @see ParserHook::renderTag
 106+ *
 107+ * @param array $parameters
 108+ *
 109+ * @return string
 110+ */
 111+ public function render( array $parameters ) {
 112+
 113+ $mode = $parameters['mode'];
 114+ $linked = $parameters['linked'];
 115+ $limit = $parameters['limit'];
 116+ $offset = $parameters['offset'];
 117+
 118+ if( is_numeric( $mode ) ) {
 119+ // get specific caller
 120+ /*
 121+ * do not just set $offset to $mode, $mode to 'list' and $limit to 1 here since handling
 122+ * for negative offset is different in 'list' mode. Here non-existant negative index will
 123+ * return '', in 'list' mode it will jump to the 0 element.
 124+ */
 125+ $index = (int)$mode;
 126+ $frame = self::getFrameStackItem( $this->frame, $index );
 127+
 128+ if( $frame === null ) {
 129+ return '';
 130+ }
 131+ return self::createSiteList(
 132+ array( $frame ),
 133+ $linked
 134+ );
 135+ }
 136+
 137+ $mode = strtolower( $mode );
 138+ switch( $mode ) {
 139+ case 'level':
 140+ // synnonym for 'count'
 141+ $mode = 'count';
 142+ case 'count':
 143+ case '':
 144+ /*
 145+ * '{{CALLER:}}', perhaps with additional parameters, but not in list mode except limit
 146+ * is set. Otherwise tread it similar to '{{CALLER}}' variable but with parameters.
 147+ */
 148+ if( $mode !== 'count' && $limit === false ) {
 149+ $limit = 1;
 150+ }
 151+ if( $offset === false ) {
 152+ // '{{CALLER}}' equals '{{CALLER:1}}', not 0, in count mode ignore current page.
 153+ $offset = 1;
 154+ }
 155+ // no-break, evaluate parameters in 'list' mode but count only
 156+ case 'list':
 157+ $stack = self::getFrameStack( $this->frame );
 158+ $offset = ( $offset === false ) ? 0 : $offset;
 159+ $limit = ( $limit === false ) ? null : $limit; // Validator can't have null as default...
 160+
 161+ $stack = array_slice( $stack, $offset, $limit );
 162+
 163+ if( $mode === 'count' ) {
 164+ // in 'count' mode, return the level
 165+ return count( $stack );
 166+ } else {
 167+ // normal list mode
 168+ return self::createSiteList(
 169+ $stack,
 170+ $linked,
 171+ $parameters['sep']
 172+ );
 173+ }
 174+ }
 175+
 176+ /*
 177+ * No valid operation mode or index given to first parameter!
 178+ * Return error message
 179+ */
 180+ $error = new ValidationError( wfMsgForContent( 'parserfun-invalid-caller-mode' ) );
 181+ return $this->renderFatalError( $error );
 182+ }
 183+
 184+ /**
 185+ * Returns a certain parent caller from a given frame by index. 0 returns the given frame, 1 would return
 186+ * the frame of the site which was calling the given frame and so on.
 187+ *
 188+ * @param PPFrame $frame
 189+ * @param int $index can be negative to return the element from the top-level caller. -1 would return
 190+ * the same as {{FULLPAGENAME}} would be. If the index doesn't exist, null will be returned.
 191+ *
 192+ * @return PPFrame|null
 193+ */
 194+ static function getFrameStackItem( PPFrame $frame, $index ) {
 195+ // get the whole stack or just till some certain index
 196+ $stack = self::getFrameStack( $frame, $index );
 197+
 198+ if( $index >= 0 ) {
 199+ if( array_key_exists( $index, $stack ) ) {
 200+ return $stack[ $index ];
 201+ }
 202+ } else {
 203+ // negative index, return from top-level
 204+ $index = count( $stack ) + $index;
 205+ if( $index >= 0 ) {
 206+ return $stack[ $index ];
 207+ }
 208+ }
 209+
 210+ // index doesn't exist!
 211+ return null;
 212+ }
 213+
 214+ /**
 215+ * Gets all parent frames from a frame and returns them as array with the given frame as first element.
 216+ *
 217+ * @param PPFrame $frame
 218+ * @param int $limit how many parent frames should be returned as maximum (in addition to given frame).
 219+ * Limit below 0 means no limit. 0 will just return an array with the given frame.
 220+ *
 221+ * @return PPFrame[]
 222+ */
 223+ static function getFrameStack( PPFrame $frame, $limit = -1 ) {
 224+ $frames = array();
 225+ if( $limit >= 0 ) {
 226+ $limit++; // given $frame doesn't count so this will be returned if 0 is given
 227+ }
 228+
 229+ while( $frame !== null && $limit !== 0 ) {
 230+ $frames[] = $frame;
 231+ $limit--;
 232+
 233+ if( $frame instanceof PPTemplateFrame_DOM ) {
 234+ $frame = $frame->parent;
 235+ } else {
 236+ // frame is no template, so this is the top-level frame (page being rendered)
 237+ $frame = null;
 238+ }
 239+ };
 240+
 241+ return $frames;
 242+ }
 243+
 244+ /**
 245+ * Create a list with page titles from a given array of frames, optionally linked output.
 246+ * The output ist un-parsed wiki markup, no HTML.
 247+ *
 248+ * @param array $frames the titles represented as frames
 249+ * @param bool $link whether or not to link the pages in the list
 250+ * @param string $sep glue between the pages
 251+ *
 252+ * @return string
 253+ */
 254+ protected static function createSiteList( $frames, $link = false, $sep = ', ' ) {
 255+ $out = array();
 256+ foreach( $frames as $frame ) {
 257+ $text = $frame->title->getPrefixedText();
 258+ if( $link ) {
 259+ $out[] = "[[:{$text}]]";
 260+ } else {
 261+ $text = wfEscapeWikiText( $text );
 262+ $out[] = $text;
 263+ }
 264+ }
 265+ return implode( $sep, $out );
 266+ }
 267+
 268+}
Property changes on: trunk/extensions/ParserFun/PFun_Caller.php
___________________________________________________________________
Added: svn:eol-style
1269 + native
Index: trunk/extensions/ParserFun/RELEASE-NOTES
@@ -1,6 +1,19 @@
22 'Parser Fun' Changelog:
33 =======================
44
 5+ * (trunk) -- Version 0.2 alpha
 6+ - New parser function/variable 'CALLER' to return a templates caller. Comes with the following parameters:
 7+ + <1>/mode - can be the level of the call stack to return (if negative the value will be returned from the
 8+ bottom. Instead of a numer a mode can be given: 'count' will return the current callstack level,
 9+ 'list' will return a list of all sites in the stack.
 10+ + linked - boolean whether page(s) should be returned linked.
 11+ + sep - separator between pages in 'list' mode. ', ' by default.
 12+ + offset - first stack item to return in 'list' mode. If negative, the list starts that far from the stacks top.
 13+ + limit - how many items to return in 'list' mode. If negative the list will end that far from the stacks top.
 14+ All parameters with specific meaning in 'list' mode have the same effect for the 'count' mode. In 'count' mode the
 15+ offset is set to 1 by default, in 'list' mode to 0.
 16+
 17+
518 * December 2, 2011 -- Version 0.1 (initial release)
619 - Magic word prefix 'THIS:', which is working with basically all functions returning page related information:
720 'FULLPAGENAME', 'PAGENAME', 'BASEPAGENAME', 'SUBPAGENAME', 'SUBJECTPAGENAME', 'TALKPAGENAME', 'NAMESPACE',
Index: trunk/extensions/ParserFun/PFun_Parse.php
@@ -105,7 +105,7 @@
106106 }
107107
108108 /**
109 - * Returns the parser function otpions.
 109+ * Returns the parser function options.
110110 * @see ParserHook::getFunctionOptions
111111 *
112112 * @return array
@@ -126,9 +126,6 @@
127127 * @return string
128128 */
129129 public function render( array $parameters ) {
130 -
131 -
132 -
133130 $text = $parameters['text'];
134131
135132 // current parsers StripState object
Index: trunk/extensions/ParserFun/ParserFun.i18n.magic.php
@@ -19,6 +19,7 @@
2020 $magicWords['en'] = array(
2121 'parse' => array( 0, 'parse' ),
2222 ExtParserFun::MAG_THIS => array( 1, 'THIS' ),
 23+ ExtParserFun::MAG_CALLER => array( 1, 'CALLER' ),
2324 );
2425
2526 /** Message documentation (Message documentation)
@@ -27,6 +28,7 @@
2829 $messages['qqq'] = array(
2930 'parse' => array( 0, 'Do not translate this! This is the magic word for the "#parse" function' ),
3031 ExtParserFun::MAG_THIS => array( 1, 'Keyword to put in front of a variable like "{{THIS:PAGENAME}}". This will output the pagename of the page where it is defined on instead of the page actually being parsed. "THIS" refers to that page.' ),
 32+ ExtParserFun::MAG_CALLER => array( 1, 'Variable/Parser function returning an templates direct initiator or with options even all or just specific initiators.' ),
3133 );
3234
3335 /** German (Deutsch)
Index: trunk/extensions/ParserFun/ParserFun.i18n.php
@@ -17,6 +17,7 @@
1818 */
1919 $messages['en'] = array(
2020 'parserfun-desc' => "Adds a parser function <code>#parse</code> for parsing wikitext and introduces <code>THIS:</code> prefix for page information related magic variables",
 21+ 'parserfun-invalid-caller-mode' => 'No valid operation mode or numeric index given.',
2122 );
2223
2324 /** Message documentation (Message documentation)
Index: trunk/extensions/ParserFun/ParserFun.php
@@ -8,7 +8,7 @@
99 * Support: http://www.mediawiki.org/wiki/Extension_talk:Parser_Fun
1010 * Source code: http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/ParserFun
1111 *
12 - * @version: 0.1
 12+ * @version: 0.2 alpha
1313 * @license: ISC license
1414 * @author: Daniel Werner < danweetz@web.de >
1515 *
@@ -59,19 +59,22 @@
6060 $wgHooks['ParserGetVariableValueSwitch'][] = 'ExtParserFun::onParserGetVariableValueSwitch';
6161
6262
63 -// 'parse' parser function initialization:
64 -$wgAutoloadClasses['ParserFunParse'] = ExtParserFun::getDir() . '/PFun_Parse.php';
 63+// 'parse' and 'CALLER' parser function initializations:
 64+$wgAutoloadClasses['ParserFunParse' ] = ExtParserFun::getDir() . '/PFun_Parse.php';
 65+$wgAutoloadClasses['ParserFunCaller'] = ExtParserFun::getDir() . '/PFun_Caller.php';
6566
6667 $wgHooks['ParserFirstCallInit'][] = 'ParserFunParse::staticInit';
6768 $wgHooks['LanguageGetMagic' ][] = 'ParserFunParse::staticMagic';
6869
 70+$wgHooks['ParserFirstCallInit'][] = 'ParserFunCaller::staticInit';
 71+$wgHooks['LanguageGetMagic' ][] = 'ParserFunCaller::staticMagic';
6972
 73+
7074 /**
7175 * Extension class of the 'Parser Fun' extension.
7276 * Handling the functionality around the 'THIS' magic word feature.
7377 */
7478 class ExtParserFun {
75 -
7679 /**
7780 * Version of the 'Parser Fun' extension.
7881 *
@@ -79,9 +82,10 @@
8083 *
8184 * @var string
8285 */
83 - const VERSION = '0.1';
 86+ const VERSION = '0.2 alpha';
8487
8588 const MAG_THIS = 'this';
 89+ const MAG_CALLER = 'caller';
8690
8791 public static function init( Parser &$parser ) {
8892 global $egParserFunEnabledFunctions;
@@ -158,6 +162,7 @@
159163 *
160164 * @param Parser $parser
161165 * @param type $word
 166+ *
162167 * @return string|null
163168 */
164169 static function getVariablesMagicWordId( Parser $parser, $word ) {
@@ -184,7 +189,7 @@
185190 /**
186191 * Returns the value of a variable like '{{FULLPAGENAME}}' in the context of the given PPFrame objects
187192 * $frame->$title instead of the Parser objects subject. Returns null in case the requested variable
188 - * doesn't support {{THIS:}}.
 193+ * does not support '{{THIS:}}'.
189194 *
190195 * @param string $mwId magic word ID of the variable
191196 * @param Parser $parser
@@ -203,6 +208,14 @@
204209
205210 // check whether info is available, e.g. 'THIS:FULLPAGENAME' requires 'FULLPAGENAME'
206211 switch( $mwId ) {
 212+ case 'namespace':
 213+ // 'namespace' function name was renamed as PHP 5.3 came along
 214+ if( is_callable( 'CoreParserFunctions::mwnamespace' ) ) {
 215+ $ret = CoreParserFunctions::mwnamespace( $parser, $title->getPrefixedText() );
 216+ break;
 217+ }
 218+ // else: no different from the other variables
 219+ // no-break, default function call
207220 case 'fullpagename':
208221 case 'fullpagenamee':
209222 case 'pagename':
@@ -215,24 +228,15 @@
216229 case 'subjectpagenamee':
217230 case 'talkpagename':
218231 case 'talkpagenamee':
219 - case 'namespacee': // for 'namespace', see bottom
 232+ case 'namespacee': // special treat for 'namespace', on top
220233 case 'subjectspace':
221234 case 'subjectspacee':
222235 case 'talkspace':
223236 case 'talkspacee':
224 - // core parser function information requested
 237+ // core parser function information requested
225238 $ret = CoreParserFunctions::$mwId( $parser, $title->getPrefixedText() );
226239 break;
227240
228 - case 'namespace':
229 - // 'namespace' function name was renamed as PHP 5.3 came along
230 - if( is_callable( 'CoreParserFunctions::mwnamespace' ) ) {
231 - $ret = CoreParserFunctions::mwnamespace( $parser, $title->getPrefixedText() );
232 - } else {
233 - $ret = CoreParserFunctions::$mwId( $parser, $title->getPrefixedText() );
234 - }
235 - break;
236 -
237241 default:
238242 // give other extensions a chance to hook up with this and return their own values:
239243 wfRunHooks( 'GetThisVariableValueSwitch', array( &$parser, $title, &$mwId, &$ret, $frame, $args ) );
@@ -240,22 +244,41 @@
241245 return $ret;
242246 }
243247
 248+
 249+ ##################
 250+ # Hooks Handling #
 251+ ##################
 252+
244253 static function onParserGetVariableValueSwitch( Parser &$parser, &$cache, &$magicWordId, &$ret, $frame = null ) {
 254+ if( $frame === null ) {
 255+ // unsupported MW version
 256+ return true;
 257+ }
245258 switch( $magicWordId ) {
246259 /** THIS **/
247260 case self::MAG_THIS:
248261 $ret = self::pfObj_this( $parser, $frame, null );
249262 break;
 263+
 264+ /** CALLER **/
 265+ case self::MAG_CALLER:
 266+ $siteFrame = ParserFunCaller::getFrameStackItem( $frame, 1 );
 267+ $ret = ( $siteFrame !== null ) ? $siteFrame->title->getPrefixedText() : '';
 268+ break;
250269 }
251270 return true;
252271 }
253272
254273 static function onMagicWordwgVariableIDs( &$variableIds ) {
255274 global $egParserFunEnabledFunctions;
 275+ // only register variables if not disabled by configuration
 276+
256277 if( in_array( self::MAG_THIS, $egParserFunEnabledFunctions ) ) {
257 - // only register variable if not disabled by configuration
258278 $variableIds[] = self::MAG_THIS;
259279 }
 280+ if( in_array( self::MAG_CALLER, $egParserFunEnabledFunctions ) ) {
 281+ $variableIds[] = self::MAG_CALLER;
 282+ }
260283 return true;
261284 }
262285
Index: trunk/extensions/ParserFun/ParserFun_Settings.php
@@ -29,4 +29,4 @@
3030 * @since 0.1
3131 * @var array
3232 */
33 -$egParserFunEnabledFunctions = array( 'this', 'parse' );
 33+$egParserFunEnabledFunctions = array( 'this', 'parse', 'caller' );

Status & tagging log