r103163 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r103162‎ | r103163 | r103164 >
Date:13:04, 15 November 2011
Author:danwe
Status:deferred
Tags:
Comment:
Version 0.4 alpha. Structural re-design, loops-count per parser instance, state of the art internationalization file
Modified paths:
  • /trunk/extensions/Loops/Loops.i18n.magic.php (added) (history)
  • /trunk/extensions/Loops/Loops.i18n.php (modified) (history)
  • /trunk/extensions/Loops/Loops.php (modified) (history)
  • /trunk/extensions/Loops/RELEASE-NOTES (modified) (history)

Diff [purge]

Index: trunk/extensions/Loops/Loops.i18n.magic.php
@@ -0,0 +1,22 @@
 2+<?php
 3+#coding: utf-8
 4+
 5+/**
 6+ * Internationalization file for magic words of the 'Loops' extension.
 7+ *
 8+ * @since 0.4
 9+ *
 10+ * @file Loops.i18n.magic.php
 11+ * @ingroup Loops
 12+ * @author Daniel Werner < danweetz@web.de >
 13+ */
 14+
 15+$magicWords = array();
 16+
 17+$magicWords['en'] = array(
 18+ 'while' => array( 0, 'while' ),
 19+ 'dowhile' => array( 0, 'dowhile' ),
 20+ 'loop' => array( 0, 'loop' ),
 21+ 'forargs' => array( 0, 'forargs' ),
 22+ 'fornumargs' => array( 0, 'fornumargs' ),
 23+);
Property changes on: trunk/extensions/Loops/Loops.i18n.magic.php
___________________________________________________________________
Added: svn:eol-style
124 + native
Index: trunk/extensions/Loops/Loops.i18n.php
@@ -1,55 +1,30 @@
22 <?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 -}
 3+#coding: utf-8
 4+
 5+/**
 6+ * Internationalization file of the 'Loops' extension.
 7+ *
 8+ * @since 0.4
 9+ *
 10+ * @file Loops.i18n.php
 11+ * @ingroup Loops
 12+ * @author Daniel Werner < danweetz@web.de >
 13+ */
 14+
 15+$messages = array();
 16+
 17+/** English
 18+ * @author David M. Sledge
 19+ */
 20+$messages['en'] = array(
 21+ 'loops-desc' => 'Parser functions for performing loops',
 22+ 'loops_max' => 'Maximum number of loops have been performed'
 23+);
 24+
 25+/** German
 26+ * @author Daniel Werner
 27+ */
 28+$messages['de'] = array(
 29+ 'loops-desc' => 'Parser-Funktionen zur Schleifen-Ausführung',
 30+ 'loops_max' => 'Die maximal erlaubte Anzahl an Schleifen wurde ausgeführt'
 31+);
Index: trunk/extensions/Loops/Loops.php
@@ -1,4 +1,5 @@
22 <?php
 3+
34 /**
45 * 'Loops' is a MediaWiki extension expanding the parser with loops functions
56 *
@@ -6,7 +7,7 @@
78 * Support: http://www.mediawiki.org/wiki/Extension_talk:Loops
89 * Source code: http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/Loops
910 *
10 - * @version: 0.3.2
 11+ * @version: 0.4 alpha
1112 * @license: GNU GPL v2 or higher
1213 * @author: David M. Sledge
1314 * @author: Daniel Werner < danweetz@web.de >
@@ -14,297 +15,321 @@
1516 * @file Loops.php
1617 * @ingroup Loops
1718 */
 19+
 20+if ( ! defined( 'MEDIAWIKI' ) ) { die( ); }
1821
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
2722 $wgExtensionCredits['parserhook'][] = array(
28 - 'path' => __FILE__,
29 - 'author' => 'David M. Sledge',
 23+ 'path' => __FILE__,
 24+ 'author' => array( 'David M. Sledge', '[http://www.mediawiki.org/wiki/User:Danwe Daniel Werner]' ),
3025 'name' => 'Loops',
3126 'version' => ExtLoops::VERSION,
32 - 'description' => 'Parser functions for performing loops',
 27+ 'descriptionmsg' => 'loops-desc',
3328 'url' => 'http://www.mediawiki.org/wiki/Extension:Loops',
3429 );
35 -
 30+
 31+// language files:
 32+$wgExtensionMessagesFiles['Loops' ] = ExtLoops::getDir() . '/Loops.i18n.php';
 33+$wgExtensionMessagesFiles['LoopsMagic'] = ExtLoops::getDir() . '/Loops.i18n.magic.php';
 34+
 35+// hooks registration:
 36+$wgHooks['ParserFirstCallInit'][] = 'ExtLoops::init';
 37+$wgHooks['ParserClearState' ][] = 'ExtLoops::onParserClearState';
 38+
 39+
 40+/**
 41+ * Class representing extension 'Loops', containing all parser functions and other
 42+ * extension logic stuff.
 43+ */
