r103474 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r103473‎ | r103474 | r103475 >
Date:16:41, 17 November 2011
Author:danwe
Status:deferred
Tags:
Comment:
Following Variables 2.0, we now use one hash tables store per Parser object as well. All parser functions representing functions are static now and have a prefix 'pf_' or 'pfObj_'.
Modified paths:
  • /trunk/extensions/HashTables/HashTables.php (modified) (history)
  • /trunk/extensions/HashTables/README (modified) (history)
  • /trunk/extensions/HashTables/RELEASE-NOTES (modified) (history)

Diff [purge]

Index: trunk/extensions/HashTables/HashTables.php
@@ -4,7 +4,7 @@
55 * Defines a subset of parser functions to handle hash tables. Inspired by the ArrayExtension
66 * (http://www.mediawiki.org/wiki/Extension:ArrayExtension).
77 *
8 - * @version: 0.7
 8+ * @version: 0.8 alpha
99 * @author: Daniel Werner < danweetz@web.de >
1010 * @license: ISC license
1111 *
@@ -24,9 +24,7 @@
2525 *
2626 */
2727
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(); }
3129
3230 $wgExtensionCredits['parserhook'][] = array(
3331 'path' => __FILE__,
@@ -37,14 +35,14 @@
3836 'url' => 'http://www.mediawiki.org/wiki/Extension:HashTables',
3937 );
4038
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';
4442
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';
4746
48 -unset( $dir );
4947
5048 /**
5149 * Extension class with all the hash table functionality
@@ -58,7 +56,7 @@
5957 *
6058 * @var string
6159 */
62 - const VERSION = '0.7';
 60+ const VERSION = '0.8 alpha';
6361
6462 /**
6563 * @since 0.1
@@ -73,43 +71,108 @@
7472 $wgHooks['ParserClearState'][] = &$this;
7573 }
7674
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+ }
82120
83121 /**
 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+ /**
84143 * Define an hash by a list of 'values' deliminated by 'itemsDelimiter'.
85144 * Hash keys and their values are deliminated by 'innerDelimiter'.
86145 * Both delimiters can be perl regular expression patterns.
87146 * Syntax: {{#hashdefine:hashId |values |itemsDelimiter |innerDelimiter}}
88147 */
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 ) ) {
91150 return '';
92 - }
93 - $this->mHashTables[ $hashId ] = array();
 151+ }
 152+ $store = self::get( $parser );
 153+
 154+ $store->setHash( $hashId );
94155
95156 if( $value !== '' ) {
96 -
97157 // Build delimiters:
98 - if ( ! $this->isValidRegEx($itemsDelimiter,'/') )
 158+ if ( ! self::isValidRegEx($itemsDelimiter,'/') ) {
99159 $itemsDelimiter = '/\s*' . preg_quote( $itemsDelimiter, '/' ) . '\s*/';
 160+ }
100161
101 - if ( ! $this->isValidRegEx($innerDelimiter,'/') )
 162+ if ( ! self::isValidRegEx($innerDelimiter,'/') ) {
102163 $innerDelimiter = '/\s*' . preg_quote( $innerDelimiter, '/' ) . '\s*/';
 164+ }
103165
104166 $items = preg_split( $itemsDelimiter, $value ); // All hash Items
105167
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 );
109170
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+ }
114177 }
115178 }
116179
@@ -119,11 +182,12 @@
120183 /**
121184 * Returns the value of the hash table item identified by a given item name.
122185 */
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 ) ) {
125188 return '';
 189+ }
126190
127 - $value = $this->getHashValue( $hashId, $key, '' );
 191+ $value = self::get( $parser )->getHashValue( $hashId, $key, '' );
128192
129193 if( $value === '' ) {
130194 $value = $default;
@@ -135,26 +199,30 @@
136200 /**
137201 * Returns the size of a hash table. Returns '' if the table doesn't exist.
138202 */
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 ) ) {
141211 return '';
142 - }
143 - return count( $this->mHashTables[ $hashId ] );
 212+ }
 213+ $hash = $store->getHash( $hashId );
 214+ return count( $hash );
