MediaWiki
REL1_23
|
00001 <?php 00028 class CoreParserFunctions { 00033 static function register( $parser ) { 00034 global $wgAllowDisplayTitle, $wgAllowSlowParserFunctions; 00035 00036 # Syntax for arguments (see self::setFunctionHook): 00037 # "name for lookup in localized magic words array", 00038 # function callback, 00039 # optional SFH_NO_HASH to omit the hash from calls (e.g. {{int:...}} 00040 # instead of {{#int:...}}) 00041 $noHashFunctions = array( 00042 'ns', 'nse', 'urlencode', 'lcfirst', 'ucfirst', 'lc', 'uc', 00043 'localurl', 'localurle', 'fullurl', 'fullurle', 'canonicalurl', 00044 'canonicalurle', 'formatnum', 'grammar', 'gender', 'plural', 00045 'numberofpages', 'numberofusers', 'numberofactiveusers', 00046 'numberofarticles', 'numberoffiles', 'numberofadmins', 00047 'numberingroup', 'numberofedits', 'numberofviews', 'language', 00048 'padleft', 'padright', 'anchorencode', 'defaultsort', 'filepath', 00049 'pagesincategory', 'pagesize', 'protectionlevel', 00050 'namespacee', 'namespacenumber', 'talkspace', 'talkspacee', 00051 'subjectspace', 'subjectspacee', 'pagename', 'pagenamee', 00052 'fullpagename', 'fullpagenamee', 'rootpagename', 'rootpagenamee', 00053 'basepagename', 'basepagenamee', 'subpagename', 'subpagenamee', 00054 'talkpagename', 'talkpagenamee', 'subjectpagename', 00055 'subjectpagenamee', 'pageid', 'revisionid', 'revisionday', 00056 'revisionday2', 'revisionmonth', 'revisionmonth1', 'revisionyear', 00057 'revisiontimestamp', 'revisionuser', 'cascadingsources', 00058 ); 00059 foreach ( $noHashFunctions as $func ) { 00060 $parser->setFunctionHook( $func, array( __CLASS__, $func ), SFH_NO_HASH ); 00061 } 00062 00063 $parser->setFunctionHook( 'namespace', array( __CLASS__, 'mwnamespace' ), SFH_NO_HASH ); 00064 $parser->setFunctionHook( 'int', array( __CLASS__, 'intFunction' ), SFH_NO_HASH ); 00065 $parser->setFunctionHook( 'special', array( __CLASS__, 'special' ) ); 00066 $parser->setFunctionHook( 'speciale', array( __CLASS__, 'speciale' ) ); 00067 $parser->setFunctionHook( 'tag', array( __CLASS__, 'tagObj' ), SFH_OBJECT_ARGS ); 00068 $parser->setFunctionHook( 'formatdate', array( __CLASS__, 'formatDate' ) ); 00069 00070 if ( $wgAllowDisplayTitle ) { 00071 $parser->setFunctionHook( 'displaytitle', array( __CLASS__, 'displaytitle' ), SFH_NO_HASH ); 00072 } 00073 if ( $wgAllowSlowParserFunctions ) { 00074 $parser->setFunctionHook( 'pagesinnamespace', array( __CLASS__, 'pagesinnamespace' ), SFH_NO_HASH ); 00075 } 00076 } 00077 00083 static function intFunction( $parser, $part1 = '' /*, ... */ ) { 00084 if ( strval( $part1 ) !== '' ) { 00085 $args = array_slice( func_get_args(), 2 ); 00086 $message = wfMessage( $part1, $args )->inLanguage( $parser->getOptions()->getUserLangObj() )->plain(); 00087 return array( $message, 'noparse' => false ); 00088 } else { 00089 return array( 'found' => false ); 00090 } 00091 } 00092 00100 static function formatDate( $parser, $date, $defaultPref = null ) { 00101 $lang = $parser->getFunctionLang(); 00102 $df = DateFormatter::getInstance( $lang ); 00103 00104 $date = trim( $date ); 00105 00106 $pref = $parser->getOptions()->getDateFormat(); 00107 00108 // Specify a different default date format other than the the normal default 00109 // if the user has 'default' for their setting 00110 if ( $pref == 'default' && $defaultPref ) { 00111 $pref = $defaultPref; 00112 } 00113 00114 $date = $df->reformat( $pref, $date, array( 'match-whole' ) ); 00115 return $date; 00116 } 00117 00118 static function ns( $parser, $part1 = '' ) { 00119 global $wgContLang; 00120 if ( intval( $part1 ) || $part1 == "0" ) { 00121 $index = intval( $part1 ); 00122 } else { 00123 $index = $wgContLang->getNsIndex( str_replace( ' ', '_', $part1 ) ); 00124 } 00125 if ( $index !== false ) { 00126 return $wgContLang->getFormattedNsText( $index ); 00127 } else { 00128 return array( 'found' => false ); 00129 } 00130 } 00131 00132 static function nse( $parser, $part1 = '' ) { 00133 $ret = self::ns( $parser, $part1 ); 00134 if ( is_string( $ret ) ) { 00135 $ret = wfUrlencode( str_replace( ' ', '_', $ret ) ); 00136 } 00137 return $ret; 00138 } 00139 00152 static function urlencode( $parser, $s = '', $arg = null ) { 00153 static $magicWords = null; 00154 if ( is_null( $magicWords ) ) { 00155 $magicWords = new MagicWordArray( array( 'url_path', 'url_query', 'url_wiki' ) ); 00156 } 00157 switch ( $magicWords->matchStartToEnd( $arg ) ) { 00158 00159 // Encode as though it's a wiki page, '_' for ' '. 00160 case 'url_wiki': 00161 $func = 'wfUrlencode'; 00162 $s = str_replace( ' ', '_', $s ); 00163 break; 00164 00165 // Encode for an HTTP Path, '%20' for ' '. 00166 case 'url_path': 00167 $func = 'rawurlencode'; 00168 break; 00169 00170 // Encode for HTTP query, '+' for ' '. 00171 case 'url_query': 00172 default: 00173 $func = 'urlencode'; 00174 } 00175 return $parser->markerSkipCallback( $s, $func ); 00176 } 00177 00178 static function lcfirst( $parser, $s = '' ) { 00179 global $wgContLang; 00180 return $wgContLang->lcfirst( $s ); 00181 } 00182 00183 static function ucfirst( $parser, $s = '' ) { 00184 global $wgContLang; 00185 return $wgContLang->ucfirst( $s ); 00186 } 00187 00193 static function lc( $parser, $s = '' ) { 00194 global $wgContLang; 00195 return $parser->markerSkipCallback( $s, array( $wgContLang, 'lc' ) ); 00196 } 00197 00203 static function uc( $parser, $s = '' ) { 00204 global $wgContLang; 00205 return $parser->markerSkipCallback( $s, array( $wgContLang, 'uc' ) ); 00206 } 00207 00208 static function localurl( $parser, $s = '', $arg = null ) { 00209 return self::urlFunction( 'getLocalURL', $s, $arg ); 00210 } 00211 00212 static function localurle( $parser, $s = '', $arg = null ) { 00213 $temp = self::urlFunction( 'getLocalURL', $s, $arg ); 00214 if ( !is_string( $temp ) ) { 00215 return $temp; 00216 } else { 00217 return htmlspecialchars( $temp ); 00218 } 00219 } 00220 00221 static function fullurl( $parser, $s = '', $arg = null ) { 00222 return self::urlFunction( 'getFullURL', $s, $arg ); 00223 } 00224 00225 static function fullurle( $parser, $s = '', $arg = null ) { 00226 $temp = self::urlFunction( 'getFullURL', $s, $arg ); 00227 if ( !is_string( $temp ) ) { 00228 return $temp; 00229 } else { 00230 return htmlspecialchars( $temp ); 00231 } 00232 } 00233 00234 static function canonicalurl( $parser, $s = '', $arg = null ) { 00235 return self::urlFunction( 'getCanonicalURL', $s, $arg ); 00236 } 00237 00238 static function canonicalurle( $parser, $s = '', $arg = null ) { 00239 return self::urlFunction( 'escapeCanonicalURL', $s, $arg ); 00240 } 00241 00242 static function urlFunction( $func, $s = '', $arg = null ) { 00243 $title = Title::newFromText( $s ); 00244 # Due to order of execution of a lot of bits, the values might be encoded 00245 # before arriving here; if that's true, then the title can't be created 00246 # and the variable will fail. If we can't get a decent title from the first 00247 # attempt, url-decode and try for a second. 00248 if ( is_null( $title ) ) { 00249 $title = Title::newFromURL( urldecode( $s ) ); 00250 } 00251 if ( !is_null( $title ) ) { 00252 # Convert NS_MEDIA -> NS_FILE 00253 if ( $title->getNamespace() == NS_MEDIA ) { 00254 $title = Title::makeTitle( NS_FILE, $title->getDBkey() ); 00255 } 00256 if ( !is_null( $arg ) ) { 00257 $text = $title->$func( $arg ); 00258 } else { 00259 $text = $title->$func(); 00260 } 00261 return $text; 00262 } else { 00263 return array( 'found' => false ); 00264 } 00265 } 00266 00273 static function formatnum( $parser, $num = '', $arg = null ) { 00274 if ( self::matchAgainstMagicword( 'rawsuffix', $arg ) ) { 00275 $func = array( $parser->getFunctionLang(), 'parseFormattedNumber' ); 00276 } elseif ( self::matchAgainstMagicword( 'nocommafysuffix', $arg ) ) { 00277 $func = array( $parser->getFunctionLang(), 'formatNumNoSeparators' ); 00278 } else { 00279 $func = array( $parser->getFunctionLang(), 'formatNum' ); 00280 } 00281 return $parser->markerSkipCallback( $num, $func ); 00282 } 00283 00290 static function grammar( $parser, $case = '', $word = '' ) { 00291 $word = $parser->killMarkers( $word ); 00292 return $parser->getFunctionLang()->convertGrammar( $word, $case ); 00293 } 00294 00300 static function gender( $parser, $username ) { 00301 wfProfileIn( __METHOD__ ); 00302 $forms = array_slice( func_get_args(), 2 ); 00303 00304 // Some shortcuts to avoid loading user data unnecessarily 00305 if ( count( $forms ) === 0 ) { 00306 wfProfileOut( __METHOD__ ); 00307 return ''; 00308 } elseif ( count( $forms ) === 1 ) { 00309 wfProfileOut( __METHOD__ ); 00310 return $forms[0]; 00311 } 00312 00313 $username = trim( $username ); 00314 00315 // default 00316 $gender = User::getDefaultOption( 'gender' ); 00317 00318 // allow prefix. 00319 $title = Title::newFromText( $username ); 00320 00321 if ( $title && $title->getNamespace() == NS_USER ) { 00322 $username = $title->getText(); 00323 } 00324 00325 // check parameter, or use the ParserOptions if in interface message 00326 $user = User::newFromName( $username ); 00327 if ( $user ) { 00328 $gender = GenderCache::singleton()->getGenderOf( $user, __METHOD__ ); 00329 } elseif ( $username === '' && $parser->getOptions()->getInterfaceMessage() ) { 00330 $gender = GenderCache::singleton()->getGenderOf( $parser->getOptions()->getUser(), __METHOD__ ); 00331 } 00332 $ret = $parser->getFunctionLang()->gender( $gender, $forms ); 00333 wfProfileOut( __METHOD__ ); 00334 return $ret; 00335 } 00336 00342 static function plural( $parser, $text = '' ) { 00343 $forms = array_slice( func_get_args(), 2 ); 00344 $text = $parser->getFunctionLang()->parseFormattedNumber( $text ); 00345 settype( $text, ctype_digit( $text ) ? 'int' : 'float' ); 00346 return $parser->getFunctionLang()->convertPlural( $text, $forms ); 00347 } 00348 00357 static function displaytitle( $parser, $text = '' ) { 00358 global $wgRestrictDisplayTitle; 00359 00360 // parse a limited subset of wiki markup (just the single quote items) 00361 $text = $parser->doQuotes( $text ); 00362 00363 // remove stripped text (e.g. the UNIQ-QINU stuff) that was generated by tag extensions/whatever 00364 $text = preg_replace( '/' . preg_quote( $parser->uniqPrefix(), '/' ) . '.*?' 00365 . preg_quote( Parser::MARKER_SUFFIX, '/' ) . '/', '', $text ); 00366 00367 // list of disallowed tags for DISPLAYTITLE 00368 // these will be escaped even though they are allowed in normal wiki text 00369 $bad = array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'blockquote', 'ol', 'ul', 'li', 'hr', 00370 'table', 'tr', 'th', 'td', 'dl', 'dd', 'caption', 'p', 'ruby', 'rb', 'rt', 'rp', 'br' ); 00371 00372 // disallow some styles that could be used to bypass $wgRestrictDisplayTitle 00373 if ( $wgRestrictDisplayTitle ) { 00374 $htmlTagsCallback = function ( &$params ) { 00375 $decoded = Sanitizer::decodeTagAttributes( $params ); 00376 00377 if ( isset( $decoded['style'] ) ) { 00378 // this is called later anyway, but we need it right now for the regexes below to be safe 00379 // calling it twice doesn't hurt 00380 $decoded['style'] = Sanitizer::checkCss( $decoded['style'] ); 00381 00382 if ( preg_match( '/(display|user-select|visibility)\s*:/i', $decoded['style'] ) ) { 00383 $decoded['style'] = '/* attempt to bypass $wgRestrictDisplayTitle */'; 00384 } 00385 } 00386 00387 $params = Sanitizer::safeEncodeTagAttributes( $decoded ); 00388 }; 00389 } else { 00390 $htmlTagsCallback = null; 00391 } 00392 00393 // only requested titles that normalize to the actual title are allowed through 00394 // if $wgRestrictDisplayTitle is true (it is by default) 00395 // mimic the escaping process that occurs in OutputPage::setPageTitle 00396 $text = Sanitizer::normalizeCharReferences( Sanitizer::removeHTMLtags( $text, $htmlTagsCallback, array(), array(), $bad ) ); 00397 $title = Title::newFromText( Sanitizer::stripAllTags( $text ) ); 00398 00399 if ( !$wgRestrictDisplayTitle ) { 00400 $parser->mOutput->setDisplayTitle( $text ); 00401 } elseif ( $title instanceof Title && !$title->hasFragment() && $title->equals( $parser->mTitle ) ) { 00402 $parser->mOutput->setDisplayTitle( $text ); 00403 } 00404 00405 return ''; 00406 } 00407 00415 private static function matchAgainstMagicword( $magicword, $value ) { 00416 $value = trim( strval( $value ) ); 00417 if ( $value === '' ) { 00418 return false; 00419 } 00420 $mwObject = MagicWord::get( $magicword ); 00421 return $mwObject->matchStartToEnd( $value ); 00422 } 00423 00424 static function formatRaw( $num, $raw ) { 00425 if ( self::matchAgainstMagicword( 'rawsuffix', $raw ) ) { 00426 return $num; 00427 } else { 00428 global $wgContLang; 00429 return $wgContLang->formatNum( $num ); 00430 } 00431 } 00432 static function numberofpages( $parser, $raw = null ) { 00433 return self::formatRaw( SiteStats::pages(), $raw ); 00434 } 00435 static function numberofusers( $parser, $raw = null ) { 00436 return self::formatRaw( SiteStats::users(), $raw ); 00437 } 00438 static function numberofactiveusers( $parser, $raw = null ) { 00439 return self::formatRaw( SiteStats::activeUsers(), $raw ); 00440 } 00441 static function numberofarticles( $parser, $raw = null ) { 00442 return self::formatRaw( SiteStats::articles(), $raw ); 00443 } 00444 static function numberoffiles( $parser, $raw = null ) { 00445 return self::formatRaw( SiteStats::images(), $raw ); 00446 } 00447 static function numberofadmins( $parser, $raw = null ) { 00448 return self::formatRaw( SiteStats::numberingroup( 'sysop' ), $raw ); 00449 } 00450 static function numberofedits( $parser, $raw = null ) { 00451 return self::formatRaw( SiteStats::edits(), $raw ); 00452 } 00453 static function numberofviews( $parser, $raw = null ) { 00454 global $wgDisableCounters; 00455 return !$wgDisableCounters ? self::formatRaw( SiteStats::views(), $raw ) : ''; 00456 } 00457 static function pagesinnamespace( $parser, $namespace = 0, $raw = null ) { 00458 return self::formatRaw( SiteStats::pagesInNs( intval( $namespace ) ), $raw ); 00459 } 00460 static function numberingroup( $parser, $name = '', $raw = null ) { 00461 return self::formatRaw( SiteStats::numberingroup( strtolower( $name ) ), $raw ); 00462 } 00463 00471 static function mwnamespace( $parser, $title = null ) { 00472 $t = Title::newFromText( $title ); 00473 if ( is_null( $t ) ) { 00474 return ''; 00475 } 00476 return str_replace( '_', ' ', $t->getNsText() ); 00477 } 00478 static function namespacee( $parser, $title = null ) { 00479 $t = Title::newFromText( $title ); 00480 if ( is_null( $t ) ) { 00481 return ''; 00482 } 00483 return wfUrlencode( $t->getNsText() ); 00484 } 00485 static function namespacenumber( $parser, $title = null ) { 00486 $t = Title::newFromText( $title ); 00487 if ( is_null( $t ) ) { 00488 return ''; 00489 } 00490 return $t->getNamespace(); 00491 } 00492 static function talkspace( $parser, $title = null ) { 00493 $t = Title::newFromText( $title ); 00494 if ( is_null( $t ) || !$t->canTalk() ) { 00495 return ''; 00496 } 00497 return str_replace( '_', ' ', $t->getTalkNsText() ); 00498 } 00499 static function talkspacee( $parser, $title = null ) { 00500 $t = Title::newFromText( $title ); 00501 if ( is_null( $t ) || !$t->canTalk() ) { 00502 return ''; 00503 } 00504 return wfUrlencode( $t->getTalkNsText() ); 00505 } 00506 static function subjectspace( $parser, $title = null ) { 00507 $t = Title::newFromText( $title ); 00508 if ( is_null( $t ) ) { 00509 return ''; 00510 } 00511 return str_replace( '_', ' ', $t->getSubjectNsText() ); 00512 } 00513 static function subjectspacee( $parser, $title = null ) { 00514 $t = Title::newFromText( $title ); 00515 if ( is_null( $t ) ) { 00516 return ''; 00517 } 00518 return wfUrlencode( $t->getSubjectNsText() ); 00519 } 00520 00526 static function pagename( $parser, $title = null ) { 00527 $t = Title::newFromText( $title ); 00528 if ( is_null( $t ) ) { 00529 return ''; 00530 } 00531 return wfEscapeWikiText( $t->getText() ); 00532 } 00533 static function pagenamee( $parser, $title = null ) { 00534 $t = Title::newFromText( $title ); 00535 if ( is_null( $t ) ) { 00536 return ''; 00537 } 00538 return wfEscapeWikiText( $t->getPartialURL() ); 00539 } 00540 static function fullpagename( $parser, $title = null ) { 00541 $t = Title::newFromText( $title ); 00542 if ( is_null( $t ) || !$t->canTalk() ) { 00543 return ''; 00544 } 00545 return wfEscapeWikiText( $t->getPrefixedText() ); 00546 } 00547 static function fullpagenamee( $parser, $title = null ) { 00548 $t = Title::newFromText( $title ); 00549 if ( is_null( $t ) || !$t->canTalk() ) { 00550 return ''; 00551 } 00552 return wfEscapeWikiText( $t->getPrefixedURL() ); 00553 } 00554 static function subpagename( $parser, $title = null ) { 00555 $t = Title::newFromText( $title ); 00556 if ( is_null( $t ) ) { 00557 return ''; 00558 } 00559 return wfEscapeWikiText( $t->getSubpageText() ); 00560 } 00561 static function subpagenamee( $parser, $title = null ) { 00562 $t = Title::newFromText( $title ); 00563 if ( is_null( $t ) ) { 00564 return ''; 00565 } 00566 return wfEscapeWikiText( $t->getSubpageUrlForm() ); 00567 } 00568 static function rootpagename( $parser, $title = null ) { 00569 $t = Title::newFromText( $title ); 00570 if ( is_null( $t ) ) { 00571 return ''; 00572 } 00573 return wfEscapeWikiText( $t->getRootText() ); 00574 } 00575 static function rootpagenamee( $parser, $title = null ) { 00576 $t = Title::newFromText( $title ); 00577 if ( is_null( $t ) ) { 00578 return ''; 00579 } 00580 return wfEscapeWikiText( wfUrlEncode( str_replace( ' ', '_', $t->getRootText() ) ) ); 00581 } 00582 static function basepagename( $parser, $title = null ) { 00583 $t = Title::newFromText( $title ); 00584 if ( is_null( $t ) ) { 00585 return ''; 00586 } 00587 return wfEscapeWikiText( $t->getBaseText() ); 00588 } 00589 static function basepagenamee( $parser, $title = null ) { 00590 $t = Title::newFromText( $title ); 00591 if ( is_null( $t ) ) { 00592 return ''; 00593 } 00594 return wfEscapeWikiText( wfUrlEncode( str_replace( ' ', '_', $t->getBaseText() ) ) ); 00595 } 00596 static function talkpagename( $parser, $title = null ) { 00597 $t = Title::newFromText( $title ); 00598 if ( is_null( $t ) || !$t->canTalk() ) { 00599 return ''; 00600 } 00601 return wfEscapeWikiText( $t->getTalkPage()->getPrefixedText() ); 00602 } 00603 static function talkpagenamee( $parser, $title = null ) { 00604 $t = Title::newFromText( $title ); 00605 if ( is_null( $t ) || !$t->canTalk() ) { 00606 return ''; 00607 } 00608 return wfEscapeWikiText( $t->getTalkPage()->getPrefixedURL() ); 00609 } 00610 static function subjectpagename( $parser, $title = null ) { 00611 $t = Title::newFromText( $title ); 00612 if ( is_null( $t ) ) { 00613 return ''; 00614 } 00615 return wfEscapeWikiText( $t->getSubjectPage()->getPrefixedText() ); 00616 } 00617 static function subjectpagenamee( $parser, $title = null ) { 00618 $t = Title::newFromText( $title ); 00619 if ( is_null( $t ) ) { 00620 return ''; 00621 } 00622 return wfEscapeWikiText( $t->getSubjectPage()->getPrefixedURL() ); 00623 } 00624 00631 static function pagesincategory( $parser, $name = '', $arg1 = null, $arg2 = null ) { 00632 global $wgContLang; 00633 static $magicWords = null; 00634 if ( is_null( $magicWords ) ) { 00635 $magicWords = new MagicWordArray( array( 00636 'pagesincategory_all', 00637 'pagesincategory_pages', 00638 'pagesincategory_subcats', 00639 'pagesincategory_files' 00640 ) ); 00641 } 00642 static $cache = array(); 00643 00644 // split the given option to its variable 00645 if ( self::matchAgainstMagicword( 'rawsuffix', $arg1 ) ) { 00646 //{{pagesincategory:|raw[|type]}} 00647 $raw = $arg1; 00648 $type = $magicWords->matchStartToEnd( $arg2 ); 00649 } else { 00650 //{{pagesincategory:[|type[|raw]]}} 00651 $type = $magicWords->matchStartToEnd( $arg1 ); 00652 $raw = $arg2; 00653 } 00654 if ( !$type ) { //backward compatibility 00655 $type = 'pagesincategory_all'; 00656 } 00657 00658 $title = Title::makeTitleSafe( NS_CATEGORY, $name ); 00659 if ( !$title ) { # invalid title 00660 return self::formatRaw( 0, $raw ); 00661 } 00662 $wgContLang->findVariantLink( $name, $title, true ); 00663 00664 // Normalize name for cache 00665 $name = $title->getDBkey(); 00666 00667 if ( !isset( $cache[$name] ) ) { 00668 $category = Category::newFromTitle( $title ); 00669 00670 $allCount = $subcatCount = $fileCount = $pagesCount = 0; 00671 if ( $parser->incrementExpensiveFunctionCount() ) { 00672 // $allCount is the total number of cat members, 00673 // not the count of how many members are normal pages. 00674 $allCount = (int)$category->getPageCount(); 00675 $subcatCount = (int)$category->getSubcatCount(); 00676 $fileCount = (int)$category->getFileCount(); 00677 $pagesCount = $allCount - $subcatCount - $fileCount; 00678 } 00679 $cache[$name]['pagesincategory_all'] = $allCount; 00680 $cache[$name]['pagesincategory_pages'] = $pagesCount; 00681 $cache[$name]['pagesincategory_subcats'] = $subcatCount; 00682 $cache[$name]['pagesincategory_files'] = $fileCount; 00683 } 00684 00685 $count = $cache[$name][$type]; 00686 return self::formatRaw( $count, $raw ); 00687 } 00688 00698 static function pagesize( $parser, $page = '', $raw = null ) { 00699 $title = Title::newFromText( $page ); 00700 00701 if ( !is_object( $title ) ) { 00702 return self::formatRaw( 0, $raw ); 00703 } 00704 00705 // fetch revision from cache/database and return the value 00706 $rev = self::getCachedRevisionObject( $parser, $title ); 00707 $length = $rev ? $rev->getSize() : 0; 00708 return self::formatRaw( $length, $raw ); 00709 } 00710 00723 static function protectionlevel( $parser, $type = '', $title = '' ) { 00724 $titleObject = Title::newFromText( $title ); 00725 if ( !( $titleObject instanceof Title ) ) { 00726 $titleObject = $parser->mTitle; 00727 } 00728 if ( $titleObject->areRestrictionsLoaded() || $parser->incrementExpensiveFunctionCount() ) { 00729 $restrictions = $titleObject->getRestrictions( strtolower( $type ) ); 00730 # Title::getRestrictions returns an array, its possible it may have 00731 # multiple values in the future 00732 return implode( $restrictions, ',' ); 00733 } 00734 return ''; 00735 } 00736 00744 static function language( $parser, $code = '', $inLanguage = '' ) { 00745 $code = strtolower( $code ); 00746 $inLanguage = strtolower( $inLanguage ); 00747 $lang = Language::fetchLanguageName( $code, $inLanguage ); 00748 return $lang !== '' ? $lang : wfBCP47( $code ); 00749 } 00750 00755 static function pad( $parser, $string, $length, $padding = '0', $direction = STR_PAD_RIGHT ) { 00756 $padding = $parser->killMarkers( $padding ); 00757 $lengthOfPadding = mb_strlen( $padding ); 00758 if ( $lengthOfPadding == 0 ) { 00759 return $string; 00760 } 00761 00762 # The remaining length to add counts down to 0 as padding is added 00763 $length = min( $length, 500 ) - mb_strlen( $string ); 00764 # $finalPadding is just $padding repeated enough times so that 00765 # mb_strlen( $string ) + mb_strlen( $finalPadding ) == $length 00766 $finalPadding = ''; 00767 while ( $length > 0 ) { 00768 # If $length < $lengthofPadding, truncate $padding so we get the 00769 # exact length desired. 00770 $finalPadding .= mb_substr( $padding, 0, $length ); 00771 $length -= $lengthOfPadding; 00772 } 00773 00774 if ( $direction == STR_PAD_LEFT ) { 00775 return $finalPadding . $string; 00776 } else { 00777 return $string . $finalPadding; 00778 } 00779 } 00780 00781 static function padleft( $parser, $string = '', $length = 0, $padding = '0' ) { 00782 return self::pad( $parser, $string, $length, $padding, STR_PAD_LEFT ); 00783 } 00784 00785 static function padright( $parser, $string = '', $length = 0, $padding = '0' ) { 00786 return self::pad( $parser, $string, $length, $padding ); 00787 } 00788 00794 static function anchorencode( $parser, $text ) { 00795 $text = $parser->killMarkers( $text ); 00796 return (string)substr( $parser->guessSectionNameFromWikiText( $text ), 1 ); 00797 } 00798 00799 static function special( $parser, $text ) { 00800 list( $page, $subpage ) = SpecialPageFactory::resolveAlias( $text ); 00801 if ( $page ) { 00802 $title = SpecialPage::getTitleFor( $page, $subpage ); 00803 return $title->getPrefixedText(); 00804 } else { 00805 // unknown special page, just use the given text as its title, if at all possible 00806 $title = Title::makeTitleSafe( NS_SPECIAL, $text ); 00807 return $title ? $title->getPrefixedText() : self::special( $parser, 'Badtitle' ); 00808 } 00809 } 00810 00811 static function speciale( $parser, $text ) { 00812 return wfUrlencode( str_replace( ' ', '_', self::special( $parser, $text ) ) ); 00813 } 00814 00823 public static function defaultsort( $parser, $text, $uarg = '' ) { 00824 static $magicWords = null; 00825 if ( is_null( $magicWords ) ) { 00826 $magicWords = new MagicWordArray( array( 'defaultsort_noerror', 'defaultsort_noreplace' ) ); 00827 } 00828 $arg = $magicWords->matchStartToEnd( $uarg ); 00829 00830 $text = trim( $text ); 00831 if ( strlen( $text ) == 0 ) { 00832 return ''; 00833 } 00834 $old = $parser->getCustomDefaultSort(); 00835 if ( $old === false || $arg !== 'defaultsort_noreplace' ) { 00836 $parser->setDefaultSort( $text ); 00837 } 00838 00839 if ( $old === false || $old == $text || $arg ) { 00840 return ''; 00841 } else { 00842 $converter = $parser->getConverterLanguage()->getConverter(); 00843 return '<span class="error">' . 00844 wfMessage( 'duplicate-defaultsort', 00845 // Message should be parsed, but these params should only be escaped. 00846 $converter->markNoConversion( wfEscapeWikiText( $old ) ), 00847 $converter->markNoConversion( wfEscapeWikiText( $text ) ) 00848 )->inContentLanguage()->text() . 00849 '</span>'; 00850 } 00851 } 00852 00853 // Usage {{filepath|300}}, {{filepath|nowiki}}, {{filepath|nowiki|300}} or {{filepath|300|nowiki}} 00854 // or {{filepath|300px}}, {{filepath|200x300px}}, {{filepath|nowiki|200x300px}}, {{filepath|200x300px|nowiki}} 00855 public static function filepath( $parser, $name = '', $argA = '', $argB = '' ) { 00856 $file = wfFindFile( $name ); 00857 00858 if ( $argA == 'nowiki' ) { 00859 // {{filepath: | option [| size] }} 00860 $isNowiki = true; 00861 $parsedWidthParam = $parser->parseWidthParam( $argB ); 00862 } else { 00863 // {{filepath: [| size [|option]] }} 00864 $parsedWidthParam = $parser->parseWidthParam( $argA ); 00865 $isNowiki = ( $argB == 'nowiki' ); 00866 } 00867 00868 if ( $file ) { 00869 $url = $file->getFullUrl(); 00870 00871 // If a size is requested... 00872 if ( count( $parsedWidthParam ) ) { 00873 $mto = $file->transform( $parsedWidthParam ); 00874 // ... and we can 00875 if ( $mto && !$mto->isError() ) { 00876 // ... change the URL to point to a thumbnail. 00877 $url = wfExpandUrl( $mto->getUrl(), PROTO_RELATIVE ); 00878 } 00879 } 00880 if ( $isNowiki ) { 00881 return array( $url, 'nowiki' => true ); 00882 } 00883 return $url; 00884 } else { 00885 return ''; 00886 } 00887 } 00888 00893 public static function tagObj( $parser, $frame, $args ) { 00894 if ( !count( $args ) ) { 00895 return ''; 00896 } 00897 $tagName = strtolower( trim( $frame->expand( array_shift( $args ) ) ) ); 00898 00899 if ( count( $args ) ) { 00900 $inner = $frame->expand( array_shift( $args ) ); 00901 } else { 00902 $inner = null; 00903 } 00904 00905 $stripList = $parser->getStripList(); 00906 if ( !in_array( $tagName, $stripList ) ) { 00907 return '<span class="error">' . 00908 wfMessage( 'unknown_extension_tag', $tagName )->inContentLanguage()->text() . 00909 '</span>'; 00910 } 00911 00912 $attributes = array(); 00913 foreach ( $args as $arg ) { 00914 $bits = $arg->splitArg(); 00915 if ( strval( $bits['index'] ) === '' ) { 00916 $name = trim( $frame->expand( $bits['name'], PPFrame::STRIP_COMMENTS ) ); 00917 $value = trim( $frame->expand( $bits['value'] ) ); 00918 if ( preg_match( '/^(?:["\'](.+)["\']|""|\'\')$/s', $value, $m ) ) { 00919 $value = isset( $m[1] ) ? $m[1] : ''; 00920 } 00921 $attributes[$name] = $value; 00922 } 00923 } 00924 00925 $params = array( 00926 'name' => $tagName, 00927 'inner' => $inner, 00928 'attributes' => $attributes, 00929 'close' => "</$tagName>", 00930 ); 00931 return $parser->extensionSubstitution( $params, $frame ); 00932 } 00933 00946 private static function getCachedRevisionObject( $parser, $title = null ) { 00947 static $cache = array(); 00948 00949 if ( is_null( $title ) ) { 00950 return null; 00951 } 00952 00953 // Use the revision from the parser itself, when param is the current page 00954 // and the revision is the current one 00955 if ( $title->equals( $parser->getTitle() ) ) { 00956 $parserRev = $parser->getRevisionObject(); 00957 if ( $parserRev && $parserRev->isCurrent() ) { 00958 // force reparse after edit with vary-revision flag 00959 $parser->getOutput()->setFlag( 'vary-revision' ); 00960 wfDebug( __METHOD__ . ": use current revision from parser, setting vary-revision...\n" ); 00961 return $parserRev; 00962 } 00963 } 00964 00965 // Normalize name for cache 00966 $page = $title->getPrefixedDBkey(); 00967 00968 if ( array_key_exists( $page, $cache ) ) { // cache contains null values 00969 return $cache[$page]; 00970 } 00971 if ( $parser->incrementExpensiveFunctionCount() ) { 00972 $rev = Revision::newFromTitle( $title, false, Revision::READ_NORMAL ); 00973 $pageID = $rev ? $rev->getPage() : 0; 00974 $revID = $rev ? $rev->getId() : 0; 00975 $cache[$page] = $rev; // maybe null 00976 00977 // Register dependency in templatelinks 00978 $parser->getOutput()->addTemplate( $title, $pageID, $revID ); 00979 00980 return $rev; 00981 } 00982 $cache[$page] = null; 00983 return null; 00984 } 00985 00992 public static function pageid( $parser, $title = null ) { 00993 $t = Title::newFromText( $title ); 00994 if ( is_null( $t ) ) { 00995 return ''; 00996 } 00997 // Use title from parser to have correct pageid after edit 00998 if ( $t->equals( $parser->getTitle() ) ) { 00999 $t = $parser->getTitle(); 01000 return $t->getArticleID(); 01001 } 01002 01003 // These can't have ids 01004 if ( !$t->canExist() || $t->isExternal() ) { 01005 return 0; 01006 } 01007 01008 // Check the link cache, maybe something already looked it up. 01009 $linkCache = LinkCache::singleton(); 01010 $pdbk = $t->getPrefixedDBkey(); 01011 $id = $linkCache->getGoodLinkID( $pdbk ); 01012 if ( $id != 0 ) { 01013 $parser->mOutput->addLink( $t, $id ); 01014 return $id; 01015 } 01016 if ( $linkCache->isBadLink( $pdbk ) ) { 01017 $parser->mOutput->addLink( $t, 0 ); 01018 return $id; 01019 } 01020 01021 // We need to load it from the DB, so mark expensive 01022 if ( $parser->incrementExpensiveFunctionCount() ) { 01023 $id = $t->getArticleID(); 01024 $parser->mOutput->addLink( $t, $id ); 01025 return $id; 01026 } 01027 return null; 01028 } 01029 01036 public static function revisionid( $parser, $title = null ) { 01037 $t = Title::newFromText( $title ); 01038 if ( is_null( $t ) ) { 01039 return ''; 01040 } 01041 // fetch revision from cache/database and return the value 01042 $rev = self::getCachedRevisionObject( $parser, $t ); 01043 return $rev ? $rev->getId() : ''; 01044 } 01045 01052 public static function revisionday( $parser, $title = null ) { 01053 $t = Title::newFromText( $title ); 01054 if ( is_null( $t ) ) { 01055 return ''; 01056 } 01057 // fetch revision from cache/database and return the value 01058 $rev = self::getCachedRevisionObject( $parser, $t ); 01059 return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'j' ) : ''; 01060 } 01061 01068 public static function revisionday2( $parser, $title = null ) { 01069 $t = Title::newFromText( $title ); 01070 if ( is_null( $t ) ) { 01071 return ''; 01072 } 01073 // fetch revision from cache/database and return the value 01074 $rev = self::getCachedRevisionObject( $parser, $t ); 01075 return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'd' ) : ''; 01076 } 01077 01084 public static function revisionmonth( $parser, $title = null ) { 01085 $t = Title::newFromText( $title ); 01086 if ( is_null( $t ) ) { 01087 return ''; 01088 } 01089 // fetch revision from cache/database and return the value 01090 $rev = self::getCachedRevisionObject( $parser, $t ); 01091 return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'm' ) : ''; 01092 } 01093 01100 public static function revisionmonth1( $parser, $title = null ) { 01101 $t = Title::newFromText( $title ); 01102 if ( is_null( $t ) ) { 01103 return ''; 01104 } 01105 // fetch revision from cache/database and return the value 01106 $rev = self::getCachedRevisionObject( $parser, $t ); 01107 return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'n' ) : ''; 01108 } 01109 01116 public static function revisionyear( $parser, $title = null ) { 01117 $t = Title::newFromText( $title ); 01118 if ( is_null( $t ) ) { 01119 return ''; 01120 } 01121 // fetch revision from cache/database and return the value 01122 $rev = self::getCachedRevisionObject( $parser, $t ); 01123 return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'Y' ) : ''; 01124 } 01125 01132 public static function revisiontimestamp( $parser, $title = null ) { 01133 $t = Title::newFromText( $title ); 01134 if ( is_null( $t ) ) { 01135 return ''; 01136 } 01137 // fetch revision from cache/database and return the value 01138 $rev = self::getCachedRevisionObject( $parser, $t ); 01139 return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'YmdHis' ) : ''; 01140 } 01141 01148 public static function revisionuser( $parser, $title = null ) { 01149 $t = Title::newFromText( $title ); 01150 if ( is_null( $t ) ) { 01151 return ''; 01152 } 01153 // fetch revision from cache/database and return the value 01154 $rev = self::getCachedRevisionObject( $parser, $t ); 01155 return $rev ? $rev->getUserText() : ''; 01156 } 01157 01170 public static function cascadingsources( $parser, $title = '' ) { 01171 $titleObject = Title::newFromText( $title ); 01172 if ( !( $titleObject instanceof Title ) ) { 01173 $titleObject = $parser->mTitle; 01174 } 01175 if ( $titleObject->areCascadeProtectionSourcesLoaded() 01176 || $parser->incrementExpensiveFunctionCount() 01177 ) { 01178 $names = array(); 01179 $sources = $titleObject->getCascadeProtectionSources(); 01180 foreach ( $sources[0] as $sourceTitle ) { 01181 $names[] = $sourceTitle->getPrefixedText(); 01182 } 01183 return implode( $names, '|' ); 01184 } 01185 return ''; 01186 } 01187 01188 }