3644 class ExtLoops {
37 - const VERSION = '0.3.2';
 45+
 46+ const VERSION = '0.4 alpha';
3847
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 -
6348 /**
64 - * limited-access constructor to insure singleton
 49+ * Configuration variable defining maximum allowed number of loops ('-1' => no limit).
 50+ * '#forargs' and '#fornumargs' are not limited by this.
 51+ *
 52+ * @var int
6553 */
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] );
 54+ public static $maxLoops = 100;
 55+
 56+ /**
 57+ * Returns the extensions base installation directory.
 58+ *
 59+ * @since 0.4
 60+ *
 61+ * @return boolean
 62+ */
 63+ public static function getDir() {
 64+ static $dir = null;
 65+
 66+ if( $dir === null ) {
 67+ $dir = dirname( __FILE__ );
7568 }
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;
 69+ return $dir;
9070 }
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 -
 71+
 72+ /**
 73+ * Sets up parser functions
 74+ *
 75+ * @since 0.4
 76+ */
 77+ public static function init( Parser &$parser ) {
 78+
 79+ /*
 80+ * store for loops count per parser object. This will solve several bugs related to
 81+ * 'ParserClearState' hook resetting the count early in combination with certain
 82+ * other extensions or special page inclusion. (since v0.4)
 83+ */
 84+ $parser->mExtLoopsCounter = 0;
 85+
 86+ self::initFunction( $parser, 'while' );
 87+ self::initFunction( $parser, 'dowhile' );
 88+ self::initFunction( $parser, 'loop' );
 89+ self::initFunction( $parser, 'forargs' );
 90+ self::initFunction( $parser, 'fornumargs' );
 91+
10192 return true;
10293 }
103 -
 94+ private static function initFunction( Parser &$parser, $name ) {
 95+ $functionCallback = array( __CLASS__, 'pfObj_' . $name );
 96+ $parser->setFunctionHook( $name, $functionCallback, SFH_OBJECT_ARGS );
 97+ }
 98+
 99+
104100 public function onParserLimitReport( $parser, &$report ) {
105 - if ( isset( $this->loopCount ) ) {
106 - $report .= "ExtLoops count: {$this->loopCount}/" . self::$maxLoops . "\n";
 101+ // add performed loops to limit report:
 102+ $report .= 'ExtLoops count: ' . self::getLoopsCount( $parser );
 103+
 104+ if( self::$maxLoops > -1 ) {
 105+ // if limit is set, communicate the limit as well:
 106+ $report .= '/' . self::$maxLoops . "\n";
107107 }
108 -
109108 return true;
110109 }
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 ) ) : '';
 110+
 111+
 112+ ####################
 113+ # Parser Functions #
 114+ ####################
 115+
 116+ public static function pfObj_while( Parser &$parser, $frame, $args ) {
 117+ return self::perform_while( $parser, $frame, $args, false );
 118+ }
 119+
 120+ public static function pfObj_dowhile( Parser &$parser, $frame, $args ) {
 121+ return self::perform_while( $parser, $frame, $args, true );
 122+ }
 123+
 124+ /**
 125+ * Generic function handling '#while' and '#dowhile' as one
 126+ */
 127+ protected static function perform_while( Parser &$parser, $frame, $args, $dowhile = false ) {
 128+ // #(do)while: | condition | code
 129+ $rawCond = isset( $args[1] ) ? $args[1] : ''; // unexpanded condition
 130+ $rawCode = isset( $args[2] ) ? $args[2] : ''; // unexpanded loop code
 131+
 132+ if(
 133+ $dowhile === false
 134+ && trim( $frame->expand( $rawCond ) ) === ''
 135+ ) {
 136+ // while, but condition not fullfilled from the start
 137+ return '';
131138 }
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 );
 139+
143140 $output = '';
144 -
 141+
145142 do {
146 - if (
147 - self::$maxLoops >= 0 &&
148 - ++$this->loopCount > self::$maxLoops
149 - )
150 - {
151 - return $output . wfMsgForContent( 'loops_max' );
 143+ // limit check:
 144+ if( ! self::incrCounter( $parser ) ) {
 145+ return self::msgLoopsLimit( $output );
152146 }
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>';
 147+ $output .= trim( $frame->expand( $rawCode ) );
 148+
 149+ } while( trim( $frame->expand( $rawCond ) ) );
 150+
159151 return $output;
160152 }
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;
 153+
 154+ public static function pfObj_loop( Parser &$parser, PPFrame $frame, $args ) {
 155+ // #loop: var | start | count | code
 156+ $varName = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : '';
 157+ $startVal = isset( $args[1] ) ? (int)trim( $frame->expand( $args[1] ) ) : 0;
 158+ $loops = isset( $args[2] ) ? (int)trim( $frame->expand( $args[2] ) ) : 0;
 159+ $rawCode = isset( $args[3] ) ? $args[3] : ''; // unexpanded loop code
 160+
 161+ if( $loops === 0 ) {
 162+ // no loops to perform
 163+ return '';
178164 }
179 -
 165+
180166 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] : '';
 167+
192168 $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 ) );
 169+ $endVal = $startVal + $loops;
 170+
 171+ while( $startVal !== $endVal ) {
 172+ // limit check:
 173+ if( ! self::incrCounter( $parser ) ) {
 174+ return self::msgLoopsLimit( $output );
206175 }
 176+
 177+ $wgExtVariables->vardefine( $parser, $varName, (string)$startVal );
 178+
 179+ $output .= trim( $frame->expand( $rawCode ) );
 180+
 181+ // in-/decrease loop count (count can be negative):
 182+ ( $startVal < $endVal ) ? $startVal++ : $startVal--;
207183 }
208 -
209184 return $output;
210185 }
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 );
 186+
 187+ /**
 188+ * #forargs: filter | keyVarName | valVarName | code
 189+ */
 190+ public static function pfObj_forargs( Parser &$parser, $frame, $args ) {
 191+ // The first arg is already expanded, but this is a good habit to have...
 192+ $filter = array_shift( $args );
 193+ $filter = $filter !== null ? trim( $frame->expand( $filter ) ) : '';
 194+
 195+ // if prefix contains numbers only or isn't set, get all arguments, otherwise just non-numeric
 196+ $tArgs = ( preg_match( '/^([1-9][0-9]*)?$/', $filter ) > 0 )
 197+ ? $frame->getArguments()
 198+ : $frame->getNamedArguments();
 199+
 200+ return self::perform_forargs( $parser, $frame, $args, $tArgs, $filter );
 201+ }
 202+
 203+ /**
 204+ * #fornumargs: keyVarName | valVarName | code
 205+ */
 206+ public static function pfObj_fornumargs( Parser &$parser, $frame, $args ) {
 207+ /*
 208+ * get numeric arguments, don't use PPFrame::getNumberedArguments because it would
 209+ * return explicitely numbered arguments only.
 210+ */
 211+ $tNumArgs = $frame->getArguments();
 212+ foreach( $tNumArgs as $argKey => $argVal ) {
 213+ // allow all numeric, including negative values!
 214+ if( is_string( $argKey ) ) {
 215+ unset( $tNumArgs[ $argKey ] );
223216 }
224 -
225 - $out .= '}}';
226 -
227 - return $out;
228217 }
229 -
 218+ ksort( $tNumArgs ); // sort from lowest to highest
 219+
 220+ return self::perform_forargs( $parser, $frame, $args, $tNumArgs, '' );
 221+ }
 222+
 223+ /**
 224+ * Generic function handling '#forargs' and '#fornumargs' as one
 225+ */
 226+ protected static function perform_forargs( Parser &$parser, PPFrame $frame, array $funcArgs, array $templateArgs, $prefix = '' ) {
 227+ // if not called within template instance:
 228+ if( !( $frame instanceof PPTemplateFrame_DOM ) ) {
 229+ return array( 'found' => false );
 230+ }
 231+
 232+ // name of the variable to store the argument name:
 233+ $keyVar = array_shift( $funcArgs );
 234+ $keyVar = $keyVar !== null ? trim( $frame->expand( $keyVar ) ) : '';
 235+ // name of the variable to store the argument value:
 236+ $valVar = array_shift( $funcArgs );
 237+ $valVar = $valVar !== null ? trim( $frame->expand( $valVar ) ) : '';
 238+ // unexpanded code:
 239+ $rawCode = array_shift( $funcArgs );
 240+ $rawCode = $rawCode !== null ? $rawCode : '';
 241+
230242 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] : '';
241243 $output = '';
242 - $numArgs = $frame->getArguments();
243 - ksort( $numArgs );
244 -
245 - foreach ( $numArgs as $argNumber => $argVal ) {
246 - if ( is_string( $argNumber ) ) {
 244+
 245+ // if prefix contains numbers only or isn't set, get all arguments, otherwise just non-numeric
 246+ $tArgs = preg_match( '/^([1-9][0-9]*)?$/', $prefix ) > 0
 247+ ? $frame->getArguments() : $frame->getNamedArguments();
 248+
 249+ foreach( $templateArgs as $argName => $argVal ) {
 250+ // if no filter or prefix in argument name:
 251+ if( $prefix !== '' && strpos( $argName, $prefix ) !== 0 ) {
247252 continue;
248253 }
249 -
250 - if ( $keyVarName !== $valueVarName ) {
251 - $wgExtVariables->vardefine( $parser, $keyVarName, trim( $argNumber ) );
 254+ if ( $keyVar !== $valVar ) {
 255+ // variable with the argument name as value
 256+ $wgExtVariables->vardefine(
 257+ $parser,
 258+ $keyVar,
 259+ trim( substr( $argName, strlen( $prefix ) ) )
 260+ );
252261 }
253 -
254 - $wgExtVariables->vardefine( $parser, $valueVarName, trim( $argVal ) );
255 - $output .= trim( $frame->expand( $loopStatement ) );
 262+ // variable with the arguments value
 263+ $wgExtVariables->vardefine( $parser, $valVar, trim( $argVal ) );
 264+
 265+ // expand current run:
 266+ $output .= trim( $frame->expand( $rawCode ) );
256267 }
257 -
 268+
258269 return $output;
259270 }
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 '';
 271+
 272+
 273+ ###############
 274+ # Loops Count #
 275+ ###############
 276+
 277+ /**
 278+ * Returns how many loops have been performed for a given Parser instance.
 279+ *
 280+ * @since 0.4
 281+ *
 282+ * @param Parser $parser
 283+ * @return int
 284+ */
 285+ public static function getLoopsCount( Parser &$parser ) {
 286+ return $parser->mExtLoopsCounter;
 287+ }
 288+
 289+ /**
 290+ * Returns whether the maximum number of loops for the given Parser instance have
 291+ * been performed already.
 292+ *
 293+ * @since 0.4
 294+ *
 295+ * @param Parser $parser
 296+ * @return bool
 297+ */
 298+ public static function maxLoopsPerformed( Parser &$parser ) {
 299+ $count = $parser->mExtLoopsCounter;
 300+ return $count > -1 && $count >= self::$maxLoops;
 301+ }
 302+
 303+ /**
 304+ * If limit has not been exceeded already, this will increase the counter. If
 305+ * exceeded false will be returned, otherwise the new counter value
 306+ *
 307+ * @return false|int
 308+ */
 309+ protected static function incrCounter( Parser &$parser ) {
 310+ if( self::maxLoopsPerformed( $parser ) ) {
 311+ return false;
275312 }
276 -
277 - $endVal = $startVal + intval( trim( $frame->expand( $count ) ) );
278 -
279 - if ( $endVal == $startVal ) {
280 - return '';
 313+ return ++$parser->mExtLoopsCounter;
 314+ }
 315+
 316+ /**
 317+ * div wrapped error message stating maximum number of loops have been performed.
 318+ */
 319+ protected static function msgLoopsLimit( $output = '' ) {
 320+ if( trim( $output ) !== '' ) {
 321+ $output .= "\n";
281322 }
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;
 323+ return $output .= '<div class="error">' . wfMsgForContent( 'loops_max' ) . '</div>';
304324 }
305 -
306 - public function onParserClearState( &$parser ) {
307 - $this->loopCount = 0;
308 -
 325+
 326+
 327+ ##################
 328+ # Hooks handling #
 329+ ##################
 330+
 331+ public static function onParserClearState( Parser &$parser ) {
 332+ // reset loops counter since the parser process finished one page
 333+ $parser->mExtLoopsCounter = 0;
309334 return true;
310335 }
311336 }
Index: trunk/extensions/Loops/RELEASE-NOTES
@@ -1,14 +1,23 @@
22 Post svn Changelog:
33 ===================
44
5 - * Version 0.3.2 by Daniel Werner
 5+ * (trunk) -- Version 0.4 alpha by Daniel Werner
 6+ - The loops count now counts per parser instance. Before there were several hacks to reset the
 7+ counter, for example including an special page in wikitext. This has been solved now.
 8+ - Language file clean-up.
 9+ - Internal structure changed, ExtLoops now works as a static class.
 10+ @ToDo: Open points for final 0.4 release:
 11+ - Compatbility to Variables Version 2.0.
 12+ - '#fornumargs' parameter 1 optional to make it more consistent with other functions.
 13+
 14+ * November 15, 2011 -- Version 0.3.2 by Daniel Werner
615 - Bug solved where '#loop' didn't create variables with name or starting index '0'.
716 - minor '#forargs' and '#fornumargs' bug solved where unnamed numeric argument values
817 could have ended up as variable value with leading space.
918 - 'README' and 'RELEASE-NOTES' files added.
1019 - Put into mediawiki.org svn repository.
 20+
1121
12 -
1322 Pre svn Changelog:
1423 ==================
1524

Status & tagging log