MediaWiki
REL1_24
|
00001 <?php 00028 class CoreParserFunctions { 00033 public static function register( $parser ) { 00034 global $wgAllowDisplayTitle, $wgAllowSlowParserFunctions; 00035 00036 # Syntax for arguments (see Parser::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( 00075 'pagesinnamespace', 00076 array( __CLASS__, 'pagesinnamespace' ), 00077 SFH_NO_HASH 00078 ); 00079 } 00080 } 00081 00087 public static function intFunction( $parser, $part1 = '' /*, ... */ ) { 00088 if ( strval( $part1 ) !== '' ) { 00089 $args = array_slice( func_get_args(), 2 ); 00090 $message = wfMessage( $part1, $args ) 00091 ->inLanguage( $parser->getOptions()->getUserLangObj() )->plain(); 00092 00093 return array( $message, 'noparse' => false ); 00094 } else { 00095 return array( 'found' => false ); 00096 } 00097 } 00098 00106 public static function formatDate( $parser, $date, $defaultPref = null ) { 00107 $lang = $parser->getFunctionLang(); 00108 $df = DateFormatter::getInstance( $lang ); 00109 00110 $date = trim( $date ); 00111 00112 $pref = $parser->getOptions()->getDateFormat(); 00113 00114 // Specify a different default date format other than the the normal default 00115 // if the user has 'default' for their setting 00116 if ( $pref == 'default' && $defaultPref ) { 00117 $pref = $defaultPref; 00118 } 00119 00120 $date = $df->reformat( $pref, $date, array( 'match-whole' ) ); 00121 return $date; 00122 } 00123 00124 public static function ns( $parser, $part1 = '' ) { 00125 global $wgContLang; 00126 if ( intval( $part1 ) || $part1 == "0" ) { 00127 $index = intval( $part1 ); 00128 } else { 00129 $index = $wgContLang->getNsIndex( str_replace( ' ', '_', $part1 ) ); 00130 } 00131 if ( $index !== false ) { 00132 return $wgContLang->getFormattedNsText( $index ); 00133 } else { 00134 return array( 'found' => false ); 00135 } 00136 } 00137 00138 public static function nse( $parser, $part1 = '' ) { 00139 $ret = self::ns( $parser, $part1 ); 00140 if ( is_string( $ret ) ) { 00141 $ret = wfUrlencode( str_replace( ' ', '_', $ret ) ); 00142 } 00143 return $ret; 00144 } 00145 00158 public static function urlencode( $parser, $s = '', $arg = null ) { 00159 static $magicWords = null; 00160 if ( is_null( $magicWords ) ) { 00161 $magicWords = new MagicWordArray( array( 'url_path', 'url_query', 'url_wiki' ) ); 00162 } 00163 switch ( $magicWords->matchStartToEnd( $arg ) ) { 00164 00165 // Encode as though it's a wiki page, '_' for ' '. 00166 case 'url_wiki': 00167 $func = 'wfUrlencode'; 00168 $s = str_replace( ' ', '_', $s ); 00169 break; 00170 00171 // Encode for an HTTP Path, '%20' for ' '. 00172 case 'url_path': 00173 $func = 'rawurlencode'; 00174 break; 00175 00176 // Encode for HTTP query, '+' for ' '. 00177 case 'url_query': 00178 default: 00179 $func = 'urlencode'; 00180 } 00181 return $parser->markerSkipCallback( $s, $func ); 00182 } 00183 00184 public static function lcfirst( $parser, $s = '' ) { 00185 global $wgContLang; 00186 return $wgContLang->lcfirst( $s ); 00187 } 00188 00189 public static function ucfirst( $parser, $s = '' ) { 00190 global $wgContLang; 00191 return $wgContLang->ucfirst( $s ); 00192 } 00193 00199 public static function lc( $parser, $s = '' ) { 00200 global $wgContLang; 00201 return $parser->markerSkipCallback( $s, array( $wgContLang, 'lc' ) ); 00202 } 00203 00209 public static function uc( $parser, $s = '' ) { 00210 global $wgContLang; 00211 return $parser->markerSkipCallback( $s, array( $wgContLang, 'uc' ) ); 00212 } 00213 00214 public static function localurl( $parser, $s = '', $arg = null ) { 00215 return self::urlFunction( 'getLocalURL', $s, $arg ); 00216 } 00217 00218 public static function localurle( $parser, $s = '', $arg = null ) { 00219 $temp = self::urlFunction( 'getLocalURL', $s, $arg ); 00220 if ( !is_string( $temp ) ) { 00221 return $temp; 00222 } else { 00223 return htmlspecialchars( $temp ); 00224 } 00225 } 00226 00227 public static function fullurl( $parser, $s = '', $arg = null ) { 00228 return self::urlFunction( 'getFullURL', $s, $arg ); 00229 } 00230 00231 public static function fullurle( $parser, $s = '', $arg = null ) { 00232 $temp = self::urlFunction( 'getFullURL', $s, $arg ); 00233 if ( !is_string( $temp ) ) { 00234 return $temp; 00235 } else { 00236 return htmlspecialchars( $temp ); 00237 } 00238 } 00239 00240 public static function canonicalurl( $parser, $s = '', $arg = null ) { 00241 return self::urlFunction( 'getCanonicalURL', $s, $arg ); 00242 } 00243 00244 public static function canonicalurle( $parser, $s = '', $arg = null ) { 00245 $temp = self::urlFunction( 'getCanonicalURL', $s, $arg ); 00246 if ( !is_string( $temp ) ) { 00247 return $temp; 00248 } else { 00249 return htmlspecialchars( $temp ); 00250 } 00251 } 00252 00253 public static function urlFunction( $func, $s = '', $arg = null ) { 00254 $title = Title::newFromText( $s ); 00255 # Due to order of execution of a lot of bits, the values might be encoded 00256 # before arriving here; if that's true, then the title can't be created 00257 # and the variable will fail. If we can't get a decent title from the first 00258 # attempt, url-decode and try for a second. 00259 if ( is_null( $title ) ) { 00260 $title = Title::newFromURL( urldecode( $s ) ); 00261 } 00262 if ( !is_null( $title ) ) { 00263 # Convert NS_MEDIA -> NS_FILE 00264 if ( $title->getNamespace() == NS_MEDIA ) { 00265 $title = Title::makeTitle( NS_FILE, $title->getDBkey() ); 00266 } 00267 if ( !is_null( $arg ) ) { 00268 $text = $title->$func( $arg ); 00269 } else { 00270 $text = $title->$func(); 00271 } 00272 return $text; 00273 } else { 00274 return array( 'found' => false ); 00275 } 00276 } 00277 00284 public static function formatnum( $parser, $num = '', $arg = null ) { 00285 if ( self::matchAgainstMagicword( 'rawsuffix', $arg ) ) { 00286 $func = array( $parser->getFunctionLang(), 'parseFormattedNumber' ); 00287 } elseif ( self::matchAgainstMagicword( 'nocommafysuffix', $arg ) ) { 00288 $func = array( $parser->getFunctionLang(), 'formatNumNoSeparators' ); 00289 } else { 00290 $func = array( $parser->getFunctionLang(), 'formatNum' ); 00291 } 00292 return $parser->markerSkipCallback( $num, $func ); 00293 } 00294 00301 public static function grammar( $parser, $case = '', $word = '' ) { 00302 $word = $parser->killMarkers( $word ); 00303 return $parser->getFunctionLang()->convertGrammar( $word, $case ); 00304 } 00305 00311 public static function gender( $parser, $username ) { 00312 wfProfileIn( __METHOD__ ); 00313 $forms = array_slice( func_get_args(), 2 ); 00314 00315 // Some shortcuts to avoid loading user data unnecessarily 00316 if ( count( $forms ) === 0 ) { 00317 wfProfileOut( __METHOD__ ); 00318 return ''; 00319 } elseif ( count( $forms ) === 1 ) { 00320 wfProfileOut( __METHOD__ ); 00321 return $forms[0]; 00322 } 00323 00324 $username = trim( $username ); 00325 00326 // default 00327 $gender = User::getDefaultOption( 'gender' ); 00328 00329 // allow prefix. 00330 $title = Title::newFromText( $username ); 00331 00332 if ( $title && $title->getNamespace() == NS_USER ) { 00333 $username = $title->getText(); 00334 } 00335 00336 // check parameter, or use the ParserOptions if in interface message 00337 $user = User::newFromName( $username ); 00338 if ( $user ) { 00339 $gender = GenderCache::singleton()->getGenderOf( $user, __METHOD__ ); 00340 } elseif ( $username === '' && $parser->getOptions()->getInterfaceMessage() ) { 00341 $gender = GenderCache::singleton()->getGenderOf( $parser->getOptions()->getUser(), __METHOD__ ); 00342 } 00343 $ret = $parser->getFunctionLang()->gender( $gender, $forms ); 00344 wfProfileOut( __METHOD__ ); 00345 return $ret; 00346 } 00347 00353 public static function plural( $parser, $text = '' ) { 00354 $forms = array_slice( func_get_args(), 2 ); 00355 $text = $parser->getFunctionLang()->parseFormattedNumber( $text ); 00356 settype( $text, ctype_digit( $text ) ? 'int' : 'float' ); 00357 return $parser->getFunctionLang()->convertPlural( $text, $forms ); 00358 } 00359 00369 public static function displaytitle( $parser, $text = '', $uarg = '' ) { 00370 global $wgRestrictDisplayTitle; 00371 00372 static $magicWords = null; 00373 if ( is_null( $magicWords ) ) { 00374 $magicWords = new MagicWordArray( array( 'displaytitle_noerror', 'displaytitle_noreplace' ) ); 00375 } 00376 $arg = $magicWords->matchStartToEnd( $uarg ); 00377 00378 // parse a limited subset of wiki markup (just the single quote items) 00379 $text = $parser->doQuotes( $text ); 00380 00381 // remove stripped text (e.g. the UNIQ-QINU stuff) that was generated by tag extensions/whatever 00382 $text = preg_replace( '/' . preg_quote( $parser->uniqPrefix(), '/' ) . '.*?' 00383 . preg_quote( Parser::MARKER_SUFFIX, '/' ) . '/', '', $text ); 00384 00385 // list of disallowed tags for DISPLAYTITLE 00386 // these will be escaped even though they are allowed in normal wiki text 00387 $bad = array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'blockquote', 'ol', 'ul', 'li', 'hr', 00388 'table', 'tr', 'th', 'td', 'dl', 'dd', 'caption', 'p', 'ruby', 'rb', 'rt', 'rtc', 'rp', 'br' ); 00389 00390 // disallow some styles that could be used to bypass $wgRestrictDisplayTitle 00391 if ( $wgRestrictDisplayTitle ) { 00392 $htmlTagsCallback = function ( &$params ) { 00393 $decoded = Sanitizer::decodeTagAttributes( $params ); 00394 00395 if ( isset( $decoded['style'] ) ) { 00396 // this is called later anyway, but we need it right now for the regexes below to be safe 00397 // calling it twice doesn't hurt 00398 $decoded['style'] = Sanitizer::checkCss( $decoded['style'] ); 00399 00400 if ( preg_match( '/(display|user-select|visibility)\s*:/i', $decoded['style'] ) ) { 00401 $decoded['style'] = '/* attempt to bypass $wgRestrictDisplayTitle */'; 00402 } 00403 } 00404 00405 $params = Sanitizer::safeEncodeTagAttributes( $decoded ); 00406 }; 00407 } else { 00408 $htmlTagsCallback = null; 00409 } 00410 00411 // only requested titles that normalize to the actual title are allowed through 00412 // if $wgRestrictDisplayTitle is true (it is by default) 00413 // mimic the escaping process that occurs in OutputPage::setPageTitle 00414 $text = Sanitizer::normalizeCharReferences( Sanitizer::removeHTMLtags( 00415 $text, 00416 $htmlTagsCallback, 00417 array(), 00418 array(), 00419 $bad 00420 ) ); 00421 $title = Title::newFromText( Sanitizer::stripAllTags( $text ) ); 00422 00423 if ( !$wgRestrictDisplayTitle || 00424 ( $title instanceof Title 00425 && !$title->hasFragment() 00426 && $title->equals( $parser->mTitle ) ) 00427 ) { 00428 $old = $parser->mOutput->getProperty( 'displaytitle' ); 00429 if ( $old === false || $arg !== 'displaytitle_noreplace' ) { 00430 $parser->mOutput->setDisplayTitle( $text ); 00431 } 00432 if ( $old !== false && $old !== $text && !$arg ) { 00433 $converter = $parser->getConverterLanguage()->getConverter(); 00434 return '<span class="error">' . 00435 wfMessage( 'duplicate-displaytitle', 00436 // Message should be parsed, but these params should only be escaped. 00437 $converter->markNoConversion( wfEscapeWikiText( $old ) ), 00438 $converter->markNoConversion( wfEscapeWikiText( $text ) ) 00439 )->inContentLanguage()->text() . 00440 '</span>'; 00441 } 00442 } 00443 00444 return ''; 00445 } 00446 00454 private static function matchAgainstMagicword( $magicword, $value ) { 00455 $value = trim( strval( $value ) ); 00456 if ( $value === '' ) { 00457 return false; 00458 } 00459 $mwObject = MagicWord::get( $magicword ); 00460 return $mwObject->matchStartToEnd( $value ); 00461 } 00462 00463 public static function formatRaw( $num, $raw ) { 00464 if ( self::matchAgainstMagicword( 'rawsuffix', $raw ) ) { 00465 return $num; 00466 } else { 00467 global $wgContLang; 00468 return $wgContLang->formatNum( $num ); 00469 } 00470 } 00471 public static function numberofpages( $parser, $raw = null ) { 00472 return self::formatRaw( SiteStats::pages(), $raw ); 00473 } 00474 public static function numberofusers( $parser, $raw = null ) { 00475 return self::formatRaw( SiteStats::users(), $raw ); 00476 } 00477 public static function numberofactiveusers( $parser, $raw = null ) { 00478 return self::formatRaw( SiteStats::activeUsers(), $raw ); 00479 } 00480 public static function numberofarticles( $parser, $raw = null ) { 00481 return self::formatRaw( SiteStats::articles(), $raw ); 00482 } 00483 public static function numberoffiles( $parser, $raw = null ) { 00484 return self::formatRaw( SiteStats::images(), $raw ); 00485 } 00486 public static function numberofadmins( $parser, $raw = null ) { 00487 return self::formatRaw( SiteStats::numberingroup( 'sysop' ), $raw ); 00488 } 00489 public static function numberofedits( $parser, $raw = null ) { 00490 return self::formatRaw( SiteStats::edits(), $raw ); 00491 } 00492 public static function numberofviews( $parser, $raw = null ) { 00493 global $wgDisableCounters; 00494 return !$wgDisableCounters ? self::formatRaw( SiteStats::views(), $raw ) : ''; 00495 } 00496 public static function pagesinnamespace( $parser, $namespace = 0, $raw = null ) { 00497 return self::formatRaw( SiteStats::pagesInNs( intval( $namespace ) ), $raw ); 00498 } 00499 public static function numberingroup( $parser, $name = '', $raw = null ) { 00500 return self::formatRaw( SiteStats::numberingroup( strtolower( $name ) ), $raw ); 00501 } 00502 00512 public static function mwnamespace( $parser, $title = null ) { 00513 $t = Title::newFromText( $title ); 00514 if ( is_null( $t ) ) { 00515 return ''; 00516 } 00517 return str_replace( '_', ' ', $t->getNsText() ); 00518 } 00519 public static function namespacee( $parser, $title = null ) { 00520 $t = Title::newFromText( $title ); 00521 if ( is_null( $t ) ) { 00522 return ''; 00523 } 00524 return wfUrlencode( $t->getNsText() ); 00525 } 00526 public static function namespacenumber( $parser, $title = null ) { 00527 $t = Title::newFromText( $title ); 00528 if ( is_null( $t ) ) { 00529 return ''; 00530 } 00531 return $t->getNamespace(); 00532 } 00533 public static function talkspace( $parser, $title = null ) { 00534 $t = Title::newFromText( $title ); 00535 if ( is_null( $t ) || !$t->canTalk() ) { 00536 return ''; 00537 } 00538 return str_replace( '_', ' ', $t->getTalkNsText() ); 00539 } 00540 public static function talkspacee( $parser, $title = null ) { 00541 $t = Title::newFromText( $title ); 00542 if ( is_null( $t ) || !$t->canTalk() ) { 00543 return ''; 00544 } 00545 return wfUrlencode( $t->getTalkNsText() ); 00546 } 00547 public static function subjectspace( $parser, $title = null ) { 00548 $t = Title::newFromText( $title ); 00549 if ( is_null( $t ) ) { 00550 return ''; 00551 } 00552 return str_replace( '_', ' ', $t->getSubjectNsText() ); 00553 } 00554 public static function subjectspacee( $parser, $title = null ) { 00555 $t = Title::newFromText( $title ); 00556 if ( is_null( $t ) ) { 00557 return ''; 00558 } 00559 return wfUrlencode( $t->getSubjectNsText() ); 00560 } 00561 00569 public static function pagename( $parser, $title = null ) { 00570 $t = Title::newFromText( $title ); 00571 if ( is_null( $t ) ) { 00572 return ''; 00573 } 00574 return wfEscapeWikiText( $t->getText() ); 00575 } 00576 public static function pagenamee( $parser, $title = null ) { 00577 $t = Title::newFromText( $title ); 00578 if ( is_null( $t ) ) { 00579 return ''; 00580 } 00581 return wfEscapeWikiText( $t->getPartialURL() ); 00582 } 00583 public static function fullpagename( $parser, $title = null ) { 00584 $t = Title::newFromText( $title ); 00585 if ( is_null( $t ) || !$t->canTalk() ) { 00586 return ''; 00587 } 00588 return wfEscapeWikiText( $t->getPrefixedText() ); 00589 } 00590 public static function fullpagenamee( $parser, $title = null ) { 00591 $t = Title::newFromText( $title ); 00592 if ( is_null( $t ) || !$t->canTalk() ) { 00593 return ''; 00594 } 00595 return wfEscapeWikiText( $t->getPrefixedURL() ); 00596 } 00597 public static function subpagename( $parser, $title = null ) { 00598 $t = Title::newFromText( $title ); 00599 if ( is_null( $t ) ) { 00600 return ''; 00601 } 00602 return wfEscapeWikiText( $t->getSubpageText() ); 00603 } 00604 public static function subpagenamee( $parser, $title = null ) { 00605 $t = Title::newFromText( $title ); 00606 if ( is_null( $t ) ) { 00607 return ''; 00608 } 00609 return wfEscapeWikiText( $t->getSubpageUrlForm() ); 00610 } 00611 public static function rootpagename( $parser, $title = null ) { 00612 $t = Title::newFromText( $title ); 00613 if ( is_null( $t ) ) { 00614 return ''; 00615 } 00616 return wfEscapeWikiText( $t->getRootText() ); 00617 } 00618 public static function rootpagenamee( $parser, $title = null ) { 00619 $t = Title::newFromText( $title ); 00620 if ( is_null( $t ) ) { 00621 return ''; 00622 } 00623 return wfEscapeWikiText( wfUrlEncode( str_replace( ' ', '_', $t->getRootText() ) ) ); 00624 } 00625 public static function basepagename( $parser, $title = null ) { 00626 $t = Title::newFromText( $title ); 00627 if ( is_null( $t ) ) { 00628 return ''; 00629 } 00630 return wfEscapeWikiText( $t->getBaseText() ); 00631 } 00632 public static function basepagenamee( $parser, $title = null ) { 00633 $t = Title::newFromText( $title ); 00634 if ( is_null( $t ) ) { 00635 return ''; 00636 } 00637 return wfEscapeWikiText( wfUrlEncode( str_replace( ' ', '_', $t->getBaseText() ) ) ); 00638 } 00639 public static function talkpagename( $parser, $title = null ) { 00640 $t = Title::newFromText( $title ); 00641 if ( is_null( $t ) || !$t->canTalk() ) { 00642 return ''; 00643 } 00644 return wfEscapeWikiText( $t->getTalkPage()->getPrefixedText() ); 00645 } 00646 public static function talkpagenamee( $parser, $title = null ) { 00647 $t = Title::newFromText( $title ); 00648 if ( is_null( $t ) || !$t->canTalk() ) { 00649 return ''; 00650 } 00651 return wfEscapeWikiText( $t->getTalkPage()->getPrefixedURL() ); 00652 } 00653 public static function subjectpagename( $parser, $title = null ) { 00654 $t = Title::newFromText( $title ); 00655 if ( is_null( $t ) ) { 00656 return ''; 00657 } 00658 return wfEscapeWikiText( $t->getSubjectPage()->getPrefixedText() ); 00659 } 00660 public static function subjectpagenamee( $parser, $title = null ) { 00661 $t = Title::newFromText( $title ); 00662 if ( is_null( $t ) ) { 00663 return ''; 00664 } 00665 return wfEscapeWikiText( $t->getSubjectPage()->getPrefixedURL() ); 00666 } 00667 00678 public static function pagesincategory( $parser, $name = '', $arg1 = null, $arg2 = null ) { 00679 global $wgContLang; 00680 static $magicWords = null; 00681 if ( is_null( $magicWords ) ) { 00682 $magicWords = new MagicWordArray( array( 00683 'pagesincategory_all', 00684 'pagesincategory_pages', 00685 'pagesincategory_subcats', 00686 'pagesincategory_files' 00687 ) ); 00688 } 00689 static $cache = array(); 00690 00691 // split the given option to its variable 00692 if ( self::matchAgainstMagicword( 'rawsuffix', $arg1 ) ) { 00693 //{{pagesincategory:|raw[|type]}} 00694 $raw = $arg1; 00695 $type = $magicWords->matchStartToEnd( $arg2 ); 00696 } else { 00697 //{{pagesincategory:[|type[|raw]]}} 00698 $type = $magicWords->matchStartToEnd( $arg1 ); 00699 $raw = $arg2; 00700 } 00701 if ( !$type ) { //backward compatibility 00702 $type = 'pagesincategory_all'; 00703 } 00704 00705 $title = Title::makeTitleSafe( NS_CATEGORY, $name ); 00706 if ( !$title ) { # invalid title 00707 return self::formatRaw( 0, $raw ); 00708 } 00709 $wgContLang->findVariantLink( $name, $title, true ); 00710 00711 // Normalize name for cache 00712 $name = $title->getDBkey(); 00713 00714 if ( !isset( $cache[$name] ) ) { 00715 $category = Category::newFromTitle( $title ); 00716 00717 $allCount = $subcatCount = $fileCount = $pagesCount = 0; 00718 if ( $parser->incrementExpensiveFunctionCount() ) { 00719 // $allCount is the total number of cat members, 00720 // not the count of how many members are normal pages. 00721 $allCount = (int)$category->getPageCount(); 00722 $subcatCount = (int)$category->getSubcatCount(); 00723 $fileCount = (int)$category->getFileCount(); 00724 $pagesCount = $allCount - $subcatCount - $fileCount; 00725 } 00726 $cache[$name]['pagesincategory_all'] = $allCount; 00727 $cache[$name]['pagesincategory_pages'] = $pagesCount; 00728 $cache[$name]['pagesincategory_subcats'] = $subcatCount; 00729 $cache[$name]['pagesincategory_files'] = $fileCount; 00730 } 00731 00732 $count = $cache[$name][$type]; 00733 return self::formatRaw( $count, $raw ); 00734 } 00735 00745 public static function pagesize( $parser, $page = '', $raw = null ) { 00746 $title = Title::newFromText( $page ); 00747 00748 if ( !is_object( $title ) ) { 00749 return self::formatRaw( 0, $raw ); 00750 } 00751 00752 // fetch revision from cache/database and return the value 00753 $rev = self::getCachedRevisionObject( $parser, $title ); 00754 $length = $rev ? $rev->getSize() : 0; 00755 return self::formatRaw( $length, $raw ); 00756 } 00757 00770 public static function protectionlevel( $parser, $type = '', $title = '' ) { 00771 $titleObject = Title::newFromText( $title ); 00772 if ( !( $titleObject instanceof Title ) ) { 00773 $titleObject = $parser->mTitle; 00774 } 00775 if ( $titleObject->areRestrictionsLoaded() || $parser->incrementExpensiveFunctionCount() ) { 00776 $restrictions = $titleObject->getRestrictions( strtolower( $type ) ); 00777 # Title::getRestrictions returns an array, its possible it may have 00778 # multiple values in the future 00779 return implode( $restrictions, ',' ); 00780 } 00781 return ''; 00782 } 00783 00791 public static function language( $parser, $code = '', $inLanguage = '' ) { 00792 $code = strtolower( $code ); 00793 $inLanguage = strtolower( $inLanguage ); 00794 $lang = Language::fetchLanguageName( $code, $inLanguage ); 00795 return $lang !== '' ? $lang : wfBCP47( $code ); 00796 } 00797 00807 public static function pad( $parser, $string, $length, $padding = '0', $direction = STR_PAD_RIGHT ) { 00808 $padding = $parser->killMarkers( $padding ); 00809 $lengthOfPadding = mb_strlen( $padding ); 00810 if ( $lengthOfPadding == 0 ) { 00811 return $string; 00812 } 00813 00814 # The remaining length to add counts down to 0 as padding is added 00815 $length = min( $length, 500 ) - mb_strlen( $string ); 00816 # $finalPadding is just $padding repeated enough times so that 00817 # mb_strlen( $string ) + mb_strlen( $finalPadding ) == $length 00818 $finalPadding = ''; 00819 while ( $length > 0 ) { 00820 # If $length < $lengthofPadding, truncate $padding so we get the 00821 # exact length desired. 00822 $finalPadding .= mb_substr( $padding, 0, $length ); 00823 $length -= $lengthOfPadding; 00824 } 00825 00826 if ( $direction == STR_PAD_LEFT ) { 00827 return $finalPadding . $string; 00828 } else { 00829 return $string . $finalPadding; 00830 } 00831 } 00832 00833 public static function padleft( $parser, $string = '', $length = 0, $padding = '0' ) { 00834 return self::pad( $parser, $string, $length, $padding, STR_PAD_LEFT ); 00835 } 00836 00837 public static function padright( $parser, $string = '', $length = 0, $padding = '0' ) { 00838 return self::pad( $parser, $string, $length, $padding ); 00839 } 00840 00846 public static function anchorencode( $parser, $text ) { 00847 $text = $parser->killMarkers( $text ); 00848 return (string)substr( $parser->guessSectionNameFromWikiText( $text ), 1 ); 00849 } 00850 00851 public static function special( $parser, $text ) { 00852 list( $page, $subpage ) = SpecialPageFactory::resolveAlias( $text ); 00853 if ( $page ) { 00854 $title = SpecialPage::getTitleFor( $page, $subpage ); 00855 return $title->getPrefixedText(); 00856 } else { 00857 // unknown special page, just use the given text as its title, if at all possible 00858 $title = Title::makeTitleSafe( NS_SPECIAL, $text ); 00859 return $title ? $title->getPrefixedText() : self::special( $parser, 'Badtitle' ); 00860 } 00861 } 00862 00863 public static function speciale( $parser, $text ) { 00864 return wfUrlencode( str_replace( ' ', '_', self::special( $parser, $text ) ) ); 00865 } 00866 00875 public static function defaultsort( $parser, $text, $uarg = '' ) { 00876 static $magicWords = null; 00877 if ( is_null( $magicWords ) ) { 00878 $magicWords = new MagicWordArray( array( 'defaultsort_noerror', 'defaultsort_noreplace' ) ); 00879 } 00880 $arg = $magicWords->matchStartToEnd( $uarg ); 00881 00882 $text = trim( $text ); 00883 if ( strlen( $text ) == 0 ) { 00884 return ''; 00885 } 00886 $old = $parser->getCustomDefaultSort(); 00887 if ( $old === false || $arg !== 'defaultsort_noreplace' ) { 00888 $parser->setDefaultSort( $text ); 00889 } 00890 00891 if ( $old === false || $old == $text || $arg ) { 00892 return ''; 00893 } else { 00894 $converter = $parser->getConverterLanguage()->getConverter(); 00895 return '<span class="error">' . 00896 wfMessage( 'duplicate-defaultsort', 00897 // Message should be parsed, but these params should only be escaped. 00898 $converter->markNoConversion( wfEscapeWikiText( $old ) ), 00899 $converter->markNoConversion( wfEscapeWikiText( $text ) ) 00900 )->inContentLanguage()->text() . 00901 '</span>'; 00902 } 00903 } 00904 00905 // Usage {{filepath|300}}, {{filepath|nowiki}}, {{filepath|nowiki|300}} 00906 // or {{filepath|300|nowiki}} or {{filepath|300px}}, {{filepath|200x300px}}, 00907 // {{filepath|nowiki|200x300px}}, {{filepath|200x300px|nowiki}}. 00908 public static function filepath( $parser, $name = '', $argA = '', $argB = '' ) { 00909 $file = wfFindFile( $name ); 00910 00911 if ( $argA == 'nowiki' ) { 00912 // {{filepath: | option [| size] }} 00913 $isNowiki = true; 00914 $parsedWidthParam = $parser->parseWidthParam( $argB ); 00915 } else { 00916 // {{filepath: [| size [|option]] }} 00917 $parsedWidthParam = $parser->parseWidthParam( $argA ); 00918 $isNowiki = ( $argB == 'nowiki' ); 00919 } 00920 00921 if ( $file ) { 00922 $url = $file->getFullUrl(); 00923 00924 // If a size is requested... 00925 if ( count( $parsedWidthParam ) ) { 00926 $mto = $file->transform( $parsedWidthParam ); 00927 // ... and we can 00928 if ( $mto && !$mto->isError() ) { 00929 // ... change the URL to point to a thumbnail. 00930 $url = wfExpandUrl( $mto->getUrl(), PROTO_RELATIVE ); 00931 } 00932 } 00933 if ( $isNowiki ) { 00934 return array( $url, 'nowiki' => true ); 00935 } 00936 return $url; 00937 } else { 00938 return ''; 00939 } 00940 } 00941 00949 public static function tagObj( $parser, $frame, $args ) { 00950 if ( !count( $args ) ) { 00951 return ''; 00952 } 00953 $tagName = strtolower( trim( $frame->expand( array_shift( $args ) ) ) ); 00954 00955 if ( count( $args ) ) { 00956 $inner = $frame->expand( array_shift( $args ) ); 00957 } else { 00958 $inner = null; 00959 } 00960 00961 $stripList = $parser->getStripList(); 00962 if ( !in_array( $tagName, $stripList ) ) { 00963 return '<span class="error">' . 00964 wfMessage( 'unknown_extension_tag', $tagName )->inContentLanguage()->text() . 00965 '</span>'; 00966 } 00967 00968 $attributes = array(); 00969 foreach ( $args as $arg ) { 00970 $bits = $arg->splitArg(); 00971 if ( strval( $bits['index'] ) === '' ) { 00972 $name = trim( $frame->expand( $bits['name'], PPFrame::STRIP_COMMENTS ) ); 00973 $value = trim( $frame->expand( $bits['value'] ) ); 00974 if ( preg_match( '/^(?:["\'](.+)["\']|""|\'\')$/s', $value, $m ) ) { 00975 $value = isset( $m[1] ) ? $m[1] : ''; 00976 } 00977 $attributes[$name] = $value; 00978 } 00979 } 00980 00981 $params = array( 00982 'name' => $tagName, 00983 'inner' => $inner, 00984 'attributes' => $attributes, 00985 'close' => "</$tagName>", 00986 ); 00987 return $parser->extensionSubstitution( $params, $frame ); 00988 } 00989 01002 private static function getCachedRevisionObject( $parser, $title = null ) { 01003 static $cache = null; 01004 if ( $cache == null ) { 01005 $cache = new MapCacheLRU( 50 ); 01006 } 01007 01008 if ( is_null( $title ) ) { 01009 return null; 01010 } 01011 01012 // Use the revision from the parser itself, when param is the current page 01013 // and the revision is the current one 01014 if ( $title->equals( $parser->getTitle() ) ) { 01015 $parserRev = $parser->getRevisionObject(); 01016 if ( $parserRev && $parserRev->isCurrent() ) { 01017 // force reparse after edit with vary-revision flag 01018 $parser->getOutput()->setFlag( 'vary-revision' ); 01019 wfDebug( __METHOD__ . ": use current revision from parser, setting vary-revision...\n" ); 01020 return $parserRev; 01021 } 01022 } 01023 01024 // Normalize name for cache 01025 $page = $title->getPrefixedDBkey(); 01026 01027 if ( $cache->has( $page ) ) { // cache contains null values 01028 return $cache->get( $page ); 01029 } 01030 if ( $parser->incrementExpensiveFunctionCount() ) { 01031 $rev = Revision::newFromTitle( $title, false, Revision::READ_NORMAL ); 01032 $pageID = $rev ? $rev->getPage() : 0; 01033 $revID = $rev ? $rev->getId() : 0; 01034 $cache->set( $page, $rev ); // maybe null 01035 01036 // Register dependency in templatelinks 01037 $parser->getOutput()->addTemplate( $title, $pageID, $revID ); 01038 01039 return $rev; 01040 } 01041 $cache->set( $page, null ); 01042 return null; 01043 } 01044 01052 public static function pageid( $parser, $title = null ) { 01053 $t = Title::newFromText( $title ); 01054 if ( is_null( $t ) ) { 01055 return ''; 01056 } 01057 // Use title from parser to have correct pageid after edit 01058 if ( $t->equals( $parser->getTitle() ) ) { 01059 $t = $parser->getTitle(); 01060 return $t->getArticleID(); 01061 } 01062 01063 // These can't have ids 01064 if ( !$t->canExist() || $t->isExternal() ) { 01065 return 0; 01066 } 01067 01068 // Check the link cache, maybe something already looked it up. 01069 $linkCache = LinkCache::singleton(); 01070 $pdbk = $t->getPrefixedDBkey(); 01071 $id = $linkCache->getGoodLinkID( $pdbk ); 01072 if ( $id != 0 ) { 01073 $parser->mOutput->addLink( $t, $id ); 01074 return $id; 01075 } 01076 if ( $linkCache->isBadLink( $pdbk ) ) { 01077 $parser->mOutput->addLink( $t, 0 ); 01078 return $id; 01079 } 01080 01081 // We need to load it from the DB, so mark expensive 01082 if ( $parser->incrementExpensiveFunctionCount() ) { 01083 $id = $t->getArticleID(); 01084 $parser->mOutput->addLink( $t, $id ); 01085 return $id; 01086 } 01087 return null; 01088 } 01089 01097 public static function revisionid( $parser, $title = null ) { 01098 $t = Title::newFromText( $title ); 01099 if ( is_null( $t ) ) { 01100 return ''; 01101 } 01102 // fetch revision from cache/database and return the value 01103 $rev = self::getCachedRevisionObject( $parser, $t ); 01104 return $rev ? $rev->getId() : ''; 01105 } 01106 01114 public static function revisionday( $parser, $title = null ) { 01115 $t = Title::newFromText( $title ); 01116 if ( is_null( $t ) ) { 01117 return ''; 01118 } 01119 // fetch revision from cache/database and return the value 01120 $rev = self::getCachedRevisionObject( $parser, $t ); 01121 return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'j' ) : ''; 01122 } 01123 01131 public static function revisionday2( $parser, $title = null ) { 01132 $t = Title::newFromText( $title ); 01133 if ( is_null( $t ) ) { 01134 return ''; 01135 } 01136 // fetch revision from cache/database and return the value 01137 $rev = self::getCachedRevisionObject( $parser, $t ); 01138 return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'd' ) : ''; 01139 } 01140 01148 public static function revisionmonth( $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 ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'm' ) : ''; 01156 } 01157 01165 public static function revisionmonth1( $parser, $title = null ) { 01166 $t = Title::newFromText( $title ); 01167 if ( is_null( $t ) ) { 01168 return ''; 01169 } 01170 // fetch revision from cache/database and return the value 01171 $rev = self::getCachedRevisionObject( $parser, $t ); 01172 return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'n' ) : ''; 01173 } 01174 01182 public static function revisionyear( $parser, $title = null ) { 01183 $t = Title::newFromText( $title ); 01184 if ( is_null( $t ) ) { 01185 return ''; 01186 } 01187 // fetch revision from cache/database and return the value 01188 $rev = self::getCachedRevisionObject( $parser, $t ); 01189 return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'Y' ) : ''; 01190 } 01191 01199 public static function revisiontimestamp( $parser, $title = null ) { 01200 $t = Title::newFromText( $title ); 01201 if ( is_null( $t ) ) { 01202 return ''; 01203 } 01204 // fetch revision from cache/database and return the value 01205 $rev = self::getCachedRevisionObject( $parser, $t ); 01206 return $rev ? MWTimestamp::getLocalInstance( $rev->getTimestamp() )->format( 'YmdHis' ) : ''; 01207 } 01208 01216 public static function revisionuser( $parser, $title = null ) { 01217 $t = Title::newFromText( $title ); 01218 if ( is_null( $t ) ) { 01219 return ''; 01220 } 01221 // fetch revision from cache/database and return the value 01222 $rev = self::getCachedRevisionObject( $parser, $t ); 01223 return $rev ? $rev->getUserText() : ''; 01224 } 01225 01238 public static function cascadingsources( $parser, $title = '' ) { 01239 $titleObject = Title::newFromText( $title ); 01240 if ( !( $titleObject instanceof Title ) ) { 01241 $titleObject = $parser->mTitle; 01242 } 01243 if ( $titleObject->areCascadeProtectionSourcesLoaded() 01244 || $parser->incrementExpensiveFunctionCount() 01245 ) { 01246 $names = array(); 01247 $sources = $titleObject->getCascadeProtectionSources(); 01248 foreach ( $sources[0] as $sourceTitle ) { 01249 $names[] = $sourceTitle->getPrefixedText(); 01250 } 01251 return implode( $names, '|' ); 01252 } 01253 return ''; 01254 } 01255 01256 }