Index: trunk/extensions/HashTables/HashTables.i18n.magic.php |
— | — | @@ -0,0 +1,45 @@ |
| 2 | +<?php |
| 3 | +#coding: utf-8 |
| 4 | + |
| 5 | +/** |
| 6 | + * Internationalization file for magic words of the 'HashTables' extension. |
| 7 | + * |
| 8 | + * @since 0.6.3 |
| 9 | + * |
| 10 | + * @file HashTables.i18n.magic.php |
| 11 | + * @ingroup HashTables |
| 12 | + * @author Daniel Werner < danweetz@web.de > |
| 13 | + */ |
| 14 | + |
| 15 | +$magicWords = array(); |
| 16 | + |
| 17 | +$magicWords['en'] = array( |
| 18 | + |
| 19 | + # hash construction: |
| 20 | + 'hashdefine' => array( 0, 'hashdefine' ), |
| 21 | + 'parameterstohash' => array( 0, 'parameterstohash' ), |
| 22 | + |
| 23 | + # output: |
| 24 | + 'hashprint' => array( 0, 'hashprint' ), |
| 25 | + 'hashvalue' => array( 0, 'hashvalue' ), |
| 26 | + 'hashsize' => array( 0, 'hashsize' ), |
| 27 | + 'hashkeyexists' => array( 0, 'hashkeyexists' ), |
| 28 | + |
| 29 | + # Alteration: |
| 30 | + 'hashinclude' => array( 0, 'hashinclude' ), |
| 31 | + 'hashexclude' => array( 0, 'hashexclude' ), |
| 32 | + 'hashreset' => array( 0, 'hashreset' ), |
| 33 | + |
| 34 | + # Interaction between hash tables: |
| 35 | + 'hashmerge' => array( 0, 'hashmerge' ), |
| 36 | + 'hashmix' => array( 0, 'hashmix' ), |
| 37 | + 'hashdiff' => array( 0, 'hashdiff' ), |
| 38 | + 'hashintersect' => array( 0, 'hashintersect' ), |
| 39 | + |
| 40 | + # Interaction with 'ArrayExtension': |
| 41 | + 'hashtoarray' => array( 0, 'hashtoarray' ), |
| 42 | + 'arraytohash' => array( 0, 'arraytohash' ), |
| 43 | + |
| 44 | + # Experimental: |
| 45 | + 'hashtotemplate' => array( 0, 'hashtotemplate' ), |
| 46 | +); |
Property changes on: trunk/extensions/HashTables/HashTables.i18n.magic.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 47 | + native |
Index: trunk/extensions/HashTables/HashTables.i18n.php |
— | — | @@ -0,0 +1,28 @@ |
| 2 | +<?php |
| 3 | +#coding: utf-8 |
| 4 | + |
| 5 | +/** |
| 6 | + * Internationalization file of the 'HashTables' extension. |
| 7 | + * |
| 8 | + * @since 0.6.3 |
| 9 | + * |
| 10 | + * @file HashTables.i18n.php |
| 11 | + * @ingroup HashTables |
| 12 | + * @author Daniel Werner < danweetz@web.de > |
| 13 | + */ |
| 14 | + |
| 15 | +$messages = array(); |
| 16 | + |
| 17 | +/** English |
| 18 | + * @author Daniel Werner |
| 19 | + */ |
| 20 | +$messages['en'] = array( |
| 21 | + 'hashtables-desc' => 'Parser functions allowing to work with hash tables in an article scoped context', |
| 22 | +); |
| 23 | + |
| 24 | +/** German |
| 25 | + * @author Daniel Werner |
| 26 | + */ |
| 27 | +$messages['de'] = array( |
| 28 | + 'hashtables-desc' => 'Bietet Parser-Funktionen zur Verwendung Assoziativer Datenfelder (Hashes) in Wiki-Artikeln', |
| 29 | +); |
Property changes on: trunk/extensions/HashTables/HashTables.i18n.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 30 | + native |
Index: trunk/extensions/HashTables/HashTables.php |
— | — | @@ -0,0 +1,668 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Defines a subset of parser functions to handle hash tables. Inspired by the ArrayExtension |
| 6 | + * (http://www.mediawiki.org/wiki/Extension:ArrayExtension). |
| 7 | + * |
| 8 | + * @version: 0.6.4 alpha |
| 9 | + * @author: Daniel Werner < danweetz@web.de > |
| 10 | + * |
| 11 | + * Documentation: http://www.mediawiki.org/wiki/Extension:HashTables |
| 12 | + * Support: http://www.mediawiki.org/wiki/Extension_talk:HashTables |
| 13 | + * Source code: http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/HashTables |
| 14 | + * |
| 15 | + * @file HashTables.php |
| 16 | + * @ingroup HashTables |
| 17 | + * |
| 18 | + * @ToDo: |
| 19 | + * ====== |
| 20 | + * - binding hash tables instance to each initialized parser instead of having one global one. |
| 21 | + * Considering about: |
| 22 | + * - Sort function |
| 23 | + * - Search function |
| 24 | + * |
| 25 | + */ |
| 26 | + |
| 27 | +if( !defined( 'MEDIAWIKI' ) ) { |
| 28 | + die( 'This file is a MediaWiki extension, it is not a valid entry point' ); |
| 29 | +} |
| 30 | + |
| 31 | +$wgExtensionCredits['parserhook'][] = array( |
| 32 | + 'path' => __FILE__, |
| 33 | + 'name' => 'HashTables', |
| 34 | + 'descriptionmsg' => 'hashtables-desc', |
| 35 | + 'version' => ExtHashTables::VERSION, |
| 36 | + 'author' => '[http://www.mediawiki.org/wiki/User:Danwe Daniel Werner]', |
| 37 | + 'url' => 'http://www.mediawiki.org/wiki/Extension:HashTables', |
| 38 | +); |
| 39 | + |
| 40 | +$wgHooks['ParserFirstCallInit'][] = 'efHashTablesParserFirstCallInit'; |
| 41 | + |
| 42 | +$dir = dirname( __FILE__ ); |
| 43 | + |
| 44 | +$wgExtensionMessagesFiles['HashTables' ] = $dir . '/HashTables.i18n.php'; |
| 45 | +$wgExtensionMessagesFiles['HashTablesMagic'] = $dir . '/HashTables.i18n.magic.php'; |
| 46 | + |
| 47 | +unset( $dir ); |
| 48 | + |
| 49 | +/** |
| 50 | + * Extension class with all the hash table functionality |
| 51 | + */ |
| 52 | +class ExtHashTables { |
| 53 | + |
| 54 | + /** |
| 55 | + * Version of the HashTables extension. |
| 56 | + * |
| 57 | + * @since 0.6.1 |
| 58 | + * |
| 59 | + * @var string |
| 60 | + */ |
| 61 | + const VERSION = '0.6.4 alpha'; |
| 62 | + |
| 63 | + /** |
| 64 | + * @since 0.1 |
| 65 | + * |
| 66 | + * @var array |
| 67 | + * @private |
| 68 | + */ |
| 69 | + var $mHashTables = array(); |
| 70 | + |
| 71 | + function __construct() { |
| 72 | + global $wgHooks; |
| 73 | + $wgHooks['ParserClearState'][] = &$this; |
| 74 | + } |
| 75 | + |
| 76 | + function onParserClearState( &$parser ) { |
| 77 | + // remove all hash tables to avoid conflicts with job queue or Special:Import |
| 78 | + $this->mHashTables = array(); |
| 79 | + return true; |
| 80 | + } |
| 81 | + |
| 82 | + /** |
| 83 | + * Define an hash by a list of 'values' deliminated by 'itemsDelimiter'. |
| 84 | + * Hash keys and their values are deliminated by 'innerDelimiter'. |
| 85 | + * Both delimiters can be perl regular expression patterns. |
| 86 | + * Syntax: {{#hashdefine:hashId |values |itemsDelimiter |innerDelimiter}} |
| 87 | + */ |
| 88 | + function hashdefine( &$parser, $hashId, $value='', $itemsDelimiter = '/\s*,\s*/', $innerDelimiter = '/\s*;\s*/' ) { |
| 89 | + if( !isset($hashId) ) { |
| 90 | + return ''; |
| 91 | + } |
| 92 | + $this->mHashTables[ $hashId ] = array(); |
| 93 | + |
| 94 | + if( $value !== '' ) { |
| 95 | + |
| 96 | + // Build delimiters: |
| 97 | + if ( ! $this->isValidRegEx($itemsDelimiter,'/') ) |
| 98 | + $itemsDelimiter = '/\s*' . preg_quote( $itemsDelimiter, '/' ) . '\s*/'; |
| 99 | + |
| 100 | + if ( ! $this->isValidRegEx($innerDelimiter,'/') ) |
| 101 | + $innerDelimiter = '/\s*' . preg_quote( $innerDelimiter, '/' ) . '\s*/'; |
| 102 | + |
| 103 | + $items = preg_split( $itemsDelimiter, $value ); // All hash Items |
| 104 | + |
| 105 | + foreach ( $items as $itemName => $itemVal ) |
| 106 | + { |
| 107 | + $hashPair = preg_split( $innerDelimiter, $itemVal, 2 ); |
| 108 | + |
| 109 | + if( count($hashPair) < 2 ) |
| 110 | + $this->mHashTables[ $hashId ][ $itemVal ] = ''; // only hash-Name given, could be even '', no value |
| 111 | + else |
| 112 | + $this->mHashTables[ $hashId ][ $hashPair[0] ] = $hashPair[1]; |
| 113 | + } |
| 114 | + } |
| 115 | + |
| 116 | + return ''; |
| 117 | + } |
| 118 | + |
| 119 | + /** |
| 120 | + * Returns the value of the hash table item identified by a given item name. |
| 121 | + */ |
| 122 | + function hashvalue( &$parser, $hashId, $key, $default = '' ) { |
| 123 | + if( !isset($hashId) || !isset($key) ) |
| 124 | + return ''; |
| 125 | + |
| 126 | + $value = $this->getHashValue( $hashId, $key, '' ); |
| 127 | + |
| 128 | + if( $value === '' ) { |
| 129 | + $value = $default; |
| 130 | + } |
| 131 | + |
| 132 | + return $value; |
| 133 | + } |
| 134 | + |
| 135 | + /** |
| 136 | + * Returns the size of a hash table. Returns '' if the table doesn't exist. |
| 137 | + */ |
| 138 | + function hashsize( &$parser, $hashId) { |
| 139 | + if( !isset($hashId) || !$this->hashExists($hashId) ) |
| 140 | + return ''; |
| 141 | + |
| 142 | + return count( $this->mHashTables[ $hashId ] ); |
| 143 | + } |
| 144 | + |
| 145 | + /** |
| 146 | + * Returns "1" or 'yes' (if set) if the hash item key 'key' exists inside the hash table 'hashId'. |
| 147 | + * Otherwise the output will be a void string or 'no' (if set). |
| 148 | + */ |
| 149 | + function hashkeyexists( &$parser, $hashId, $key = '', $yes = '1', $no = '' ) { |
| 150 | + // get hash or null: |
| 151 | + $hash = $this->getHash( $hashId ); |
| 152 | + |
| 153 | + if( $hash !== null && array_key_exists( $key, $hash ) ) { |
| 154 | + return $yes; |
| 155 | + } |
| 156 | + else { |
| 157 | + return $no; |
| 158 | + } |
| 159 | + } |
| 160 | + |
| 161 | + /** |
| 162 | + * Allows to print all entries of a hash table seperated by a delimiter. |
| 163 | + * Syntax: |
| 164 | + * {{#hashprint:hashID |seperator |keyPattern |valuePattern |subject |printOrderArrayId}} |
| 165 | + */ |
| 166 | + function hashprint( Parser &$parser, PPFrame $frame, $args) { |
| 167 | + if( ! isset( $args[0] ) ) { |
| 168 | + return ''; |
| 169 | + } |
| 170 | + $hashId = trim( $frame->expand( $args[0] ) ); |
| 171 | + $values = $this->getHash( $hashId ); |
| 172 | + |
| 173 | + if( $values === null ) { |
| 174 | + return ''; |
| 175 | + } |
| 176 | + |
| 177 | + // parameter validation: |
| 178 | + $seperator = isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) : ', '; |
| 179 | + $keyPattern = isset( $args[2] ) ? trim( $frame->expand( $args[2], PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES ) ) : ''; |
| 180 | + $valuePattern = isset( $args[3] ) ? trim( $frame->expand( $args[3], PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES ) ) : '@@@@'; |
| 181 | + $subject = isset( $args[4] ) ? trim( $frame->expand( $args[4], PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES ) ) : '@@@@'; |
| 182 | + $printOrderArrayId = isset( $args[5] ) ? trim( $frame->expand( $args[5], PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES ) ) : null; |
| 183 | + |
| 184 | + if( $printOrderArrayId !== null ) { |
| 185 | + global $wgArrayExtension; |
| 186 | + |
| 187 | + if( ! isset( $wgArrayExtension ) ) { |
| 188 | + return ''; // array extension not found |
| 189 | + } |
| 190 | + // if array with print order doesn't exist |
| 191 | + if( ! array_key_exists( $printOrderArrayId, $wgArrayExtension->mArrayExtension ) ) { |
| 192 | + return ''; |
| 193 | + } |
| 194 | + $printOrderArray = $wgArrayExtension->mArrayExtension[ $printOrderArrayId ]; |
| 195 | + } |
| 196 | + else { |
| 197 | + // No print order given, copy hash keys in print order array |
| 198 | + $printOrderArray = array_keys( $values ); |
| 199 | + } |
| 200 | + |
| 201 | + $renderedResults = array(); |
| 202 | + |
| 203 | + foreach( $printOrderArray as $itemKey ) { |
| 204 | + if( ! array_key_exists($itemKey, $values) ) { |
| 205 | + continue; |
| 206 | + } |
| 207 | + $itemVal = $values[ $itemKey ]; // get value of the current print item from the values array |
| 208 | + |
| 209 | + $rawResult = $subject; |
| 210 | + if( $keyPattern !== '' ) { |
| 211 | + $rawResult = str_replace($keyPattern, $itemKey, $rawResult); |
| 212 | + } |
| 213 | + if( $valuePattern !== '' ) { |
| 214 | + $rawResult = str_replace($valuePattern, $itemVal, $rawResult); |
| 215 | + } |
| 216 | + |
| 217 | + /** @todo: it doesn't make sense to check whether we are in template or not |
| 218 | + * Parser::PTD_FOR_INCLUSION should be used in any case propably. |
| 219 | + */ |
| 220 | + $rawResult = $parser->preprocessToDom( $rawResult, $frame->isTemplate() ? Parser::PTD_FOR_INCLUSION : 0 ); |
| 221 | + $rawResult = trim( $frame->expand( $rawResult ) ); |
| 222 | + |
| 223 | + $renderedResults[] = $rawResult ; |
| 224 | + } |
| 225 | + return array( implode( $seperator, $renderedResults) , 'noparse' => false, 'isHTML' => false ); |
| 226 | + } |
| 227 | + |
| 228 | + /** |
| 229 | + * Define an hash filled with all given parameters of the current template. |
| 230 | + * In case there are no parameters, the hash will be void. |
| 231 | + */ |
| 232 | + function parameterstohash( &$parser, $frame, $args) { |
| 233 | + if( !isset($args[0]) ) |
| 234 | + return ''; |
| 235 | + |
| 236 | + $hashId = trim( $frame->expand($args[0]) ); |
| 237 | + |
| 238 | + // in case the page is not used as template i.e. when displayed by it's own... |
| 239 | + if( !( $frame instanceof PPTemplateFrame_Dom ) ) |
| 240 | + { |
| 241 | + $this->mHashTables[ $hashId ] = array(); // create empty hash table |
| 242 | + return ''; |
| 243 | + } |
| 244 | + |
| 245 | + $templateArgs = $frame->getArguments(); |
| 246 | + |
| 247 | + foreach ( $templateArgs as $argName => $argVal ) |
| 248 | + { |
| 249 | + $this->mHashTables[ $hashId ][ trim( $argName ) ] = trim( $argVal ); |
| 250 | + } |
| 251 | + return ''; |
| 252 | + |
| 253 | + } |
| 254 | + |
| 255 | + /** |
| 256 | + * Resets the hashes given in parameter 1 to n. If there are no parameters given, |
| 257 | + * the function will reset all hashes. |
| 258 | + */ |
| 259 | + function hashreset( &$parser, $frame, $args) { |
| 260 | + // reset all hash tables if no specific tables are given: |
| 261 | + if( !isset( $args[0] ) || ( $args[0] === '' && count( $args ) == 1 ) ) |
| 262 | + $this->mHashTables = array(); |
| 263 | + else { |
| 264 | + foreach ( $args as $arg ) |
| 265 | + { |
| 266 | + $argVal = trim( $frame->expand($arg) ); |
| 267 | + $this->removeHash( $argVal ); |
| 268 | + } |
| 269 | + } |
| 270 | + return ''; |
| 271 | + } |
| 272 | + |
| 273 | + /** |
| 274 | + * Adds new keys and values to a hash table. This function can also be used as alternative |
| 275 | + * way to create hash tables. |
| 276 | + * Syntax: |
| 277 | + * {{#hashinclude:hashID |key1=val1 |key2=val2 |... |key n=val n}} |
| 278 | + */ |
| 279 | + function hashinclude( &$parser, $frame, $args) { |
| 280 | + // get hash table ID from first parameter: |
| 281 | + $hashId = trim( $frame->expand($args[0] ) ); |
| 282 | + unset( $args[0] ); |
| 283 | + |
| 284 | + if( !$this->hashExists($hashId) ) |
| 285 | + $this->mHashTables[ $hashId ] = array(); |
| 286 | + |
| 287 | + // all following parameters contain hash table keys and values '|key=value' |
| 288 | + foreach ( $args as $arg ) |
| 289 | + { |
| 290 | + $argString = $frame->expand($arg); |
| 291 | + $argItem = explode( '=', $argString, 2 ); |
| 292 | + $argName = trim( $argItem[0] ); |
| 293 | + $argVal = ( count( $argItem ) > 1 ) ? trim( $argItem[1] ) : ''; |
| 294 | + |
| 295 | + $this->mHashTables[ $hashId ][ $argName ] = $argVal; |
| 296 | + } |
| 297 | + return ''; |
| 298 | + } |
| 299 | + |
| 300 | + /** |
| 301 | + * Removes certain given keys from a hash table. |
| 302 | + * Syntax: |
| 303 | + * {{#hashexclude:hashID |key1 |key2 |... |key n}} |
| 304 | + */ |
| 305 | + function hashexclude( &$parser, $frame, $args) { |
| 306 | + // get hash table ID from first parameter: |
| 307 | + $hashId = trim( $frame->expand($args[0]) ); |
| 308 | + unset( $args[0] ); |
| 309 | + |
| 310 | + if( !$this->hashExists($hashId) ) |
| 311 | + return''; |
| 312 | + |
| 313 | + // all following parameters contain hash table keys and values '|key=value' |
| 314 | + foreach ( $args as $arg ) |
| 315 | + { |
| 316 | + $argName = trim( $frame->expand($arg) ); |
| 317 | + unset( $this->mHashTables[ $hashId ][ $argName ] ); |
| 318 | + } |
| 319 | + return ''; |
| 320 | + } |
| 321 | + |
| 322 | + /** |
| 323 | + * Merge two or more hash tables like the php function 'array_merge' would merge them. |
| 324 | + * Syntax: |
| 325 | + * {{#hashmerge:hashID |hash1 |hash2 |... |hash n}} |
| 326 | + */ |
| 327 | + function hashmerge( &$parser, $frame, $args) { |
| 328 | + $this->multiHashOperation( $frame, $args, __FUNCTION__ ); |
| 329 | + return ''; |
| 330 | + } |
| 331 | + private function multi_hashmerge( $hash1, $hash2 ) { |
| 332 | + return array_merge( $hash1, $hash2 ); |
| 333 | + } |
| 334 | + |
| 335 | + /** |
| 336 | + * Mix two or more hash tables. For the most part this function works like 'hashmerge' with one exception: |
| 337 | + * Numeric hash table keys will be treated like string keys. |
| 338 | + * Syntax: |
| 339 | + * {{#hashmix:hashID |hash1 |hash2 |... |hash n}} |
| 340 | + */ |
| 341 | + function hashmix( &$parser, $frame, $args) { |
| 342 | + $this->multiHashOperation( $frame, $args, __FUNCTION__ ); |
| 343 | + return ''; |
| 344 | + } |
| 345 | + private function multi_hashmix( $hash1, $hash2 ) { |
| 346 | + // copy all entries from hash2 to hash1 |
| 347 | + foreach($hash2 as $key => $value) { |
| 348 | + $hash1[ $key ] = $value; |
| 349 | + } |
| 350 | + return $hash1; |
| 351 | + } |
| 352 | + |
| 353 | + /** |
| 354 | + * Compare two or more hash tables like the php function 'array_diff_key' would compare them. |
| 355 | + * All items contained in the first array but in none of the other ones will end up in the |
| 356 | + * new hash table. |
| 357 | + * Syntax: |
| 358 | + * {{#hashdiff:hashID |hash1 |hash2 |... |hash n}} |
| 359 | + */ |
| 360 | + function hashdiff( &$parser, $frame, $args) { |
| 361 | + $this->multiHashOperation( $frame, $args, __FUNCTION__ ); |
| 362 | + return ''; |
| 363 | + } |
| 364 | + private function multi_hashdiff( $hash1, $hash2 ) { |
| 365 | + return array_diff_key( $hash1, $hash2 ); |
| 366 | + } |
| 367 | + |
| 368 | + /** |
| 369 | + * Compare two or more hash tables like the php function 'array_intersect_key' would compare them. |
| 370 | + * Creates a new hash table containing all entries of 'hash1' which are present in the other |
| 371 | + * hash tables given in parameters 3 to n. |
| 372 | + * Syntax: |
| 373 | + * {{#hashintersect:hashID |hash1 |hash2 |... |hash n}} |
| 374 | + */ |
| 375 | + function hashintersect( &$parser, $frame, $args) { |
| 376 | + $this->multiHashOperation( $frame, $args, __FUNCTION__ ); |
| 377 | + return ''; |
| 378 | + } |
| 379 | + private function multi_hashintersect( $hash1, $hash2 ) { |
| 380 | + return array_intersect_key( $hash1, $hash2 ); |
| 381 | + } |
| 382 | + |
| 383 | + /** |
| 384 | + * Create an array from a hash tables values. Optional a seccond array with the keys. If the 'valArrayID' |
| 385 | + * equals the 'keyArrayID', the array will contain only the key names and not the values. |
| 386 | + * Syntax: |
| 387 | + * {{#hashtoarray:valArrayID |hashID |keyArrayID}} |
| 388 | + */ |
| 389 | + function hashtoarray( &$parser, $valArrayId, $hashId, $keyArrayId = null) { |
| 390 | + |
| 391 | + if( !isset($hashId) || !isset($valArrayId) ) |
| 392 | + return ''; |
| 393 | + |
| 394 | + global $wgArrayExtension; |
| 395 | + |
| 396 | + // create void arrays in case hash doesn't exist |
| 397 | + $valArray = array(); |
| 398 | + $keyArray = array(); |
| 399 | + |
| 400 | + if( $this->hashExists($hashId) ) |
| 401 | + { |
| 402 | + $hash = $this->mHashTables[ $hashId ]; |
| 403 | + |
| 404 | + foreach( $hash as $hashKey => $hashVal ) { |
| 405 | + $valArray[] = $hashVal; |
| 406 | + if( $keyArrayId !== null ) |
| 407 | + $keyArray[] = $hashKey; |
| 408 | + } |
| 409 | + } |
| 410 | + |
| 411 | + |
| 412 | + |
| 413 | + $wgArrayExtension->mArrayExtension[ $valArrayId ] = $valArray; |
| 414 | + if( $keyArrayId !== null ) { |
| 415 | + $wgArrayExtension->mArrayExtension[ $keyArrayId ] = $keyArray; |
| 416 | + } |
| 417 | + return ''; |
| 418 | + } |
| 419 | + |
| 420 | + /** |
| 421 | + * Create a hash table from an array. |
| 422 | + * Syntax: |
| 423 | + * {{#arraytohash:hashID |valuesArrayID |keysArrayID}} |
| 424 | + * |
| 425 | + * The 'keysArrayID' is optional. If set the items in this array will end up as keys in |
| 426 | + * the new hash table. |
| 427 | + */ |
| 428 | + function arraytohash( &$parser, $hashId, $valArrId, $keyArrId = null) { |
| 429 | + |
| 430 | + if( !isset($hashId) ) |
| 431 | + return ''; |
| 432 | + |
| 433 | + global $wgArrayExtension; |
| 434 | + |
| 435 | + // if array doesn't exist |
| 436 | + if( !array_key_exists( $valArrId, $wgArrayExtension->mArrayExtension ) ) |
| 437 | + $arrExtValArray = array(); |
| 438 | + else |
| 439 | + $arrExtValArray = $wgArrayExtension->mArrayExtension[ $valArrId ]; |
| 440 | + |
| 441 | + $newHash = array(); |
| 442 | + |
| 443 | + // if no key array is given OR the key array doesn't exist |
| 444 | + if( !isset($keyArrId) || !array_key_exists( $keyArrId, $wgArrayExtension->mArrayExtension ) ) |
| 445 | + { |
| 446 | + // Copy the whole array. Result will be a hash with numeric keys |
| 447 | + $newHash = $arrExtValArray; |
| 448 | + } |
| 449 | + else |
| 450 | + { |
| 451 | + $keyArray = $wgArrayExtension->mArrayExtension[ $keyArrId ]; |
| 452 | + $valArray = $arrExtValArray; |
| 453 | + |
| 454 | + for( $i=0; $i < count($keyArray); $i++ ) { |
| 455 | + $currVal = array_key_exists( $i, $valArray ) ? $valArray[$i] : ''; |
| 456 | + $newHash[ $keyArray[$i] ] = $currVal; |
| 457 | + } |
| 458 | + } |
| 459 | + $this->mHashTables[ $hashId ] = $newHash; |
| 460 | + return ''; |
| 461 | + } |
| 462 | + |
| 463 | + |
| 464 | + /** |
| 465 | + * Allows to call a template with keys of a hash table as parameters and their values as parameter values. |
| 466 | + * The pipe-replace parameter allows to define a string which will replace '|' pipes. Can be useful to preserve |
| 467 | + * links. Default replacement string is '|'. '{{((}}!{{))}}' could be useful in case those templates exist. |
| 468 | + * Syntax: |
| 469 | + * {{#hashtotemplate:template |hash |pipe-replacer}} |
| 470 | + */ |
| 471 | + function hashtotemplate( &$parser, $frame, $args ) { |
| 472 | + if( ! isset($args[0]) || ! isset($args[1]) ) |
| 473 | + return ''; |
| 474 | + |
| 475 | + $template = trim( $frame->expand($args[0] ) ); |
| 476 | + $hashId = trim( $frame->expand($args[1] ) ); |
| 477 | + $pipeReplacer = isset($args[2]) ? trim( $frame->expand( $args[2] ) ) : '|'; |
| 478 | + |
| 479 | + if( !$this->hashExists( $hashId ) ) |
| 480 | + return ''; |
| 481 | + |
| 482 | + $params = $this->mHashTables[ $hashId ]; |
| 483 | + $templateCall = '{{' . $template; |
| 484 | + |
| 485 | + foreach ($params as $paramKey => $paramValue){ |
| 486 | + // replace '}' and '|' to avoid template call manipulation |
| 487 | + $paramValue = str_replace( array( '}', '|' ), array( '}', $pipeReplacer ), $paramValue ); |
| 488 | + $templateCall .= "|$paramKey=$paramValue"; |
| 489 | + } |
| 490 | + $templateCall .= '}}'; |
| 491 | + |
| 492 | + $result = $parser->preprocessToDom( $templateCall, $frame->isTemplate() ? Parser::PTD_FOR_INCLUSION : 0 ); |
| 493 | + $result = trim( $frame->expand( $result ) ); |
| 494 | + |
| 495 | + return array( $result , 'noparse' => false, 'isHTML' => false ); |
| 496 | + } |
| 497 | + |
| 498 | + /* ============================ */ |
| 499 | + /* ============================ */ |
| 500 | + /* === === */ |
| 501 | + /* === HELPER FUNCTIONS === */ |
| 502 | + /* === === */ |
| 503 | + /* ============================ */ |
| 504 | + /* ============================ */ |
| 505 | + |
| 506 | + /** |
| 507 | + * Returns a value within a hash. If key or hash doesn't exist, this will return null |
| 508 | + * or another predefined default. |
| 509 | + * |
| 510 | + * @since 0.6.4 |
| 511 | + * |
| 512 | + * @param string $hashId |
| 513 | + * @param string $key |
| 514 | + * @param mixed $default value to return in cas the value doesn't exist. null by default. |
| 515 | + * @return string |
| 516 | + */ |
| 517 | + public function getHashValue( $hashId = '', $key = '', $default = null ) { |
| 518 | + $hashId = trim( $hashId ); |
| 519 | + if( $this->hashExists( $hashId ) && array_key_exists( $key, $this->mHashTables[ $hashId ] ) ) |
| 520 | + return $this->mHashTables[ $hashId ][ $key ]; |
| 521 | + else |
| 522 | + return $default; |
| 523 | + } |
| 524 | + |
| 525 | + /** |
| 526 | + * Returns an hash identified by $hashId. If it doesn't exist this will return null. |
| 527 | + * |
| 528 | + * @since 0.6 |
| 529 | + * |
| 530 | + * @param string $hashId |
| 531 | + * @return array|null |
| 532 | + */ |
| 533 | + public function getHash( $hashId = '' ) { |
| 534 | + if( $this->hashExists( $hashId ) ) |
| 535 | + return $this->mHashTables[ $hashId ]; |
| 536 | + else |
| 537 | + return null; |
| 538 | + } |
| 539 | + |
| 540 | + /** |
| 541 | + * Returns whether a hash exists within the page scope. |
| 542 | + * |
| 543 | + * @since 0.6 |
| 544 | + * |
| 545 | + * @param string $hashId |
| 546 | + * @return boolean |
| 547 | + */ |
| 548 | + public function hashExists( $hashId = '' ) { |
| 549 | + return array_key_exists( trim( $hashId ), $this->mHashTables ); |
| 550 | + } |
| 551 | + |
| 552 | + /** |
| 553 | + * This will add a new hash or overwrite an existing one. Values should be delliverd as array |
| 554 | + * values in form of a string. |
| 555 | + * |
| 556 | + * @since 0.6 |
| 557 | + * |
| 558 | + * @param string $hashId |
| 559 | + * @param array $hashTable |
| 560 | + */ |
| 561 | + public function createHash( $hashId = '', $hashTable = array() ) { |
| 562 | + $this->mHashTables[ trim( $hashId ) ] = $hashTable; |
| 563 | + } |
| 564 | + |
| 565 | + /** |
| 566 | + * Removes an existing hash. If the hash doesn't exist this will return false, otherwise true. |
| 567 | + * |
| 568 | + * @since 0.6 |
| 569 | + * |
| 570 | + * @param string $hashId |
| 571 | + * @return boolean |
| 572 | + */ |
| 573 | + public function removeHash( $hashId = '' ) { |
| 574 | + $hashId = trim( $hashId ); |
| 575 | + if( $this->hashExists( $hashId ) ) { |
| 576 | + unset( $this->mHashTables[ $hashId ] ); |
| 577 | + return true; |
| 578 | + } else { |
| 579 | + return false; |
| 580 | + } |
| 581 | + } |
| 582 | + |
| 583 | + /** |
| 584 | + * Base function for operations with multiple hashes given thru n parameters |
| 585 | + * $operationFunc expects a function name prefix (suffix 'multi_') with two parameters |
| 586 | + * $hash1 and $hash2 which will perform an action between $hash1 and hash2 which will |
| 587 | + * result into a new $hash1. There can be 1 to n $hash2 in the whole process. |
| 588 | + * |
| 589 | + * @param $frame |
| 590 | + * @param $args |
| 591 | + * @param $operationFunc name of the function calling this. There must be a counterpart |
| 592 | + * function with prefix 'multi_' which should have two parameters. Both parameters |
| 593 | + * will receive a hash (array), the function must return the result hash of the |
| 594 | + * processing. |
| 595 | + */ |
| 596 | + protected function multiHashOperation( $frame, $args ,$operationFunc ) { |
| 597 | + $lastHash = null; |
| 598 | + $finalHashId = trim( $frame->expand( $args[0] ) ); |
| 599 | + $operationFunc = 'multi_' . $operationFunc; |
| 600 | + |
| 601 | + // For all hashes given in parameters 2 to n (ignore 1 because this is the new hash) |
| 602 | + for( $i = 1; $i < count( $args ); $i++ ) |
| 603 | + { |
| 604 | + if( ! array_key_exists( $i, $args ) ) { |
| 605 | + continue; |
| 606 | + } |
| 607 | + $argHashId = trim( $frame->expand( $args[ $i ] ) ); |
| 608 | + |
| 609 | + if( $this->hashExists( $argHashId ) ) { |
| 610 | + $argHash = $this->mHashTables[ $argHashId ]; |
| 611 | + if( $lastHash === null ) { |
| 612 | + // first valid hash table, process together with second... |
| 613 | + $lastHash = $argHash; |
| 614 | + } |
| 615 | + else { |
| 616 | + // second or later hash table, process with previous: |
| 617 | + $lastHash = $this->{ $operationFunc }( $lastHash, $argHash ); // perform action between last and current hash |
| 618 | + } |
| 619 | + } |
| 620 | + } |
| 621 | + // in case no array were given: |
| 622 | + if( $lastHash === null ) { |
| 623 | + $lastHash = array(); |
| 624 | + } |
| 625 | + $this->mHashTables[ $finalHashId ] = $lastHash; |
| 626 | + } |
| 627 | + |
| 628 | + /** |
| 629 | + * Decides for the given $pattern whether its a valid regular expression acceptable for |
| 630 | + * HashTables parser functions or not. |
| 631 | + * |
| 632 | + * @param string $pattern regular expression including delimiters and optional flags |
| 633 | + * @return boolean |
| 634 | + */ |
| 635 | + function isValidRegEx( $pattern ) { |
| 636 | + return preg_match( '/^([\\/\\|%]).*\\1[imsSuUx]*$/', $pattern ); |
| 637 | + } |
| 638 | +} |
| 639 | + |
| 640 | + |
| 641 | + |
| 642 | +function efHashTablesParserFirstCallInit( &$parser ) { |
| 643 | + global $wgHashTables, $wgArrayExtension; |
| 644 | + |
| 645 | + $wgHashTables = new ExtHashTables(); |
| 646 | + |
| 647 | + $parser->setFunctionHook( 'hashdefine', array( &$wgHashTables, 'hashdefine' ) ); |
| 648 | + $parser->setFunctionHook( 'hashvalue', array( &$wgHashTables, 'hashvalue' ) ); |
| 649 | + $parser->setFunctionHook( 'hashsize', array( &$wgHashTables, 'hashsize' ) ); |
| 650 | + $parser->setFunctionHook( 'hashkeyexists', array( &$wgHashTables, 'hashkeyexists' ) ); |
| 651 | + $parser->setFunctionHook( 'hashprint', array( &$wgHashTables, 'hashprint' ), SFH_OBJECT_ARGS ); |
| 652 | + $parser->setFunctionHook( 'parameterstohash', array( &$wgHashTables, 'parameterstohash' ), SFH_OBJECT_ARGS ); |
| 653 | + $parser->setFunctionHook( 'hashtotemplate', array( &$wgHashTables, 'hashtotemplate' ), SFH_OBJECT_ARGS ); |
| 654 | + $parser->setFunctionHook( 'hashinclude', array( &$wgHashTables, 'hashinclude' ), SFH_OBJECT_ARGS ); |
| 655 | + $parser->setFunctionHook( 'hashexclude', array( &$wgHashTables, 'hashexclude' ), SFH_OBJECT_ARGS ); |
| 656 | + $parser->setFunctionHook( 'hashreset', array( &$wgHashTables, 'hashreset' ), SFH_OBJECT_ARGS ); |
| 657 | + $parser->setFunctionHook( 'hashmerge', array( &$wgHashTables, 'hashmerge' ), SFH_OBJECT_ARGS ); |
| 658 | + $parser->setFunctionHook( 'hashmix', array( &$wgHashTables, 'hashmix' ), SFH_OBJECT_ARGS ); |
| 659 | + $parser->setFunctionHook( 'hashdiff', array( &$wgHashTables, 'hashdiff' ), SFH_OBJECT_ARGS ); |
| 660 | + $parser->setFunctionHook( 'hashintersect', array( &$wgHashTables, 'hashintersect' ), SFH_OBJECT_ARGS ); |
| 661 | + |
| 662 | + // if array extension is available, rgister array-hash interactions: |
| 663 | + if( isset( $wgArrayExtension ) ) { |
| 664 | + $parser->setFunctionHook( 'hashtoarray', array( &$wgHashTables, 'hashtoarray' ) ); |
| 665 | + $parser->setFunctionHook( 'arraytohash', array( &$wgHashTables, 'arraytohash' ) ); |
| 666 | + } |
| 667 | + |
| 668 | + return true; |
| 669 | +} |
Property changes on: trunk/extensions/HashTables/HashTables.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 670 | + native |