Index: trunk/extensions/ArrayExtension/ArrayExtension.i18n.php |
— | — | @@ -0,0 +1,41 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Get translated magic words, if available |
| 6 | + * |
| 7 | + * @param string $lang Language code |
| 8 | + * @return array |
| 9 | + */ |
| 10 | +function efArrayExtensionWords( $lang ) { |
| 11 | + $words = array(); |
| 12 | + |
| 13 | + /** |
| 14 | + * English |
| 15 | + */ |
| 16 | + $words['en'] = array( |
| 17 | + 'arraydefine' => array( 0, 'arraydefine' ), |
| 18 | + |
| 19 | + 'arrayprint' => array( 0, 'arrayprint' ), |
| 20 | + 'arraysize' => array( 0, 'arraysize' ), |
| 21 | + 'arrayindex' => array( 0, 'arrayindex' ), |
| 22 | + 'arraysearch' => array( 0, 'arraysearch' ), |
| 23 | + |
| 24 | + 'arrayunique' => array( 0, 'arrayunique' ), |
| 25 | + 'arraysort' => array( 0, 'arraysort' ), |
| 26 | + 'arrayreset' => array( 0, 'arrayreset' ), |
| 27 | + |
| 28 | + 'arraymerge' => array( 0, 'arraymerge' ), |
| 29 | + 'arrayslice' => array( 0, 'arrayslice' ), |
| 30 | + |
| 31 | + 'arrayunion' => array( 0, 'arrayunion' ), |
| 32 | + 'arrayintersect' => array( 0, 'arrayintersect' ), |
| 33 | + 'arraydiff' => array( 0, 'arraydiff' ), |
| 34 | + 'arraysearcharray' => array( 0, 'arraysearcharray' ), |
| 35 | + ); |
| 36 | + |
| 37 | + # English is used as a fallback, and the English synonyms are |
| 38 | + # used if a translation has not been provided for a given word |
| 39 | + return ( $lang == 'en' || !isset( $words[$lang] ) ) |
| 40 | + ? $words['en'] |
| 41 | + : array_merge( $words['en'], $words[$lang] ); |
| 42 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/ArrayExtension/ArrayExtension.i18n.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 43 | + native |
Index: trunk/extensions/ArrayExtension/ArrayExtension.php |
— | — | @@ -0,0 +1,874 @@ |
| 2 | +<?php |
| 3 | +/* |
| 4 | + Defines a subset of parser functions that operate with arrays. |
| 5 | + verion: 1.3.2 |
| 6 | + authors: Li Ding (lidingpku@gmail.com) and Jie Bao, Daniel Werner (since version 1.3) |
| 7 | + update: 24th January 2011 |
| 8 | + |
| 9 | + homepage: http://www.mediawiki.org/wiki/Extension:ArrayExtension |
| 10 | + |
| 11 | + |
| 12 | +ToDo: |
| 13 | +===== |
| 14 | + |
| 15 | + - add experimental table (2 dimension array) data structure |
| 16 | + * table = header, row+ (1,1....) |
| 17 | + * sort_table_by_header (header) |
| 18 | + * sort_table_by_col (col) |
| 19 | + * print_table (format) e.g. csv, ul, ol, |
| 20 | + * add_table_row (array) |
| 21 | + * get_table_row (row) to an array |
| 22 | + * add_table_col(array) |
| 23 | + * get_table_col (col) to an array |
| 24 | + * get_table_header () to an array |
| 25 | + * get_total_row |
| 26 | + * get_total_col |
| 27 | + |
| 28 | + |
| 29 | + Changelog: |
| 30 | + ========== |
| 31 | + * January 24, 2011 version 1.3.2 |
| 32 | + - New public class methods for creating and removing arrays. Good for use by other extensions. |
| 33 | + - VERSION constant added to ArrayExtension class |
| 34 | + * July 20, 2010 version 1.3.1 |
| 35 | + - Removed critical bug. Some kind of "Superglobal" Arrays on page imports and job queue jobs. Values were passed from one page to another page. |
| 36 | + |
| 37 | + * July 5, 2010 version 1.3 |
| 38 | + - update arrayunion and arraydiff, fixed heavy bug (gaps between array indexes doing some serious trouble in other arrayfunctions like arraysearch) |
| 39 | + - array function #arraysearcharray added |
| 40 | + - #arraysearch code cleanup, search parameter is optional now, searching for empty elements is possible now |
| 41 | + - advanced check for regular expressions in #arraysearch, #arraydefine and #arraysearcharray |
| 42 | + Pivate function isValidRegEx() added |
| 43 | + - #arraymerge bug fixed: Php message in case of non existant seccond array |
| 44 | + - now using preg_quote in arraydefine when using a non regular expression delimiter |
| 45 | + - some minor code changes and cleanup |
| 46 | + |
| 47 | + * January 23, 2010 version 1.2.4 |
| 48 | + - update arraydefine, add more parameter for combining print with arraydefine |
| 49 | + |
| 50 | + * July 16, 2009 version 1.2.3 |
| 51 | + - update arrayunique, fixed bug (empty string should be eliminated in array after arrayunique) |
| 52 | + |
| 53 | + * July 16, 2009 version 1.2.2 |
| 54 | + - update arrayunique, fixed bug (zero mistakenly eliminated in array after arrayunique) |
| 55 | + - rename key=>arrayid, should not affect any existing users |
| 56 | + - rename validate_array_by_name to validate_array_by_arrayid |
| 57 | + - add "asc" as option of arraysort |
| 58 | + |
| 59 | + * May 03, 2009 version 1.2.1 |
| 60 | + - update arraydefine by adding options: "unique"; sort=( "desc", "asce", "random", "reverse"), and print=( "list" ). Options are diliminated by comma, e.g. "unique, sort=desc,print=list". |
| 61 | + - fixed bug in arrayslice (offset can be greater than array size): if offset is no less than array size, empty array will be returned, if offset if no greater than negative array size, a new array with all elements will be returned |
| 62 | + - update arrayindex by adding print option when (i) the array is not defined; (ii) the index is not valid in the specified array: e.g. "default=bad array" |
| 63 | + * April 24, 2009 version 1.2 |
| 64 | + |
| 65 | + - fixed a bug in arrayslice, (offset=0) |
| 66 | + - clean up code, added two private functions, validate_array_index, validate_array_offset, validate_array_by_arrayid; rename some parameters key=> new_key, differentiate offset and index |
| 67 | + * April 18, 2009 version 1.1.6 |
| 68 | + - fixed a bug in arraymerge and arrayslice, |
| 69 | + * Mar 17, 2009 version 1.1.5 |
| 70 | + - update #arraysort, add "reverse" option, http://us3.php.net/manual/en/function.array-reverse.php |
| 71 | + - update #arrayreset, add option to reset a selection of arrays |
| 72 | + * Feb 23, 2009 version 1.1.4 |
| 73 | + - fixed #arraysearch, better recognize perl patterns identified by starting with "/", http://www.perl.com/doc/manual/html/pod/perlre.html |
| 74 | + * Feb 23, 2009 version 1.1.3 |
| 75 | + - fixed #arraysearch, "Warning: Missing argument 4..." |
| 76 | + * Feb 9, 2009 version 1.1.2 |
| 77 | + - update #arraysearch, now support offset and preg regular expression |
| 78 | + * Feb 8, 2009 version 1.1.1 |
| 79 | + - update #arrayprint, now wiki links, parser functions and templates properly parsed. This enables foreach loop call. |
| 80 | + - update #arraysearch, now allows customized output upon found/non-found by specifying additional parameters |
| 81 | + * Feb 5, 2009 version 1.1 |
| 82 | + - update #arraydefine: replacing 'explode' by 'preg_split', |
| 83 | + and we now allow delimitors to be (i) a string; or (ii) a perl regular expressnion pattern, sourrounded by '/', e.g. '/..blah.../' |
| 84 | + - update #arrayprint, change parameters from "prefix","suffix" to a "template", |
| 85 | + and users can replace a substring in the template with array value, similar to arraymap in semantic forms |
| 86 | + - update #arrayunique, empty elements will be removed |
| 87 | + - update #arraysort: adding "random" option to make the array of values in random order |
| 88 | + - add #arrayreset to free all defined arrays for memory saving |
| 89 | + - add #arrayslice to return an array bounded by start_index and length. |
| 90 | + - add #arraysearch. now we can return the index of the first occurence of an element, return -1 if not found |
| 91 | + - remove #arraymember, obsoleted by #arraysearch |
| 92 | + - remove #arraypush, obsoleted by #arraydefine and #arraymerge |
| 93 | + - remove #arraypop, obsoleted by #arrayslice |
| 94 | + - add safty check code to avoid unset parameters |
| 95 | + |
| 96 | + * Feb 1, 2009 version 1.0.3 |
| 97 | + - fixed bug on arrayunique, php array_unique only make values unique, but the array index was not updated. (arraydefine is also affected) |
| 98 | + * Jan 28, 2009 version 1.0.2 |
| 99 | + - changed arraypop (add one parameter to support multiple pop) |
| 100 | + - added arrayindex (return an array element at index) |
| 101 | + * Jan 27, 2009 version 1.0.1 |
| 102 | + - changed arraydefine (allow defining empty array) |
| 103 | + |
| 104 | + |
| 105 | + |
| 106 | + ------------------------------------------- |
| 107 | + the following fuctions are obsoleted |
| 108 | + #arraypush (replaced by arraymerge) |
| 109 | + #arraypop (replaced by arrayslice) |
| 110 | + #arraymember (replaced by arraysearch) |
| 111 | + ------------------------------------------- |
| 112 | + |
| 113 | + |
| 114 | +The MIT License |
| 115 | + |
| 116 | + Copyright (c) 2008 |
| 117 | + |
| 118 | + |
| 119 | + Permission is hereby granted, free of charge, to any person |
| 120 | + obtaining a copy of this software and associated documentation |
| 121 | + files (the "Software"), to deal in the Software without |
| 122 | + restriction, including without limitation the rights to use, |
| 123 | + copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 124 | + copies of the Software, and to permit persons to whom the |
| 125 | + Software is furnished to do so, subject to the following |
| 126 | + conditions: |
| 127 | + |
| 128 | + |
| 129 | + The above copyright notice and this permission notice shall be |
| 130 | + included in all copies or substantial portions of the Software. |
| 131 | + |
| 132 | + |
| 133 | + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 134 | + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
| 135 | + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 136 | + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
| 137 | + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| 138 | + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| 139 | + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| 140 | + OTHER DEALINGS IN THE SOFTWARE. |
| 141 | + |
| 142 | +*/ |
| 143 | + |
| 144 | +if ( ! defined( 'MEDIAWIKI' ) ) { |
| 145 | + die( 'This file is a MediaWiki extension, it is not a valid entry point' ); |
| 146 | +} |
| 147 | + |
| 148 | +$wgExtensionFunctions[] = 'efSetupArrayExtension'; |
| 149 | + |
| 150 | +$wgExtensionCredits['parserhook'][] = array( |
| 151 | + 'name' => 'ArrayExtension', |
| 152 | + 'url' => 'http://www.mediawiki.org/wiki/Extension:ArrayExtension', |
| 153 | + 'author' => array ('Li Ding', 'Jie Bao', 'Daniel Werner'), |
| 154 | + 'description' => 'Store and compute named arrays', |
| 155 | + 'version' => ArrayExtension::VERSION, |
| 156 | + |
| 157 | +); |
| 158 | + |
| 159 | +$wgHooks['LanguageGetMagic'][] = 'efArrayExtensionLanguageGetMagic'; |
| 160 | + |
| 161 | + |
| 162 | +/** |
| 163 | + * named arrays - an array has a list of values, and could be set to a SET |
| 164 | + */ |
| 165 | +class ArrayExtension { |
| 166 | + |
| 167 | + const VERSION = '1.3.2'; |
| 168 | + |
| 169 | + var $mArrayExtension = array(); |
| 170 | + |
| 171 | + function ArrayExtension() { |
| 172 | + global $wgHooks; |
| 173 | + $wgHooks['ParserClearState'][] = &$this; |
| 174 | + } |
| 175 | + |
| 176 | + function onParserClearState( &$parser ) { |
| 177 | + $this->mArrayExtension = array(); //remove all arrays to avoid conflicts with job queue or Special:Import or SMW semantic updates |
| 178 | + return true; |
| 179 | + } |
| 180 | + |
| 181 | + /////////////////////////////////////////////////////////// |
| 182 | + // PART 1. constructor |
| 183 | + /////////////////////////////////////////////////////////// |
| 184 | + |
| 185 | + /** |
| 186 | + * Define an array by a list of 'values' deliminated by 'delimiter', |
| 187 | + * the delimiter should be perl regular expression pattern |
| 188 | + * usage: |
| 189 | + * {{#arraydefine:arrayid|values|delimiter|options}} |
| 190 | + * |
| 191 | + * http://us2.php.net/manual/en/book.pcre.php |
| 192 | + * see also: http://us2.php.net/manual/en/function.preg-split.php |
| 193 | + */ |
| 194 | + function arraydefine( &$parser, $arrayid, $value='', $delimiter = '/\s*,\s*/', $options = '', $delimiter2= ', ', $search='@@@@', $subject='@@@@', $frame=null) { |
| 195 | + if (!isset($arrayid)) |
| 196 | + return ''; |
| 197 | + |
| 198 | + //normalize |
| 199 | + $value = trim($value); |
| 200 | + $delimiter = trim($delimiter); |
| 201 | + |
| 202 | + if (!$this->is_non_empty ($value) ){ |
| 203 | + $this->mArrayExtension[$arrayid] = array(); |
| 204 | + }else if (!$this->is_non_empty($delimiter)){ |
| 205 | + $this->mArrayExtension[$arrayid] = array( $value ); |
| 206 | + }else{ |
| 207 | + if ( !$this->isValidRegEx( $delimiter ) ) |
| 208 | + $delimiter = '/\s*' . preg_quote( $delimiter, '/' ) . '\s*/'; //Anpassung von Daniel Werner (preg_quote) |
| 209 | + |
| 210 | + $this->mArrayExtension[$arrayid] = preg_split($delimiter, $value); |
| 211 | + |
| 212 | + // validate if the array has been successfully created |
| 213 | + $ret = $this->validate_array_by_arrayid($arrayid); |
| 214 | + if ($ret !== true){ |
| 215 | + return ''; |
| 216 | + } |
| 217 | + |
| 218 | + // now parse the options, and do posterior process on the created array |
| 219 | + $ary_option = $this->parse_options($options); |
| 220 | + |
| 221 | + // make it unique if option is set |
| 222 | + if (FALSE !== array_key_exists('unique', $ary_option)){ |
| 223 | + $this->arrayunique($parser, $arrayid); |
| 224 | + } |
| 225 | + |
| 226 | + // sort array if the option is set |
| 227 | + $this->arraysort($parser, $arrayid, $this->get_array_value($ary_option,"sort")); |
| 228 | + |
| 229 | + // print the array upon request |
| 230 | + if (strcmp("list", $this->get_array_value($ary_option,"print"))===0){ |
| 231 | + return $this->arrayprint($parser, $arrayid); |
| 232 | + }else if (strcmp("full", $this->get_array_value($ary_option,"print"))===0){ |
| 233 | + return $this->arrayprint($parser, $arrayid, $delimiter2, $search, $subject, $frame); |
| 234 | + } |
| 235 | + } |
| 236 | + |
| 237 | + return ''; |
| 238 | + } |
| 239 | + |
| 240 | + |
| 241 | + /////////////////////////////////////////////////////////// |
| 242 | + // PART 2. print |
| 243 | + /////////////////////////////////////////////////////////// |
| 244 | + |
| 245 | + |
| 246 | + /** |
| 247 | + * print an array. |
| 248 | + * foreach element of the array, print 'subject' where all occurrences of 'search' is replaced with the element, |
| 249 | + * and each element print-out is deliminated by 'delimiter' |
| 250 | + * The subject can embed parser functions; wiki links; and templates. |
| 251 | + * usage: |
| 252 | + * {{#arrayprint:arrayid|delimiter|search|subject}} |
| 253 | + * examples: |
| 254 | + * {{#arrayprint:b}} -- simple |
| 255 | + * {{#arrayprint:b|<br/>}} -- add change line |
| 256 | + * {{#arrayprint:b|<br/>|@@@|[[@@@]]}} -- embed wiki links |
| 257 | + * {{#arrayprint:b|<br/>|@@@|{{#set:prop=@@@}} }} -- embed parser function |
| 258 | + * {{#arrayprint:b|<br/>|@@@|{{f.tag{{f.print.vbar}}prop{{f.print.vbar}}@@@}} }} -- embed template function |
| 259 | + * {{#arrayprint:b|<br/>|@@@|[[name::@@@]]}} -- make SMW links |
| 260 | + */ |
| 261 | + function arrayprint( &$parser, $arrayid , $delimiter = ', ', $search='@@@@', $subject='@@@@', $frame=null) { |
| 262 | + $ret = $this->validate_array_by_arrayid($arrayid); |
| 263 | + if ($ret !== true){ |
| 264 | + return $ret; |
| 265 | + } |
| 266 | + |
| 267 | + $values=$this->mArrayExtension[$arrayid]; |
| 268 | + $rendered_values= array(); |
| 269 | + foreach($values as $v){ |
| 270 | + $temp_result_value = str_replace($search, $v, $subject); |
| 271 | + if (isset($frame)){ |
| 272 | + $temp_result_value = $parser->preprocessToDom($temp_result_value, $frame->isTemplate() ? Parser::PTD_FOR_INCLUSION : 0); |
| 273 | + $temp_result_value = trim($frame->expand($temp_result_value)); |
| 274 | + } |
| 275 | + $rendered_values[] = $temp_result_value ; |
| 276 | + } |
| 277 | + return array(implode( $delimiter, $rendered_values) , 'noparse' => false, 'isHTML' => false); |
| 278 | + } |
| 279 | + |
| 280 | + function arrayprintObj( &$parser, $frame, $args ) { |
| 281 | + // Set variables |
| 282 | + $arrayid = isset($args[0]) ? trim($frame->expand($args[0])) : ''; |
| 283 | + $delimiter = isset($args[1]) ? trim($frame->expand($args[1])) : ', '; |
| 284 | + $search = isset($args[2]) ? trim($frame->expand($args[2], PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES)) : '@@@@'; |
| 285 | + $subject = isset($args[3]) ? trim($frame->expand($args[3], PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES)) : '@@@@'; |
| 286 | + |
| 287 | + return $this->arrayprint($parser, $arrayid, $delimiter, $search, $subject, $frame); |
| 288 | + } |
| 289 | + |
| 290 | + |
| 291 | + /** |
| 292 | + * 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. |
| 293 | + * usage: |
| 294 | + * {{#arrayindex:arrayid|index}} |
| 295 | + */ |
| 296 | + function arrayindex( &$parser, $arrayid , $index , $options='') { |
| 297 | + // now parse the options, and do posterior process on the created array |
| 298 | + $ary_option = $this->parse_options($options); |
| 299 | + |
| 300 | + $ret = $this->validate_array_by_arrayid($arrayid); |
| 301 | + if ($ret !== true){ |
| 302 | + return $this->get_array_value($ary_option,"default"); |
| 303 | + } |
| 304 | + |
| 305 | + $ret = $this->validate_array_index($index, $this->mArrayExtension[$arrayid]); |
| 306 | + if ($ret !== true){ |
| 307 | + return $this->get_array_value($ary_option,"default"); |
| 308 | + } |
| 309 | + |
| 310 | + return $this->mArrayExtension[$arrayid][$index]; |
| 311 | + } |
| 312 | + |
| 313 | + /** |
| 314 | + * return size of array. |
| 315 | + * Print the size (number of elements) in the specified array |
| 316 | + * usage: |
| 317 | + * {{#arraysize:arrayid}} |
| 318 | + * |
| 319 | + * See: http://www.php.net/manual/en/function.count.php |
| 320 | + */ |
| 321 | + function arraysize( &$parser, $arrayid) { |
| 322 | + $ret = $this->validate_array_by_arrayid($arrayid); |
| 323 | + if ($ret !== true){ |
| 324 | + return ''; |
| 325 | + } |
| 326 | + |
| 327 | + return count ($this->mArrayExtension[$arrayid]); |
| 328 | + } |
| 329 | + |
| 330 | + |
| 331 | + |
| 332 | + |
| 333 | + |
| 334 | + /** |
| 335 | + * locate the index of the first occurence of an element starting from the 'index' |
| 336 | + * - print "-1" (not found) or index (found) to show the index of the first occurence of 'value' in the array identified by arrayid |
| 337 | + * - if 'yes' and 'no' are set, print value of them when found or not-found |
| 338 | + * - index is 0-based , it must be non-negative and less than lenth |
| 339 | + * usage: |
| 340 | + * {{#arraysearch:arrayid|value|index|yes|no}} |
| 341 | + * |
| 342 | + * See: http://www.php.net/manual/en/function.array-search.php |
| 343 | + * note it is extended to support regular expression match and index |
| 344 | + */ |
| 345 | + function arraysearch( &$parser, $arrayid, $needle = '/^\s*$/', $index = 0, $yes = null, $no = '-1') { |
| 346 | + $ret = $this->validate_array_by_arrayid($arrayid); |
| 347 | + if ($ret !== true) |
| 348 | + return $no; |
| 349 | + |
| 350 | + $ret = $this->validate_array_index($index, $this->mArrayExtension[$arrayid]); |
| 351 | + if ( !$ret ) |
| 352 | + return $no; |
| 353 | + |
| 354 | + if ( !$this->isValidRegEx( $needle ) ) |
| 355 | + $needle = '/^\s*' . preg_quote( $needle, '/' ) . '\s*$/'; |
| 356 | + |
| 357 | + //search for a match inside the array: |
| 358 | + for ($i=$index; $i < count($this->mArrayExtension[$arrayid]); $i++){ |
| 359 | + $value = $this->mArrayExtension[$arrayid][$i]; |
| 360 | + |
| 361 | + if (preg_match($needle, $value)){ |
| 362 | + if (isset($yes)) |
| 363 | + return $yes; |
| 364 | + else |
| 365 | + return $i; |
| 366 | + } |
| 367 | + } |
| 368 | + |
| 369 | + //no match: |
| 370 | + return $no; |
| 371 | + } |
| 372 | + |
| 373 | + /** |
| 374 | + * search an array and create a new array with all the results. Transforming the new entries before storing them is possible too. |
| 375 | + * usage: |
| 376 | + * {{#arraysearcharray:arrayid_new|arrayid|needle|index|limit|transform}} |
| 377 | + * |
| 378 | + * "needle" can be a regular expression or a string search value. If "needle" is a regular expression, "transform" kan contain |
| 379 | + * "$n" where "n" stands for a number to access a variable from the regex result. |
| 380 | + */ |
| 381 | + function arraysearcharray( &$parser, $arrayid_new, $arrayid, $needle = '/^(\s*)$/', $index = 0, $limit = -1, $transform = '' ) { |
| 382 | + $ret = $this->validate_array_by_arrayid($arrayid); |
| 383 | + if( !$ret ) |
| 384 | + return ''; |
| 385 | + |
| 386 | + if( !isset($arrayid_new) ) |
| 387 | + return ''; |
| 388 | + |
| 389 | + if( !is_numeric($index) ) |
| 390 | + $index = 0; |
| 391 | + |
| 392 | + if( !is_numeric($limit) ) |
| 393 | + $limit = -1; |
| 394 | + |
| 395 | + //calculate start index for negative start indexes: |
| 396 | + if( $index < 0 ) { |
| 397 | + $index = count( $this->mArrayExtension[$arrayid] ) + $index; |
| 398 | + if( $index < 0 ) $index = 0; |
| 399 | + } |
| 400 | + |
| 401 | + $newArr = array(); |
| 402 | + $newArrSize = 0; |
| 403 | + |
| 404 | + if ( !$this->isValidRegEx( $needle ) ) |
| 405 | + $needle = '/^\s*(' . preg_quote( $needle, '/' ) . ')\s*$/'; |
| 406 | + |
| 407 | + //search the array for all matches and put them in the new array |
| 408 | + for ($i = $index; $i < count($this->mArrayExtension[$arrayid]); $i++) |
| 409 | + { |
| 410 | + $value = $this->mArrayExtension[$arrayid][$i]; |
| 411 | + |
| 412 | + if( preg_match($needle, $value) ) { |
| 413 | + if( $transform != '' ) { |
| 414 | + $value = preg_replace( $needle, $transform, $value ); |
| 415 | + } |
| 416 | + $newArr[] = $value; |
| 417 | + $newArrSize++; |
| 418 | + //stop if limit is reached |
| 419 | + if( $newArrSize == $limit ) |
| 420 | + break; |
| 421 | + } |
| 422 | + } |
| 423 | + |
| 424 | + $this->mArrayExtension[$arrayid_new] = $newArr; |
| 425 | + return ''; |
| 426 | + } |
| 427 | + |
| 428 | + |
| 429 | + |
| 430 | + /////////////////////////////////////////////////////////// |
| 431 | + // PART 3. alter an array |
| 432 | + /////////////////////////////////////////////////////////// |
| 433 | + |
| 434 | + /** |
| 435 | + * reset some or all defined arrayes |
| 436 | + * usage: |
| 437 | + * {{#arrayreset:}} |
| 438 | + * {{#arrayreset:arrayid1,arrayid2,...arrayidn}} |
| 439 | + */ |
| 440 | + function arrayreset( &$parser, $arrayids) { |
| 441 | + if (!$this->is_non_empty($arrayids)){ |
| 442 | + //reset all |
| 443 | + $this->mArrayExtension = array(); |
| 444 | + }else{ |
| 445 | + $arykeys = explode(',', $arrayids); |
| 446 | + foreach ($arykeys as $arrayid){ |
| 447 | + $this->removeArray( $arrayids ); |
| 448 | + } |
| 449 | + } |
| 450 | + return ''; |
| 451 | + } |
| 452 | + |
| 453 | + |
| 454 | + /** |
| 455 | + * convert an array to set |
| 456 | + * convert the array identified by arrayid into a set (all elements are unique) |
| 457 | + * usage: |
| 458 | + * {{#arrayunique:arrayid}} |
| 459 | + * |
| 460 | + * see: http://www.php.net/manual/en/function.array-unique.php |
| 461 | + */ |
| 462 | + function arrayunique( &$parser, $arrayid ) { |
| 463 | + $ret = $this->validate_array_by_arrayid($arrayid); |
| 464 | + if ($ret !== true){ |
| 465 | + return ''; |
| 466 | + } |
| 467 | + |
| 468 | + $this->mArrayExtension[$arrayid]= array_unique ($this->mArrayExtension[$arrayid]); |
| 469 | + $values= array(); |
| 470 | + foreach ($this->mArrayExtension[$arrayid] as $v){ |
| 471 | + //if (!isset($v)) |
| 472 | + if (strlen($v)>0) |
| 473 | + $values[]=$v; |
| 474 | + } |
| 475 | + $this->mArrayExtension[$arrayid] = $values; |
| 476 | + } |
| 477 | + |
| 478 | + |
| 479 | + /** |
| 480 | + * sort specified array in the following order: |
| 481 | + * - none: No sort (default) |
| 482 | + * - desc: In descending order, large to small |
| 483 | + * - asce: In ascending order, small to large |
| 484 | + * - random: Shuffle the arrry in random order |
| 485 | + * - reverse: Return an array with elements in reverse order |
| 486 | + * usage: |
| 487 | + * {{#arraysort:arrayid|order}} |
| 488 | + * |
| 489 | + * see: http://www.php.net/manual/en/function.sort.php |
| 490 | + * http://www.php.net/manual/en/function.rsort.php |
| 491 | + * http://www.php.net/manual/en/function.shuffle.php |
| 492 | + * http://us3.php.net/manual/en/function.array-reverse.php |
| 493 | + */ |
| 494 | + function arraysort( &$parser, $arrayid , $sort = 'none') { |
| 495 | + $ret = $this->validate_array_by_arrayid($arrayid); |
| 496 | + if ($ret !== true){ |
| 497 | + return ''; |
| 498 | + } |
| 499 | + |
| 500 | + |
| 501 | + switch ($sort){ |
| 502 | + case 'asc': |
| 503 | + case 'asce': |
| 504 | + case 'ascending': sort($this->mArrayExtension[$arrayid]); break; |
| 505 | + |
| 506 | + |
| 507 | + case 'desc': |
| 508 | + case 'descending': rsort($this->mArrayExtension[$arrayid]); break; |
| 509 | + |
| 510 | + case 'random': shuffle($this->mArrayExtension[$arrayid]); break; |
| 511 | + |
| 512 | + |
| 513 | + case 'reverse': $this->mArrayExtension[$arrayid]= array_reverse($this->mArrayExtension[$arrayid]); break; |
| 514 | + }; |
| 515 | + } |
| 516 | + |
| 517 | + |
| 518 | + /////////////////////////////////////////////////////////// |
| 519 | + // PART 4. create an array |
| 520 | + /////////////////////////////////////////////////////////// |
| 521 | + |
| 522 | + /** |
| 523 | + * merge two arrays, keep duplicated values |
| 524 | + * usage: |
| 525 | + * {{#arraymerge:arrayid_new|arrayid1|arrayid2}} |
| 526 | + * |
| 527 | + * merge values two arrayes identified by arrayid1 and arrayid2 into a new array identified by arrayid_new. |
| 528 | + * this merge differs from array_merge of php because it merges values. |
| 529 | + */ |
| 530 | + function arraymerge( &$parser, $arrayid_new, $arrayid1, $arrayid2='' ) { |
| 531 | + if (!isset($arrayid_new) ) |
| 532 | + return ''; |
| 533 | + |
| 534 | + $ret = $this->validate_array_by_arrayid($arrayid1); |
| 535 | + if ($ret !== true){ |
| 536 | + return ''; |
| 537 | + } |
| 538 | + |
| 539 | + $temp_array = array(); |
| 540 | + foreach ($this->mArrayExtension[$arrayid1] as $entry){ |
| 541 | + array_push ($temp_array, $entry); |
| 542 | + } |
| 543 | + |
| 544 | + if ( isset($arrayid2) && strlen($arrayid2)>0){ |
| 545 | + $ret = $this->validate_array_by_arrayid($arrayid2); |
| 546 | + if ( $ret === true ){ |
| 547 | + foreach ($this->mArrayExtension[$arrayid2] as $entry){ |
| 548 | + array_push ($temp_array, $entry); |
| 549 | + } |
| 550 | + } |
| 551 | + } |
| 552 | + |
| 553 | + $this->mArrayExtension[$arrayid_new] = $temp_array; |
| 554 | + return ''; |
| 555 | + } |
| 556 | + |
| 557 | + /** |
| 558 | + * extract a slice from an array |
| 559 | + * usage: |
| 560 | + * {{#arrayslice:arrayid_new|arrayid|offset|length}} |
| 561 | + * |
| 562 | + * extract a slice from an array |
| 563 | + * see: http://www.php.net/manual/en/function.array-slice.php |
| 564 | + */ |
| 565 | + function arrayslice( &$parser, $arrayid_new , $arrayid , $offset, $length='') { |
| 566 | + if (!isset($arrayid_new) ) |
| 567 | + return ''; |
| 568 | + |
| 569 | + $ret = $this->validate_array_by_arrayid($arrayid); |
| 570 | + if ($ret !== true){ |
| 571 | + return ''; |
| 572 | + } |
| 573 | + |
| 574 | + //$ret = $this->validate_array_offset($offset, $this->mArrayExtension[$arrayid]); |
| 575 | + //if ($ret !== true){ |
| 576 | + // return ''; |
| 577 | + //} |
| 578 | + |
| 579 | + $temp_array = array(); |
| 580 | + if (is_numeric($offset)){ |
| 581 | + if ($this->is_non_empty($length) && is_numeric($length)){ |
| 582 | + $temp = array_slice($this->mArrayExtension[$arrayid], $offset, $length); |
| 583 | + }else{ |
| 584 | + $temp = array_slice($this->mArrayExtension[$arrayid], $offset); |
| 585 | + } |
| 586 | + |
| 587 | + if (!empty($temp) && is_array($temp)) |
| 588 | + $temp_array = array_values($temp); |
| 589 | + } |
| 590 | + $this->mArrayExtension[$arrayid_new] = $temp_array; |
| 591 | + return ''; |
| 592 | + } |
| 593 | + |
| 594 | + /** |
| 595 | + * set operation, {red, white} = {red, white} union {red} |
| 596 | + * usage: |
| 597 | + * {{#arrayunion:arrayid_new|arrayid1|arrayid2}} |
| 598 | + |
| 599 | + * similar to arraymerge, this union works on values. |
| 600 | + */ |
| 601 | + function arrayunion( &$parser, $arrayid_new , $arrayid1 , $arrayid2 ) { |
| 602 | + if (!isset($arrayid_new) ) |
| 603 | + return ''; |
| 604 | + |
| 605 | + |
| 606 | + $ret = $this->validate_array_by_arrayid($arrayid1); |
| 607 | + if ($ret !== true){ |
| 608 | + return ''; |
| 609 | + } |
| 610 | + |
| 611 | + $ret = $this->validate_array_by_arrayid($arrayid2); |
| 612 | + if ($ret !== true){ |
| 613 | + return ''; |
| 614 | + } |
| 615 | + |
| 616 | + $this->arraymerge($parser, $arrayid_new, $arrayid1, $arrayid2); |
| 617 | + $this->mArrayExtension[$arrayid_new] = array_unique ($this->mArrayExtension[$arrayid_new]); |
| 618 | + |
| 619 | + return ''; |
| 620 | + } |
| 621 | + |
| 622 | + ////////////////////////////////////////////////// |
| 623 | + // SET OPERATIONS: a set does not have duplicated element |
| 624 | + |
| 625 | + /** |
| 626 | + * set operation, {red} = {red, white} intersect {red,black} |
| 627 | + * usage: |
| 628 | + * {{#arrayintersect:arrayid_new|arrayid1|arrayid2}} |
| 629 | + * See: http://www.php.net/manual/en/function.array-intersect.php |
| 630 | + */ |
| 631 | + function arrayintersect( &$parser, $arrayid_new , $arrayid1 , $arrayid2 ) { |
| 632 | + if (!isset($arrayid_new) ) |
| 633 | + return ''; |
| 634 | + |
| 635 | + $ret = $this->validate_array_by_arrayid($arrayid1); |
| 636 | + if ($ret !== true){ |
| 637 | + return ''; |
| 638 | + } |
| 639 | + |
| 640 | + $ret = $this->validate_array_by_arrayid($arrayid2); |
| 641 | + if ($ret !== true){ |
| 642 | + return ''; |
| 643 | + } |
| 644 | + |
| 645 | + //keys will be preserved... |
| 646 | + $newArray = array_intersect( array_unique($this->mArrayExtension[$arrayid1]), array_unique($this->mArrayExtension[$arrayid2]) ); |
| 647 | + |
| 648 | + //...so we have to reorganize the key order |
| 649 | + $this->mArrayExtension[$arrayid_new] = $this->reorganizeArrayKeys($newArray); |
| 650 | + |
| 651 | + return ''; |
| 652 | + } |
| 653 | + |
| 654 | + /** |
| 655 | + * |
| 656 | + * usage: |
| 657 | + * {{#arraydiff:arrayid_new|arrayid1|arrayid2}} |
| 658 | + |
| 659 | + * set operation, {white} = {red, white} - {red} |
| 660 | + * see: http://www.php.net/manual/en/function.array-diff.php |
| 661 | + */ |
| 662 | + function arraydiff( &$parser, $arrayid_new , $arrayid1 , $arrayid2 ) { |
| 663 | + if (!isset($arrayid_new) ) |
| 664 | + return ''; |
| 665 | + |
| 666 | + $ret = $this->validate_array_by_arrayid($arrayid1); |
| 667 | + if ($ret !== true){ |
| 668 | + return ''; |
| 669 | + } |
| 670 | + |
| 671 | + $ret = $this->validate_array_by_arrayid($arrayid2); |
| 672 | + if ($ret !== true){ |
| 673 | + return ''; |
| 674 | + } |
| 675 | + |
| 676 | + //keys will be preserved... |
| 677 | + $newArray = array_diff( array_unique($this->mArrayExtension[$arrayid1]),array_unique($this->mArrayExtension[$arrayid2])); |
| 678 | + |
| 679 | + //...so we have to reorganize the key order |
| 680 | + $this->mArrayExtension[$arrayid_new] = $this->reorganizeArrayKeys($newArray); |
| 681 | + |
| 682 | + return ''; |
| 683 | + } |
| 684 | + |
| 685 | + |
| 686 | + |
| 687 | + ////////////////////////////////////////////////// |
| 688 | + // private functions |
| 689 | + ////////////////////////////////////////////////// |
| 690 | + |
| 691 | + function is_non_empty($var){ |
| 692 | + return isset($var) && strlen($var)>0; |
| 693 | + } |
| 694 | + |
| 695 | + // private functions for validating the index of an array |
| 696 | + function validate_array_index($index, $array){ |
| 697 | + if (!isset($index)) |
| 698 | + return false; |
| 699 | + |
| 700 | + if (!is_numeric($index)) |
| 701 | + return false; |
| 702 | + |
| 703 | + if (!isset($array) || !is_array($array)) |
| 704 | + return false; |
| 705 | + |
| 706 | + if (!array_key_exists($index, $array)) /*($index<0 || $index>=count($array))*/ |
| 707 | + return false; |
| 708 | + |
| 709 | + return true; |
| 710 | + } |
| 711 | + |
| 712 | + // private functions for validating the index of an array |
| 713 | + function validate_array_offset($offset, $array){ |
| 714 | + if (!isset($offset)) |
| 715 | + return false; |
| 716 | + |
| 717 | + |
| 718 | + if (!is_numeric($offset)) |
| 719 | + return false; |
| 720 | + |
| 721 | + |
| 722 | + if (!isset($array) || !is_array($array)) |
| 723 | + return false; |
| 724 | + |
| 725 | + if ( $offset>=count($array)) |
| 726 | + return false; |
| 727 | + |
| 728 | + return true; |
| 729 | + } |
| 730 | + |
| 731 | + //private function for validating array by name |
| 732 | + function validate_array_by_arrayid($array_name){ |
| 733 | + if (!isset($array_name)) |
| 734 | + return ''; |
| 735 | + |
| 736 | + if (!isset($this->mArrayExtension)) |
| 737 | + return "undefined array: $array_name"; |
| 738 | + |
| 739 | + if (!array_key_exists($array_name,$this->mArrayExtension) || !is_array($this->mArrayExtension[$array_name])) |
| 740 | + return "undefined array: $array_name"; |
| 741 | + |
| 742 | + return true; |
| 743 | + } |
| 744 | + |
| 745 | + function get_array_value($array, $field){ |
| 746 | + if (is_array($array) && FALSE !== array_key_exists($field, $array)) |
| 747 | + return $array[$field]; |
| 748 | + else |
| 749 | + return ''; |
| 750 | + } |
| 751 | + |
| 752 | + function parse_options($options){ |
| 753 | + if (isset($options)){ |
| 754 | + // now parse the options, and do posterior process on the created array |
| 755 | + $ary_option = preg_split ('/\s*[,]\s*/', strtolower($options)); |
| 756 | + } |
| 757 | + |
| 758 | + $ret = array(); |
| 759 | + if (isset($ary_option) && is_array($ary_option) && sizeof($ary_option)>0){ |
| 760 | + foreach ($ary_option as $option){ |
| 761 | + $ary_pair = explode('=', $option,2); |
| 762 | + if (sizeof($ary_pair)==1){ |
| 763 | + $ret[$ary_pair[0]] = true; |
| 764 | + }else{ |
| 765 | + $ret[$ary_pair[0]] = $ary_pair[1]; |
| 766 | + } |
| 767 | + } |
| 768 | + } |
| 769 | + return $ret; |
| 770 | + } |
| 771 | + |
| 772 | + /* ============================ */ |
| 773 | + /* ============================ */ |
| 774 | + /* === === */ |
| 775 | + /* === HELPER FUNCTIONS === */ |
| 776 | + /* === === */ |
| 777 | + /* ============================ */ |
| 778 | + /* ============================ */ |
| 779 | + |
| 780 | + function getArrayValue( $arrayId='', $key='' ) { |
| 781 | + $arrayId = trim( $arrayId ); |
| 782 | + if( $this->arrayExists( $arrayId ) && array_key_exists( $key, $this->mArrayExtension[ $arrayId ] ) ) |
| 783 | + return $this->mArrayExtension[ $arrayId ][ $key ]; |
| 784 | + else |
| 785 | + return ''; |
| 786 | + } |
| 787 | + |
| 788 | + //return an array identified by $arrayId. If it doesn't exist this will return null. |
| 789 | + function getArray( $arrayId='' ) { |
| 790 | + if( $this->arrayExists( $arrayId ) ) |
| 791 | + return $this->mArrayExtension[ $arrayId ]; |
| 792 | + else |
| 793 | + return null; |
| 794 | + } |
| 795 | + |
| 796 | + function arrayExists( $arrayId='' ) { |
| 797 | + if( array_key_exists( trim( $arrayId ), $this->mArrayExtension ) ) |
| 798 | + |
| 799 | + |
| 800 | + |
| 801 | + return true; |
| 802 | + else |
| 803 | + return false; |
| 804 | + } |
| 805 | + |
| 806 | + //add a new array or overwrite existing one. Values delivered as real array. |
| 807 | + function createArray( $arrayId='', $arr=array() ) { |
| 808 | + $arr = $this->reorganizeArrayKeys( $arr ); |
| 809 | + $this->mArrayExtension[ trim( $arrayId ) ] = $arr; |
| 810 | + } |
| 811 | + |
| 812 | + |
| 813 | + //remove an existing array. If array doesn't exist this will return false, otherwise true. |
| 814 | + function removeArray( $arrayId='' ) { |
| 815 | + $arrayId = trim( $arrayId ); |
| 816 | + if( $this->arrayExists( $arrayId ) ) { |
| 817 | + unset( $this->mArrayExtension[ $arrayId ] ); |
| 818 | + return true; |
| 819 | + } else { |
| 820 | + return false; |
| 821 | + } |
| 822 | + |
| 823 | + |
| 824 | + } |
| 825 | + |
| 826 | + //Rebuild the array and reorganize all keys. This means all gaps between array items will be closed. |
| 827 | + function reorganizeArrayKeys( $arr = array() ) { |
| 828 | + $newArray = array(); |
| 829 | + foreach ($arr as $val){ |
| 830 | + $newArray[] = trim( $val ); |
| 831 | + } |
| 832 | + return $newArray; |
| 833 | + } |
| 834 | + |
| 835 | + //Decide for the given $pattern if its a valid regular expression or not |
| 836 | + function isValidRegEx( $pattern ) { |
| 837 | + return preg_match( '/^([\\/\\|%]).*\\1[imsSuUx]*$/', $pattern ); |
| 838 | + } |
| 839 | +} |
| 840 | + |
| 841 | +function efSetupArrayExtension() { |
| 842 | + global $wgParser, $wgArrayExtension; |
| 843 | + |
| 844 | + $wgArrayExtension = new ArrayExtension; |
| 845 | + $wgParser->setFunctionHook( 'arraydefine', array( &$wgArrayExtension, 'arraydefine' ) ); |
| 846 | + |
| 847 | + if( defined( get_class( $wgParser) . '::SFH_OBJECT_ARGS' ) ) { |
| 848 | + $wgParser->setFunctionHook('arrayprint', array( &$wgArrayExtension, 'arrayprintObj' ), SFH_OBJECT_ARGS); |
| 849 | + } else { |
| 850 | + $wgParser->setFunctionHook( 'arrayprint', array( &$wgArrayExtension, 'arrayprint' ) ); |
| 851 | + } |
| 852 | + |
| 853 | + $wgParser->setFunctionHook( 'arraysize', array( &$wgArrayExtension, 'arraysize' ) ); |
| 854 | + $wgParser->setFunctionHook( 'arrayindex', array( &$wgArrayExtension, 'arrayindex' ) ); |
| 855 | + $wgParser->setFunctionHook( 'arraysearch', array( &$wgArrayExtension, 'arraysearch' ) ); |
| 856 | + |
| 857 | + $wgParser->setFunctionHook( 'arraysort', array( &$wgArrayExtension, 'arraysort' ) ); |
| 858 | + $wgParser->setFunctionHook( 'arrayunique', array( &$wgArrayExtension, 'arrayunique' ) ); |
| 859 | + $wgParser->setFunctionHook( 'arrayreset', array( &$wgArrayExtension, 'arrayreset' ) ); |
| 860 | + |
| 861 | + $wgParser->setFunctionHook( 'arraymerge', array( &$wgArrayExtension, 'arraymerge' ) ); |
| 862 | + $wgParser->setFunctionHook( 'arrayslice', array( &$wgArrayExtension, 'arrayslice' ) ); |
| 863 | + |
| 864 | + $wgParser->setFunctionHook( 'arrayunion', array( &$wgArrayExtension, 'arrayunion' ) ); |
| 865 | + $wgParser->setFunctionHook( 'arrayintersect', array( &$wgArrayExtension, 'arrayintersect' ) ); |
| 866 | + $wgParser->setFunctionHook( 'arraydiff', array( &$wgArrayExtension, 'arraydiff' ) ); |
| 867 | + $wgParser->setFunctionHook( 'arraysearcharray', array( &$wgArrayExtension, 'arraysearcharray' ) ); |
| 868 | +} |
| 869 | + |
| 870 | +function efArrayExtensionLanguageGetMagic( &$magicWords, $langCode ) { |
| 871 | + require_once( dirname( __FILE__ ) . '/ArrayExtension.i18n.php' ); |
| 872 | + foreach( efArrayExtensionWords( $langCode ) as $word => $trans ) |
| 873 | + $magicWords[$word] = $trans; |
| 874 | + return true; |
| 875 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/ArrayExtension/ArrayExtension.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 876 | + native |