Index: trunk/extensions/HashTables/HashTables.php |
— | — | @@ -4,7 +4,7 @@ |
5 | 5 | * Defines a subset of parser functions to handle hash tables. Inspired by the ArrayExtension |
6 | 6 | * (http://www.mediawiki.org/wiki/Extension:ArrayExtension). |
7 | 7 | * |
8 | | - * @version: 0.7 |
| 8 | + * @version: 0.8 alpha |
9 | 9 | * @author: Daniel Werner < danweetz@web.de > |
10 | 10 | * @license: ISC license |
11 | 11 | * |
— | — | @@ -24,9 +24,7 @@ |
25 | 25 | * |
26 | 26 | */ |
27 | 27 | |
28 | | -if( !defined( 'MEDIAWIKI' ) ) { |
29 | | - die( 'This file is a MediaWiki extension, it is not a valid entry point' ); |
30 | | -} |
| 28 | +if ( ! defined( 'MEDIAWIKI' ) ) { die(); } |
31 | 29 | |
32 | 30 | $wgExtensionCredits['parserhook'][] = array( |
33 | 31 | 'path' => __FILE__, |
— | — | @@ -37,14 +35,14 @@ |
38 | 36 | 'url' => 'http://www.mediawiki.org/wiki/Extension:HashTables', |
39 | 37 | ); |
40 | 38 | |
41 | | -$wgHooks['ParserFirstCallInit'][] = 'efHashTablesParserFirstCallInit'; |
42 | | - |
43 | | -$dir = dirname( __FILE__ ); |
| 39 | +// language files: |
| 40 | +$wgExtensionMessagesFiles['HashTables' ] = ExtHashTables::getDir() . '/HashTables.i18n.php'; |
| 41 | +$wgExtensionMessagesFiles['HashTablesMagic'] = ExtHashTables::getDir() . '/HashTables.i18n.magic.php'; |
44 | 42 | |
45 | | -$wgExtensionMessagesFiles['HashTables' ] = $dir . '/HashTables.i18n.php'; |
46 | | -$wgExtensionMessagesFiles['HashTablesMagic'] = $dir . '/HashTables.i18n.magic.php'; |
| 43 | +// hooks registration: |
| 44 | +$wgHooks['ParserFirstCallInit'][] = 'ExtHashTables::init'; |
| 45 | +$wgHooks['ParserClearState' ][] = 'ExtHashTables::onParserClearState'; |
47 | 46 | |
48 | | -unset( $dir ); |
49 | 47 | |
50 | 48 | /** |
51 | 49 | * Extension class with all the hash table functionality |
— | — | @@ -58,7 +56,7 @@ |
59 | 57 | * |
60 | 58 | * @var string |
61 | 59 | */ |
62 | | - const VERSION = '0.7'; |
| 60 | + const VERSION = '0.8 alpha'; |
63 | 61 | |
64 | 62 | /** |
65 | 63 | * @since 0.1 |
— | — | @@ -73,43 +71,108 @@ |
74 | 72 | $wgHooks['ParserClearState'][] = &$this; |
75 | 73 | } |
76 | 74 | |
77 | | - function onParserClearState( &$parser ) { |
78 | | - // remove all hash tables to avoid conflicts with job queue or Special:Import |
79 | | - $this->mHashTables = array(); |
80 | | - return true; |
81 | | - } |
| 75 | + /** |
| 76 | + * Sets up parser functions |
| 77 | + * |
| 78 | + * @since 0.8 |
| 79 | + */ |
| 80 | + public static function init( Parser &$parser ) { |
| 81 | + |
| 82 | + /* |
| 83 | + * store for variables per parser object. This will solve several bugs related to |
| 84 | + * 'ParserClearState' hook clearing all variables early in combination with certain |
| 85 | + * other extensions. (since v2.0) |
| 86 | + */ |
| 87 | + $parser->mExtHashTables = new self(); |
| 88 | + |
| 89 | + // SFH_OBJECT_ARGS available since MW 1.12 |
| 90 | + self::initFunction( $parser, 'hashdefine' ); |
| 91 | + self::initFunction( $parser, 'hashvalue' ); |
| 92 | + self::initFunction( $parser, 'hashsize' ); |
| 93 | + self::initFunction( $parser, 'hashkeyexists', SFH_OBJECT_ARGS ); |
| 94 | + self::initFunction( $parser, 'hashprint', SFH_OBJECT_ARGS ); |
| 95 | + self::initFunction( $parser, 'parameterstohash', SFH_OBJECT_ARGS ); |
| 96 | + self::initFunction( $parser, 'hashtotemplate', SFH_OBJECT_ARGS ); |
| 97 | + self::initFunction( $parser, 'hashinclude', SFH_OBJECT_ARGS ); |
| 98 | + self::initFunction( $parser, 'hashexclude', SFH_OBJECT_ARGS ); |
| 99 | + self::initFunction( $parser, 'hashreset', SFH_OBJECT_ARGS ); |
| 100 | + self::initFunction( $parser, 'hashmerge', SFH_OBJECT_ARGS ); |
| 101 | + self::initFunction( $parser, 'hashmix', SFH_OBJECT_ARGS ); |
| 102 | + self::initFunction( $parser, 'hashdiff', SFH_OBJECT_ARGS ); |
| 103 | + self::initFunction( $parser, 'hashintersect', SFH_OBJECT_ARGS ); |
| 104 | + |
| 105 | + // if array extension is available, rgister array-hash interactions: |
| 106 | + if( class_exists( 'ArrayExtension' ) ) { |
| 107 | + self::initFunction( $parser, 'hashtoarray' ); |
| 108 | + self::initFunction( $parser, 'arraytohash' ); |
| 109 | + } |
| 110 | + |
| 111 | + return true; |
| 112 | + } |
| 113 | + private static function initFunction( Parser &$parser, $name, $flags = 0 ) { |
| 114 | + // all parser functions with prefix: |
| 115 | + $prefix = ( $flags & SFH_OBJECT_ARGS ) ? 'pfObj_' : 'pf_'; |
| 116 | + $functionCallback = array( __CLASS__, $prefix . $name ); |
| 117 | + |
| 118 | + $parser->setFunctionHook( $name, $functionCallback, $flags ); |
| 119 | + } |
82 | 120 | |
83 | 121 | /** |
| 122 | + * Returns the extensions base installation directory. |
| 123 | + * |
| 124 | + * @since 0.8 |
| 125 | + * |
| 126 | + * @return boolean |
| 127 | + */ |
| 128 | + public static function getDir() { |
| 129 | + static $dir = null; |
| 130 | + |
| 131 | + if( $dir === null ) { |
| 132 | + $dir = dirname( __FILE__ ); |
| 133 | + } |
| 134 | + return $dir; |
| 135 | + } |
| 136 | + |
| 137 | + |
| 138 | + #################### |
| 139 | + # Parser Functions # |
| 140 | + #################### |
| 141 | + |
| 142 | + /** |
84 | 143 | * Define an hash by a list of 'values' deliminated by 'itemsDelimiter'. |
85 | 144 | * Hash keys and their values are deliminated by 'innerDelimiter'. |
86 | 145 | * Both delimiters can be perl regular expression patterns. |
87 | 146 | * Syntax: {{#hashdefine:hashId |values |itemsDelimiter |innerDelimiter}} |
88 | 147 | */ |
89 | | - function hashdefine( &$parser, $hashId, $value='', $itemsDelimiter = '/\s*,\s*/', $innerDelimiter = '/\s*;\s*/' ) { |
90 | | - if( !isset($hashId) ) { |
| 148 | + static function pf_hashdefine( Parser &$parser, $hashId, $value = '', $itemsDelimiter = '/\s*,\s*/', $innerDelimiter = '/\s*;\s*/' ) { |
| 149 | + if( ! isset( $hashId ) ) { |
91 | 150 | return ''; |
92 | | - } |
93 | | - $this->mHashTables[ $hashId ] = array(); |
| 151 | + } |
| 152 | + $store = self::get( $parser ); |
| 153 | + |
| 154 | + $store->setHash( $hashId ); |
94 | 155 | |
95 | 156 | if( $value !== '' ) { |
96 | | - |
97 | 157 | // Build delimiters: |
98 | | - if ( ! $this->isValidRegEx($itemsDelimiter,'/') ) |
| 158 | + if ( ! self::isValidRegEx($itemsDelimiter,'/') ) { |
99 | 159 | $itemsDelimiter = '/\s*' . preg_quote( $itemsDelimiter, '/' ) . '\s*/'; |
| 160 | + } |
100 | 161 | |
101 | | - if ( ! $this->isValidRegEx($innerDelimiter,'/') ) |
| 162 | + if ( ! self::isValidRegEx($innerDelimiter,'/') ) { |
102 | 163 | $innerDelimiter = '/\s*' . preg_quote( $innerDelimiter, '/' ) . '\s*/'; |
| 164 | + } |
103 | 165 | |
104 | 166 | $items = preg_split( $itemsDelimiter, $value ); // All hash Items |
105 | 167 | |
106 | | - foreach ( $items as $itemName => $itemVal ) |
107 | | - { |
108 | | - $hashPair = preg_split( $innerDelimiter, $itemVal, 2 ); |
| 168 | + foreach ( $items as $item ) { |
| 169 | + $hashPair = preg_split( $innerDelimiter, $item, 2 ); |
109 | 170 | |
110 | | - if( count($hashPair) < 2 ) |
111 | | - $this->mHashTables[ $hashId ][ $itemVal ] = ''; // only hash-Name given, could be even '', no value |
112 | | - else |
113 | | - $this->mHashTables[ $hashId ][ $hashPair[0] ] = $hashPair[1]; |
| 171 | + if( count($hashPair) < 2 ) { |
| 172 | + // only hash-Name given, could be even '', no value |
| 173 | + $store->setHashValue( $hashId, $item, '' ); |
| 174 | + } else { |
| 175 | + $store->setHashValue( $hashId, $hashPair[0], $hashPair[1] ); |
| 176 | + } |
114 | 177 | } |
115 | 178 | } |
116 | 179 | |
— | — | @@ -119,11 +182,12 @@ |
120 | 183 | /** |
121 | 184 | * Returns the value of the hash table item identified by a given item name. |
122 | 185 | */ |
123 | | - function hashvalue( &$parser, $hashId, $key, $default = '' ) { |
124 | | - if( !isset($hashId) || !isset($key) ) |
| 186 | + static function pf_hashvalue( Parser &$parser, $hashId, $key, $default = '' ) { |
| 187 | + if( ! isset( $hashId ) || ! isset( $key ) ) { |
125 | 188 | return ''; |
| 189 | + } |
126 | 190 | |
127 | | - $value = $this->getHashValue( $hashId, $key, '' ); |
| 191 | + $value = self::get( $parser )->getHashValue( $hashId, $key, '' ); |
128 | 192 | |
129 | 193 | if( $value === '' ) { |
130 | 194 | $value = $default; |
— | — | @@ -135,26 +199,30 @@ |
136 | 200 | /** |
137 | 201 | * Returns the size of a hash table. Returns '' if the table doesn't exist. |
138 | 202 | */ |
139 | | - function hashsize( &$parser, $hashId) { |
140 | | - if( ! isset($hashId) || ! $this->hashExists($hashId) ) { |
| 203 | + static function pf_hashsize( Parser &$parser, $hashId) { |
| 204 | + $store = self::get( $parser ); |
| 205 | + |
| 206 | + /* |
| 207 | + * in old ArrayExtension tradition, return '' if hash doesn't exist. |
| 208 | + * Though it might be a bit confusing in the beginning, we won't need any '#hashexists' function |
| 209 | + */ |
| 210 | + if( ! isset( $hashId ) || ! $store->hashExists( $hashId ) ) { |
141 | 211 | return ''; |
142 | | - } |
143 | | - return count( $this->mHashTables[ $hashId ] ); |
| 212 | + } |
| 213 | + $hash = $store->getHash( $hashId ); |
| 214 | + return count( $hash ); |
144 | 215 | } |
145 | 216 | |
146 | 217 | /** |
147 | 218 | * Returns "1" or the third parameter (if set) if the hash item key 'key' exists inside the hash |
148 | 219 | * table 'hashId'. Otherwise the output will be a void string or the fourth (if set). |
149 | 220 | */ |
150 | | - function hashkeyexists( Parser &$parser, PPFrame $frame, $args ) { |
| 221 | + static function pfObj_hashkeyexists( Parser &$parser, PPFrame $frame, $args ) { |
151 | 222 | $hashId = trim( $frame->expand( $args[0] ) ); |
152 | 223 | $key = isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) : ''; |
153 | | - |
154 | | - // get hash or null: |
155 | | - $hash = $this->getHash( $hashId ); |
156 | | - |
| 224 | + |
157 | 225 | // only expand the one argument needed: |
158 | | - if( $hash !== null && array_key_exists( $key, $hash ) ) { |
| 226 | + if( self::get( $parser )->getHashValue( $hashId, $key ) !== null ) { |
159 | 227 | return isset( $args[2] ) ? trim( $frame->expand( $args[2] ) ) : '1'; // true '1' |
160 | 228 | } |
161 | 229 | else { |
— | — | @@ -167,19 +235,21 @@ |
168 | 236 | * Syntax: |
169 | 237 | * {{#hashprint:hashID |seperator |keyPattern |valuePattern |subject |printOrderArrayId}} |
170 | 238 | */ |
171 | | - function hashprint( Parser &$parser, PPFrame $frame, $args ) { |
| 239 | + static function pfObj_hashprint( Parser &$parser, PPFrame $frame, $args ) { |
172 | 240 | if( ! isset( $args[0] ) ) { |
173 | 241 | return ''; |
174 | 242 | } |
| 243 | + |
175 | 244 | $hashId = trim( $frame->expand( $args[0] ) ); |
176 | | - $values = $this->getHash( $hashId ); |
| 245 | + $values = self::get( $parser )->getHash( $hashId ); |
177 | 246 | |
178 | 247 | if( $values === null ) { |
179 | 248 | return ''; |
180 | 249 | } |
181 | 250 | |
182 | | - // parameter validation: |
183 | | - $seperator = isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) : ', '; |
| 251 | + // parameter validation: |
| 252 | + |
| 253 | + $seperator = isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) : ', '; |
184 | 254 | /* |
185 | 255 | * PPFrame::NO_ARGS and PPFrame::NO_TEMPLATES for expansion make a lot of sense here since the patterns getting replaced |
186 | 256 | * in $subject before $subject is being parsed. So any template or argument influence in the patterns wouldn't make any |
— | — | @@ -228,7 +298,7 @@ |
229 | 299 | */ |
230 | 300 | $rawResult = $parser->preprocessToDom( $rawResult, $frame->isTemplate() ? Parser::PTD_FOR_INCLUSION : 0 ); |
231 | 301 | $rawResult = trim( $frame->expand( $rawResult ) ); |
232 | | - |
| 302 | + |
233 | 303 | $renderedResults[] = $rawResult ; |
234 | 304 | } |
235 | 305 | return array( implode( $seperator, $renderedResults) , 'noparse' => false, 'isHTML' => false ); |
— | — | @@ -238,12 +308,14 @@ |
239 | 309 | * Define an hash filled with all given parameters of the current template. |
240 | 310 | * In case there are no parameters, the hash will be void. |
241 | 311 | */ |
242 | | - function parameterstohash( &$parser, PPFrame $frame, $args) { |
| 312 | + static function pfObj_parameterstohash( &$parser, PPFrame $frame, $args) { |
243 | 313 | if( ! isset( $args[0] ) ) { |
244 | 314 | return ''; |
245 | 315 | } |
| 316 | + $store = self::get( $parser ); |
| 317 | + |
246 | 318 | $hashId = trim( $frame->expand( $args[0] ) ); |
247 | | - $this->mHashTables[ $hashId ] = array(); // create empty hash table |
| 319 | + $store->setHash( $hashId ); // create empty hash table |
248 | 320 | |
249 | 321 | // in case the page is not used as template i.e. when displayed on its own |
250 | 322 | if( ! $frame->isTemplate() ) { |
— | — | @@ -253,7 +325,8 @@ |
254 | 326 | $templateArgs = $frame->getArguments(); |
255 | 327 | |
256 | 328 | foreach ( $templateArgs as $argName => $argVal ) { |
257 | | - $this->mHashTables[ $hashId ][ trim( $argName ) ] = trim( $argVal ); |
| 329 | + // one hash value for each parameter |
| 330 | + $store->setHashValue( $hashId, $argName, $argVal ); |
258 | 331 | } |
259 | 332 | return ''; |
260 | 333 | } |
— | — | @@ -262,16 +335,19 @@ |
263 | 336 | * Resets the hashes given in parameter 1 to n. If there are no parameters given, |
264 | 337 | * the function will reset all hashes. |
265 | 338 | */ |
266 | | - function hashreset( &$parser, $frame, $args) { |
| 339 | + static function pfObj_hashreset( &$parser, $frame, $args) { |
| 340 | + $store = self::get( $parser ); |
| 341 | + |
267 | 342 | // reset all hash tables if no specific tables are given: |
268 | | - if( !isset( $args[0] ) || ( $args[0] === '' && count( $args ) == 1 ) ) { |
269 | | - $this->mHashTables = array(); |
| 343 | + if( ! isset( $args[0] ) || ( $args[0] === '' && count( $args ) == 1 ) ) { |
| 344 | + $store->mHashTables = array(); |
270 | 345 | } |
271 | 346 | else { |
272 | | - foreach ( $args as $arg ) |
273 | | - { |
274 | | - $argVal = trim( $frame->expand($arg) ); |
275 | | - $this->removeHash( $argVal ); |
| 347 | + // reset specific hash tables: |
| 348 | + foreach( $args as $arg ) { |
| 349 | + $hashId = trim( $frame->expand($arg) ); |
| 350 | + $store->unsetHash( $hashId ); |
| 351 | + |
276 | 352 | } |
277 | 353 | } |
278 | 354 | return ''; |
— | — | @@ -283,23 +359,26 @@ |
284 | 360 | * Syntax: |
285 | 361 | * {{#hashinclude:hashID |key1=val1 |key2=val2 |... |key n=val n}} |
286 | 362 | */ |
287 | | - function hashinclude( &$parser, $frame, $args) { |
| 363 | + static function pfObj_hashinclude( &$parser, $frame, $args) { |
288 | 364 | // get hash table ID from first parameter: |
289 | 365 | $hashId = trim( $frame->expand( $args[0] ) ); |
290 | 366 | unset( $args[0] ); |
291 | 367 | |
292 | | - if( !$this->hashExists($hashId) ) |
293 | | - $this->mHashTables[ $hashId ] = array(); |
| 368 | + $store = self::get( $parser ); |
294 | 369 | |
| 370 | + if( ! $store->hashExists($hashId) ) { |
| 371 | + $store->setHash( $hashId ); |
| 372 | + } |
| 373 | + |
295 | 374 | // all following parameters contain hash table keys and values '|key=value' |
296 | | - foreach ( $args as $arg ) |
297 | | - { |
| 375 | + foreach ( $args as $arg ) { |
298 | 376 | $argString = $frame->expand($arg); |
299 | 377 | $argItem = explode( '=', $argString, 2 ); |
300 | | - $argName = trim( $argItem[0] ); |
301 | | - $argVal = ( count( $argItem ) > 1 ) ? trim( $argItem[1] ) : ''; |
| 378 | + $argName = $argItem[0]; |
| 379 | + $argVal = ( count( $argItem ) > 1 ) ? $argItem[1] : ''; |
302 | 380 | |
303 | | - $this->mHashTables[ $hashId ][ $argName ] = $argVal; |
| 381 | + // set the value (this will trim the values as well) |
| 382 | + $store->setHashValue( $hashId, $argName, $argVal ); |
304 | 383 | } |
305 | 384 | return ''; |
306 | 385 | } |
— | — | @@ -309,19 +388,21 @@ |
310 | 389 | * Syntax: |
311 | 390 | * {{#hashexclude:hashID |key1 |key2 |... |key n}} |
312 | 391 | */ |
313 | | - function hashexclude( &$parser, $frame, $args) { |
| 392 | + static function pfObj_hashexclude( &$parser, $frame, $args) { |
314 | 393 | // get hash table ID from first parameter: |
315 | 394 | $hashId = trim( $frame->expand($args[0]) ); |
316 | 395 | unset( $args[0] ); |
317 | 396 | |
318 | | - if( !$this->hashExists($hashId) ) |
319 | | - return''; |
| 397 | + $store = self::get( $parser ); |
320 | 398 | |
| 399 | + if( ! $store->hashExists( $hashId ) ) { |
| 400 | + return''; |
| 401 | + } |
| 402 | + |
321 | 403 | // all following parameters contain hash table keys and values '|key=value' |
322 | | - foreach ( $args as $arg ) |
323 | | - { |
324 | | - $argName = trim( $frame->expand($arg) ); |
325 | | - unset( $this->mHashTables[ $hashId ][ $argName ] ); |
| 404 | + foreach ( $args as $arg ) { |
| 405 | + $argName = trim( $frame->expand($arg) ); |
| 406 | + $store->unsetHashValue( $hashId, $argName ); |
326 | 407 | } |
327 | 408 | return ''; |
328 | 409 | } |
— | — | @@ -331,8 +412,8 @@ |
332 | 413 | * Syntax: |
333 | 414 | * {{#hashmerge:hashID |hash1 |hash2 |... |hash n}} |
334 | 415 | */ |
335 | | - function hashmerge( &$parser, $frame, $args) { |
336 | | - $this->multiHashOperation( $frame, $args, __FUNCTION__, true ); |
| 416 | + static function pfObj_hashmerge( &$parser, $frame, $args) { |
| 417 | + self::get( $parser )->multiHashOperation( $frame, $args, __FUNCTION__, true ); |
337 | 418 | return ''; |
338 | 419 | } |
339 | 420 | private function multi_hashmerge( $hash1, $hash2 = array() ) { |
— | — | @@ -345,8 +426,8 @@ |
346 | 427 | * Syntax: |
347 | 428 | * {{#hashmix:hashID |hash1 |hash2 |... |hash n}} |
348 | 429 | */ |
349 | | - function hashmix( &$parser, $frame, $args) { |
350 | | - $this->multiHashOperation( $frame, $args, __FUNCTION__, false ); |
| 430 | + static function pfObj_hashmix( &$parser, $frame, $args) { |
| 431 | + self::get( $parser )->multiHashOperation( $frame, $args, __FUNCTION__, false ); |
351 | 432 | return ''; |
352 | 433 | } |
353 | 434 | private function multi_hashmix( $hash1, $hash2 ) { |
— | — | @@ -364,8 +445,8 @@ |
365 | 446 | * Syntax: |
366 | 447 | * {{#hashdiff:hashID |hash1 |hash2 |... |hash n}} |
367 | 448 | */ |
368 | | - function hashdiff( &$parser, $frame, $args) { |
369 | | - $this->multiHashOperation( $frame, $args, __FUNCTION__, false ); |
| 449 | + static function pfObj_hashdiff( &$parser, $frame, $args) { |
| 450 | + self::get( $parser )->multiHashOperation( $frame, $args, __FUNCTION__, false ); |
370 | 451 | return ''; |
371 | 452 | } |
372 | 453 | private function multi_hashdiff( $hash1, $hash2 ) { |
— | — | @@ -379,8 +460,8 @@ |
380 | 461 | * Syntax: |
381 | 462 | * {{#hashintersect:hashID |hash1 |hash2 |... |hash n}} |
382 | 463 | */ |
383 | | - function hashintersect( &$parser, $frame, $args) { |
384 | | - $this->multiHashOperation( $frame, $args, __FUNCTION__, false ); |
| 464 | + static function pfObj_hashintersect( &$parser, $frame, $args) { |
| 465 | + self::get( $parser )->multiHashOperation( $frame, $args, __FUNCTION__, false ); |
385 | 466 | return ''; |
386 | 467 | } |
387 | 468 | private function multi_hashintersect( $hash1, $hash2 ) { |
— | — | @@ -393,10 +474,10 @@ |
394 | 475 | * Syntax: |
395 | 476 | * {{#hashtoarray:valArrayID |hashID |keyArrayID}} |
396 | 477 | */ |
397 | | - function hashtoarray( &$parser, $valArrayId, $hashId, $keyArrayId = null) { |
398 | | - |
399 | | - if( !isset($hashId) || !isset($valArrayId) ) |
| 478 | + static function pf_hashtoarray( Parser &$parser, $valArrayId, $hashId, $keyArrayId = null) { |
| 479 | + if( ! isset( $hashId ) || ! isset( $valArrayId ) ) { |
400 | 480 | return ''; |
| 481 | + } |
401 | 482 | |
402 | 483 | global $wgArrayExtension; |
403 | 484 | |
— | — | @@ -404,22 +485,22 @@ |
405 | 486 | $valArray = array(); |
406 | 487 | $keyArray = array(); |
407 | 488 | |
408 | | - if( $this->hashExists($hashId) ) |
409 | | - { |
410 | | - $hash = $this->mHashTables[ $hashId ]; |
411 | | - |
| 489 | + $hash = self::get( $parser )->getHash( $hashId ); |
| 490 | + |
| 491 | + if( $hash !== null ) { |
412 | 492 | foreach( $hash as $hashKey => $hashVal ) { |
413 | 493 | $valArray[] = $hashVal; |
414 | | - if( $keyArrayId !== null ) |
| 494 | + if( $keyArrayId !== null ) { |
| 495 | + // for additional array with keys |
415 | 496 | $keyArray[] = $hashKey; |
| 497 | + } |
416 | 498 | } |
417 | 499 | } |
418 | 500 | |
419 | | - |
420 | | - |
421 | | - $wgArrayExtension->mArrayExtension[ $valArrayId ] = $valArray; |
| 501 | + $wgArrayExtension->mArrayExtension[ trim( $valArrayId ) ] = $valArray; |
422 | 502 | if( $keyArrayId !== null ) { |
423 | | - $wgArrayExtension->mArrayExtension[ $keyArrayId ] = $keyArray; |
| 503 | + // additional array for hash keys: |
| 504 | + $wgArrayExtension->mArrayExtension[ trim( $keyArrayId ) ] = $keyArray; |
424 | 505 | } |
425 | 506 | return ''; |
426 | 507 | } |
— | — | @@ -432,15 +513,15 @@ |
433 | 514 | * The 'keysArrayID' is optional. If set the items in this array will end up as keys in |
434 | 515 | * the new hash table. |
435 | 516 | */ |
436 | | - function arraytohash( &$parser, $hashId, $valArrId, $keyArrId = null) { |
437 | | - |
438 | | - if( !isset($hashId) ) |
| 517 | + static function pf_arraytohash( Parser &$parser, $hashId, $valArrId, $keyArrId = null) { |
| 518 | + if( ! isset( $hashId) ) { |
439 | 519 | return ''; |
| 520 | + } |
440 | 521 | |
441 | 522 | global $wgArrayExtension; |
442 | 523 | |
443 | 524 | // if array doesn't exist |
444 | | - if( !array_key_exists( $valArrId, $wgArrayExtension->mArrayExtension ) ) |
| 525 | + if( ! array_key_exists( $valArrId, $wgArrayExtension->mArrayExtension ) ) |
445 | 526 | $arrExtValArray = array(); |
446 | 527 | else |
447 | 528 | $arrExtValArray = $wgArrayExtension->mArrayExtension[ $valArrId ]; |
— | — | @@ -448,7 +529,7 @@ |
449 | 530 | $newHash = array(); |
450 | 531 | |
451 | 532 | // if no key array is given OR the key array doesn't exist |
452 | | - if( !isset($keyArrId) || !array_key_exists( $keyArrId, $wgArrayExtension->mArrayExtension ) ) |
| 533 | + if( ! isset($keyArrId) || ! array_key_exists( $keyArrId, $wgArrayExtension->mArrayExtension ) ) |
453 | 534 | { |
454 | 535 | // Copy the whole array. Result will be a hash with numeric keys |
455 | 536 | $newHash = $arrExtValArray; |
— | — | @@ -459,11 +540,12 @@ |
460 | 541 | $valArray = $arrExtValArray; |
461 | 542 | |
462 | 543 | for( $i=0; $i < count($keyArray); $i++ ) { |
463 | | - $currVal = array_key_exists( $i, $valArray ) ? $valArray[$i] : ''; |
464 | | - $newHash[ $keyArray[$i] ] = $currVal; |
| 544 | + $currVal = array_key_exists( $i, $valArray ) ? trim( $valArray[ $i ] ) : ''; |
| 545 | + $newHash[ $keyArray[ $i ] ] = $currVal; |
465 | 546 | } |
466 | 547 | } |
467 | | - $this->mHashTables[ $hashId ] = $newHash; |
| 548 | + |
| 549 | + self::get( $parser )->mHashTables[ $hashId ] = $newHash; |
468 | 550 | return ''; |
469 | 551 | } |
470 | 552 | |
— | — | @@ -475,18 +557,22 @@ |
476 | 558 | * Syntax: |
477 | 559 | * {{#hashtotemplate:template |hash |pipe-replacer}} |
478 | 560 | */ |
479 | | - function hashtotemplate( &$parser, $frame, $args ) { |
480 | | - if( ! isset($args[0]) || ! isset($args[1]) ) |
| 561 | + static function pfObj_hashtotemplate( Parser &$parser, $frame, $args ) { |
| 562 | + if( ! isset( $args[0] ) || ! isset( $args[1] ) ) { |
481 | 563 | return ''; |
| 564 | + } |
482 | 565 | |
| 566 | + $store = self::get( $parser ); |
| 567 | + |
483 | 568 | $template = trim( $frame->expand($args[0] ) ); |
484 | 569 | $hashId = trim( $frame->expand($args[1] ) ); |
485 | 570 | $pipeReplacer = isset($args[2]) ? trim( $frame->expand( $args[2] ) ) : '|'; |
486 | 571 | |
487 | | - if( !$this->hashExists( $hashId ) ) |
| 572 | + if( ! $store->hashExists( $hashId ) ) { |
488 | 573 | return ''; |
| 574 | + } |
489 | 575 | |
490 | | - $params = $this->mHashTables[ $hashId ]; |
| 576 | + $params = $store->getHash( $hashId ); |
491 | 577 | $templateCall = '{{' . $template; |
492 | 578 | |
493 | 579 | foreach ($params as $paramKey => $paramValue){ |
— | — | @@ -504,92 +590,12 @@ |
505 | 591 | return array( $result , 'noparse' => true, 'isHTML' => false ); |
506 | 592 | } |
507 | 593 | |
508 | | - /* ============================ */ |
509 | | - /* ============================ */ |
510 | | - /* === === */ |
511 | | - /* === HELPER FUNCTIONS === */ |
512 | | - /* === === */ |
513 | | - /* ============================ */ |
514 | | - /* ============================ */ |
515 | 594 | |
516 | | - /** |
517 | | - * Returns a value within a hash. If key or hash doesn't exist, this will return null |
518 | | - * or another predefined default. |
519 | | - * |
520 | | - * @since 0.7 |
521 | | - * |
522 | | - * @param string $hashId |
523 | | - * @param string $key |
524 | | - * @param mixed $default value to return in cas the value doesn't exist. null by default. |
525 | | - * @return string |
526 | | - */ |
527 | | - public function getHashValue( $hashId = '', $key = '', $default = null ) { |
528 | | - $hashId = trim( $hashId ); |
529 | | - if( $this->hashExists( $hashId ) && array_key_exists( $key, $this->mHashTables[ $hashId ] ) ) |
530 | | - return $this->mHashTables[ $hashId ][ $key ]; |
531 | | - else |
532 | | - return $default; |
533 | | - } |
534 | | - |
535 | | - /** |
536 | | - * Returns an hash identified by $hashId. If it doesn't exist this will return null. |
537 | | - * |
538 | | - * @since 0.6 |
539 | | - * |
540 | | - * @param string $hashId |
541 | | - * @return array|null |
542 | | - */ |
543 | | - public function getHash( $hashId = '' ) { |
544 | | - if( $this->hashExists( $hashId ) ) |
545 | | - return $this->mHashTables[ $hashId ]; |
546 | | - else |
547 | | - return null; |
548 | | - } |
| 595 | + ################## |
| 596 | + # Private Helper # |
| 597 | + ################## |
549 | 598 | |
550 | 599 | /** |
551 | | - * Returns whether a hash exists within the page scope. |
552 | | - * |
553 | | - * @since 0.6 |
554 | | - * |
555 | | - * @param string $hashId |
556 | | - * @return boolean |
557 | | - */ |
558 | | - public function hashExists( $hashId = '' ) { |
559 | | - return array_key_exists( trim( $hashId ), $this->mHashTables ); |
560 | | - } |
561 | | - |
562 | | - /** |
563 | | - * This will add a new hash or overwrite an existing one. Values should be delliverd as array |
564 | | - * values in form of a string. |
565 | | - * |
566 | | - * @since 0.6 |
567 | | - * |
568 | | - * @param string $hashId |
569 | | - * @param array $hashTable |
570 | | - */ |
571 | | - public function createHash( $hashId = '', $hashTable = array() ) { |
572 | | - $this->mHashTables[ trim( $hashId ) ] = $hashTable; |
573 | | - } |
574 | | - |
575 | | - /** |
576 | | - * Removes an existing hash. If the hash doesn't exist this will return false, otherwise true. |
577 | | - * |
578 | | - * @since 0.6 |
579 | | - * |
580 | | - * @param string $hashId |
581 | | - * @return boolean |
582 | | - */ |
583 | | - public function removeHash( $hashId = '' ) { |
584 | | - $hashId = trim( $hashId ); |
585 | | - if( $this->hashExists( $hashId ) ) { |
586 | | - unset( $this->mHashTables[ $hashId ] ); |
587 | | - return true; |
588 | | - } else { |
589 | | - return false; |
590 | | - } |
591 | | - } |
592 | | - |
593 | | - /** |
594 | 600 | * Base function for operations with multiple hashes given thru n parameters |
595 | 601 | * $operationFunc expects a function name prefix (suffix 'multi_') with two parameters |
596 | 602 | * $hash1 and $hash2 which will perform an action between $hash1 and hash2 which will |
— | — | @@ -608,7 +614,7 @@ |
609 | 615 | $lastHash = null; |
610 | 616 | $operationRan = false; |
611 | 617 | $finalHashId = trim( $frame->expand( $args[0] ) ); |
612 | | - $operationFunc = 'multi_' . $operationFunc; |
| 618 | + $operationFunc = 'multi_' . preg_replace( '/^pfObj_/', '', $operationFunc ); |
613 | 619 | |
614 | 620 | // For all hashes given in parameters 2 to n (ignore 1 because this is the new hash) |
615 | 621 | for( $i = 1; $i < count( $args ); $i++ ) |
— | — | @@ -617,7 +623,7 @@ |
618 | 624 | continue; |
619 | 625 | } |
620 | 626 | $argHashId = trim( $frame->expand( $args[ $i ] ) ); |
621 | | - |
| 627 | + |
622 | 628 | if( $this->hashExists( $argHashId ) ) { |
623 | 629 | $argHash = $this->mHashTables[ $argHashId ]; |
624 | 630 | if( $lastHash === null ) { |
— | — | @@ -629,58 +635,178 @@ |
630 | 636 | $lastHash = $this->{ $operationFunc }( $lastHash, $argHash ); // perform action between last and current hash |
631 | 637 | $operationRan = true; |
632 | 638 | } |
633 | | - } |
| 639 | + } |
634 | 640 | } |
| 641 | + |
635 | 642 | // in case no hash was given at all: |
636 | 643 | if( $lastHash === null ) { |
637 | 644 | $lastHash = array(); |
638 | 645 | } |
| 646 | + |
639 | 647 | // if the operation didn't run because there was only one or no array: |
640 | 648 | if( $operationRan == false && $runFuncOnSingleHash ) { |
641 | 649 | $lastHash = $this->{ $operationFunc }( $lastHash ); |
642 | 650 | } |
| 651 | + |
643 | 652 | $this->mHashTables[ $finalHashId ] = $lastHash; |
644 | 653 | } |
645 | 654 | |
| 655 | + |
| 656 | + ############## |
| 657 | + # Used Hooks # |
| 658 | + ############## |
| 659 | + |
646 | 660 | /** |
| 661 | + * This will clean up the hash table store after parsing has finished. It will prevent strange things to happen |
| 662 | + * for example during import of several pages or job queue is running for multiple pages. In these cases hashes |
| 663 | + * would become some kind of superglobals, being passed from one page to the other. |
| 664 | + */ |
| 665 | + static function onParserClearState( Parser &$parser ) { |
| 666 | + /** |
| 667 | + * MessageCaches Parser clone will mess things up if we don't reset the entire object. |
| 668 | + * Only resetting the array would unset it in the original object as well! This instead |
| 669 | + * will break the entire reference to the object |
| 670 | + */ |
| 671 | + $parser->mExtHashTables = new self(); |
| 672 | + return true; |
| 673 | + } |
| 674 | + |
| 675 | + |
| 676 | + #################################### |
| 677 | + # Public functions for interaction # |
| 678 | + #################################### |
| 679 | + # |
| 680 | + # public non-parser functions, accessible for |
| 681 | + # other extensions doing interactive stuff |
| 682 | + # with 'HashTables' extension. |
| 683 | + # |
| 684 | + |
| 685 | + /** |
| 686 | + * Convenience function to return the 'HashTables' extensions hash table store connected |
| 687 | + * to a certain Parser object. Each parser has its own store which will be reset after |
| 688 | + * a parsing process [Parser::parse()] has finished. |
| 689 | + * |
| 690 | + * @since 0.8 |
| 691 | + * |
| 692 | + * @param Parser &$parser |
| 693 | + * |
| 694 | + * @return ExtHashTables by reference so we still have the right object after 'ParserClearState' |
| 695 | + */ |
| 696 | + public static function &get( Parser &$parser ) { |
| 697 | + return $parser->mExtHashTables; |
| 698 | + } |
| 699 | + |
| 700 | + /** |
| 701 | + * Returns an hash identified by $hashId. If it doesn't exist this will return null. |
| 702 | + * |
| 703 | + * @since 0.6 |
| 704 | + * |
| 705 | + * @param string $hashId |
| 706 | + * |
| 707 | + * @return array|null |
| 708 | + */ |
| 709 | + public function getHash( $hashId ) { |
| 710 | + if( $this->hashExists( $hashId ) ) { |
| 711 | + return $this->mHashTables[ $hashId ]; |
| 712 | + } else { |
| 713 | + return null; |
| 714 | + } |
| 715 | + } |
| 716 | + |
| 717 | + /** |
| 718 | + * This will add a new hash or overwrite an existing one. Values should be delliverd as array |
| 719 | + * values in form of a string. All values will be converted to strings, trim() will iterate |
| 720 | + * over them. |
| 721 | + * |
| 722 | + * @since 0.8 |
| 723 | + * |
| 724 | + * @param string $hashId |
| 725 | + * @param array $hashTable |
| 726 | + */ |
| 727 | + public function setHash( $hashId, $hashTable = array() ) { |
| 728 | + $hashTable = array_map( 'trim', $hashTable ); // make it all string and trim |
| 729 | + $this->mHashTables[ trim( $hashId ) ] = $hashTable; |
| 730 | + } |
| 731 | + |
| 732 | + /** |
| 733 | + * Returns a value within a hash. If key or hash doesn't exist, this will return null |
| 734 | + * or another predefined default. |
| 735 | + * |
| 736 | + * @since 0.7 |
| 737 | + * |
| 738 | + * @param string $hashId |
| 739 | + * @param string $key |
| 740 | + * @param mixed $default value to return in cas the value doesn't exist. null by default. |
| 741 | + * |
| 742 | + * @return string |
| 743 | + */ |
| 744 | + public function getHashValue( $hashId, $key, $default = null ) { |
| 745 | + $hashId = trim( $hashId ); |
| 746 | + if( $this->hashExists( $hashId ) && array_key_exists( $key, $this->mHashTables[ $hashId ] ) ) { |
| 747 | + return $this->mHashTables[ $hashId ][ $key ]; |
| 748 | + } else { |
| 749 | + return $default; |
| 750 | + } |
| 751 | + } |
| 752 | + |
| 753 | + /** |
| 754 | + * Rest a specific hash tables entry. |
| 755 | + * |
| 756 | + * @since 0.8 |
| 757 | + * |
| 758 | + * @param type $hashId |
| 759 | + * @param type $key |
| 760 | + */ |
| 761 | + public function unsetHashValue( $hashId, $key ) { |
| 762 | + unset( $this->mHashTables[ $hashId ][ $key ] ); |
| 763 | + } |
| 764 | + |
| 765 | + /** |
| 766 | + * Set a value of a hash table to a specific value. If the hash table doesn't exist already, |
| 767 | + * it will be created. |
| 768 | + * |
| 769 | + * @since 0.8 |
| 770 | + * |
| 771 | + * @param string $hashId |
| 772 | + * @param array $hashTable |
| 773 | + */ |
| 774 | + public function setHashValue( $hashId, $key, $value ) { |
| 775 | + $this->mHashTables[ trim( $hashId ) ][ trim( $key ) ] = trim( $value ); |
| 776 | + } |
| 777 | + |
| 778 | + /** |
| 779 | + * Returns whether a hash exists within the page scope. |
| 780 | + * |
| 781 | + * @since 0.6 |
| 782 | + * |
| 783 | + * @param string $hashId |
| 784 | + * |
| 785 | + * @return boolean |
| 786 | + */ |
| 787 | + public function hashExists( $hashId ) { |
| 788 | + return array_key_exists( trim( $hashId ), $this->mHashTables ); |
| 789 | + } |
| 790 | + |
| 791 | + /** |
| 792 | + * Allows to unset a certain variable |
| 793 | + * |
| 794 | + * @since 0.8 |
| 795 | + * |
| 796 | + * @param type $varName |
| 797 | + */ |
| 798 | + public function unsetHash( $hashId ) { |
| 799 | + unset( $this->mHashTables[ $hashId ] ); |
| 800 | + } |
| 801 | + |
| 802 | + /** |
647 | 803 | * Decides for the given $pattern whether its a valid regular expression acceptable for |
648 | 804 | * HashTables parser functions or not. |
649 | 805 | * |
650 | 806 | * @param string $pattern regular expression including delimiters and optional flags |
651 | 807 | * @return boolean |
652 | 808 | */ |
653 | | - function isValidRegEx( $pattern ) { |
| 809 | + static function isValidRegEx( $pattern ) { |
654 | 810 | return preg_match( '/^([\\/\\|%]).*\\1[imsSuUx]*$/', $pattern ); |
655 | 811 | } |
656 | | -} |
657 | | - |
658 | | - |
659 | | - |
660 | | -function efHashTablesParserFirstCallInit( Parser &$parser ) { |
661 | | - global $wgHashTables, $wgArrayExtension; |
662 | | - |
663 | | - $wgHashTables = new ExtHashTables(); |
664 | | - |
665 | | - $parser->setFunctionHook( 'hashdefine', array( &$wgHashTables, 'hashdefine' ) ); |
666 | | - $parser->setFunctionHook( 'hashvalue', array( &$wgHashTables, 'hashvalue' ) ); |
667 | | - $parser->setFunctionHook( 'hashsize', array( &$wgHashTables, 'hashsize' ) ); |
668 | | - $parser->setFunctionHook( 'hashkeyexists', array( &$wgHashTables, 'hashkeyexists' ), SFH_OBJECT_ARGS ); |
669 | | - $parser->setFunctionHook( 'hashprint', array( &$wgHashTables, 'hashprint' ), SFH_OBJECT_ARGS ); |
670 | | - $parser->setFunctionHook( 'parameterstohash', array( &$wgHashTables, 'parameterstohash' ), SFH_OBJECT_ARGS ); |
671 | | - $parser->setFunctionHook( 'hashtotemplate', array( &$wgHashTables, 'hashtotemplate' ), SFH_OBJECT_ARGS ); |
672 | | - $parser->setFunctionHook( 'hashinclude', array( &$wgHashTables, 'hashinclude' ), SFH_OBJECT_ARGS ); |
673 | | - $parser->setFunctionHook( 'hashexclude', array( &$wgHashTables, 'hashexclude' ), SFH_OBJECT_ARGS ); |
674 | | - $parser->setFunctionHook( 'hashreset', array( &$wgHashTables, 'hashreset' ), SFH_OBJECT_ARGS ); |
675 | | - $parser->setFunctionHook( 'hashmerge', array( &$wgHashTables, 'hashmerge' ), SFH_OBJECT_ARGS ); |
676 | | - $parser->setFunctionHook( 'hashmix', array( &$wgHashTables, 'hashmix' ), SFH_OBJECT_ARGS ); |
677 | | - $parser->setFunctionHook( 'hashdiff', array( &$wgHashTables, 'hashdiff' ), SFH_OBJECT_ARGS ); |
678 | | - $parser->setFunctionHook( 'hashintersect', array( &$wgHashTables, 'hashintersect' ), SFH_OBJECT_ARGS ); |
679 | 812 | |
680 | | - // if array extension is available, rgister array-hash interactions: |
681 | | - if( isset( $wgArrayExtension ) ) { |
682 | | - $parser->setFunctionHook( 'hashtoarray', array( &$wgHashTables, 'hashtoarray' ) ); |
683 | | - $parser->setFunctionHook( 'arraytohash', array( &$wgHashTables, 'arraytohash' ) ); |
684 | | - } |
685 | | - |
686 | | - return true; |
687 | 813 | } |
Index: trunk/extensions/HashTables/RELEASE-NOTES |
— | — | @@ -1,7 +1,15 @@ |
2 | 2 | Changelog: |
3 | 3 | ========== |
| 4 | + |
| 5 | + * (trunk) Version 0.8 |
| 6 | + This release has lots of internal changes in it. All functions representing a parser funcdtions now |
| 7 | + use a 'pf_' or 'pfObj_' prefix, are declared static and there are new/changed public functions for |
| 8 | + interaction with 'HashTables' extension. |
| 9 | + - Compatbility with other extensions increased by using one hash tables store per Parser instance. |
| 10 | + - Inclusion of special pages in the middle of the page won't reset all defined hash tables anymore. |
| 11 | + |
4 | 12 | |
5 | | - * November 4, 2011 version 0.7 |
| 13 | + * November 4, 2011 -- Version 0.7 |
6 | 14 | - buggy behavior in 'hashkeyexists' which led to expanding both arguments 'yes' and 'no' in |
7 | 15 | case custom arguments were given is solved. Now only the one actual case is being expanded. |
8 | 16 | - 'hashtotemplate' now changes '{' to '{' since '{{' made some problems in some cases. |
— | — | @@ -14,48 +22,48 @@ |
15 | 23 | - distributed under ISC license. |
16 | 24 | |
17 | 25 | |
18 | | - * August 3, 2011 version 0.6.3 |
| 26 | + * August 3, 2011 -- Version 0.6.3 |
19 | 27 | - minor bug in 'parameterstohash' function solved. |
20 | 28 | |
21 | | - * March 29, 2011 version 0.6.2 |
| 29 | + * March 29, 2011 -- Version 0.6.2 |
22 | 30 | - 'hashtotemplate' has a new parameter to define a string which will replace pipes '|'. Can be |
23 | 31 | useful to preserve links. |
24 | 32 | |
25 | | - * January 24, 2011 version 0.6.1 |
| 33 | + * January 24, 2011 -- Version 0.6.1 |
26 | 34 | - Constant VERSION and function getHash() added to class ExtHashTables. |
27 | 35 | |
28 | | - * January 19, 2011 version 0.6 |
| 36 | + * January 19, 2011 -- Version 0.6 |
29 | 37 | - New public class methods for creating and removing hash tables. Good for use by other extensions. |
30 | 38 | - New experimental function 'hashtotemplate'. |
31 | 39 | |
32 | 40 | |
33 | | - * August 3, 2010 version 0.5.1 |
| 41 | + * August 3, 2010 -- Version 0.5.1 |
34 | 42 | - Hashinclude didn't trim key and value so keys with ending space ' ' and values with leading |
35 | 43 | space were possible when defining something like {{#hashinclude: a | a = 1}} |
36 | 44 | |
37 | | - * August 1, 2010 version 0.5 |
| 45 | + * August 1, 2010 -- Version 0.5 |
38 | 46 | - New parameter for function 'hashtoarray' which allows to specify the name of a second array |
39 | 47 | which will contain the key names. |
40 | 48 | - Function 'arraytohash' doesn't mind non existent arrays in parameter 2 anymore. This allows |
41 | 49 | to create an hash table with keys only. |
42 | 50 | |
43 | 51 | |
44 | | - * July 20, 2010 version 0.4 |
| 52 | + * July 20, 2010 -- Version 0.4 |
45 | 53 | - Removed critical bug. Some kind of "Superglobal" HashTables on page imports and job queue jobs. |
46 | 54 | Values were passed from one page to another page. |
47 | 55 | |
48 | 56 | |
49 | | - * June 11, 2010 version 0.3 |
| 57 | + * June 11, 2010 -- Version 0.3 |
50 | 58 | - Third parameter for 'arraytohash' allows to set a key array. |
51 | 59 | - New function 'hashkeyexists'. |
52 | 60 | |
53 | 61 | |
54 | | - * June 6, 2010 version 0.2 |
| 62 | + * June 6, 2010 -- Version 0.2 |
55 | 63 | - New functions 'hashmerge', 'hashmix', 'hashdiff', 'hashinclude' and 'hashexclude'. |
56 | 64 | - New functions if 'ArrayExtension' is available in the wiki: 'hashtoarray' and 'arraytohash'. |
57 | 65 | - New parameter for 'hashprint' which allows to define the print order thru an array. |
58 | 66 | |
59 | 67 | |
60 | | - * Mai 30, 2010 version 0.1 |
| 68 | + * Mai 30, 2010 -- Version 0.1 |
61 | 69 | - First version of HashTables featuring the functions 'hashdefine', 'hashvalue', 'hashsize', |
62 | 70 | 'hashprint', 'hashreset' and 'parameterstohash'. |
Index: trunk/extensions/HashTables/README |
— | — | @@ -1,6 +1,6 @@ |
2 | 2 | == About == |
3 | 3 | |
4 | | -The ''HashTables'' extension Enhances the parser with hash table functions and a function |
| 4 | +The 'HashTables' extension Enhances the parser with hash table functions and a function |
5 | 5 | to store all parameters given to a template. |
6 | 6 | |
7 | 7 | * Website: http://www.mediawiki.org/wiki/Extension:HashTables |
— | — | @@ -20,7 +20,7 @@ |
21 | 21 | |
22 | 22 | == Contributing == |
23 | 23 | |
24 | | -If you have bug reports or feature requests, please add them to the ''HashTables'' |
| 24 | +If you have bug reports or feature requests, please add them to the 'HashTables' |
25 | 25 | Talk page [0]. You can also send them to Daniel Werner < danweetz@web.de > |
26 | 26 | |
27 | 27 | [0] http://www.mediawiki.org/w/index.php?title=Extension_talk:HashTables |