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 |
1 | 57 | + 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 |
1 | 312 | + 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
|