Extension:LO Parser Functions
From MediaWiki.org
LO ParserFunctions Release status: Beta |
|
---|---|
Implementation | Parser extension, Parser function |
Description | A collection of parser functions such as expression handling and time calculation unit. |
Author(s) | Tim Starling (this extraction from his ParserFunctions extension is maintained by David M. Sledge) |
Last version | N/A (2007-11-15) |
MediaWiki | > 1.6.8 |
License | GNU GPL 2.0 or later |
Download | No link |
Check usage (experimental) |
This extension contains the parser functions from the ParserFunctions extension that aren't in the control structure functions extension; #expr, #time, and #rel2abs. See ParserFunctions for usage.
[edit] Installation
See Replacing ParserFunctions with Control Structure Functions before installing.
Download the file Expr.php and put it in a new directory called LOParserFunctions in your extensions directory. Then in the new directory, create the files LOParserFunctions.php and LOParserFunctions.i18n.php that contains the following source code:
LOParserFunctions.php:
<?php if ( !defined( 'MEDIAWIKI' ) ) { die( 'This file is a MediaWiki extension, it is not a valid entry point' ); } $wgExtensionFunctions[] = 'wfSetupLOParserFunctions'; $wgExtensionCredits['parserhook'][] = array( 'name' => 'Left-Over Parser Functions', 'url' => 'http://www.mediawiki.org/wiki/Extension:LO_Parser_Functions', 'author' => 'Tim Starling', 'description' => 'Enhance parser with logical functions', ); $wgHooks['LanguageGetMagic'][] = 'wfLOParserFunctionsLanguageGetMagic'; class ExtLOParserFunctions { 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->mExprParser ) ) { 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(); } } /** * 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->getTitle()->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 time( &$parser, $format = '', $date = '', $local = false ) { global $wgContLang, $wgLocaltimezone; if ( isset( $this->mTimeCache[$format][$date][$local] ) ) { return $this->mTimeCache[$format][$date][$local]; } 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 { if ( $local ) { # Use the time zone if ( isset( $wgLocaltimezone ) ) { $oldtz = getenv( 'TZ' ); putenv( 'TZ='.$wgLocaltimezone ); } wfSuppressWarnings(); // E_STRICT system time bitching $ts = date( 'YmdHis', $unix ); wfRestoreWarnings(); if ( isset( $wgLocaltimezone ) ) { putenv( 'TZ='.$oldtz ); } } 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][$local] = $result; return $result; } function localTime( &$parser, $format = '', $date = '' ) { return $this->time( $parser, $format, $date, true ); } /** * Obtain a specified number of slash-separated parts of a title, * e.g. {{#titleparts:Hello/World|1}} => "Hello" * * @param Parser $parser Parent parser * @param string $title Title to split * @param int $parts Number of parts to keep * @param int $offset Offset starting at 1 * @return string */ public function titleparts( $parser, $title = '', $parts = -1, $offset = 1 ) { $parts = intval( $parts ); $offset = intval( $offset ) - 1; $ntitle = Title::newFromText( $title ); if( $ntitle instanceof Title ) { $bits = explode( '/', $ntitle->getPrefixedText() ); if( $parts <= 0 || $parts > count( $bits ) ) { return $ntitle->getPrefixedText(); } elseif( $offset < 0 || $offset > count( $bits ) ) { return $ntitle->getPrefixedText(); } else { $keep = array(); for( $i = 0; $i < $offset; $i++ ) array_shift( $bits ); for( $i = 0; $i < $parts; $i++ ) $keep[] = array_shift( $bits ); return implode( '/', $keep ); } } else { return $title; } } } function wfSetupLOParserFunctions() { global $wgParser, $wgMessageCache, $wgExtLOParserFunctions, $wgMessageCache, $wgHooks; $wgExtLOParserFunctions = new ExtLOParserFunctions; $wgParser->setFunctionHook( 'expr', array( &$wgExtLOParserFunctions, 'expr' ) ); $wgParser->setFunctionHook( 'time', array( &$wgExtLOParserFunctions, 'time' ) ); $wgParser->setFunctionHook( 'timel', array( &$wgExtLOParserFunctions, 'localTime' ) ); $wgParser->setFunctionHook( 'rel2abs', array( &$wgExtLOParserFunctions, 'rel2abs' ) ); $wgParser->setFunctionHook( 'titleparts', array( &$wgExtLOParserFunctions, 'titleparts' ) ); require_once( dirname( __FILE__ ) . '/LOParserFunctions.i18n.php' ); foreach( efLOParserFunctionsMessages() as $lang => $messages ) $wgMessageCache->addMessages( $messages, $lang ); $wgHooks['ParserClearState'][] = array( &$wgExtLOParserFunctions, 'clearState' ); } function wfLOParserFunctionsLanguageGetMagic( &$magicWords, $langCode ) { require_once( dirname( __FILE__ ) . '/LOParserFunctions.i18n.php' ); foreach( efLOParserFunctionsWords( $langCode ) as $word => $trans ) $magicWords[$word] = $trans; return true; }
LOParserFunctions.i18n.php:
<?php /** * Get translated magic words, if available * * @param string $lang Language code * @return array */ function efLOParserFunctionsWords( $lang ) { $words = array(); /** * English */ $words['en'] = array( 'expr' => array( 0, 'expr' ), 'time' => array( 0, 'time' ), 'timel' => array( 0, 'timel' ), 'rel2abs' => array( 0, 'rel2abs' ), 'titleparts' => array( 0, 'titleparts' ), ); /** * Farsi-Persian */ $words['fa'] = array( 'expr' => array( 0, 'ØØ³Ø§Ø¨', 'expr' ), 'time' => array( 0, 'زمان', 'time' ), 'rel2abs' => array( 0, 'نسبی‌به‌مطلق', 'rel2abs' ), ); /** * Hebrew */ $words['he'] = array( 'expr' => array( 0, 'חשב', 'expr' ), 'time' => array( 0, 'זמן', 'time' ), 'timel' => array( 0, 'זמןמ', 'timel' ), 'rel2abs' => array( 0, 'יחסי למוחלט', 'rel2abs' ), 'titleparts' => array( 0, 'חלק בכותרת', 'titleparts' ), ); /** * Indonesian */ $words['id'] = array( 'expr' => array( 0, 'hitung', 'expr' ), 'time' => array( 0, 'waktu', 'time' ), 'rel2abs' => array( 0, 'rel2abs' ), 'titleparts' => array( 0, 'bagianjudul', 'titleparts' ), ); # English is used as a fallback, and the English synonyms are # used if a translation has not been provided for a given word return ( $lang == 'en' || !isset( $words[$lang] ) ) ? $words['en'] : array_merge( $words['en'], $words[$lang] ); } /** * Get extension messages * * @return array */ function efLOParserFunctionsMessages() { $messages = array( /* English */ 'en' => array( 'pfunc_time_error' => 'Error: invalid time', 'pfunc_time_too_long' => 'Error: too many #time calls', 'pfunc_rel2abs_invalid_depth' => 'Error: Invalid depth in path: \"$1\" (tried to access a node above the root node)', ), /* German */ 'de' => array( 'pfunc_time_error' => 'Fehler: ungültige Zeitangabe', 'pfunc_time_too_long' => 'Fehler: zu viele #time-Aufrufe', 'pfunc_rel2abs_invalid_depth' => 'Fehler: ungültige Tiefe in Pfad: „$1“ (Versuch, auf einen Knotenpunkt oberhalb des Hauptknotenpunktes zuzugreifen)', ), /* French */ 'fr' => array( 'pfunc_time_error' => 'Erreur: durée invalide', 'pfunc_time_too_long' => 'Erreur: parser #time appelé trop de fois', 'pfunc_rel2abs_invalid_depth' => 'Erreur: niveau de répertoire invalide dans le chemin : \"$1\" (a essayé d’accéder à un niveau au-dessus du répertoire racine)', ), /* Hebrew */ 'he' => array( 'pfunc_time_error' => 'שגי×?×”: זמן שגוי', 'pfunc_time_too_long' => 'שגי×?×”: שימוש ב"#זמן" פעמי×? רבות מדי', 'pfunc_rel2abs_invalid_depth' => 'שגי×?×”: עומק שגוי ×‘× ×ª×™×‘: \"$1\" (× ×™×¡×™×•×Ÿ ×›× ×™×¡×” לצומת מעל צומת השורש)', ), /* Kazakh Cyrillic */ 'kk-kz' => array( 'pfunc_time_error' => 'Қате: жарамÑ?ыз уақыт', 'pfunc_time_too_long' => 'Қате: #time әмірін шақыруы тым көп', 'pfunc_rel2abs_invalid_depth' => 'Қате: Мына жолдың жарамÑ?ыз терендігі "$1" (тамыр түйіннің Ò¯Ñ?тіндегі түйінге қатынау талабы)', ), /* Kazakh Latin */ 'kk-tr' => array( 'pfunc_time_error' => 'Qate: jaramsız waqıt', 'pfunc_time_too_long' => 'Qate: #time ämirin ÅŸaqırwı tım köp', 'pfunc_rel2abs_invalid_depth' => 'Qate: Mına joldıñ jaramsız terendigi "$1" (tamır tüýinniñ üstindegi tüýinge qatınaw talabı)', ), /* Kazakh Arabic */ 'kk-cn' => array( 'pfunc_time_error' => 'قاتە: جارامسىز ۋاقىت', 'pfunc_time_too_long' => 'قاتە: #time ٵمٸرٸن شاقىرۋى تىم ÙƒÙ¶Ù¾', 'pfunc_rel2abs_invalid_depth' => 'قاتە: مىنا Ø¬ÙˆÙ„Ø¯Ù‰Ú Ø¬Ø§Ø±Ø§Ù…Ø³Ù‰Ø² تەرەندٸگٸ "$1" (تامىر ØªÙ·ÙŠÙ¸Ù†Ù†Ù¸Ú Ù·Ø³ØªÙ¸Ù†Ø¯Û•Ú¯Ù¸ تٷيٸنگە قاتىناۋ تالابى)', ), /* Dutch */ 'nl' => array( 'pfunc_time_error' => 'Fout: ongeldige tijd', 'pfunc_time_too_long' => 'Fout: #time te vaak aangeroepen', 'pfunc_rel2abs_invalid_depth' => 'Fout: ongeldige diepte in pad: \"$1\" (probeerde een node boven de stamnode aan te roepen)', ), /* Swedish */ 'sv' => array( 'pfunc_time_error' => 'Fel: ogiltig tid', 'pfunc_time_too_long' => 'Fel: för mÃ¥nga anrop av #time', 'pfunc_rel2abs_invalid_depth' => 'Fel: felaktig djup i sökväg: "$1" (försöker nÃ¥ en nod ovanför rotnoden)', ), /* Cantonese */ 'yue' => array( 'pfunc_time_error' => '錯: 唔啱嘅時間', 'pfunc_time_too_long' => '錯: 太多 #time 呼å?«', 'pfunc_rel2abs_invalid_depth' => '錯: 唔啱路徑嘅深度: \"$1\" (已經試é?Žç”±é 點è?½å€‹é»žåº¦)', ), /* Chinese (Simplified) */ 'zh-hans' => array( 'pfunc_time_error' => '错误: ä¸?æ£ç¡®çš„æ—¶é—´', 'pfunc_time_too_long' => '错误: 过多 #time 的呼å?«', 'pfunc_rel2abs_invalid_depth' => '错误: ä¸?æ£ç¡®çš„路径深度: \"$1\" (å·²ç»?å°?试在顶点访问该点)', ), /* Chinese (Traditional) */ 'zh-hant' => array( 'pfunc_time_error' => '錯誤: ä¸?æ£ç¢ºçš„æ™‚é–“', 'pfunc_time_too_long' => '錯誤: é?Žå¤š #time 的呼å?«', 'pfunc_rel2abs_invalid_depth' => '錯誤: ä¸?æ£ç¢ºçš„路徑深度: \"$1\" (å·²ç¶“å˜—è©¦åœ¨é ‚é»žå˜å?–該點)', ), ); /* Kazakh default, fallback to kk-kz */ $messages['kk'] = $messages['kk-kz']; /* Chinese defaults, fallback to zh-hans */ $messages['zh'] = $messages['zh-hans']; $messages['zh-cn'] = $messages['zh-hans']; $messages['zh-hk'] = $messages['zh-hant']; $messages['zh-sg'] = $messages['zh-hans']; $messages['zh-tw'] = $messages['zh-hant']; /* Cantonese default, fallback to yue */ $messages['zh-yue'] = $messages['yue']; return $messages ; }
Then put the following at the end of your LocalSettings.php:
require_once( "$IP/extensions/LOParserFunctions/LOParserFunctions.php" );