r103158 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r103157‎ | r103158 | r103159 >
Date:12:52, 15 November 2011
Author:danwe
Status:deferred
Tags:
Comment:
Tag for Loops 0.3.2
Modified paths:
  • /tags/extensions/Loops (added) (history)
  • /tags/extensions/Loops/REL_0_3_2 (added) (history)
  • /tags/extensions/Loops/REL_0_3_2/Loops.i18n.php (added) (history)
  • /tags/extensions/Loops/REL_0_3_2/Loops.php (added) (history)
  • /tags/extensions/Loops/REL_0_3_2/README (added) (history)
  • /tags/extensions/Loops/REL_0_3_2/RELEASE-NOTES (added) (history)

Diff [purge]

Index: tags/extensions/Loops/REL_0_3_2/Loops.i18n.php
@@ -0,0 +1,55 @@
 2+<?php
 3+
 4+class Loops_i18n {
 5+ private $words = array(
 6+ // English
 7+ 'en' => array(
 8+ 'dowhile' => array( 0, 'dowhile' ),
 9+ 'while' => array( 0, 'while' ),
 10+ 'forargs' => array( 0, 'forargs' ),
 11+ 'fornumargs' => array( 0, 'fornumargs' ),
 12+ 'loop' => array( 0, 'loop' ),
 13+ ),
 14+ );
 15+
 16+ private $messages = array(
 17+ // English
 18+ 'en' => array(
 19+ 'loops_max' => 'Maximum number of loops have been performed',
 20+ )
 21+ );
 22+
 23+ private static $instance = null;
 24+
 25+ public static function getInstance() {
 26+ // create the singleton if needed
 27+ if ( self::$instance === null ) {
 28+ self::$instance = new self();
 29+ }
 30+
 31+ return self::$instance;
 32+ }
 33+
 34+ /**
 35+ * limited-access constructor to insure singleton
 36+ */
 37+ protected function __construct() { }
 38+
 39+ /**
 40+ * Get translated magic words, if available
 41+ *
 42+ * @param $lang String: language code
 43+ * @return array
 44+ */
 45+ public function magicWords( $lang ) {
 46+ // English is used as a fallback, and the English synonyms are
 47+ // used if a translation has not been provided for a given word
 48+ return ( $lang == 'en' || !isset( $this->words[$lang] ) ) ?
 49+ $this->words['en'] :
 50+ array_merge( $this->words['en'], $this->words[$lang] );
 51+ }
 52+
 53+ public function getMessages() {
 54+ return $this->messages;
 55+ }
 56+}
