Extension:ParserFunctions/Extended
![]() |
This extension stores its source code on a wiki page. Please be aware that this code may be unreviewed or maliciously altered. They may contain security holes, outdated interfaces that are no longer compatible etc. Note: No localisation updates are provided for this extension by translatewiki.net. |
Note: this extension has been useful when ParserFunctions was more limited than it is now. Most of the functionality of this extension is now in the regular ParserFunctions.
This extension consists of ParserFunctions after applying patch [1] by Carl Fürstenberg. The next section gives the resulting Expr.php after applying the patch to [2]. The following section gives the resulting Expr.php after applying the patch to [3], and adapting it to the changed error handling [4].
With this extension scientific notation is not only produced as output, but also allowed as input. Also the power sign ^ works.
Further it includes the PHP functions abs, floor, ceil, fmod, and sqrt, and a function idiv which applies conversion to an integer by the PHP function "(int)" (rounding towards zero) to the quotient of the arguments.
Finally it contains the functions #min and #max, which are the PHP functions min and max, for the case that each argument is numeric.
Examples:
- {{#expr:2e3^10}} gives 1.024E+033
- {{#expr:-10 fmod 7}} gives -3
- {{#expr:-10 idiv 7}} gives -1
- {{#expr:floor (-10/7)}} gives -2
- {{#expr:ceil (-10/7)}} gives -1
- {{#expr:abs-3}} gives 3
- {{#expr:sqrt3}} gives 1.7320508075689
- {{#min:4e3|3e4|35*450}} gives 4000
- {{#max:4e3|3e4|35*450}} gives 30000
Expr.php (extended)[edit | edit source]
<?php if ( !defined( 'MEDIAWIKI' ) ) { die( 'This file is a MediaWiki extension, it is not a valid entry point' ); } // Character classes define( 'EXPR_WHITE_CLASS', " \t\r\n" ); define( 'EXPR_NUMBER_CLASS', '0123456789.' ); // Token types define( 'EXPR_WHITE', 1 ); define( 'EXPR_NUMBER', 2 ); define( 'EXPR_NEGATIVE', 3 ); define( 'EXPR_POSITIVE', 4 ); define( 'EXPR_PLUS', 5 ); define( 'EXPR_MINUS', 6 ); define( 'EXPR_TIMES', 7 ); define( 'EXPR_DIVIDE', 8 ); define( 'EXPR_MOD', 9 ); define( 'EXPR_OPEN', 10 ); define( 'EXPR_CLOSE', 11 ); define( 'EXPR_AND', 12 ); define( 'EXPR_OR', 13 ); define( 'EXPR_NOT', 14 ); define( 'EXPR_EQUALITY', 15 ); define( 'EXPR_LESS', 16 ); define( 'EXPR_GREATER', 17 ); define( 'EXPR_LESSEQ', 18 ); define( 'EXPR_GREATEREQ', 19 ); define( 'EXPR_NOTEQ', 20 ); define( 'EXPR_ROUND', 21 ); define( 'EXPR_INT_DIVIDE', 22); define( 'EXPR_CEIL', 23); define( 'EXPR_FLOOR', 24); define( 'EXPR_ABS', 25); define( 'EXPR_FLOAT_MOD', 26); define( 'EXPR_POW', 27); define( 'EXPR_SQRT', 28); define( 'EXPR_E', 29); class ExprError extends Exception { public function __construct($msg, $parameter = ''){ $this->message = wfMsgForContent( "expr_$msg", htmlspecialchars( $parameter ) ); } } class ExprParser { var $maxStackSize = 100; var $precedence = array( EXPR_NEGATIVE => 10, EXPR_POSITIVE => 10, EXPR_E => 10, EXPR_NOT => 9, EXPR_ABS => 9, EXPR_CEIL => 9, EXPR_FLOOR => 9, EXPR_POW => 9, EXPR_SQRT => 9, EXPR_TIMES => 8, EXPR_DIVIDE => 8, EXPR_INT_DIVIDE => 8, EXPR_MOD => 8, EXPR_FLOAT_MOD => 8, EXPR_PLUS => 6, EXPR_MINUS => 6, EXPR_ROUND => 5, EXPR_EQUALITY => 4, EXPR_LESS => 4, EXPR_GREATER => 4, EXPR_LESSEQ => 4, EXPR_GREATEREQ => 4, EXPR_NOTEQ => 4, EXPR_AND => 3, EXPR_OR => 2, EXPR_OPEN => -1, EXPR_CLOSE => -1 ); var $names = array( EXPR_NEGATIVE => '-', EXPR_POSITIVE => '+', EXPR_NOT => 'not', EXPR_TIMES => '*', EXPR_DIVIDE => '/', EXPR_MOD => 'mod', EXPR_FLOAT_MOD => 'fmod', EXPR_PLUS => '+', EXPR_MINUS => '-', EXPR_ROUND => 'round', EXPR_EQUALITY => '=', EXPR_LESS => '<', EXPR_GREATER => '>', EXPR_LESSEQ => '<=', EXPR_GREATEREQ => '>=', EXPR_NOTEQ => '<>', EXPR_AND => 'and', EXPR_OR => 'or', EXPR_INT_DIVIDE => 'idiv', EXPR_ABS => 'abs', EXPR_CEIL => 'ceil', EXPR_FLOOR => 'floor', EXPR_POW => '^', EXPR_SQRT => 'sqrt', EXPR_E => 'e', ); var $words = array( 'mod' => EXPR_MOD, 'and' => EXPR_AND, 'or' => EXPR_OR, 'not' => EXPR_NOT, 'round' => EXPR_ROUND, 'div' => EXPR_DIVIDE, 'idiv' => EXPR_INT_DIVIDE, 'floor' => EXPR_FLOOR, 'ceil' => EXPR_CEIL, 'abs' => EXPR_ABS, 'fmod' => EXPR_FLOAT_MOD, 'sqrt' => EXPR_SQRT, 'e' => EXPR_E, ); /** * Add expression messages to the message cache * @static */ function addMessages() { global $wgMessageCache; $wgMessageCache->addMessages( array( 'expr_stack_exhausted' => 'Expression error: Stack exhausted', 'expr_unexpected_number' => 'Expression error: Unexpected number', 'expr_preg_match_failure' => 'Expression error: Unexpected preg_match failure', 'expr_unrecognised_word' => 'Expression error: Unrecognised word "$1"', 'expr_unexpected_operator' => 'Expression error: Unexpected $1 operator', 'expr_missing_operand' => 'Expression error: Missing operand for $1', 'expr_unexpected_closing_bracket' => 'Expression error: Unexpected closing bracket', 'expr_unrecognised_punctuation' => 'Expression error: Unrecognised punctuation character "$1"', 'expr_unclosed_bracket' => 'Expression error: Unclosed bracket', 'expr_division_by_zero' => 'Division by zero', 'expr_unknown_error' => 'Expression error: Unknown error ($1)', 'expr_not_a_number' => 'In $1: result is not a number', )); } /** * Evaluate a mathematical expression * * The algorithm here is based on the infix to RPN algorithm given in * http://montcs.bloomu.edu/~bobmon/Information/RPN/infix2rpn.shtml * It's essentially the same as Dijkstra's shunting yard algorithm. */ function doExpression( $expr ) { $operands = array(); $operators = array(); # Unescape inequality operators $expr = strtr( $expr, array( '<' => '<', '>' => '>' ) ); $p = 0; $end = strlen( $expr ); $expecting = 'expression'; while ( $p < $end ) { if ( count( $operands ) > $this->maxStackSize || count( $operators ) > $this->maxStackSize ) { throw new ExprError('stack_exhausted'); } $char = $expr[$p]; $char2 = substr( $expr, $p, 2 ); // Mega if-elseif-else construct // Only binary operators fall through for processing at the bottom, the rest // finish their processing and continue // First the unlimited length classes if ( false !== strpos( EXPR_WHITE_CLASS, $char ) ) { // Whitespace $p += strspn( $expr, EXPR_WHITE_CLASS, $p ); continue; } elseif ( false !== strpos( EXPR_NUMBER_CLASS, $char ) ) { // Number if ( $expecting != 'expression' ) { throw new ExprError('unexpected_number'); } // Find the rest of it $length = strspn( $expr, EXPR_NUMBER_CLASS, $p ); // Convert it to float, silently removing double decimal points $operands[] = floatval( substr( $expr, $p, $length ) ); $p += $length; $expecting = 'operator'; continue; } elseif ( ctype_alpha( $char ) ) { // Word // Find the rest of it $remaining = substr( $expr, $p ); if ( !preg_match( '/^[A-Za-z]*/', $remaining, $matches ) ) { // This should be unreachable throw new ExprError('preg_match_failure'); } $word = strtolower( $matches[0] ); $p += strlen( $word ); // Interpret the word if ( !isset( $this->words[$word] ) ){ throw new ExprError('unrecognised_word', $word); } $op = $this->words[$word]; // Unary operator switch($op){ case EXPR_NOT: case EXPR_CEIL: case EXPR_FLOOR: case EXPR_ABS: case EXPR_SQRT: if ( $expecting != 'expression' ) { throw new ExprError('unexpected_operator', $word); } $operators[] = $op; continue 2; } // Binary operator, fall through $name = $word; } // Next the two-character operators elseif ( $char2 == '<=' ) { $name = $char2; $op = EXPR_LESSEQ; $p += 2; } elseif ( $char2 == '>=' ) { $name = $char2; $op = EXPR_GREATEREQ; $p += 2; } elseif ( $char2 == '<>' || $char2 == '!=' ) { $name = $char2; $op = EXPR_NOTEQ; $p += 2; } // Finally the single-character operators elseif ( $char == '+' ) { ++$p; if ( $expecting == 'expression' ) { // Unary plus $operators[] = EXPR_POSITIVE; continue; } else { // Binary plus $op = EXPR_PLUS; } } elseif ( $char == '-' ) { ++$p; if ( $expecting == 'expression' ) { // Unary minus $operators[] = EXPR_NEGATIVE; continue; } else { // Binary minus $op = EXPR_MINUS; } } elseif ( $char == '*' ) { $name = $char; $op = EXPR_TIMES; ++$p; } elseif ( $char == '/' ) { $name = $char; $op = EXPR_DIVIDE; ++$p; } elseif ( $char == '(' ) { if ( $expecting == 'operator' ) { throw new ExprError('unexpected_operator', '('); } $operators[] = EXPR_OPEN; ++$p; continue; } elseif ( $char == ')' ) { $lastOp = end( $operators ); while ( $lastOp && $lastOp != EXPR_OPEN ) { $this->doOperation( $lastOp, $operands ); array_pop( $operators ); $lastOp = end( $operators ); } if ( $lastOp ) { array_pop( $operators ); } else { throw new ExprError('unexpected_closing_bracket'); } $expecting = 'operator'; ++$p; continue; } elseif ( $char == '=' ) { $name = $char; $op = EXPR_EQUALITY; ++$p; } elseif ( $char == '<' ) { $name = $char; $op = EXPR_LESS; ++$p; } elseif ( $char == '>' ) { $name = $char; $op = EXPR_GREATER; ++$p; } elseif ( $char == '^' ) { $name = $char; $op = EXPR_POW; ++$p; } else { throw new ExprError('unrecognised_punctuation', $char); } // Binary operator processing if ( $expecting == 'expression' ) { throw new ExprError('unexpected_operator', $name); } // Shunting yard magic $lastOp = end( $operators ); while ( $lastOp && $this->precedence[$op] <= $this->precedence[$lastOp] ) { $this->doOperation( $lastOp, $operands ); array_pop( $operators ); $lastOp = end( $operators ); } $operators[] = $op; $expecting = 'expression'; } // Finish off the operator array while ( $op = array_pop( $operators ) ) { if ( $op == EXPR_OPEN ) { throw new ExprError('unclosed_bracket'); } $this->doOperation( $op, $operands ); } return implode( "<br />\n", $operands ); } function doOperation( $op, &$stack ) { switch ( $op ) { case EXPR_NEGATIVE: if ( count( $stack ) < 1 ) throw new ExprError('missing_operand', $this->names[$op]); $arg = array_pop( $stack ); $stack[] = -$arg; break; case EXPR_POSITIVE: if ( count( $stack ) < 1 ) throw new ExprError('missing_operand', $this->names[$op]); break; case EXPR_TIMES: if ( count( $stack ) < 2 ) throw new ExprError('missing_operand', $this->names[$op]); $right = array_pop( $stack ); $left = array_pop( $stack ); $stack[] = $left * $right; break; case EXPR_DIVIDE: if ( count( $stack ) < 2 ) throw new ExprError('missing_operand', $this->names[$op]); $right = array_pop( $stack ); $left = array_pop( $stack ); if ( $right == 0 ) throw new ExprError('division_by_zero', $this->names[$op]); $stack[] = $left / $right; break; case EXPR_MOD: if ( count( $stack ) < 2 ) throw new ExprError('missing_operand', $this->names[$op]); $right = array_pop( $stack ); $left = array_pop( $stack ); if ( $right == 0 ) throw new ExprError('division_by_zero', $this->names[$op]); $stack[] = $left % $right; break; case EXPR_PLUS: if ( count( $stack ) < 2 ) throw new ExprError('missing_operand', $this->names[$op]); $right = array_pop( $stack ); $left = array_pop( $stack ); $stack[] = $left + $right; break; case EXPR_MINUS: if ( count( $stack ) < 2 ) throw new ExprError('missing_operand', $this->names[$op]); $right = array_pop( $stack ); $left = array_pop( $stack ); $stack[] = $left - $right; break; case EXPR_AND: if ( count( $stack ) < 2 ) throw new ExprError('missing_operand', $this->names[$op]); $right = array_pop( $stack ); $left = array_pop( $stack ); $stack[] = ( $left && $right ) ? 1 : 0; break; case EXPR_OR: if ( count( $stack ) < 2 ) throw new ExprError('missing_operand', $this->names[$op]); $right = array_pop( $stack ); $left = array_pop( $stack ); $stack[] = ( $left || $right ) ? 1 : 0; break; case EXPR_EQUALITY: if ( count( $stack ) < 2 ) throw new ExprError('missing_operand', $this->names[$op]); $right = array_pop( $stack ); $left = array_pop( $stack ); $stack[] = ( $left == $right ) ? 1 : 0; break; case EXPR_NOT: if ( count( $stack ) < 1 ) throw new ExprError('missing_operand', $this->names[$op]); $arg = array_pop( $stack ); $stack[] = (!$arg) ? 1 : 0; break; case EXPR_ROUND: if ( count( $stack ) < 2 ) throw new ExprError('missing_operand', $this->names[$op]); $digits = intval( array_pop( $stack ) ); $value = array_pop( $stack ); $stack[] = round( $value, $digits ); break; case EXPR_LESS: if ( count( $stack ) < 2 ) throw new ExprError('missing_operand', $this->names[$op]); $right = array_pop( $stack ); $left = array_pop( $stack ); $stack[] = ( $left < $right ) ? 1 : 0; break; case EXPR_GREATER: if ( count( $stack ) < 2 ) throw new ExprError('missing_operand', $this->names[$op]); $right = array_pop( $stack ); $left = array_pop( $stack ); $stack[] = ( $left > $right ) ? 1 : 0; break; case EXPR_LESSEQ: if ( count( $stack ) < 2 ) throw new ExprError('missing_operand', $this->names[$op]); $right = array_pop( $stack ); $left = array_pop( $stack ); $stack[] = ( $left <= $right ) ? 1 : 0; break; case EXPR_GREATEREQ: if ( count( $stack ) < 2 ) throw new ExprError('missing_operand', $this->names[$op]); $right = array_pop( $stack ); $left = array_pop( $stack ); $stack[] = ( $left >= $right ) ? 1 : 0; break; case EXPR_NOTEQ: if ( count( $stack ) < 2 ) throw new ExprError('missing_operand', $this->names[$op]); $right = array_pop( $stack ); $left = array_pop( $stack ); $stack[] = ( $left != $right ) ? 1 : 0; break; case EXPR_ABS: if ( count( $stack ) < 1 ) throw new ExprError('missing_operand', $this->names[$op]); $arg = array_pop( $stack ); $stack[] = abs($arg); break; case EXPR_CEIL: if ( count( $stack ) < 1 ) throw new ExprError('missing_operand', $this->names[$op]); $arg = array_pop( $stack ); $stack[] = ceil($arg); break; case EXPR_FLOOR: if ( count( $stack ) < 1 ) throw new ExprError('missing_operand', $this->names[$op]); $arg = array_pop( $stack ); $stack[] = floor($arg); break; case EXPR_E: if ( count( $stack ) < 2 ) throw new ExprError('missing_operand', $this->names[$op]); $right = array_pop( $stack ); $left = array_pop( $stack ); // can never be NaN $stack[] = $left * pow(10,$right); break; case EXPR_POW: if ( count( $stack ) < 2 ) throw new ExprError('missing_operand', $this->names[$op]); $right = array_pop( $stack ); $left = array_pop( $stack ); $result = pow($left,$right); if (is_nan($result)) throw new ExprError('not_a_number', $this->names[$op]); $stack[] = $result; break; case EXPR_FLOAT_MOD: if ( count( $stack ) < 2 ) throw new ExprError('missing_operand', $this->names[$op]); $right = array_pop( $stack ); $left = array_pop( $stack ); if ( $right == 0 ) throw new ExprError('division_by_zero', $this->names[$op]); $stack[] = fmod($left,$right); break; case EXPR_SQRT: if ( count( $stack ) < 1 ) throw new ExprError('missing_operand', $this->names[$op]); $arg = array_pop( $stack ); $result = sqrt($arg); if (is_nan($result)) throw new ExprError('not_a_number', $this->names[$op]); $stack[] = $result; break; case EXPR_INT_DIVIDE: if ( count( $stack ) < 2 ) throw new ExprError('missing_operand', $this->names[$op]); $right = array_pop( $stack ); $left = array_pop( $stack ); if ( $right == 0 ) throw new ExprError('division_by_zero', $this->names[$op]); $stack[] = (int)($left / $right); break; default: // Should be impossible to reach here. throw new ExprError('unknown_error'); } } }
ParserFunctions.php (extended)[edit | edit source]
<?php if ( !defined( 'MEDIAWIKI' ) ) { die( 'This file is a MediaWiki extension, it is not a valid entry point' ); } $wgExtensionFunctions[] = 'wfSetupParserFunctions'; $wgExtensionCredits['parserhook'][] = array( 'name' => 'ParserFunctions (extended)', 'url' => 'http://meta.wikimedia.org/wiki/ParserFunctions', 'author' => 'Tim Starling, Carl Fürstenberg (AzaToth)', 'description' => 'Enhance parser with mathematical and logical functions', ); $wgHooks['LanguageGetMagic'][] = 'wfParserFunctionsLanguageGetMagic'; class ExtParserFunctions { var $mExprParser; var $mTimeCache = array(); var $mTimeChars = 0; var $mMaxTimeChars = 6000; # ~10 seconds function clearState() { $this->mTimeChars = 0; return true; } function &getExprParser() { if ( !isset( $this->mExpr ) ) { if ( !class_exists( 'ExprParser' ) ) { require( dirname( __FILE__ ) . '/Expr.php' ); ExprParser::addMessages(); } $this->mExprParser = new ExprParser; } return $this->mExprParser; } function expr( &$parser, $expr = '' ) { try { return $this->getExprParser()->doExpression( $expr ); } catch(ExprError $e) { return $e->getMessage(); } } function maxHook(&$parser) { try { $args = func_get_args(); array_shift( $args ); $exprParser = $this->getExprParser(); foreach($args as $expr){ $res = $exprParser->doExpression($expr); $result[] = $res; } return max($result); } catch(ExprError $e) { return $e->getMessage(); } } function minHook(&$parser) { try { $args = func_get_args(); array_shift( $args ); $exprParser = $this->getExprParser(); foreach($args as $expr){ $res = $exprParser->doExpression($expr); $result[] = $res; } return min($result); } catch(ExprError $e) { return $e->getMessage(); } } function ifexpr( &$parser, $expr = '', $then = '', $else = '' ) { try{ if($this->getExprParser()->doExpression( $expr )) { return $then; } else { return $else; } } catch (ExprError $e){ return $e->getMessage(); } } function ifHook( &$parser, $test = '', $then = '', $else = '' ) { if ( $test !== '' ) { return $then; } else { return $else; } } function ifeq( &$parser, $left = '', $right = '', $then = '', $else = '' ) { if ( $left == $right ) { return $then; } else { return $else; } } function switchHook( &$parser /*,...*/ ) { $args = func_get_args(); array_shift( $args ); $value = trim(array_shift($args)); $found = false; $parts = null; $default = null; foreach( $args as $arg ) { $parts = array_map( 'trim', explode( '=', $arg, 2 ) ); if ( count( $parts ) == 2 ) { if ( $found || $parts[0] == $value ) { return $parts[1]; } else { $mwDefault =& MagicWord::get( 'default' ); if ( $mwDefault->matchStartAndRemove( $parts[0] ) ) { $default = $parts[1]; } # else wrong case, continue } } elseif ( count( $parts ) == 1 ) { # Multiple input, single output # If the value matches, set a flag and continue if ( $parts[0] == $value ) { $found = true; } } # else RAM corruption due to cosmic ray? } # Default case # Check if the last item had no = sign, thus specifying the default case if ( count( $parts ) == 1) { return $parts[0]; } elseif ( !is_null( $default ) ) { return $default; } else { return ''; } } /** * Returns the absolute path to a subpage, relative to the current article * title. Treats titles as slash-separated paths. * * Following subpage link syntax instead of standard path syntax, an * initial slash is treated as a relative path, and vice versa. */ public function rel2abs( &$parser , $to = '' , $from = '' ) { $from = trim($from); if( $from == '' ) { $from = $parser->mTitle->getPrefixedText(); } $to = rtrim( $to , ' /' ); // if we have an empty path, or just one containing a dot if( $to == '' || $to == '.' ) { return $from; } // if the path isn't relative if ( substr( $to , 0 , 1) != '/' && substr( $to , 0 , 2) != './' && substr( $to , 0 , 3) != '../' && $to != '..' ) { $from = ''; } // Make a long path, containing both, enclose it in /.../ $fullPath = '/' . $from . '/' . $to . '/'; // remove redundant current path dots $fullPath = preg_replace( '!/(\./)+!', '/', $fullPath ); // remove double slashes $fullPath = preg_replace( '!/{2,}!', '/', $fullPath ); // remove the enclosing slashes now $fullPath = trim( $fullPath , '/' ); $exploded = explode ( '/' , $fullPath ); $newExploded = array(); foreach ( $exploded as $current ) { if( $current == '..' ) { // removing one level if( !count( $newExploded ) ){ // attempted to access a node above root node return wfMsgForContent( 'pfunc_rel2abs_invalid_depth', $fullPath ); } // remove last level from the stack array_pop( $newExploded ); } else { // add the current level to the stack $newExploded[] = $current; } } // we can now join it again return implode( '/' , $newExploded ); } function ifexist( &$parser, $title = '', $then = '', $else = '' ) { $title = Title::newFromText( $title ); return is_object( $title ) && $title->exists() ? $then : $else; } function time( &$parser, $format = '', $date = '' ) { global $wgContLang; if ( isset( $this->mTimeCache[$format][$date] ) ) { return $this->mTimeCache[$format][$date]; } if ( $date !== '' ) { $unix = @strtotime( $date ); } else { $unix = time(); } if ( $unix == -1 || $unix == false ) { $result = wfMsgForContent( 'pfunc_time_error' ); } else { $this->mTimeChars += strlen( $format ); if ( $this->mTimeChars > $this->mMaxTimeChars ) { return wfMsgForContent( 'pfunc_time_too_long' ); } else { $ts = wfTimestamp( TS_MW, $unix ); if ( method_exists( $wgContLang, 'sprintfDate' ) ) { $result = $wgContLang->sprintfDate( $format, $ts ); } else { if ( !class_exists( 'SprintfDateCompat' ) ) { require( dirname( __FILE__ ) . '/SprintfDateCompat.php' ); } $result = SprintfDateCompat::sprintfDate( $format, $ts ); } } } $this->mTimeCache[$format][$date] = $result; return $result; } } function wfSetupParserFunctions() { global $wgParser, $wgMessageCache, $wgExtParserFunctions, $wgMessageCache, $wgHooks; $wgExtParserFunctions = new ExtParserFunctions; $wgParser->setFunctionHook( 'expr', array( &$wgExtParserFunctions, 'expr' ) ); $wgParser->setFunctionHook( 'if', array( &$wgExtParserFunctions, 'ifHook' ) ); $wgParser->setFunctionHook( 'ifeq', array( &$wgExtParserFunctions, 'ifeq' ) ); $wgParser->setFunctionHook( 'ifexpr', array( &$wgExtParserFunctions, 'ifexpr' ) ); $wgParser->setFunctionHook( 'switch', array( &$wgExtParserFunctions, 'switchHook' ) ); $wgParser->setFunctionHook( 'ifexist', array( &$wgExtParserFunctions, 'ifexist' ) ); $wgParser->setFunctionHook( 'time', array( &$wgExtParserFunctions, 'time' ) ); $wgParser->setFunctionHook( 'max', array( &$wgExtParserFunctions, 'maxHook' ) ); $wgParser->setFunctionHook( 'min', array( &$wgExtParserFunctions, 'minHook' ) ); $wgParser->setFunctionHook( 'rel2abs', array( &$wgExtParserFunctions, 'rel2abs' ) ); $wgMessageCache->addMessage( 'pfunc_time_error', "Error: invalid time" ); $wgMessageCache->addMessage( 'pfunc_time_too_long', "Error: too many #time calls" ); $wgMessageCache->addMessage( 'pfunc_rel2abs_invalid_depth', "Error: Invalid depth in path: \"$1\" (tried to access a node above the root node)" ); $wgHooks['ParserClearState'][] = array( &$wgExtParserFunctions, 'clearState' ); } function wfParserFunctionsLanguageGetMagic( &$magicWords, $langCode ) { switch ( $langCode ) { case 'he': $magicWords['expr'] = array( 0, 'חשב', 'expr' ); $magicWords['if'] = array( 0, 'תנאי', 'if' ); $magicWords['ifeq'] = array( 0, 'שווה', 'ifeq' ); $magicWords['ifexpr'] = array( 0, 'חשב תנאי', 'ifexpr' ); $magicWords['switch'] = array( 0, 'בחר', 'switch' ); $magicWords['default'] = array( 0, '#ברירת מחדל', '#default' ); $magicWords['ifexist'] = array( 0, 'קיים', 'ifexist' ); $magicWords['time'] = array( 0, 'זמן', 'time' ); $magicWords['rel2abs'] = array( 0, 'יחסי למוחלט', 'rel2abs' ); break; default: $magicWords['expr'] = array( 0, 'expr' ); $magicWords['if'] = array( 0, 'if' ); $magicWords['ifeq'] = array( 0, 'ifeq' ); $magicWords['ifexpr'] = array( 0, 'ifexpr' ); $magicWords['switch'] = array( 0, 'switch' ); $magicWords['default'] = array( 0, '#default' ); $magicWords['ifexist'] = array( 0, 'ifexist' ); $magicWords['time'] = array( 0, 'time' ); $magicWords['max'] = array( 0, 'max' ); $magicWords['min'] = array( 0, 'min' ); $magicWords['rel2abs'] = array( 0, 'rel2abs' ); } return true; }