Index: trunk/extensions/ArrayExtension/ArrayExtension.php |
— | — | @@ -15,6 +15,12 @@ |
16 | 16 | * @author Li Ding (lidingpku@gmail.com) |
17 | 17 | * @author Jie Bao |
18 | 18 | * @author Daniel Werner (since version 1.3) |
| 19 | + * |
| 20 | + * @ToDo: |
| 21 | + * use $egArrayExtensionCompatbilityMode to finally get rid of unlogic behavior of certain functions |
| 22 | + * who create a new array from the data of one or more old arrays. In case only the new array name is |
| 23 | + * given, sometimes the new array will be created, sometimes not. It should always be created to make |
| 24 | + * things more consistent and clear. |
19 | 25 | */ |
20 | 26 | |
21 | 27 | /** |
— | — | @@ -35,7 +41,7 @@ |
36 | 42 | * get_table_col (col) to an array |
37 | 43 | * get_table_header () to an array |
38 | 44 | * get_total_row |
39 | | - * get_total_col |
| 45 | + * get_total_col |
40 | 46 | */ |
41 | 47 | |
42 | 48 | if ( ! defined( 'MEDIAWIKI' ) ) { |
— | — | @@ -65,7 +71,7 @@ |
66 | 72 | * |
67 | 73 | * @var boolean |
68 | 74 | */ |
69 | | -$wgArrayExtensionCompatbilityMode = true; |
| 75 | +$egArrayExtensionCompatbilityMode = true; |
70 | 76 | |
71 | 77 | |
72 | 78 | /** |
— | — | @@ -93,7 +99,7 @@ |
94 | 100 | $wgHooks['ParserClearState'][] = &$this; |
95 | 101 | } |
96 | 102 | |
97 | | - function onParserClearState( &$parser ) { |
| 103 | + function onParserClearState( Parser &$parser ) { |
98 | 104 | // remove all arrays to avoid conflicts with job queue or Special:Import or SMW semantic updates |
99 | 105 | $this->mArrayExtension = array(); |
100 | 106 | return true; |
— | — | @@ -113,9 +119,9 @@ |
114 | 120 | * see also: http://us2.php.net/manual/en/function.preg-split.php |
115 | 121 | */ |
116 | 122 | function arraydefine( |
117 | | - &$parser, |
118 | | - $arrayid, |
119 | | - $value = '', |
| 123 | + Parser &$parser, |
| 124 | + $arrayId, |
| 125 | + $value = null, |
120 | 126 | $delimiter = '/\s*,\s*/', |
121 | 127 | $options = '', |
122 | 128 | $delimiter2 = ', ', |
— | — | @@ -123,60 +129,93 @@ |
124 | 130 | $subject = '@@@@', |
125 | 131 | $frame = null |
126 | 132 | ) { |
127 | | - if ( !isset( $arrayid ) ) { |
| 133 | + if ( !isset( $arrayId ) ) { |
128 | 134 | return ''; |
129 | 135 | } |
130 | | - |
131 | | - // normalize |
132 | | - $value = trim( $value ); |
| 136 | + |
| 137 | + $out = ''; |
| 138 | + $array = array(); |
| 139 | + $trimDone = false; // whether or not we can be sure that all array elements are trimmed |
| 140 | + |
| 141 | + // normalize |
133 | 142 | $delimiter = trim( $delimiter ); |
134 | 143 | |
135 | | - if ( !$this->is_non_empty( $value ) ) { |
136 | | - $this->mArrayExtension[$arrayid] = array(); |
137 | | - } elseif ( !$this->is_non_empty( $delimiter ) ) { |
138 | | - $this->mArrayExtension[$arrayid] = array( $value ); |
139 | | - } else { |
140 | | - if ( !$this->isValidRegEx( $delimiter ) ) { |
141 | | - $delimiter = '/\s*' . preg_quote( $delimiter, '/' ) . '\s*/'; // Anpassung von Daniel Werner (preg_quote) |
142 | | - } |
| 144 | + if( $value === null ) { |
| 145 | + // no element set, not even an empty one |
| 146 | + $array = array(); |
| 147 | + } |
| 148 | + else { |
| 149 | + $value = trim( $value ); // just in case... |
| 150 | + |
| 151 | + // fill array with user input: |
| 152 | + if( $delimiter === '' ) { |
| 153 | + // whole input one element, also takes care of special case empty '' value and 'unique' option set |
| 154 | + $array = array( $value ); |
| 155 | + $trimDone = true; |
| 156 | + } |
| 157 | + else { |
| 158 | + // if no regex delimiter given, build one: |
| 159 | + if( ! $this->isValidRegEx( $delimiter ) ) { |
| 160 | + $delimiter = '/\s*' . preg_quote( $delimiter, '/' ) . '\s*/'; |
| 161 | + $trimDone = true; // spaces are part of the delimiter now |
| 162 | + } |
| 163 | + $array = preg_split( $delimiter, $value ); |
| 164 | + } |
| 165 | + |
| 166 | + // trim all values before unique if still necessary, otherwise unique might not work correctly |
| 167 | + if( ! $trimDone ) { |
| 168 | + $array = $this->sanitizeArray( $array ); |
| 169 | + } |
143 | 170 | |
144 | | - $this->mArrayExtension[$arrayid] = preg_split( $delimiter, $value ); |
145 | | - |
146 | | - // validate if the array has been successfully created |
147 | | - $ret = $this->validate_array_by_arrayid( $arrayid ); |
148 | | - if ( $ret !== true ) { |
149 | | - return ''; |
| 171 | + // now parse the options, and do posterior process on the created array |
| 172 | + $arrayOptions = $this->parse_options( $options ); |
| 173 | + |
| 174 | + // make it unique if option is set |
| 175 | + if( array_key_exists( 'unique', $arrayOptions ) ) { |
| 176 | + // unique like the parser function would do it |
| 177 | + $array = $this->array_unique( $array ); |
150 | 178 | } |
151 | | - |
152 | | - // now parse the options, and do posterior process on the created array |
153 | | - $ary_option = $this->parse_options( $options ); |
154 | | - |
155 | | - if ( !array_key_exists( 'empty', $ary_option ) ) { |
156 | | - foreach ( $this->mArrayExtension[$arrayid] as $key => $value ) { |
157 | | - if ( trim( $value ) == '' ) { |
158 | | - unset( $this->mArrayExtension[$arrayid][$key] ); |
| 179 | + |
| 180 | + /** |
| 181 | + * @ToDo: |
| 182 | + * The 'empty' option was introduced in r81676 but actually breaks old functionality since it will remove |
| 183 | + * all empty elements by default. |
| 184 | + * 'unique' already allows to remove all empty elements but it will also remove al duplicates, there should |
| 185 | + * be a more intelligent alternative to 'unique' which allows both, to preserve or remove empty elements |
| 186 | + * independent from removing duplicate values. |
| 187 | + */ |
| 188 | + /* |
| 189 | + // remove all empty '' elements if option is NOT set |
| 190 | + if( ! array_key_exists( 'empty', $arrayOptions ) ) { |
| 191 | + $values = array(); // temp array so we won't have gaps (don't use unset!) |
| 192 | + foreach ( $array as $key => $value ) { |
| 193 | + if( $value !== '' ) { |
| 194 | + $values[] = $elem; |
159 | 195 | } |
160 | 196 | } |
| 197 | + $array = $values; |
| 198 | + unset( $values ); |
161 | 199 | } |
| 200 | + */ |
162 | 201 | |
163 | | - // make it unique if option is set |
164 | | - if ( array_key_exists( 'unique', $ary_option ) ) { |
165 | | - $this->arrayunique( $parser, $arrayid ); |
166 | | - } |
167 | | - |
168 | 202 | // sort array if the option is set |
169 | | - $this->arraysort( $parser, $arrayid, $this->get_array_value( $ary_option, 'sort' ) ); |
| 203 | + $this->arraysort( $parser, $arrayId, $this->array_value( $arrayOptions, 'sort' ) ); |
170 | 204 | |
171 | 205 | // print the array upon request |
172 | | - if ( strcmp( 'list', $this->get_array_value( $ary_option, 'print' ) ) === 0 ) { |
173 | | - return $this->arrayprint( $parser, $arrayid ); |
| 206 | + switch( $this->array_value( $arrayOptions, 'print' ) ) { |
| 207 | + case 'list': |
| 208 | + $out = $this->arrayprint( $parser, $arrayId ); |
| 209 | + break; |
| 210 | + |
| 211 | + case 'print': |
| 212 | + $out = $this->arrayprint( $parser, $arrayId, $delimiter2, $search, $subject, $frame ); |
| 213 | + break; |
174 | 214 | } |
175 | | - elseif ( strcmp( 'full', $this->get_array_value( $ary_option, 'print' ) ) === 0 ) { |
176 | | - return $this->arrayprint( $parser, $arrayid, $delimiter2, $search, $subject, $frame ); |
177 | | - } |
178 | 215 | } |
| 216 | + |
| 217 | + $this->mArrayExtension[ $arrayId ] = $array; |
179 | 218 | |
180 | | - return ''; |
| 219 | + return $out; |
181 | 220 | } |
182 | 221 | |
183 | 222 | |
— | — | @@ -200,13 +239,13 @@ |
201 | 240 | * {{#arrayprint:b|<br/>|@@@|{{f.tag{{f.print.vbar}}prop{{f.print.vbar}}@@@}} }} -- embed template function |
202 | 241 | * {{#arrayprint:b|<br/>|@@@|[[name::@@@]]}} -- make SMW links |
203 | 242 | */ |
204 | | - function arrayprint( &$parser, $arrayid , $delimiter = ', ', $search = '@@@@', $subject = '@@@@', $frame = null ) { |
205 | | - $ret = $this->validate_array_by_arrayid( $arrayid ); |
| 243 | + function arrayprint( Parser &$parser, $arrayId , $delimiter = ', ', $search = '@@@@', $subject = '@@@@', $frame = null ) { |
| 244 | + $ret = $this->validate_array_by_arrayId( $arrayId ); |
206 | 245 | if ( $ret !== true ) { |
207 | 246 | return $ret; |
208 | 247 | } |
209 | 248 | |
210 | | - $values = $this->mArrayExtension[$arrayid]; |
| 249 | + $values = $this->mArrayExtension[$arrayId]; |
211 | 250 | $rendered_values = array(); |
212 | 251 | foreach ( $values as $v ) { |
213 | 252 | $temp_result_value = str_replace( $search, $v, $subject ); |
— | — | @@ -244,9 +283,9 @@ |
245 | 284 | ); |
246 | 285 | } |
247 | 286 | |
248 | | - function arrayprintObj( &$parser, $frame, $args ) { |
| 287 | + function arrayprintObj( Parser &$parser, $frame, $args ) { |
249 | 288 | // Set variables |
250 | | - $arrayid = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : ''; |
| 289 | + $arrayId = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : ''; |
251 | 290 | $delimiter = isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) : ', '; |
252 | 291 | /* |
253 | 292 | * PPFrame::NO_ARGS and PPFrame::NO_TEMPLATES for expansion make a lot of sense here since the patterns getting replaced |
— | — | @@ -256,7 +295,7 @@ |
257 | 296 | $search = isset( $args[2] ) ? trim( $frame->expand( $args[2], PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES ) ) : '@@@@'; |
258 | 297 | $subject = isset( $args[3] ) ? trim( $frame->expand( $args[3], PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES ) ) : '@@@@'; |
259 | 298 | |
260 | | - return $this->arrayprint( $parser, $arrayid, $delimiter, $search, $subject, $frame ); |
| 299 | + return $this->arrayprint( $parser, $arrayId, $delimiter, $search, $subject, $frame ); |
261 | 300 | } |
262 | 301 | |
263 | 302 | |
— | — | @@ -265,37 +304,34 @@ |
266 | 305 | * usage: |
267 | 306 | * {{#arrayindex:arrayid|index}} |
268 | 307 | */ |
269 | | - function arrayindex( &$parser, $arrayid , $index , $options = '' ) { |
| 308 | + function arrayindex( Parser &$parser, $arrayId , $index , $options = '' ) { |
270 | 309 | // now parse the options, and do posterior process on the created array |
271 | 310 | $ary_option = $this->parse_options( $options ); |
272 | | - |
273 | | - $ret = $this->validate_array_by_arrayid( $arrayid ); |
274 | | - if ( $ret !== true ) { |
275 | | - return $this->get_array_value( $ary_option, "default" ); |
276 | | - } |
277 | 311 | |
278 | | - if ( ! $this->validate_array_index( $arrayid, $index, false ) ) { |
279 | | - return $this->get_array_value( $ary_option, "default" ); |
| 312 | + // index must exist, strict check, non-numeric will fail: |
| 313 | + if( true !== $this->validate_array_by_arrayId( $arrayId ) |
| 314 | + || ! $this->validate_array_index( $arrayId, $index, true ) |
| 315 | + ) { |
| 316 | + return $this->array_value( $ary_option, 'default' ); |
280 | 317 | } |
281 | 318 | |
282 | | - return $this->mArrayExtension[ $arrayid ][ $index ]; |
| 319 | + return $this->mArrayExtension[ $arrayId ][ $index ]; |
283 | 320 | } |
284 | 321 | |
285 | 322 | /** |
286 | | - * return size of array. |
287 | | - * Print the size (number of elements) in the specified array |
| 323 | + * returns the size of an array. |
| 324 | + * Print the size (number of elements) in the specified array and '' if array doesn't exist |
288 | 325 | * usage: |
289 | 326 | * {{#arraysize:arrayid}} |
290 | 327 | * |
291 | 328 | * See: http://www.php.net/manual/en/function.count.php |
292 | 329 | */ |
293 | | - function arraysize( &$parser, $arrayid ) { |
294 | | - $ret = $this->validate_array_by_arrayid( $arrayid ); |
295 | | - if ( $ret !== true ) { |
| 330 | + function arraysize( Parser &$parser, $arrayId ) { |
| 331 | + if( ! $this->arrayExists( $arrayId ) ) { |
296 | 332 | return ''; |
297 | 333 | } |
298 | | - |
299 | | - return count ( $this->mArrayExtension[$arrayid] ); |
| 334 | + |
| 335 | + return count( $this->mArrayExtension[ $arrayId ] ); |
300 | 336 | } |
301 | 337 | |
302 | 338 | |
— | — | @@ -313,14 +349,13 @@ |
314 | 350 | * See: http://www.php.net/manual/en/function.array-search.php |
315 | 351 | * note it is extended to support regular expression match and index |
316 | 352 | */ |
317 | | - //function arraysearch( &$parser, $arrayid, $needle = '/^\s*$/', $index = 0, $yes = null, $no = '-1' ) { |
318 | 353 | function arraysearch( Parser &$parser, PPFrame $frame, $args ) { |
319 | 354 | |
320 | 355 | $arrayId = trim( $frame->expand( $args[0] ) ); |
321 | 356 | $index = isset( $args[2] ) ? trim( $frame->expand( $args[2] ) ) : 0; |
322 | 357 | |
323 | | - if( $this->validate_array_by_arrayid( $arrayId ) |
324 | | - && $this->validate_array_index( $arrayId, $index, true ) |
| 358 | + if( $this->arrayExists( $arrayId ) |
| 359 | + && $this->validate_array_index( $arrayId, $index, false ) |
325 | 360 | ) { |
326 | 361 | $array = $this->mArrayExtension[ $arrayId ]; |
327 | 362 | |
— | — | @@ -356,12 +391,12 @@ |
357 | 392 | } |
358 | 393 | } |
359 | 394 | |
360 | | - global $wgArrayExtensionCompatbilityMode; |
| 395 | + global $egArrayExtensionCompatbilityMode; |
361 | 396 | |
362 | 397 | // no match! (Expand only when needed!) |
363 | 398 | $no = isset( $args[4] ) |
364 | 399 | ? trim( $frame->expand( $args[4] ) ) |
365 | | - : $wgArrayExtensionCompatbilityMode ? '-1' : ''; // COMPATBILITY-MODE |
| 400 | + : $egArrayExtensionCompatbilityMode ? '-1' : ''; // COMPATBILITY-MODE |
366 | 401 | return $no; |
367 | 402 | } |
368 | 403 | |
— | — | @@ -370,53 +405,67 @@ |
371 | 406 | * usage: |
372 | 407 | * {{#arraysearcharray:arrayid_new|arrayid|needle|index|limit|transform}} |
373 | 408 | * |
374 | | - * "needle" can be a regular expression or a string search value. If "needle" is a regular expression, "transform" kan contain |
| 409 | + * "needle" can be a regular expression or a string search value. If "needle" is a regular expression, "transform" can contain |
375 | 410 | * "$n" where "n" stands for a number to access a variable from the regex result. |
376 | 411 | */ |
377 | | - function arraysearcharray( &$parser, $arrayid_new, $arrayid, $needle = '/^(\s*)$/', $index = 0, $limit = -1, $transform = '' ) { |
378 | | - $ret = $this->validate_array_by_arrayid( $arrayid ); |
379 | | - if ( !$ret ) |
| 412 | + function arraysearcharray( |
| 413 | + Parser &$parser, |
| 414 | + $arrayId_new, |
| 415 | + $arrayId = null, |
| 416 | + $needle = '/^(\s*)$/', |
| 417 | + $index = 0, |
| 418 | + $limit = -1, |
| 419 | + $transform = '' |
| 420 | + ) { |
| 421 | + if( $arrayId === null ) { |
| 422 | + $this->setArray( $arrayId_new ); |
380 | 423 | return ''; |
381 | | - |
382 | | - if ( !isset( $arrayid_new ) ) |
| 424 | + } |
| 425 | + // also takes care of negative index by calculating start index: |
| 426 | + $validIndex = $this->validate_array_index( $arrayId, $index, false ); |
| 427 | + |
| 428 | + // make sure at least empty array exists but don't overwrite data |
| 429 | + // we still need in case new array ID same as target array ID |
| 430 | + $array = $this->getArray( $arrayId ); |
| 431 | + $this->setArray( $arrayId_new ); |
| 432 | + |
| 433 | + if( $array === null || !$validIndex ) { |
383 | 434 | return ''; |
384 | | - |
385 | | - if ( !is_numeric( $index ) ) |
386 | | - $index = 0; |
387 | | - |
388 | | - if ( !is_numeric( $limit ) ) |
389 | | - $limit = -1; |
390 | | - |
391 | | - // calculate start index for negative start indexes: |
392 | | - if ( $index < 0 ) { |
393 | | - $index = count( $this->mArrayExtension[$arrayid] ) + $index; |
394 | | - if ( $index < 0 ) $index = 0; |
395 | 435 | } |
396 | | - |
397 | | - $newArr = array(); |
398 | | - $newArrSize = 0; |
399 | | - |
400 | | - if ( !$this->isValidRegEx( $needle ) ) |
| 436 | + |
| 437 | + // non-numeric limit will be set to 0 |
| 438 | + $limit = (int)$limit; |
| 439 | + if( $limit === 0 ) { |
| 440 | + return ''; |
| 441 | + } |
| 442 | + |
| 443 | + $newArr = array(); |
| 444 | + |
| 445 | + if( !$this->isValidRegEx( $needle ) ) { |
401 | 446 | $needle = '/^\s*(' . preg_quote( $needle, '/' ) . ')\s*$/'; |
| 447 | + } |
402 | 448 | |
403 | 449 | // search the array for all matches and put them in the new array |
404 | | - for ( $i = $index; $i < count( $this->mArrayExtension[$arrayid] ); $i++ ) |
405 | | - { |
406 | | - $value = $this->mArrayExtension[$arrayid][$i]; |
| 450 | + $total = count( $array ); |
| 451 | + for( $i = $index; $i < $total; $i++ ) { |
| 452 | + |
| 453 | + $value = $array[ $i ]; |
407 | 454 | |
408 | | - if ( preg_match( $needle, $value ) ) { |
409 | | - if ( $transform != '' ) { |
| 455 | + if( preg_match( $needle, $value ) ) { |
| 456 | + if( $transform !== '' ) { |
410 | 457 | $value = preg_replace( $needle, $transform, $value ); |
411 | 458 | } |
412 | | - $newArr[] = $value; |
413 | | - $newArrSize++; |
414 | | - // stop if limit is reached |
415 | | - if ( $newArrSize == $limit ) |
| 459 | + $newArr[] = trim( $value ); |
| 460 | + |
| 461 | + // stop if limit is reached, limit -1 means no limit |
| 462 | + if( --$limit === 0 ) { |
416 | 463 | break; |
| 464 | + } |
417 | 465 | } |
418 | 466 | } |
419 | | - |
420 | | - $this->mArrayExtension[$arrayid_new] = $newArr; |
| 467 | + |
| 468 | + // set new array: |
| 469 | + $this->setArray( $arrayId_new, $newArr ); |
421 | 470 | return ''; |
422 | 471 | } |
423 | 472 | |
— | — | @@ -432,10 +481,10 @@ |
433 | 482 | * {{#arrayreset:}} |
434 | 483 | * {{#arrayreset:arrayid1,arrayid2,...arrayidn}} |
435 | 484 | */ |
436 | | - function arrayreset( &$parser, PPFrame $frame, $args) { |
437 | | - global $wgArrayExtensionCompatbilityMode; |
| 485 | + function arrayreset( Parser &$parser, PPFrame $frame, $args) { |
| 486 | + global $egArrayExtensionCompatbilityMode; |
438 | 487 | |
439 | | - if( $wgArrayExtensionCompatbilityMode && count( $args ) == 1 ) { |
| 488 | + if( $egArrayExtensionCompatbilityMode && count( $args ) == 1 ) { |
440 | 489 | /* |
441 | 490 | * COMPATBILITY-MODE: before arrays were separated by ';' which is an bad idea since |
442 | 491 | * the ',' is an allowed character in array names! |
— | — | @@ -459,65 +508,62 @@ |
460 | 509 | |
461 | 510 | |
462 | 511 | /** |
463 | | - * convert an array to set |
464 | | - * convert the array identified by arrayid into a set (all elements are unique) |
465 | | - * usage: |
466 | | - * {{#arrayunique:arrayid}} |
467 | | - * |
468 | | - * see: http://www.php.net/manual/en/function.array-unique.php |
469 | | - */ |
470 | | - function arrayunique( &$parser, $arrayid ) { |
471 | | - $ret = $this->validate_array_by_arrayid( $arrayid ); |
472 | | - if ( $ret !== true ) { |
473 | | - return ''; |
| 512 | + * convert an array to a set |
| 513 | + * convert the array identified by arrayid into a set (all elements are unique) |
| 514 | + * also removes empty '' elements from the array |
| 515 | + * usage: |
| 516 | + * {{#arrayunique:arrayid}} |
| 517 | + * |
| 518 | + * see: http://www.php.net/manual/en/function.array-unique.php |
| 519 | + */ |
| 520 | + function pf_arrayunique( Parser &$parser, $arrayId ) { |
| 521 | + if( $this->arrayExists( $arrayId ) ) { |
| 522 | + $this->mArrayExtension[ $arrayId ] = $this->array_unique( $this->mArrayExtension[ $arrayId ] ); |
474 | 523 | } |
475 | | - |
476 | | - $this->mArrayExtension[$arrayid] = array_unique ( $this->mArrayExtension[$arrayid] ); |
477 | | - $values = array(); |
478 | | - foreach ( $this->mArrayExtension[$arrayid] as $v ) { |
479 | | - // if (!isset($v)) |
480 | | - if ( strlen( $v ) > 0 ) |
481 | | - $values[] = $v; |
482 | | - } |
483 | | - $this->mArrayExtension[$arrayid] = $values; |
| 524 | + return ''; |
484 | 525 | } |
485 | 526 | |
486 | 527 | |
487 | 528 | /** |
488 | | - * sort specified array in the following order: |
489 | | - * - none: No sort (default) |
490 | | - * - desc: In descending order, large to small |
491 | | - * - asce: In ascending order, small to large |
492 | | - * - random: Shuffle the arrry in random order |
493 | | - * - reverse: Return an array with elements in reverse order |
494 | | - * usage: |
495 | | - * {{#arraysort:arrayid|order}} |
496 | | - * |
497 | | - * see: http://www.php.net/manual/en/function.sort.php |
498 | | - * http://www.php.net/manual/en/function.rsort.php |
499 | | - * http://www.php.net/manual/en/function.shuffle.php |
500 | | - * http://us3.php.net/manual/en/function.array-reverse.php |
501 | | - */ |
502 | | - function arraysort( &$parser, $arrayid , $sort = 'none' ) { |
503 | | - $ret = $this->validate_array_by_arrayid( $arrayid ); |
504 | | - if ( $ret !== true ) { |
| 529 | + * sort specified array in the following order: |
| 530 | + * - none: No sort (default) |
| 531 | + * - desc: In descending order, large to small |
| 532 | + * - asce: In ascending order, small to large |
| 533 | + * - random: Shuffle the arrry in random order |
| 534 | + * - reverse: Return an array with elements in reverse order |
| 535 | + * usage: |
| 536 | + * {{#arraysort:arrayid|order}} |
| 537 | + * |
| 538 | + * see: http://www.php.net/manual/en/function.sort.php |
| 539 | + * http://www.php.net/manual/en/function.rsort.php |
| 540 | + * http://www.php.net/manual/en/function.shuffle.php |
| 541 | + * http://us3.php.net/manual/en/function.array-reverse.php |
| 542 | + */ |
| 543 | + function arraysort( Parser &$parser, $arrayId , $sort = 'none' ) { |
| 544 | + if( ! $this->arrayExists( $arrayId ) ) { |
505 | 545 | return ''; |
506 | 546 | } |
507 | | - |
508 | | - |
509 | | - switch ( $sort ) { |
| 547 | + |
| 548 | + // do the requested sorting of the given array: |
| 549 | + switch( $sort ) { |
510 | 550 | case 'asc': |
511 | 551 | case 'asce': |
512 | | - case 'ascending': sort( $this->mArrayExtension[$arrayid] ); break; |
513 | | - |
514 | | - |
| 552 | + case 'ascending': |
| 553 | + sort( $this->mArrayExtension[ $arrayId ] ); |
| 554 | + break; |
| 555 | + |
515 | 556 | case 'desc': |
516 | | - case 'descending': rsort( $this->mArrayExtension[$arrayid] ); break; |
| 557 | + case 'descending': |
| 558 | + rsort( $this->mArrayExtension[ $arrayId ] ); |
| 559 | + break; |
517 | 560 | |
518 | | - case 'random': shuffle( $this->mArrayExtension[$arrayid] ); break; |
| 561 | + case 'random': |
| 562 | + shuffle( $this->mArrayExtension[ $arrayId ] ); |
| 563 | + break; |
519 | 564 | |
520 | | - |
521 | | - case 'reverse': $this->mArrayExtension[$arrayid] = array_reverse( $this->mArrayExtension[$arrayid] ); break; |
| 565 | + case 'reverse': |
| 566 | + $this->mArrayExtension[ $arrayId ] = array_reverse( $this->mArrayExtension[ $arrayId ] ); |
| 567 | + break; |
522 | 568 | } ; |
523 | 569 | } |
524 | 570 | |
— | — | @@ -534,30 +580,30 @@ |
535 | 581 | * merge values two arrayes identified by arrayid1 and arrayid2 into a new array identified by arrayid_new. |
536 | 582 | * this merge differs from array_merge of php because it merges values. |
537 | 583 | */ |
538 | | - function arraymerge( &$parser, $arrayid_new, $arrayid1, $arrayid2 = '' ) { |
539 | | - if ( !isset( $arrayid_new ) || !isset( $arrayid1 ) ) |
| 584 | + function arraymerge( Parser &$parser, $arrayId_new, $arrayId1 = '', $arrayId2 = '' ) { |
| 585 | + if( !isset( $arrayId_new ) || !isset( $arrayId1 ) ) |
540 | 586 | return ''; |
541 | 587 | |
542 | | - $ret = $this->validate_array_by_arrayid( $arrayid1 ); |
543 | | - if ( $ret !== true ) { |
| 588 | + $ret = $this->validate_array_by_arrayId( $arrayId1 ); |
| 589 | + if( $ret !== true ) { |
544 | 590 | return ''; |
545 | 591 | } |
546 | 592 | |
547 | 593 | $temp_array = array(); |
548 | | - foreach ( $this->mArrayExtension[$arrayid1] as $entry ) { |
| 594 | + foreach( $this->mArrayExtension[ $arrayId1 ] as $entry ) { |
549 | 595 | array_push ( $temp_array, $entry ); |
550 | 596 | } |
551 | 597 | |
552 | | - if ( isset( $arrayid2 ) && strlen( $arrayid2 ) > 0 ) { |
553 | | - $ret = $this->validate_array_by_arrayid( $arrayid2 ); |
554 | | - if ( $ret === true ) { |
555 | | - foreach ( $this->mArrayExtension[$arrayid2] as $entry ) { |
| 598 | + if( isset( $arrayId2 ) && strlen( $arrayId2 ) > 0 ) { |
| 599 | + $ret = $this->validate_array_by_arrayId( $arrayId2 ); |
| 600 | + if( $ret === true ) { |
| 601 | + foreach( $this->mArrayExtension[ $arrayId2 ] as $entry ) { |
556 | 602 | array_push ( $temp_array, $entry ); |
557 | 603 | } |
558 | 604 | } |
559 | 605 | } |
560 | 606 | |
561 | | - $this->mArrayExtension[$arrayid_new] = $temp_array; |
| 607 | + $this->mArrayExtension[$arrayId_new] = $temp_array; |
562 | 608 | return ''; |
563 | 609 | } |
564 | 610 | |
— | — | @@ -569,35 +615,34 @@ |
570 | 616 | * extract a slice from an array |
571 | 617 | * see: http://www.php.net/manual/en/function.array-slice.php |
572 | 618 | */ |
573 | | - function arrayslice( &$parser, $arrayid_new , $arrayid , $offset, $length = '' ) { |
574 | | - if ( ! isset( $arrayid_new ) || ! isset( $arrayid ) || ! isset( $offset ) ) |
575 | | - return ''; |
| 619 | + function arrayslice( Parser &$parser, $arrayId_new, $arrayId = null , $offset = 0, $length = null ) { |
| 620 | + if( $arrayId === null ) { |
| 621 | + $this->setArray( $arrayId_new ); |
| 622 | + return ''; |
| 623 | + } |
| 624 | + // get target array before overwriting it in any way |
| 625 | + $array = $this->getArray( $arrayId ); |
576 | 626 | |
577 | | - $ret = $this->validate_array_by_arrayid( $arrayid ); |
578 | | - if ( $ret !== true ) { |
579 | | - return ''; |
580 | | - } |
| 627 | + // make sure at least an empty array exists if we return early |
| 628 | + $this->setArray( $arrayId_new ); |
| 629 | + |
| 630 | + if( $array === null |
| 631 | + || ! is_numeric( $offset ) // don't ignore invalid offset |
| 632 | + ) { |
| 633 | + return ''; |
| 634 | + } |
581 | 635 | |
582 | | - // $ret = $this->validate_array_offset($offset, $this->mArrayExtension[$arrayid]); |
583 | | - // if ($ret !== true){ |
584 | | - // return ''; |
585 | | - // } |
| 636 | + if( ! is_numeric( $length ) ) { |
| 637 | + $length = null; // ignore invalid input, slice till end |
| 638 | + } |
| 639 | + |
| 640 | + // array_slice will re-organize keys |
| 641 | + $newArray = array_slice( $array, $offset, $length ); |
| 642 | + $this->mArrayExtension[ $arrayId_new ] = $newArray; |
| 643 | + |
| 644 | + return ''; |
| 645 | + } |
586 | 646 | |
587 | | - $temp_array = array(); |
588 | | - if ( is_numeric( $offset ) ) { |
589 | | - if ( $this->is_non_empty( $length ) && is_numeric( $length ) ) { |
590 | | - $temp = array_slice( $this->mArrayExtension[$arrayid], $offset, $length ); |
591 | | - } else { |
592 | | - $temp = array_slice( $this->mArrayExtension[$arrayid], $offset ); |
593 | | - } |
594 | | - |
595 | | - if ( !empty( $temp ) && is_array( $temp ) ) |
596 | | - $temp_array = array_values( $temp ); |
597 | | - } |
598 | | - $this->mArrayExtension[$arrayid_new] = $temp_array; |
599 | | - return ''; |
600 | | - } |
601 | | - |
602 | 647 | /** |
603 | 648 | * set operation, {red, white} = {red, white} union {red} |
604 | 649 | * usage: |
— | — | @@ -605,23 +650,19 @@ |
606 | 651 | |
607 | 652 | * similar to arraymerge, this union works on values. |
608 | 653 | */ |
609 | | - function arrayunion( &$parser, $arrayid_new , $arrayid1 = null , $arrayid2 = null ) { |
610 | | - if ( ! isset( $arrayid_new ) || ! isset( $arrayid1 ) || ! isset( $arrayid2 ) ) { |
| 654 | + function arrayunion( Parser &$parser, $arrayId_new, $arrayId1 = null , $arrayId2 = null ) { |
| 655 | + if ( ! isset( $arrayId_new ) || ! isset( $arrayId1 ) || ! isset( $arrayId2 ) ) { |
611 | 656 | return ''; |
612 | 657 | } |
613 | | - |
614 | | - $ret = $this->validate_array_by_arrayid( $arrayid1 ); |
615 | | - if ( $ret !== true ) { |
| 658 | + if( ! isset( $arrayId1 ) || ! $this->arrayExists( $arrayId1 ) ) { |
616 | 659 | return ''; |
617 | 660 | } |
618 | | - |
619 | | - $ret = $this->validate_array_by_arrayid( $arrayid2 ); |
620 | | - if ( $ret !== true ) { |
| 661 | + if( ! isset( $arrayId2 ) || ! $this->arrayExists( $arrayId2 ) ) { |
621 | 662 | return ''; |
622 | 663 | } |
623 | 664 | |
624 | | - $this->arraymerge( $parser, $arrayid_new, $arrayid1, $arrayid2 ); |
625 | | - $this->mArrayExtension[$arrayid_new] = array_unique ( $this->mArrayExtension[$arrayid_new] ); |
| 665 | + $this->arraymerge( $parser, $arrayId_new, $arrayId1, $arrayId2 ); |
| 666 | + $this->mArrayExtension[$arrayId_new] = array_unique ( $this->mArrayExtension[$arrayId_new] ); |
626 | 667 | |
627 | 668 | return ''; |
628 | 669 | } |
— | — | @@ -635,26 +676,22 @@ |
636 | 677 | * {{#arrayintersect:arrayid_new|arrayid1|arrayid2}} |
637 | 678 | * See: http://www.php.net/manual/en/function.array-intersect.php |
638 | 679 | */ |
639 | | - function arrayintersect( &$parser, $arrayid_new , $arrayid1 = null , $arrayid2 = null ) { |
640 | | - if ( ! isset( $arrayid_new ) || ! isset( $arrayid1 ) || ! isset( $arrayid2 ) ) { |
| 680 | + function arrayintersect( Parser &$parser, $arrayId_new, $arrayId1 = null , $arrayId2 = null ) { |
| 681 | + if ( ! isset( $arrayId_new ) || ! isset( $arrayId1 ) || ! isset( $arrayId2 ) ) { |
641 | 682 | return ''; |
642 | 683 | } |
643 | | - |
644 | | - $ret = $this->validate_array_by_arrayid( $arrayid1 ); |
645 | | - if ( $ret !== true ) { |
| 684 | + if( ! isset( $arrayId1 ) || ! $this->arrayExists( $arrayId1 ) ) { |
646 | 685 | return ''; |
647 | 686 | } |
648 | | - |
649 | | - $ret = $this->validate_array_by_arrayid( $arrayid2 ); |
650 | | - if ( $ret !== true ) { |
| 687 | + if( ! isset( $arrayId2 ) || ! $this->arrayExists( $arrayId2 ) ) { |
651 | 688 | return ''; |
652 | 689 | } |
653 | 690 | |
654 | 691 | // keys will be preserved... |
655 | | - $newArray = array_intersect( array_unique( $this->mArrayExtension[$arrayid1] ), array_unique( $this->mArrayExtension[$arrayid2] ) ); |
| 692 | + $newArray = array_intersect( array_unique( $this->mArrayExtension[$arrayId1] ), array_unique( $this->mArrayExtension[$arrayId2] ) ); |
656 | 693 | |
657 | 694 | // ...so we have to reorganize the key order |
658 | | - $this->mArrayExtension[$arrayid_new] = $this->reorganizeArrayKeys( $newArray ); |
| 695 | + $this->mArrayExtension[$arrayId_new] = $this->sanitizeArray( $newArray ); |
659 | 696 | |
660 | 697 | return ''; |
661 | 698 | } |
— | — | @@ -667,26 +704,22 @@ |
668 | 705 | * set operation, {white} = {red, white} - {red} |
669 | 706 | * see: http://www.php.net/manual/en/function.array-diff.php |
670 | 707 | */ |
671 | | - function arraydiff( &$parser, $arrayid_new , $arrayid1 = null , $arrayid2 = null ) { |
672 | | - if ( ! isset( $arrayid_new ) || ! isset( $arrayid1 ) || ! isset( $arrayid2 ) ) { |
| 708 | + function arraydiff( Parser &$parser, $arrayId_new, $arrayId1 = null , $arrayId2 = null ) { |
| 709 | + if ( ! isset( $arrayId_new ) || ! isset( $arrayId1 ) || ! isset( $arrayId2 ) ) { |
673 | 710 | return ''; |
674 | | - } |
675 | | - |
676 | | - $ret = $this->validate_array_by_arrayid( $arrayid1 ); |
677 | | - if ( $ret !== true ) { |
| 711 | + } |
| 712 | + if( ! isset( $arrayId1 ) || ! $this->arrayExists( $arrayId1 ) ) { |
678 | 713 | return ''; |
679 | 714 | } |
680 | | - |
681 | | - $ret = $this->validate_array_by_arrayid( $arrayid2 ); |
682 | | - if ( $ret !== true ) { |
| 715 | + if( ! isset( $arrayId2 ) || ! $this->arrayExists( $arrayId2 ) ) { |
683 | 716 | return ''; |
684 | 717 | } |
685 | 718 | |
686 | 719 | // keys will be preserved... |
687 | | - $newArray = array_diff( array_unique( $this->mArrayExtension[$arrayid1] ), array_unique( $this->mArrayExtension[$arrayid2] ) ); |
| 720 | + $newArray = array_diff( array_unique( $this->mArrayExtension[$arrayId1] ), array_unique( $this->mArrayExtension[$arrayId2] ) ); |
688 | 721 | |
689 | 722 | // ...so we have to reorganize the key order |
690 | | - $this->mArrayExtension[$arrayid_new] = $this->reorganizeArrayKeys( $newArray ); |
| 723 | + $this->mArrayExtension[$arrayId_new] = $this->sanitizeArray( $newArray ); |
691 | 724 | |
692 | 725 | return ''; |
693 | 726 | } |
— | — | @@ -697,16 +730,30 @@ |
698 | 731 | // private functions |
699 | 732 | ///////////////////////////////////////////////// / |
700 | 733 | |
701 | | - function is_non_empty( $var ) { |
702 | | - return isset( $var ) && strlen( $var ) > 0; |
703 | | - } |
704 | | - |
705 | | - // private functions for validating the index of an array |
706 | | - function validate_array_index( $arrayId, &$index, $negativeBelowZeroReset = false ) { |
| 734 | + /** |
| 735 | + * Validates an index for an array and returns true in case the index is a valid index within |
| 736 | + * the array. This also changes the index value, which is given by reference, in case it is |
| 737 | + * set to a negative value. In case $strictIndex is set to false, further transforming of |
| 738 | + * $index might be done - in the same cases normally the function would return false. |
| 739 | + * |
| 740 | + * @param string $arrayId |
| 741 | + * @param mixed &$index |
| 742 | + * @param bool $strictIndex Whether non-numeric indexes and negative indexes which would |
| 743 | + * end up out of range, below 0, should be set to 0 automatically. |
| 744 | + * |
| 745 | + * @return boolean |
| 746 | + */ |
| 747 | + private function validate_array_index( $arrayId, &$index, $strictIndex = false ) { |
| 748 | + |
| 749 | + if ( ! is_numeric( $index ) ) { |
| 750 | + if( $strictIndex ) { |
| 751 | + return false; |
| 752 | + } else { |
| 753 | + $index = 0; |
| 754 | + } |
| 755 | + } |
| 756 | + $index = (int)$index; |
707 | 757 | |
708 | | - if ( ! is_numeric( $index ) ) |
709 | | - return false; |
710 | | - |
711 | 758 | if( ! array_key_exists( $arrayId, $this->mArrayExtension ) ) |
712 | 759 | return false; |
713 | 760 | |
— | — | @@ -715,61 +762,53 @@ |
716 | 763 | // calculate start index for negative start indexes: |
717 | 764 | if ( $index < 0 ) { |
718 | 765 | $index = count( $array ) + $index; |
719 | | - if ( $index < 0 && $negativeBelowZeroReset ) { |
| 766 | + if ( $index < 0 && !$strictIndex ) { |
720 | 767 | $index = 0; |
721 | 768 | } |
722 | 769 | } |
723 | 770 | |
724 | | - if ( ! isset( $array ) ) |
725 | | - return false; |
726 | | - |
727 | | - if ( ! array_key_exists( $index, $array ) ) |
728 | | - return false; |
729 | | - |
| 771 | + if ( ! isset( $array ) ) { |
| 772 | + return false; |
| 773 | + } |
| 774 | + if ( ! array_key_exists( $index, $array ) ) { |
| 775 | + return false; |
| 776 | + } |
730 | 777 | return true; |
731 | 778 | } |
732 | 779 | |
733 | | - // private functions for validating the index of an array |
734 | | - function validate_array_offset( $offset, $array ) { |
735 | | - if ( !isset( $offset ) ) |
736 | | - return false; |
737 | | - |
738 | | - |
739 | | - if ( !is_numeric( $offset ) ) |
740 | | - return false; |
741 | | - |
742 | | - |
743 | | - if ( !isset( $array ) || !is_array( $array ) ) |
744 | | - return false; |
745 | | - |
746 | | - if ( $offset >= count( $array ) ) |
747 | | - return false; |
748 | | - |
749 | | - return true; |
750 | | - } |
751 | | - |
752 | 780 | // private function for validating array by name |
753 | | - function validate_array_by_arrayid( $array_name ) { |
754 | | - if ( !isset( $array_name ) ) |
| 781 | + private function validate_array_by_arrayId( $arrayId ) { |
| 782 | + if( ! isset( $arrayId ) ) |
755 | 783 | return ''; |
756 | 784 | |
757 | | - if ( !isset( $this->mArrayExtension ) ) |
758 | | - return "undefined array: $array_name"; |
| 785 | + if( ! isset( $this->mArrayExtension ) |
| 786 | + || ! array_key_exists( $arrayId, $this->mArrayExtension ) |
| 787 | + || ! is_array( $this->mArrayExtension[ $arrayId ] ) |
| 788 | + ) { |
| 789 | + global $egArrayExtensionCompatbilityMode; |
| 790 | + if( $egArrayExtensionCompatbilityMode ) { |
| 791 | + return "undefined array: $arrayId"; // COMPATBILITY-MODE |
| 792 | + } else { |
| 793 | + return ''; |
| 794 | + } |
| 795 | + } |
759 | 796 | |
760 | | - if ( !array_key_exists( $array_name, $this->mArrayExtension ) || !is_array( $this->mArrayExtension[$array_name] ) ) |
761 | | - return "undefined array: $array_name"; |
762 | | - |
763 | 797 | return true; |
764 | 798 | } |
765 | | - |
766 | | - function get_array_value( $array, $field ) { |
767 | | - if ( is_array( $array ) && FALSE !== array_key_exists( $field, $array ) ) |
768 | | - return $array[$field]; |
769 | | - else |
770 | | - return ''; |
| 799 | + |
| 800 | + /** |
| 801 | + * Convenience function to get a value from an array. Returns '' in case the |
| 802 | + * value doesn't exist or no array was given |
| 803 | + */ |
| 804 | + private function array_value( $array, $field ) { |
| 805 | + if ( is_array( $array ) && array_key_exists( $field, $array ) ) { |
| 806 | + return $array[ $field ]; |
| 807 | + } else { |
| 808 | + return ''; |
| 809 | + } |
771 | 810 | } |
772 | 811 | |
773 | | - function parse_options( $options ) { |
| 812 | + private function parse_options( $options ) { |
774 | 813 | if ( isset( $options ) ) { |
775 | 814 | // now parse the options, and do posterior process on the created array |
776 | 815 | $ary_option = preg_split ( '/\s*[,]\s*/', strtolower( $options ) ); |
— | — | @@ -797,48 +836,86 @@ |
798 | 837 | /* ============================ */ |
799 | 838 | /* ============================ */ |
800 | 839 | |
801 | | - function getArrayValue( $arrayId = '', $key = '' ) { |
| 840 | + /** |
| 841 | + * Returns an array identified by $arrayId. If it doesn't exist, null will be returned. |
| 842 | + * |
| 843 | + * @since 1.4 |
| 844 | + * |
| 845 | + * @param string $arrayId |
| 846 | + * |
| 847 | + * @return array|null |
| 848 | + */ |
| 849 | + function getArray( $arrayId ) { |
802 | 850 | $arrayId = trim( $arrayId ); |
803 | | - if ( $this->arrayExists( $arrayId ) && array_key_exists( $key, $this->mArrayExtension[ $arrayId ] ) ) |
804 | | - return $this->mArrayExtension[ $arrayId ][ $key ]; |
805 | | - else |
806 | | - return ''; |
807 | | - } |
808 | | - |
809 | | - // return an array identified by $arrayId. If it doesn't exist this will return null. |
810 | | - function getArray( $arrayId = '' ) { |
811 | | - if ( $this->arrayExists( $arrayId ) ) |
| 851 | + if( $this->arrayExists( $arrayId ) ) { |
812 | 852 | return $this->mArrayExtension[ $arrayId ]; |
813 | | - else |
814 | | - return null; |
| 853 | + } |
| 854 | + return null; |
815 | 855 | } |
816 | 856 | |
817 | 857 | /** |
| 858 | + * This will add a new array or overwrite an existing one. Values should be delliverd as array |
| 859 | + * values in form of a string. The array will be sanitized internally. |
| 860 | + * |
| 861 | + * @param string $arrayId |
| 862 | + * @param array $array |
| 863 | + */ |
| 864 | + public function createArray( $arrayId, $array = array() ) { |
| 865 | + $array = $this->sanitizeArray( $array ); |
| 866 | + $this->mArrayExtension[ trim( $arrayId ) ] = $array; |
| 867 | + } |
| 868 | + |
| 869 | + /** |
| 870 | + * Same as the public createArray but without sanitizing the array automatically |
| 871 | + * |
| 872 | + * @param type $arrayId |
| 873 | + * @param type $array |
| 874 | + */ |
| 875 | + protected function setArray( $arrayId, $array = array() ) { |
| 876 | + $this->mArrayExtension[ trim( $arrayId ) ] = $array; |
| 877 | + } |
| 878 | + |
| 879 | + /** |
818 | 880 | * Returns whether a certain array is defined within the page scope. |
819 | 881 | * |
820 | 882 | * @param string $arrayId |
| 883 | + * |
821 | 884 | * @return boolean |
822 | 885 | */ |
823 | | - function arrayExists( $arrayId = '' ) { |
| 886 | + function arrayExists( $arrayId ) { |
824 | 887 | return array_key_exists( trim( $arrayId ), $this->mArrayExtension ); |
825 | 888 | } |
826 | | - |
| 889 | + |
827 | 890 | /** |
828 | | - * Adds a new array or overwrites an existing one. |
| 891 | + * Returns a value within an array. If key or array do not exist, this will return null |
| 892 | + * or another predefined default. |
829 | 893 | * |
| 894 | + * @since 1.4 |
| 895 | + * |
830 | 896 | * @param string $arrayId |
831 | | - * @param array $arr the new array, should contain string values. |
| 897 | + * @param string $key |
| 898 | + * @param mixed $default value to return in case the value doesn't exist. null by default. |
| 899 | + * |
| 900 | + * @return string |
832 | 901 | */ |
833 | | - public function createArray( $arrayId = '', $arr = array() ) { |
834 | | - $arr = $this->reorganizeArrayKeys( $arr ); |
835 | | - $this->mArrayExtension[ trim( $arrayId ) ] = $arr; |
836 | | - } |
| 902 | + function getArrayValue( $arrayId, $key, $default = null ) { |
| 903 | + $arrayId = trim( $arrayId ); |
| 904 | + if( $this->arrayExists( $arrayId ) |
| 905 | + && array_key_exists( $key, $this->mArrayExtension[ $arrayId ] ) |
| 906 | + ) { |
| 907 | + return $this->mArrayExtension[ $arrayId ][ $key ]; |
| 908 | + } |
| 909 | + else { |
| 910 | + return $default; |
| 911 | + } |
| 912 | + } |
837 | 913 | |
838 | 914 | |
839 | 915 | /** |
840 | 916 | * Removes an existing array. If array didn't exist this will return false, otherwise true. |
841 | 917 | * |
842 | 918 | * @param string $arrayId |
| 919 | + * |
843 | 920 | * @return boolean whether the array existed and has been removed |
844 | 921 | */ |
845 | 922 | public function unsetArray( $arrayId ) { |
— | — | @@ -851,24 +928,59 @@ |
852 | 929 | } |
853 | 930 | |
854 | 931 | /** |
855 | | - * Rebuild the array and reorganize all keys. This means all gaps between array items will be closed. |
| 932 | + * Rebuild the array and reorganize all keys, trim all values. |
| 933 | + * All gaps between array items will be closed. |
856 | 934 | * |
857 | 935 | * @param array $arr array to be reorganized |
858 | 936 | * @return array |
859 | 937 | */ |
860 | | - public function reorganizeArrayKeys( $arr = array() ) { |
| 938 | + public function sanitizeArray( $array ) { |
861 | 939 | $newArray = array(); |
862 | | - foreach ( $arr as $val ) { |
| 940 | + foreach( $array as $val ) { |
863 | 941 | $newArray[] = trim( $val ); |
864 | 942 | } |
865 | 943 | return $newArray; |
866 | 944 | } |
| 945 | + |
| 946 | + /** |
| 947 | + * Removes duplicate values and all empty elements from an array just like the |
| 948 | + * arrayunique parser function would do it. The array will be sanitized internally. |
| 949 | + * |
| 950 | + * @since 1.4 |
| 951 | + * |
| 952 | + * @param array $array |
| 953 | + * |
| 954 | + * @return array |
| 955 | + */ |
| 956 | + public function arrayUnique( array $array ) { |
| 957 | + $arr = $this->sanitizeArray( $arr ); |
| 958 | + $array = $this->array_unique( $array ); |
| 959 | + } |
| 960 | + |
| 961 | + /** |
| 962 | + * same as self::arrayUnique() but without sanitazation, only for internal use. |
| 963 | + */ |
| 964 | + private function array_unique( array $array ) { |
| 965 | + // delete duplicate values |
| 966 | + $array = array_unique( $array ); |
| 967 | + |
| 968 | + $values = array(); |
| 969 | + foreach( $array as $key => $val ) { |
| 970 | + // don't put emty elements into the array |
| 971 | + if( $val !== '' ) { |
| 972 | + $values[] = $val; |
| 973 | + } |
| 974 | + } |
| 975 | + |
| 976 | + return $values; |
| 977 | + } |
867 | 978 | |
868 | 979 | /** |
869 | 980 | * Decides for the given $pattern whether its a valid regular expression acceptable for |
870 | 981 | * ArrayExtension parser functions or not. |
871 | 982 | * |
872 | 983 | * @param string $pattern regular expression including delimiters and optional flags |
| 984 | + * |
873 | 985 | * @return boolean |
874 | 986 | */ |
875 | 987 | function isValidRegEx( $pattern ) { |
— | — | @@ -882,7 +994,7 @@ |
883 | 995 | } |
884 | 996 | } |
885 | 997 | |
886 | | -function efArrayExtensionParserFirstCallInit( &$parser ) { |
| 998 | +function efArrayExtensionParserFirstCallInit( Parser &$parser ) { |
887 | 999 | global $wgArrayExtension; |
888 | 1000 | |
889 | 1001 | $wgArrayExtension = new ArrayExtension(); |
— | — | @@ -899,7 +1011,7 @@ |
900 | 1012 | $parser->setFunctionHook( 'arraysearch', array( &$wgArrayExtension, 'arraysearch' ), SFH_OBJECT_ARGS ); |
901 | 1013 | |
902 | 1014 | $parser->setFunctionHook( 'arraysort', array( &$wgArrayExtension, 'arraysort' ) ); |
903 | | - $parser->setFunctionHook( 'arrayunique', array( &$wgArrayExtension, 'arrayunique' ) ); |
| 1015 | + $parser->setFunctionHook( 'arrayunique', array( &$wgArrayExtension, 'pf_arrayunique' ) ); |
904 | 1016 | $parser->setFunctionHook( 'arrayreset', array( &$wgArrayExtension, 'arrayreset' ), SFH_OBJECT_ARGS ); |
905 | 1017 | |
906 | 1018 | $parser->setFunctionHook( 'arraymerge', array( &$wgArrayExtension, 'arraymerge' ) ); |
Index: trunk/extensions/ArrayExtension/RELEASE-NOTES |
— | — | @@ -1,110 +1,122 @@ |
2 | 2 | Changelog: |
3 | 3 | ========== |
4 | | - * (trunk) version 1.4 |
5 | | - - Configuration variable '$wgArrayExtensionCompatbilityMode' to deactivate the following |
6 | | - breaking changes: |
7 | | - + '#arrayreset' now uses n parameters instead of ',' as separator for n arrays to reset |
8 | | - + '#arraysearch' returns an empty string '' instead of '-1' in case nothing was found. |
| 4 | + |
| 5 | + * (trunk) -- Version 1.4 |
| 6 | + - Configuration variable '$egArrayExtensionCompatbilityMode' for deactivating the following newly |
| 7 | + introduced breaking changes: |
| 8 | + + '#arrayreset' now uses n parameters instead of ',' as separator for n arrays to reset |
| 9 | + + '#arraysearch' returns an empty string '' instead of '-1' in case nothing was found. |
9 | 10 | - '#arraysearch' will only expand 'yes' or 'no' if given, but never both. |
10 | | - - negative indexes for '#arraysearch' and '#arrayindex' possible. |
| 11 | + - negative indexes for '#arrayindex', '#arraysearch' and '#arraysearcharray' are possible now. |
| 12 | + - bugfix in '#arraysearcharray', index and limit working fine now. |
11 | 13 | - arrayprint will handle <includeonly>/<noinclude> correct in case it's used in a template. |
12 | | - - Internationalization in several languages added. |
13 | | - - moved into mediawiki.org svn repository. |
14 | | - |
15 | | - @ToDo before release: |
16 | | - - As in Variables 2.0, one store per Parser should be used. |
17 | | - - ''#arraysearch'' should not expand both, 'yes' and 'no', just the one actual case. |
18 | | - - Further breaking changes fixing weird old behavior and functionality |
19 | | - |
20 | | - |
21 | | - * January 24, 2011 version 1.3.2 |
| 14 | + - Internationalization for several languages added. |
| 15 | + - moved into mediawiki.org svn repository. |
| 16 | + |
| 17 | + @ToDo before release: |
| 18 | + - As in Variables 2.0, one store per Parser should be used. |
| 19 | + - ''#arraysearch'' should not expand both, 'yes' and 'no', just the one actual case. |
| 20 | + - Further breaking changes fixing weird old behavior and functionality |
| 21 | + |
| 22 | + |
| 23 | + * January 24, 2011 -- Version 1.3.2 |
22 | 24 | - New public class methods for creating and removing arrays. Good for use by other extensions. |
23 | 25 | - VERSION constant added to ArrayExtension class |
24 | | - * July 20, 2010 version 1.3.1 |
25 | | - - Removed critical bug. Some kind of "Superglobal" Arrays on page imports and job queue jobs. |
26 | | - Values were passed from one page to another page. |
27 | 26 | |
28 | | - * July 5, 2010 version 1.3 |
29 | | - - update arrayunion and arraydiff, fixed heavy bug (gaps between array indexes doing some serious |
30 | | - trouble in other arrayfunctions like arraysearch) |
31 | | - - array function ''#arraysearcharray'' added |
32 | | - - '#arraysearch' code cleanup, search parameter is optional now, searching for empty elements is |
33 | | - possible now |
34 | | - - advanced check for regular expressions in '#arraysearch,' '#arraydefine' and '#arraysearcharray' |
35 | | - Pivate function isValidRegEx() added |
36 | | - - '#arraymerge' bug fixed: Php message in case of non existant seccond array |
37 | | - - now using preg_quote in arraydefine when using a non regular expression delimiter |
38 | | - - some minor code changes and cleanup |
39 | | - |
40 | | - * January 23, 2010 version 1.2.4 |
| 27 | + * July 20, 2010 -- Version 1.3.1 |
| 28 | + - Removed critical bug. Some kind of "Superglobal" Arrays on page imports and job queue jobs. |
| 29 | + Values were passed from one page to another page. |
| 30 | + |
| 31 | + * July 5, 2010 -- Version 1.3 |
| 32 | + - update arrayunion and arraydiff, fixed heavy bug (gaps between array indexes doing some serious |
| 33 | + trouble in other arrayfunctions like arraysearch) |
| 34 | + - array function ''#arraysearcharray'' added |
| 35 | + - '#arraysearch' code cleanup, search parameter is optional now, searching for empty elements is |
| 36 | + possible now |
| 37 | + - advanced check for regular expressions in '#arraysearch,' '#arraydefine' and '#arraysearcharray' |
| 38 | + Pivate function isValidRegEx() added |
| 39 | + - '#arraymerge' bug fixed: Php message in case of non existant seccond array |
| 40 | + - now using preg_quote in arraydefine when using a non regular expression delimiter |
| 41 | + - some minor code changes and cleanup |
| 42 | + |
| 43 | + |
| 44 | + * January 23, 2010 -- Version 1.2.4 |
41 | 45 | - update arraydefine, add more parameter for combining print with arraydefine |
42 | 46 | |
43 | | - * July 16, 2009 version 1.2.3 |
| 47 | + * July 16, 2009 -- Version 1.2.3 |
44 | 48 | - update arrayunique, fixed bug (empty string should be eliminated in array after arrayunique) |
45 | 49 | |
46 | | - * July 16, 2009 version 1.2.2 |
| 50 | + * July 16, 2009 -- Version 1.2.2 |
47 | 51 | - update arrayunique, fixed bug (zero mistakenly eliminated in array after arrayunique) |
48 | 52 | - rename key=>arrayid, should not affect any existing users |
49 | 53 | - rename validate_array_by_name to validate_array_by_arrayid |
50 | 54 | - add "asc" as option of arraysort |
51 | 55 | |
52 | | - * May 03, 2009 version 1.2.1 |
| 56 | + * May 03, 2009 -- Version 1.2.1 |
53 | 57 | - update arraydefine by adding options: "unique"; sort=( "desc", "asce", "random", "reverse"), and |
54 | 58 | print=( "list" ). Options are diliminated by comma, e.g. "unique, sort=desc,print=list". |
55 | 59 | - fixed bug in arrayslice (offset can be greater than array size): if offset is no less than array |
56 | 60 | size, empty array will be returned, if offset if no greater than negative array size, a new array |
57 | | - with all elements will be returned |
| 61 | + with all elements will be returned |
58 | 62 | - update arrayindex by adding print option when (i) the array is not defined; (ii) the index is not |
59 | 63 | valid in the specified array: e.g. "default=bad array" |
60 | | - * April 24, 2009 version 1.2 |
61 | | - |
| 64 | + |
| 65 | + * April 24, 2009 -- Version 1.2 |
62 | 66 | - fixed a bug in arrayslice, (offset=0) |
63 | 67 | - clean up code, added two private functions, validate_array_index, validate_array_offset, |
64 | 68 | validate_array_by_arrayid; rename some parameters key=> new_key, differentiate offset and index |
65 | | - * April 18, 2009 version 1.1.6 |
66 | | - - fixed a bug in arraymerge and arrayslice, |
67 | | - * Mar 17, 2009 version 1.1.5 |
| 69 | + |
| 70 | + * April 18, 2009 -- Version 1.1.6 |
| 71 | + - fixed a bug in arraymerge and arrayslice, |
| 72 | + |
| 73 | + * Mar 17, 2009 -- Version 1.1.5 |
68 | 74 | - update '#arraysort,' add "reverse" option, http://us3.php.net/manual/en/function.array-reverse.php |
69 | 75 | - update '#arrayreset,' add option to reset a selection of arrays |
70 | | - * Feb 23, 2009 version 1.1.4 |
| 76 | + |
| 77 | + * Feb 23, 2009 -- Version 1.1.4 |
71 | 78 | - fixed '#arraysearch,' better recognize perl patterns identified by starting with "/", |
72 | 79 | http://www.perl.com/doc/manual/html/pod/perlre.html |
73 | | - * Feb 23, 2009 version 1.1.3 |
| 80 | + |
| 81 | + * Feb 23, 2009 -- Version 1.1.3 |
74 | 82 | - fixed '#arraysearch,' "Warning: Missing argument 4..." |
75 | | - * Feb 9, 2009 version 1.1.2 |
| 83 | + |
| 84 | + * Feb 9, 2009 -- Version 1.1.2 |
76 | 85 | - update '#arraysearch,' now support offset and preg regular expression |
77 | | - * Feb 8, 2009 version 1.1.1 |
| 86 | + |
| 87 | + * Feb 8, 2009 -- Version 1.1.1 |
78 | 88 | - update '#arrayprint,' now wiki links, parser functions and templates properly parsed. This enables |
79 | | - foreach loop call. |
| 89 | + foreach loop call. |
80 | 90 | - update '#arraysearch,' now allows customized output upon found/non-found by specifying additional |
81 | | - parameters |
82 | | - * Feb 5, 2009 version 1.1 |
| 91 | + parameters |
| 92 | + |
| 93 | + * Feb 5, 2009 -- Version 1.1 |
83 | 94 | - update '#arraydefine:' replacing 'explode' by 'preg_split', |
84 | 95 | and we now allow delimitors to be (i) a string; or (ii) a perl regular expressnion pattern, |
85 | | - sourrounded by '/', e.g. '/..blah.../' |
| 96 | + sourrounded by '/', e.g. '/..blah.../' |
86 | 97 | - update '#arrayprint,' change parameters from "prefix","suffix" to a "template", and users can |
87 | | - replace a substring in the template with array value, similar to arraymap in semantic forms |
| 98 | + replace a substring in the template with array value, similar to arraymap in semantic forms |
88 | 99 | - update '#arrayunique,' empty elements will be removed |
89 | 100 | - update '#arraysort:' adding "random" option to make the array of values in random order |
90 | 101 | - add '#arrayreset' to free all defined arrays for memory saving |
91 | 102 | - add '#arrayslice' to return an array bounded by start_index and length. |
92 | 103 | - add '#arraysearch.' now we can return the index of the first occurence of an element, return -1 if |
93 | | - not found |
| 104 | + not found |
94 | 105 | - remove '#arraymember,' obsoleted by '#arraysearch' |
95 | 106 | - remove '#arraypush,' obsoleted by '#arraydefine' and '#arraymerge' |
96 | 107 | - remove '#arraypop,' obsoleted by '#arrayslice' |
97 | 108 | - add safty check code to avoid unset parameters |
98 | | - |
99 | | - * Feb 1, 2009 version 1.0.3 |
| 109 | + |
| 110 | + * Feb 1, 2009 -- Version 1.0.3 |
100 | 111 | - fixed bug on arrayunique, php array_unique only make values unique, but the array index was not |
101 | | - updated. (arraydefine is also affected) |
102 | | - * Jan 28, 2009 version 1.0.2 |
| 112 | + updated. (arraydefine is also affected) |
| 113 | + |
| 114 | + * Jan 28, 2009 -- Version 1.0.2 |
103 | 115 | - changed arraypop (add one parameter to support multiple pop) |
104 | 116 | - added arrayindex (return an array element at index) |
105 | | - * Jan 27, 2009 version 1.0.1 |
| 117 | + |
| 118 | + * Jan 27, 2009 -- Version 1.0.1 |
106 | 119 | - changed arraydefine (allow defining empty array) |
107 | | - |
108 | | - |
| 120 | + |
109 | 121 | ------------------------------------------- |
110 | 122 | the following fuctions are obsoleted |
111 | 123 | '#arraypush' (replaced by arraymerge) |