Property changes on: tags/extensions/Loops/REL_0_3_2/Loops.i18n.php
___________________________________________________________________
Added: svn:eol-style
157 + native
Index: tags/extensions/Loops/REL_0_3_2/Loops.php
@@ -0,0 +1,310 @@
 2+<?php
 3+/**
 4+ * 'Loops' is a MediaWiki extension expanding the parser with loops functions
 5+ *
 6+ * Documentation: http://www.mediawiki.org/wiki/Extension:Loops
 7+ * Support: http://www.mediawiki.org/wiki/Extension_talk:Loops
 8+ * Source code: http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/Loops
 9+ *
 10+ * @version: 0.3.2
 11+ * @license: GNU GPL v2 or higher
 12+ * @author: David M. Sledge
 13+ * @author: Daniel Werner < danweetz@web.de >
 14+ *
 15+ * @file Loops.php
 16+ * @ingroup Loops
 17+ */
 18+
 19+if ( !defined( 'MEDIAWIKI' ) ) {
 20+ die( 'This file is a MediaWiki extension, it is not a valid entry point' );
 21+}
 22+
 23+$wgHooks['ParserFirstCallInit'][] = $wgHooks['LanguageGetMagic'][]
 24+ = $wgHooks['ParserLimitReport'][] = ExtLoops::getInstance();
 25+
 26+// Extension credits that will show up on Special:Version
 27+$wgExtensionCredits['parserhook'][] = array(
 28+ 'path' => __FILE__,
 29+ 'author' => 'David M. Sledge',
 30+ 'name' => 'Loops',
 31+ 'version' => ExtLoops::VERSION,
 32+ 'description' => 'Parser functions for performing loops',
 33+ 'url' => 'http://www.mediawiki.org/wiki/Extension:Loops',
 34+);
 35+
 36+class ExtLoops {
 37+ const VERSION = '0.3.2';
 38+
 39+ public static $maxLoops = 100; // maximum number of loops allowed
 40+ // (-1 = no limit). #forargs is
 41+ // not limited by this.
 42+ private static $instance = null;
 43+
 44+ private $parserFunctions = array(
 45+ 'dowhile' => array( 'dowhile', SFH_OBJECT_ARGS ),
 46+ 'while' => array( 'whileHook', SFH_OBJECT_ARGS ),
 47+ 'loop' => array( 'loop', SFH_OBJECT_ARGS ),
 48+ 'forargs' => array( 'forArgs', SFH_OBJECT_ARGS ),
 49+ 'fornumargs' => array( 'forNumArgs', SFH_OBJECT_ARGS ),
 50+ );
 51+
 52+ private $loopCount = 0;
 53+
 54+ public static function getInstance() {
 55+ // create the singleton if needed
 56+ if ( self::$instance === null ) {
 57+ self::$instance = new self();
 58+ }
 59+
 60+ return self::$instance;
 61+ }
 62+
 63+ /**
 64+ * limited-access constructor to insure singleton
 65+ */
 66+ protected function __construct() { }
 67+
 68+ public function onParserFirstCallInit( &$parser ) {
 69+ global $wgMessageCache, $wgHooks;
 70+
 71+ // These functions accept DOM-style arguments
 72+ foreach( $this->parserFunctions as $hook => $callAndFlags ) {
 73+ $parser->setFunctionHook( $hook, array( $this, $callAndFlags[0] ),
 74+ $callAndFlags[1] );
 75+ }
 76+
 77+ require_once( dirname( __FILE__ ) . '/Loops.i18n.php' );
 78+
 79+ // @todo FIXME: $wgMessageCache and the addMessages method were
 80+ // removed in http://www.mediawiki.org/wiki/Special:Code/MediaWiki/81027
 81+ foreach( Loops_i18n::getInstance()->getMessages()
 82+ as $lang => $messages )
 83+ {
 84+ $wgMessageCache->addMessages( $messages, $lang );
 85+ }
 86+
 87+ $wgHooks['ParserClearState'][] = $this;
 88+
 89+ return true;
 90+ }
 91+
 92+ public function onLanguageGetMagic( &$magicWords, $langCode ) {
 93+ require_once( dirname( __FILE__ ) . '/Loops.i18n.php' );
 94+
 95+ foreach( Loops_i18n::getInstance()->magicWords( $langCode )
 96+ as $word => $trans )
 97+ {
 98+ $magicWords[$word] = $trans;
 99+ }
 100+
 101+ return true;
 102+ }
 103+
 104+ public function onParserLimitReport( $parser, &$report ) {
 105+ if ( isset( $this->loopCount ) ) {
 106+ $report .= "ExtLoops count: {$this->loopCount}/" . self::$maxLoops . "\n";
 107+ }
 108+
 109+ return true;
 110+ }
 111+
 112+ public function whileHook( &$parser, $frame, $args ) {
 113+ // bug 12842: first argument is automatically
 114+ // expanded, so we ignore this one
 115+ array_shift( $args );
 116+ $test = array_shift( $args );
 117+ $loopStatement = array_shift( $args );
 118+ $output = '';
 119+
 120+ while ( isset( $test ) && trim( $frame->expand( $test ) ) !== '' ) {
 121+ if (
 122+ self::$maxLoops >= 0 &&
 123+ ++$this->loopCount > self::$maxLoops
 124+ )
 125+ {
 126+ return $output . wfMsgForContent( 'loops_max' );
 127+ }
 128+
 129+ $output .= isset( $loopStatement ) ?
 130+ trim( $frame->expand( $loopStatement ) ) : '';
 131+ }
 132+
 133+ //return '<pre><nowiki>'. $output . '</nowiki></'. 'pre>';
 134+ return $output;
 135+ }
 136+
 137+ public function dowhile( &$parser, $frame, $args ) {
 138+ // bug 12842: first argument is automatically
 139+ // expanded, so we ignore this one
 140+ array_shift( $args );
 141+ $test = array_shift( $args );
 142+ $loopStatement = array_shift( $args );
 143+ $output = '';
 144+
 145+ do {
 146+ if (
 147+ self::$maxLoops >= 0 &&
 148+ ++$this->loopCount > self::$maxLoops
 149+ )
 150+ {
 151+ return $output . wfMsgForContent( 'loops_max' );
 152+ }
 153+
 154+ $output .= isset( $loopStatement ) ?
 155+ trim( $frame->expand( $loopStatement ) ) : '';
 156+ } while ( isset( $test ) && trim( $frame->expand( $test ) ) !== '' );
 157+
 158+ //return '<pre><nowiki>'. $output . '</nowiki></'. 'pre>';
 159+ return $output;
 160+ }
 161+
 162+ public function forArgs( &$parser, $frame, $args ) {
 163+ if ( !( $frame instanceof PPTemplateFrame_DOM ) ) {
 164+ $arg = array_shift( $args );
 165+ $arg = isset( $arg ) ? $frame->expand( $arg ) : '';
 166+
 167+ // TODO: get the synonym for the content language
 168+ $out = "{{#forargs:$arg";
 169+
 170+ // expand and display each argument
 171+ while ( ( $arg = array_shift( $args ) ) !== null ) {
 172+ $out .= '|' . $frame->expand( $arg );
 173+ }
 174+
 175+ $out .= '}}';
 176+
 177+ return $out;
 178+ }
 179+
 180+ global $wgExtVariables;
 181+
 182+ // The first arg is already expanded, but this is a good habit to have.
 183+ $filter = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : '';
 184+ // name of the variable to store the argument name. this
 185+ // will be accessed in the loop by using {{#var:}}
 186+ $keyVarName = isset( $args[1] ) ?
 187+ trim( $frame->expand( $args[1] ) ) : '';
 188+ // name of the variable to store the argument value.
 189+ $valueVarName = isset( $args[2] ) ?
 190+ trim( $frame->expand( $args[2] ) ) : '';
 191+ $loopStatement = isset( $args[3] ) ? $args[3] : '';
 192+ $output = '';
 193+
 194+ $tArgs = preg_match( '/^([1-9][0-9]*)?$/', $filter ) > 0
 195+ ? $frame->getArguments() : $frame->getNamedArguments();
 196+
 197+ foreach ( $tArgs as $argName => $argVal ) {
 198+ if ( $filter == '' || strpos( $argName, $filter ) === 0 ) {
 199+ if ( $keyVarName !== $valueVarName ) {
 200+ $wgExtVariables->vardefine( $parser, $keyVarName,
 201+ trim( substr( $argName, strlen( $filter ) ) ) );
 202+ }
 203+
 204+ $wgExtVariables->vardefine( $parser, $valueVarName, trim( $argVal ) );
 205+ $output .= trim( $frame->expand( $loopStatement ) );
 206+ }
 207+ }
 208+
 209+ return $output;
 210+ }
 211+
 212+ public function forNumArgs( &$parser, $frame, $args ) {
 213+ if ( !( $frame instanceof PPTemplateFrame_DOM ) ) {
 214+ $arg = array_shift( $args );
 215+ $arg = isset( $arg ) ? $frame->expand( $arg ) : '';
 216+
 217+ // TODO: get the synonym for the content language
 218+ $out = "{{#forargs:$arg";
 219+
 220+ // expand and display each argument
 221+ while ( ( $arg = array_shift( $args ) ) !== null ) {
 222+ $out .= '|' . $frame->expand( $arg );
 223+ }
 224+
 225+ $out .= '}}';
 226+
 227+ return $out;
 228+ }
 229+
 230+ global $wgExtVariables;
 231+
 232+ // The first arg is already expanded, but this is a good habit to have.
 233+ // name of the variable to store the argument name. this
 234+ // will be accessed in the loop by using {{#var:}}
 235+ $keyVarName = isset( $args[0] ) ?
 236+ trim( $frame->expand( $args[0] ) ) : '';
 237+ // name of the variable to store the argument value.
 238+ $valueVarName = isset( $args[1] ) ?
 239+ trim( $frame->expand( $args[1] ) ) : '';
 240+ $loopStatement = isset( $args[2] ) ? $args[2] : '';
 241+ $output = '';
 242+ $numArgs = $frame->getArguments();
 243+ ksort( $numArgs );
 244+
 245+ foreach ( $numArgs as $argNumber => $argVal ) {
 246+ if ( is_string( $argNumber ) ) {
 247+ continue;
 248+ }
 249+
 250+ if ( $keyVarName !== $valueVarName ) {
 251+ $wgExtVariables->vardefine( $parser, $keyVarName, trim( $argNumber ) );
 252+ }
 253+
 254+ $wgExtVariables->vardefine( $parser, $valueVarName, trim( $argVal ) );
 255+ $output .= trim( $frame->expand( $loopStatement ) );
 256+ }
 257+
 258+ return $output;
 259+ }
 260+
 261+ public function loop( &$parser, $frame, $args ) {
 262+ global $wgExtVariables;
 263+ // snag the variable name
 264+ $varName = array_shift( $args );
 265+ $varName = $varName === null ? '' : trim( $frame->expand( $varName ) );
 266+ // grab the intitial value for the variable (default to 0)
 267+ $startVal = array_shift( $args );
 268+ $startVal = $startVal === null
 269+ ? 0 : intval( trim( $frame->expand( $startVal ) ) );
 270+ // How many times are we gonna loop?
 271+ $count = array_shift( $args );
 272+
 273+ if ( $count === null ) {
 274+ return '';
 275+ }
 276+
 277+ $endVal = $startVal + intval( trim( $frame->expand( $count ) ) );
 278+
 279+ if ( $endVal == $startVal ) {
 280+ return '';
 281+ }
 282+
 283+ // grab the unexpanded loop statement
 284+ $loopStatement = array_shift( $args );
 285+ $output = '';
 286+
 287+ for ( ; $startVal != $endVal;
 288+ $startVal < $endVal ? $startVal++ : $startVal-- )
 289+ {
 290+ if (
 291+ self::$maxLoops >= 0 &&
 292+ ++$this->loopCount > self::$maxLoops
 293+ ) {
 294+ return $output . wfMsgForContent( 'loops_max' );
 295+ }
 296+
 297+ $wgExtVariables->vardefine( $parser, $varName, trim( $startVal ) );
 298+
 299+ $output .= isset( $loopStatement ) ?
 300+ trim( $frame->expand( $loopStatement ) ) : '';
 301+ }
 302+
 303+ return $output;
 304+ }
 305+
 306+ public function onParserClearState( &$parser ) {
 307+ $this->loopCount = 0;
 308+
 309+ return true;
 310+ }
 311+}
