Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like CoreParserFunctions often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use CoreParserFunctions, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 28 | class CoreParserFunctions { |
||
| 29 | /** |
||
| 30 | * @param Parser $parser |
||
| 31 | * @return void |
||
| 32 | */ |
||
| 33 | public static function register( $parser ) { |
||
| 34 | global $wgAllowDisplayTitle, $wgAllowSlowParserFunctions; |
||
| 35 | |||
| 36 | # Syntax for arguments (see Parser::setFunctionHook): |
||
| 37 | # "name for lookup in localized magic words array", |
||
| 38 | # function callback, |
||
| 39 | # optional Parser::SFH_NO_HASH to omit the hash from calls (e.g. {{int:...}} |
||
| 40 | # instead of {{#int:...}}) |
||
| 41 | $noHashFunctions = [ |
||
| 42 | 'ns', 'nse', 'urlencode', 'lcfirst', 'ucfirst', 'lc', 'uc', |
||
| 43 | 'localurl', 'localurle', 'fullurl', 'fullurle', 'canonicalurl', |
||
| 44 | 'canonicalurle', 'formatnum', 'grammar', 'gender', 'plural', 'bidi', |
||
| 45 | 'numberofpages', 'numberofusers', 'numberofactiveusers', |
||
| 46 | 'numberofarticles', 'numberoffiles', 'numberofadmins', |
||
| 47 | 'numberingroup', 'numberofedits', 'language', |
||
| 48 | 'padleft', 'padright', 'anchorencode', 'defaultsort', 'filepath', |
||
| 49 | 'pagesincategory', 'pagesize', 'protectionlevel', 'protectionexpiry', |
||
| 50 | 'namespacee', 'namespacenumber', 'talkspace', 'talkspacee', |
||
| 51 | 'subjectspace', 'subjectspacee', 'pagename', 'pagenamee', |
||
| 52 | 'fullpagename', 'fullpagenamee', 'rootpagename', 'rootpagenamee', |
||
| 53 | 'basepagename', 'basepagenamee', 'subpagename', 'subpagenamee', |
||
| 54 | 'talkpagename', 'talkpagenamee', 'subjectpagename', |
||
| 55 | 'subjectpagenamee', 'pageid', 'revisionid', 'revisionday', |
||
| 56 | 'revisionday2', 'revisionmonth', 'revisionmonth1', 'revisionyear', |
||
| 57 | 'revisiontimestamp', 'revisionuser', 'cascadingsources', |
||
| 58 | ]; |
||
| 59 | foreach ( $noHashFunctions as $func ) { |
||
| 60 | $parser->setFunctionHook( $func, [ __CLASS__, $func ], Parser::SFH_NO_HASH ); |
||
| 61 | } |
||
| 62 | |||
| 63 | $parser->setFunctionHook( |
||
| 64 | 'namespace', |
||
| 65 | [ __CLASS__, 'mwnamespace' ], |
||
| 66 | Parser::SFH_NO_HASH |
||
| 67 | ); |
||
| 68 | $parser->setFunctionHook( 'int', [ __CLASS__, 'intFunction' ], Parser::SFH_NO_HASH ); |
||
| 69 | $parser->setFunctionHook( 'special', [ __CLASS__, 'special' ] ); |
||
| 70 | $parser->setFunctionHook( 'speciale', [ __CLASS__, 'speciale' ] ); |
||
| 71 | $parser->setFunctionHook( 'tag', [ __CLASS__, 'tagObj' ], Parser::SFH_OBJECT_ARGS ); |
||
| 72 | $parser->setFunctionHook( 'formatdate', [ __CLASS__, 'formatDate' ] ); |
||
| 73 | |||
| 74 | if ( $wgAllowDisplayTitle ) { |
||
| 75 | $parser->setFunctionHook( |
||
| 76 | 'displaytitle', |
||
| 77 | [ __CLASS__, 'displaytitle' ], |
||
| 78 | Parser::SFH_NO_HASH |
||
| 79 | ); |
||
| 80 | } |
||
| 81 | if ( $wgAllowSlowParserFunctions ) { |
||
| 82 | $parser->setFunctionHook( |
||
| 83 | 'pagesinnamespace', |
||
| 84 | [ __CLASS__, 'pagesinnamespace' ], |
||
| 85 | Parser::SFH_NO_HASH |
||
| 86 | ); |
||
| 87 | } |
||
| 88 | } |
||
| 89 | |||
| 90 | /** |
||
| 91 | * @param Parser $parser |
||
| 92 | * @param string $part1 |
||
| 93 | * @return array |
||
| 94 | */ |
||
| 95 | public static function intFunction( $parser, $part1 = '' /*, ... */ ) { |
||
| 96 | if ( strval( $part1 ) !== '' ) { |
||
| 97 | $args = array_slice( func_get_args(), 2 ); |
||
| 98 | $message = wfMessage( $part1, $args ) |
||
| 99 | ->inLanguage( $parser->getOptions()->getUserLangObj() ); |
||
| 100 | if ( !$message->exists() ) { |
||
| 101 | // When message does not exists, the message name is surrounded by angle |
||
| 102 | // and can result in a tag, therefore escape the angles |
||
| 103 | return $message->escaped(); |
||
| 104 | } |
||
| 105 | return [ $message->plain(), 'noparse' => false ]; |
||
| 106 | } else { |
||
| 107 | return [ 'found' => false ]; |
||
| 108 | } |
||
| 109 | } |
||
| 110 | |||
| 111 | /** |
||
| 112 | * @param Parser $parser |
||
| 113 | * @param string $date |
||
| 114 | * @param string $defaultPref |
||
| 115 | * |
||
| 116 | * @return string |
||
| 117 | */ |
||
| 118 | public static function formatDate( $parser, $date, $defaultPref = null ) { |
||
| 119 | $lang = $parser->getFunctionLang(); |
||
| 120 | $df = DateFormatter::getInstance( $lang ); |
||
| 121 | |||
| 122 | $date = trim( $date ); |
||
| 123 | |||
| 124 | $pref = $parser->getOptions()->getDateFormat(); |
||
| 125 | |||
| 126 | // Specify a different default date format other than the normal default |
||
| 127 | // if the user has 'default' for their setting |
||
| 128 | if ( $pref == 'default' && $defaultPref ) { |
||
|
|
|||
| 129 | $pref = $defaultPref; |
||
| 130 | } |
||
| 131 | |||
| 132 | $date = $df->reformat( $pref, $date, [ 'match-whole' ] ); |
||
| 133 | return $date; |
||
| 134 | } |
||
| 135 | |||
| 136 | public static function ns( $parser, $part1 = '' ) { |
||
| 137 | global $wgContLang; |
||
| 138 | if ( intval( $part1 ) || $part1 == "0" ) { |
||
| 139 | $index = intval( $part1 ); |
||
| 140 | } else { |
||
| 141 | $index = $wgContLang->getNsIndex( str_replace( ' ', '_', $part1 ) ); |
||
| 142 | } |
||
| 143 | if ( $index !== false ) { |
||
| 144 | return $wgContLang->getFormattedNsText( $index ); |
||
| 145 | } else { |
||
| 146 | return [ 'found' => false ]; |
||
| 147 | } |
||
| 148 | } |
||
| 149 | |||
| 150 | public static function nse( $parser, $part1 = '' ) { |
||
| 151 | $ret = self::ns( $parser, $part1 ); |
||
| 152 | if ( is_string( $ret ) ) { |
||
| 153 | $ret = wfUrlencode( str_replace( ' ', '_', $ret ) ); |
||
| 154 | } |
||
| 155 | return $ret; |
||
| 156 | } |
||
| 157 | |||
| 158 | /** |
||
| 159 | * urlencodes a string according to one of three patterns: (bug 22474) |
||
| 160 | * |
||
| 161 | * By default (for HTTP "query" strings), spaces are encoded as '+'. |
||
| 162 | * Or to encode a value for the HTTP "path", spaces are encoded as '%20'. |
||
| 163 | * For links to "wiki"s, or similar software, spaces are encoded as '_', |
||
| 164 | * |
||
| 165 | * @param Parser $parser |
||
| 166 | * @param string $s The text to encode. |
||
| 167 | * @param string $arg (optional): The type of encoding. |
||
| 168 | * @return string |
||
| 169 | */ |
||
| 170 | public static function urlencode( $parser, $s = '', $arg = null ) { |
||
| 171 | static $magicWords = null; |
||
| 172 | if ( is_null( $magicWords ) ) { |
||
| 173 | $magicWords = new MagicWordArray( [ 'url_path', 'url_query', 'url_wiki' ] ); |
||
| 174 | } |
||
| 175 | switch ( $magicWords->matchStartToEnd( $arg ) ) { |
||
| 176 | |||
| 177 | // Encode as though it's a wiki page, '_' for ' '. |
||
| 178 | case 'url_wiki': |
||
| 179 | $func = 'wfUrlencode'; |
||
| 180 | $s = str_replace( ' ', '_', $s ); |
||
| 181 | break; |
||
| 182 | |||
| 183 | // Encode for an HTTP Path, '%20' for ' '. |
||
| 184 | case 'url_path': |
||
| 185 | $func = 'rawurlencode'; |
||
| 186 | break; |
||
| 187 | |||
| 188 | // Encode for HTTP query, '+' for ' '. |
||
| 189 | case 'url_query': |
||
| 190 | default: |
||
| 191 | $func = 'urlencode'; |
||
| 192 | } |
||
| 193 | // See T105242, where the choice to kill markers and various |
||
| 194 | // other options were discussed. |
||
| 195 | return $func( $parser->killMarkers( $s ) ); |
||
| 196 | } |
||
| 197 | |||
| 198 | public static function lcfirst( $parser, $s = '' ) { |
||
| 199 | global $wgContLang; |
||
| 200 | return $wgContLang->lcfirst( $s ); |
||
| 201 | } |
||
| 202 | |||
| 203 | public static function ucfirst( $parser, $s = '' ) { |
||
| 204 | global $wgContLang; |
||
| 205 | return $wgContLang->ucfirst( $s ); |
||
| 206 | } |
||
| 207 | |||
| 208 | /** |
||
| 209 | * @param Parser $parser |
||
| 210 | * @param string $s |
||
| 211 | * @return string |
||
| 212 | */ |
||
| 213 | public static function lc( $parser, $s = '' ) { |
||
| 214 | global $wgContLang; |
||
| 215 | return $parser->markerSkipCallback( $s, [ $wgContLang, 'lc' ] ); |
||
| 216 | } |
||
| 217 | |||
| 218 | /** |
||
| 219 | * @param Parser $parser |
||
| 220 | * @param string $s |
||
| 221 | * @return string |
||
| 222 | */ |
||
| 223 | public static function uc( $parser, $s = '' ) { |
||
| 224 | global $wgContLang; |
||
| 225 | return $parser->markerSkipCallback( $s, [ $wgContLang, 'uc' ] ); |
||
| 226 | } |
||
| 227 | |||
| 228 | public static function localurl( $parser, $s = '', $arg = null ) { |
||
| 229 | return self::urlFunction( 'getLocalURL', $s, $arg ); |
||
| 230 | } |
||
| 231 | |||
| 232 | View Code Duplication | public static function localurle( $parser, $s = '', $arg = null ) { |
|
| 233 | $temp = self::urlFunction( 'getLocalURL', $s, $arg ); |
||
| 234 | if ( !is_string( $temp ) ) { |
||
| 235 | return $temp; |
||
| 236 | } else { |
||
| 237 | return htmlspecialchars( $temp ); |
||
| 238 | } |
||
| 239 | } |
||
| 240 | |||
| 241 | public static function fullurl( $parser, $s = '', $arg = null ) { |
||
| 242 | return self::urlFunction( 'getFullURL', $s, $arg ); |
||
| 243 | } |
||
| 244 | |||
| 245 | View Code Duplication | public static function fullurle( $parser, $s = '', $arg = null ) { |
|
| 246 | $temp = self::urlFunction( 'getFullURL', $s, $arg ); |
||
| 247 | if ( !is_string( $temp ) ) { |
||
| 248 | return $temp; |
||
| 249 | } else { |
||
| 250 | return htmlspecialchars( $temp ); |
||
| 251 | } |
||
| 252 | } |
||
| 253 | |||
| 254 | public static function canonicalurl( $parser, $s = '', $arg = null ) { |
||
| 255 | return self::urlFunction( 'getCanonicalURL', $s, $arg ); |
||
| 256 | } |
||
| 257 | |||
| 258 | View Code Duplication | public static function canonicalurle( $parser, $s = '', $arg = null ) { |
|
| 259 | $temp = self::urlFunction( 'getCanonicalURL', $s, $arg ); |
||
| 260 | if ( !is_string( $temp ) ) { |
||
| 261 | return $temp; |
||
| 262 | } else { |
||
| 263 | return htmlspecialchars( $temp ); |
||
| 264 | } |
||
| 265 | } |
||
| 266 | |||
| 267 | public static function urlFunction( $func, $s = '', $arg = null ) { |
||
| 268 | $title = Title::newFromText( $s ); |
||
| 269 | # Due to order of execution of a lot of bits, the values might be encoded |
||
| 270 | # before arriving here; if that's true, then the title can't be created |
||
| 271 | # and the variable will fail. If we can't get a decent title from the first |
||
| 272 | # attempt, url-decode and try for a second. |
||
| 273 | if ( is_null( $title ) ) { |
||
| 274 | $title = Title::newFromURL( urldecode( $s ) ); |
||
| 275 | } |
||
| 276 | if ( !is_null( $title ) ) { |
||
| 277 | # Convert NS_MEDIA -> NS_FILE |
||
| 278 | if ( $title->getNamespace() == NS_MEDIA ) { |
||
| 279 | $title = Title::makeTitle( NS_FILE, $title->getDBkey() ); |
||
| 280 | } |
||
| 281 | if ( !is_null( $arg ) ) { |
||
| 282 | $text = $title->$func( $arg ); |
||
| 283 | } else { |
||
| 284 | $text = $title->$func(); |
||
| 285 | } |
||
| 286 | return $text; |
||
| 287 | } else { |
||
| 288 | return [ 'found' => false ]; |
||
| 289 | } |
||
| 290 | } |
||
| 291 | |||
| 292 | /** |
||
| 293 | * @param Parser $parser |
||
| 294 | * @param string $num |
||
| 295 | * @param string $arg |
||
| 296 | * @return string |
||
| 297 | */ |
||
| 298 | public static function formatnum( $parser, $num = '', $arg = null ) { |
||
| 299 | if ( self::matchAgainstMagicword( 'rawsuffix', $arg ) ) { |
||
| 300 | $func = [ $parser->getFunctionLang(), 'parseFormattedNumber' ]; |
||
| 301 | } elseif ( self::matchAgainstMagicword( 'nocommafysuffix', $arg ) ) { |
||
| 302 | $func = [ $parser->getFunctionLang(), 'formatNumNoSeparators' ]; |
||
| 303 | } else { |
||
| 304 | $func = [ $parser->getFunctionLang(), 'formatNum' ]; |
||
| 305 | } |
||
| 306 | return $parser->markerSkipCallback( $num, $func ); |
||
| 307 | } |
||
| 308 | |||
| 309 | /** |
||
| 310 | * @param Parser $parser |
||
| 311 | * @param string $case |
||
| 312 | * @param string $word |
||
| 313 | * @return string |
||
| 314 | */ |
||
| 315 | public static function grammar( $parser, $case = '', $word = '' ) { |
||
| 316 | $word = $parser->killMarkers( $word ); |
||
| 317 | return $parser->getFunctionLang()->convertGrammar( $word, $case ); |
||
| 318 | } |
||
| 319 | |||
| 320 | /** |
||
| 321 | * @param Parser $parser |
||
| 322 | * @param string $username |
||
| 323 | * @return string |
||
| 324 | */ |
||
| 325 | public static function gender( $parser, $username ) { |
||
| 326 | $forms = array_slice( func_get_args(), 2 ); |
||
| 327 | |||
| 328 | // Some shortcuts to avoid loading user data unnecessarily |
||
| 329 | if ( count( $forms ) === 0 ) { |
||
| 330 | return ''; |
||
| 331 | } elseif ( count( $forms ) === 1 ) { |
||
| 332 | return $forms[0]; |
||
| 333 | } |
||
| 334 | |||
| 335 | $username = trim( $username ); |
||
| 336 | |||
| 337 | // default |
||
| 338 | $gender = User::getDefaultOption( 'gender' ); |
||
| 339 | |||
| 340 | // allow prefix. |
||
| 341 | $title = Title::newFromText( $username ); |
||
| 342 | |||
| 343 | if ( $title && $title->getNamespace() == NS_USER ) { |
||
| 344 | $username = $title->getText(); |
||
| 345 | } |
||
| 346 | |||
| 347 | // check parameter, or use the ParserOptions if in interface message |
||
| 348 | $user = User::newFromName( $username ); |
||
| 349 | if ( $user ) { |
||
| 350 | $gender = GenderCache::singleton()->getGenderOf( $user, __METHOD__ ); |
||
| 351 | } elseif ( $username === '' && $parser->getOptions()->getInterfaceMessage() ) { |
||
| 352 | $gender = GenderCache::singleton()->getGenderOf( $parser->getOptions()->getUser(), __METHOD__ ); |
||
| 353 | } |
||
| 354 | $ret = $parser->getFunctionLang()->gender( $gender, $forms ); |
||
| 355 | return $ret; |
||
| 356 | } |
||
| 357 | |||
| 358 | /** |
||
| 359 | * @param Parser $parser |
||
| 360 | * @param string $text |
||
| 361 | * @return string |
||
| 362 | */ |
||
| 363 | public static function plural( $parser, $text = '' ) { |
||
| 364 | $forms = array_slice( func_get_args(), 2 ); |
||
| 365 | $text = $parser->getFunctionLang()->parseFormattedNumber( $text ); |
||
| 366 | settype( $text, ctype_digit( $text ) ? 'int' : 'float' ); |
||
| 367 | return $parser->getFunctionLang()->convertPlural( $text, $forms ); |
||
| 368 | } |
||
| 369 | |||
| 370 | /** |
||
| 371 | * @param Parser $parser |
||
| 372 | * @param string $text |
||
| 373 | * @return string |
||
| 374 | */ |
||
| 375 | public static function bidi( $parser, $text = '' ) { |
||
| 376 | return $parser->getFunctionLang()->embedBidi( $text ); |
||
| 377 | } |
||
| 378 | |||
| 379 | /** |
||
| 380 | * Override the title of the page when viewed, provided we've been given a |
||
| 381 | * title which will normalise to the canonical title |
||
| 382 | * |
||
| 383 | * @param Parser $parser Parent parser |
||
| 384 | * @param string $text Desired title text |
||
| 385 | * @param string $uarg |
||
| 386 | * @return string |
||
| 387 | */ |
||
| 388 | public static function displaytitle( $parser, $text = '', $uarg = '' ) { |
||
| 473 | |||
| 474 | /** |
||
| 475 | * Matches the given value against the value of given magic word |
||
| 476 | * |
||
| 477 | * @param string $magicword Magic word key |
||
| 478 | * @param string $value Value to match |
||
| 479 | * @return bool True on successful match |
||
| 480 | */ |
||
| 481 | private static function matchAgainstMagicword( $magicword, $value ) { |
||
| 482 | $value = trim( strval( $value ) ); |
||
| 483 | if ( $value === '' ) { |
||
| 484 | return false; |
||
| 485 | } |
||
| 486 | $mwObject = MagicWord::get( $magicword ); |
||
| 487 | return $mwObject->matchStartToEnd( $value ); |
||
| 488 | } |
||
| 489 | |||
| 490 | public static function formatRaw( $num, $raw ) { |
||
| 491 | if ( self::matchAgainstMagicword( 'rawsuffix', $raw ) ) { |
||
| 492 | return $num; |
||
| 493 | } else { |
||
| 494 | global $wgContLang; |
||
| 495 | return $wgContLang->formatNum( $num ); |
||
| 496 | } |
||
| 497 | } |
||
| 498 | public static function numberofpages( $parser, $raw = null ) { |
||
| 499 | return self::formatRaw( SiteStats::pages(), $raw ); |
||
| 500 | } |
||
| 501 | public static function numberofusers( $parser, $raw = null ) { |
||
| 502 | return self::formatRaw( SiteStats::users(), $raw ); |
||
| 503 | } |
||
| 504 | public static function numberofactiveusers( $parser, $raw = null ) { |
||
| 505 | return self::formatRaw( SiteStats::activeUsers(), $raw ); |
||
| 506 | } |
||
| 507 | public static function numberofarticles( $parser, $raw = null ) { |
||
| 508 | return self::formatRaw( SiteStats::articles(), $raw ); |
||
| 509 | } |
||
| 510 | public static function numberoffiles( $parser, $raw = null ) { |
||
| 511 | return self::formatRaw( SiteStats::images(), $raw ); |
||
| 512 | } |
||
| 513 | public static function numberofadmins( $parser, $raw = null ) { |
||
| 514 | return self::formatRaw( SiteStats::numberingroup( 'sysop' ), $raw ); |
||
| 515 | } |
||
| 516 | public static function numberofedits( $parser, $raw = null ) { |
||
| 517 | return self::formatRaw( SiteStats::edits(), $raw ); |
||
| 518 | } |
||
| 519 | public static function pagesinnamespace( $parser, $namespace = 0, $raw = null ) { |
||
| 520 | return self::formatRaw( SiteStats::pagesInNs( intval( $namespace ) ), $raw ); |
||
| 521 | } |
||
| 522 | public static function numberingroup( $parser, $name = '', $raw = null ) { |
||
| 523 | return self::formatRaw( SiteStats::numberingroup( strtolower( $name ) ), $raw ); |
||
| 524 | } |
||
| 525 | |||
| 526 | /** |
||
| 527 | * Given a title, return the namespace name that would be given by the |
||
| 528 | * corresponding magic word |
||
| 529 | * Note: function name changed to "mwnamespace" rather than "namespace" |
||
| 530 | * to not break PHP 5.3 |
||
| 531 | * @param Parser $parser |
||
| 532 | * @param string $title |
||
| 533 | * @return mixed|string |
||
| 534 | */ |
||
| 535 | public static function mwnamespace( $parser, $title = null ) { |
||
| 536 | $t = Title::newFromText( $title ); |
||
| 537 | if ( is_null( $t ) ) { |
||
| 538 | return ''; |
||
| 539 | } |
||
| 540 | return str_replace( '_', ' ', $t->getNsText() ); |
||
| 541 | } |
||
| 542 | View Code Duplication | public static function namespacee( $parser, $title = null ) { |
|
| 543 | $t = Title::newFromText( $title ); |
||
| 544 | if ( is_null( $t ) ) { |
||
| 545 | return ''; |
||
| 546 | } |
||
| 547 | return wfUrlencode( $t->getNsText() ); |
||
| 548 | } |
||
| 549 | public static function namespacenumber( $parser, $title = null ) { |
||
| 550 | $t = Title::newFromText( $title ); |
||
| 551 | if ( is_null( $t ) ) { |
||
| 552 | return ''; |
||
| 553 | } |
||
| 554 | return $t->getNamespace(); |
||
| 555 | } |
||
| 556 | public static function talkspace( $parser, $title = null ) { |
||
| 557 | $t = Title::newFromText( $title ); |
||
| 558 | if ( is_null( $t ) || !$t->canTalk() ) { |
||
| 559 | return ''; |
||
| 560 | } |
||
| 561 | return str_replace( '_', ' ', $t->getTalkNsText() ); |
||
| 562 | } |
||
| 563 | public static function talkspacee( $parser, $title = null ) { |
||
| 564 | $t = Title::newFromText( $title ); |
||
| 565 | if ( is_null( $t ) || !$t->canTalk() ) { |
||
| 566 | return ''; |
||
| 567 | } |
||
| 568 | return wfUrlencode( $t->getTalkNsText() ); |
||
| 569 | } |
||
| 570 | View Code Duplication | public static function subjectspace( $parser, $title = null ) { |
|
| 571 | $t = Title::newFromText( $title ); |
||
| 572 | if ( is_null( $t ) ) { |
||
| 573 | return ''; |
||
| 574 | } |
||
| 575 | return str_replace( '_', ' ', $t->getSubjectNsText() ); |
||
| 576 | } |
||
| 577 | View Code Duplication | public static function subjectspacee( $parser, $title = null ) { |
|
| 578 | $t = Title::newFromText( $title ); |
||
| 579 | if ( is_null( $t ) ) { |
||
| 580 | return ''; |
||
| 581 | } |
||
| 582 | return wfUrlencode( $t->getSubjectNsText() ); |
||
| 583 | } |
||
| 584 | |||
| 585 | /** |
||
| 586 | * Functions to get and normalize pagenames, corresponding to the magic words |
||
| 587 | * of the same names |
||
| 588 | * @param Parser $parser |
||
| 589 | * @param string $title |
||
| 590 | * @return string |
||
| 591 | */ |
||
| 592 | View Code Duplication | public static function pagename( $parser, $title = null ) { |
|
| 593 | $t = Title::newFromText( $title ); |
||
| 594 | if ( is_null( $t ) ) { |
||
| 595 | return ''; |
||
| 596 | } |
||
| 597 | return wfEscapeWikiText( $t->getText() ); |
||
| 598 | } |
||
| 599 | View Code Duplication | public static function pagenamee( $parser, $title = null ) { |
|
| 600 | $t = Title::newFromText( $title ); |
||
| 601 | if ( is_null( $t ) ) { |
||
| 602 | return ''; |
||
| 603 | } |
||
| 604 | return wfEscapeWikiText( $t->getPartialURL() ); |
||
| 605 | } |
||
| 606 | View Code Duplication | public static function fullpagename( $parser, $title = null ) { |
|
| 607 | $t = Title::newFromText( $title ); |
||
| 608 | if ( is_null( $t ) || !$t->canTalk() ) { |
||
| 609 | return ''; |
||
| 610 | } |
||
| 611 | return wfEscapeWikiText( $t->getPrefixedText() ); |
||
| 612 | } |
||
| 613 | public static function fullpagenamee( $parser, $title = null ) { |
||
| 614 | $t = Title::newFromText( $title ); |
||
| 615 | if ( is_null( $t ) || !$t->canTalk() ) { |
||
| 616 | return ''; |
||
| 617 | } |
||
| 618 | return wfEscapeWikiText( $t->getPrefixedURL() ); |
||
| 619 | } |
||
| 620 | View Code Duplication | public static function subpagename( $parser, $title = null ) { |
|
| 621 | $t = Title::newFromText( $title ); |
||
| 622 | if ( is_null( $t ) ) { |
||
| 623 | return ''; |
||
| 624 | } |
||
| 625 | return wfEscapeWikiText( $t->getSubpageText() ); |
||
| 626 | } |
||
| 627 | View Code Duplication | public static function subpagenamee( $parser, $title = null ) { |
|
| 628 | $t = Title::newFromText( $title ); |
||
| 629 | if ( is_null( $t ) ) { |
||
| 630 | return ''; |
||
| 631 | } |
||
| 632 | return wfEscapeWikiText( $t->getSubpageUrlForm() ); |
||
| 633 | } |
||
| 634 | View Code Duplication | public static function rootpagename( $parser, $title = null ) { |
|
| 635 | $t = Title::newFromText( $title ); |
||
| 636 | if ( is_null( $t ) ) { |
||
| 637 | return ''; |
||
| 638 | } |
||
| 639 | return wfEscapeWikiText( $t->getRootText() ); |
||
| 640 | } |
||
| 641 | View Code Duplication | public static function rootpagenamee( $parser, $title = null ) { |
|
| 642 | $t = Title::newFromText( $title ); |
||
| 643 | if ( is_null( $t ) ) { |
||
| 644 | return ''; |
||
| 645 | } |
||
| 646 | return wfEscapeWikiText( wfUrlencode( str_replace( ' ', '_', $t->getRootText() ) ) ); |
||
| 647 | } |
||
| 648 | View Code Duplication | public static function basepagename( $parser, $title = null ) { |
|
| 649 | $t = Title::newFromText( $title ); |
||
| 650 | if ( is_null( $t ) ) { |
||
| 651 | return ''; |
||
| 652 | } |
||
| 653 | return wfEscapeWikiText( $t->getBaseText() ); |
||
| 654 | } |
||
| 655 | View Code Duplication | public static function basepagenamee( $parser, $title = null ) { |
|
| 656 | $t = Title::newFromText( $title ); |
||
| 657 | if ( is_null( $t ) ) { |
||
| 658 | return ''; |
||
| 659 | } |
||
| 660 | return wfEscapeWikiText( wfUrlencode( str_replace( ' ', '_', $t->getBaseText() ) ) ); |
||
| 661 | } |
||
| 662 | public static function talkpagename( $parser, $title = null ) { |
||
| 663 | $t = Title::newFromText( $title ); |
||
| 664 | if ( is_null( $t ) || !$t->canTalk() ) { |
||
| 665 | return ''; |
||
| 666 | } |
||
| 667 | return wfEscapeWikiText( $t->getTalkPage()->getPrefixedText() ); |
||
| 668 | } |
||
| 669 | public static function talkpagenamee( $parser, $title = null ) { |
||
| 670 | $t = Title::newFromText( $title ); |
||
| 671 | if ( is_null( $t ) || !$t->canTalk() ) { |
||
| 672 | return ''; |
||
| 673 | } |
||
| 674 | return wfEscapeWikiText( $t->getTalkPage()->getPrefixedURL() ); |
||
| 675 | } |
||
| 676 | View Code Duplication | public static function subjectpagename( $parser, $title = null ) { |
|
| 677 | $t = Title::newFromText( $title ); |
||
| 678 | if ( is_null( $t ) ) { |
||
| 679 | return ''; |
||
| 680 | } |
||
| 681 | return wfEscapeWikiText( $t->getSubjectPage()->getPrefixedText() ); |
||
| 682 | } |
||
| 683 | View Code Duplication | public static function subjectpagenamee( $parser, $title = null ) { |
|
| 684 | $t = Title::newFromText( $title ); |
||
| 685 | if ( is_null( $t ) ) { |
||
| 686 | return ''; |
||
| 687 | } |
||
| 688 | return wfEscapeWikiText( $t->getSubjectPage()->getPrefixedURL() ); |
||
| 689 | } |
||
| 690 | |||
| 691 | /** |
||
| 692 | * Return the number of pages, files or subcats in the given category, |
||
| 693 | * or 0 if it's nonexistent. This is an expensive parser function and |
||
| 694 | * can't be called too many times per page. |
||
| 695 | * @param Parser $parser |
||
| 696 | * @param string $name |
||
| 697 | * @param string $arg1 |
||
| 698 | * @param string $arg2 |
||
| 699 | * @return string |
||
| 700 | */ |
||
| 701 | public static function pagesincategory( $parser, $name = '', $arg1 = null, $arg2 = null ) { |
||
| 702 | global $wgContLang; |
||
| 703 | static $magicWords = null; |
||
| 704 | if ( is_null( $magicWords ) ) { |
||
| 705 | $magicWords = new MagicWordArray( [ |
||
| 706 | 'pagesincategory_all', |
||
| 707 | 'pagesincategory_pages', |
||
| 708 | 'pagesincategory_subcats', |
||
| 709 | 'pagesincategory_files' |
||
| 710 | ] ); |
||
| 711 | } |
||
| 712 | static $cache = []; |
||
| 713 | |||
| 714 | // split the given option to its variable |
||
| 715 | if ( self::matchAgainstMagicword( 'rawsuffix', $arg1 ) ) { |
||
| 716 | // {{pagesincategory:|raw[|type]}} |
||
| 717 | $raw = $arg1; |
||
| 718 | $type = $magicWords->matchStartToEnd( $arg2 ); |
||
| 719 | } else { |
||
| 720 | // {{pagesincategory:[|type[|raw]]}} |
||
| 721 | $type = $magicWords->matchStartToEnd( $arg1 ); |
||
| 722 | $raw = $arg2; |
||
| 723 | } |
||
| 724 | if ( !$type ) { // backward compatibility |
||
| 725 | $type = 'pagesincategory_all'; |
||
| 726 | } |
||
| 727 | |||
| 728 | $title = Title::makeTitleSafe( NS_CATEGORY, $name ); |
||
| 729 | if ( !$title ) { # invalid title |
||
| 730 | return self::formatRaw( 0, $raw ); |
||
| 731 | } |
||
| 732 | $wgContLang->findVariantLink( $name, $title, true ); |
||
| 733 | |||
| 734 | // Normalize name for cache |
||
| 735 | $name = $title->getDBkey(); |
||
| 736 | |||
| 737 | if ( !isset( $cache[$name] ) ) { |
||
| 738 | $category = Category::newFromTitle( $title ); |
||
| 739 | |||
| 740 | $allCount = $subcatCount = $fileCount = $pagesCount = 0; |
||
| 741 | if ( $parser->incrementExpensiveFunctionCount() ) { |
||
| 742 | // $allCount is the total number of cat members, |
||
| 743 | // not the count of how many members are normal pages. |
||
| 744 | $allCount = (int)$category->getPageCount(); |
||
| 745 | $subcatCount = (int)$category->getSubcatCount(); |
||
| 746 | $fileCount = (int)$category->getFileCount(); |
||
| 747 | $pagesCount = $allCount - $subcatCount - $fileCount; |
||
| 748 | } |
||
| 749 | $cache[$name]['pagesincategory_all'] = $allCount; |
||
| 750 | $cache[$name]['pagesincategory_pages'] = $pagesCount; |
||
| 751 | $cache[$name]['pagesincategory_subcats'] = $subcatCount; |
||
| 752 | $cache[$name]['pagesincategory_files'] = $fileCount; |
||
| 753 | } |
||
| 754 | |||
| 755 | $count = $cache[$name][$type]; |
||
| 756 | return self::formatRaw( $count, $raw ); |
||
| 757 | } |
||
| 758 | |||
| 759 | /** |
||
| 760 | * Return the size of the given page, or 0 if it's nonexistent. This is an |
||
| 761 | * expensive parser function and can't be called too many times per page. |
||
| 762 | * |
||
| 763 | * @param Parser $parser |
||
| 764 | * @param string $page Name of page to check (Default: empty string) |
||
| 765 | * @param string $raw Should number be human readable with commas or just number |
||
| 766 | * @return string |
||
| 767 | */ |
||
| 768 | public static function pagesize( $parser, $page = '', $raw = null ) { |
||
| 784 | |||
| 785 | /** |
||
| 786 | * Returns the requested protection level for the current page. This |
||
| 787 | * is an expensive parser function and can't be called too many times |
||
| 788 | * per page, unless the protection levels/expiries for the given title |
||
| 789 | * have already been retrieved |
||
| 790 | * |
||
| 791 | * @param Parser $parser |
||
| 792 | * @param string $type |
||
| 793 | * @param string $title |
||
| 794 | * |
||
| 795 | * @return string |
||
| 796 | */ |
||
| 797 | View Code Duplication | public static function protectionlevel( $parser, $type = '', $title = '' ) { |
|
| 798 | $titleObject = Title::newFromText( $title ); |
||
| 799 | if ( !( $titleObject instanceof Title ) ) { |
||
| 800 | $titleObject = $parser->mTitle; |
||
| 801 | } |
||
| 802 | if ( $titleObject->areRestrictionsLoaded() || $parser->incrementExpensiveFunctionCount() ) { |
||
| 803 | $restrictions = $titleObject->getRestrictions( strtolower( $type ) ); |
||
| 804 | # Title::getRestrictions returns an array, its possible it may have |
||
| 805 | # multiple values in the future |
||
| 806 | return implode( $restrictions, ',' ); |
||
| 807 | } |
||
| 808 | return ''; |
||
| 809 | } |
||
| 810 | |||
| 811 | /** |
||
| 812 | * Returns the requested protection expiry for the current page. This |
||
| 813 | * is an expensive parser function and can't be called too many times |
||
| 814 | * per page, unless the protection levels/expiries for the given title |
||
| 815 | * have already been retrieved |
||
| 816 | * |
||
| 817 | * @param Parser $parser |
||
| 818 | * @param string $type |
||
| 819 | * @param string $title |
||
| 820 | * |
||
| 821 | * @return string |
||
| 822 | */ |
||
| 823 | View Code Duplication | public static function protectionexpiry( $parser, $type = '', $title = '' ) { |
|
| 824 | $titleObject = Title::newFromText( $title ); |
||
| 825 | if ( !( $titleObject instanceof Title ) ) { |
||
| 826 | $titleObject = $parser->mTitle; |
||
| 827 | } |
||
| 828 | if ( $titleObject->areRestrictionsLoaded() || $parser->incrementExpensiveFunctionCount() ) { |
||
| 829 | $expiry = $titleObject->getRestrictionExpiry( strtolower( $type ) ); |
||
| 830 | // getRestrictionExpiry() returns false on invalid type; trying to |
||
| 831 | // match protectionlevel() function that returns empty string instead |
||
| 832 | if ( $expiry === false ) { |
||
| 833 | $expiry = ''; |
||
| 834 | } |
||
| 835 | return $expiry; |
||
| 836 | } |
||
| 837 | return ''; |
||
| 838 | } |
||
| 839 | |||
| 840 | /** |
||
| 841 | * Gives language names. |
||
| 842 | * @param Parser $parser |
||
| 843 | * @param string $code Language code (of which to get name) |
||
| 844 | * @param string $inLanguage Language code (in which to get name) |
||
| 845 | * @return string |
||
| 846 | */ |
||
| 847 | public static function language( $parser, $code = '', $inLanguage = '' ) { |
||
| 853 | |||
| 854 | /** |
||
| 855 | * Unicode-safe str_pad with the restriction that $length is forced to be <= 500 |
||
| 856 | * @param Parser $parser |
||
| 857 | * @param string $string |
||
| 858 | * @param int $length |
||
| 859 | * @param string $padding |
||
| 860 | * @param int $direction |
||
| 861 | * @return string |
||
| 862 | */ |
||
| 863 | public static function pad( |
||
| 890 | |||
| 891 | public static function padleft( $parser, $string = '', $length = 0, $padding = '0' ) { |
||
| 894 | |||
| 895 | public static function padright( $parser, $string = '', $length = 0, $padding = '0' ) { |
||
| 898 | |||
| 899 | /** |
||
| 900 | * @param Parser $parser |
||
| 901 | * @param string $text |
||
| 902 | * @return string |
||
| 903 | */ |
||
| 904 | public static function anchorencode( $parser, $text ) { |
||
| 908 | |||
| 909 | public static function special( $parser, $text ) { |
||
| 920 | |||
| 921 | public static function speciale( $parser, $text ) { |
||
| 924 | |||
| 925 | /** |
||
| 926 | * @param Parser $parser |
||
| 927 | * @param string $text The sortkey to use |
||
| 928 | * @param string $uarg Either "noreplace" or "noerror" (in en) |
||
| 929 | * both suppress errors, and noreplace does nothing if |
||
| 930 | * a default sortkey already exists. |
||
| 931 | * @return string |
||
| 932 | */ |
||
| 933 | public static function defaultsort( $parser, $text, $uarg = '' ) { |
||
| 962 | |||
| 963 | /** |
||
| 964 | * Usage {{filepath|300}}, {{filepath|nowiki}}, {{filepath|nowiki|300}} |
||
| 965 | * or {{filepath|300|nowiki}} or {{filepath|300px}}, {{filepath|200x300px}}, |
||
| 966 | * {{filepath|nowiki|200x300px}}, {{filepath|200x300px|nowiki}}. |
||
| 967 | * |
||
| 968 | * @param Parser $parser |
||
| 969 | * @param string $name |
||
| 970 | * @param string $argA |
||
| 971 | * @param string $argB |
||
| 972 | * @return array|string |
||
| 973 | */ |
||
| 974 | public static function filepath( $parser, $name = '', $argA = '', $argB = '' ) { |
||
| 1007 | |||
| 1008 | /** |
||
| 1009 | * Parser function to extension tag adaptor |
||
| 1010 | * @param Parser $parser |
||
| 1011 | * @param PPFrame $frame |
||
| 1012 | * @param PPNode[] $args |
||
| 1013 | * @return string |
||
| 1014 | */ |
||
| 1015 | public static function tagObj( $parser, $frame, $args ) { |
||
| 1061 | |||
| 1062 | /** |
||
| 1063 | * Fetched the current revision of the given title and return this. |
||
| 1064 | * Will increment the expensive function count and |
||
| 1065 | * add a template link to get the value refreshed on changes. |
||
| 1066 | * For a given title, which is equal to the current parser title, |
||
| 1067 | * the revision object from the parser is used, when that is the current one |
||
| 1068 | * |
||
| 1069 | * @param Parser $parser |
||
| 1070 | * @param Title $title |
||
| 1071 | * @return Revision |
||
| 1072 | * @since 1.23 |
||
| 1073 | */ |
||
| 1074 | private static function getCachedRevisionObject( $parser, $title = null ) { |
||
| 1107 | |||
| 1108 | /** |
||
| 1109 | * Get the pageid of a specified page |
||
| 1110 | * @param Parser $parser |
||
| 1111 | * @param string $title Title to get the pageid from |
||
| 1112 | * @return int|null|string |
||
| 1113 | * @since 1.23 |
||
| 1114 | */ |
||
| 1115 | public static function pageid( $parser, $title = null ) { |
||
| 1152 | |||
| 1153 | /** |
||
| 1154 | * Get the id from the last revision of a specified page. |
||
| 1155 | * @param Parser $parser |
||
| 1156 | * @param string $title Title to get the id from |
||
| 1157 | * @return int|null|string |
||
| 1158 | * @since 1.23 |
||
| 1159 | */ |
||
| 1160 | View Code Duplication | public static function revisionid( $parser, $title = null ) { |
|
| 1169 | |||
| 1170 | /** |
||
| 1171 | * Get the day from the last revision of a specified page. |
||
| 1172 | * @param Parser $parser |
||
| 1173 | * @param string $title Title to get the day from |
||
| 1174 | * @return string |
||
| 1175 | * @since 1.23 |
||
| 1176 | */ |
||
| 1177 | View Code Duplication | public static function revisionday( $parser, $title = null ) { |
|
| 1186 | |||
| 1187 | /** |
||
| 1188 | * Get the day with leading zeros from the last revision of a specified page. |
||
| 1189 | * @param Parser $parser |
||
| 1190 | * @param string $title Title to get the day from |
||
| 1191 | * @return string |
||
| 1192 | * @since 1.23 |
||
| 1193 | */ |
||
| 1194 | View Code Duplication | public static function revisionday2( $parser, $title = null ) { |
|
| 1203 | |||
| 1204 | /** |
||
| 1205 | * Get the month with leading zeros from the last revision of a specified page. |
||
| 1206 | * @param Parser $parser |
||
| 1207 | * @param string $title Title to get the month from |
||
| 1208 | * @return string |
||
| 1209 | * @since 1.23 |
||
| 1210 | */ |
||
| 1211 | View Code Duplication | public static function revisionmonth( $parser, $title = null ) { |
|
| 1220 | |||
| 1221 | /** |
||
| 1222 | * Get the month from the last revision of a specified page. |
||
| 1223 | * @param Parser $parser |
||
| 1224 | * @param string $title Title to get the month from |
||
| 1225 | * @return string |
||
| 1226 | * @since 1.23 |
||
| 1227 | */ |
||
| 1228 | View Code Duplication | public static function revisionmonth1( $parser, $title = null ) { |
|
| 1237 | |||
| 1238 | /** |
||
| 1239 | * Get the year from the last revision of a specified page. |
||
| 1240 | * @param Parser $parser |
||
| 1241 | * @param string $title Title to get the year from |
||
| 1242 | * @return string |
||
| 1243 | * @since 1.23 |
||
| 1244 | */ |
||
| 1245 | View Code Duplication | public static function revisionyear( $parser, $title = null ) { |
|
| 1254 | |||
| 1255 | /** |
||
| 1256 | * Get the timestamp from the last revision of a specified page. |
||
| 1257 | * @param Parser $parser |
||
| 1258 | * @param string $title Title to get the timestamp from |
||
| 1259 | * @return string |
||
| 1260 | * @since 1.23 |
||
| 1261 | */ |
||
| 1262 | View Code Duplication | public static function revisiontimestamp( $parser, $title = null ) { |
|
| 1271 | |||
| 1272 | /** |
||
| 1273 | * Get the user from the last revision of a specified page. |
||
| 1274 | * @param Parser $parser |
||
| 1275 | * @param string $title Title to get the user from |
||
| 1276 | * @return string |
||
| 1277 | * @since 1.23 |
||
| 1278 | */ |
||
| 1279 | View Code Duplication | public static function revisionuser( $parser, $title = null ) { |
|
| 1288 | |||
| 1289 | /** |
||
| 1290 | * Returns the sources of any cascading protection acting on a specified page. |
||
| 1291 | * Pages will not return their own title unless they transclude themselves. |
||
| 1292 | * This is an expensive parser function and can't be called too many times per page, |
||
| 1293 | * unless cascading protection sources for the page have already been loaded. |
||
| 1294 | * |
||
| 1295 | * @param Parser $parser |
||
| 1296 | * @param string $title |
||
| 1297 | * |
||
| 1298 | * @return string |
||
| 1299 | * @since 1.23 |
||
| 1300 | */ |
||
| 1301 | public static function cascadingsources( $parser, $title = '' ) { |
||
| 1318 | |||
| 1319 | } |
||
| 1320 |
In PHP, under loose comparison (like
==, or!=, orswitchconditions), values of different types might be equal.For
stringvalues, the empty string''is a special case, in particular the following results might be unexpected: