PageRenderTime 60ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/mediawiki-integration/source/php/mediawiki/skins/disabled/MonoBookCBT.php

https://code.google.com/
PHP | 1389 lines | 1163 code | 159 blank | 67 comment | 182 complexity | 94415b70fec61dac22ff43e379b5bcb6 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-3.0
  1. <?php
  2. if ( !defined( 'MEDIAWIKI' ) ) {
  3. die( "This file is part of MediaWiki, it is not a valid entry point\n" );
  4. }
  5. require_once( 'includes/cbt/CBTProcessor.php' );
  6. require_once( 'includes/cbt/CBTCompiler.php' );
  7. require_once( 'includes/SkinTemplate.php' );
  8. /**
  9. * MonoBook clone using the new dependency-tracking template processor.
  10. * EXPERIMENTAL - use only for testing and profiling at this stage.
  11. *
  12. * See includes/cbt/README for an explanation.
  13. *
  14. * The main thing that's missing is cache invalidation, on change of:
  15. * * messages
  16. * * user preferences
  17. * * source template
  18. * * source code and configuration files
  19. *
  20. * The other thing is that lots of dependencies that are declared in the callbacks
  21. * are not intelligently handled. There's some room for improvement there.
  22. *
  23. * The class is derived from SkinTemplate, but that's only temporary. Eventually
  24. * it'll be derived from Skin, and I've avoided using SkinTemplate functions as
  25. * much as possible. In fact, the only SkinTemplate dependencies I know of at the
  26. * moment are the functions to generate the gen=css and gen=js files.
  27. *
  28. */
  29. class SkinMonoBookCBT extends SkinTemplate {
  30. var $mOut, $mTitle;
  31. var $mStyleName = 'monobook';
  32. var $mCompiling = false;
  33. var $mFunctionCache = array();
  34. /******************************************************
  35. * General functions *
  36. ******************************************************/
  37. /** Execute the template and write out the result */
  38. function outputPage( &$out ) {
  39. echo $this->execute( $out );
  40. }
  41. function execute( &$out ) {
  42. global $wgTitle, $wgStyleDirectory, $wgParserCacheType;
  43. $fname = 'SkinMonoBookCBT::execute';
  44. wfProfileIn( $fname );
  45. wfProfileIn( "$fname-setup" );
  46. Skin::initPage( $out );
  47. $this->mOut =& $out;
  48. $this->mTitle =& $wgTitle;
  49. $sourceFile = "$wgStyleDirectory/MonoBook.tpl";
  50. wfProfileOut( "$fname-setup" );
  51. if ( $wgParserCacheType == CACHE_NONE ) {
  52. $template = file_get_contents( $sourceFile );
  53. $text = $this->executeTemplate( $template );
  54. } else {
  55. $compiled = $this->getCompiledTemplate( $sourceFile );
  56. wfProfileIn( "$fname-eval" );
  57. $text = eval( $compiled );
  58. wfProfileOut( "$fname-eval" );
  59. }
  60. wfProfileOut( $fname );
  61. return $text;
  62. }
  63. function getCompiledTemplate( $sourceFile ) {
  64. global $wgDBname, $wgMemc, $wgRequest, $wgUser, $parserMemc;
  65. $fname = 'SkinMonoBookCBT::getCompiledTemplate';
  66. $expiry = 3600;
  67. // Sandbox template execution
  68. if ( $this->mCompiling ) {
  69. return;
  70. }
  71. wfProfileIn( $fname );
  72. // Is the request an ordinary page view?
  73. if ( $wgRequest->wasPosted() ||
  74. count( array_diff( array_keys( $_GET ), array( 'title', 'useskin', 'recompile' ) ) ) != 0 )
  75. {
  76. $type = 'nonview';
  77. } else {
  78. $type = 'view';
  79. }
  80. // Per-user compiled template
  81. // Put all logged-out users on the same cache key
  82. $cacheKey = "$wgDBname:monobookcbt:$type:" . $wgUser->getId();
  83. $recompile = $wgRequest->getVal( 'recompile' );
  84. if ( $recompile == 'user' ) {
  85. $recompileUser = true;
  86. $recompileGeneric = false;
  87. } elseif ( $recompile ) {
  88. $recompileUser = true;
  89. $recompileGeneric = true;
  90. } else {
  91. $recompileUser = false;
  92. $recompileGeneric = false;
  93. }
  94. if ( !$recompileUser ) {
  95. $php = $parserMemc->get( $cacheKey );
  96. }
  97. if ( $recompileUser || !$php ) {
  98. if ( $wgUser->isLoggedIn() ) {
  99. // Perform staged compilation
  100. // First compile a generic template for all logged-in users
  101. $genericKey = "$wgDBname:monobookcbt:$type:loggedin";
  102. if ( !$recompileGeneric ) {
  103. $template = $parserMemc->get( $genericKey );
  104. }
  105. if ( $recompileGeneric || !$template ) {
  106. $template = file_get_contents( $sourceFile );
  107. $ignore = array( 'loggedin', '!loggedin dynamic' );
  108. if ( $type == 'view' ) {
  109. $ignore[] = 'nonview dynamic';
  110. }
  111. $template = $this->compileTemplate( $template, $ignore );
  112. $parserMemc->set( $genericKey, $template, $expiry );
  113. }
  114. } else {
  115. $template = file_get_contents( $sourceFile );
  116. }
  117. $ignore = array( 'lang', 'loggedin', 'user' );
  118. if ( $wgUser->isLoggedIn() ) {
  119. $ignore[] = '!loggedin dynamic';
  120. } else {
  121. $ignore[] = 'loggedin dynamic';
  122. }
  123. if ( $type == 'view' ) {
  124. $ignore[] = 'nonview dynamic';
  125. }
  126. $compiled = $this->compileTemplate( $template, $ignore );
  127. // Reduce whitespace
  128. // This is done here instead of in CBTProcessor because we can be
  129. // more sure it is safe here.
  130. $compiled = preg_replace( '/^[ \t]+/m', '', $compiled );
  131. $compiled = preg_replace( '/[\r\n]+/', "\n", $compiled );
  132. // Compile to PHP
  133. $compiler = new CBTCompiler( $compiled );
  134. $ret = $compiler->compile();
  135. if ( $ret !== true ) {
  136. echo $ret;
  137. wfErrorExit();
  138. }
  139. $php = $compiler->generatePHP( '$this' );
  140. $parserMemc->set( $cacheKey, $php, $expiry );
  141. }
  142. wfProfileOut( $fname );
  143. return $php;
  144. }
  145. function compileTemplate( $template, $ignore ) {
  146. $tp = new CBTProcessor( $template, $this, $ignore );
  147. $tp->mFunctionCache = $this->mFunctionCache;
  148. $this->mCompiling = true;
  149. $compiled = $tp->compile();
  150. $this->mCompiling = false;
  151. if ( $tp->getLastError() ) {
  152. // If there was a compile error, don't save the template
  153. // Instead just print the error and exit
  154. echo $compiled;
  155. wfErrorExit();
  156. }
  157. $this->mFunctionCache = $tp->mFunctionCache;
  158. return $compiled;
  159. }
  160. function executeTemplate( $template ) {
  161. $fname = 'SkinMonoBookCBT::executeTemplate';
  162. wfProfileIn( $fname );
  163. $tp = new CBTProcessor( $template, $this );
  164. $tp->mFunctionCache = $this->mFunctionCache;
  165. $this->mCompiling = true;
  166. $text = $tp->execute();
  167. $this->mCompiling = false;
  168. $this->mFunctionCache = $tp->mFunctionCache;
  169. wfProfileOut( $fname );
  170. return $text;
  171. }
  172. /******************************************************
  173. * Callbacks *
  174. ******************************************************/
  175. function lang() { return $GLOBALS['wgContLanguageCode']; }
  176. function dir() {
  177. global $wgContLang;
  178. return $wgContLang->isRTL() ? 'rtl' : 'ltr';
  179. }
  180. function mimetype() { return $GLOBALS['wgMimeType']; }
  181. function charset() { return $GLOBALS['wgOutputEncoding']; }
  182. function headlinks() {
  183. return cbt_value( $this->mOut->getHeadLinks(), 'dynamic' );
  184. }
  185. function headscripts() {
  186. return cbt_value( $this->mOut->getScript(), 'dynamic' );
  187. }
  188. function pagetitle() {
  189. return cbt_value( $this->mOut->getHTMLTitle(), array( 'title', 'lang' ) );
  190. }
  191. function stylepath() { return $GLOBALS['wgStylePath']; }
  192. function stylename() { return $this->mStyleName; }
  193. function notprintable() {
  194. global $wgRequest;
  195. return cbt_value( !$wgRequest->getBool( 'printable' ), 'nonview dynamic' );
  196. }
  197. function jsmimetype() { return $GLOBALS['wgJsMimeType']; }
  198. function jsvarurl() {
  199. global $wgUseSiteJs, $wgUser;
  200. if ( !$wgUseSiteJs ) return '';
  201. if ( $wgUser->isLoggedIn() ) {
  202. $url = self::makeUrl( '-','action=raw&smaxage=0&gen=js' );
  203. } else {
  204. $url = self::makeUrl( '-','action=raw&gen=js' );
  205. }
  206. return cbt_value( $url, 'loggedin' );
  207. }
  208. function pagecss() {
  209. global $wgHooks;
  210. $out = false;
  211. wfRunHooks( 'SkinTemplateSetupPageCss', array( &$out ) );
  212. // Unknown dependencies
  213. return cbt_value( $out, 'dynamic' );
  214. }
  215. function usercss() {
  216. if ( $this->isCssPreview() ) {
  217. global $wgRequest;
  218. $usercss = $this->makeStylesheetCdata( $wgRequest->getText('wpTextbox1') );
  219. } else {
  220. $usercss = $this->makeStylesheetLink( self::makeUrl($this->getUserPageText() .
  221. '/'.$this->mStyleName.'.css', 'action=raw&ctype=text/css' ) );
  222. }
  223. // Dynamic when not an ordinary page view, also depends on the username
  224. return cbt_value( $usercss, array( 'nonview dynamic', 'user' ) );
  225. }
  226. function sitecss() {
  227. global $wgUseSiteCss;
  228. if ( !$wgUseSiteCss ) {
  229. return '';
  230. }
  231. global $wgSquidMaxage, $wgContLang, $wgStylePath;
  232. $query = "action=raw&ctype=text/css&smaxage=$wgSquidMaxage";
  233. $sitecss = '';
  234. if ( $wgContLang->isRTL() ) {
  235. $sitecss .= $this->makeStylesheetLink( $wgStylePath . '/' . $this->mStyleName . '/rtl.css' ) . "\n";
  236. }
  237. $sitecss .= $this->makeStylesheetLink( self::makeNSUrl( 'Common.css', $query, NS_MEDIAWIKI ) ) . "\n";
  238. $sitecss .= $this->makeStylesheetLink( self::makeNSUrl( ucfirst( $this->mStyleName ) . '.css', $query, NS_MEDIAWIKI ) ) . "\n";
  239. // No deps
  240. return $sitecss;
  241. }
  242. function gencss() {
  243. global $wgUseSiteCss;
  244. if ( !$wgUseSiteCss ) return '';
  245. global $wgSquidMaxage, $wgUser, $wgAllowUserCss;
  246. if ( $this->isCssPreview() ) {
  247. $siteargs = '&smaxage=0&maxage=0';
  248. } else {
  249. $siteargs = '&maxage=' . $wgSquidMaxage;
  250. }
  251. if ( $wgAllowUserCss && $wgUser->isLoggedIn() ) {
  252. $siteargs .= '&ts={user_touched}';
  253. $isTemplate = true;
  254. } else {
  255. $isTemplate = false;
  256. }
  257. $link = $this->makeStylesheetLink( self::makeUrl('-','action=raw&gen=css' . $siteargs) ) . "\n";
  258. if ( $wgAllowUserCss ) {
  259. $deps = 'loggedin';
  260. } else {
  261. $deps = array();
  262. }
  263. return cbt_value( $link, $deps, $isTemplate );
  264. }
  265. function user_touched() {
  266. global $wgUser;
  267. return cbt_value( $wgUser->mTouched, 'dynamic' );
  268. }
  269. function userjs() {
  270. global $wgAllowUserJs, $wgJsMimeType;
  271. if ( !$wgAllowUserJs ) return '';
  272. if ( $this->isJsPreview() ) {
  273. $url = '';
  274. } else {
  275. $url = self::makeUrl($this->getUserPageText().'/'.$this->mStyleName.'.js', 'action=raw&ctype='.$wgJsMimeType.'&dontcountme=s');
  276. }
  277. return cbt_value( $url, array( 'nonview dynamic', 'user' ) );
  278. }
  279. function userjsprev() {
  280. global $wgAllowUserJs, $wgRequest;
  281. if ( !$wgAllowUserJs ) return '';
  282. if ( $this->isJsPreview() ) {
  283. $js = '/*<![CDATA[*/ ' . $wgRequest->getText('wpTextbox1') . ' /*]]>*/';
  284. } else {
  285. $js = '';
  286. }
  287. return cbt_value( $js, array( 'nonview dynamic' ) );
  288. }
  289. function trackbackhtml() {
  290. global $wgUseTrackbacks;
  291. if ( !$wgUseTrackbacks ) return '';
  292. if ( $this->mOut->isArticleRelated() ) {
  293. $tb = $this->mTitle->trackbackRDF();
  294. } else {
  295. $tb = '';
  296. }
  297. return cbt_value( $tb, 'dynamic' );
  298. }
  299. function body_ondblclick() {
  300. global $wgUser;
  301. if( $this->isEditable() && $wgUser->getOption("editondblclick") ) {
  302. $js = 'document.location = "' . $this->getEditUrl() .'";';
  303. } else {
  304. $js = '';
  305. }
  306. if ( User::getDefaultOption('editondblclick') ) {
  307. return cbt_value( $js, 'user', 'title' );
  308. } else {
  309. // Optimise away for logged-out users
  310. return cbt_value( $js, 'loggedin dynamic' );
  311. }
  312. }
  313. function body_onload() {
  314. global $wgUser;
  315. if ( $this->isEditable() && $wgUser->getOption( 'editsectiononrightclick' ) ) {
  316. $js = 'setupRightClickEdit()';
  317. } else {
  318. $js = '';
  319. }
  320. return cbt_value( $js, 'loggedin dynamic' );
  321. }
  322. function nsclass() {
  323. return cbt_value( 'ns-' . $this->mTitle->getNamespace(), 'title' );
  324. }
  325. function sitenotice() {
  326. // Perhaps this could be given special dependencies using our knowledge of what
  327. // wfGetSiteNotice() depends on.
  328. return cbt_value( wfGetSiteNotice(), 'dynamic' );
  329. }
  330. function title() {
  331. return cbt_value( $this->mOut->getPageTitle(), array( 'title', 'lang' ) );
  332. }
  333. function title_urlform() {
  334. return cbt_value( $this->getThisTitleUrlForm(), 'title' );
  335. }
  336. function title_userurl() {
  337. return cbt_value( urlencode( $this->mTitle->getDBkey() ), 'title' );
  338. }
  339. function subtitle() {
  340. $subpagestr = $this->subPageSubtitle();
  341. if ( !empty( $subpagestr ) ) {
  342. $s = '<span class="subpages">'.$subpagestr.'</span>'.$this->mOut->getSubtitle();
  343. } else {
  344. $s = $this->mOut->getSubtitle();
  345. }
  346. return cbt_value( $s, array( 'title', 'nonview dynamic' ) );
  347. }
  348. function undelete() {
  349. return cbt_value( $this->getUndeleteLink(), array( 'title', 'lang' ) );
  350. }
  351. function newtalk() {
  352. global $wgUser, $wgDBname;
  353. $newtalks = $wgUser->getNewMessageLinks();
  354. if (count($newtalks) == 1 && $newtalks[0]["wiki"] === $wgDBname) {
  355. $usertitle = $this->getUserPageTitle();
  356. $usertalktitle = $usertitle->getTalkPage();
  357. if( !$usertalktitle->equals( $this->mTitle ) ) {
  358. $ntl = wfMsg( 'youhavenewmessages',
  359. $this->makeKnownLinkObj(
  360. $usertalktitle,
  361. wfMsgHtml( 'newmessageslink' ),
  362. 'redirect=no'
  363. ),
  364. $this->makeKnownLinkObj(
  365. $usertalktitle,
  366. wfMsgHtml( 'newmessagesdifflink' ),
  367. 'diff=cur'
  368. )
  369. );
  370. # Disable Cache
  371. $this->mOut->setSquidMaxage(0);
  372. }
  373. } else if (count($newtalks)) {
  374. $sep = str_replace("_", " ", wfMsgHtml("newtalkseperator"));
  375. $msgs = array();
  376. foreach ($newtalks as $newtalk) {
  377. $msgs[] = wfElement("a",
  378. array('href' => $newtalk["link"]), $newtalk["wiki"]);
  379. }
  380. $parts = implode($sep, $msgs);
  381. $ntl = wfMsgHtml('youhavenewmessagesmulti', $parts);
  382. $this->mOut->setSquidMaxage(0);
  383. } else {
  384. $ntl = '';
  385. }
  386. return cbt_value( $ntl, 'dynamic' );
  387. }
  388. function showjumplinks() {
  389. global $wgUser;
  390. return cbt_value( $wgUser->getOption( 'showjumplinks' ) ? 'true' : '', 'user' );
  391. }
  392. function bodytext() {
  393. return cbt_value( $this->mOut->getHTML(), 'dynamic' );
  394. }
  395. function catlinks() {
  396. if ( !isset( $this->mCatlinks ) ) {
  397. $this->mCatlinks = $this->getCategories();
  398. }
  399. return cbt_value( $this->mCatlinks, 'dynamic' );
  400. }
  401. function extratabs( $itemTemplate ) {
  402. global $wgContLang, $wgDisableLangConversion;
  403. $etpl = cbt_escape( $itemTemplate );
  404. /* show links to different language variants */
  405. $variants = $wgContLang->getVariants();
  406. $s = '';
  407. if ( !$wgDisableLangConversion && count( $wgContLang->getVariants() ) > 1 ) {
  408. $vcount=0;
  409. foreach ( $variants as $code ) {
  410. $name = $wgContLang->getVariantname( $code );
  411. if ( $name == 'disable' ) {
  412. continue;
  413. }
  414. $code = cbt_escape( $code );
  415. $name = cbt_escape( $name );
  416. $s .= "{ca_variant {{$code}} {{$name}} {{$vcount}} {{$etpl}}}\n";
  417. $vcount ++;
  418. }
  419. }
  420. return cbt_value( $s, array(), true );
  421. }
  422. function is_special() { return cbt_value( $this->mTitle->getNamespace() == NS_SPECIAL, 'title' ); }
  423. function can_edit() { return cbt_value( (string)($this->mTitle->userCanEdit()), 'dynamic' ); }
  424. function can_move() { return cbt_value( (string)($this->mTitle->userCanMove()), 'dynamic' ); }
  425. function is_talk() { return cbt_value( (string)($this->mTitle->isTalkPage()), 'title' ); }
  426. function is_protected() { return cbt_value( (string)$this->mTitle->isProtected(), 'dynamic' ); }
  427. function nskey() { return cbt_value( $this->mTitle->getNamespaceKey(), 'title' ); }
  428. function request_url() {
  429. global $wgRequest;
  430. return cbt_value( $wgRequest->getRequestURL(), 'dynamic' );
  431. }
  432. function subject_url() {
  433. $title = $this->getSubjectPage();
  434. if ( $title->exists() ) {
  435. $url = $title->getLocalUrl();
  436. } else {
  437. $url = $title->getLocalUrl( 'action=edit' );
  438. }
  439. return cbt_value( $url, 'title' );
  440. }
  441. function talk_url() {
  442. $title = $this->getTalkPage();
  443. if ( $title->exists() ) {
  444. $url = $title->getLocalUrl();
  445. } else {
  446. $url = $title->getLocalUrl( 'action=edit' );
  447. }
  448. return cbt_value( $url, 'title' );
  449. }
  450. function edit_url() {
  451. return cbt_value( $this->getEditUrl(), array( 'title', 'nonview dynamic' ) );
  452. }
  453. function move_url() {
  454. return cbt_value( $this->makeSpecialParamUrl( 'Movepage' ), array(), true );
  455. }
  456. function localurl( $query ) {
  457. return cbt_value( $this->mTitle->getLocalURL( $query ), 'title' );
  458. }
  459. function selecttab( $tab, $extraclass = '' ) {
  460. if ( !isset( $this->mSelectedTab ) ) {
  461. $prevent_active_tabs = false ;
  462. wfRunHooks( 'SkinTemplatePreventOtherActiveTabs', array( &$this , &$preventActiveTabs ) );
  463. $actionTabs = array(
  464. 'edit' => 'edit',
  465. 'submit' => 'edit',
  466. 'history' => 'history',
  467. 'protect' => 'protect',
  468. 'unprotect' => 'protect',
  469. 'delete' => 'delete',
  470. 'watch' => 'watch',
  471. 'unwatch' => 'watch',
  472. );
  473. if ( $preventActiveTabs ) {
  474. $this->mSelectedTab = false;
  475. } else {
  476. $action = $this->getAction();
  477. $section = $this->getSection();
  478. if ( isset( $actionTabs[$action] ) ) {
  479. $this->mSelectedTab = $actionTabs[$action];
  480. if ( $this->mSelectedTab == 'edit' && $section == 'new' ) {
  481. $this->mSelectedTab = 'addsection';
  482. }
  483. } elseif ( $this->mTitle->isTalkPage() ) {
  484. $this->mSelectedTab = 'talk';
  485. } else {
  486. $this->mSelectedTab = 'subject';
  487. }
  488. }
  489. }
  490. if ( $extraclass ) {
  491. if ( $this->mSelectedTab == $tab ) {
  492. $s = 'class="selected ' . htmlspecialchars( $extraclass ) . '"';
  493. } else {
  494. $s = 'class="' . htmlspecialchars( $extraclass ) . '"';
  495. }
  496. } else {
  497. if ( $this->mSelectedTab == $tab ) {
  498. $s = 'class="selected"';
  499. } else {
  500. $s = '';
  501. }
  502. }
  503. return cbt_value( $s, array( 'nonview dynamic', 'title' ) );
  504. }
  505. function subject_newclass() {
  506. $title = $this->getSubjectPage();
  507. $class = $title->exists() ? '' : 'new';
  508. return cbt_value( $class, 'dynamic' );
  509. }
  510. function talk_newclass() {
  511. $title = $this->getTalkPage();
  512. $class = $title->exists() ? '' : 'new';
  513. return cbt_value( $class, 'dynamic' );
  514. }
  515. function ca_variant( $code, $name, $index, $template ) {
  516. global $wgContLang;
  517. $selected = ($code == $wgContLang->getPreferredVariant());
  518. $action = $this->getAction();
  519. $actstr = '';
  520. if( $action )
  521. $actstr = 'action=' . $action . '&';
  522. $s = strtr( $template, array(
  523. '$id' => htmlspecialchars( 'varlang-' . $index ),
  524. '$class' => $selected ? 'class="selected"' : '',
  525. '$text' => $name,
  526. '$href' => htmlspecialchars( $this->mTitle->getLocalUrl( $actstr . 'variant=' . $code ) )
  527. ));
  528. return cbt_value( $s, 'dynamic' );
  529. }
  530. function is_watching() {
  531. return cbt_value( (string)$this->mTitle->userIsWatching(), array( 'dynamic' ) );
  532. }
  533. function personal_urls( $itemTemplate ) {
  534. global $wgShowIPinHeader, $wgContLang;
  535. # Split this function up into many small functions, to obtain the
  536. # best specificity in the dependencies of each one. The template below
  537. # has no dependencies, so its generation, and any static subfunctions,
  538. # can be optimised away.
  539. $etpl = cbt_escape( $itemTemplate );
  540. $s = "
  541. {userpage {{$etpl}}}
  542. {mytalk {{$etpl}}}
  543. {preferences {{$etpl}}}
  544. {watchlist {{$etpl}}}
  545. {mycontris {{$etpl}}}
  546. {logout {{$etpl}}}
  547. ";
  548. if ( $wgShowIPinHeader ) {
  549. $s .= "
  550. {anonuserpage {{$etpl}}}
  551. {anontalk {{$etpl}}}
  552. {anonlogin {{$etpl}}}
  553. ";
  554. } else {
  555. $s .= "{login {{$etpl}}}\n";
  556. }
  557. // No dependencies
  558. return cbt_value( $s, array(), true /*this is a template*/ );
  559. }
  560. function userpage( $itemTemplate ) {
  561. global $wgUser;
  562. if ( $this->isLoggedIn() ) {
  563. $userPage = $this->getUserPageTitle();
  564. $s = $this->makeTemplateLink( $itemTemplate, 'userpage', $userPage, $wgUser->getName() );
  565. } else {
  566. $s = '';
  567. }
  568. return cbt_value( $s, 'user' );
  569. }
  570. function mytalk( $itemTemplate ) {
  571. global $wgUser;
  572. if ( $this->isLoggedIn() ) {
  573. $userPage = $this->getUserPageTitle();
  574. $talkPage = $userPage->getTalkPage();
  575. $s = $this->makeTemplateLink( $itemTemplate, 'mytalk', $talkPage, wfMsg('mytalk') );
  576. } else {
  577. $s = '';
  578. }
  579. return cbt_value( $s, 'user' );
  580. }
  581. function preferences( $itemTemplate ) {
  582. if ( $this->isLoggedIn() ) {
  583. $s = $this->makeSpecialTemplateLink( $itemTemplate, 'preferences',
  584. 'Preferences', wfMsg( 'preferences' ) );
  585. } else {
  586. $s = '';
  587. }
  588. return cbt_value( $s, array( 'loggedin', 'lang' ) );
  589. }
  590. function watchlist( $itemTemplate ) {
  591. if ( $this->isLoggedIn() ) {
  592. $s = $this->makeSpecialTemplateLink( $itemTemplate, 'watchlist',
  593. 'Watchlist', wfMsg( 'watchlist' ) );
  594. } else {
  595. $s = '';
  596. }
  597. return cbt_value( $s, array( 'loggedin', 'lang' ) );
  598. }
  599. function mycontris( $itemTemplate ) {
  600. if ( $this->isLoggedIn() ) {
  601. global $wgUser;
  602. $s = $this->makeSpecialTemplateLink( $itemTemplate, 'mycontris',
  603. "Contributions/" . $wgUser->getTitleKey(), wfMsg('mycontris') );
  604. } else {
  605. $s = '';
  606. }
  607. return cbt_value( $s, 'user' );
  608. }
  609. function logout( $itemTemplate ) {
  610. if ( $this->isLoggedIn() ) {
  611. $s = $this->makeSpecialTemplateLink( $itemTemplate, 'logout',
  612. 'Userlogout', wfMsg( 'userlogout' ),
  613. $this->mTitle->getNamespace() === NS_SPECIAL && $this->mTitle->getText() === 'Preferences'
  614. ? '' : "returnto=" . $this->mTitle->getPrefixedURL() );
  615. } else {
  616. $s = '';
  617. }
  618. return cbt_value( $s, 'loggedin dynamic' );
  619. }
  620. function anonuserpage( $itemTemplate ) {
  621. if ( $this->isLoggedIn() ) {
  622. $s = '';
  623. } else {
  624. global $wgUser;
  625. $userPage = $this->getUserPageTitle();
  626. $s = $this->makeTemplateLink( $itemTemplate, 'userpage', $userPage, $wgUser->getName() );
  627. }
  628. return cbt_value( $s, '!loggedin dynamic' );
  629. }
  630. function anontalk( $itemTemplate ) {
  631. if ( $this->isLoggedIn() ) {
  632. $s = '';
  633. } else {
  634. $userPage = $this->getUserPageTitle();
  635. $talkPage = $userPage->getTalkPage();
  636. $s = $this->makeTemplateLink( $itemTemplate, 'mytalk', $talkPage, wfMsg('anontalk') );
  637. }
  638. return cbt_value( $s, '!loggedin dynamic' );
  639. }
  640. function anonlogin( $itemTemplate ) {
  641. if ( $this->isLoggedIn() ) {
  642. $s = '';
  643. } else {
  644. $s = $this->makeSpecialTemplateLink( $itemTemplate, 'anonlogin', 'Userlogin',
  645. wfMsg( 'userlogin' ), 'returnto=' . urlencode( $this->getThisPDBK() ) );
  646. }
  647. return cbt_value( $s, '!loggedin dynamic' );
  648. }
  649. function login( $itemTemplate ) {
  650. if ( $this->isLoggedIn() ) {
  651. $s = '';
  652. } else {
  653. $s = $this->makeSpecialTemplateLink( $itemTemplate, 'login', 'Userlogin',
  654. wfMsg( 'userlogin' ), 'returnto=' . urlencode( $this->getThisPDBK() ) );
  655. }
  656. return cbt_value( $s, '!loggedin dynamic' );
  657. }
  658. function logopath() { return $GLOBALS['wgLogo']; }
  659. function mainpage() { return self::makeMainPageUrl(); }
  660. function sidebar( $startSection, $endSection, $innerTpl ) {
  661. $s = '';
  662. $lines = explode( "\n", wfMsgForContent( 'sidebar' ) );
  663. $firstSection = true;
  664. foreach ($lines as $line) {
  665. if (strpos($line, '*') !== 0)
  666. continue;
  667. if (strpos($line, '**') !== 0) {
  668. $bar = trim($line, '* ');
  669. $name = wfMsg( $bar );
  670. if (wfEmptyMsg($bar, $name)) {
  671. $name = $bar;
  672. }
  673. if ( $firstSection ) {
  674. $firstSection = false;
  675. } else {
  676. $s .= $endSection;
  677. }
  678. $s .= strtr( $startSection,
  679. array(
  680. '$bar' => htmlspecialchars( $bar ),
  681. '$barname' => $name
  682. ) );
  683. } else {
  684. if (strpos($line, '|') !== false) { // sanity check
  685. $line = explode( '|' , trim($line, '* '), 2 );
  686. $link = wfMsgForContent( $line[0] );
  687. if ($link == '-')
  688. continue;
  689. if (wfEmptyMsg($line[1], $text = wfMsg($line[1])))
  690. $text = $line[1];
  691. if (wfEmptyMsg($line[0], $link))
  692. $link = $line[0];
  693. $href = self::makeInternalOrExternalUrl( $link );
  694. $s .= strtr( $innerTpl,
  695. array(
  696. '$text' => htmlspecialchars( $text ),
  697. '$href' => htmlspecialchars( $href ),
  698. '$id' => htmlspecialchars( 'n-' . strtr($line[1], ' ', '-') ),
  699. '$classactive' => ''
  700. ) );
  701. } else { continue; }
  702. }
  703. }
  704. if ( !$firstSection ) {
  705. $s .= $endSection;
  706. }
  707. // Depends on user language only
  708. return cbt_value( $s, 'lang' );
  709. }
  710. function searchaction() {
  711. // Static link
  712. return $this->getSearchLink();
  713. }
  714. function search() {
  715. global $wgRequest;
  716. return cbt_value( trim( $this->getSearch() ), 'special dynamic' );
  717. }
  718. function notspecialpage() {
  719. return cbt_value( $this->mTitle->getNamespace() != NS_SPECIAL, 'special' );
  720. }
  721. function nav_whatlinkshere() {
  722. return cbt_value( $this->makeSpecialParamUrl('Whatlinkshere' ), array(), true );
  723. }
  724. function article_exists() {
  725. return cbt_value( (string)($this->mTitle->getArticleId() !== 0), 'title' );
  726. }
  727. function nav_recentchangeslinked() {
  728. return cbt_value( $this->makeSpecialParamUrl('Recentchangeslinked' ), array(), true );
  729. }
  730. function feeds( $itemTemplate = '' ) {
  731. if ( !$this->mOut->isSyndicated() ) {
  732. $feeds = '';
  733. } elseif ( $itemTemplate == '' ) {
  734. // boolean only required
  735. $feeds = 'true';
  736. } else {
  737. $feeds = '';
  738. global $wgFeedClasses, $wgRequest;
  739. foreach( $wgFeedClasses as $format => $class ) {
  740. $feeds .= strtr( $itemTemplate,
  741. array(
  742. '$key' => htmlspecialchars( $format ),
  743. '$text' => $format,
  744. '$href' => $wgRequest->appendQuery( "feed=$format" )
  745. ) );
  746. }
  747. }
  748. return cbt_value( $feeds, 'special dynamic' );
  749. }
  750. function is_userpage() {
  751. list( $id, $ip ) = $this->getUserPageIdIp();
  752. return cbt_value( (string)($id || $ip), 'title' );
  753. }
  754. function is_ns_mediawiki() {
  755. return cbt_value( (string)$this->mTitle->getNamespace() == NS_MEDIAWIKI, 'title' );
  756. }
  757. function is_loggedin() {
  758. global $wgUser;
  759. return cbt_value( (string)($wgUser->isLoggedIn()), 'loggedin' );
  760. }
  761. function nav_contributions() {
  762. $url = $this->makeSpecialParamUrl( 'Contributions', '', '{title_userurl}' );
  763. return cbt_value( $url, array(), true );
  764. }
  765. function is_allowed( $right ) {
  766. global $wgUser;
  767. return cbt_value( (string)$wgUser->isAllowed( $right ), 'user' );
  768. }
  769. function nav_blockip() {
  770. $url = $this->makeSpecialParamUrl( 'Blockip', '', '{title_userurl}' );
  771. return cbt_value( $url, array(), true );
  772. }
  773. function nav_emailuser() {
  774. global $wgEnableEmail, $wgEnableUserEmail, $wgUser;
  775. if ( !$wgEnableEmail || !$wgEnableUserEmail ) return '';
  776. $url = $this->makeSpecialParamUrl( 'Emailuser', '', '{title_userurl}' );
  777. return cbt_value( $url, array(), true );
  778. }
  779. function nav_upload() {
  780. global $wgEnableUploads, $wgUploadNavigationUrl;
  781. if ( !$wgEnableUploads ) {
  782. return '';
  783. } elseif ( $wgUploadNavigationUrl ) {
  784. return $wgUploadNavigationUrl;
  785. } else {
  786. return self::makeSpecialUrl('Upload');
  787. }
  788. }
  789. function nav_specialpages() {
  790. return self::makeSpecialUrl('Specialpages');
  791. }
  792. function nav_print() {
  793. global $wgRequest, $wgArticle;
  794. $action = $this->getAction();
  795. $url = '';
  796. if( $this->mTitle->getNamespace() !== NS_SPECIAL
  797. && ($action == '' || $action == 'view' || $action == 'purge' ) )
  798. {
  799. $revid = $wgArticle->getLatest();
  800. if ( $revid != 0 ) {
  801. $url = $wgRequest->appendQuery( 'printable=yes' );
  802. }
  803. }
  804. return cbt_value( $url, array( 'nonview dynamic', 'title' ) );
  805. }
  806. function nav_permalink() {
  807. $url = (string)$this->getPermalink();
  808. return cbt_value( $url, 'dynamic' );
  809. }
  810. function nav_trackbacklink() {
  811. global $wgUseTrackbacks;
  812. if ( !$wgUseTrackbacks ) return '';
  813. return cbt_value( $this->mTitle->trackbackURL(), 'title' );
  814. }
  815. function is_permalink() {
  816. return cbt_value( (string)($this->getPermalink() === false), 'nonview dynamic' );
  817. }
  818. function toolboxend() {
  819. // This is where the MonoBookTemplateToolboxEnd hook went in the old skin
  820. return '';
  821. }
  822. function language_urls( $outer, $inner ) {
  823. global $wgHideInterlanguageLinks, $wgOut, $wgContLang;
  824. if ( $wgHideInterlanguageLinks ) return '';
  825. $links = $wgOut->getLanguageLinks();
  826. $s = '';
  827. if ( count( $links ) ) {
  828. foreach( $links as $l ) {
  829. $tmp = explode( ':', $l, 2 );
  830. $nt = Title::newFromText( $l );
  831. $s .= strtr( $inner,
  832. array(
  833. '$class' => htmlspecialchars( 'interwiki-' . $tmp[0] ),
  834. '$href' => htmlspecialchars( $nt->getFullURL() ),
  835. '$text' => ($wgContLang->getLanguageName( $nt->getInterwiki() ) != ''?
  836. $wgContLang->getLanguageName( $nt->getInterwiki() ) : $l ),
  837. )
  838. );
  839. }
  840. $s = str_replace( '$body', $s, $outer );
  841. }
  842. return cbt_value( $s, 'dynamic' );
  843. }
  844. function poweredbyico() { return $this->getPoweredBy(); }
  845. function copyrightico() { return $this->getCopyrightIcon(); }
  846. function lastmod() {
  847. global $wgMaxCredits;
  848. if ( $wgMaxCredits ) return '';
  849. if ( !isset( $this->mLastmod ) ) {
  850. if ( $this->isCurrentArticleView() ) {
  851. $this->mLastmod = $this->lastModified();
  852. } else {
  853. $this->mLastmod = '';
  854. }
  855. }
  856. return cbt_value( $this->mLastmod, 'dynamic' );
  857. }
  858. function viewcount() {
  859. global $wgDisableCounters;
  860. if ( $wgDisableCounters ) return '';
  861. global $wgLang, $wgArticle;
  862. if ( is_object( $wgArticle ) ) {
  863. $viewcount = $wgLang->formatNum( $wgArticle->getCount() );
  864. if ( $viewcount ) {
  865. $viewcount = wfMsg( "viewcount", $viewcount );
  866. } else {
  867. $viewcount = '';
  868. }
  869. } else {
  870. $viewcount = '';
  871. }
  872. return cbt_value( $viewcount, 'dynamic' );
  873. }
  874. function numberofwatchingusers() {
  875. global $wgPageShowWatchingUsers;
  876. if ( !$wgPageShowWatchingUsers ) return '';
  877. $dbr =& wfGetDB( DB_SLAVE );
  878. extract( $dbr->tableNames( 'watchlist' ) );
  879. $sql = "SELECT COUNT(*) AS n FROM $watchlist
  880. WHERE wl_title='" . $dbr->strencode($this->mTitle->getDBKey()) .
  881. "' AND wl_namespace=" . $this->mTitle->getNamespace() ;
  882. $res = $dbr->query( $sql, 'SkinTemplate::outputPage');
  883. $row = $dbr->fetchObject( $res );
  884. $num = $row->n;
  885. if ($num > 0) {
  886. $s = wfMsg('number_of_watching_users_pageview', $num);
  887. } else {
  888. $s = '';
  889. }
  890. return cbt_value( $s, 'dynamic' );
  891. }
  892. function credits() {
  893. global $wgMaxCredits;
  894. if ( !$wgMaxCredits ) return '';
  895. if ( $this->isCurrentArticleView() ) {
  896. require_once("Credits.php");
  897. global $wgArticle, $wgShowCreditsIfMax;
  898. $credits = getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax);
  899. } else {
  900. $credits = '';
  901. }
  902. return cbt_value( $credits, 'view dynamic' );
  903. }
  904. function normalcopyright() {
  905. return $this->getCopyright( 'normal' );
  906. }
  907. function historycopyright() {
  908. return $this->getCopyright( 'history' );
  909. }
  910. function is_currentview() {
  911. global $wgRequest;
  912. return cbt_value( (string)$this->isCurrentArticleView(), 'view' );
  913. }
  914. function usehistorycopyright() {
  915. global $wgRequest;
  916. if ( wfMsgForContent( 'history_copyright' ) == '-' ) return '';
  917. $oldid = $this->getOldId();
  918. $diff = $this->getDiff();
  919. $use = (string)(!is_null( $oldid ) && is_null( $diff ));
  920. return cbt_value( $use, 'nonview dynamic' );
  921. }
  922. function privacy() {
  923. return cbt_value( $this->privacyLink(), 'lang' );
  924. }
  925. function about() {
  926. return cbt_value( $this->aboutLink(), 'lang' );
  927. }
  928. function disclaimer() {
  929. return cbt_value( $this->disclaimerLink(), 'lang' );
  930. }
  931. function tagline() {
  932. # A reference to this tag existed in the old MonoBook.php, but the
  933. # template data wasn't set anywhere
  934. return '';
  935. }
  936. function reporttime() {
  937. return cbt_value( $this->mOut->reportTime(), 'dynamic' );
  938. }
  939. function msg( $name ) {
  940. return cbt_value( wfMsg( $name ), 'lang' );
  941. }
  942. function fallbackmsg( $name, $fallback ) {
  943. $text = wfMsg( $name );
  944. if ( wfEmptyMsg( $name, $text ) ) {
  945. $text = $fallback;
  946. }
  947. return cbt_value( $text, 'lang' );
  948. }
  949. /******************************************************
  950. * Utility functions *
  951. ******************************************************/
  952. /** Return true if this request is a valid, secure CSS preview */
  953. function isCssPreview() {
  954. if ( !isset( $this->mCssPreview ) ) {
  955. global $wgRequest, $wgAllowUserCss, $wgUser;
  956. $this->mCssPreview =
  957. $wgAllowUserCss &&
  958. $wgUser->isLoggedIn() &&
  959. $this->mTitle->isCssSubpage() &&
  960. $this->userCanPreview( $this->getAction() );
  961. }
  962. return $this->mCssPreview;
  963. }
  964. /** Return true if this request is a valid, secure JS preview */
  965. function isJsPreview() {
  966. if ( !isset( $this->mJsPreview ) ) {
  967. global $wgRequest, $wgAllowUserJs, $wgUser;
  968. $this->mJsPreview =
  969. $wgAllowUserJs &&
  970. $wgUser->isLoggedIn() &&
  971. $this->mTitle->isJsSubpage() &&
  972. $this->userCanPreview( $this->getAction() );
  973. }
  974. return $this->mJsPreview;
  975. }
  976. /** Get the title of the $wgUser's user page */
  977. function getUserPageTitle() {
  978. if ( !isset( $this->mUserPageTitle ) ) {
  979. global $wgUser;
  980. $this->mUserPageTitle = $wgUser->getUserPage();
  981. }
  982. return $this->mUserPageTitle;
  983. }
  984. /** Get the text of the user page title */
  985. function getUserPageText() {
  986. if ( !isset( $this->mUserPageText ) ) {
  987. $userPage = $this->getUserPageTitle();
  988. $this->mUserPageText = $userPage->getPrefixedText();
  989. }
  990. return $this->mUserPageText;
  991. }
  992. /** Make an HTML element for a stylesheet link */
  993. function makeStylesheetLink( $url ) {
  994. return '<link rel="stylesheet" type="text/css" href="' . htmlspecialchars( $url ) . "\"/>";
  995. }
  996. /** Make an XHTML element for inline CSS */
  997. function makeStylesheetCdata( $style ) {
  998. return "<style type=\"text/css\"> /*<![CDATA[*/ {$style} /*]]>*/ </style>";
  999. }
  1000. /** Get the edit URL for this page */
  1001. function getEditUrl() {
  1002. if ( !isset( $this->mEditUrl ) ) {
  1003. $this->mEditUrl = $this->mTitle->getLocalUrl( $this->editUrlOptions() );
  1004. }
  1005. return $this->mEditUrl;
  1006. }
  1007. /** Get the prefixed DB key for this page */
  1008. function getThisPDBK() {
  1009. if ( !isset( $this->mThisPDBK ) ) {
  1010. $this->mThisPDBK = $this->mTitle->getPrefixedDbKey();
  1011. }
  1012. return $this->mThisPDBK;
  1013. }
  1014. function getThisTitleUrlForm() {
  1015. if ( !isset( $this->mThisTitleUrlForm ) ) {
  1016. $this->mThisTitleUrlForm = $this->mTitle->getPrefixedURL();
  1017. }
  1018. return $this->mThisTitleUrlForm;
  1019. }
  1020. /**
  1021. * If the current page is a user page, get the user's ID and IP. Otherwise return array(0,false)
  1022. */
  1023. function getUserPageIdIp() {
  1024. if ( !isset( $this->mUserPageId ) ) {
  1025. if( $this->mTitle->getNamespace() == NS_USER || $this->mTitle->getNamespace() == NS_USER_TALK ) {
  1026. $this->mUserPageId = User::idFromName($this->mTitle->getText());
  1027. $this->mUserPageIp = User::isIP($this->mTitle->getText());
  1028. } else {
  1029. $this->mUserPageId = 0;
  1030. $this->mUserPageIp = false;
  1031. }
  1032. }
  1033. return array( $this->mUserPageId, $this->mUserPageIp );
  1034. }
  1035. /**
  1036. * Returns a permalink URL, or false if the current page is already a
  1037. * permalink, or blank if a permalink shouldn't be displayed
  1038. */
  1039. function getPermalink() {
  1040. if ( !isset( $this->mPermalink ) ) {
  1041. global $wgRequest, $wgArticle;
  1042. $action = $this->getAction();
  1043. $oldid = $this->getOldId();
  1044. $url = '';
  1045. if( $this->mTitle->getNamespace() !== NS_SPECIAL
  1046. && $this->mTitle->getArticleId() != 0
  1047. && ($action == '' || $action == 'view' || $action == 'purge' ) )
  1048. {
  1049. if ( !$oldid ) {
  1050. $revid = $wgArticle->getLatest();
  1051. $url = $this->mTitle->getLocalURL( "oldid=$revid" );
  1052. } else {
  1053. $url = false;
  1054. }
  1055. } else {
  1056. $url = '';
  1057. }
  1058. }
  1059. return $url;
  1060. }
  1061. /**
  1062. * Returns true if the current page is an article, not a special page,
  1063. * and we are viewing a revision, not a diff
  1064. */
  1065. function isArticleView() {
  1066. global $wgOut, $wgArticle, $wgRequest;
  1067. if ( !isset( $this->mIsArticleView ) ) {
  1068. $oldid = $this->getOldId();
  1069. $diff = $this->getDiff();
  1070. $this->mIsArticleView = $wgOut->isArticle() and
  1071. (!is_null( $oldid ) or is_null( $diff )) and 0 != $wgArticle->getID();
  1072. }
  1073. return $this->mIsArticleView;
  1074. }
  1075. function isCurrentArticleView() {
  1076. if ( !isset( $this->mIsCurrentArticleView ) ) {
  1077. global $wgOut, $wgArticle, $wgRequest;
  1078. $oldid = $this->getOldId();
  1079. $this->mIsCurrentArticleView = $wgOut->isArticle() && is_null( $oldid ) && 0 != $wgArticle->getID();
  1080. }
  1081. return $this->mIsCurrentArticleView;
  1082. }
  1083. /**
  1084. * Return true if the current page is editable; if edit section on right
  1085. * click should be enabled.
  1086. */
  1087. function isEditable() {
  1088. global $wgRequest;
  1089. $action = $this->getAction();
  1090. return ($this->mTitle->getNamespace() != NS_SPECIAL and !($action == 'edit' or $action == 'submit'));
  1091. }
  1092. /** Return true if the user is logged in */
  1093. function isLoggedIn() {
  1094. global $wgUser;
  1095. return $wgUser->isLoggedIn();
  1096. }
  1097. /** Get the local URL of the current page */
  1098. function getPageUrl() {
  1099. if ( !isset( $this->mPageUrl ) ) {
  1100. $this->mPageUrl = $this->mTitle->getLocalURL();
  1101. }
  1102. return $this->mPageUrl;
  1103. }
  1104. /** Make a link to a title using a template */
  1105. function makeTemplateLink( $template, $key, $title, $text ) {
  1106. $url = $title->getLocalUrl();
  1107. return strtr( $template,
  1108. array(
  1109. '$key' => $key,
  1110. '$classactive' => ($url == $this->getPageUrl()) ? 'class="active"' : '',
  1111. '$class' => $title->getArticleID() == 0 ? 'class="new"' : '',
  1112. '$href' => htmlspecialchars( $url ),
  1113. '$text' => $text
  1114. ) );
  1115. }
  1116. /** Make a link to a URL using a template */
  1117. function makeTemplateLinkUrl( $template, $key, $url, $text ) {
  1118. return strtr( $template,
  1119. array(
  1120. '$key' => $key,
  1121. '$classactive' => ($url == $this->getPageUrl()) ? 'class="active"' : '',
  1122. '$class' => '',
  1123. '$href' => htmlspecialchars( $url ),
  1124. '$text' => $text
  1125. ) );
  1126. }
  1127. /** Make a link to a special page using a template */
  1128. function makeSpecialTemplateLink( $template, $key, $specialName, $text, $query = '' ) {
  1129. $url = self::makeSpecialUrl( $specialName, $query );
  1130. // Ignore the query when comparing
  1131. $active = ($this->mTitle->getNamespace() == NS_SPECIAL && $this->mTitle->getDBkey() == $specialName);
  1132. return strtr( $template,
  1133. array(
  1134. '$key' => $key,
  1135. '$classactive' => $active ? 'class="active"' : '',
  1136. '$class' => '',
  1137. '$href' => htmlspecialchars( $url ),
  1138. '$text' => $text
  1139. ) );
  1140. }
  1141. function loadRequestValues() {
  1142. global $wgRequest;
  1143. $this->mAction = $wgRequest->getText( 'action' );
  1144. $this->mOldId = $wgRequest->getVal( 'oldid' );
  1145. $this->mDiff = $wgRequest->getVal( 'diff' );
  1146. $this->mSection = $wgRequest->getVal( 'section' );
  1147. $this->mSearch = $wgRequest->getVal( 'search' );
  1148. $this->mRequestValuesLoaded = true;
  1149. }
  1150. /** Get the action parameter of the request */
  1151. function getAction() {
  1152. if ( !isset( $this->mRequestValuesLoaded ) ) {
  1153. $this->loadRequestValues();
  1154. }
  1155. return $this->mAction;
  1156. }
  1157. /** Get the oldid parameter */
  1158. function getOldId() {
  1159. if ( !isset( $this->mRequestValuesLoaded ) ) {
  1160. $this->loadRequestValues();
  1161. }
  1162. return $this->mOldId;
  1163. }
  1164. /** Get the diff parameter */
  1165. function getDiff() {
  1166. if ( !isset( $this->mRequestValuesLoaded ) ) {
  1167. $this->loadRequestValues();
  1168. }
  1169. return $this->mDiff;
  1170. }
  1171. function getSection() {
  1172. if ( !isset( $this->mRequestValuesLoaded ) ) {
  1173. $this->loadRequestValues();
  1174. }
  1175. return $this->mSection;
  1176. }
  1177. function getSearch() {
  1178. if ( !isset( $this->mRequestValuesLoaded ) ) {
  1179. $this->loadRequestValues();
  1180. }
  1181. return $this->mSearch;
  1182. }
  1183. /** Make a special page URL of the form [[Special:Somepage/{title_urlform}]] */
  1184. function makeSpecialParamUrl( $name, $query = '', $param = '{title_urlform}' ) {
  1185. // Abuse makeTitle's lax validity checking to slip a control character into the URL
  1186. $title = Title::makeTitle( NS_SPECIAL, "$name/\x1a" );
  1187. $url = cbt_escape( $title->getLocalURL( $query ) );
  1188. // Now replace it with the parameter
  1189. return str_replace( '%1A', $param, $url );
  1190. }
  1191. function getSubjectPage() {
  1192. if ( !isset( $this->mSubjectPage ) ) {
  1193. $this->mSubjectPage = $this->mTitle->getSubjectPage();
  1194. }
  1195. return $this->mSubjectPage;
  1196. }
  1197. function getTalkPage() {
  1198. if ( !isset( $this->mTalkPage ) ) {
  1199. $this->mTalkPage = $this->mTitle->getTalkPage();
  1200. }
  1201. return $this->mTalkPage;
  1202. }
  1203. }
  1204. ?>