Property changes on: tags/extensions/Loops/REL_0_3_2/Loops.php
___________________________________________________________________
Added: svn:eol-style
1312 + native
Index: tags/extensions/Loops/REL_0_3_2/RELEASE-NOTES
@@ -0,0 +1,28 @@
 2+ Post svn Changelog:
 3+ ===================
 4+
 5+ * Version 0.3.2 by Daniel Werner
 6+ - Bug solved where '#loop' didn't create variables with name or starting index '0'.
 7+ - minor '#forargs' and '#fornumargs' bug solved where unnamed numeric argument values
 8+ could have ended up as variable value with leading space.
 9+ - 'README' and 'RELEASE-NOTES' files added.
 10+ - Put into mediawiki.org svn repository.
 11+
 12+
 13+ Pre svn Changelog:
 14+ ==================
 15+
 16+ The following pre-svn changelog was composed after the extension has been moved into mediawiki.org
 17+ svn. All changes can still be retrace at:
 18+
 19+ http://www.mediawiki.org/w/index.php?title=Extension:Loops&action=history
 20+
 21+ * Version 0.3.0 by David M. Sledge
 22+ - '#loop' and '#fornumargs' parser functions were introduced.
 23+ - '#foreachnamedarg' renamed to '#forargs' and loops through indexed template arguments as well
 24+ as named arguments now.
 25+
 26+ * Version 0.2.0 by David M. Sledge
 27+ - '#foreachnamedarg' parser function introduced. Allows to loop through named template arguments.
 28+
 29+ * Version 0.1.0 (initial release) by David M. Sledge
Index: tags/extensions/Loops/REL_0_3_2/README
@@ -0,0 +1,24 @@
 2+== About ==
 3+
 4+The 'Loops' extension Enhances the parser with parser functions to perform loops.
 5+It is not compatible with MediaWiki versions below 1.12.
 6+
 7+* Website: http://www.mediawiki.org/wiki/Extension:Loops
 8+* Authors: David M. Sledge, Daniel Werner < danweetz@web.de >
 9+* License: ISC license
 10+
 11+
 12+== Installation ==
 13+
 14+Once you have downloaded the code, place the 'Loops' directory within your
 15+MediaWiki 'extensions' directory. Then add the following code to your
 16+[[Manual:LocalSettings.php|LocalSettings.php]] file:
 17+
 18+ # Loops
 19+ require_once( "$IP/extensions/Loops/Loops.php" );
 20+
 21+
 22+== Contributing ==
 23+
 24+If you have bug reports or feature requests, please add them to the 'Loops'
 25+Talk page http://www.mediawiki.org/w/index.php?title=Extension_talk:Loops

Status & tagging log