https://www.mediawiki.org/wiki/Special:Code/MediaWiki/103474
Revision: 103474
Author: danwe
Date: 2011-11-17 16:41:26 +0000 (Thu, 17 Nov 2011)
Log Message:
-----------
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
trunk/extensions/HashTables/README
trunk/extensions/HashTables/RELEASE-NOTES
Modified: trunk/extensions/HashTables/HashTables.php
===================================================================
--- trunk/extensions/HashTables/HashTables.php 2011-11-17 16:25:25 UTC (rev
103473)
+++ trunk/extensions/HashTables/HashTables.php 2011-11-17 16:41:26 UTC (rev
103474)
@@ -4,7 +4,7 @@
* Defines a subset of parser functions to handle hash tables. Inspired by the
ArrayExtension
* (http://www.mediawiki.org/wiki/Extension:ArrayExtension).
*
- * @version: 0.7
+ * @version: 0.8 alpha
* @author: Daniel Werner < [email protected] >
* @license: ISC license
*
@@ -24,9 +24,7 @@
*
*/
-if( !defined( 'MEDIAWIKI' ) ) {
- die( 'This file is a MediaWiki extension, it is not a valid entry point' );
-}
+if ( ! defined( 'MEDIAWIKI' ) ) { die(); }
$wgExtensionCredits['parserhook'][] = array(
'path' => __FILE__,
@@ -37,14 +35,14 @@
'url' =>
'http://www.mediawiki.org/wiki/Extension:HashTables',
);
-$wgHooks['ParserFirstCallInit'][] = 'efHashTablesParserFirstCallInit';
-
-$dir = dirname( __FILE__ );
+// language files:
+$wgExtensionMessagesFiles['HashTables' ] = ExtHashTables::getDir() .
'/HashTables.i18n.php';
+$wgExtensionMessagesFiles['HashTablesMagic'] = ExtHashTables::getDir() .
'/HashTables.i18n.magic.php';
-$wgExtensionMessagesFiles['HashTables' ] = $dir . '/HashTables.i18n.php';
-$wgExtensionMessagesFiles['HashTablesMagic'] = $dir .
'/HashTables.i18n.magic.php';
+// hooks registration:
+$wgHooks['ParserFirstCallInit'][] = 'ExtHashTables::init';
+$wgHooks['ParserClearState' ][] = 'ExtHashTables::onParserClearState';
-unset( $dir );
/**
* Extension class with all the hash table functionality
@@ -58,7 +56,7 @@
*
* @var string
*/
- const VERSION = '0.7';
+ const VERSION = '0.8 alpha';
/**
* @since 0.1
@@ -73,43 +71,108 @@
$wgHooks['ParserClearState'][] = &$this;
}
- function onParserClearState( &$parser ) {
- // remove all hash tables to avoid conflicts with job queue or
Special:Import
- $this->mHashTables = array();
- return true;
- }
+ /**
+ * Sets up parser functions
+ *
+ * @since 0.8
+ */
+ public static function init( Parser &$parser ) {
+
+ /*
+ * store for variables per parser object. This will solve
several bugs related to
+ * 'ParserClearState' hook clearing all variables early in
combination with certain
+ * other extensions. (since v2.0)
+ */
+ $parser->mExtHashTables = new self();
+
+ // SFH_OBJECT_ARGS available since MW 1.12
+ self::initFunction( $parser, 'hashdefine' );
+ self::initFunction( $parser, 'hashvalue' );
+ self::initFunction( $parser, 'hashsize' );
+ self::initFunction( $parser, 'hashkeyexists', SFH_OBJECT_ARGS );
+ self::initFunction( $parser, 'hashprint', SFH_OBJECT_ARGS );
+ self::initFunction( $parser, 'parameterstohash',
SFH_OBJECT_ARGS );
+ self::initFunction( $parser, 'hashtotemplate', SFH_OBJECT_ARGS
);
+ self::initFunction( $parser, 'hashinclude', SFH_OBJECT_ARGS );
+ self::initFunction( $parser, 'hashexclude', SFH_OBJECT_ARGS );
+ self::initFunction( $parser, 'hashreset', SFH_OBJECT_ARGS );
+ self::initFunction( $parser, 'hashmerge', SFH_OBJECT_ARGS );
+ self::initFunction( $parser, 'hashmix', SFH_OBJECT_ARGS );
+ self::initFunction( $parser, 'hashdiff', SFH_OBJECT_ARGS );
+ self::initFunction( $parser, 'hashintersect', SFH_OBJECT_ARGS );
+
+ // if array extension is available, rgister array-hash
interactions:
+ if( class_exists( 'ArrayExtension' ) ) {
+ self::initFunction( $parser, 'hashtoarray' );
+ self::initFunction( $parser, 'arraytohash' );
+ }
+
+ return true;
+ }
+ private static function initFunction( Parser &$parser, $name, $flags =
0 ) {
+ // all parser functions with prefix:
+ $prefix = ( $flags & SFH_OBJECT_ARGS ) ? 'pfObj_' : 'pf_';
+ $functionCallback = array( __CLASS__, $prefix . $name );
+
+ $parser->setFunctionHook( $name, $functionCallback, $flags );
+ }
/**
+ * Returns the extensions base installation directory.
+ *
+ * @since 0.8
+ *
+ * @return boolean
+ */
+ public static function getDir() {
+ static $dir = null;
+
+ if( $dir === null ) {
+ $dir = dirname( __FILE__ );
+ }
+ return $dir;
+ }
+
+
+ ####################
+ # Parser Functions #
+ ####################
+
+ /**
* Define an hash by a list of 'values' deliminated by 'itemsDelimiter'.
* Hash keys and their values are deliminated by 'innerDelimiter'.
* Both delimiters can be perl regular expression patterns.
* Syntax: {{#hashdefine:hashId |values |itemsDelimiter
|innerDelimiter}}
*/
- function hashdefine( &$parser, $hashId, $value='', $itemsDelimiter =
'/\s*,\s*/', $innerDelimiter = '/\s*;\s*/' ) {
- if( !isset($hashId) ) {
+ static function pf_hashdefine( Parser &$parser, $hashId, $value = '',
$itemsDelimiter = '/\s*,\s*/', $innerDelimiter = '/\s*;\s*/' ) {
+ if( ! isset( $hashId ) ) {
return '';
- }
- $this->mHashTables[ $hashId ] = array();
+ }
+ $store = self::get( $parser );
+
+ $store->setHash( $hashId );
if( $value !== '' ) {
-
// Build delimiters:
- if ( ! $this->isValidRegEx($itemsDelimiter,'/') )
+ if ( ! self::isValidRegEx($itemsDelimiter,'/') ) {
$itemsDelimiter = '/\s*' . preg_quote( $itemsDelimiter, '/' )
. '\s*/';
+ }
- if ( ! $this->isValidRegEx($innerDelimiter,'/') )
+ if ( ! self::isValidRegEx($innerDelimiter,'/') ) {
$innerDelimiter = '/\s*' . preg_quote( $innerDelimiter, '/' )
. '\s*/';
+ }
$items = preg_split( $itemsDelimiter, $value ); // All
hash Items
- foreach ( $items as $itemName => $itemVal )
- {
- $hashPair = preg_split( $innerDelimiter,
$itemVal, 2 );
+ foreach ( $items as $item ) {
+ $hashPair = preg_split( $innerDelimiter, $item,
2 );
- if( count($hashPair) < 2 )
- $this->mHashTables[ $hashId ][ $itemVal
] = ''; // only hash-Name given, could be even '', no value
- else
- $this->mHashTables[ $hashId ][
$hashPair[0] ] = $hashPair[1];
+ if( count($hashPair) < 2 ) {
+ // only hash-Name given, could be even
'', no value
+ $store->setHashValue( $hashId, $item,
'' );
+ } else {
+ $store->setHashValue( $hashId,
$hashPair[0], $hashPair[1] );
+ }
}
}
@@ -119,11 +182,12 @@
/**
* Returns the value of the hash table item identified by a given item
name.
*/
- function hashvalue( &$parser, $hashId, $key, $default = '' ) {
- if( !isset($hashId) || !isset($key) )
+ static function pf_hashvalue( Parser &$parser, $hashId, $key, $default =
'' ) {
+ if( ! isset( $hashId ) || ! isset( $key ) ) {
return '';
+ }
- $value = $this->getHashValue( $hashId, $key, '' );
+ $value = self::get( $parser )->getHashValue( $hashId, $key, '' );
if( $value === '' ) {
$value = $default;
@@ -135,26 +199,30 @@
/**
* Returns the size of a hash table. Returns '' if the table doesn't
exist.
*/
- function hashsize( &$parser, $hashId) {
- if( ! isset($hashId) || ! $this->hashExists($hashId) ) {
+ static function pf_hashsize( Parser &$parser, $hashId) {
+ $store = self::get( $parser );
+
+ /*
+ * in old ArrayExtension tradition, return '' if hash doesn't
exist.
+ * Though it might be a bit confusing in the beginning, we
won't need any '#hashexists' function
+ */
+ if( ! isset( $hashId ) || ! $store->hashExists( $hashId ) ) {
return '';
- }
- return count( $this->mHashTables[ $hashId ] );
+ }
+ $hash = $store->getHash( $hashId );
+ return count( $hash );
}
/**
* Returns "1" or the third parameter (if set) if the hash item key
'key' exists inside the hash
* table 'hashId'. Otherwise the output will be a void string or the
fourth (if set).
*/
- function hashkeyexists( Parser &$parser, PPFrame $frame, $args ) {
+ static function pfObj_hashkeyexists( Parser &$parser, PPFrame $frame,
$args ) {
$hashId = trim( $frame->expand( $args[0] ) );
$key = isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) : '';
-
- // get hash or null:
- $hash = $this->getHash( $hashId );
-
+
// only expand the one argument needed:
- if( $hash !== null && array_key_exists( $key, $hash ) ) {
+ if( self::get( $parser )->getHashValue( $hashId, $key ) !==
null ) {
return isset( $args[2] ) ? trim( $frame->expand(
$args[2] ) ) : '1'; // true '1'
}
else {
@@ -167,19 +235,21 @@
* Syntax:
* {{#hashprint:hashID |seperator |keyPattern |valuePattern |subject
|printOrderArrayId}}
*/
- function hashprint( Parser &$parser, PPFrame $frame, $args ) {
+ static function pfObj_hashprint( Parser &$parser, PPFrame $frame, $args ) {
if( ! isset( $args[0] ) ) {
return '';
}
+
$hashId = trim( $frame->expand( $args[0] ) );
- $values = $this->getHash( $hashId );
+ $values = self::get( $parser )->getHash( $hashId );
if( $values === null ) {
return '';
}
- // parameter validation:
- $seperator = isset( $args[1] ) ? trim( $frame->expand(
$args[1] ) ) : ', ';
+ // parameter validation:
+
+ $seperator = isset( $args[1] ) ? trim( $frame->expand( $args[1] ) ) :
', ';
/*
* PPFrame::NO_ARGS and PPFrame::NO_TEMPLATES for expansion
make a lot of sense here since the patterns getting replaced
* in $subject before $subject is being parsed. So any template
or argument influence in the patterns wouldn't make any
@@ -228,7 +298,7 @@
*/
$rawResult = $parser->preprocessToDom( $rawResult,
$frame->isTemplate() ? Parser::PTD_FOR_INCLUSION : 0 );
$rawResult = trim( $frame->expand( $rawResult ) );
-
+
$renderedResults[] = $rawResult ;
}
return array( implode( $seperator, $renderedResults) , 'noparse' =>
false, 'isHTML' => false );
@@ -238,12 +308,14 @@
* Define an hash filled with all given parameters of the current
template.
* In case there are no parameters, the hash will be void.
*/
- function parameterstohash( &$parser, PPFrame $frame, $args) {
+ static function pfObj_parameterstohash( &$parser, PPFrame $frame, $args) {
if( ! isset( $args[0] ) ) {
return '';
}
+ $store = self::get( $parser );
+
$hashId = trim( $frame->expand( $args[0] ) );
- $this->mHashTables[ $hashId ] = array(); // create empty hash
table
+ $store->setHash( $hashId ); // create empty hash table
// in case the page is not used as template i.e. when displayed
on its own
if( ! $frame->isTemplate() ) {
@@ -253,7 +325,8 @@
$templateArgs = $frame->getArguments();
foreach ( $templateArgs as $argName => $argVal ) {
- $this->mHashTables[ $hashId ][ trim( $argName ) ] =
trim( $argVal );
+ // one hash value for each parameter
+ $store->setHashValue( $hashId, $argName, $argVal );
}
return '';
}
@@ -262,16 +335,19 @@
* Resets the hashes given in parameter 1 to n. If there are no
parameters given,
* the function will reset all hashes.
*/
- function hashreset( &$parser, $frame, $args) {
+ static function pfObj_hashreset( &$parser, $frame, $args) {
+ $store = self::get( $parser );
+
// reset all hash tables if no specific tables are given:
- if( !isset( $args[0] ) || ( $args[0] === '' && count( $args )
== 1 ) ) {
- $this->mHashTables = array();
+ if( ! isset( $args[0] ) || ( $args[0] === '' && count( $args )
== 1 ) ) {
+ $store->mHashTables = array();
}
else {
- foreach ( $args as $arg )
- {
- $argVal = trim( $frame->expand($arg) );
- $this->removeHash( $argVal );
+ // reset specific hash tables:
+ foreach( $args as $arg ) {
+ $hashId = trim( $frame->expand($arg) );
+ $store->unsetHash( $hashId );
+
}
}
return '';
@@ -283,23 +359,26 @@
* Syntax:
* {{#hashinclude:hashID |key1=val1 |key2=val2 |... |key n=val n}}
*/
- function hashinclude( &$parser, $frame, $args) {
+ static function pfObj_hashinclude( &$parser, $frame, $args) {
// get hash table ID from first parameter:
$hashId = trim( $frame->expand( $args[0] ) );
unset( $args[0] );
- if( !$this->hashExists($hashId) )
- $this->mHashTables[ $hashId ] = array();
+ $store = self::get( $parser );
+ if( ! $store->hashExists($hashId) ) {
+ $store->setHash( $hashId );
+ }
+
// all following parameters contain hash table keys and values
'|key=value'
- foreach ( $args as $arg )
- {
+ foreach ( $args as $arg ) {
$argString = $frame->expand($arg);
$argItem = explode( '=', $argString, 2 );
- $argName = trim( $argItem[0] );
- $argVal = ( count( $argItem ) > 1 ) ? trim( $argItem[1]
) : '';
+ $argName = $argItem[0];
+ $argVal = ( count( $argItem ) > 1 ) ? $argItem[1] : '';
- $this->mHashTables[ $hashId ][ $argName ] = $argVal;
+ // set the value (this will trim the values as well)
+ $store->setHashValue( $hashId, $argName, $argVal );
}
return '';
}
@@ -309,19 +388,21 @@
* Syntax:
* {{#hashexclude:hashID |key1 |key2 |... |key n}}
*/
- function hashexclude( &$parser, $frame, $args) {
+ static function pfObj_hashexclude( &$parser, $frame, $args) {
// get hash table ID from first parameter:
$hashId = trim( $frame->expand($args[0]) );
unset( $args[0] );
- if( !$this->hashExists($hashId) )
- return'';
+ $store = self::get( $parser );
+ if( ! $store->hashExists( $hashId ) ) {
+ return'';
+ }
+
// all following parameters contain hash table keys and values
'|key=value'
- foreach ( $args as $arg )
- {
- $argName = trim( $frame->expand($arg) );
- unset( $this->mHashTables[ $hashId ][ $argName ] );
+ foreach ( $args as $arg ) {
+ $argName = trim( $frame->expand($arg) );
+ $store->unsetHashValue( $hashId, $argName );
}
return '';
}
@@ -331,8 +412,8 @@
* Syntax:
* {{#hashmerge:hashID |hash1 |hash2 |... |hash n}}
*/
- function hashmerge( &$parser, $frame, $args) {
- $this->multiHashOperation( $frame, $args, __FUNCTION__, true );
+ static function pfObj_hashmerge( &$parser, $frame, $args) {
+ self::get( $parser )->multiHashOperation( $frame, $args,
__FUNCTION__, true );
return '';
}
private function multi_hashmerge( $hash1, $hash2 = array() ) {
@@ -345,8 +426,8 @@
* Syntax:
* {{#hashmix:hashID |hash1 |hash2 |... |hash n}}
*/
- function hashmix( &$parser, $frame, $args) {
- $this->multiHashOperation( $frame, $args, __FUNCTION__, false );
+ static function pfObj_hashmix( &$parser, $frame, $args) {
+ self::get( $parser )->multiHashOperation( $frame, $args,
__FUNCTION__, false );
return '';
}
private function multi_hashmix( $hash1, $hash2 ) {
@@ -364,8 +445,8 @@
* Syntax:
* {{#hashdiff:hashID |hash1 |hash2 |... |hash n}}
*/
- function hashdiff( &$parser, $frame, $args) {
- $this->multiHashOperation( $frame, $args, __FUNCTION__, false );
+ static function pfObj_hashdiff( &$parser, $frame, $args) {
+ self::get( $parser )->multiHashOperation( $frame, $args,
__FUNCTION__, false );
return '';
}
private function multi_hashdiff( $hash1, $hash2 ) {
@@ -379,8 +460,8 @@
* Syntax:
* {{#hashintersect:hashID |hash1 |hash2 |... |hash n}}
*/
- function hashintersect( &$parser, $frame, $args) {
- $this->multiHashOperation( $frame, $args, __FUNCTION__, false );
+ static function pfObj_hashintersect( &$parser, $frame, $args) {
+ self::get( $parser )->multiHashOperation( $frame, $args,
__FUNCTION__, false );
return '';
}
private function multi_hashintersect( $hash1, $hash2 ) {
@@ -393,10 +474,10 @@
* Syntax:
* {{#hashtoarray:valArrayID |hashID |keyArrayID}}
*/
- function hashtoarray( &$parser, $valArrayId, $hashId, $keyArrayId =
null) {
-
- if( !isset($hashId) || !isset($valArrayId) )
+ static function pf_hashtoarray( Parser &$parser, $valArrayId, $hashId,
$keyArrayId = null) {
+ if( ! isset( $hashId ) || ! isset( $valArrayId ) ) {
return '';
+ }
global $wgArrayExtension;
@@ -404,22 +485,22 @@
$valArray = array();
$keyArray = array();
- if( $this->hashExists($hashId) )
- {
- $hash = $this->mHashTables[ $hashId ];
-
+ $hash = self::get( $parser )->getHash( $hashId );
+
+ if( $hash !== null ) {
foreach( $hash as $hashKey => $hashVal ) {
$valArray[] = $hashVal;
- if( $keyArrayId !== null )
+ if( $keyArrayId !== null ) {
+ // for additional array with keys
$keyArray[] = $hashKey;
+ }
}
}
-
-
- $wgArrayExtension->mArrayExtension[ $valArrayId ] = $valArray;
+ $wgArrayExtension->mArrayExtension[ trim( $valArrayId ) ] =
$valArray;
if( $keyArrayId !== null ) {
- $wgArrayExtension->mArrayExtension[ $keyArrayId ] =
$keyArray;
+ // additional array for hash keys:
+ $wgArrayExtension->mArrayExtension[ trim( $keyArrayId )
] = $keyArray;
}
return '';
}
@@ -432,15 +513,15 @@
* The 'keysArrayID' is optional. If set the items in this array will
end up as keys in
* the new hash table.
*/
- function arraytohash( &$parser, $hashId, $valArrId, $keyArrId = null) {
-
- if( !isset($hashId) )
+ static function pf_arraytohash( Parser &$parser, $hashId, $valArrId,
$keyArrId = null) {
+ if( ! isset( $hashId) ) {
return '';
+ }
global $wgArrayExtension;
// if array doesn't exist
- if( !array_key_exists( $valArrId,
$wgArrayExtension->mArrayExtension ) )
+ if( ! array_key_exists( $valArrId,
$wgArrayExtension->mArrayExtension ) )
$arrExtValArray = array();
else
$arrExtValArray = $wgArrayExtension->mArrayExtension[
$valArrId ];
@@ -448,7 +529,7 @@
$newHash = array();
// if no key array is given OR the key array doesn't exist
- if( !isset($keyArrId) || !array_key_exists( $keyArrId,
$wgArrayExtension->mArrayExtension ) )
+ if( ! isset($keyArrId) || ! array_key_exists( $keyArrId,
$wgArrayExtension->mArrayExtension ) )
{
// Copy the whole array. Result will be a hash with
numeric keys
$newHash = $arrExtValArray;
@@ -459,11 +540,12 @@
$valArray = $arrExtValArray;
for( $i=0; $i < count($keyArray); $i++ ) {
- $currVal = array_key_exists( $i, $valArray ) ?
$valArray[$i] : '';
- $newHash[ $keyArray[$i] ] = $currVal;
+ $currVal = array_key_exists( $i, $valArray ) ?
trim( $valArray[ $i ] ) : '';
+ $newHash[ $keyArray[ $i ] ] = $currVal;
}
}
- $this->mHashTables[ $hashId ] = $newHash;
+
+ self::get( $parser )->mHashTables[ $hashId ] = $newHash;
return '';
}
@@ -475,18 +557,22 @@
* Syntax:
* {{#hashtotemplate:template |hash |pipe-replacer}}
*/
- function hashtotemplate( &$parser, $frame, $args ) {
- if( ! isset($args[0]) || ! isset($args[1]) )
+ static function pfObj_hashtotemplate( Parser &$parser, $frame, $args ) {
+ if( ! isset( $args[0] ) || ! isset( $args[1] ) ) {
return '';
+ }
+ $store = self::get( $parser );
+
$template = trim( $frame->expand($args[0] ) );
$hashId = trim( $frame->expand($args[1] ) );
$pipeReplacer = isset($args[2]) ? trim( $frame->expand(
$args[2] ) ) : '|';
- if( !$this->hashExists( $hashId ) )
+ if( ! $store->hashExists( $hashId ) ) {
return '';
+ }
- $params = $this->mHashTables[ $hashId ];
+ $params = $store->getHash( $hashId );
$templateCall = '{{' . $template;
foreach ($params as $paramKey => $paramValue){
@@ -504,92 +590,12 @@
return array( $result , 'noparse' => true, 'isHTML' => false );
}
- /* ============================ */
- /* ============================ */
- /* === === */
- /* === HELPER FUNCTIONS === */
- /* === === */
- /* ============================ */
- /* ============================ */
- /**
- * Returns a value within a hash. If key or hash doesn't exist, this
will return null
- * or another predefined default.
- *
- * @since 0.7
- *
- * @param string $hashId
- * @param string $key
- * @param mixed $default value to return in cas the value doesn't
exist. null by default.
- * @return string
- */
- public function getHashValue( $hashId = '', $key = '', $default = null ) {
- $hashId = trim( $hashId );
- if( $this->hashExists( $hashId ) && array_key_exists( $key,
$this->mHashTables[ $hashId ] ) )
- return $this->mHashTables[ $hashId ][ $key ];
- else
- return $default;
- }
-
- /**
- * Returns an hash identified by $hashId. If it doesn't exist this will
return null.
- *
- * @since 0.6
- *
- * @param string $hashId
- * @return array|null
- */
- public function getHash( $hashId = '' ) {
- if( $this->hashExists( $hashId ) )
- return $this->mHashTables[ $hashId ];
- else
- return null;
- }
+ ##################
+ # Private Helper #
+ ##################
/**
- * Returns whether a hash exists within the page scope.
- *
- * @since 0.6
- *
- * @param string $hashId
- * @return boolean
- */
- public function hashExists( $hashId = '' ) {
- return array_key_exists( trim( $hashId ), $this->mHashTables );
- }
-
- /**
- * This will add a new hash or overwrite an existing one. Values should
be delliverd as array
- * values in form of a string.
- *
- * @since 0.6
- *
- * @param string $hashId
- * @param array $hashTable
- */
- public function createHash( $hashId = '', $hashTable = array() ) {
- $this->mHashTables[ trim( $hashId ) ] = $hashTable;
- }
-
- /**
- * Removes an existing hash. If the hash doesn't exist this will return
false, otherwise true.
- *
- * @since 0.6
- *
- * @param string $hashId
- * @return boolean
- */
- public function removeHash( $hashId = '' ) {
- $hashId = trim( $hashId );
- if( $this->hashExists( $hashId ) ) {
- unset( $this->mHashTables[ $hashId ] );
- return true;
- } else {
- return false;
- }
- }
-
- /**
* Base function for operations with multiple hashes given thru n
parameters
* $operationFunc expects a function name prefix (suffix 'multi_') with
two parameters
* $hash1 and $hash2 which will perform an action between $hash1 and
hash2 which will
@@ -608,7 +614,7 @@
$lastHash = null;
$operationRan = false;
$finalHashId = trim( $frame->expand( $args[0] ) );
- $operationFunc = 'multi_' . $operationFunc;
+ $operationFunc = 'multi_' . preg_replace( '/^pfObj_/', '',
$operationFunc );
// For all hashes given in parameters 2 to n (ignore 1 because
this is the new hash)
for( $i = 1; $i < count( $args ); $i++ )
@@ -617,7 +623,7 @@
continue;
}
$argHashId = trim( $frame->expand( $args[ $i ] ) );
-
+
if( $this->hashExists( $argHashId ) ) {
$argHash = $this->mHashTables[ $argHashId ];
if( $lastHash === null ) {
@@ -629,58 +635,178 @@
$lastHash = $this->{ $operationFunc }(
$lastHash, $argHash ); // perform action between last and current hash
$operationRan = true;
}
- }
+ }
}
+
// in case no hash was given at all:
if( $lastHash === null ) {
$lastHash = array();
}
+
// if the operation didn't run because there was only one or no
array:
if( $operationRan == false && $runFuncOnSingleHash ) {
$lastHash = $this->{ $operationFunc }( $lastHash );
}
+
$this->mHashTables[ $finalHashId ] = $lastHash;
}
+
+ ##############
+ # Used Hooks #
+ ##############
+
/**
+ * This will clean up the hash table store after parsing has finished.
It will prevent strange things to happen
+ * for example during import of several pages or job queue is running
for multiple pages. In these cases hashes
+ * would become some kind of superglobals, being passed from one page
to the other.
+ */
+ static function onParserClearState( Parser &$parser ) {
+ /**
+ * MessageCaches Parser clone will mess things up if we don't
reset the entire object.
+ * Only resetting the array would unset it in the original
object as well! This instead
+ * will break the entire reference to the object
+ */
+ $parser->mExtHashTables = new self();
+ return true;
+ }
+
+
+ ####################################
+ # Public functions for interaction #
+ ####################################
+ #
+ # public non-parser functions, accessible for
+ # other extensions doing interactive stuff
+ # with 'HashTables' extension.
+ #
+
+ /**
+ * Convenience function to return the 'HashTables' extensions hash
table store connected
+ * to a certain Parser object. Each parser has its own store which will
be reset after
+ * a parsing process [Parser::parse()] has finished.
+ *
+ * @since 0.8
+ *
+ * @param Parser &$parser
+ *
+ * @return ExtHashTables by reference so we still have the right object
after 'ParserClearState'
+ */
+ public static function &get( Parser &$parser ) {
+ return $parser->mExtHashTables;
+ }
+
+ /**
+ * Returns an hash identified by $hashId. If it doesn't exist this will
return null.
+ *
+ * @since 0.6
+ *
+ * @param string $hashId
+ *
+ * @return array|null
+ */
+ public function getHash( $hashId ) {
+ if( $this->hashExists( $hashId ) ) {
+ return $this->mHashTables[ $hashId ];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * This will add a new hash or overwrite an existing one. Values should
be delliverd as array
+ * values in form of a string. All values will be converted to strings,
trim() will iterate
+ * over them.
+ *
+ * @since 0.8
+ *
+ * @param string $hashId
+ * @param array $hashTable
+ */
+ public function setHash( $hashId, $hashTable = array() ) {
+ $hashTable = array_map( 'trim', $hashTable ); // make it all
string and trim
+ $this->mHashTables[ trim( $hashId ) ] = $hashTable;
+ }
+
+ /**
+ * Returns a value within a hash. If key or hash doesn't exist, this
will return null
+ * or another predefined default.
+ *
+ * @since 0.7
+ *
+ * @param string $hashId
+ * @param string $key
+ * @param mixed $default value to return in cas the value doesn't
exist. null by default.
+ *
+ * @return string
+ */
+ public function getHashValue( $hashId, $key, $default = null ) {
+ $hashId = trim( $hashId );
+ if( $this->hashExists( $hashId ) && array_key_exists( $key,
$this->mHashTables[ $hashId ] ) ) {
+ return $this->mHashTables[ $hashId ][ $key ];
+ } else {
+ return $default;
+ }
+ }
+
+ /**
+ * Rest a specific hash tables entry.
+ *
+ * @since 0.8
+ *
+ * @param type $hashId
+ * @param type $key
+ */
+ public function unsetHashValue( $hashId, $key ) {
+ unset( $this->mHashTables[ $hashId ][ $key ] );
+ }
+
+ /**
+ * Set a value of a hash table to a specific value. If the hash table
doesn't exist already,
+ * it will be created.
+ *
+ * @since 0.8
+ *
+ * @param string $hashId
+ * @param array $hashTable
+ */
+ public function setHashValue( $hashId, $key, $value ) {
+ $this->mHashTables[ trim( $hashId ) ][ trim( $key ) ] = trim(
$value );
+ }
+
+ /**
+ * Returns whether a hash exists within the page scope.
+ *
+ * @since 0.6
+ *
+ * @param string $hashId
+ *
+ * @return boolean
+ */
+ public function hashExists( $hashId ) {
+ return array_key_exists( trim( $hashId ), $this->mHashTables );
+ }
+
+ /**
+ * Allows to unset a certain variable
+ *
+ * @since 0.8
+ *
+ * @param type $varName
+ */
+ public function unsetHash( $hashId ) {
+ unset( $this->mHashTables[ $hashId ] );
+ }
+
+ /**
* Decides for the given $pattern whether its a valid regular
expression acceptable for
* HashTables parser functions or not.
*
* @param string $pattern regular expression including delimiters and
optional flags
* @return boolean
*/
- function isValidRegEx( $pattern ) {
+ static function isValidRegEx( $pattern ) {
return preg_match( '/^([\\/\\|%]).*\\1[imsSuUx]*$/', $pattern );
}
-}
-
-
-
-function efHashTablesParserFirstCallInit( Parser &$parser ) {
- global $wgHashTables, $wgArrayExtension;
-
- $wgHashTables = new ExtHashTables();
-
- $parser->setFunctionHook( 'hashdefine', array( &$wgHashTables,
'hashdefine' ) );
- $parser->setFunctionHook( 'hashvalue', array( &$wgHashTables,
'hashvalue' ) );
- $parser->setFunctionHook( 'hashsize', array( &$wgHashTables,
'hashsize' ) );
- $parser->setFunctionHook( 'hashkeyexists', array( &$wgHashTables,
'hashkeyexists' ), SFH_OBJECT_ARGS );
- $parser->setFunctionHook( 'hashprint', array( &$wgHashTables,
'hashprint' ), SFH_OBJECT_ARGS );
- $parser->setFunctionHook( 'parameterstohash', array( &$wgHashTables,
'parameterstohash' ), SFH_OBJECT_ARGS );
- $parser->setFunctionHook( 'hashtotemplate', array( &$wgHashTables,
'hashtotemplate' ), SFH_OBJECT_ARGS );
- $parser->setFunctionHook( 'hashinclude', array( &$wgHashTables,
'hashinclude' ), SFH_OBJECT_ARGS );
- $parser->setFunctionHook( 'hashexclude', array( &$wgHashTables,
'hashexclude' ), SFH_OBJECT_ARGS );
- $parser->setFunctionHook( 'hashreset', array( &$wgHashTables,
'hashreset' ), SFH_OBJECT_ARGS );
- $parser->setFunctionHook( 'hashmerge', array( &$wgHashTables,
'hashmerge' ), SFH_OBJECT_ARGS );
- $parser->setFunctionHook( 'hashmix', array( &$wgHashTables,
'hashmix' ), SFH_OBJECT_ARGS );
- $parser->setFunctionHook( 'hashdiff', array( &$wgHashTables,
'hashdiff' ), SFH_OBJECT_ARGS );
- $parser->setFunctionHook( 'hashintersect', array( &$wgHashTables,
'hashintersect' ), SFH_OBJECT_ARGS );
- // if array extension is available, rgister array-hash interactions:
- if( isset( $wgArrayExtension ) ) {
- $parser->setFunctionHook( 'hashtoarray', array( &$wgHashTables,
'hashtoarray' ) );
- $parser->setFunctionHook( 'arraytohash', array( &$wgHashTables,
'arraytohash' ) );
- }
-
- return true;
}
Modified: trunk/extensions/HashTables/README
===================================================================
--- trunk/extensions/HashTables/README 2011-11-17 16:25:25 UTC (rev 103473)
+++ trunk/extensions/HashTables/README 2011-11-17 16:41:26 UTC (rev 103474)
@@ -1,6 +1,6 @@
== About ==
-The ''HashTables'' extension Enhances the parser with hash table functions and
a function
+The 'HashTables' extension Enhances the parser with hash table functions and a
function
to store all parameters given to a template.
* Website: http://www.mediawiki.org/wiki/Extension:HashTables
@@ -20,7 +20,7 @@
== Contributing ==
-If you have bug reports or feature requests, please add them to the
''HashTables''
+If you have bug reports or feature requests, please add them to the
'HashTables'
Talk page [0]. You can also send them to Daniel Werner < [email protected] >
[0] http://www.mediawiki.org/w/index.php?title=Extension_talk:HashTables
Modified: trunk/extensions/HashTables/RELEASE-NOTES
===================================================================
--- trunk/extensions/HashTables/RELEASE-NOTES 2011-11-17 16:25:25 UTC (rev
103473)
+++ trunk/extensions/HashTables/RELEASE-NOTES 2011-11-17 16:41:26 UTC (rev
103474)
@@ -1,7 +1,15 @@
Changelog:
==========
+
+ * (trunk) Version 0.8
+ This release has lots of internal changes in it. All functions representing
a parser funcdtions now
+ use a 'pf_' or 'pfObj_' prefix, are declared static and there are
new/changed public functions for
+ interaction with 'HashTables' extension.
+ - Compatbility with other extensions increased by using one hash tables
store per Parser instance.
+ - Inclusion of special pages in the middle of the page won't reset all
defined hash tables anymore.
+
- * November 4, 2011 version 0.7
+ * November 4, 2011 -- Version 0.7
- buggy behavior in 'hashkeyexists' which led to expanding both arguments
'yes' and 'no' in
case custom arguments were given is solved. Now only the one actual case
is being expanded.
- 'hashtotemplate' now changes '{' to '{' since '{{' made some
problems in some cases.
@@ -14,48 +22,48 @@
- distributed under ISC license.
- * August 3, 2011 version 0.6.3
+ * August 3, 2011 -- Version 0.6.3
- minor bug in 'parameterstohash' function solved.
- * March 29, 2011 version 0.6.2
+ * March 29, 2011 -- Version 0.6.2
- 'hashtotemplate' has a new parameter to define a string which will
replace pipes '|'. Can be
useful to preserve links.
- * January 24, 2011 version 0.6.1
+ * January 24, 2011 -- Version 0.6.1
- Constant VERSION and function getHash() added to class ExtHashTables.
- * January 19, 2011 version 0.6
+ * January 19, 2011 -- Version 0.6
- New public class methods for creating and removing hash tables. Good for
use by other extensions.
- New experimental function 'hashtotemplate'.
- * August 3, 2010 version 0.5.1
+ * August 3, 2010 -- Version 0.5.1
- Hashinclude didn't trim key and value so keys with ending space ' ' and
values with leading
space were possible when defining something like {{#hashinclude: a | a =
1}}
- * August 1, 2010 version 0.5
+ * August 1, 2010 -- Version 0.5
- New parameter for function 'hashtoarray' which allows to specify the name
of a second array
which will contain the key names.
- Function 'arraytohash' doesn't mind non existent arrays in parameter 2
anymore. This allows
to create an hash table with keys only.
- * July 20, 2010 version 0.4
+ * July 20, 2010 -- Version 0.4
- Removed critical bug. Some kind of "Superglobal" HashTables on page
imports and job queue jobs.
Values were passed from one page to another page.
- * June 11, 2010 version 0.3
+ * June 11, 2010 -- Version 0.3
- Third parameter for 'arraytohash' allows to set a key array.
- New function 'hashkeyexists'.
- * June 6, 2010 version 0.2
+ * June 6, 2010 -- Version 0.2
- New functions 'hashmerge', 'hashmix', 'hashdiff', 'hashinclude' and
'hashexclude'.
- New functions if 'ArrayExtension' is available in the wiki: 'hashtoarray'
and 'arraytohash'.
- New parameter for 'hashprint' which allows to define the print order thru
an array.
- * Mai 30, 2010 version 0.1
+ * Mai 30, 2010 -- Version 0.1
- First version of HashTables featuring the functions 'hashdefine',
'hashvalue', 'hashsize',
'hashprint', 'hashreset' and 'parameterstohash'.
_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs