Index: trunk/extensions/ArrayExtension/ArrayExtension.php |
— | — | @@ -44,9 +44,7 @@ |
45 | 45 | * get_total_col |
46 | 46 | */ |
47 | 47 | |
48 | | -if ( ! defined( 'MEDIAWIKI' ) ) { |
49 | | - die( 'This file is a MediaWiki extension, it is not a valid entry point' ); |
50 | | -} |
| 48 | +if ( ! defined( 'MEDIAWIKI' ) ) { die(); } |
51 | 49 | |
52 | 50 | $wgExtensionCredits['parserhook'][] = array( |
53 | 51 | 'path' => __FILE__, |
— | — | @@ -54,39 +52,41 @@ |
55 | 53 | 'url' => 'http://www.mediawiki.org/wiki/Extension:ArrayExtension', |
56 | 54 | 'author' => array ( 'Li Ding', 'Jie Bao', '[http://www.mediawiki.org/wiki/User:Danwe Daniel Werner]' ), |
57 | 55 | 'descriptionmsg' => 'arrayext-desc', |
58 | | - 'version' => ArrayExtension::VERSION |
| 56 | + 'version' => ExtArrayExtension::VERSION |
59 | 57 | ); |
60 | 58 | |
61 | | -$wgHooks['ParserFirstCallInit'][] = 'efArrayExtensionParserFirstCallInit'; |
| 59 | +$wgExtensionMessagesFiles['ArrayExtension' ] = ExtArrayExtension::getDir() . '/ArrayExtension.i18n.php'; |
| 60 | +$wgExtensionMessagesFiles['ArrayExtensionMagic'] = ExtArrayExtension::getDir() . '/ArrayExtension.i18n.magic.php'; |
62 | 61 | |
63 | | -$dir = dirname( __FILE__ ); |
| 62 | +// hooks registration: |
| 63 | +$wgHooks['ParserFirstCallInit'][] = 'ExtArrayExtension::init'; |
| 64 | +$wgHooks['ParserClearState' ][] = 'ExtArrayExtension::onParserClearState'; |
64 | 65 | |
65 | | -$wgExtensionMessagesFiles['ArrayExtension' ] = $dir . '/ArrayExtension.i18n.php'; |
66 | | -$wgExtensionMessagesFiles['ArrayExtensionMagic'] = $dir . '/ArrayExtension.i18n.magic.php'; |
67 | 66 | |
68 | | -unset( $dir ); |
69 | | - |
70 | 67 | /** |
71 | 68 | * Full compatbility to versions before 1.4 |
72 | 69 | * |
73 | | - * @since 1.4 |
| 70 | + * @since 1.4 alpha |
74 | 71 | * |
75 | 72 | * @var boolean |
76 | 73 | */ |
77 | | -$egArrayExtensionCompatbilityMode = true; |
| 74 | +$egArrayExtensionCompatbilityMode = false; |
78 | 75 | |
79 | 76 | |
80 | 77 | /** |
81 | | - * named arrays - an array has a list of values, and could be set to a SET |
| 78 | + * Extension class with all the array functionality, also serves as store for arrays per |
| 79 | + * Parser object and offers public accessors for interaction with ArrayExtension. |
| 80 | + * |
| 81 | + * @since 2.0 ('ArrayExtension' before and one global instance, also non-static parser functions) |
82 | 82 | */ |
83 | | -class ArrayExtension { |
| 83 | +class ExtArrayExtension { |
84 | 84 | |
85 | 85 | /** |
86 | 86 | * Version of the ArrayExtension extension. |
87 | 87 | * |
88 | | - * @since 1.3.2 |
| 88 | + * @since 2.0 (before in 'ArrayExtension' class since 1.3.2) |
89 | 89 | */ |
90 | | - const VERSION = '1.4 alpha'; |
| 90 | + const VERSION = '2.0 alpha'; |
91 | 91 | |
92 | 92 | /** |
93 | 93 | * Store for arrays. |
— | — | @@ -94,18 +94,67 @@ |
95 | 95 | * @var array |
96 | 96 | * @private |
97 | 97 | */ |
98 | | - var $mArrayExtension = array(); |
| 98 | + var $mArrays = array(); |
99 | 99 | |
100 | | - function __construct() { |
101 | | - global $wgHooks; |
102 | | - $wgHooks['ParserClearState'][] = &$this; |
103 | | - } |
| 100 | + /** |
| 101 | + * Sets up parser functions |
| 102 | + * |
| 103 | + * @since 2.0 |
| 104 | + */ |
| 105 | + public static function init( Parser &$parser ) { |
| 106 | + /* |
| 107 | + * store for arrays per Parser object. This will solve several bugs related to |
| 108 | + * 'ParserClearState' hook clearing all variables early in combination with certain |
| 109 | + * other extensions. (since v2.0) |
| 110 | + */ |
| 111 | + $parser->mExtArrayExtension = new self(); |
104 | 112 | |
105 | | - function onParserClearState( Parser &$parser ) { |
106 | | - // remove all arrays to avoid conflicts with job queue or Special:Import or SMW semantic updates |
107 | | - $this->mArrayExtension = array(); |
| 113 | + // SFH_OBJECT_ARGS available since MW 1.12 |
| 114 | + self::initFunction( $parser, 'arraydefine' ); |
| 115 | + self::initFunction( $parser, 'arrayprint', SFH_OBJECT_ARGS ); |
| 116 | + self::initFunction( $parser, 'arrayindex', SFH_OBJECT_ARGS ); |
| 117 | + self::initFunction( $parser, 'arraysize' ); |
| 118 | + self::initFunction( $parser, 'arraysearch', SFH_OBJECT_ARGS ); |
| 119 | + self::initFunction( $parser, 'arraysearcharray' ); |
| 120 | + self::initFunction( $parser, 'arrayslice' ); |
| 121 | + self::initFunction( $parser, 'arrayreset', SFH_OBJECT_ARGS ); |
| 122 | + self::initFunction( $parser, 'arrayunique' ); |
| 123 | + self::initFunction( $parser, 'arraysort' ); |
| 124 | + self::initFunction( $parser, 'arraymerge' ); |
| 125 | + self::initFunction( $parser, 'arrayunion' ); |
| 126 | + self::initFunction( $parser, 'arraydiff' ); |
| 127 | + self::initFunction( $parser, 'arrayintersect' ); |
| 128 | + |
108 | 129 | return true; |
109 | 130 | } |
| 131 | + private static function initFunction( Parser &$parser, $name, $flags = 0 ) { |
| 132 | + // all parser functions with prefix: |
| 133 | + $prefix = ( $flags & SFH_OBJECT_ARGS ) ? 'pfObj_' : 'pf_'; |
| 134 | + $functionCallback = array( __CLASS__, $prefix . $name ); |
| 135 | + |
| 136 | + $parser->setFunctionHook( $name, $functionCallback, $flags ); |
| 137 | + } |
| 138 | + |
| 139 | + /** |
| 140 | + * Returns the extensions base installation directory. |
| 141 | + * |
| 142 | + * @since 2.0 |
| 143 | + * |
| 144 | + * @return boolean |
| 145 | + */ |
| 146 | + public static function getDir() { |
| 147 | + static $dir = null; |
| 148 | + |
| 149 | + if( $dir === null ) { |
| 150 | + $dir = dirname( __FILE__ ); |
| 151 | + } |
| 152 | + return $dir; |
| 153 | + } |
| 154 | + |
| 155 | + |
| 156 | + #################### |
| 157 | + # Parser Functions # |
| 158 | + #################### |
110 | 159 | |
111 | 160 | /////////////////////////////////////////////////////////// |
112 | 161 | // PART 1. constructor |
— | — | @@ -120,7 +169,7 @@ |
121 | 170 | * http://us2.php.net/manual/en/book.pcre.php |
122 | 171 | * see also: http://us2.php.net/manual/en/function.preg-split.php |
123 | 172 | */ |
124 | | - function arraydefine( |
| 173 | + static function pf_arraydefine( |
125 | 174 | Parser &$parser, |
126 | 175 | $arrayId, |
127 | 176 | $value = null, |
— | — | @@ -157,7 +206,7 @@ |
158 | 207 | } |
159 | 208 | else { |
160 | 209 | // if no regex delimiter given, build one: |
161 | | - if( ! $this->isValidRegEx( $delimiter ) ) { |
| 210 | + if( ! self::isValidRegEx( $delimiter ) ) { |
162 | 211 | $delimiter = '/\s*' . preg_quote( $delimiter, '/' ) . '\s*/'; |
163 | 212 | $trimDone = true; // spaces are part of the delimiter now |
164 | 213 | } |
— | — | @@ -166,16 +215,16 @@ |
167 | 216 | |
168 | 217 | // trim all values before unique if still necessary, otherwise unique might not work correctly |
169 | 218 | if( ! $trimDone ) { |
170 | | - $array = $this->sanitizeArray( $array ); |
| 219 | + $array = self::sanitizeArray( $array ); |
171 | 220 | } |
172 | 221 | |
173 | 222 | // now parse the options, and do posterior process on the created array |
174 | | - $arrayOptions = $this->parse_options( $options ); |
| 223 | + $arrayOptions = self::parse_options( $options ); |
175 | 224 | |
176 | 225 | // make it unique if option is set |
177 | 226 | if( array_key_exists( 'unique', $arrayOptions ) ) { |
178 | 227 | // unique like the parser function would do it |
179 | | - $array = $this->array_unique( $array ); |
| 228 | + $array = self::array_unique( $array ); |
180 | 229 | } |
181 | 230 | |
182 | 231 | /** |
— | — | @@ -201,21 +250,21 @@ |
202 | 251 | */ |
203 | 252 | |
204 | 253 | // sort array if the option is set |
205 | | - $this->arraysort( $parser, $arrayId, $this->array_value( $arrayOptions, 'sort' ) ); |
| 254 | + self::pf_arraysort( $parser, $arrayId, self::array_value( $arrayOptions, 'sort' ) ); |
206 | 255 | |
207 | 256 | // print the array upon request |
208 | | - switch( $this->array_value( $arrayOptions, 'print' ) ) { |
| 257 | + switch( self::array_value( $arrayOptions, 'print' ) ) { |
209 | 258 | case 'list': |
210 | | - $out = $this->arrayprint( $parser, $arrayId ); |
| 259 | + $out = self::pf_arrayprint( $parser, $arrayId ); |
211 | 260 | break; |
212 | 261 | |
213 | | - case 'print': |
214 | | - $out = $this->arrayprint( $parser, $arrayId, $delimiter2, $search, $subject, $frame ); |
| 262 | + case 'print': |
| 263 | + $out = self::pf_arrayprint( $parser, $arrayId, $delimiter2, $search, $subject, $frame ); |
215 | 264 | break; |
216 | 265 | } |
217 | 266 | } |
218 | | - |
219 | | - $this->mArrayExtension[ $arrayId ] = $array; |
| 267 | + |
| 268 | + self::get( $parser )->setArray( $arrayId, $array ); |
220 | 269 | |
221 | 270 | return $out; |
222 | 271 | } |
— | — | @@ -241,52 +290,47 @@ |
242 | 291 | * {{#arrayprint:b|<br/>|@@@|{{f.tag{{f.print.vbar}}prop{{f.print.vbar}}@@@}} }} -- embed template function |
243 | 292 | * {{#arrayprint:b|<br/>|@@@|[[name::@@@]]}} -- make SMW links |
244 | 293 | */ |
245 | | - function arrayprint( Parser &$parser, $arrayId , $delimiter = ', ', $search = '@@@@', $subject = '@@@@', $frame = null ) { |
246 | | - $ret = $this->validate_array_by_arrayId( $arrayId ); |
247 | | - if ( $ret !== true ) { |
248 | | - return $ret; |
| 294 | + static function pf_arrayprint( Parser &$parser, $arrayId , $delimiter = ', ', $search = '@@@@', $subject = '@@@@', $frame = null ) { |
| 295 | + // get array, null if non-existant: |
| 296 | + $array = self::get( $parser )->getArray( $arrayId ); |
| 297 | + |
| 298 | + if( $array === null ) { |
| 299 | + return ''; |
249 | 300 | } |
250 | 301 | |
251 | | - $values = $this->mArrayExtension[$arrayId]; |
252 | 302 | $rendered_values = array(); |
253 | | - foreach ( $values as $v ) { |
254 | | - $temp_result_value = str_replace( $search, $v, $subject ); |
255 | | - // frame is only available in newer MW versions |
256 | | - if ( isset( $frame ) ) { |
257 | | - /* |
258 | | - * in case frame is given (new MW versions) the $subjectd still is un-expanded (this allows to use |
259 | | - * some parser functions like {{FULLPAGENAME:@@@@}} directly without getting parsed before @@@@ is replaced. |
260 | | - * Expand it so we replace templates like {{!}} which we need for the final parse. |
261 | | - */ |
262 | | - $temp_result_value = $parser->preprocessToDom( $temp_result_value, $frame->isTemplate() ? Parser::PTD_FOR_INCLUSION : 0 ); |
263 | | - $temp_result_value = trim( $frame->expand( $temp_result_value ) ); |
264 | | - } |
265 | | - $rendered_values[] = $temp_result_value; |
| 303 | + foreach( $array as $val ) { |
| 304 | + // replace place holder with current value: |
| 305 | + $rawResult = str_replace( $search, $val, $subject ); |
| 306 | + |
| 307 | + /* |
| 308 | + * $subjectd still is un-expanded (this allows to use some parser functions like |
| 309 | + * {{FULLPAGENAME:@@@@}} directly without getting parsed before @@@@ is replaced. |
| 310 | + * Expand it so we replace templates like {{!}} which we need for the final parse. |
| 311 | + */ |
| 312 | + $rawResult = $parser->preprocessToDom( $rawResult, $frame->isTemplate() ? Parser::PTD_FOR_INCLUSION : 0 ); |
| 313 | + $rawResult = trim( $frame->expand( $rawResult ) ); |
| 314 | + |
| 315 | + $rendered_values[] = $rawResult; |
266 | 316 | } |
267 | 317 | |
268 | 318 | $output = implode( $delimiter, $rendered_values ); |
269 | 319 | $noparse = false; |
270 | | - |
271 | | - if ( isset( $frame ) ) { |
272 | | - /* |
273 | | - * don't leave the final parse to Parser::braceSubstitution() since there are some special cases where it |
274 | | - * would produce unexpected output (it uses a new child frame and ignores whether the frame is a template!) |
275 | | - */ |
276 | | - $noparse = true; |
277 | 320 | |
278 | | - $output = $parser->preprocessToDom( $output, $frame->isTemplate() ? Parser::PTD_FOR_INCLUSION : 0 ); |
279 | | - $output = trim( $frame->expand( $output ) ); |
280 | | - } |
| 321 | + /* |
| 322 | + * don't leave the final parse to Parser::braceSubstitution() since there are some special cases where it |
| 323 | + * would produce unexpected output (it uses a new child frame and ignores whether the frame is a template!) |
| 324 | + */ |
| 325 | + $noparse = true; |
| 326 | + |
| 327 | + $output = $parser->preprocessToDom( $output, $frame->isTemplate() ? Parser::PTD_FOR_INCLUSION : 0 ); |
| 328 | + $output = trim( $frame->expand( $output ) ); |
281 | 329 | |
282 | | - return array( |
283 | | - $output, |
284 | | - 'noparse' => $noparse, |
285 | | - 'isHTML' => false |
286 | | - ); |
| 330 | + return $output; |
287 | 331 | } |
288 | 332 | |
289 | | - function arrayprintObj( Parser &$parser, $frame, $args ) { |
290 | | - // Set variables |
| 333 | + static function pfObj_arrayprint( Parser &$parser, $frame, $args ) { |
| 334 | + // Get Parameters |
291 | 335 | $arrayId = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : ''; |
292 | 336 | $delimiter = isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) : ', '; |
293 | 337 | /* |
— | — | @@ -297,36 +341,52 @@ |
298 | 342 | $search = isset( $args[2] ) ? trim( $frame->expand( $args[2], PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES ) ) : '@@@@'; |
299 | 343 | $subject = isset( $args[3] ) ? trim( $frame->expand( $args[3], PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES ) ) : '@@@@'; |
300 | 344 | |
301 | | - return $this->arrayprint( $parser, $arrayId, $delimiter, $search, $subject, $frame ); |
| 345 | + return self::pf_arrayprint( $parser, $arrayId, $delimiter, $search, $subject, $frame ); |
302 | 346 | } |
303 | | - |
304 | | - |
| 347 | + |
| 348 | + |
305 | 349 | /** |
306 | 350 | * print the value of an array (identified by arrayid) by the index, invalid index results in the default value being printed. note the index is 0-based. |
307 | 351 | * usage: |
308 | 352 | * {{#arrayindex:arrayid|index}} |
309 | 353 | */ |
310 | | - function arrayindex( Parser &$parser, $arrayId , $index , $defaultOrOptions = '' ) { |
311 | | - // index must exist, strict check, non-numeric will fail: |
312 | | - if( true !== $this->validate_array_by_arrayId( $arrayId ) |
313 | | - || ! $this->validate_array_index( $arrayId, $index, true ) |
314 | | - ) { |
315 | | - // index doesn't exist, return default |
316 | | - global $egArrayExtensionCompatbilityMode; |
| 354 | + static function pfObj_arrayindex( Parser &$parser, PPFrame $frame, $args ) { |
| 355 | + global $egArrayExtensionCompatbilityMode; |
| 356 | + |
| 357 | + // Get Parameters |
| 358 | + $arrayId = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : ''; |
| 359 | + $rawOptions = isset( $args[2] ) ? $args[2] : ''; |
| 360 | + |
| 361 | + if( ! isset( $args[1] ) ) { |
| 362 | + return ''; |
| 363 | + } |
| 364 | + $index = trim( $frame->expand( $args[1] ) ); |
| 365 | + |
| 366 | + // get value or null if it doesn't exist. Takes care of negative index as well |
| 367 | + $val = self::get( $parser )->getArrayValue( $arrayId, $index ); |
| 368 | + |
| 369 | + if( $val === null || ( $val === '' && !$egArrayExtensionCompatbilityMode ) ) { |
| 370 | + // index doesn't exist, return default (parameter 3)! |
| 371 | + // without compatbility, also return default in case of empty string '' |
317 | 372 | |
| 373 | + // only expand default when needed |
| 374 | + $defaultOrOptions = trim( $frame->expand( $rawOptions ) ); |
| 375 | + |
318 | 376 | if( $egArrayExtensionCompatbilityMode ) { |
319 | 377 | // COMPATBILITY-MODE |
320 | 378 | // now parse the options, and do posterior process on the created array |
321 | | - $ary_option = $this->parse_options( $defaultOrOptions ); |
322 | | - return $this->array_value( $ary_option, 'default' ); |
| 379 | + $options = self::parse_options( $defaultOrOptions ); |
| 380 | + $default = self::array_value( $options, 'default' ); |
323 | 381 | } else { |
324 | | - return $defaultOrOptions; |
| 382 | + $default = $defaultOrOptions; |
325 | 383 | } |
| 384 | + |
| 385 | + return $default; |
326 | 386 | } |
327 | | - |
328 | | - return $this->mArrayExtension[ $arrayId ][ $index ]; |
| 387 | + |
| 388 | + return $val; |
329 | 389 | } |
330 | | - |
| 390 | + |
331 | 391 | /** |
332 | 392 | * returns the size of an array. |
333 | 393 | * Print the size (number of elements) in the specified array and '' if array doesn't exist |
— | — | @@ -335,18 +395,17 @@ |
336 | 396 | * |
337 | 397 | * See: http://www.php.net/manual/en/function.count.php |
338 | 398 | */ |
339 | | - function arraysize( Parser &$parser, $arrayId ) { |
340 | | - if( ! $this->arrayExists( $arrayId ) ) { |
| 399 | + static function pf_arraysize( Parser &$parser, $arrayId ) { |
| 400 | + $store = self::get( $parser ); |
| 401 | + |
| 402 | + if( ! $store->arrayExists( $arrayId ) ) { |
341 | 403 | return ''; |
342 | 404 | } |
343 | 405 | |
344 | | - return count( $this->mArrayExtension[ $arrayId ] ); |
| 406 | + return count( $store->getArray( $arrayId ) ); |
345 | 407 | } |
346 | 408 | |
347 | | - |
348 | | - |
349 | | - |
350 | | - |
| 409 | + |
351 | 410 | /** |
352 | 411 | * locate the index of the first occurence of an element starting from the 'index' |
353 | 412 | * - print "-1" (not found) or index (found) to show the index of the first occurence of 'value' in the array identified by arrayid |
— | — | @@ -358,22 +417,24 @@ |
359 | 418 | * See: http://www.php.net/manual/en/function.array-search.php |
360 | 419 | * note it is extended to support regular expression match and index |
361 | 420 | */ |
362 | | - function arraysearch( Parser &$parser, PPFrame $frame, $args ) { |
| 421 | + static function pfObj_arraysearch( Parser &$parser, PPFrame $frame, $args ) { |
363 | 422 | |
364 | 423 | $arrayId = trim( $frame->expand( $args[0] ) ); |
365 | 424 | $index = isset( $args[2] ) ? trim( $frame->expand( $args[2] ) ) : 0; |
366 | 425 | |
367 | | - if( $this->arrayExists( $arrayId ) |
368 | | - && $this->validate_array_index( $arrayId, $index, false ) |
| 426 | + $store = self::get( $parser ); |
| 427 | + |
| 428 | + if( $store->arrayExists( $arrayId ) |
| 429 | + && $store->validate_array_index( $arrayId, $index, false ) |
369 | 430 | ) { |
370 | | - $array = $this->mArrayExtension[ $arrayId ]; |
| 431 | + $array = $store->getArray( $arrayId ); |
371 | 432 | |
372 | 433 | // validate/build search regex: |
373 | 434 | if( isset( $args[1] ) ) { |
374 | 435 | |
375 | 436 | $needle = trim( $frame->expand( $args[1] ) ); |
376 | 437 | |
377 | | - if ( ! $this->isValidRegEx( $needle ) ) { |
| 438 | + if ( ! self::isValidRegEx( $needle ) ) { |
378 | 439 | $needle = '/^\s*' . preg_quote( trim( $needle ), '/' ) . '\s*$/'; |
379 | 440 | } |
380 | 441 | } |
— | — | @@ -417,7 +478,7 @@ |
418 | 479 | * "needle" can be a regular expression or a string search value. If "needle" is a regular expression, "transform" can contain |
419 | 480 | * "$n" where "n" stands for a number to access a variable from the regex result. |
420 | 481 | */ |
421 | | - function arraysearcharray( |
| 482 | + static function pf_arraysearcharray( |
422 | 483 | Parser &$parser, |
423 | 484 | $arrayId_new, |
424 | 485 | $arrayId = null, |
— | — | @@ -425,21 +486,23 @@ |
426 | 487 | $index = 0, |
427 | 488 | $limit = -1, |
428 | 489 | $transform = '' |
429 | | - ) { |
| 490 | + ) { |
| 491 | + $store = self::get( $parser ); |
| 492 | + |
430 | 493 | if( $arrayId === null ) { |
431 | 494 | global $egArrayExtensionCompatbilityMode; |
432 | 495 | if( ! $egArrayExtensionCompatbilityMode ) { // COMPATBILITY-MODE |
433 | | - $this->setArray( $arrayId_new ); |
| 496 | + $store->setArray( $arrayId_new ); |
434 | 497 | } |
435 | 498 | return ''; |
436 | 499 | } |
437 | 500 | // also takes care of negative index by calculating start index: |
438 | | - $validIndex = $this->validate_array_index( $arrayId, $index, false ); |
| 501 | + $validIndex = $store->validate_array_index( $arrayId, $index, false ); |
439 | 502 | |
440 | 503 | // make sure at least empty array exists but don't overwrite data |
441 | 504 | // we still need in case new array ID same as target array ID |
442 | | - $array = $this->getArray( $arrayId ); |
443 | | - $this->setArray( $arrayId_new ); |
| 505 | + $array = $store->getArray( $arrayId ); |
| 506 | + $store->setArray( $arrayId_new ); |
444 | 507 | |
445 | 508 | if( $array === null || !$validIndex ) { |
446 | 509 | return ''; |
— | — | @@ -453,7 +516,7 @@ |
454 | 517 | |
455 | 518 | $newArr = array(); |
456 | 519 | |
457 | | - if( !$this->isValidRegEx( $needle ) ) { |
| 520 | + if( ! self::isValidRegEx( $needle ) ) { |
458 | 521 | $needle = '/^\s*(' . preg_quote( $needle, '/' ) . ')\s*$/'; |
459 | 522 | } |
460 | 523 | |
— | — | @@ -477,7 +540,7 @@ |
478 | 541 | } |
479 | 542 | |
480 | 543 | // set new array: |
481 | | - $this->setArray( $arrayId_new, $newArr ); |
| 544 | + $store->setArray( $arrayId_new, $newArr ); |
482 | 545 | return ''; |
483 | 546 | } |
484 | 547 | |
— | — | @@ -493,7 +556,7 @@ |
494 | 557 | * {{#arrayreset:}} |
495 | 558 | * {{#arrayreset:arrayid1,arrayid2,...arrayidn}} |
496 | 559 | */ |
497 | | - function arrayreset( Parser &$parser, PPFrame $frame, $args) { |
| 560 | + static function pfObj_arrayreset( Parser &$parser, PPFrame $frame, $args) { |
498 | 561 | global $egArrayExtensionCompatbilityMode; |
499 | 562 | |
500 | 563 | if( $egArrayExtensionCompatbilityMode && count( $args ) == 1 ) { |
— | — | @@ -501,18 +564,20 @@ |
502 | 565 | * COMPATBILITY-MODE: before arrays were separated by ';' which is an bad idea since |
503 | 566 | * the ',' is an allowed character in array names! |
504 | 567 | */ |
505 | | - $args = preg_split( '/\s*,\s*/', $args[0] ); |
| 568 | + $args = preg_split( '/\s*,\s*/', trim( $frame->expand( $args[0] ) ) ); |
506 | 569 | } |
507 | 570 | |
| 571 | + $store = self::get( $parser ); |
| 572 | + |
508 | 573 | // reset all hash tables if no specific tables are given: |
509 | 574 | if( ! isset( $args[0] ) || ( $args[0] === '' && count( $args ) == 1 ) ) { |
510 | | - $this->mArrayExtension = array(); |
| 575 | + $store->mArrays = array(); |
511 | 576 | } |
512 | 577 | else { |
513 | 578 | // reset specific hash tables: |
514 | 579 | foreach( $args as $arg ) { |
515 | 580 | $arrayId = trim( $frame->expand( $arg ) ); |
516 | | - $this->unsetArray( $arrayId ); |
| 581 | + $store->unsetArray( $arrayId ); |
517 | 582 | } |
518 | 583 | } |
519 | 584 | return ''; |
— | — | @@ -528,9 +593,13 @@ |
529 | 594 | * |
530 | 595 | * see: http://www.php.net/manual/en/function.array-unique.php |
531 | 596 | */ |
532 | | - function pf_arrayunique( Parser &$parser, $arrayId ) { |
533 | | - if( $this->arrayExists( $arrayId ) ) { |
534 | | - $this->mArrayExtension[ $arrayId ] = $this->array_unique( $this->mArrayExtension[ $arrayId ] ); |
| 597 | + static function pf_arrayunique( Parser &$parser, $arrayId ) { |
| 598 | + $store = self::get( $parser ); |
| 599 | + |
| 600 | + if( $store->arrayExists( $arrayId ) ) { |
| 601 | + $array = $store->getArray( $arrayId ); |
| 602 | + $array = self::array_unique( $array ); |
| 603 | + $store->setArray( $arrayId, $array ); |
535 | 604 | } |
536 | 605 | return ''; |
537 | 606 | } |
— | — | @@ -551,8 +620,10 @@ |
552 | 621 | * http://www.php.net/manual/en/function.shuffle.php |
553 | 622 | * http://us3.php.net/manual/en/function.array-reverse.php |
554 | 623 | */ |
555 | | - function arraysort( Parser &$parser, $arrayId , $sort = 'none' ) { |
556 | | - if( ! $this->arrayExists( $arrayId ) ) { |
| 624 | + static function pf_arraysort( Parser &$parser, $arrayId , $sort = 'none' ) { |
| 625 | + $store = self::get( $parser ); |
| 626 | + |
| 627 | + if( ! $store->arrayExists( $arrayId ) ) { |
557 | 628 | return ''; |
558 | 629 | } |
559 | 630 | |
— | — | @@ -561,20 +632,20 @@ |
562 | 633 | case 'asc': |
563 | 634 | case 'asce': |
564 | 635 | case 'ascending': |
565 | | - sort( $this->mArrayExtension[ $arrayId ] ); |
| 636 | + sort( $store->mArrays[ $arrayId ] ); |
566 | 637 | break; |
567 | 638 | |
568 | 639 | case 'desc': |
569 | 640 | case 'descending': |
570 | | - rsort( $this->mArrayExtension[ $arrayId ] ); |
| 641 | + rsort( $store->mArrays[ $arrayId ] ); |
571 | 642 | break; |
572 | 643 | |
573 | 644 | case 'random': |
574 | | - shuffle( $this->mArrayExtension[ $arrayId ] ); |
| 645 | + shuffle( $store->mArrays[ $arrayId ] ); |
575 | 646 | break; |
576 | 647 | |
577 | 648 | case 'reverse': |
578 | | - $this->mArrayExtension[ $arrayId ] = array_reverse( $this->mArrayExtension[ $arrayId ] ); |
| 649 | + $store->mArrays[ $arrayId ] = array_reverse( $store->mArrays[ $arrayId ] ); |
579 | 650 | break; |
580 | 651 | } ; |
581 | 652 | } |
— | — | @@ -592,30 +663,32 @@ |
593 | 664 | * merge values two arrayes identified by arrayid1 and arrayid2 into a new array identified by arrayid_new. |
594 | 665 | * this merge differs from array_merge of php because it merges values. |
595 | 666 | */ |
596 | | - function arraymerge( Parser &$parser, $arrayId_new, $arrayId1 = null, $arrayId2 = null ) { |
597 | | - if( ! isset( $arrayId_new ) || ! isset( $arrayId1 ) || ! isset( $arrayId2 ) ) |
| 667 | + static function pf_arraymerge( Parser &$parser, $arrayId_new, $arrayId1 = null, $arrayId2 = null ) { |
| 668 | + if( ! isset( $arrayId_new ) || ! isset( $arrayId1 ) || ! isset( $arrayId2 ) ) { |
598 | 669 | return ''; |
599 | | - |
600 | | - $ret = $this->validate_array_by_arrayId( $arrayId1 ); |
| 670 | + } |
| 671 | + $store = self::get( $parser ); |
| 672 | + |
| 673 | + $ret = $store->validate_array_by_arrayId( $arrayId1 ); |
601 | 674 | if( $ret !== true ) { |
602 | 675 | return ''; |
603 | 676 | } |
604 | 677 | |
605 | 678 | $temp_array = array(); |
606 | | - foreach( $this->mArrayExtension[ $arrayId1 ] as $entry ) { |
| 679 | + foreach( $store->mArrays[ $arrayId1 ] as $entry ) { |
607 | 680 | array_push ( $temp_array, $entry ); |
608 | 681 | } |
609 | 682 | |
610 | 683 | if( isset( $arrayId2 ) && strlen( $arrayId2 ) > 0 ) { |
611 | | - $ret = $this->validate_array_by_arrayId( $arrayId2 ); |
| 684 | + $ret = $store->validate_array_by_arrayId( $arrayId2 ); |
612 | 685 | if( $ret === true ) { |
613 | | - foreach( $this->mArrayExtension[ $arrayId2 ] as $entry ) { |
| 686 | + foreach( $store->mArrays[ $arrayId2 ] as $entry ) { |
614 | 687 | array_push ( $temp_array, $entry ); |
615 | 688 | } |
616 | 689 | } |
617 | 690 | } |
618 | 691 | |
619 | | - $this->mArrayExtension[$arrayId_new] = $temp_array; |
| 692 | + $store->mArrays[$arrayId_new] = $temp_array; |
620 | 693 | return ''; |
621 | 694 | } |
622 | 695 | |
— | — | @@ -627,19 +700,20 @@ |
628 | 701 | * extract a slice from an array |
629 | 702 | * see: http://www.php.net/manual/en/function.array-slice.php |
630 | 703 | */ |
631 | | - function arrayslice( Parser &$parser, $arrayId_new, $arrayId = null , $offset = 0, $length = null ) { |
| 704 | + static function pf_arrayslice( Parser &$parser, $arrayId_new, $arrayId = null , $offset = 0, $length = null ) { |
| 705 | + $store = self::get( $parser ); |
632 | 706 | if( $arrayId === null ) { |
633 | 707 | global $egArrayExtensionCompatbilityMode; |
634 | 708 | if( ! $egArrayExtensionCompatbilityMode ) { // COMPATBILITY-MODE |
635 | | - $this->setArray( $arrayId_new ); |
| 709 | + $store->setArray( $arrayId_new ); |
636 | 710 | } |
637 | 711 | return ''; |
638 | 712 | } |
639 | 713 | // get target array before overwriting it in any way |
640 | | - $array = $this->getArray( $arrayId ); |
| 714 | + $array = $store->getArray( $arrayId ); |
641 | 715 | |
642 | 716 | // make sure at least an empty array exists if we return early |
643 | | - $this->setArray( $arrayId_new ); |
| 717 | + $store->setArray( $arrayId_new ); |
644 | 718 | |
645 | 719 | if( $array === null |
646 | 720 | || ! is_numeric( $offset ) // don't ignore invalid offset |
— | — | @@ -652,8 +726,8 @@ |
653 | 727 | } |
654 | 728 | |
655 | 729 | // array_slice will re-organize keys |
656 | | - $newArray = array_slice( $array, $offset, $length ); |
657 | | - $this->mArrayExtension[ $arrayId_new ] = $newArray; |
| 730 | + $newArray = array_slice( $array, $offset, $length ); |
| 731 | + $store->setArray( $arrayId_new, $newArray ); |
658 | 732 | |
659 | 733 | return ''; |
660 | 734 | } |
— | — | @@ -668,20 +742,21 @@ |
669 | 743 | |
670 | 744 | * similar to arraymerge, this union works on values. |
671 | 745 | */ |
672 | | - function arrayunion( Parser &$parser, $arrayId_new, $arrayId1 = null , $arrayId2 = null ) { |
| 746 | + static function pf_arrayunion( Parser &$parser, $arrayId_new, $arrayId1 = null , $arrayId2 = null ) { |
| 747 | + $store = self::get( $parser ); |
673 | 748 | if ( ! isset( $arrayId_new ) || ! isset( $arrayId1 ) || ! isset( $arrayId2 ) ) { |
674 | 749 | return ''; |
675 | 750 | } |
676 | | - if( ! isset( $arrayId1 ) || ! $this->arrayExists( $arrayId1 ) ) { |
| 751 | + if( ! isset( $arrayId1 ) || ! $store->arrayExists( $arrayId1 ) ) { |
677 | 752 | return ''; |
678 | 753 | } |
679 | | - if( ! isset( $arrayId2 ) || ! $this->arrayExists( $arrayId2 ) ) { |
| 754 | + if( ! isset( $arrayId2 ) || ! $store->arrayExists( $arrayId2 ) ) { |
680 | 755 | return ''; |
681 | 756 | } |
682 | 757 | |
683 | | - $this->arraymerge( $parser, $arrayId_new, $arrayId1, $arrayId2 ); |
684 | | - $this->mArrayExtension[$arrayId_new] = array_unique ( $this->mArrayExtension[$arrayId_new] ); |
685 | | - |
| 758 | + self::pf_arraymerge( $parser, $arrayId_new, $arrayId1, $arrayId2 ); |
| 759 | + $store->setArray( $arrayId_new, array_unique ( $store->getArray( $arrayId_new ) ) ); |
| 760 | + |
686 | 761 | return ''; |
687 | 762 | } |
688 | 763 | |
— | — | @@ -691,22 +766,23 @@ |
692 | 767 | * {{#arrayintersect:arrayid_new|arrayid1|arrayid2}} |
693 | 768 | * See: http://www.php.net/manual/en/function.array-intersect.php |
694 | 769 | */ |
695 | | - function arrayintersect( Parser &$parser, $arrayId_new, $arrayId1 = null , $arrayId2 = null ) { |
| 770 | + static function pf_arrayintersect( Parser &$parser, $arrayId_new, $arrayId1 = null , $arrayId2 = null ) { |
| 771 | + $store = self::get( $parser ); |
696 | 772 | if ( ! isset( $arrayId_new ) || ! isset( $arrayId1 ) || ! isset( $arrayId2 ) ) { |
697 | 773 | return ''; |
698 | 774 | } |
699 | | - if( ! isset( $arrayId1 ) || ! $this->arrayExists( $arrayId1 ) ) { |
| 775 | + if( ! isset( $arrayId1 ) || ! $store->arrayExists( $arrayId1 ) ) { |
700 | 776 | return ''; |
701 | 777 | } |
702 | | - if( ! isset( $arrayId2 ) || ! $this->arrayExists( $arrayId2 ) ) { |
| 778 | + if( ! isset( $arrayId2 ) || ! $store->arrayExists( $arrayId2 ) ) { |
703 | 779 | return ''; |
704 | 780 | } |
705 | 781 | |
706 | 782 | // keys will be preserved... |
707 | | - $newArray = array_intersect( array_unique( $this->mArrayExtension[$arrayId1] ), array_unique( $this->mArrayExtension[$arrayId2] ) ); |
| 783 | + $newArray = array_intersect( array_unique( $store->mArrays[$arrayId1] ), array_unique( $store->mArrays[$arrayId2] ) ); |
708 | 784 | |
709 | 785 | // ...so we have to reorganize the key order |
710 | | - $this->mArrayExtension[$arrayId_new] = $this->sanitizeArray( $newArray ); |
| 786 | + $store->mArrays[$arrayId_new] = self::sanitizeArray( $newArray ); |
711 | 787 | |
712 | 788 | return ''; |
713 | 789 | } |
— | — | @@ -719,32 +795,31 @@ |
720 | 796 | * set operation, {white} = {red, white} - {red} |
721 | 797 | * see: http://www.php.net/manual/en/function.array-diff.php |
722 | 798 | */ |
723 | | - function arraydiff( Parser &$parser, $arrayId_new, $arrayId1 = null , $arrayId2 = null ) { |
724 | | - if ( ! isset( $arrayId_new ) || ! isset( $arrayId1 ) || ! isset( $arrayId2 ) ) { |
| 799 | + static function pf_arraydiff( Parser &$parser, $arrayId_new, $arrayId1 = null , $arrayId2 = null ) { |
| 800 | + $store = self::get( $parser ); |
| 801 | + if( ! isset( $arrayId_new ) || ! isset( $arrayId1 ) || ! isset( $arrayId2 ) ) { |
725 | 802 | return ''; |
726 | 803 | } |
727 | | - if( ! isset( $arrayId1 ) || ! $this->arrayExists( $arrayId1 ) ) { |
| 804 | + if( ! isset( $arrayId1 ) || ! $store->arrayExists( $arrayId1 ) ) { |
728 | 805 | return ''; |
729 | 806 | } |
730 | | - if( ! isset( $arrayId2 ) || ! $this->arrayExists( $arrayId2 ) ) { |
| 807 | + if( ! isset( $arrayId2 ) || ! $store->arrayExists( $arrayId2 ) ) { |
731 | 808 | return ''; |
732 | | - } |
733 | | - |
| 809 | + } |
734 | 810 | // keys will be preserved... |
735 | | - $newArray = array_diff( array_unique( $this->mArrayExtension[$arrayId1] ), array_unique( $this->mArrayExtension[$arrayId2] ) ); |
| 811 | + $newArray = array_diff( array_unique( $store->mArrays[$arrayId1] ), array_unique( $store->mArrays[$arrayId2] ) ); |
736 | 812 | |
737 | 813 | // ...so we have to reorganize the key order |
738 | | - $this->mArrayExtension[$arrayId_new] = $this->sanitizeArray( $newArray ); |
| 814 | + $store->mArrays[$arrayId_new] = self::sanitizeArray( $newArray ); |
739 | 815 | |
740 | 816 | return ''; |
741 | 817 | } |
| 818 | + |
| 819 | + |
| 820 | + ################## |
| 821 | + # Private helper # |
| 822 | + ################## |
742 | 823 | |
743 | | - |
744 | | - |
745 | | - ///////////////////////////////////////////////// / |
746 | | - // private functions |
747 | | - ///////////////////////////////////////////////// / |
748 | | - |
749 | 824 | /** |
750 | 825 | * Validates an index for an array and returns true in case the index is a valid index within |
751 | 826 | * the array. This also changes the index value, which is given by reference, in case it is |
— | — | @@ -758,9 +833,8 @@ |
759 | 834 | * |
760 | 835 | * @return boolean |
761 | 836 | */ |
762 | | - private function validate_array_index( $arrayId, &$index, $strictIndex = false ) { |
763 | | - |
764 | | - if ( ! is_numeric( $index ) ) { |
| 837 | + protected function validate_array_index( $arrayId, &$index, $strictIndex = false ) { |
| 838 | + if( ! is_numeric( $index ) ) { |
765 | 839 | if( $strictIndex ) { |
766 | 840 | return false; |
767 | 841 | } else { |
— | — | @@ -769,36 +843,41 @@ |
770 | 844 | } |
771 | 845 | $index = (int)$index; |
772 | 846 | |
773 | | - if( ! array_key_exists( $arrayId, $this->mArrayExtension ) ) |
| 847 | + if( ! array_key_exists( $arrayId, $this->mArrays ) ) { |
774 | 848 | return false; |
| 849 | + } |
775 | 850 | |
776 | | - $array = $this->mArrayExtension[ $arrayId ]; |
| 851 | + $array = $this->mArrays[ $arrayId ]; |
777 | 852 | |
778 | 853 | // calculate start index for negative start indexes: |
779 | | - if ( $index < 0 ) { |
| 854 | + if( $index < 0 ) { |
780 | 855 | $index = count( $array ) + $index; |
781 | 856 | if ( $index < 0 && !$strictIndex ) { |
782 | 857 | $index = 0; |
783 | 858 | } |
784 | 859 | } |
785 | 860 | |
786 | | - if ( ! isset( $array ) ) { |
| 861 | + if( ! isset( $array ) ) { |
787 | 862 | return false; |
788 | 863 | } |
789 | | - if ( ! array_key_exists( $index, $array ) ) { |
| 864 | + if( ! array_key_exists( $index, $array ) ) { |
790 | 865 | return false; |
791 | 866 | } |
792 | 867 | return true; |
793 | 868 | } |
794 | | - |
795 | | - // private function for validating array by name |
796 | | - private function validate_array_by_arrayId( $arrayId ) { |
797 | | - if( ! isset( $arrayId ) ) |
798 | | - return ''; |
799 | | - |
800 | | - if( ! isset( $this->mArrayExtension ) |
801 | | - || ! array_key_exists( $arrayId, $this->mArrayExtension ) |
802 | | - || ! is_array( $this->mArrayExtension[ $arrayId ] ) |
| 869 | + |
| 870 | + /** |
| 871 | + * private function for validating array by name |
| 872 | + * @ToDo: get rid of this! |
| 873 | + * @deprecated |
| 874 | + */ |
| 875 | + protected function validate_array_by_arrayId( $arrayId ) { |
| 876 | + if( ! isset( $arrayId ) ) { |
| 877 | + return ''; |
| 878 | + } |
| 879 | + if( ! isset( $this->mArrays ) |
| 880 | + || ! array_key_exists( $arrayId, $this->mArrays ) |
| 881 | + || ! is_array( $this->mArrays[ $arrayId ] ) |
803 | 882 | ) { |
804 | 883 | global $egArrayExtensionCompatbilityMode; |
805 | 884 | if( $egArrayExtensionCompatbilityMode ) { |
— | — | @@ -808,49 +887,75 @@ |
809 | 888 | } |
810 | 889 | } |
811 | 890 | |
812 | | - return true; |
| 891 | + return true; |
813 | 892 | } |
814 | 893 | |
815 | 894 | /** |
816 | 895 | * Convenience function to get a value from an array. Returns '' in case the |
817 | 896 | * value doesn't exist or no array was given |
818 | 897 | */ |
819 | | - private function array_value( $array, $field ) { |
| 898 | + protected static function array_value( $array, $field ) { |
820 | 899 | if ( is_array( $array ) && array_key_exists( $field, $array ) ) { |
821 | 900 | return $array[ $field ]; |
822 | | - } else { |
823 | | - return ''; |
824 | 901 | } |
| 902 | + return ''; |
825 | 903 | } |
| 904 | + |
| 905 | + /** |
| 906 | + * Parses a string of options separated by ','. Options can be just certain key-words or |
| 907 | + * key-value pairs separated by '='. Options are case-insensitive and spacing between |
| 908 | + * separators will be ignored. |
| 909 | + */ |
| 910 | + protected static function parse_options( $options ) { |
| 911 | + if( ! isset( $options ) ) { |
| 912 | + return array(); |
| 913 | + } |
826 | 914 | |
827 | | - private function parse_options( $options ) { |
828 | | - if ( isset( $options ) ) { |
829 | | - // now parse the options, and do posterior process on the created array |
830 | | - $ary_option = preg_split ( '/\s*[,]\s*/', strtolower( $options ) ); |
831 | | - } |
| 915 | + // now parse the options, and do posterior process on the created array |
| 916 | + $options = preg_split( '/\s*,\s*/', strtolower( $options ) ); |
832 | 917 | |
833 | | - $ret = array(); |
834 | | - if ( isset( $ary_option ) && is_array( $ary_option ) && sizeof( $ary_option ) > 0 ) { |
835 | | - foreach ( $ary_option as $option ) { |
836 | | - $ary_pair = explode( '=', $option, 2 ); |
837 | | - if ( sizeof( $ary_pair ) == 1 ) { |
838 | | - $ret[$ary_pair[0]] = true; |
839 | | - } else { |
840 | | - $ret[$ary_pair[0]] = $ary_pair[1]; |
841 | | - } |
842 | | - } |
843 | | - } |
844 | | - return $ret; |
| 918 | + $ret = array(); |
| 919 | + foreach( $options as $option ) { |
| 920 | + $optPair = preg_split( '/\s*\=\s*/', $option, 2 ); |
| 921 | + if( sizeof( $optPair ) == 1 ) { |
| 922 | + $ret[ $optPair[0] ] = true; |
| 923 | + } else { |
| 924 | + $ret[ $optPair[0] ] = $optPair[1]; |
| 925 | + } |
| 926 | + } |
| 927 | + return $ret; |
845 | 928 | } |
| 929 | + |
| 930 | + /** |
| 931 | + * same as self::arrayUnique() but without sanitazation, only for internal use. |
| 932 | + */ |
| 933 | + protected static function array_unique( array $array ) { |
| 934 | + // delete duplicate values |
| 935 | + $array = array_unique( $array ); |
| 936 | + |
| 937 | + $values = array(); |
| 938 | + foreach( $array as $key => $val ) { |
| 939 | + // don't put emty elements into the array |
| 940 | + if( $val !== '' ) { |
| 941 | + $values[] = $val; |
| 942 | + } |
| 943 | + } |
| 944 | + |
| 945 | + return $values; |
| 946 | + } |
846 | 947 | |
847 | | - /* ============================ */ |
848 | | - /* ============================ */ |
849 | | - /* === === */ |
850 | | - /* === HELPER FUNCTIONS === */ |
851 | | - /* === === */ |
852 | | - /* ============================ */ |
853 | | - /* ============================ */ |
854 | 948 | |
| 949 | + ############## |
| 950 | + # Used Hooks # |
| 951 | + ############## |
| 952 | + |
| 953 | + static function onParserClearState( Parser &$parser ) { |
| 954 | + // remove all arrays to avoid conflicts with job queue or Special:Import or SMW semantic updates |
| 955 | + $parser->mExtArrayExtension = new self(); |
| 956 | + return true; |
| 957 | + } |
| 958 | + |
| 959 | + |
855 | 960 | #################################### |
856 | 961 | # Public functions for interaction # |
857 | 962 | #################################### |
— | — | @@ -865,11 +970,11 @@ |
866 | 971 | * to a certain Parser object. Each parser has its own store which will be reset after |
867 | 972 | * a parsing process [Parser::parse()] has finished. |
868 | 973 | * |
869 | | - * @since 1.4 |
| 974 | + * @since 2.0 |
870 | 975 | * |
871 | 976 | * @param Parser &$parser |
872 | 977 | * |
873 | | - * @return ExtHashTables by reference so we still have the right object after 'ParserClearState' |
| 978 | + * @return ExtArrayExtension by reference so we still have the right object after 'ParserClearState' |
874 | 979 | */ |
875 | 980 | public static function &get( Parser &$parser ) { |
876 | 981 | return $parser->mExtArrayExtension; |
— | — | @@ -878,7 +983,7 @@ |
879 | 984 | /** |
880 | 985 | * Returns an array identified by $arrayId. If it doesn't exist, null will be returned. |
881 | 986 | * |
882 | | - * @since 1.4 |
| 987 | + * @since 2.0 |
883 | 988 | * |
884 | 989 | * @param string $arrayId |
885 | 990 | * |
— | — | @@ -887,7 +992,7 @@ |
888 | 993 | function getArray( $arrayId ) { |
889 | 994 | $arrayId = trim( $arrayId ); |
890 | 995 | if( $this->arrayExists( $arrayId ) ) { |
891 | | - return $this->mArrayExtension[ $arrayId ]; |
| 996 | + return $this->mArrays[ $arrayId ]; |
892 | 997 | } |
893 | 998 | return null; |
894 | 999 | } |
— | — | @@ -900,18 +1005,20 @@ |
901 | 1006 | * @param array $array |
902 | 1007 | */ |
903 | 1008 | public function createArray( $arrayId, $array = array() ) { |
904 | | - $array = $this->sanitizeArray( $array ); |
905 | | - $this->mArrayExtension[ trim( $arrayId ) ] = $array; |
| 1009 | + $array = self::sanitizeArray( $array ); |
| 1010 | + $this->mArrays[ trim( $arrayId ) ] = $array; |
906 | 1011 | } |
907 | 1012 | |
908 | 1013 | /** |
909 | | - * Same as the public createArray but without sanitizing the array automatically |
| 1014 | + * Same as the public function createArray() but without sanitizing the array automatically. |
| 1015 | + * This is save and faster for internal usage, just be sure your array doesn't have un-trimmed |
| 1016 | + * values or non-numeric or negative array keys and no gaps between keys. |
910 | 1017 | * |
911 | 1018 | * @param type $arrayId |
912 | 1019 | * @param type $array |
913 | 1020 | */ |
914 | 1021 | protected function setArray( $arrayId, $array = array() ) { |
915 | | - $this->mArrayExtension[ trim( $arrayId ) ] = $array; |
| 1022 | + $this->mArrays[ trim( $arrayId ) ] = $array; |
916 | 1023 | } |
917 | 1024 | |
918 | 1025 | /** |
— | — | @@ -922,27 +1029,29 @@ |
923 | 1030 | * @return boolean |
924 | 1031 | */ |
925 | 1032 | function arrayExists( $arrayId ) { |
926 | | - return array_key_exists( trim( $arrayId ), $this->mArrayExtension ); |
| 1033 | + return array_key_exists( trim( $arrayId ), $this->mArrays ); |
927 | 1034 | } |
928 | 1035 | |
929 | 1036 | /** |
930 | 1037 | * Returns a value within an array. If key or array do not exist, this will return null |
931 | | - * or another predefined default. |
| 1038 | + * or another predefined default. $index can also be a negative value, in this case the |
| 1039 | + * value that far from the end of the array will be returned. |
932 | 1040 | * |
933 | | - * @since 1.4 |
| 1041 | + * @since 2.0 |
934 | 1042 | * |
935 | 1043 | * @param string $arrayId |
936 | | - * @param string $key |
| 1044 | + * @param string $index |
937 | 1045 | * @param mixed $default value to return in case the value doesn't exist. null by default. |
938 | 1046 | * |
939 | | - * @return string |
| 1047 | + * @return string|null |
940 | 1048 | */ |
941 | | - function getArrayValue( $arrayId, $key, $default = null ) { |
942 | | - $arrayId = trim( $arrayId ); |
| 1049 | + function getArrayValue( $arrayId, $index, $default = null ) { |
| 1050 | + $arrayId = trim( $arrayId ); |
943 | 1051 | if( $this->arrayExists( $arrayId ) |
944 | | - && array_key_exists( $key, $this->mArrayExtension[ $arrayId ] ) |
| 1052 | + && $this->validate_array_index( $arrayId, $index, true ) |
| 1053 | + && array_key_exists( $index, $this->mArrays[ $arrayId ] ) |
945 | 1054 | ) { |
946 | | - return $this->mArrayExtension[ $arrayId ][ $key ]; |
| 1055 | + return $this->mArrays[ $arrayId ][ $index ]; |
947 | 1056 | } |
948 | 1057 | else { |
949 | 1058 | return $default; |
— | — | @@ -953,6 +1062,8 @@ |
954 | 1063 | /** |
955 | 1064 | * Removes an existing array. If array didn't exist this will return false, otherwise true. |
956 | 1065 | * |
| 1066 | + * @since 2.0 |
| 1067 | + * |
957 | 1068 | * @param string $arrayId |
958 | 1069 | * |
959 | 1070 | * @return boolean whether the array existed and has been removed |
— | — | @@ -960,7 +1071,7 @@ |
961 | 1072 | public function unsetArray( $arrayId ) { |
962 | 1073 | $arrayId = trim( $arrayId ); |
963 | 1074 | if( $this->arrayExists( $arrayId ) ) { |
964 | | - unset( $this->mArrayExtension[ $arrayId ] ); |
| 1075 | + unset( $this->mArrays[ $arrayId ] ); |
965 | 1076 | return true; |
966 | 1077 | } |
967 | 1078 | return false; |
— | — | @@ -970,10 +1081,12 @@ |
971 | 1082 | * Rebuild the array and reorganize all keys, trim all values. |
972 | 1083 | * All gaps between array items will be closed. |
973 | 1084 | * |
| 1085 | + * @since 2.0 |
| 1086 | + * |
974 | 1087 | * @param array $arr array to be reorganized |
975 | 1088 | * @return array |
976 | 1089 | */ |
977 | | - public function sanitizeArray( $array ) { |
| 1090 | + public static function sanitizeArray( $array ) { |
978 | 1091 | $newArray = array(); |
979 | 1092 | foreach( $array as $val ) { |
980 | 1093 | $newArray[] = trim( $val ); |
— | — | @@ -985,34 +1098,16 @@ |
986 | 1099 | * Removes duplicate values and all empty elements from an array just like the |
987 | 1100 | * arrayunique parser function would do it. The array will be sanitized internally. |
988 | 1101 | * |
989 | | - * @since 1.4 |
| 1102 | + * @since 2.0 |
990 | 1103 | * |
991 | 1104 | * @param array $array |
992 | 1105 | * |
993 | 1106 | * @return array |
994 | 1107 | */ |
995 | | - public function arrayUnique( array $array ) { |
| 1108 | + public static function arrayUnique( array $array ) { |
996 | 1109 | $arr = $this->sanitizeArray( $arr ); |
997 | | - $array = $this->array_unique( $array ); |
| 1110 | + $array = self::array_unique( $array ); |
998 | 1111 | } |
999 | | - |
1000 | | - /** |
1001 | | - * same as self::arrayUnique() but without sanitazation, only for internal use. |
1002 | | - */ |
1003 | | - private function array_unique( array $array ) { |
1004 | | - // delete duplicate values |
1005 | | - $array = array_unique( $array ); |
1006 | | - |
1007 | | - $values = array(); |
1008 | | - foreach( $array as $key => $val ) { |
1009 | | - // don't put emty elements into the array |
1010 | | - if( $val !== '' ) { |
1011 | | - $values[] = $val; |
1012 | | - } |
1013 | | - } |
1014 | | - |
1015 | | - return $values; |
1016 | | - } |
1017 | 1112 | |
1018 | 1113 | /** |
1019 | 1114 | * Decides for the given $pattern whether its a valid regular expression acceptable for |
— | — | @@ -1022,7 +1117,7 @@ |
1023 | 1118 | * |
1024 | 1119 | * @return boolean |
1025 | 1120 | */ |
1026 | | - function isValidRegEx( $pattern ) { |
| 1121 | + static function isValidRegEx( $pattern ) { |
1027 | 1122 | if( ! preg_match( '/^([\\/\\|%]).*\\1[imsSuUx]*$/', $pattern ) ) { |
1028 | 1123 | return false; |
1029 | 1124 | } |
— | — | @@ -1032,34 +1127,3 @@ |
1033 | 1128 | return $isValid; |
1034 | 1129 | } |
1035 | 1130 | } |
1036 | | - |
1037 | | -function efArrayExtensionParserFirstCallInit( Parser &$parser ) { |
1038 | | - global $wgArrayExtension; |
1039 | | - |
1040 | | - $wgArrayExtension = new ArrayExtension(); |
1041 | | - $parser->setFunctionHook( 'arraydefine', array( &$wgArrayExtension, 'arraydefine' ) ); |
1042 | | - |
1043 | | - if ( defined( get_class( $parser ) . '::SFH_OBJECT_ARGS' ) ) { |
1044 | | - $parser->setFunctionHook( 'arrayprint', array( &$wgArrayExtension, 'arrayprintObj' ), SFH_OBJECT_ARGS ); |
1045 | | - } else { |
1046 | | - $parser->setFunctionHook( 'arrayprint', array( &$wgArrayExtension, 'arrayprint' ) ); |
1047 | | - } |
1048 | | - |
1049 | | - $parser->setFunctionHook( 'arraysize', array( &$wgArrayExtension, 'arraysize' ) ); |
1050 | | - $parser->setFunctionHook( 'arrayindex', array( &$wgArrayExtension, 'arrayindex' ) ); |
1051 | | - $parser->setFunctionHook( 'arraysearch', array( &$wgArrayExtension, 'arraysearch' ), SFH_OBJECT_ARGS ); |
1052 | | - |
1053 | | - $parser->setFunctionHook( 'arraysort', array( &$wgArrayExtension, 'arraysort' ) ); |
1054 | | - $parser->setFunctionHook( 'arrayunique', array( &$wgArrayExtension, 'pf_arrayunique' ) ); |
1055 | | - $parser->setFunctionHook( 'arrayreset', array( &$wgArrayExtension, 'arrayreset' ), SFH_OBJECT_ARGS ); |
1056 | | - |
1057 | | - $parser->setFunctionHook( 'arraymerge', array( &$wgArrayExtension, 'arraymerge' ) ); |
1058 | | - $parser->setFunctionHook( 'arrayslice', array( &$wgArrayExtension, 'arrayslice' ) ); |
1059 | | - |
1060 | | - $parser->setFunctionHook( 'arrayunion', array( &$wgArrayExtension, 'arrayunion' ) ); |
1061 | | - $parser->setFunctionHook( 'arrayintersect', array( &$wgArrayExtension, 'arrayintersect' ) ); |
1062 | | - $parser->setFunctionHook( 'arraydiff', array( &$wgArrayExtension, 'arraydiff' ) ); |
1063 | | - $parser->setFunctionHook( 'arraysearcharray', array( &$wgArrayExtension, 'arraysearcharray' ) ); |
1064 | | - |
1065 | | - return true; |
1066 | | -} |
Index: trunk/extensions/ArrayExtension/RELEASE-NOTES |
— | — | @@ -1,7 +1,23 @@ |
2 | 2 | Changelog: |
3 | 3 | ========== |
4 | 4 | |
5 | | - * (trunk) -- Version 1.4 |
| 5 | + * (trunk) -- Version 2.0 |
| 6 | + This release is built upon 1.4 alpha. See changes of 1.4 alpha as well. |
| 7 | + - class 'ArrayExtension' renamed to 'ExtArrayExtension' |
| 8 | + - '#arrayindex' will only expand options/default when required. |
| 9 | + - Compatbility mode variable '$egArrayExtensionCompatbilityMode' is set to false by default. See |
| 10 | + Version 1.4 alpha for further information. Further changes to the compatbility mode behavior |
| 11 | + in version 2.0: |
| 12 | + + '#arrayindex' will return its default also in case of existing index but empty value. This |
| 13 | + makes the function consistent with Variables '#var' and hash tables '#hashvalue'. |
| 14 | + + See 1.4 alpha for previous changes |
| 15 | + |
| 16 | + |
| 17 | + * November 20, 2001 -- Version 1.4 alpha (r103716) |
| 18 | + This release introduces some useful bugfixes and optional new behavior for various functionality. |
| 19 | + This version never made it into a final stage because version 2.0 will introduce some rather |
| 20 | + radical changes, so this alpha release allows to profit from bugfixes that might be quite useful |
| 21 | + if you don't want to use Version 2.0 for some reason. |
6 | 22 | - Configuration variable '$egArrayExtensionCompatbilityMode' for deactivating the following newly |
7 | 23 | introduced breaking changes: |
8 | 24 | + '#arrayprint' no longer returns an error text in case the array doesn't exist. |
— | — | @@ -11,7 +27,7 @@ |
12 | 28 | + '#arraysearch' returns an empty string '' instead of '-1' in case nothing was found. |
13 | 29 | + '#arraysearcharray' and '#arrayslice' without all necessary parameters set will always create |
14 | 30 | a new empty array. |
15 | | - Compatbility mode is active by default, it will be disabled in version 2.0 |
| 31 | + Compatbility mode is active by default. In Version 2.0 it will be set to inactive by default. |
16 | 32 | - '#arraysearch' will only expand 'yes' or 'no' if given, but never both. |
17 | 33 | - negative indexes for '#arrayindex', '#arraysearch' and '#arraysearcharray' are possible now. |
18 | 34 | - bugfix in '#arraysearcharray', index and limit working fine now. |