PageRenderTime 58ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/includes/parser/CoreParserFunctions.php

https://bitbucket.org/kgrashad/thawrapedia
PHP | 675 lines | 512 code | 65 blank | 98 comment | 94 complexity | 92534d8b9acb28000922780cad1bdd29 MD5 | raw file
Possible License(s): GPL-2.0, Apache-2.0, LGPL-3.0
  1. <?php
  2. /**
  3. * Parser functions provided by MediaWiki core
  4. *
  5. * @file
  6. */
  7. /**
  8. * Various core parser functions, registered in Parser::firstCallInit()
  9. * @ingroup Parser
  10. */
  11. class CoreParserFunctions {
  12. static function register( $parser ) {
  13. global $wgAllowDisplayTitle, $wgAllowSlowParserFunctions;
  14. # Syntax for arguments (see self::setFunctionHook):
  15. # "name for lookup in localized magic words array",
  16. # function callback,
  17. # optional SFH_NO_HASH to omit the hash from calls (e.g. {{int:...}}
  18. # instead of {{#int:...}})
  19. $parser->setFunctionHook( 'int', array( __CLASS__, 'intFunction' ), SFH_NO_HASH );
  20. $parser->setFunctionHook( 'ns', array( __CLASS__, 'ns' ), SFH_NO_HASH );
  21. $parser->setFunctionHook( 'nse', array( __CLASS__, 'nse' ), SFH_NO_HASH );
  22. $parser->setFunctionHook( 'urlencode', array( __CLASS__, 'urlencode' ), SFH_NO_HASH );
  23. $parser->setFunctionHook( 'lcfirst', array( __CLASS__, 'lcfirst' ), SFH_NO_HASH );
  24. $parser->setFunctionHook( 'ucfirst', array( __CLASS__, 'ucfirst' ), SFH_NO_HASH );
  25. $parser->setFunctionHook( 'lc', array( __CLASS__, 'lc' ), SFH_NO_HASH );
  26. $parser->setFunctionHook( 'uc', array( __CLASS__, 'uc' ), SFH_NO_HASH );
  27. $parser->setFunctionHook( 'localurl', array( __CLASS__, 'localurl' ), SFH_NO_HASH );
  28. $parser->setFunctionHook( 'localurle', array( __CLASS__, 'localurle' ), SFH_NO_HASH );
  29. $parser->setFunctionHook( 'fullurl', array( __CLASS__, 'fullurl' ), SFH_NO_HASH );
  30. $parser->setFunctionHook( 'fullurle', array( __CLASS__, 'fullurle' ), SFH_NO_HASH );
  31. $parser->setFunctionHook( 'formatnum', array( __CLASS__, 'formatnum' ), SFH_NO_HASH );
  32. $parser->setFunctionHook( 'grammar', array( __CLASS__, 'grammar' ), SFH_NO_HASH );
  33. $parser->setFunctionHook( 'gender', array( __CLASS__, 'gender' ), SFH_NO_HASH );
  34. $parser->setFunctionHook( 'plural', array( __CLASS__, 'plural' ), SFH_NO_HASH );
  35. $parser->setFunctionHook( 'numberofpages', array( __CLASS__, 'numberofpages' ), SFH_NO_HASH );
  36. $parser->setFunctionHook( 'numberofusers', array( __CLASS__, 'numberofusers' ), SFH_NO_HASH );
  37. $parser->setFunctionHook( 'numberofactiveusers', array( __CLASS__, 'numberofactiveusers' ), SFH_NO_HASH );
  38. $parser->setFunctionHook( 'numberofarticles', array( __CLASS__, 'numberofarticles' ), SFH_NO_HASH );
  39. $parser->setFunctionHook( 'numberoffiles', array( __CLASS__, 'numberoffiles' ), SFH_NO_HASH );
  40. $parser->setFunctionHook( 'numberofadmins', array( __CLASS__, 'numberofadmins' ), SFH_NO_HASH );
  41. $parser->setFunctionHook( 'numberingroup', array( __CLASS__, 'numberingroup' ), SFH_NO_HASH );
  42. $parser->setFunctionHook( 'numberofedits', array( __CLASS__, 'numberofedits' ), SFH_NO_HASH );
  43. $parser->setFunctionHook( 'numberofviews', array( __CLASS__, 'numberofviews' ), SFH_NO_HASH );
  44. $parser->setFunctionHook( 'language', array( __CLASS__, 'language' ), SFH_NO_HASH );
  45. $parser->setFunctionHook( 'padleft', array( __CLASS__, 'padleft' ), SFH_NO_HASH );
  46. $parser->setFunctionHook( 'padright', array( __CLASS__, 'padright' ), SFH_NO_HASH );
  47. $parser->setFunctionHook( 'anchorencode', array( __CLASS__, 'anchorencode' ), SFH_NO_HASH );
  48. $parser->setFunctionHook( 'special', array( __CLASS__, 'special' ) );
  49. $parser->setFunctionHook( 'defaultsort', array( __CLASS__, 'defaultsort' ), SFH_NO_HASH );
  50. $parser->setFunctionHook( 'filepath', array( __CLASS__, 'filepath' ), SFH_NO_HASH );
  51. $parser->setFunctionHook( 'pagesincategory', array( __CLASS__, 'pagesincategory' ), SFH_NO_HASH );
  52. $parser->setFunctionHook( 'pagesize', array( __CLASS__, 'pagesize' ), SFH_NO_HASH );
  53. $parser->setFunctionHook( 'protectionlevel', array( __CLASS__, 'protectionlevel' ), SFH_NO_HASH );
  54. $parser->setFunctionHook( 'namespace', array( __CLASS__, 'mwnamespace' ), SFH_NO_HASH );
  55. $parser->setFunctionHook( 'namespacee', array( __CLASS__, 'namespacee' ), SFH_NO_HASH );
  56. $parser->setFunctionHook( 'talkspace', array( __CLASS__, 'talkspace' ), SFH_NO_HASH );
  57. $parser->setFunctionHook( 'talkspacee', array( __CLASS__, 'talkspacee' ), SFH_NO_HASH );
  58. $parser->setFunctionHook( 'subjectspace', array( __CLASS__, 'subjectspace' ), SFH_NO_HASH );
  59. $parser->setFunctionHook( 'subjectspacee', array( __CLASS__, 'subjectspacee' ), SFH_NO_HASH );
  60. $parser->setFunctionHook( 'pagename', array( __CLASS__, 'pagename' ), SFH_NO_HASH );
  61. $parser->setFunctionHook( 'pagenamee', array( __CLASS__, 'pagenamee' ), SFH_NO_HASH );
  62. $parser->setFunctionHook( 'fullpagename', array( __CLASS__, 'fullpagename' ), SFH_NO_HASH );
  63. $parser->setFunctionHook( 'fullpagenamee', array( __CLASS__, 'fullpagenamee' ), SFH_NO_HASH );
  64. $parser->setFunctionHook( 'basepagename', array( __CLASS__, 'basepagename' ), SFH_NO_HASH );
  65. $parser->setFunctionHook( 'basepagenamee', array( __CLASS__, 'basepagenamee' ), SFH_NO_HASH );
  66. $parser->setFunctionHook( 'subpagename', array( __CLASS__, 'subpagename' ), SFH_NO_HASH );
  67. $parser->setFunctionHook( 'subpagenamee', array( __CLASS__, 'subpagenamee' ), SFH_NO_HASH );
  68. $parser->setFunctionHook( 'talkpagename', array( __CLASS__, 'talkpagename' ), SFH_NO_HASH );
  69. $parser->setFunctionHook( 'talkpagenamee', array( __CLASS__, 'talkpagenamee' ), SFH_NO_HASH );
  70. $parser->setFunctionHook( 'subjectpagename', array( __CLASS__, 'subjectpagename' ), SFH_NO_HASH );
  71. $parser->setFunctionHook( 'subjectpagenamee', array( __CLASS__, 'subjectpagenamee' ), SFH_NO_HASH );
  72. $parser->setFunctionHook( 'tag', array( __CLASS__, 'tagObj' ), SFH_OBJECT_ARGS );
  73. $parser->setFunctionHook( 'formatdate', array( __CLASS__, 'formatDate' ) );
  74. if ( $wgAllowDisplayTitle ) {
  75. $parser->setFunctionHook( 'displaytitle', array( __CLASS__, 'displaytitle' ), SFH_NO_HASH );
  76. }
  77. if ( $wgAllowSlowParserFunctions ) {
  78. $parser->setFunctionHook( 'pagesinnamespace', array( __CLASS__, 'pagesinnamespace' ), SFH_NO_HASH );
  79. }
  80. }
  81. static function intFunction( $parser, $part1 = '' /*, ... */ ) {
  82. if ( strval( $part1 ) !== '' ) {
  83. $args = array_slice( func_get_args(), 2 );
  84. $message = wfMsgGetKey( $part1, true, $parser->getOptions()->getUserLang(), false );
  85. $message = wfMsgReplaceArgs( $message, $args );
  86. $message = $parser->replaceVariables( $message ); // like $wgMessageCache->transform()
  87. return $message;
  88. } else {
  89. return array( 'found' => false );
  90. }
  91. }
  92. static function formatDate( $parser, $date, $defaultPref = null ) {
  93. $df = DateFormatter::getInstance();
  94. $date = trim( $date );
  95. $pref = $parser->getOptions()->getDateFormat();
  96. // Specify a different default date format other than the the normal default
  97. // iff the user has 'default' for their setting
  98. if ( $pref == 'default' && $defaultPref )
  99. $pref = $defaultPref;
  100. $date = $df->reformat( $pref, $date, array( 'match-whole' ) );
  101. return $date;
  102. }
  103. static function ns( $parser, $part1 = '' ) {
  104. global $wgContLang;
  105. if ( intval( $part1 ) || $part1 == "0" ) {
  106. $index = intval( $part1 );
  107. } else {
  108. $index = $wgContLang->getNsIndex( str_replace( ' ', '_', $part1 ) );
  109. }
  110. if ( $index !== false ) {
  111. return $wgContLang->getFormattedNsText( $index );
  112. } else {
  113. return array( 'found' => false );
  114. }
  115. }
  116. static function nse( $parser, $part1 = '' ) {
  117. return wfUrlencode( str_replace( ' ', '_', self::ns( $parser, $part1 ) ) );
  118. }
  119. /**
  120. * urlencodes a string according to one of three patterns: (bug 22474)
  121. *
  122. * By default (for HTTP "query" strings), spaces are encoded as '+'.
  123. * Or to encode a value for the HTTP "path", spaces are encoded as '%20'.
  124. * For links to "wiki"s, or similar software, spaces are encoded as '_',
  125. *
  126. * @param $parser Parser object
  127. * @param $s String: The text to encode.
  128. * @param $arg String (optional): The type of encoding.
  129. */
  130. static function urlencode( $parser, $s = '', $arg = null ) {
  131. static $magicWords = null;
  132. if ( is_null( $magicWords ) ) {
  133. $magicWords = new MagicWordArray( array( 'url_path', 'url_query', 'url_wiki' ) );
  134. }
  135. switch( $magicWords->matchStartToEnd( $arg ) ) {
  136. // Encode as though it's a wiki page, '_' for ' '.
  137. case 'url_wiki':
  138. return wfUrlencode( str_replace( ' ', '_', $s ) );
  139. // Encode for an HTTP Path, '%20' for ' '.
  140. case 'url_path':
  141. return rawurlencode( $s );
  142. // Encode for HTTP query, '+' for ' '.
  143. case 'url_query':
  144. default:
  145. return urlencode( $s );
  146. }
  147. }
  148. static function lcfirst( $parser, $s = '' ) {
  149. global $wgContLang;
  150. return $wgContLang->lcfirst( $s );
  151. }
  152. static function ucfirst( $parser, $s = '' ) {
  153. global $wgContLang;
  154. return $wgContLang->ucfirst( $s );
  155. }
  156. static function lc( $parser, $s = '' ) {
  157. global $wgContLang;
  158. if ( is_callable( array( $parser, 'markerSkipCallback' ) ) ) {
  159. return $parser->markerSkipCallback( $s, array( $wgContLang, 'lc' ) );
  160. } else {
  161. return $wgContLang->lc( $s );
  162. }
  163. }
  164. static function uc( $parser, $s = '' ) {
  165. global $wgContLang;
  166. if ( is_callable( array( $parser, 'markerSkipCallback' ) ) ) {
  167. return $parser->markerSkipCallback( $s, array( $wgContLang, 'uc' ) );
  168. } else {
  169. return $wgContLang->uc( $s );
  170. }
  171. }
  172. static function localurl( $parser, $s = '', $arg = null ) { return self::urlFunction( 'getLocalURL', $s, $arg ); }
  173. static function localurle( $parser, $s = '', $arg = null ) { return self::urlFunction( 'escapeLocalURL', $s, $arg ); }
  174. static function fullurl( $parser, $s = '', $arg = null ) { return self::urlFunction( 'getFullURL', $s, $arg ); }
  175. static function fullurle( $parser, $s = '', $arg = null ) { return self::urlFunction( 'escapeFullURL', $s, $arg ); }
  176. static function urlFunction( $func, $s = '', $arg = null ) {
  177. $title = Title::newFromText( $s );
  178. # Due to order of execution of a lot of bits, the values might be encoded
  179. # before arriving here; if that's true, then the title can't be created
  180. # and the variable will fail. If we can't get a decent title from the first
  181. # attempt, url-decode and try for a second.
  182. if( is_null( $title ) )
  183. $title = Title::newFromURL( urldecode( $s ) );
  184. if( !is_null( $title ) ) {
  185. # Convert NS_MEDIA -> NS_FILE
  186. if( $title->getNamespace() == NS_MEDIA ) {
  187. $title = Title::makeTitle( NS_FILE, $title->getDBkey() );
  188. }
  189. if( !is_null( $arg ) ) {
  190. $text = $title->$func( $arg );
  191. } else {
  192. $text = $title->$func();
  193. }
  194. return $text;
  195. } else {
  196. return array( 'found' => false );
  197. }
  198. }
  199. static function formatNum( $parser, $num = '', $raw = null) {
  200. if ( self::israw( $raw ) ) {
  201. return $parser->getFunctionLang()->parseFormattedNumber( $num );
  202. } else {
  203. return $parser->getFunctionLang()->formatNum( $num );
  204. }
  205. }
  206. static function grammar( $parser, $case = '', $word = '' ) {
  207. return $parser->getFunctionLang()->convertGrammar( $word, $case );
  208. }
  209. static function gender( $parser, $user ) {
  210. wfProfileIn( __METHOD__ );
  211. $forms = array_slice( func_get_args(), 2);
  212. // default
  213. $gender = User::getDefaultOption( 'gender' );
  214. // allow prefix.
  215. $title = Title::newFromText( $user );
  216. if ( is_object( $title ) && $title->getNamespace() == NS_USER )
  217. $user = $title->getText();
  218. // check parameter, or use $wgUser if in interface message
  219. $user = User::newFromName( $user );
  220. if ( $user ) {
  221. $gender = $user->getOption( 'gender' );
  222. } elseif ( $parser->getOptions()->getInterfaceMessage() ) {
  223. global $wgUser;
  224. $gender = $wgUser->getOption( 'gender' );
  225. }
  226. $ret = $parser->getFunctionLang()->gender( $gender, $forms );
  227. wfProfileOut( __METHOD__ );
  228. return $ret;
  229. }
  230. static function plural( $parser, $text = '' ) {
  231. $forms = array_slice( func_get_args(), 2 );
  232. $text = $parser->getFunctionLang()->parseFormattedNumber( $text );
  233. return $parser->getFunctionLang()->convertPlural( $text, $forms );
  234. }
  235. /**
  236. * Override the title of the page when viewed, provided we've been given a
  237. * title which will normalise to the canonical title
  238. *
  239. * @param $parser Parser: parent parser
  240. * @param $text String: desired title text
  241. * @return String
  242. */
  243. static function displaytitle( $parser, $text = '' ) {
  244. global $wgRestrictDisplayTitle;
  245. #parse a limited subset of wiki markup (just the single quote items)
  246. $text = $parser->doQuotes( $text );
  247. #remove stripped text (e.g. the UNIQ-QINU stuff) that was generated by tag extensions/whatever
  248. $text = preg_replace( '/' . preg_quote( $parser->uniqPrefix(), '/' ) . '.*?'
  249. . preg_quote( Parser::MARKER_SUFFIX, '/' ) . '/', '', $text );
  250. #list of disallowed tags for DISPLAYTITLE
  251. #these will be escaped even though they are allowed in normal wiki text
  252. $bad = array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'blockquote', 'ol', 'ul', 'li', 'hr',
  253. 'table', 'tr', 'th', 'td', 'dl', 'dd', 'caption', 'p', 'ruby', 'rb', 'rt', 'rp', 'br' );
  254. #only requested titles that normalize to the actual title are allowed through
  255. #if $wgRestrictDisplayTitle is true (it is by default)
  256. #mimic the escaping process that occurs in OutputPage::setPageTitle
  257. $text = Sanitizer::normalizeCharReferences( Sanitizer::removeHTMLtags( $text, null, array(), array(), $bad ) );
  258. $title = Title::newFromText( Sanitizer::stripAllTags( $text ) );
  259. if( !$wgRestrictDisplayTitle ) {
  260. $parser->mOutput->setDisplayTitle( $text );
  261. } else {
  262. if ( $title instanceof Title && $title->getFragment() == '' && $title->equals( $parser->mTitle ) ) {
  263. $parser->mOutput->setDisplayTitle( $text );
  264. }
  265. }
  266. return '';
  267. }
  268. static function isRaw( $param ) {
  269. static $mwRaw;
  270. if ( !$mwRaw ) {
  271. $mwRaw =& MagicWord::get( 'rawsuffix' );
  272. }
  273. if ( is_null( $param ) ) {
  274. return false;
  275. } else {
  276. return $mwRaw->match( $param );
  277. }
  278. }
  279. static function formatRaw( $num, $raw ) {
  280. if( self::isRaw( $raw ) ) {
  281. return $num;
  282. } else {
  283. global $wgContLang;
  284. return $wgContLang->formatNum( $num );
  285. }
  286. }
  287. static function numberofpages( $parser, $raw = null ) {
  288. return self::formatRaw( SiteStats::pages(), $raw );
  289. }
  290. static function numberofusers( $parser, $raw = null ) {
  291. return self::formatRaw( SiteStats::users(), $raw );
  292. }
  293. static function numberofactiveusers( $parser, $raw = null ) {
  294. return self::formatRaw( SiteStats::activeUsers(), $raw );
  295. }
  296. static function numberofarticles( $parser, $raw = null ) {
  297. return self::formatRaw( SiteStats::articles(), $raw );
  298. }
  299. static function numberoffiles( $parser, $raw = null ) {
  300. return self::formatRaw( SiteStats::images(), $raw );
  301. }
  302. static function numberofadmins( $parser, $raw = null ) {
  303. return self::formatRaw( SiteStats::numberingroup('sysop'), $raw );
  304. }
  305. static function numberofedits( $parser, $raw = null ) {
  306. return self::formatRaw( SiteStats::edits(), $raw );
  307. }
  308. static function numberofviews( $parser, $raw = null ) {
  309. return self::formatRaw( SiteStats::views(), $raw );
  310. }
  311. static function pagesinnamespace( $parser, $namespace = 0, $raw = null ) {
  312. return self::formatRaw( SiteStats::pagesInNs( intval( $namespace ) ), $raw );
  313. }
  314. static function numberingroup( $parser, $name = '', $raw = null) {
  315. return self::formatRaw( SiteStats::numberingroup( strtolower( $name ) ), $raw );
  316. }
  317. /**
  318. * Given a title, return the namespace name that would be given by the
  319. * corresponding magic word
  320. * Note: function name changed to "mwnamespace" rather than "namespace"
  321. * to not break PHP 5.3
  322. */
  323. static function mwnamespace( $parser, $title = null ) {
  324. $t = Title::newFromText( $title );
  325. if ( is_null( $t ) )
  326. return '';
  327. return str_replace( '_', ' ', $t->getNsText() );
  328. }
  329. static function namespacee( $parser, $title = null ) {
  330. $t = Title::newFromText( $title );
  331. if ( is_null( $t ) )
  332. return '';
  333. return wfUrlencode( $t->getNsText() );
  334. }
  335. static function talkspace( $parser, $title = null ) {
  336. $t = Title::newFromText( $title );
  337. if ( is_null( $t ) || !$t->canTalk() )
  338. return '';
  339. return str_replace( '_', ' ', $t->getTalkNsText() );
  340. }
  341. static function talkspacee( $parser, $title = null ) {
  342. $t = Title::newFromText( $title );
  343. if ( is_null( $t ) || !$t->canTalk() )
  344. return '';
  345. return wfUrlencode( $t->getTalkNsText() );
  346. }
  347. static function subjectspace( $parser, $title = null ) {
  348. $t = Title::newFromText( $title );
  349. if ( is_null( $t ) )
  350. return '';
  351. return str_replace( '_', ' ', $t->getSubjectNsText() );
  352. }
  353. static function subjectspacee( $parser, $title = null ) {
  354. $t = Title::newFromText( $title );
  355. if ( is_null( $t ) )
  356. return '';
  357. return wfUrlencode( $t->getSubjectNsText() );
  358. }
  359. /*
  360. * Functions to get and normalize pagenames, corresponding to the magic words
  361. * of the same names
  362. */
  363. static function pagename( $parser, $title = null ) {
  364. $t = Title::newFromText( $title );
  365. if ( is_null( $t ) )
  366. return '';
  367. return wfEscapeWikiText( $t->getText() );
  368. }
  369. static function pagenamee( $parser, $title = null ) {
  370. $t = Title::newFromText( $title );
  371. if ( is_null( $t ) )
  372. return '';
  373. return $t->getPartialURL();
  374. }
  375. static function fullpagename( $parser, $title = null ) {
  376. $t = Title::newFromText( $title );
  377. if ( is_null( $t ) || !$t->canTalk() )
  378. return '';
  379. return wfEscapeWikiText( $t->getPrefixedText() );
  380. }
  381. static function fullpagenamee( $parser, $title = null ) {
  382. $t = Title::newFromText( $title );
  383. if ( is_null( $t ) || !$t->canTalk() )
  384. return '';
  385. return $t->getPrefixedURL();
  386. }
  387. static function subpagename( $parser, $title = null ) {
  388. $t = Title::newFromText( $title );
  389. if ( is_null( $t ) )
  390. return '';
  391. return $t->getSubpageText();
  392. }
  393. static function subpagenamee( $parser, $title = null ) {
  394. $t = Title::newFromText( $title );
  395. if ( is_null( $t ) )
  396. return '';
  397. return $t->getSubpageUrlForm();
  398. }
  399. static function basepagename( $parser, $title = null ) {
  400. $t = Title::newFromText( $title );
  401. if ( is_null( $t ) )
  402. return '';
  403. return $t->getBaseText();
  404. }
  405. static function basepagenamee( $parser, $title = null ) {
  406. $t = Title::newFromText( $title );
  407. if ( is_null( $t ) )
  408. return '';
  409. return wfUrlEncode( str_replace( ' ', '_', $t->getBaseText() ) );
  410. }
  411. static function talkpagename( $parser, $title = null ) {
  412. $t = Title::newFromText( $title );
  413. if ( is_null( $t ) || !$t->canTalk() )
  414. return '';
  415. return wfEscapeWikiText( $t->getTalkPage()->getPrefixedText() );
  416. }
  417. static function talkpagenamee( $parser, $title = null ) {
  418. $t = Title::newFromText( $title );
  419. if ( is_null( $t ) || !$t->canTalk() )
  420. return '';
  421. return $t->getTalkPage()->getPrefixedUrl();
  422. }
  423. static function subjectpagename( $parser, $title = null ) {
  424. $t = Title::newFromText( $title );
  425. if ( is_null( $t ) )
  426. return '';
  427. return wfEscapeWikiText( $t->getSubjectPage()->getPrefixedText() );
  428. }
  429. static function subjectpagenamee( $parser, $title = null ) {
  430. $t = Title::newFromText( $title );
  431. if ( is_null( $t ) )
  432. return '';
  433. return $t->getSubjectPage()->getPrefixedUrl();
  434. }
  435. /**
  436. * Return the number of pages in the given category, or 0 if it's nonexis-
  437. * tent. This is an expensive parser function and can't be called too many
  438. * times per page.
  439. */
  440. static function pagesincategory( $parser, $name = '', $raw = null ) {
  441. static $cache = array();
  442. $category = Category::newFromName( $name );
  443. if( !is_object( $category ) ) {
  444. $cache[$name] = 0;
  445. return self::formatRaw( 0, $raw );
  446. }
  447. # Normalize name for cache
  448. $name = $category->getName();
  449. $count = 0;
  450. if( isset( $cache[$name] ) ) {
  451. $count = $cache[$name];
  452. } elseif( $parser->incrementExpensiveFunctionCount() ) {
  453. $count = $cache[$name] = (int)$category->getPageCount();
  454. }
  455. return self::formatRaw( $count, $raw );
  456. }
  457. /**
  458. * Return the size of the given page, or 0 if it's nonexistent. This is an
  459. * expensive parser function and can't be called too many times per page.
  460. *
  461. * @todo Fixme: This doesn't work correctly on preview for getting the size
  462. * of the current page.
  463. * @todo Fixme: Title::getLength() documentation claims that it adds things
  464. * to the link cache, so the local cache here should be unnecessary, but
  465. * in fact calling getLength() repeatedly for the same $page does seem to
  466. * run one query for each call?
  467. */
  468. static function pagesize( $parser, $page = '', $raw = null ) {
  469. static $cache = array();
  470. $title = Title::newFromText( $page );
  471. if( !is_object( $title ) ) {
  472. $cache[$page] = 0;
  473. return self::formatRaw( 0, $raw );
  474. }
  475. # Normalize name for cache
  476. $page = $title->getPrefixedText();
  477. $length = 0;
  478. if( isset( $cache[$page] ) ) {
  479. $length = $cache[$page];
  480. } elseif( $parser->incrementExpensiveFunctionCount() ) {
  481. $rev = Revision::newFromTitle( $title );
  482. $id = $rev ? $rev->getPage() : 0;
  483. $length = $cache[$page] = $rev ? $rev->getSize() : 0;
  484. // Register dependency in templatelinks
  485. $parser->mOutput->addTemplate( $title, $id, $rev ? $rev->getId() : 0 );
  486. }
  487. return self::formatRaw( $length, $raw );
  488. }
  489. /**
  490. * Returns the requested protection level for the current page
  491. */
  492. static function protectionlevel( $parser, $type = '' ) {
  493. $restrictions = $parser->mTitle->getRestrictions( strtolower( $type ) );
  494. # Title::getRestrictions returns an array, its possible it may have
  495. # multiple values in the future
  496. return implode( $restrictions, ',' );
  497. }
  498. static function language( $parser, $arg = '' ) {
  499. global $wgContLang;
  500. $lang = $wgContLang->getLanguageName( strtolower( $arg ) );
  501. return $lang != '' ? $lang : $arg;
  502. }
  503. /**
  504. * Unicode-safe str_pad with the restriction that $length is forced to be <= 500
  505. */
  506. static function pad( $string, $length, $padding = '0', $direction = STR_PAD_RIGHT ) {
  507. $lengthOfPadding = mb_strlen( $padding );
  508. if ( $lengthOfPadding == 0 ) return $string;
  509. # The remaining length to add counts down to 0 as padding is added
  510. $length = min( $length, 500 ) - mb_strlen( $string );
  511. # $finalPadding is just $padding repeated enough times so that
  512. # mb_strlen( $string ) + mb_strlen( $finalPadding ) == $length
  513. $finalPadding = '';
  514. while ( $length > 0 ) {
  515. # If $length < $lengthofPadding, truncate $padding so we get the
  516. # exact length desired.
  517. $finalPadding .= mb_substr( $padding, 0, $length );
  518. $length -= $lengthOfPadding;
  519. }
  520. if ( $direction == STR_PAD_LEFT ) {
  521. return $finalPadding . $string;
  522. } else {
  523. return $string . $finalPadding;
  524. }
  525. }
  526. static function padleft( $parser, $string = '', $length = 0, $padding = '0' ) {
  527. return self::pad( $string, $length, $padding, STR_PAD_LEFT );
  528. }
  529. static function padright( $parser, $string = '', $length = 0, $padding = '0' ) {
  530. return self::pad( $string, $length, $padding );
  531. }
  532. static function anchorencode( $parser, $text ) {
  533. return substr( $parser->guessSectionNameFromWikiText( $text ), 1);
  534. }
  535. static function special( $parser, $text ) {
  536. list( $page, $subpage ) = SpecialPage::resolveAliasWithSubpage( $text );
  537. if ( $page ) {
  538. $title = SpecialPage::getTitleFor( $page, $subpage );
  539. return $title;
  540. } else {
  541. return wfMsgForContent( 'nosuchspecialpage' );
  542. }
  543. }
  544. public static function defaultsort( $parser, $text ) {
  545. $text = trim( $text );
  546. if( strlen( $text ) == 0 )
  547. return '';
  548. $old = $parser->getCustomDefaultSort();
  549. $parser->setDefaultSort( $text );
  550. if( $old === false || $old == $text )
  551. return '';
  552. else
  553. return( '<span class="error">' .
  554. wfMsgForContent( 'duplicate-defaultsort',
  555. htmlspecialchars( $old ),
  556. htmlspecialchars( $text ) ) .
  557. '</span>' );
  558. }
  559. public static function filepath( $parser, $name='', $option='' ) {
  560. $file = wfFindFile( $name );
  561. if( $file ) {
  562. $url = $file->getFullUrl();
  563. if( $option == 'nowiki' ) {
  564. return array( $url, 'nowiki' => true );
  565. }
  566. return $url;
  567. } else {
  568. return '';
  569. }
  570. }
  571. /**
  572. * Parser function to extension tag adaptor
  573. */
  574. public static function tagObj( $parser, $frame, $args ) {
  575. if ( !count( $args ) ) {
  576. return '';
  577. }
  578. $tagName = strtolower( trim( $frame->expand( array_shift( $args ) ) ) );
  579. if ( count( $args ) ) {
  580. $inner = $frame->expand( array_shift( $args ) );
  581. } else {
  582. $inner = null;
  583. }
  584. $stripList = $parser->getStripList();
  585. if ( !in_array( $tagName, $stripList ) ) {
  586. return '<span class="error">' .
  587. wfMsgForContent( 'unknown_extension_tag', $tagName ) .
  588. '</span>';
  589. }
  590. $attributes = array();
  591. foreach ( $args as $arg ) {
  592. $bits = $arg->splitArg();
  593. if ( strval( $bits['index'] ) === '' ) {
  594. $name = trim( $frame->expand( $bits['name'], PPFrame::STRIP_COMMENTS ) );
  595. $value = trim( $frame->expand( $bits['value'] ) );
  596. if ( preg_match( '/^(?:["\'](.+)["\']|""|\'\')$/s', $value, $m ) ) {
  597. $value = isset( $m[1] ) ? $m[1] : '';
  598. }
  599. $attributes[$name] = $value;
  600. }
  601. }
  602. $params = array(
  603. 'name' => $tagName,
  604. 'inner' => $inner,
  605. 'attributes' => $attributes,
  606. 'close' => "</$tagName>",
  607. );
  608. return $parser->extensionSubstitution( $params, $frame );
  609. }
  610. }