r103897 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r103896‎ | r103897 | r103898 >
Date:14:41, 22 November 2011
Author:danwe
Status:deferred
Tags:
Comment:
'ArrayExtension' renamed to 'Arrays' using svn move.
Modified paths:
  • /trunk/extensions/Arrays (added) (history)
  • /trunk/extensions/Arrays/ArrayExtension.i18n.magic.php (deleted) (history)
  • /trunk/extensions/Arrays/ArrayExtension.i18n.php (deleted) (history)
  • /trunk/extensions/Arrays/ArrayExtension.php (deleted) (history)
  • /trunk/extensions/Arrays/Arrays.i18n.magic.php (added) (history)
  • /trunk/extensions/Arrays/Arrays.i18n.php (added) (history)
  • /trunk/extensions/Arrays/Arrays.php (added) (history)
  • /trunk/extensions/Arrays/COPYING (modified) (history)
  • /trunk/extensions/Arrays/README (modified) (history)
  • /trunk/extensions/Arrays/RELEASE-NOTES (modified) (history)

Diff [purge]

Index: trunk/extensions/Arrays/Arrays.i18n.magic.php
@@ -0,0 +1,33 @@
 2+<?php
 3+
 4+/**
 5+ * Internationalization file for magic words in the 'Arrays' extension.
 6+ *
 7+ * @file Arrays.i18n.magic.php
 8+ * @ingroup Arrays
 9+ *
 10+ * @licence MIT License
 11+ */
 12+
 13+$magicWords = array();
 14+
 15+$magicWords['en'] = array(
 16+ 'arraydefine' => array( 0, 'arraydefine' ),
 17+
 18+ 'arrayprint' => array( 0, 'arrayprint' ),
 19+ 'arraysize' => array( 0, 'arraysize' ),
 20+ 'arrayindex' => array( 0, 'arrayindex' ),
 21+ 'arraysearch' => array( 0, 'arraysearch' ),
 22+
 23+ 'arrayunique' => array( 0, 'arrayunique' ),
 24+ 'arraysort' => array( 0, 'arraysort' ),
 25+ 'arrayreset' => array( 0, 'arrayreset' ),
 26+
 27+ 'arraymerge' => array( 0, 'arraymerge' ),
 28+ 'arrayslice' => array( 0, 'arrayslice' ),
 29+
 30+ 'arrayunion' => array( 0, 'arrayunion' ),
 31+ 'arrayintersect' => array( 0, 'arrayintersect' ),
 32+ 'arraydiff' => array( 0, 'arraydiff' ),
 33+ 'arraysearcharray' => array( 0, 'arraysearcharray' ),
 34+);
Property changes on: trunk/extensions/Arrays/Arrays.i18n.magic.php
___________________________________________________________________
Added: svn:eol-style
135 + native
Index: trunk/extensions/Arrays/Arrays.i18n.php
@@ -0,0 +1,297 @@
 2+<?php
 3+
 4+/**
 5+ * Internationalization file for the 'Arrays' extension.
 6+ *
 7+ * @since 1.3.4
 8+ *
 9+ * @file Arrays.i18n.php
 10+ * @ingroup Arrays
 11+ *
 12+ * @licence MIT License
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+
 16+$messages = array();
 17+
 18+/** English
 19+ * @author Jeroen De Dauw
 20+ */
 21+$messages['en'] = array(
 22+ 'arrayext-desc' => 'Store and compute named arrays',
 23+);
 24+
 25+/** Message documentation (Message documentation)
 26+ * @author Purodha
 27+ */
 28+$messages['qqq'] = array(
 29+ 'arrayext-desc' => '{{desc}}',
 30+);
 31+
 32+/** Arabic (العربية)
 33+ * @author Ciphers
 34+ */
 35+$messages['ar'] = array(
 36+ 'arrayext-desc' => 'تخزين وحساب مصفوفات مسماة',
 37+);
 38+
 39+/** Asturian (Asturianu)
 40+ * @author Xuacu
 41+ */
 42+$messages['ast'] = array(
 43+ 'arrayext-desc' => 'Almacenar y calcular matrices con nome',
 44+);
 45+
 46+/** Bashkir (Башҡортса)
 47+ * @author Assele
 48+ */
 49+$messages['ba'] = array(
 50+ 'arrayext-desc' => 'Исемләнгән массивтарҙы һаҡлау һәм иҫәпләү',
 51+);
 52+
 53+/** Belarusian (Taraškievica orthography) (‪Беларуская (тарашкевіца)‬)
 54+ * @author EugeneZelenko
 55+ */
 56+$messages['be-tarask'] = array(
 57+ 'arrayext-desc' => 'Захаваньне і вылічэньне масіваў з назвамі',
 58+);
 59+
 60+/** Breton (Brezhoneg)
 61+ * @author Fulup
 62+ */
 63+$messages['br'] = array(
 64+ 'arrayext-desc' => 'Enrollañ ha plediñ gant an taolennoù anvet',
 65+);
 66+
 67+/** Bosnian (Bosanski)
 68+ * @author CERminator
 69+ */
 70+$messages['bs'] = array(
 71+ 'arrayext-desc' => 'Sačuvaj i izračunaj imenovane nizove',
 72+);
 73+
 74+/** Welsh (Cymraeg)
 75+ * @author Pwyll
 76+ */
 77+$messages['cy'] = array(
 78+ 'arrayext-desc' => "Storio a chyfrifo trefnau wedi'u henwi",
 79+);
 80+
 81+/** German (Deutsch)
 82+ * @author Kghbln
 83+ */
 84+$messages['de'] = array(
 85+ 'arrayext-desc' => 'Ermöglicht das Speichern und Nutzen definierter Datenreihen (Arrays)',
 86+);
 87+
 88+/** French (Français)
 89+ * @author Wyz
 90+ */
 91+$messages['fr'] = array(
 92+ 'arrayext-desc' => 'Enregistrer et traiter les tableaux nommés',
 93+);
 94+
 95+/** Franco-Provençal (Arpetan)
 96+ * @author ChrisPtDe
 97+ */
 98+$messages['frp'] = array(
 99+ 'arrayext-desc' => 'Encartar et trètar los tablôs apelâs',
 100+);
 101+
 102+/** Galician (Galego)
 103+ * @author Toliño
 104+ */
 105+$messages['gl'] = array(
 106+ 'arrayext-desc' => 'Almacenar e calcular táboas con nomes',
 107+);
 108+
 109+/** Swiss German (Alemannisch)
 110+ * @author Als-Holder
 111+ */
 112+$messages['gsw'] = array(
 113+ 'arrayext-desc' => 'Macht s Spychere un Nutze vu definierte Datezylete megli',
 114+);
 115+
 116+/** Hebrew (עברית)
 117+ * @author Amire80
 118+ */
 119+$messages['he'] = array(
 120+ 'arrayext-desc' => 'אחסון וחישוב של מערכים בעלי שמות',
 121+);
 122+
 123+/** Upper Sorbian (Hornjoserbsce)
 124+ * @author Michawiki
 125+ */
 126+$messages['hsb'] = array(
 127+ 'arrayext-desc' => 'Pomjenowane polowe wariable składować a wobličić',
 128+);
 129+
 130+/** Hungarian (Magyar)
 131+ * @author Dj
 132+ */
 133+$messages['hu'] = array(
 134+ 'arrayext-desc' => 'Nevesített tömbök tárolása és számítása',
 135+);
 136+
 137+/** Interlingua (Interlingua)
 138+ * @author McDutchie
 139+ */
 140+$messages['ia'] = array(
 141+ 'arrayext-desc' => 'Immagazinar e computar arrays nominate',
 142+);
 143+
 144+/** Indonesian (Bahasa Indonesia)
 145+ * @author IvanLanin
 146+ */
 147+$messages['id'] = array(
 148+ 'arrayext-desc' => 'Menyimpan dan menghitung larik bernama',
 149+);
 150+
 151+/** Italian (Italiano)
 152+ * @author Beta16
 153+ */
 154+$messages['it'] = array(
 155+ 'arrayext-desc' => 'Memorizza e calcola matrici di nomi',
 156+);
 157+
 158+/** Colognian (Ripoarisch)
 159+ * @author Purodha
 160+ */
 161+$messages['ksh'] = array(
 162+ 'arrayext-desc' => 'Felder met Name berääschne un faßhallde.',
 163+);
 164+
 165+/** Luxembourgish (Lëtzebuergesch)
 166+ * @author Robby
 167+ */
 168+$messages['lb'] = array(
 169+ 'arrayext-desc' => 'Späicheren a Benotze vun definéierten Tabellen',
 170+);
 171+
 172+/** Lithuanian (Lietuvių)
 173+ * @author Ignas693
 174+ */
 175+$messages['lt'] = array(
 176+ 'arrayext-desc' => 'Saugoti ir apskaičiuoti pavadintas masyvai',
 177+);
 178+
 179+/** Macedonian (Македонски)
 180+ * @author Bjankuloski06
 181+ */
 182+$messages['mk'] = array(
 183+ 'arrayext-desc' => 'Складирај и пресметај именувани низи',
 184+);
 185+
 186+/** Malay (Bahasa Melayu)
 187+ * @author Anakmalaysia
 188+ */
 189+$messages['ms'] = array(
 190+ 'arrayext-desc' => 'Menyimpan dan mengira tatasusunan bernama',
 191+);
 192+
 193+/** Dutch (Nederlands)
 194+ * @author Siebrand
 195+ */
 196+$messages['nl'] = array(
 197+ 'arrayext-desc' => 'Benoemde verzamelingen opslaan en berekenen',
 198+);
 199+
 200+/** Norwegian (bokmål)‬ (‪Norsk (bokmål)‬)
 201+ * @author Nghtwlkr
 202+ */
 203+$messages['no'] = array(
 204+ 'arrayext-desc' => 'Lagre og beregne navngitte tabeller',
 205+);
 206+
 207+/** Polish (Polski)
 208+ * @author Sp5uhe
 209+ */
 210+$messages['pl'] = array(
 211+ 'arrayext-desc' => 'Przechowywanie i przeliczanie nazwanych tabel',
 212+);
 213+
 214+/** Piedmontese (Piemontèis)
 215+ * @author Borichèt
 216+ * @author Dragonòt
 217+ */
 218+$messages['pms'] = array(
 219+ 'arrayext-desc' => 'Memorisé e calcolé le tàule nominà',
 220+);
 221+
 222+/** Portuguese (Português)
 223+ * @author Hamilton Abreu
 224+ */
 225+$messages['pt'] = array(
 226+ 'arrayext-desc' => 'Armazenar e calcular matrizes designadas',
 227+);
 228+
 229+/** Brazilian Portuguese (Português do Brasil)
 230+ * @author Giro720
 231+ */
 232+$messages['pt-br'] = array(
 233+ 'arrayext-desc' => 'Armazenar e calcular matrizes designadas',
 234+);
 235+
 236+/** Tarandíne (Tarandíne)
 237+ * @author Joetaras
 238+ */
 239+$messages['roa-tara'] = array(
 240+ 'arrayext-desc' => 'Stipe e calcole le array nomenate',
 241+);
 242+
 243+/** Russian (Русский)
 244+ * @author Александр Сигачёв
 245+ */
 246+$messages['ru'] = array(
 247+ 'arrayext-desc' => 'Хранение и вычисление именованных массивов',
 248+);
 249+
 250+/** Slovenian (Slovenščina)
 251+ * @author Dbc334
 252+ */
 253+$messages['sl'] = array(
 254+ 'arrayext-desc' => 'Shrani in izračuna imenovana polja',
 255+);
 256+
 257+/** Swedish (Svenska)
 258+ * @author WikiPhoenix
 259+ */
 260+$messages['sv'] = array(
 261+ 'arrayext-desc' => 'Lagra och beräkna namngivna arrayer',
 262+);
 263+
 264+/** Tagalog (Tagalog)
 265+ * @author AnakngAraw
 266+ */
 267+$messages['tl'] = array(
 268+ 'arrayext-desc' => 'Itabi at tuusin ang pinangalanang mga hanay',
 269+);
 270+
 271+/** Turkish (Türkçe)
 272+ * @author Khutuck
 273+ */
 274+$messages['tr'] = array(
 275+ 'arrayext-desc' => 'İsimlendirilmiş dizileri sakla ve hsapla',
 276+);
 277+
 278+/** Ukrainian (Українська)
 279+ * @author Sodmy
 280+ */
 281+$messages['uk'] = array(
 282+ 'arrayext-desc' => 'Зберігання та обчислення іменованих масивів',
 283+);
 284+
 285+/** Veps (Vepsan kel')
 286+ * @author Игорь Бродский
 287+ */
 288+$messages['vep'] = array(
 289+ 'arrayext-desc' => 'Varata da lugeda nimitadud massivad',
 290+);
 291+
 292+/** Simplified Chinese (‪中文(简体)‬)
 293+ * @author Hydra
 294+ */
 295+$messages['zh-hans'] = array(
 296+ 'arrayext-desc' => '存储和计算指定的数组',
 297+);
 298+
Property changes on: trunk/extensions/Arrays/Arrays.i18n.php
___________________________________________________________________
Added: svn:eol-style
1299 + native
Index: trunk/extensions/Arrays/RELEASE-NOTES
@@ -0,0 +1,151 @@
 2+ Changelog:
 3+ ==========
 4+
 5+ * (trunk) -- Version 2.0
 6+ This release is built upon 1.4 alpha. See changes of 1.4 alpha as well.
 7+ 'ArrayExtension' is now simply called 'Arrays'. Therefore you have to adjust your LocalSettings.php.
 8+ - class 'ArrayExtension' renamed to 'ExtArrays'
 9+ - '#arrayindex' will only expand options/default when required.
 10+ - '#arraymerge', '#arrayunion', '#arraydiff' and '#arrayintersect' can handle multiple arrays now.
 11+ - Compatibility mode variable '$egArrayExtensionCompatbilityMode' is set to false by default. See
 12+ Version 1.4 alpha for further information. Further changes to the compatibility mode behavior
 13+ in version 2.0:
 14+ + '#arrayindex' will return its default also in case of existing index but empty value. This
 15+ makes the function consistent with Variables '#var' and hash tables '#hashvalue'.
 16+ + '#arraymerge', '#arrayunion', '#arraydiff' and '#arrayintersect' with only one array for
 17+ the operation will make a copy of that array instead of creating no array at all.
 18+ + See 1.4 alpha for previous changes
 19+
 20+
 21+ * November 20, 2001 -- Version 1.4 alpha (r103716)
 22+ This release introduces some useful bugfixes and optional new behavior for various functionality.
 23+ This version never made it into a final stage because version 2.0 will introduce some rather
 24+ radical changes, so this alpha release allows to profit from bugfixes that might be quite useful
 25+ if you don't want to use Version 2.0 for some reason.
 26+ - Configuration variable '$egArrayExtensionCompatbilityMode' for deactivating the following newly
 27+ introduced breaking changes:
 28+ + '#arrayprint' no longer returns an error text in case the array doesn't exist.
 29+ + '#arrayreset' now uses n parameters instead of ',' as separator for n arrays to reset
 30+ + '#arrayindex' options removed, instead third parameter simply is the default value (without
 31+ any 'default=' in front).
 32+ + '#arraysearch' returns an empty string '' instead of '-1' in case nothing was found.
 33+ + '#arraysearcharray' and '#arrayslice' without all necessary parameters set will always create
 34+ a new empty array.
 35+ Compatibility mode is active by default. In Version 2.0 it will be set to inactive by default.
 36+ - '#arraysearch' will only expand 'yes' or 'no' if given, but never both.
 37+ - negative indexes for '#arrayindex', '#arraysearch' and '#arraysearcharray' are possible now.
 38+ - bugfix in '#arraysearcharray', index and limit working fine now.
 39+ - arrayprint will handle <includeonly>/<noinclude> correct in case it's used in a template.
 40+ - Internationalization for several languages added.
 41+ - moved into mediawiki.org svn repository.
 42+
 43+ @ToDo before release:
 44+ - As in Variables 2.0, one store per Parser should be used.
 45+ - ''#arraysearch'' should not expand both, 'yes' and 'no', just the one actual case.
 46+ - Further breaking changes fixing weird old behavior and functionality
 47+
 48+
 49+ * January 24, 2011 -- Version 1.3.2
 50+ - New public class methods for creating and removing arrays. Good for use by other extensions.
 51+ - VERSION constant added to ArrayExtension class
 52+
 53+ * July 20, 2010 -- Version 1.3.1
 54+ - Removed critical bug. Some kind of "Superglobal" Arrays on page imports and job queue jobs.
 55+ Values were passed from one page to another page.
 56+
 57+ * July 5, 2010 -- Version 1.3
 58+ - update arrayunion and arraydiff, fixed heavy bug (gaps between array indexes doing some serious
 59+ trouble in other arrayfunctions like arraysearch)
 60+ - array function ''#arraysearcharray'' added
 61+ - '#arraysearch' code cleanup, search parameter is optional now, searching for empty elements is
 62+ possible now
 63+ - advanced check for regular expressions in '#arraysearch,' '#arraydefine' and '#arraysearcharray'
 64+ Pivate function isValidRegEx() added
 65+ - '#arraymerge' bug fixed: Php message in case of non existant seccond array
 66+ - now using preg_quote in arraydefine when using a non regular expression delimiter
 67+ - some minor code changes and cleanup
 68+
 69+
 70+ * January 23, 2010 -- Version 1.2.4
 71+ - update arraydefine, add more parameter for combining print with arraydefine
 72+
 73+ * July 16, 2009 -- Version 1.2.3
 74+ - update arrayunique, fixed bug (empty string should be eliminated in array after arrayunique)
 75+
 76+ * July 16, 2009 -- Version 1.2.2
 77+ - update arrayunique, fixed bug (zero mistakenly eliminated in array after arrayunique)
 78+ - rename key=>arrayid, should not affect any existing users
 79+ - rename validate_array_by_name to validate_array_by_arrayid
 80+ - add "asc" as option of arraysort
 81+
 82+ * May 03, 2009 -- Version 1.2.1
 83+ - update arraydefine by adding options: "unique"; sort=( "desc", "asce", "random", "reverse"), and
 84+ print=( "list" ). Options are diliminated by comma, e.g. "unique, sort=desc,print=list".
 85+ - fixed bug in arrayslice (offset can be greater than array size): if offset is no less than array
 86+ size, empty array will be returned, if offset if no greater than negative array size, a new array
 87+ with all elements will be returned
 88+ - update arrayindex by adding print option when (i) the array is not defined; (ii) the index is not
 89+ valid in the specified array: e.g. "default=bad array"
 90+
 91+ * April 24, 2009 -- Version 1.2
 92+ - fixed a bug in arrayslice, (offset=0)
 93+ - clean up code, added two private functions, validate_array_index, validate_array_offset,
 94+ validate_array_by_arrayid; rename some parameters key=> new_key, differentiate offset and index
 95+
 96+ * April 18, 2009 -- Version 1.1.6
 97+ - fixed a bug in arraymerge and arrayslice,
 98+
 99+ * Mar 17, 2009 -- Version 1.1.5
 100+ - update '#arraysort,' add "reverse" option, http://us3.php.net/manual/en/function.array-reverse.php
 101+ - update '#arrayreset,' add option to reset a selection of arrays
 102+
 103+ * Feb 23, 2009 -- Version 1.1.4
 104+ - fixed '#arraysearch,' better recognize perl patterns identified by starting with "/",
 105+ http://www.perl.com/doc/manual/html/pod/perlre.html
 106+
 107+ * Feb 23, 2009 -- Version 1.1.3
 108+ - fixed '#arraysearch,' "Warning: Missing argument 4..."
 109+
 110+ * Feb 9, 2009 -- Version 1.1.2
 111+ - update '#arraysearch,' now support offset and preg regular expression
 112+
 113+ * Feb 8, 2009 -- Version 1.1.1
 114+ - update '#arrayprint,' now wiki links, parser functions and templates properly parsed. This enables
 115+ foreach loop call.
 116+ - update '#arraysearch,' now allows customized output upon found/non-found by specifying additional
 117+ parameters
 118+
 119+ * Feb 5, 2009 -- Version 1.1
 120+ - update '#arraydefine:' replacing 'explode' by 'preg_split',
 121+ and we now allow delimitors to be (i) a string; or (ii) a perl regular expressnion pattern,
 122+ sourrounded by '/', e.g. '/..blah.../'
 123+ - update '#arrayprint,' change parameters from "prefix","suffix" to a "template", and users can
 124+ replace a substring in the template with array value, similar to arraymap in semantic forms
 125+ - update '#arrayunique,' empty elements will be removed
 126+ - update '#arraysort:' adding "random" option to make the array of values in random order
 127+ - add '#arrayreset' to free all defined arrays for memory saving
 128+ - add '#arrayslice' to return an array bounded by start_index and length.
 129+ - add '#arraysearch.' now we can return the index of the first occurence of an element, return -1 if
 130+ not found
 131+ - remove '#arraymember,' obsoleted by '#arraysearch'
 132+ - remove '#arraypush,' obsoleted by '#arraydefine' and '#arraymerge'
 133+ - remove '#arraypop,' obsoleted by '#arrayslice'
 134+ - add safty check code to avoid unset parameters
 135+
 136+ * Feb 1, 2009 -- Version 1.0.3
 137+ - fixed bug on arrayunique, php array_unique only make values unique, but the array index was not
 138+ updated. (arraydefine is also affected)
 139+
 140+ * Jan 28, 2009 -- Version 1.0.2
 141+ - changed arraypop (add one parameter to support multiple pop)
 142+ - added arrayindex (return an array element at index)
 143+
 144+ * Jan 27, 2009 -- Version 1.0.1
 145+ - changed arraydefine (allow defining empty array)
 146+
 147+ -------------------------------------------
 148+ the following fuctions are obsoleted
 149+ '#arraypush' (replaced by arraymerge)
 150+ '#arraypop' (replaced by arrayslice)
 151+ '#arraymember' (replaced by arraysearch)
 152+ -------------------------------------------
\ No newline at end of file
Property changes on: trunk/extensions/Arrays/RELEASE-NOTES
___________________________________________________________________
Added: svn:eol-style
1153 + native
Index: trunk/extensions/Arrays/Arrays.php
@@ -0,0 +1,1138 @@
 2+<?php
 3+
 4+/**
 5+ * Initialization file for the 'Arrays' (former 'ArrayExtension') extension.
 6+ *
 7+ * Documentation: http://www.mediawiki.org/wiki/Extension:Arrays
 8+ * Support: http://www.mediawiki.org/wiki/Extension_talk:Arrays
 9+ * Source code: http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/Arrays
 10+ *
 11+ * @file Arrays.php
 12+ * @ingroup Arrays
 13+ *
 14+ * @licence MIT License
 15+ *
 16+ * @author Li Ding < lidingpku@gmail.com >
 17+ * @author Jie Bao
 18+ * @author Daniel Werner < danweetz@web.de > (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.
 25+ */
 26+
 27+if ( ! defined( 'MEDIAWIKI' ) ) { die(); }
 28+
 29+$wgExtensionCredits['parserhook'][] = array(
 30+ 'path' => __FILE__,
 31+ 'name' => 'Arrays',
 32+ 'url' => 'http://www.mediawiki.org/wiki/Extension:Arrays',
 33+ 'author' => array ( 'Li Ding', 'Jie Bao', '[http://www.mediawiki.org/wiki/User:Danwe Daniel Werner]' ),
 34+ 'descriptionmsg' => 'arrayext-desc',
 35+ 'version' => ExtArrays::VERSION
 36+);
 37+
 38+$wgExtensionMessagesFiles['Arrays' ] = ExtArrays::getDir() . '/Arrays.i18n.php';
 39+$wgExtensionMessagesFiles['ArraysMagic'] = ExtArrays::getDir() . '/Arrays.i18n.magic.php';
 40+
 41+// hooks registration:
 42+$wgHooks['ParserFirstCallInit'][] = 'ExtArrays::init';
 43+$wgHooks['ParserClearState' ][] = 'ExtArrays::onParserClearState';
 44+
 45+
 46+/**
 47+ * Full compatbility to versions before 1.4.
 48+ * Set to true by default since version 2.0.
 49+ * Regretable, this one has a speclling error...
 50+ *
 51+ * @since 1.4 alpha
 52+ *
 53+ * @var boolean
 54+ */
 55+$egArrayExtensionCompatbilityMode = false;
 56+
 57+
 58+/**
 59+ * Extension class with all the array functionality, also serves as store for arrays per
 60+ * Parser object and offers public accessors for interaction with the 'Arrays' extension.
 61+ *
 62+ * @since 2.0 ('ArrayExtension' before and one global instance, also non-static parser functions)
 63+ */
 64+class ExtArrays {
 65+
 66+ /**
 67+ * Version of the 'Arrays' extension.
 68+ *
 69+ * @since 2.0 (before in 'Arrays' class since 1.3.2)
 70+ */
 71+ const VERSION = '2.0 alpha';
 72+
 73+ /**
 74+ * Store for arrays.
 75+ *
 76+ * @var array
 77+ * @private
 78+ */
 79+ var $mArrays = array();
 80+
 81+ /**
 82+ * Sets up parser functions
 83+ *
 84+ * @since 2.0
 85+ */
 86+ public static function init( Parser &$parser ) {
 87+ /*
 88+ * store for arrays per Parser object. This will solve several bugs related to
 89+ * 'ParserClearState' hook clearing all variables early in combination with certain
 90+ * other extensions. (since v2.0)
 91+ */
 92+ $parser->mExtArrays = new self();
 93+
 94+ // SFH_OBJECT_ARGS available since MW 1.12
 95+ self::initFunction( $parser, 'arraydefine' );
 96+ self::initFunction( $parser, 'arrayprint', SFH_OBJECT_ARGS );
 97+ self::initFunction( $parser, 'arrayindex', SFH_OBJECT_ARGS );
 98+ self::initFunction( $parser, 'arraysize' );
 99+ self::initFunction( $parser, 'arraysearch', SFH_OBJECT_ARGS );
 100+ self::initFunction( $parser, 'arraysearcharray' );
 101+ self::initFunction( $parser, 'arrayslice' );
 102+ self::initFunction( $parser, 'arrayreset', SFH_OBJECT_ARGS );
 103+ self::initFunction( $parser, 'arrayunique' );
 104+ self::initFunction( $parser, 'arraysort' );
 105+ self::initFunction( $parser, 'arraymerge', SFH_OBJECT_ARGS );
 106+ self::initFunction( $parser, 'arrayunion', SFH_OBJECT_ARGS );
 107+ self::initFunction( $parser, 'arraydiff', SFH_OBJECT_ARGS );
 108+ self::initFunction( $parser, 'arrayintersect', SFH_OBJECT_ARGS );
 109+
 110+ return true;
 111+ }
 112+ private static function initFunction( Parser &$parser, $name, $flags = 0 ) {
 113+ // all parser functions with prefix:
 114+ $prefix = ( $flags & SFH_OBJECT_ARGS ) ? 'pfObj_' : 'pf_';
 115+ $functionCallback = array( __CLASS__, $prefix . $name );
 116+
 117+ $parser->setFunctionHook( $name, $functionCallback, $flags );
 118+ }
 119+
 120+ /**
 121+ * Returns the extensions base installation directory.
 122+ *
 123+ * @since 2.0
 124+ *
 125+ * @return boolean
 126+ */
 127+ public static function getDir() {
 128+ static $dir = null;
 129+
 130+ if( $dir === null ) {
 131+ $dir = dirname( __FILE__ );
 132+ }
 133+ return $dir;
 134+ }
 135+
 136+
 137+ ####################
 138+ # Parser Functions #
 139+ ####################
 140+
 141+ ///////////////////////////////////////////////////////////
 142+ // PART 1. Array Construction
 143+ ///////////////////////////////////////////////////////////
 144+
 145+ /**
 146+ * Define an array by a list of 'values' deliminated by 'delimiter',
 147+ * the delimiter should be perl regular expression pattern
 148+ * usage:
 149+ * {{#arraydefine:arrayid|values|delimiter|options}}
 150+ *
 151+ * http://us2.php.net/manual/en/book.pcre.php
 152+ * see also: http://us2.php.net/manual/en/function.preg-split.php
 153+ */
 154+ static function pf_arraydefine(
 155+ Parser &$parser,
 156+ $arrayId,
 157+ $value = null,
 158+ $delimiter = '/\s*,\s*/',
 159+ $options = '',
 160+ $delimiter2 = ', ',
 161+ $search = '@@@@',
 162+ $subject = '@@@@',
 163+ $frame = null
 164+ ) {
 165+ if ( !isset( $arrayId ) ) {
 166+ return '';
 167+ }
 168+
 169+ $out = '';
 170+ $array = array();
 171+ $trimDone = false; // whether or not we can be sure that all array elements are trimmed
 172+
 173+ // normalize
 174+ $delimiter = trim( $delimiter );
 175+
 176+ if( $value === null ) {
 177+ // no element set, not even an empty one
 178+ $array = array();
 179+ }
 180+ else {
 181+ $value = trim( $value ); // just in case...
 182+
 183+ // fill array with user input:
 184+ if( $delimiter === '' ) {
 185+ // whole input one element, also takes care of special case empty '' value and 'unique' option set
 186+ $array = array( $value );
 187+ $trimDone = true;
 188+ }
 189+ else {
 190+ // if no regex delimiter given, build one:
 191+ if( ! self::isValidRegEx( $delimiter ) ) {
 192+ $delimiter = '/\s*' . preg_quote( $delimiter, '/' ) . '\s*/';
 193+ $trimDone = true; // spaces are part of the delimiter now
 194+ }
 195+ $array = preg_split( $delimiter, $value );
 196+ }
 197+
 198+ // trim all values before unique if still necessary, otherwise unique might not work correctly
 199+ if( ! $trimDone ) {
 200+ $array = self::sanitizeArray( $array );
 201+ }
 202+
 203+ // now parse the options, and do posterior process on the created array
 204+ $arrayOptions = self::parse_options( $options );
 205+
 206+ // make it unique if option is set
 207+ if( array_key_exists( 'unique', $arrayOptions ) ) {
 208+ // unique like the parser function would do it
 209+ $array = self::array_unique( $array );
 210+ }
 211+
 212+ /**
 213+ * @ToDo:
 214+ * The 'empty' option was introduced in r81676 but actually breaks old functionality since it will remove
 215+ * all empty elements by default.
 216+ * 'unique' already allows to remove all empty elements but it will also remove al duplicates, there should
 217+ * be a more intelligent alternative to 'unique' which allows both, to preserve or remove empty elements
 218+ * independent from removing duplicate values.
 219+ */
 220+ /*
 221+ // remove all empty '' elements if option is NOT set
 222+ if( ! array_key_exists( 'empty', $arrayOptions ) ) {
 223+ $values = array(); // temp array so we won't have gaps (don't use unset!)
 224+ foreach ( $array as $key => $value ) {
 225+ if( $value !== '' ) {
 226+ $values[] = $elem;
 227+ }
 228+ }
 229+ $array = $values;
 230+ unset( $values );
 231+ }
 232+ */
 233+
 234+ // sort array if the option is set
 235+ self::pf_arraysort( $parser, $arrayId, self::array_value( $arrayOptions, 'sort' ) );
 236+
 237+ // print the array upon request
 238+ switch( self::array_value( $arrayOptions, 'print' ) ) {
 239+ case 'list':
 240+ $out = self::pf_arrayprint( $parser, $arrayId );
 241+ break;
 242+
 243+ case 'print':
 244+ $out = self::pf_arrayprint( $parser, $arrayId, $delimiter2, $search, $subject, $frame );
 245+ break;
 246+ }
 247+ }
 248+
 249+ self::get( $parser )->setArray( $arrayId, $array );
 250+
 251+ return $out;
 252+ }
 253+
 254+
 255+ ///////////////////////////////////////////////////////////
 256+ // PART 2. Extracting Information
 257+ ///////////////////////////////////////////////////////////
 258+
 259+
 260+ /**
 261+ * print an array.
 262+ * foreach element of the array, print 'subject' where all occurrences of 'search' is replaced with the element,
 263+ * and each element print-out is deliminated by 'delimiter'
 264+ * The subject can embed parser functions; wiki links; and templates.
 265+ * usage:
 266+ * {{#arrayprint:arrayid|delimiter|search|subject}}
 267+ * examples:
 268+ * {{#arrayprint:b}} -- simple
 269+ * {{#arrayprint:b|<br/>}} -- add change line
 270+ * {{#arrayprint:b|<br/>|@@@|[[@@@]]}} -- embed wiki links
 271+ * {{#arrayprint:b|<br/>|@@@|{{#set:prop=@@@}} }} -- embed parser function
 272+ * {{#arrayprint:b|<br/>|@@@|{{f.tag{{f.print.vbar}}prop{{f.print.vbar}}@@@}} }} -- embed template function
 273+ * {{#arrayprint:b|<br/>|@@@|[[name::@@@]]}} -- make SMW links
 274+ */
 275+ static function pf_arrayprint( Parser &$parser, $arrayId , $delimiter = ', ', $search = '@@@@', $subject = '@@@@', $frame = null ) {
 276+ // get array, null if non-existant:
 277+ $array = self::get( $parser )->getArray( $arrayId );
 278+
 279+ if( $array === null ) {
 280+ // array we want to print doesn't exist!
 281+ global $egArrayExtensionCompatbilityMode;
 282+ if( ! $egArrayExtensionCompatbilityMode ) {
 283+ return '';
 284+ } else {
 285+ // COMPATIBILITY-MODE
 286+ return "undefined array: $arrayId";
 287+ }
 288+ }
 289+
 290+ $rendered_values = array();
 291+ foreach( $array as $val ) {
 292+ // replace place holder with current value:
 293+ $rawResult = str_replace( $search, $val, $subject );
 294+
 295+ /*
 296+ * $subjectd still is un-expanded (this allows to use some parser functions like
 297+ * {{FULLPAGENAME:@@@@}} directly without getting parsed before @@@@ is replaced.
 298+ * Expand it so we replace templates like {{!}} which we need for the final parse.
 299+ */
 300+ $rawResult = $parser->preprocessToDom( $rawResult, $frame->isTemplate() ? Parser::PTD_FOR_INCLUSION : 0 );
 301+ $rawResult = trim( $frame->expand( $rawResult ) );
 302+
 303+ $rendered_values[] = $rawResult;
 304+ }
 305+
 306+ $output = implode( $delimiter, $rendered_values );
 307+ $noparse = false;
 308+
 309+ /*
 310+ * don't leave the final parse to Parser::braceSubstitution() since there are some special cases where it
 311+ * would produce unexpected output (it uses a new child frame and ignores whether the frame is a template!)
 312+ */
 313+ $noparse = true;
 314+
 315+ $output = $parser->preprocessToDom( $output, $frame->isTemplate() ? Parser::PTD_FOR_INCLUSION : 0 );
 316+ $output = trim( $frame->expand( $output ) );
 317+
 318+ return $output;
 319+ }
 320+
 321+ static function pfObj_arrayprint( Parser &$parser, $frame, $args ) {
 322+ // Get Parameters
 323+ $arrayId = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : '';
 324+ $delimiter = isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) : ', ';
 325+ /*
 326+ * PPFrame::NO_ARGS and PPFrame::NO_TEMPLATES for expansion make a lot of sense here since the patterns getting replaced
 327+ * in $subject before $subject is being parsed. So any template or argument influence in the patterns wouldn't make any
 328+ * sense in any sane scenario.
 329+ */
 330+ $search = isset( $args[2] ) ? trim( $frame->expand( $args[2], PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES ) ) : '@@@@';
 331+ $subject = isset( $args[3] ) ? trim( $frame->expand( $args[3], PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES ) ) : '@@@@';
 332+
 333+ return self::pf_arrayprint( $parser, $arrayId, $delimiter, $search, $subject, $frame );
 334+ }
 335+
 336+
 337+ /**
 338+ * 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.
 339+ * usage:
 340+ * {{#arrayindex:arrayid|index}}
 341+ */
 342+ static function pfObj_arrayindex( Parser &$parser, PPFrame $frame, $args ) {
 343+ global $egArrayExtensionCompatbilityMode;
 344+
 345+ // Get Parameters
 346+ $arrayId = isset( $args[0] ) ? trim( $frame->expand( $args[0] ) ) : '';
 347+ $rawOptions = isset( $args[2] ) ? $args[2] : '';
 348+
 349+ if( ! isset( $args[1] ) ) {
 350+ return '';
 351+ }
 352+ $index = trim( $frame->expand( $args[1] ) );
 353+
 354+ // get value or null if it doesn't exist. Takes care of negative index as well
 355+ $val = self::get( $parser )->getArrayValue( $arrayId, $index );
 356+
 357+ if( $val === null || ( $val === '' && !$egArrayExtensionCompatbilityMode ) ) {
 358+ // index doesn't exist, return default (parameter 3)!
 359+ // without compatibility, also return default in case of empty string ''
 360+
 361+ // only expand default when needed
 362+ $defaultOrOptions = trim( $frame->expand( $rawOptions ) );
 363+
 364+ if( $egArrayExtensionCompatbilityMode ) {
 365+ // COMPATIBILITY-MODE
 366+ // now parse the options, and do posterior process on the created array
 367+ $options = self::parse_options( $defaultOrOptions );
 368+ $default = self::array_value( $options, 'default' );
 369+ } else {
 370+ $default = $defaultOrOptions;
 371+ }
 372+
 373+ return $default;
 374+ }
 375+
 376+ return $val;
 377+ }
 378+
 379+ /**
 380+ * returns the size of an array.
 381+ * Print the size (number of elements) in the specified array and '' if array doesn't exist
 382+ * usage:
 383+ * {{#arraysize:arrayid}}
 384+ *
 385+ * See: http://www.php.net/manual/en/function.count.php
 386+ */
 387+ static function pf_arraysize( Parser &$parser, $arrayId ) {
 388+ $store = self::get( $parser );
 389+
 390+ if( ! $store->arrayExists( $arrayId ) ) {
 391+ return '';
 392+ }
 393+
 394+ return count( $store->getArray( $arrayId ) );
 395+ }
 396+
 397+
 398+ /**
 399+ * locate the index of the first occurence of an element starting from the 'index'
 400+ * - print "-1" (not found) or index (found) to show the index of the first occurence of 'value' in the array identified by arrayid
 401+ * - if 'yes' and 'no' are set, print value of them when found or not-found
 402+ * - index is 0-based , it must be non-negative and less than lenth
 403+ * usage:
 404+ * {{#arraysearch:arrayid|value|index|yes|no}}
 405+ *
 406+ * See: http://www.php.net/manual/en/function.array-search.php
 407+ * note it is extended to support regular expression match and index
 408+ */
 409+ static function pfObj_arraysearch( Parser &$parser, PPFrame $frame, $args ) {
 410+
 411+ $arrayId = trim( $frame->expand( $args[0] ) );
 412+ $index = isset( $args[2] ) ? trim( $frame->expand( $args[2] ) ) : 0;
 413+
 414+ $store = self::get( $parser );
 415+
 416+ if( $store->arrayExists( $arrayId )
 417+ && $store->validate_array_index( $arrayId, $index, false )
 418+ ) {
 419+ $array = $store->getArray( $arrayId );
 420+
 421+ // validate/build search regex:
 422+ if( isset( $args[1] ) ) {
 423+
 424+ $needle = trim( $frame->expand( $args[1] ) );
 425+
 426+ if ( ! self::isValidRegEx( $needle ) ) {
 427+ $needle = '/^\s*' . preg_quote( trim( $needle ), '/' ) . '\s*$/';
 428+ }
 429+ }
 430+ else {
 431+ $needle = '/^\s*$/';
 432+ }
 433+
 434+ // search for a match inside the array:
 435+ $total = count( $array );
 436+ for ( $i = $index; $i < $total; $i++ ) {
 437+ $value = $array[ $i ];
 438+
 439+ if ( preg_match( $needle, $value ) ) {
 440+ // found!
 441+ if ( isset( $args[3] ) ) {
 442+ // Expand only when needed!
 443+ return trim( $frame->expand( $args[3] ) );
 444+ }
 445+ else {
 446+ // return index of first found item
 447+ return $i;
 448+ }
 449+ }
 450+ }
 451+ }
 452+
 453+ global $egArrayExtensionCompatbilityMode;
 454+
 455+ // no match! (Expand only when needed!)
 456+ $no = isset( $args[4] )
 457+ ? trim( $frame->expand( $args[4] ) )
 458+ : $egArrayExtensionCompatbilityMode ? '-1' : ''; // COMPATIBILITY-MODE
 459+ return $no;
 460+ }
 461+
 462+ /**
 463+ * search an array and create a new array with all the results. Transforming the new entries before storing them is possible too.
 464+ * usage:
 465+ * {{#arraysearcharray:arrayid_new|arrayid|needle|index|limit|transform}}
 466+ *
 467+ * "needle" can be a regular expression or a string search value. If "needle" is a regular expression, "transform" can contain
 468+ * "$n" where "n" stands for a number to access a variable from the regex result.
 469+ */
 470+ static function pf_arraysearcharray(
 471+ Parser &$parser,
 472+ $arrayId_new,
 473+ $arrayId = null,
 474+ $needle = '/^(\s*)$/',
 475+ $index = 0,
 476+ $limit = -1,
 477+ $transform = ''
 478+ ) {
 479+ $store = self::get( $parser );
 480+
 481+ if( $arrayId === null ) {
 482+ global $egArrayExtensionCompatbilityMode;
 483+ if( ! $egArrayExtensionCompatbilityMode ) { // COMPATIBILITY-MODE
 484+ $store->setArray( $arrayId_new );
 485+ }
 486+ return '';
 487+ }
 488+ // also takes care of negative index by calculating start index:
 489+ $validIndex = $store->validate_array_index( $arrayId, $index, false );
 490+
 491+ // make sure at least empty array exists but don't overwrite data
 492+ // we still need in case new array ID same as target array ID
 493+ $array = $store->getArray( $arrayId );
 494+ $store->setArray( $arrayId_new );
 495+
 496+ if( $array === null || !$validIndex ) {
 497+ return '';
 498+ }
 499+
 500+ // non-numeric limit will be set to 0
 501+ $limit = (int)$limit;
 502+ if( $limit === 0 ) {
 503+ return '';
 504+ }
 505+
 506+ $newArr = array();
 507+
 508+ if( ! self::isValidRegEx( $needle ) ) {
 509+ $needle = '/^\s*(' . preg_quote( $needle, '/' ) . ')\s*$/';
 510+ }
 511+
 512+ // search the array for all matches and put them in the new array
 513+ $total = count( $array );
 514+ for( $i = $index; $i < $total; $i++ ) {
 515+
 516+ $value = $array[ $i ];
 517+
 518+ if( preg_match( $needle, $value ) ) {
 519+ if( $transform !== '' ) {
 520+ $value = preg_replace( $needle, $transform, $value );
 521+ }
 522+ $newArr[] = trim( $value );
 523+
 524+ // stop if limit is reached, limit -1 means no limit
 525+ if( --$limit === 0 ) {
 526+ break;
 527+ }
 528+ }
 529+ }
 530+
 531+ // set new array:
 532+ $store->setArray( $arrayId_new, $newArr );
 533+ return '';
 534+ }
 535+
 536+ /**
 537+ * extract a slice from an array
 538+ * usage:
 539+ * {{#arrayslice:arrayid_new|arrayid|offset|length}}
 540+ *
 541+ * extract a slice from an array
 542+ * see: http://www.php.net/manual/en/function.array-slice.php
 543+ */
 544+ static function pf_arrayslice( Parser &$parser, $arrayId_new, $arrayId = null , $offset = 0, $length = null ) {
 545+ $store = self::get( $parser );
 546+ if( $arrayId === null ) {
 547+ global $egArrayExtensionCompatbilityMode;
 548+ if( ! $egArrayExtensionCompatbilityMode ) { // COMPATIBILITY-MODE
 549+ $store->setArray( $arrayId_new );
 550+ }
 551+ return '';
 552+ }
 553+ // get target array before overwriting it in any way
 554+ $array = $store->getArray( $arrayId );
 555+
 556+ // make sure at least an empty array exists if we return early
 557+ $store->setArray( $arrayId_new );
 558+
 559+ if( $array === null
 560+ || ! is_numeric( $offset ) // don't ignore invalid offset
 561+ ) {
 562+ return '';
 563+ }
 564+
 565+ if( ! is_numeric( $length ) ) {
 566+ $length = null; // ignore invalid input, slice till end
 567+ }
 568+
 569+ // array_slice will re-organize keys
 570+ $newArray = array_slice( $array, $offset, $length );
 571+ $store->setArray( $arrayId_new, $newArray );
 572+
 573+ return '';
 574+ }
 575+
 576+
 577+ ///////////////////////////////////////////////////////////
 578+ // PART 3. Array Alteration
 579+ ///////////////////////////////////////////////////////////
 580+
 581+ /**
 582+ * reset some or all defined arrayes
 583+ * usage:
 584+ * {{#arrayreset:}}
 585+ * {{#arrayreset:arrayid1,arrayid2,...arrayidn}}
 586+ */
 587+ static function pfObj_arrayreset( Parser &$parser, PPFrame $frame, $args) {
 588+ global $egArrayExtensionCompatbilityMode;
 589+
 590+ if( $egArrayExtensionCompatbilityMode && count( $args ) == 1 ) {
 591+ /*
 592+ * COMPATIBILITY-MODE: before arrays were separated by ';' which is an bad idea since
 593+ * the ',' is an allowed character in array names!
 594+ */
 595+ $args = preg_split( '/\s*,\s*/', trim( $frame->expand( $args[0] ) ) );
 596+ }
 597+
 598+ $store = self::get( $parser );
 599+
 600+ // reset all hash tables if no specific tables are given:
 601+ if( ! isset( $args[0] ) || ( $args[0] === '' && count( $args ) == 1 ) ) {
 602+ $store->mArrays = array();
 603+ }
 604+ else {
 605+ // reset specific hash tables:
 606+ foreach( $args as $arg ) {
 607+ $arrayId = trim( $frame->expand( $arg ) );
 608+ $store->unsetArray( $arrayId );
 609+ }
 610+ }
 611+ return '';
 612+ }
 613+
 614+
 615+ /**
 616+ * convert an array to a set
 617+ * convert the array identified by arrayid into a set (all elements are unique)
 618+ * also removes empty '' elements from the array
 619+ * usage:
 620+ * {{#arrayunique:arrayid}}
 621+ *
 622+ * see: http://www.php.net/manual/en/function.array-unique.php
 623+ */
 624+ static function pf_arrayunique( Parser &$parser, $arrayId ) {
 625+ $store = self::get( $parser );
 626+
 627+ if( $store->arrayExists( $arrayId ) ) {
 628+ $array = $store->getArray( $arrayId );
 629+ $array = self::array_unique( $array );
 630+ $store->setArray( $arrayId, $array );
 631+ }
 632+ return '';
 633+ }
 634+
 635+
 636+ /**
 637+ * sort specified array in the following order:
 638+ * - none: No sort (default)
 639+ * - desc: In descending order, large to small
 640+ * - asce: In ascending order, small to large
 641+ * - random: Shuffle the arrry in random order
 642+ * - reverse: Return an array with elements in reverse order
 643+ * usage:
 644+ * {{#arraysort:arrayid|order}}
 645+ *
 646+ * see: http://www.php.net/manual/en/function.sort.php
 647+ * http://www.php.net/manual/en/function.rsort.php
 648+ * http://www.php.net/manual/en/function.shuffle.php
 649+ * http://us3.php.net/manual/en/function.array-reverse.php
 650+ */
 651+ static function pf_arraysort( Parser &$parser, $arrayId , $sort = 'none' ) {
 652+ $store = self::get( $parser );
 653+
 654+ if( ! $store->arrayExists( $arrayId ) ) {
 655+ return '';
 656+ }
 657+
 658+ // do the requested sorting of the given array:
 659+ switch( $sort ) {
 660+ case 'asc':
 661+ case 'asce':
 662+ case 'ascending':
 663+ sort( $store->mArrays[ $arrayId ] );
 664+ break;
 665+
 666+ case 'desc':
 667+ case 'descending':
 668+ rsort( $store->mArrays[ $arrayId ] );
 669+ break;
 670+
 671+ case 'random':
 672+ shuffle( $store->mArrays[ $arrayId ] );
 673+ break;
 674+
 675+ case 'reverse':
 676+ $store->mArrays[ $arrayId ] = array_reverse( $store->mArrays[ $arrayId ] );
 677+ break;
 678+ } ;
 679+ }
 680+
 681+
 682+ ///////////////////////////////////////////////////////////
 683+ // PART 4. Array Interaction
 684+ ///////////////////////////////////////////////////////////
 685+
 686+ /**
 687+ * Merge values two arrayes identified by arrayid1 and arrayid2 into a new array identified by arrayid_new.
 688+ * This merge differs from array_merge of php because it merges values.
 689+ *
 690+ * Usage:
 691+ * {{#arraymerge:arrayid_new |array1 |array2 |... |array n}}
 692+ * See: http://www.php.net/manual/en/function.array-merge.php
 693+ */
 694+ static function pfObj_arraymerge( &$parser, $frame, $args) {
 695+ self::get( $parser )->multiArrayOperation( $frame, $args, __FUNCTION__, false );
 696+ return '';
 697+ }
 698+ private function multi_arraymerge( $array1, $array2 ) {
 699+ // keys will not be re-organized
 700+ return array_merge( $array1, $array2 );
 701+ }
 702+
 703+ /**
 704+ * Usage:
 705+ * {{#arrayunion:arrayid_new|arrayid1|arrayid2}}
 706+ *
 707+ * Set operation, {red, white} = {red, white} union {red}
 708+ * Similar to arraymerge but with unique values. This union works on values.
 709+ */
 710+ static function pfObj_arrayunion( &$parser, $frame, $args) {
 711+ self::get( $parser )->multiArrayOperation( $frame, $args, __FUNCTION__, false );
 712+ return '';
 713+ }
 714+ private function multi_arrayunion( $array1, $array2 ) {
 715+ // keys will not be re-organized
 716+ return array_unique( array_merge( $array1, $array2 ) );
 717+ }
 718+
 719+ /**
 720+ * Usage:
 721+ * {{#arrayintersect:arrayid_new |array1 |array2 |... |array n}}
 722+ *
 723+ * Set operation, {red} = {red, white} intersect {red,black}
 724+ * See: http://www.php.net/manual/en/function.array-intersect.php
 725+ */
 726+ static function pfObj_arrayintersect( &$parser, $frame, $args) {
 727+ self::get( $parser )->multiArrayOperation( $frame, $args, __FUNCTION__, false );
 728+ return '';
 729+ }
 730+ private function multi_arrayintersect( $array1, $array2 ) {
 731+ // keys will be preserved!
 732+ return array_intersect( $array1, $array2 );
 733+ }
 734+
 735+ /**
 736+ *
 737+ * Usage:
 738+ * {{#arraydiff:arrayid_new |array1 |array2 |... |array n}}
 739+ *
 740+ * Set operation, {white} = {red, white} - {red}
 741+ * See: http://www.php.net/manual/en/function.array-diff.php
 742+ */
 743+ static function pfObj_arraydiff( &$parser, $frame, $args) {
 744+ self::get( $parser )->multiArrayOperation( $frame, $args, __FUNCTION__, false );
 745+ return '';
 746+ }
 747+ private function multi_arraydiff( $array1, $array2 ) {
 748+ // keys will be preserved!
 749+ return array_diff( $array1, $array2 );
 750+ }
 751+
 752+
 753+ ##################
 754+ # Private helper #
 755+ ##################
 756+
 757+ /**
 758+ * Base function for operations with multiple arrays given thru n parameters
 759+ * $operationFunc expects a function name prefix (suffix 'multi_') with two parameters
 760+ * $array1 and $array2 which will perform an action between $array1 and $array2 which
 761+ * will result into a new $array1. There can be 1 to n $hash2 in the whole process.
 762+ *
 763+ * Note: This function is similar to that of Extension:HashTables.
 764+ *
 765+ * @since 2.0
 766+ *
 767+ * @param $frame PPFrame
 768+ * @param $args array
 769+ * @param $operationFunc string name of the function calling this. There must be a counterpart
 770+ * function with prefix 'multi_' which should have two parameters. Both parameters
 771+ * will receive an array, the function must return the result array of the processing.
 772+ * @param $runFuncOnSingleArray boolean whether the $operationFunc function should be run in case
 773+ * only one array id is given. If not, the original array will end up in the new array.
 774+ */
 775+ protected function multiArrayOperation( PPFrame $frame, array $args, $operationFunc, $runFuncOnSingleArray = true ) {
 776+ $lastArray = null;
 777+ $operationRan = false;
 778+ $finalArrayId = trim( $frame->expand( $args[0] ) );
 779+ $operationFunc = 'multi_' . preg_replace( '/^pfObj_/', '', $operationFunc );
 780+
 781+ // For all arrays given in parameters 2 to n (ignore 1 because this is the name of the new array)
 782+ for( $i = 1; $i < count( $args ); $i++ ) {
 783+ // just make sure we don't fall into gaps of given arguments:
 784+ if( ! array_key_exists( $i, $args ) ) {
 785+ continue;
 786+ }
 787+ $argArrayId = trim( $frame->expand( $args[ $i ] ) );
 788+
 789+ // ignore all tables which do not exist
 790+ if( $this->arrayExists( $argArrayId ) ) {
 791+ $argArray = $this->getArray( $argArrayId );
 792+ if( $lastArray === null ) {
 793+ // first valid array, process together with second...
 794+ $lastArray = $argArray;
 795+ }
 796+ else {
 797+ // second or later hash table, process with previous:
 798+ $lastArray = $this->{ $operationFunc }( $lastArray, $argArray ); // perform action between last and current array
 799+ $operationRan = true;
 800+ }
 801+ }
 802+ }
 803+
 804+ // in case no array was given at all:
 805+ if( $lastArray === null ) {
 806+ $lastArray = array();
 807+ }
 808+
 809+ global $egArrayExtensionCompatbilityMode;
 810+
 811+ if( ! $operationRan && $egArrayExtensionCompatbilityMode
 812+ && $operationFunc !== 'multi_arraymerge' // only exception was 'arraymerge'
 813+ ) {
 814+ /*
 815+ * COMPATIBILITY-MODE:
 816+ * Before version 2.0 we didn't create a new array in case only one array was given.
 817+ * The only exception was 'arraymerge' which did duplicate the array.
 818+ */
 819+ return '';
 820+ }
 821+
 822+ // if the operation didn't run because there was only one or no array:
 823+ if( ! $operationRan && $runFuncOnSingleArray ) {
 824+ $lastArray = $this->{ $operationFunc }( $lastArray );
 825+ }
 826+
 827+ // re-organize all keys since some 'multi_' functions will preserve keys!
 828+ $lastArray = array_merge( $lastArray );
 829+
 830+ $this->setArray( $finalArrayId, $lastArray );
 831+ }
 832+
 833+ /**
 834+ * Validates an index for an array and returns true in case the index is a valid index within
 835+ * the array. This also changes the index value, which is given by reference, in case it is
 836+ * set to a negative value. In case $strictIndex is set to false, further transforming of
 837+ * $index might be done - in the same cases normally the function would return false.
 838+ *
 839+ * @param string $arrayId
 840+ * @param mixed &$index
 841+ * @param bool $strictIndex Whether non-numeric indexes and negative indexes which would
 842+ * end up out of range, below 0, should be set to 0 automatically.
 843+ *
 844+ * @return boolean
 845+ */
 846+ protected function validate_array_index( $arrayId, &$index, $strictIndex = false ) {
 847+ if( ! is_numeric( $index ) ) {
 848+ if( $strictIndex ) {
 849+ return false;
 850+ } else {
 851+ $index = 0;
 852+ }
 853+ }
 854+ $index = (int)$index;
 855+
 856+ if( ! array_key_exists( $arrayId, $this->mArrays ) ) {
 857+ return false;
 858+ }
 859+
 860+ $array = $this->mArrays[ $arrayId ];
 861+
 862+ // calculate start index for negative start indexes:
 863+ if( $index < 0 ) {
 864+ $index = count( $array ) + $index;
 865+ if ( $index < 0 && !$strictIndex ) {
 866+ $index = 0;
 867+ }
 868+ }
 869+
 870+ if( ! isset( $array ) ) {
 871+ return false;
 872+ }
 873+ if( ! array_key_exists( $index, $array ) ) {
 874+ return false;
 875+ }
 876+ return true;
 877+ }
 878+
 879+ /**
 880+ * private function for validating array by name
 881+ * @ToDo: get rid of this!
 882+ * @deprecated
 883+ */
 884+ protected function validate_array_by_arrayId( $arrayId ) {
 885+ if( ! isset( $arrayId ) ) {
 886+ return '';
 887+ }
 888+ if( ! isset( $this->mArrays )
 889+ || ! array_key_exists( $arrayId, $this->mArrays )
 890+ || ! is_array( $this->mArrays[ $arrayId ] )
 891+ ) {
 892+ global $egArrayExtensionCompatbilityMode;
 893+ if( $egArrayExtensionCompatbilityMode ) {
 894+ return "undefined array: $arrayId"; // COMPATIBILITY-MODE
 895+ } else {
 896+ return '';
 897+ }
 898+ }
 899+
 900+ return true;
 901+ }
 902+
 903+ /**
 904+ * Convenience function to get a value from an array. Returns '' in case the
 905+ * value doesn't exist or no array was given
 906+ */
 907+ protected static function array_value( $array, $field ) {
 908+ if ( is_array( $array ) && array_key_exists( $field, $array ) ) {
 909+ return $array[ $field ];
 910+ }
 911+ return '';
 912+ }
 913+
 914+ /**
 915+ * Parses a string of options separated by ','. Options can be just certain key-words or
 916+ * key-value pairs separated by '='. Options are case-insensitive and spacing between
 917+ * separators will be ignored.
 918+ */
 919+ protected static function parse_options( $options ) {
 920+ if( ! isset( $options ) ) {
 921+ return array();
 922+ }
 923+
 924+ // now parse the options, and do posterior process on the created array
 925+ $options = preg_split( '/\s*,\s*/', strtolower( $options ) );
 926+
 927+ $ret = array();
 928+ foreach( $options as $option ) {
 929+ $optPair = preg_split( '/\s*\=\s*/', $option, 2 );
 930+ if( sizeof( $optPair ) == 1 ) {
 931+ $ret[ $optPair[0] ] = true;
 932+ } else {
 933+ $ret[ $optPair[0] ] = $optPair[1];
 934+ }
 935+ }
 936+ return $ret;
 937+ }
 938+
 939+ /**
 940+ * same as self::arrayUnique() but without sanitazation, only for internal use.
 941+ */
 942+ protected static function array_unique( array $array ) {
 943+ // delete duplicate values
 944+ $array = array_unique( $array );
 945+
 946+ $values = array();
 947+ foreach( $array as $key => $val ) {
 948+ // don't put emty elements into the array
 949+ if( $val !== '' ) {
 950+ $values[] = $val;
 951+ }
 952+ }
 953+
 954+ return $values;
 955+ }
 956+
 957+
 958+ ##############
 959+ # Used Hooks #
 960+ ##############
 961+
 962+ static function onParserClearState( Parser &$parser ) {
 963+ // remove all arrays to avoid conflicts with job queue or Special:Import or SMW semantic updates
 964+ $parser->mExtArrays = new self();
 965+ return true;
 966+ }
 967+
 968+
 969+ ####################################
 970+ # Public functions for interaction #
 971+ ####################################
 972+ #
 973+ # public non-parser functions, accessible for
 974+ # other extensions doing interactive stuff
 975+ # with the Array extension.
 976+ #
 977+
 978+ /**
 979+ * Convenience function to return the 'Arrays' extensions array store connected
 980+ * to a certain Parser object. Each parser has its own store which will be reset after
 981+ * a parsing process [Parser::parse()] has finished.
 982+ *
 983+ * @since 2.0
 984+ *
 985+ * @param Parser &$parser
 986+ *
 987+ * @return ExtArrays by reference so we still have the right object after 'ParserClearState'
 988+ */
 989+ public static function &get( Parser &$parser ) {
 990+ return $parser->mExtArrays;
 991+ }
 992+
 993+ /**
 994+ * Returns an array identified by $arrayId. If it doesn't exist, null will be returned.
 995+ *
 996+ * @since 2.0
 997+ *
 998+ * @param string $arrayId
 999+ *
 1000+ * @return array|null
 1001+ */
 1002+ function getArray( $arrayId ) {
 1003+ $arrayId = trim( $arrayId );
 1004+ if( $this->arrayExists( $arrayId ) ) {
 1005+ return $this->mArrays[ $arrayId ];
 1006+ }
 1007+ return null;
 1008+ }
 1009+
 1010+ /**
 1011+ * This will add a new array or overwrite an existing one. Values should be delliverd as array
 1012+ * values in form of a string. The array will be sanitized internally.
 1013+ *
 1014+ * @param string $arrayId
 1015+ * @param array $array
 1016+ */
 1017+ public function createArray( $arrayId, $array = array() ) {
 1018+ $array = self::sanitizeArray( $array );
 1019+ $this->mArrays[ trim( $arrayId ) ] = $array;
 1020+ }
 1021+
 1022+ /**
 1023+ * Same as the public function createArray() but without sanitizing the array automatically.
 1024+ * This is save and faster for internal usage, just be sure your array doesn't have un-trimmed
 1025+ * values or non-numeric or negative array keys and no gaps between keys.
 1026+ *
 1027+ * @param type $arrayId
 1028+ * @param type $array
 1029+ */
 1030+ protected function setArray( $arrayId, $array = array() ) {
 1031+ $this->mArrays[ trim( $arrayId ) ] = $array;
 1032+ }
 1033+
 1034+ /**
 1035+ * Returns whether a certain array is defined within the page scope.
 1036+ *
 1037+ * @param string $arrayId
 1038+ *
 1039+ * @return boolean
 1040+ */
 1041+ function arrayExists( $arrayId ) {
 1042+ return array_key_exists( trim( $arrayId ), $this->mArrays );
 1043+ }
 1044+
 1045+ /**
 1046+ * Returns a value within an array. If key or array do not exist, this will return null
 1047+ * or another predefined default. $index can also be a negative value, in this case the
 1048+ * value that far from the end of the array will be returned.
 1049+ *
 1050+ * @since 2.0
 1051+ *
 1052+ * @param string $arrayId
 1053+ * @param string $index
 1054+ * @param mixed $default value to return in case the value doesn't exist. null by default.
 1055+ *
 1056+ * @return string|null
 1057+ */
 1058+ function getArrayValue( $arrayId, $index, $default = null ) {
 1059+ $arrayId = trim( $arrayId );
 1060+ if( $this->arrayExists( $arrayId )
 1061+ && $this->validate_array_index( $arrayId, $index, true )
 1062+ && array_key_exists( $index, $this->mArrays[ $arrayId ] )
 1063+ ) {
 1064+ return $this->mArrays[ $arrayId ][ $index ];
 1065+ }
 1066+ else {
 1067+ return $default;
 1068+ }
 1069+ }
 1070+
 1071+
 1072+ /**
 1073+ * Removes an existing array. If array didn't exist this will return false, otherwise true.
 1074+ *
 1075+ * @since 2.0
 1076+ *
 1077+ * @param string $arrayId
 1078+ *
 1079+ * @return boolean whether the array existed and has been removed
 1080+ */
 1081+ public function unsetArray( $arrayId ) {
 1082+ $arrayId = trim( $arrayId );
 1083+ if( $this->arrayExists( $arrayId ) ) {
 1084+ unset( $this->mArrays[ $arrayId ] );
 1085+ return true;
 1086+ }
 1087+ return false;
 1088+ }
 1089+
 1090+ /**
 1091+ * Rebuild the array and reorganize all keys, trim all values.
 1092+ * All gaps between array items will be closed.
 1093+ *
 1094+ * @since 2.0
 1095+ *
 1096+ * @param array $arr array to be reorganized
 1097+ * @return array
 1098+ */
 1099+ public static function sanitizeArray( $array ) {
 1100+ $newArray = array();
 1101+ foreach( $array as $val ) {
 1102+ $newArray[] = trim( $val );
 1103+ }
 1104+ return $newArray;
 1105+ }
 1106+
 1107+ /**
 1108+ * Removes duplicate values and all empty elements from an array just like the
 1109+ * arrayunique parser function would do it. The array will be sanitized internally.
 1110+ *
 1111+ * @since 2.0
 1112+ *
 1113+ * @param array $array
 1114+ *
 1115+ * @return array
 1116+ */
 1117+ public static function arrayUnique( array $array ) {
 1118+ $arr = $this->sanitizeArray( $arr );
 1119+ $array = self::array_unique( $array );
 1120+ }
 1121+
 1122+ /**
 1123+ * Decides for the given $pattern whether its a valid regular expression acceptable for
 1124+ * Arrays parser functions or not.
 1125+ *
 1126+ * @param string $pattern regular expression including delimiters and optional flags
 1127+ *
 1128+ * @return boolean
 1129+ */
 1130+ static function isValidRegEx( $pattern ) {
 1131+ if( ! preg_match( '/^([\\/\\|%]).*\\1[imsSuUx]*$/', $pattern ) ) {
 1132+ return false;
 1133+ }
 1134+ wfSuppressWarnings(); // instead of using the evil @ operator!
 1135+ $isValid = false !== preg_match( $pattern, ' ' ); // preg_match returns false on error
 1136+ wfRestoreWarnings();
 1137+ return $isValid;
 1138+ }
 1139+}