144215 }
145216
146217 /**
147218 * Returns "1" or the third parameter (if set) if the hash item key 'key' exists inside the hash
148219 * table 'hashId'. Otherwise the output will be a void string or the fourth (if set).
149220 */
150 - function hashkeyexists( Parser &$parser, PPFrame $frame, $args ) {
 221+ static function pfObj_hashkeyexists( Parser &$parser, PPFrame $frame, $args ) {
151222 $hashId = trim( $frame->expand( $args[0] ) );
152223 $key = isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) : '';
153 -
154 - // get hash or null:
155 - $hash = $this->getHash( $hashId );
156 -
 224+
157225 // only expand the one argument needed:
158 - if( $hash !== null && array_key_exists( $key, $hash ) ) {
 226+ if( self::get( $parser )->getHashValue( $hashId, $key ) !== null ) {
159227 return isset( $args[2] ) ? trim( $frame->expand( $args[2] ) ) : '1'; // true '1'
160228 }
161229 else {
@@ -167,19 +235,21 @@
168236 * Syntax:
169237 * {{#hashprint:hashID |seperator |keyPattern |valuePattern |subject |printOrderArrayId}}
170238 */
171 - function hashprint( Parser &$parser, PPFrame $frame, $args ) {
 239+ static function pfObj_hashprint( Parser &$parser, PPFrame $frame, $args ) {
172240 if( ! isset( $args[0] ) ) {
173241 return '';
174242 }
 243+
175244 $hashId = trim( $frame->expand( $args[0] ) );
176 - $values = $this->getHash( $hashId );
 245+ $values = self::get( $parser )->getHash( $hashId );
177246
178247 if( $values === null ) {
179248 return '';
180249 }
181250
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] ) ) : ', ';
184254 /*
185255 * PPFrame::NO_ARGS and PPFrame::NO_TEMPLATES for expansion make a lot of sense here since the patterns getting replaced
186256 * in $subject before $subject is being parsed. So any template or argument influence in the patterns wouldn't make any
@@ -228,7 +298,7 @@
229299 */
230300 $rawResult = $parser->preprocessToDom( $rawResult, $frame->isTemplate() ? Parser::PTD_FOR_INCLUSION : 0 );
231301 $rawResult = trim( $frame->expand( $rawResult ) );
232 -
 302+
233303 $renderedResults[] = $rawResult ;
234304 }
235305 return array( implode( $seperator, $renderedResults) , 'noparse' => false, 'isHTML' => false );
@@ -238,12 +308,14 @@
239309 * Define an hash filled with all given parameters of the current template.
240310 * In case there are no parameters, the hash will be void.
241311 */
242 - function parameterstohash( &$parser, PPFrame $frame, $args) {
 312+ static function pfObj_parameterstohash( &$parser, PPFrame $frame, $args) {
243313 if( ! isset( $args[0] ) ) {
244314 return '';
245315 }
 316+ $store = self::get( $parser );
 317+
246318 $hashId = trim( $frame->expand( $args[0] ) );
247 - $this->mHashTables[ $hashId ] = array(); // create empty hash table
 319+ $store->setHash( $hashId ); // create empty hash table
248320
249321 // in case the page is not used as template i.e. when displayed on its own
250322 if( ! $frame->isTemplate() ) {
@@ -253,7 +325,8 @@
254326 $templateArgs = $frame->getArguments();
255327
256328 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 );
258331 }
259332 return '';
260333 }
@@ -262,16 +335,19 @@
263336 * Resets the hashes given in parameter 1 to n. If there are no parameters given,
264337 * the function will reset all hashes.
265338 */
266 - function hashreset( &$parser, $frame, $args) {
 339+ static function pfObj_hashreset( &$parser, $frame, $args) {
 340+ $store = self::get( $parser );
 341+
267342 // 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();
270345 }
271346 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+
276352 }
277353 }
278354 return '';
@@ -283,23 +359,26 @@
284360 * Syntax:
285361 * {{#hashinclude:hashID |key1=val1 |key2=val2 |... |key n=val n}}
286362 */
287 - function hashinclude( &$parser, $frame, $args) {
 363+ static function pfObj_hashinclude( &$parser, $frame, $args) {
288364 // get hash table ID from first parameter:
289365 $hashId = trim( $frame->expand( $args[0] ) );
290366 unset( $args[0] );
291367
292 - if( !$this->hashExists($hashId) )
293 - $this->mHashTables[ $hashId ] = array();
 368+ $store = self::get( $parser );
294369
 370+ if( ! $store->hashExists($hashId) ) {
 371+ $store->setHash( $hashId );
 372+ }
 373+
295374 // all following parameters contain hash table keys and values '|key=value'
296 - foreach ( $args as $arg )
297 - {
 375+ foreach ( $args as $arg ) {
298376 $argString = $frame->expand($arg);
299377 $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] : '';
302380
303 - $this->mHashTables[ $hashId ][ $argName ] = $argVal;
 381+ // set the value (this will trim the values as well)
 382+ $store->setHashValue( $hashId, $argName, $argVal );
304383 }
305384 return '';
306385 }
@@ -309,19 +388,21 @@
310389 * Syntax:
311390 * {{#hashexclude:hashID |key1 |key2 |... |key n}}
312391 */
313 - function hashexclude( &$parser, $frame, $args) {
 392+ static function pfObj_hashexclude( &$parser, $frame, $args) {
314393 // get hash table ID from first parameter:
315394 $hashId = trim( $frame->expand($args[0]) );
316395 unset( $args[0] );
317396
318 - if( !$this->hashExists($hashId) )
319 - return'';
 397+ $store = self::get( $parser );
320398
 399+ if( ! $store->hashExists( $hashId ) ) {
 400+ return'';
 401+ }
 402+
321403 // 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 );
326407 }
327408 return '';
328409 }
@@ -331,8 +412,8 @@
332413 * Syntax:
333414 * {{#hashmerge:hashID |hash1 |hash2 |... |hash n}}
334415 */
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 );
337418 return '';
338419 }
339420 private function multi_hashmerge( $hash1, $hash2 = array() ) {
@@ -345,8 +426,8 @@
346427 * Syntax:
347428 * {{#hashmix:hashID |hash1 |hash2 |... |hash n}}
348429 */
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 );
351432 return '';
352433 }
353434 private function multi_hashmix( $hash1, $hash2 ) {
@@ -364,8 +445,8 @@
365446 * Syntax:
366447 * {{#hashdiff:hashID |hash1 |hash2 |... |hash n}}
367448 */
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 );
370451 return '';
371452 }
372453 private function multi_hashdiff( $hash1, $hash2 ) {
@@ -379,8 +460,8 @@
380461 * Syntax:
381462 * {{#hashintersect:hashID |hash1 |hash2 |... |hash n}}
382463 */
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 );
385466 return '';
386467 }
387468 private function multi_hashintersect( $hash1, $hash2 ) {
@@ -393,10 +474,10 @@
394475 * Syntax:
395476 * {{#hashtoarray:valArrayID |hashID |keyArrayID}}
396477 */
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 ) ) {
400480 return '';
 481+ }
401482
402483 global $wgArrayExtension;
403484
@@ -404,22 +485,22 @@
405486 $valArray = array();
406487 $keyArray = array();
407488
408 - if( $this->hashExists($hashId) )
409 - {
410 - $hash = $this->mHashTables[ $hashId ];
411 -
 489+ $hash = self::get( $parser )->getHash( $hashId );
 490+
 491+ if( $hash !== null ) {
412492 foreach( $hash as $hashKey => $hashVal ) {
413493 $valArray[] = $hashVal;
414 - if( $keyArrayId !== null )
 494+ if( $keyArrayId !== null ) {
 495+ // for additional array with keys
415496 $keyArray[] = $hashKey;
 497+ }
416498 }
417499 }
418500
419 -
420 -
421 - $wgArrayExtension->mArrayExtension[ $valArrayId ] = $valArray;
 501+ $wgArrayExtension->mArrayExtension[ trim( $valArrayId ) ] = $valArray;
422502 if( $keyArrayId !== null ) {
423 - $wgArrayExtension->mArrayExtension[ $keyArrayId ] = $keyArray;
 503+ // additional array for hash keys:
 504+ $wgArrayExtension->mArrayExtension[ trim( $keyArrayId ) ] = $keyArray;
424505 }
425506 return '';
426507 }
@@ -432,15 +513,15 @@
433514 * The 'keysArrayID' is optional. If set the items in this array will end up as keys in
434515 * the new hash table.
435516 */
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) ) {
439519 return '';
 520+ }
440521
441522 global $wgArrayExtension;
442523
443524 // if array doesn't exist
444 - if( !array_key_exists( $valArrId, $wgArrayExtension->mArrayExtension ) )
 525+ if( ! array_key_exists( $valArrId, $wgArrayExtension->mArrayExtension ) )
445526 $arrExtValArray = array();
446527 else
447528 $arrExtValArray = $wgArrayExtension->mArrayExtension[ $valArrId ];
@@ -448,7 +529,7 @@
449530 $newHash = array();
450531
451532 // 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 ) )
453534 {
454535 // Copy the whole array. Result will be a hash with numeric keys
455536 $newHash = $arrExtValArray;
@@ -459,11 +540,12 @@
460541 $valArray = $arrExtValArray;
461542
462543 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;
465546 }
466547 }
467 - $this->mHashTables[ $hashId ] = $newHash;
 548+
 549+ self::get( $parser )->mHashTables[ $hashId ] = $newHash;
468550 return '';
469551 }
470552
@@ -475,18 +557,22 @@
476558 * Syntax:
477559 * {{#hashtotemplate:template |hash |pipe-replacer}}
478560 */
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] ) ) {
481563 return '';
 564+ }
482565
 566+ $store = self::get( $parser );
 567+
483568 $template = trim( $frame->expand($args[0] ) );
484569 $hashId = trim( $frame->expand($args[1] ) );
485570 $pipeReplacer = isset($args[2]) ? trim( $frame->expand( $args[2] ) ) : '&#124;';
486571
487 - if( !$this->hashExists( $hashId ) )
 572+ if( ! $store->hashExists( $hashId ) ) {
488573 return '';
 574+ }
489575
490 - $params = $this->mHashTables[ $hashId ];
 576+ $params = $store->getHash( $hashId );
491577 $templateCall = '{{' . $template;
492578
493579 foreach ($params as $paramKey => $paramValue){
@@ -504,92 +590,12 @@
505591 return array( $result , 'noparse' => true, 'isHTML' => false );
506592 }
507593
508 - /* ============================ */
509 - /* ============================ */
510 - /* === === */
511 - /* === HELPER FUNCTIONS === */
512 - /* === === */
513 - /* ============================ */
514 - /* ============================ */
515594
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+ ##################
549598
550599 /**
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 - /**
594600 * Base function for operations with multiple hashes given thru n parameters
595601 * $operationFunc expects a function name prefix (suffix 'multi_') with two parameters
596602 * $hash1 and $hash2 which will perform an action between $hash1 and hash2 which will
@@ -608,7 +614,7 @@
609615 $lastHash = null;
610616 $operationRan = false;
611617 $finalHashId = trim( $frame->expand( $args[0] ) );
612 - $operationFunc = 'multi_' . $operationFunc;
 618+ $operationFunc = 'multi_' . preg_replace( '/^pfObj_/', '', $operationFunc );
613619
614620 // For all hashes given in parameters 2 to n (ignore 1 because this is the new hash)
615621 for( $i = 1; $i < count( $args ); $i++ )
@@ -617,7 +623,7 @@
618624 continue;
619625 }
620626 $argHashId = trim( $frame->expand( $args[ $i ] ) );
621 -
 627+
622628 if( $this->hashExists( $argHashId ) ) {
623629 $argHash = $this->mHashTables[ $argHashId ];
624630 if( $lastHash === null ) {
@@ -629,58 +635,178 @@
630636 $lastHash = $this->{ $operationFunc }( $lastHash, $argHash ); // perform action between last and current hash
631637 $operationRan = true;
632638 }
633 - }
 639+ }
634640 }
 641+
635642 // in case no hash was given at all:
636643 if( $lastHash === null ) {
637644 $lastHash = array();
638645 }
 646+
639647 // if the operation didn't run because there was only one or no array:
640648 if( $operationRan == false && $runFuncOnSingleHash ) {
641649 $lastHash = $this->{ $operationFunc }( $lastHash );
642650 }
 651+
643652 $this->mHashTables[ $finalHashId ] = $lastHash;
644653 }
645654
 655+
 656+ ##############
 657+ # Used Hooks #
 658+ ##############
 659+
646660 /**
 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+ /**
647803 * Decides for the given $pattern whether its a valid regular expression acceptable for
648804 * HashTables parser functions or not.
649805 *
650806 * @param string $pattern regular expression including delimiters and optional flags
651807 * @return boolean
652808 */
653 - function isValidRegEx( $pattern ) {
 809+ static function isValidRegEx( $pattern ) {
654810 return preg_match( '/^([\\/\\|%]).*\\1[imsSuUx]*$/', $pattern );
655811 }
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 );
679812
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;
687813 }
Index: trunk/extensions/HashTables/RELEASE-NOTES
@@ -1,7 +1,15 @@
22 Changelog:
33 ==========
 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+
412
5 - * November 4, 2011 version 0.7
 13+ * November 4, 2011 -- Version 0.7
614 - buggy behavior in 'hashkeyexists' which led to expanding both arguments 'yes' and 'no' in
715 case custom arguments were given is solved. Now only the one actual case is being expanded.
816 - 'hashtotemplate' now changes '{' to '&#123;' since '{{' made some problems in some cases.
@@ -14,48 +22,48 @@
1523 - distributed under ISC license.
1624
1725
18 - * August 3, 2011 version 0.6.3
 26+ * August 3, 2011 -- Version 0.6.3
1927 - minor bug in 'parameterstohash' function solved.
2028
21 - * March 29, 2011 version 0.6.2
 29+ * March 29, 2011 -- Version 0.6.2
2230 - 'hashtotemplate' has a new parameter to define a string which will replace pipes '|'. Can be
2331 useful to preserve links.
2432
25 - * January 24, 2011 version 0.6.1
 33+ * January 24, 2011 -- Version 0.6.1
2634 - Constant VERSION and function getHash() added to class ExtHashTables.
2735
28 - * January 19, 2011 version 0.6
 36+ * January 19, 2011 -- Version 0.6
2937 - New public class methods for creating and removing hash tables. Good for use by other extensions.
3038 - New experimental function 'hashtotemplate'.
3139
3240
33 - * August 3, 2010 version 0.5.1
 41+ * August 3, 2010 -- Version 0.5.1
3442 - Hashinclude didn't trim key and value so keys with ending space ' ' and values with leading
3543 space were possible when defining something like {{#hashinclude: a | a = 1}}
3644
37 - * August 1, 2010 version 0.5
 45+ * August 1, 2010 -- Version 0.5
3846 - New parameter for function 'hashtoarray' which allows to specify the name of a second array
3947 which will contain the key names.
4048 - Function 'arraytohash' doesn't mind non existent arrays in parameter 2 anymore. This allows
4149 to create an hash table with keys only.
4250
4351
44 - * July 20, 2010 version 0.4
 52+ * July 20, 2010 -- Version 0.4
4553 - Removed critical bug. Some kind of "Superglobal" HashTables on page imports and job queue jobs.
4654 Values were passed from one page to another page.
4755
4856
49 - * June 11, 2010 version 0.3
 57+ * June 11, 2010 -- Version 0.3
5058 - Third parameter for 'arraytohash' allows to set a key array.
5159 - New function 'hashkeyexists'.
5260
5361
54 - * June 6, 2010 version 0.2
 62+ * June 6, 2010 -- Version 0.2
5563 - New functions 'hashmerge', 'hashmix', 'hashdiff', 'hashinclude' and 'hashexclude'.
5664 - New functions if 'ArrayExtension' is available in the wiki: 'hashtoarray' and 'arraytohash'.
5765 - New parameter for 'hashprint' which allows to define the print order thru an array.
5866
5967
60 - * Mai 30, 2010 version 0.1
 68+ * Mai 30, 2010 -- Version 0.1
6169 - First version of HashTables featuring the functions 'hashdefine', 'hashvalue', 'hashsize',
6270 'hashprint', 'hashreset' and 'parameterstohash'.
Index: trunk/extensions/HashTables/README
@@ -1,6 +1,6 @@
22 == About ==
33
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
55 to store all parameters given to a template.
66
77 * Website: http://www.mediawiki.org/wiki/Extension:HashTables
@@ -20,7 +20,7 @@
2121
2222 == Contributing ==
2323
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'
2525 Talk page [0]. You can also send them to Daniel Werner < danweetz@web.de >
2626
2727 [0] http://www.mediawiki.org/w/index.php?title=Extension_talk:HashTables

Status & tagging log