Property changes on: trunk/extensions/Arrays/Arrays.php
___________________________________________________________________
Added: svn:eol-style
11140 + native
Index: trunk/extensions/Arrays/COPYING
@@ -0,0 +1,27 @@
 2+The MIT License
 3+
 4+ Copyright (c) 2008 - 2011
 5+
 6+
 7+ Permission is hereby granted, free of charge, to any person
 8+ obtaining a copy of this software and associated documentation
 9+ files (the "Software"), to deal in the Software without
 10+ restriction, including without limitation the rights to use,
 11+ copy, modify, merge, publish, distribute, sublicense, and/or sell
 12+ copies of the Software, and to permit persons to whom the
 13+ Software is furnished to do so, subject to the following
 14+ conditions:
 15+
 16+
 17+ The above copyright notice and this permission notice shall be
 18+ included in all copies or substantial portions of the Software.
 19+
 20+
 21+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 22+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 23+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 24+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 25+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 26+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 27+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 28+ OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
Property changes on: trunk/extensions/Arrays/COPYING
___________________________________________________________________
Added: svn:eol-style
129 + native
Index: trunk/extensions/Arrays/README
@@ -0,0 +1,26 @@
 2+== About ==
 3+
 4+The 'Arrays' extension (former 'ArrayExtension') Enhances the parser with functions to handle
 5+arrays within wiki markup text.
 6+
 7+* Website: http://www.mediawiki.org/wiki/Extension:Arrays
 8+* Authors: Li Ding, Jie Bao, Daniel Werner < danweetz@web.de >
 9+* License: MIT license
 10+
 11+
 12+== Installation ==
 13+
 14+Once you have downloaded the code, place the 'Array' directory within your
 15+MediaWiki 'extensions' directory. Then add the following code to your
 16+[[Manual:LocalSettings.php|LocalSettings.php]] file:
 17+
 18+ # Arrays
 19+ require_once( "$IP/extensions/Arrays/Arrays.php" );
 20+
 21+
 22+== Contributing ==
 23+
 24+If you have bug reports or feature requests, please add them to the 'Arrays'
 25+Talk page [0]. You can also send them to Daniel Werner < danweetz@web.de >
 26+
 27+[0] http://www.mediawiki.org/w/index.php?title=Extension_talk:Arrays
Property changes on: trunk/extensions/Arrays/README
___________________________________________________________________
Added: svn:eol-style
128 + native

Follow-up revisions

RevisionCommit summaryAuthorDate
r103899'ArrayExtension' renamed to 'Arrays' in r103897danwe14:48, 22 November 2011
r103912Rename description key for consistency too (r103897).raymond16:10, 22 November 2011
r103913Followup r103897 for Translateeiki.netraymond16:10, 22 November 2011

Status & tagging log