MediaWiki  1.27.0
OutputPage.php
Go to the documentation of this file.
1 <?php
26 
42 class OutputPage extends ContextSource {
44  protected $mMetatags = [];
45 
47  protected $mLinktags = [];
48 
50  protected $mCanonicalUrl = false;
51 
56  protected $mExtStyles = [];
57 
61  public $mPagetitle = '';
62 
67  public $mBodytext = '';
68 
74  public $mDebugtext = '';
75 
77  private $mHTMLtitle = '';
78 
83  private $mIsarticle = false;
84 
86  private $mIsArticleRelated = true;
87 
92  private $mPrintable = false;
93 
98  private $mSubtitle = [];
99 
101  public $mRedirect = '';
102 
104  protected $mStatusCode;
105 
110  protected $mLastModified = '';
111 
121  private $mETag = false;
122 
124  protected $mCategoryLinks = [];
125 
127  protected $mCategories = [];
128 
130  protected $mIndicators = [];
131 
133  private $mLanguageLinks = [];
134 
141  private $mScripts = '';
142 
144  protected $mInlineStyles = '';
145 
150  public $mPageLinkTitle = '';
151 
153  protected $mHeadItems = [];
154 
156  protected $mModules = [];
157 
159  protected $mModuleScripts = [];
160 
162  protected $mModuleStyles = [];
163 
165  protected $mResourceLoader;
166 
168  protected $mJsConfigVars = [];
169 
171  protected $mTemplateIds = [];
172 
174  protected $mImageTimeKeys = [];
175 
177  public $mRedirectCode = '';
178 
179  protected $mFeedLinksAppendQuery = null;
180 
186  protected $mAllowedModules = [
188  ];
189 
191  protected $mDoNothing = false;
192 
193  // Parser related.
194 
196  protected $mContainsNewMagic = 0;
197 
202  protected $mParserOptions = null;
203 
209  private $mFeedLinks = [];
210 
211  // Gwicke work on squid caching? Roughly from 2003.
212  protected $mEnableClientCache = true;
213 
215  private $mArticleBodyOnly = false;
216 
218  protected $mNewSectionLink = false;
219 
221  protected $mHideNewSectionLink = false;
222 
228  public $mNoGallery = false;
229 
231  private $mPageTitleActionText = '';
232 
234  protected $mCdnMaxage = 0;
236  protected $mCdnMaxageLimit = INF;
237 
243  protected $mPreventClickjacking = true;
244 
246  private $mRevisionId = null;
247 
249  private $mRevisionTimestamp = null;
250 
252  protected $mFileVersion = null;
253 
262  protected $styles = [];
263 
267  protected $mJQueryDone = false;
268 
269  private $mIndexPolicy = 'index';
270  private $mFollowPolicy = 'follow';
271  private $mVaryHeader = [
272  'Accept-Encoding' => [ 'match=gzip' ],
273  ];
274 
281  private $mRedirectedFrom = null;
282 
286  private $mProperties = [];
287 
291  private $mTarget = null;
292 
296  private $mEnableTOC = true;
297 
301  private $mEnableSectionEditLinks = true;
302 
306  private $copyrightUrl;
307 
314  function __construct( IContextSource $context = null ) {
315  if ( $context === null ) {
316  # Extensions should use `new RequestContext` instead of `new OutputPage` now.
317  wfDeprecated( __METHOD__, '1.18' );
318  } else {
319  $this->setContext( $context );
320  }
321  }
322 
329  public function redirect( $url, $responsecode = '302' ) {
330  # Strip newlines as a paranoia check for header injection in PHP<5.1.2
331  $this->mRedirect = str_replace( "\n", '', $url );
332  $this->mRedirectCode = $responsecode;
333  }
334 
340  public function getRedirect() {
341  return $this->mRedirect;
342  }
343 
352  public function setCopyrightUrl( $url ) {
353  $this->copyrightUrl = $url;
354  }
355 
361  public function setStatusCode( $statusCode ) {
362  $this->mStatusCode = $statusCode;
363  }
364 
372  function addMeta( $name, $val ) {
373  array_push( $this->mMetatags, [ $name, $val ] );
374  }
375 
382  public function getMetaTags() {
383  return $this->mMetatags;
384  }
385 
393  function addLink( array $linkarr ) {
394  array_push( $this->mLinktags, $linkarr );
395  }
396 
403  public function getLinkTags() {
404  return $this->mLinktags;
405  }
406 
414  function addMetadataLink( array $linkarr ) {
415  $linkarr['rel'] = $this->getMetadataAttribute();
416  $this->addLink( $linkarr );
417  }
418 
424  function setCanonicalUrl( $url ) {
425  $this->mCanonicalUrl = $url;
426  }
427 
435  public function getCanonicalUrl() {
436  return $this->mCanonicalUrl;
437  }
438 
444  public function getMetadataAttribute() {
445  # note: buggy CC software only reads first "meta" link
446  static $haveMeta = false;
447  if ( $haveMeta ) {
448  return 'alternate meta';
449  } else {
450  $haveMeta = true;
451  return 'meta';
452  }
453  }
454 
462  function addScript( $script ) {
463  $this->mScripts .= $script;
464  }
465 
475  public function addExtensionStyle( $url ) {
476  wfDeprecated( __METHOD__, '1.27' );
477  array_push( $this->mExtStyles, $url );
478  }
479 
486  function getExtStyle() {
487  wfDeprecated( __METHOD__, '1.27' );
488  return $this->mExtStyles;
489  }
490 
499  public function addScriptFile( $file, $version = null ) {
500  // See if $file parameter is an absolute URL or begins with a slash
501  if ( substr( $file, 0, 1 ) == '/' || preg_match( '#^[a-z]*://#i', $file ) ) {
502  $path = $file;
503  } else {
504  $path = $this->getConfig()->get( 'StylePath' ) . "/common/{$file}";
505  }
506  if ( is_null( $version ) ) {
507  $version = $this->getConfig()->get( 'StyleVersion' );
508  }
510  }
511 
518  public function addInlineScript( $script ) {
519  $this->mScripts .= Html::inlineScript( $script );
520  }
521 
530  protected function filterModules( array $modules, $position = null,
532  ) {
534  $filteredModules = [];
535  foreach ( $modules as $val ) {
536  $module = $resourceLoader->getModule( $val );
537  if ( $module instanceof ResourceLoaderModule
538  && $module->getOrigin() <= $this->getAllowedModules( $type )
539  && ( is_null( $position ) || $module->getPosition() == $position )
540  && ( !$this->mTarget || in_array( $this->mTarget, $module->getTargets() ) )
541  ) {
542  $filteredModules[] = $val;
543  }
544  }
545  return $filteredModules;
546  }
547 
556  public function getModules( $filter = false, $position = null, $param = 'mModules' ) {
557  $modules = array_values( array_unique( $this->$param ) );
558  return $filter
559  ? $this->filterModules( $modules, $position )
560  : $modules;
561  }
562 
570  public function addModules( $modules ) {
571  $this->mModules = array_merge( $this->mModules, (array)$modules );
572  }
573 
582  public function getModuleScripts( $filter = false, $position = null ) {
583  return $this->getModules( $filter, $position, 'mModuleScripts' );
584  }
585 
593  public function addModuleScripts( $modules ) {
594  $this->mModuleScripts = array_merge( $this->mModuleScripts, (array)$modules );
595  }
596 
605  public function getModuleStyles( $filter = false, $position = null ) {
606  return $this->getModules( $filter, $position, 'mModuleStyles' );
607  }
608 
618  public function addModuleStyles( $modules ) {
619  $this->mModuleStyles = array_merge( $this->mModuleStyles, (array)$modules );
620  }
621 
630  public function getModuleMessages( $filter = false, $position = null ) {
631  wfDeprecated( __METHOD__, '1.26' );
632  return [];
633  }
634 
641  public function addModuleMessages( $modules ) {
642  wfDeprecated( __METHOD__, '1.26' );
643  }
644 
648  public function getTarget() {
649  return $this->mTarget;
650  }
651 
657  public function setTarget( $target ) {
658  $this->mTarget = $target;
659  }
660 
666  function getHeadItemsArray() {
667  return $this->mHeadItems;
668  }
669 
682  public function addHeadItem( $name, $value ) {
683  $this->mHeadItems[$name] = $value;
684  }
685 
692  public function hasHeadItem( $name ) {
693  return isset( $this->mHeadItems[$name] );
694  }
695 
701  function setETag( $tag ) {
702  $this->mETag = $tag;
703  }
704 
712  public function setArticleBodyOnly( $only ) {
713  $this->mArticleBodyOnly = $only;
714  }
715 
721  public function getArticleBodyOnly() {
723  }
724 
732  public function setProperty( $name, $value ) {
733  $this->mProperties[$name] = $value;
734  }
735 
743  public function getProperty( $name ) {
744  if ( isset( $this->mProperties[$name] ) ) {
745  return $this->mProperties[$name];
746  } else {
747  return null;
748  }
749  }
750 
762  public function checkLastModified( $timestamp ) {
763  if ( !$timestamp || $timestamp == '19700101000000' ) {
764  wfDebug( __METHOD__ . ": CACHE DISABLED, NO TIMESTAMP\n" );
765  return false;
766  }
767  $config = $this->getConfig();
768  if ( !$config->get( 'CachePages' ) ) {
769  wfDebug( __METHOD__ . ": CACHE DISABLED\n" );
770  return false;
771  }
772 
774  $modifiedTimes = [
775  'page' => $timestamp,
776  'user' => $this->getUser()->getTouched(),
777  'epoch' => $config->get( 'CacheEpoch' )
778  ];
779  if ( $config->get( 'UseSquid' ) ) {
780  // bug 44570: the core page itself may not change, but resources might
781  $modifiedTimes['sepoch'] = wfTimestamp( TS_MW, time() - $config->get( 'SquidMaxage' ) );
782  }
783  Hooks::run( 'OutputPageCheckLastModified', [ &$modifiedTimes ] );
784 
785  $maxModified = max( $modifiedTimes );
786  $this->mLastModified = wfTimestamp( TS_RFC2822, $maxModified );
787 
788  $clientHeader = $this->getRequest()->getHeader( 'If-Modified-Since' );
789  if ( $clientHeader === false ) {
790  wfDebug( __METHOD__ . ": client did not send If-Modified-Since header", 'private' );
791  return false;
792  }
793 
794  # IE sends sizes after the date like this:
795  # Wed, 20 Aug 2003 06:51:19 GMT; length=5202
796  # this breaks strtotime().
797  $clientHeader = preg_replace( '/;.*$/', '', $clientHeader );
798 
799  MediaWiki\suppressWarnings(); // E_STRICT system time bitching
800  $clientHeaderTime = strtotime( $clientHeader );
801  MediaWiki\restoreWarnings();
802  if ( !$clientHeaderTime ) {
803  wfDebug( __METHOD__
804  . ": unable to parse the client's If-Modified-Since header: $clientHeader\n" );
805  return false;
806  }
807  $clientHeaderTime = wfTimestamp( TS_MW, $clientHeaderTime );
808 
809  # Make debug info
810  $info = '';
811  foreach ( $modifiedTimes as $name => $value ) {
812  if ( $info !== '' ) {
813  $info .= ', ';
814  }
815  $info .= "$name=" . wfTimestamp( TS_ISO_8601, $value );
816  }
817 
818  wfDebug( __METHOD__ . ": client sent If-Modified-Since: " .
819  wfTimestamp( TS_ISO_8601, $clientHeaderTime ), 'private' );
820  wfDebug( __METHOD__ . ": effective Last-Modified: " .
821  wfTimestamp( TS_ISO_8601, $maxModified ), 'private' );
822  if ( $clientHeaderTime < $maxModified ) {
823  wfDebug( __METHOD__ . ": STALE, $info", 'private' );
824  return false;
825  }
826 
827  # Not modified
828  # Give a 304 Not Modified response code and disable body output
829  wfDebug( __METHOD__ . ": NOT MODIFIED, $info", 'private' );
830  ini_set( 'zlib.output_compression', 0 );
831  $this->getRequest()->response()->statusHeader( 304 );
832  $this->sendCacheControl();
833  $this->disable();
834 
835  // Don't output a compressed blob when using ob_gzhandler;
836  // it's technically against HTTP spec and seems to confuse
837  // Firefox when the response gets split over two packets.
839 
840  return true;
841  }
842 
849  public function setLastModified( $timestamp ) {
850  $this->mLastModified = wfTimestamp( TS_RFC2822, $timestamp );
851  }
852 
861  public function setRobotPolicy( $policy ) {
862  $policy = Article::formatRobotPolicy( $policy );
863 
864  if ( isset( $policy['index'] ) ) {
865  $this->setIndexPolicy( $policy['index'] );
866  }
867  if ( isset( $policy['follow'] ) ) {
868  $this->setFollowPolicy( $policy['follow'] );
869  }
870  }
871 
879  public function setIndexPolicy( $policy ) {
880  $policy = trim( $policy );
881  if ( in_array( $policy, [ 'index', 'noindex' ] ) ) {
882  $this->mIndexPolicy = $policy;
883  }
884  }
885 
893  public function setFollowPolicy( $policy ) {
894  $policy = trim( $policy );
895  if ( in_array( $policy, [ 'follow', 'nofollow' ] ) ) {
896  $this->mFollowPolicy = $policy;
897  }
898  }
899 
906  public function setPageTitleActionText( $text ) {
907  $this->mPageTitleActionText = $text;
908  }
909 
915  public function getPageTitleActionText() {
917  }
918 
925  public function setHTMLTitle( $name ) {
926  if ( $name instanceof Message ) {
927  $this->mHTMLtitle = $name->setContext( $this->getContext() )->text();
928  } else {
929  $this->mHTMLtitle = $name;
930  }
931  }
932 
938  public function getHTMLTitle() {
939  return $this->mHTMLtitle;
940  }
941 
947  public function setRedirectedFrom( $t ) {
948  $this->mRedirectedFrom = $t;
949  }
950 
961  public function setPageTitle( $name ) {
962  if ( $name instanceof Message ) {
963  $name = $name->setContext( $this->getContext() )->text();
964  }
965 
966  # change "<script>foo&bar</script>" to "&lt;script&gt;foo&amp;bar&lt;/script&gt;"
967  # but leave "<i>foobar</i>" alone
969  $this->mPagetitle = $nameWithTags;
970 
971  # change "<i>foo&amp;bar</i>" to "foo&bar"
972  $this->setHTMLTitle(
973  $this->msg( 'pagetitle' )->rawParams( Sanitizer::stripAllTags( $nameWithTags ) )
974  ->inContentLanguage()
975  );
976  }
977 
983  public function getPageTitle() {
984  return $this->mPagetitle;
985  }
986 
992  public function setTitle( Title $t ) {
993  $this->getContext()->setTitle( $t );
994  }
995 
1001  public function setSubtitle( $str ) {
1002  $this->clearSubtitle();
1003  $this->addSubtitle( $str );
1004  }
1005 
1011  public function addSubtitle( $str ) {
1012  if ( $str instanceof Message ) {
1013  $this->mSubtitle[] = $str->setContext( $this->getContext() )->parse();
1014  } else {
1015  $this->mSubtitle[] = $str;
1016  }
1017  }
1018 
1027  public static function buildBacklinkSubtitle( Title $title, $query = [] ) {
1028  if ( $title->isRedirect() ) {
1029  $query['redirect'] = 'no';
1030  }
1031  return wfMessage( 'backlinksubtitle' )
1032  ->rawParams( Linker::link( $title, null, [], $query ) );
1033  }
1034 
1041  public function addBacklinkSubtitle( Title $title, $query = [] ) {
1042  $this->addSubtitle( self::buildBacklinkSubtitle( $title, $query ) );
1043  }
1044 
1048  public function clearSubtitle() {
1049  $this->mSubtitle = [];
1050  }
1051 
1057  public function getSubtitle() {
1058  return implode( "<br />\n\t\t\t\t", $this->mSubtitle );
1059  }
1060 
1065  public function setPrintable() {
1066  $this->mPrintable = true;
1067  }
1068 
1074  public function isPrintable() {
1075  return $this->mPrintable;
1076  }
1077 
1081  public function disable() {
1082  $this->mDoNothing = true;
1083  }
1084 
1090  public function isDisabled() {
1091  return $this->mDoNothing;
1092  }
1093 
1099  public function showNewSectionLink() {
1100  return $this->mNewSectionLink;
1101  }
1102 
1108  public function forceHideNewSectionLink() {
1110  }
1111 
1120  public function setSyndicated( $show = true ) {
1121  if ( $show ) {
1122  $this->setFeedAppendQuery( false );
1123  } else {
1124  $this->mFeedLinks = [];
1125  }
1126  }
1127 
1137  public function setFeedAppendQuery( $val ) {
1138  $this->mFeedLinks = [];
1139 
1140  foreach ( $this->getConfig()->get( 'AdvertisedFeedTypes' ) as $type ) {
1141  $query = "feed=$type";
1142  if ( is_string( $val ) ) {
1143  $query .= '&' . $val;
1144  }
1145  $this->mFeedLinks[$type] = $this->getTitle()->getLocalURL( $query );
1146  }
1147  }
1148 
1155  public function addFeedLink( $format, $href ) {
1156  if ( in_array( $format, $this->getConfig()->get( 'AdvertisedFeedTypes' ) ) ) {
1157  $this->mFeedLinks[$format] = $href;
1158  }
1159  }
1160 
1165  public function isSyndicated() {
1166  return count( $this->mFeedLinks ) > 0;
1167  }
1168 
1173  public function getSyndicationLinks() {
1174  return $this->mFeedLinks;
1175  }
1176 
1182  public function getFeedAppendQuery() {
1184  }
1185 
1193  public function setArticleFlag( $v ) {
1194  $this->mIsarticle = $v;
1195  if ( $v ) {
1196  $this->mIsArticleRelated = $v;
1197  }
1198  }
1199 
1206  public function isArticle() {
1207  return $this->mIsarticle;
1208  }
1209 
1216  public function setArticleRelated( $v ) {
1217  $this->mIsArticleRelated = $v;
1218  if ( !$v ) {
1219  $this->mIsarticle = false;
1220  }
1221  }
1222 
1228  public function isArticleRelated() {
1229  return $this->mIsArticleRelated;
1230  }
1231 
1238  public function addLanguageLinks( array $newLinkArray ) {
1239  $this->mLanguageLinks += $newLinkArray;
1240  }
1241 
1248  public function setLanguageLinks( array $newLinkArray ) {
1249  $this->mLanguageLinks = $newLinkArray;
1250  }
1251 
1257  public function getLanguageLinks() {
1258  return $this->mLanguageLinks;
1259  }
1260 
1266  public function addCategoryLinks( array $categories ) {
1268 
1269  if ( !is_array( $categories ) || count( $categories ) == 0 ) {
1270  return;
1271  }
1272 
1273  # Add the links to a LinkBatch
1274  $arr = [ NS_CATEGORY => $categories ];
1275  $lb = new LinkBatch;
1276  $lb->setArray( $arr );
1277 
1278  # Fetch existence plus the hiddencat property
1279  $dbr = wfGetDB( DB_SLAVE );
1280  $fields = [ 'page_id', 'page_namespace', 'page_title', 'page_len',
1281  'page_is_redirect', 'page_latest', 'pp_value' ];
1282 
1283  if ( $this->getConfig()->get( 'ContentHandlerUseDB' ) ) {
1284  $fields[] = 'page_content_model';
1285  }
1286  if ( $this->getConfig()->get( 'PageLanguageUseDB' ) ) {
1287  $fields[] = 'page_lang';
1288  }
1289 
1290  $res = $dbr->select( [ 'page', 'page_props' ],
1291  $fields,
1292  $lb->constructSet( 'page', $dbr ),
1293  __METHOD__,
1294  [],
1295  [ 'page_props' => [ 'LEFT JOIN', [
1296  'pp_propname' => 'hiddencat',
1297  'pp_page = page_id'
1298  ] ] ]
1299  );
1300 
1301  # Add the results to the link cache
1302  $lb->addResultToCache( LinkCache::singleton(), $res );
1303 
1304  # Set all the values to 'normal'.
1305  $categories = array_fill_keys( array_keys( $categories ), 'normal' );
1306 
1307  # Mark hidden categories
1308  foreach ( $res as $row ) {
1309  if ( isset( $row->pp_value ) ) {
1310  $categories[$row->page_title] = 'hidden';
1311  }
1312  }
1313 
1314  # Add the remaining categories to the skin
1315  if ( Hooks::run(
1316  'OutputPageMakeCategoryLinks',
1317  [ &$this, $categories, &$this->mCategoryLinks ] )
1318  ) {
1319  foreach ( $categories as $category => $type ) {
1320  // array keys will cast numeric category names to ints, so cast back to string
1321  $category = (string)$category;
1322  $origcategory = $category;
1323  $title = Title::makeTitleSafe( NS_CATEGORY, $category );
1324  if ( !$title ) {
1325  continue;
1326  }
1327  $wgContLang->findVariantLink( $category, $title, true );
1328  if ( $category != $origcategory && array_key_exists( $category, $categories ) ) {
1329  continue;
1330  }
1331  $text = $wgContLang->convertHtml( $title->getText() );
1332  $this->mCategories[] = $title->getText();
1333  $this->mCategoryLinks[$type][] = Linker::link( $title, $text );
1334  }
1335  }
1336  }
1337 
1343  public function setCategoryLinks( array $categories ) {
1344  $this->mCategoryLinks = [];
1345  $this->addCategoryLinks( $categories );
1346  }
1347 
1356  public function getCategoryLinks() {
1357  return $this->mCategoryLinks;
1358  }
1359 
1365  public function getCategories() {
1366  return $this->mCategories;
1367  }
1368 
1378  public function setIndicators( array $indicators ) {
1379  $this->mIndicators = $indicators + $this->mIndicators;
1380  // Keep ordered by key
1381  ksort( $this->mIndicators );
1382  }
1383 
1392  public function getIndicators() {
1393  return $this->mIndicators;
1394  }
1395 
1404  public function addHelpLink( $to, $overrideBaseUrl = false ) {
1405  $this->addModuleStyles( 'mediawiki.helplink' );
1406  $text = $this->msg( 'helppage-top-gethelp' )->escaped();
1407 
1408  if ( $overrideBaseUrl ) {
1409  $helpUrl = $to;
1410  } else {
1411  $toUrlencoded = wfUrlencode( str_replace( ' ', '_', $to ) );
1412  $helpUrl = "//www.mediawiki.org/wiki/Special:MyLanguage/$toUrlencoded";
1413  }
1414 
1416  'a',
1417  [
1418  'href' => $helpUrl,
1419  'target' => '_blank',
1420  'class' => 'mw-helplink',
1421  ],
1422  $text
1423  );
1424 
1425  $this->setIndicators( [ 'mw-helplink' => $link ] );
1426  }
1427 
1436  public function disallowUserJs() {
1437  $this->reduceAllowedModules(
1440  );
1441 
1442  // Site-wide styles are controlled by a config setting, see bug 71621
1443  // for background on why. User styles are never allowed.
1444  if ( $this->getConfig()->get( 'AllowSiteCSSOnRestrictedPages' ) ) {
1446  } else {
1448  }
1449  $this->reduceAllowedModules(
1451  $styleOrigin
1452  );
1453  }
1454 
1461  public function getAllowedModules( $type ) {
1463  return min( array_values( $this->mAllowedModules ) );
1464  } else {
1465  return isset( $this->mAllowedModules[$type] )
1466  ? $this->mAllowedModules[$type]
1468  }
1469  }
1470 
1480  public function reduceAllowedModules( $type, $level ) {
1481  $this->mAllowedModules[$type] = min( $this->getAllowedModules( $type ), $level );
1482  }
1483 
1489  public function prependHTML( $text ) {
1490  $this->mBodytext = $text . $this->mBodytext;
1491  }
1492 
1498  public function addHTML( $text ) {
1499  $this->mBodytext .= $text;
1500  }
1501 
1511  public function addElement( $element, array $attribs = [], $contents = '' ) {
1512  $this->addHTML( Html::element( $element, $attribs, $contents ) );
1513  }
1514 
1518  public function clearHTML() {
1519  $this->mBodytext = '';
1520  }
1521 
1527  public function getHTML() {
1528  return $this->mBodytext;
1529  }
1530 
1538  public function parserOptions( $options = null ) {
1539  if ( $options !== null && !empty( $options->isBogus ) ) {
1540  // Someone is trying to set a bogus pre-$wgUser PO. Check if it has
1541  // been changed somehow, and keep it if so.
1542  $anonPO = ParserOptions::newFromAnon();
1543  $anonPO->setEditSection( false );
1544  if ( !$options->matches( $anonPO ) ) {
1545  wfLogWarning( __METHOD__ . ': Setting a changed bogus ParserOptions: ' . wfGetAllCallers( 5 ) );
1546  $options->isBogus = false;
1547  }
1548  }
1549 
1550  if ( !$this->mParserOptions ) {
1551  if ( !$this->getContext()->getUser()->isSafeToLoad() ) {
1552  // $wgUser isn't unstubbable yet, so don't try to get a
1553  // ParserOptions for it. And don't cache this ParserOptions
1554  // either.
1556  $po->setEditSection( false );
1557  $po->isBogus = true;
1558  if ( $options !== null ) {
1559  $this->mParserOptions = empty( $options->isBogus ) ? $options : null;
1560  }
1561  return $po;
1562  }
1563 
1564  $this->mParserOptions = ParserOptions::newFromContext( $this->getContext() );
1565  $this->mParserOptions->setEditSection( false );
1566  }
1567 
1568  if ( $options !== null && !empty( $options->isBogus ) ) {
1569  // They're trying to restore the bogus pre-$wgUser PO. Do the right
1570  // thing.
1571  return wfSetVar( $this->mParserOptions, null, true );
1572  } else {
1573  return wfSetVar( $this->mParserOptions, $options );
1574  }
1575  }
1576 
1584  public function setRevisionId( $revid ) {
1585  $val = is_null( $revid ) ? null : intval( $revid );
1586  return wfSetVar( $this->mRevisionId, $val );
1587  }
1588 
1594  public function getRevisionId() {
1595  return $this->mRevisionId;
1596  }
1597 
1605  public function setRevisionTimestamp( $timestamp ) {
1606  return wfSetVar( $this->mRevisionTimestamp, $timestamp );
1607  }
1608 
1615  public function getRevisionTimestamp() {
1617  }
1618 
1625  public function setFileVersion( $file ) {
1626  $val = null;
1627  if ( $file instanceof File && $file->exists() ) {
1628  $val = [ 'time' => $file->getTimestamp(), 'sha1' => $file->getSha1() ];
1629  }
1630  return wfSetVar( $this->mFileVersion, $val, true );
1631  }
1632 
1638  public function getFileVersion() {
1639  return $this->mFileVersion;
1640  }
1641 
1648  public function getTemplateIds() {
1649  return $this->mTemplateIds;
1650  }
1651 
1658  public function getFileSearchOptions() {
1659  return $this->mImageTimeKeys;
1660  }
1661 
1671  public function addWikiText( $text, $linestart = true, $interface = true ) {
1672  $title = $this->getTitle(); // Work around E_STRICT
1673  if ( !$title ) {
1674  throw new MWException( 'Title is null' );
1675  }
1676  $this->addWikiTextTitle( $text, $title, $linestart, /*tidy*/false, $interface );
1677  }
1678 
1686  public function addWikiTextWithTitle( $text, &$title, $linestart = true ) {
1687  $this->addWikiTextTitle( $text, $title, $linestart );
1688  }
1689 
1697  function addWikiTextTitleTidy( $text, &$title, $linestart = true ) {
1698  $this->addWikiTextTitle( $text, $title, $linestart, true );
1699  }
1700 
1707  public function addWikiTextTidy( $text, $linestart = true ) {
1708  $title = $this->getTitle();
1709  $this->addWikiTextTitleTidy( $text, $title, $linestart );
1710  }
1711 
1722  public function addWikiTextTitle( $text, Title $title, $linestart,
1723  $tidy = false, $interface = false
1724  ) {
1725  global $wgParser;
1726 
1727  $popts = $this->parserOptions();
1728  $oldTidy = $popts->setTidy( $tidy );
1729  $popts->setInterfaceMessage( (bool)$interface );
1730 
1731  $parserOutput = $wgParser->getFreshParser()->parse(
1732  $text, $title, $popts,
1733  $linestart, true, $this->mRevisionId
1734  );
1735 
1736  $popts->setTidy( $oldTidy );
1737 
1738  $this->addParserOutput( $parserOutput );
1739 
1740  }
1741 
1749  wfDeprecated( __METHOD__, '1.24' );
1751  }
1752 
1762  $this->mLanguageLinks += $parserOutput->getLanguageLinks();
1763  $this->addCategoryLinks( $parserOutput->getCategories() );
1764  $this->setIndicators( $parserOutput->getIndicators() );
1765  $this->mNewSectionLink = $parserOutput->getNewSection();
1766  $this->mHideNewSectionLink = $parserOutput->getHideNewSection();
1767 
1768  if ( !$parserOutput->isCacheable() ) {
1769  $this->enableClientCache( false );
1770  }
1771  $this->mNoGallery = $parserOutput->getNoGallery();
1772  $this->mHeadItems = array_merge( $this->mHeadItems, $parserOutput->getHeadItems() );
1773  $this->addModules( $parserOutput->getModules() );
1774  $this->addModuleScripts( $parserOutput->getModuleScripts() );
1775  $this->addModuleStyles( $parserOutput->getModuleStyles() );
1776  $this->addJsConfigVars( $parserOutput->getJsConfigVars() );
1777  $this->mPreventClickjacking = $this->mPreventClickjacking
1778  || $parserOutput->preventClickjacking();
1779 
1780  // Template versioning...
1781  foreach ( (array)$parserOutput->getTemplateIds() as $ns => $dbks ) {
1782  if ( isset( $this->mTemplateIds[$ns] ) ) {
1783  $this->mTemplateIds[$ns] = $dbks + $this->mTemplateIds[$ns];
1784  } else {
1785  $this->mTemplateIds[$ns] = $dbks;
1786  }
1787  }
1788  // File versioning...
1789  foreach ( (array)$parserOutput->getFileSearchOptions() as $dbk => $data ) {
1790  $this->mImageTimeKeys[$dbk] = $data;
1791  }
1792 
1793  // Hooks registered in the object
1794  $parserOutputHooks = $this->getConfig()->get( 'ParserOutputHooks' );
1795  foreach ( $parserOutput->getOutputHooks() as $hookInfo ) {
1796  list( $hookName, $data ) = $hookInfo;
1797  if ( isset( $parserOutputHooks[$hookName] ) ) {
1798  call_user_func( $parserOutputHooks[$hookName], $this, $parserOutput, $data );
1799  }
1800  }
1801 
1802  // enable OOUI if requested via ParserOutput
1803  if ( $parserOutput->getEnableOOUI() ) {
1804  $this->enableOOUI();
1805  }
1806 
1807  // Link flags are ignored for now, but may in the future be
1808  // used to mark individual language links.
1809  $linkFlags = [];
1810  Hooks::run( 'LanguageLinks', [ $this->getTitle(), &$this->mLanguageLinks, &$linkFlags ] );
1811  Hooks::run( 'OutputPageParserOutput', [ &$this, $parserOutput ] );
1812  }
1813 
1823 
1824  $this->addModules( $parserOutput->getModules() );
1825  $this->addModuleScripts( $parserOutput->getModuleScripts() );
1826  $this->addModuleStyles( $parserOutput->getModuleStyles() );
1827 
1828  $this->addJsConfigVars( $parserOutput->getJsConfigVars() );
1829  }
1830 
1837  public function addParserOutputText( $parserOutput ) {
1838  $text = $parserOutput->getText();
1839  Hooks::run( 'OutputPageBeforeHTML', [ &$this, &$text ] );
1840  $this->addHTML( $text );
1841  }
1842 
1850  $parserOutput->setTOCEnabled( $this->mEnableTOC );
1851 
1852  // Touch section edit links only if not previously disabled
1853  if ( $parserOutput->getEditSectionTokens() ) {
1854  $parserOutput->setEditSectionTokens( $this->mEnableSectionEditLinks );
1855  }
1856 
1858  }
1859 
1865  public function addTemplate( &$template ) {
1866  $this->addHTML( $template->getHTML() );
1867  }
1868 
1881  public function parse( $text, $linestart = true, $interface = false, $language = null ) {
1882  global $wgParser;
1883 
1884  if ( is_null( $this->getTitle() ) ) {
1885  throw new MWException( 'Empty $mTitle in ' . __METHOD__ );
1886  }
1887 
1888  $popts = $this->parserOptions();
1889  if ( $interface ) {
1890  $popts->setInterfaceMessage( true );
1891  }
1892  if ( $language !== null ) {
1893  $oldLang = $popts->setTargetLanguage( $language );
1894  }
1895 
1896  $parserOutput = $wgParser->getFreshParser()->parse(
1897  $text, $this->getTitle(), $popts,
1898  $linestart, true, $this->mRevisionId
1899  );
1900 
1901  if ( $interface ) {
1902  $popts->setInterfaceMessage( false );
1903  }
1904  if ( $language !== null ) {
1905  $popts->setTargetLanguage( $oldLang );
1906  }
1907 
1908  return $parserOutput->getText();
1909  }
1910 
1921  public function parseInline( $text, $linestart = true, $interface = false ) {
1922  $parsed = $this->parse( $text, $linestart, $interface );
1923  return Parser::stripOuterParagraph( $parsed );
1924  }
1925 
1930  public function setSquidMaxage( $maxage ) {
1931  $this->setCdnMaxage( $maxage );
1932  }
1933 
1939  public function setCdnMaxage( $maxage ) {
1940  $this->mCdnMaxage = min( $maxage, $this->mCdnMaxageLimit );
1941  }
1942 
1949  public function lowerCdnMaxage( $maxage ) {
1950  $this->mCdnMaxageLimit = min( $maxage, $this->mCdnMaxageLimit );
1951  $this->setCdnMaxage( $this->mCdnMaxage );
1952  }
1953 
1961  public function enableClientCache( $state ) {
1962  return wfSetVar( $this->mEnableClientCache, $state );
1963  }
1964 
1970  function getCacheVaryCookies() {
1971  static $cookies;
1972  if ( $cookies === null ) {
1973  $config = $this->getConfig();
1974  $cookies = array_merge(
1975  SessionManager::singleton()->getVaryCookies(),
1976  [
1977  'forceHTTPS',
1978  ],
1979  $config->get( 'CacheVaryCookies' )
1980  );
1981  Hooks::run( 'GetCacheVaryCookies', [ $this, &$cookies ] );
1982  }
1983  return $cookies;
1984  }
1985 
1993  $request = $this->getRequest();
1994  foreach ( $this->getCacheVaryCookies() as $cookieName ) {
1995  if ( $request->getCookie( $cookieName, '', '' ) !== '' ) {
1996  wfDebug( __METHOD__ . ": found $cookieName\n" );
1997  return true;
1998  }
1999  }
2000  wfDebug( __METHOD__ . ": no cache-varying cookies found\n" );
2001  return false;
2002  }
2003 
2012  public function addVaryHeader( $header, array $option = null ) {
2013  if ( !array_key_exists( $header, $this->mVaryHeader ) ) {
2014  $this->mVaryHeader[$header] = [];
2015  }
2016  if ( !is_array( $option ) ) {
2017  $option = [];
2018  }
2019  $this->mVaryHeader[$header] = array_unique( array_merge( $this->mVaryHeader[$header], $option ) );
2020  }
2021 
2028  public function getVaryHeader() {
2029  // If we vary on cookies, let's make sure it's always included here too.
2030  if ( $this->getCacheVaryCookies() ) {
2031  $this->addVaryHeader( 'Cookie' );
2032  }
2033 
2034  foreach ( SessionManager::singleton()->getVaryHeaders() as $header => $options ) {
2035  $this->addVaryHeader( $header, $options );
2036  }
2037  return 'Vary: ' . implode( ', ', array_keys( $this->mVaryHeader ) );
2038  }
2039 
2045  public function getKeyHeader() {
2046  $cvCookies = $this->getCacheVaryCookies();
2047 
2048  $cookiesOption = [];
2049  foreach ( $cvCookies as $cookieName ) {
2050  $cookiesOption[] = 'param=' . $cookieName;
2051  }
2052  $this->addVaryHeader( 'Cookie', $cookiesOption );
2053 
2054  foreach ( SessionManager::singleton()->getVaryHeaders() as $header => $options ) {
2055  $this->addVaryHeader( $header, $options );
2056  }
2057 
2058  $headers = [];
2059  foreach ( $this->mVaryHeader as $header => $option ) {
2060  $newheader = $header;
2061  if ( is_array( $option ) && count( $option ) > 0 ) {
2062  $newheader .= ';' . implode( ';', $option );
2063  }
2064  $headers[] = $newheader;
2065  }
2066  $key = 'Key: ' . implode( ',', $headers );
2067 
2068  return $key;
2069  }
2070 
2079  function addAcceptLanguage() {
2080  $title = $this->getTitle();
2081  if ( !$title instanceof Title ) {
2082  return;
2083  }
2084 
2085  $lang = $title->getPageLanguage();
2086  if ( !$this->getRequest()->getCheck( 'variant' ) && $lang->hasVariants() ) {
2087  $variants = $lang->getVariants();
2088  $aloption = [];
2089  foreach ( $variants as $variant ) {
2090  if ( $variant === $lang->getCode() ) {
2091  continue;
2092  } else {
2093  $aloption[] = 'substr=' . $variant;
2094 
2095  // IE and some other browsers use BCP 47 standards in
2096  // their Accept-Language header, like "zh-CN" or "zh-Hant".
2097  // We should handle these too.
2098  $variantBCP47 = wfBCP47( $variant );
2099  if ( $variantBCP47 !== $variant ) {
2100  $aloption[] = 'substr=' . $variantBCP47;
2101  }
2102  }
2103  }
2104  $this->addVaryHeader( 'Accept-Language', $aloption );
2105  }
2106  }
2107 
2118  public function preventClickjacking( $enable = true ) {
2119  $this->mPreventClickjacking = $enable;
2120  }
2121 
2127  public function allowClickjacking() {
2128  $this->mPreventClickjacking = false;
2129  }
2130 
2137  public function getPreventClickjacking() {
2139  }
2140 
2148  public function getFrameOptions() {
2149  $config = $this->getConfig();
2150  if ( $config->get( 'BreakFrames' ) ) {
2151  return 'DENY';
2152  } elseif ( $this->mPreventClickjacking && $config->get( 'EditPageFrameOptions' ) ) {
2153  return $config->get( 'EditPageFrameOptions' );
2154  }
2155  return false;
2156  }
2157 
2161  public function sendCacheControl() {
2162  $response = $this->getRequest()->response();
2163  $config = $this->getConfig();
2164  if ( $config->get( 'UseETag' ) && $this->mETag ) {
2165  $response->header( "ETag: $this->mETag" );
2166  }
2167 
2168  $this->addVaryHeader( 'Cookie' );
2169  $this->addAcceptLanguage();
2170 
2171  # don't serve compressed data to clients who can't handle it
2172  # maintain different caches for logged-in users and non-logged in ones
2173  $response->header( $this->getVaryHeader() );
2174 
2175  if ( $config->get( 'UseKeyHeader' ) ) {
2176  $response->header( $this->getKeyHeader() );
2177  }
2178 
2179  if ( $this->mEnableClientCache ) {
2180  if (
2181  $config->get( 'UseSquid' ) &&
2182  !$response->hasCookies() &&
2183  !SessionManager::getGlobalSession()->isPersistent() &&
2184  !$this->isPrintable() &&
2185  $this->mCdnMaxage != 0 &&
2186  !$this->haveCacheVaryCookies()
2187  ) {
2188  if ( $config->get( 'UseESI' ) ) {
2189  # We'll purge the proxy cache explicitly, but require end user agents
2190  # to revalidate against the proxy on each visit.
2191  # Surrogate-Control controls our CDN, Cache-Control downstream caches
2192  wfDebug( __METHOD__ . ": proxy caching with ESI; {$this->mLastModified} **", 'private' );
2193  # start with a shorter timeout for initial testing
2194  # header( 'Surrogate-Control: max-age=2678400+2678400, content="ESI/1.0"');
2195  $response->header( 'Surrogate-Control: max-age=' . $config->get( 'SquidMaxage' )
2196  . '+' . $this->mCdnMaxage . ', content="ESI/1.0"' );
2197  $response->header( 'Cache-Control: s-maxage=0, must-revalidate, max-age=0' );
2198  } else {
2199  # We'll purge the proxy cache for anons explicitly, but require end user agents
2200  # to revalidate against the proxy on each visit.
2201  # IMPORTANT! The CDN needs to replace the Cache-Control header with
2202  # Cache-Control: s-maxage=0, must-revalidate, max-age=0
2203  wfDebug( __METHOD__ . ": local proxy caching; {$this->mLastModified} **", 'private' );
2204  # start with a shorter timeout for initial testing
2205  # header( "Cache-Control: s-maxage=2678400, must-revalidate, max-age=0" );
2206  $response->header( 'Cache-Control: s-maxage=' . $this->mCdnMaxage
2207  . ', must-revalidate, max-age=0' );
2208  }
2209  } else {
2210  # We do want clients to cache if they can, but they *must* check for updates
2211  # on revisiting the page.
2212  wfDebug( __METHOD__ . ": private caching; {$this->mLastModified} **", 'private' );
2213  $response->header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', 0 ) . ' GMT' );
2214  $response->header( "Cache-Control: private, must-revalidate, max-age=0" );
2215  }
2216  if ( $this->mLastModified ) {
2217  $response->header( "Last-Modified: {$this->mLastModified}" );
2218  }
2219  } else {
2220  wfDebug( __METHOD__ . ": no caching **", 'private' );
2221 
2222  # In general, the absence of a last modified header should be enough to prevent
2223  # the client from using its cache. We send a few other things just to make sure.
2224  $response->header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', 0 ) . ' GMT' );
2225  $response->header( 'Cache-Control: no-cache, no-store, max-age=0, must-revalidate' );
2226  $response->header( 'Pragma: no-cache' );
2227  }
2228  }
2229 
2234  public function output() {
2235  if ( $this->mDoNothing ) {
2236  return;
2237  }
2238 
2239  $response = $this->getRequest()->response();
2240  $config = $this->getConfig();
2241 
2242  if ( $this->mRedirect != '' ) {
2243  # Standards require redirect URLs to be absolute
2244  $this->mRedirect = wfExpandUrl( $this->mRedirect, PROTO_CURRENT );
2245 
2246  $redirect = $this->mRedirect;
2248 
2249  if ( Hooks::run( "BeforePageRedirect", [ $this, &$redirect, &$code ] ) ) {
2250  if ( $code == '301' || $code == '303' ) {
2251  if ( !$config->get( 'DebugRedirects' ) ) {
2252  $response->statusHeader( $code );
2253  }
2254  $this->mLastModified = wfTimestamp( TS_RFC2822 );
2255  }
2256  if ( $config->get( 'VaryOnXFP' ) ) {
2257  $this->addVaryHeader( 'X-Forwarded-Proto' );
2258  }
2259  $this->sendCacheControl();
2260 
2261  $response->header( "Content-Type: text/html; charset=utf-8" );
2262  if ( $config->get( 'DebugRedirects' ) ) {
2263  $url = htmlspecialchars( $redirect );
2264  print "<html>\n<head>\n<title>Redirect</title>\n</head>\n<body>\n";
2265  print "<p>Location: <a href=\"$url\">$url</a></p>\n";
2266  print "</body>\n</html>\n";
2267  } else {
2268  $response->header( 'Location: ' . $redirect );
2269  }
2270  }
2271 
2272  return;
2273  } elseif ( $this->mStatusCode ) {
2274  $response->statusHeader( $this->mStatusCode );
2275  }
2276 
2277  # Buffer output; final headers may depend on later processing
2278  ob_start();
2279 
2280  $response->header( 'Content-type: ' . $config->get( 'MimeType' ) . '; charset=UTF-8' );
2281  $response->header( 'Content-language: ' . $config->get( 'LanguageCode' ) );
2282 
2283  // Avoid Internet Explorer "compatibility view" in IE 8-10, so that
2284  // jQuery etc. can work correctly.
2285  $response->header( 'X-UA-Compatible: IE=Edge' );
2286 
2287  // Prevent framing, if requested
2288  $frameOptions = $this->getFrameOptions();
2289  if ( $frameOptions ) {
2290  $response->header( "X-Frame-Options: $frameOptions" );
2291  }
2292 
2293  if ( $this->mArticleBodyOnly ) {
2294  echo $this->mBodytext;
2295  } else {
2296  $sk = $this->getSkin();
2297  // add skin specific modules
2298  $modules = $sk->getDefaultModules();
2299 
2300  // Enforce various default modules for all skins
2301  $coreModules = [
2302  // Keep this list as small as possible
2303  'site',
2304  'mediawiki.page.startup',
2305  'mediawiki.user',
2306  ];
2307 
2308  // Support for high-density display images if enabled
2309  if ( $config->get( 'ResponsiveImages' ) ) {
2310  $coreModules[] = 'mediawiki.hidpi';
2311  }
2312 
2313  $this->addModules( $coreModules );
2314  foreach ( $modules as $group ) {
2315  $this->addModules( $group );
2316  }
2317  MWDebug::addModules( $this );
2318 
2319  // Hook that allows last minute changes to the output page, e.g.
2320  // adding of CSS or Javascript by extensions.
2321  Hooks::run( 'BeforePageDisplay', [ &$this, &$sk ] );
2322 
2323  try {
2324  $sk->outputPage();
2325  } catch ( Exception $e ) {
2326  ob_end_clean(); // bug T129657
2327  throw $e;
2328  }
2329  }
2330 
2331  try {
2332  // This hook allows last minute changes to final overall output by modifying output buffer
2333  Hooks::run( 'AfterFinalPageOutput', [ $this ] );
2334  } catch ( Exception $e ) {
2335  ob_end_clean(); // bug T129657
2336  throw $e;
2337  }
2338 
2339  $this->sendCacheControl();
2340 
2341  ob_end_flush();
2342 
2343  }
2344 
2355  public function prepareErrorPage( $pageTitle, $htmlTitle = false ) {
2356  $this->setPageTitle( $pageTitle );
2357  if ( $htmlTitle !== false ) {
2358  $this->setHTMLTitle( $htmlTitle );
2359  }
2360  $this->setRobotPolicy( 'noindex,nofollow' );
2361  $this->setArticleRelated( false );
2362  $this->enableClientCache( false );
2363  $this->mRedirect = '';
2364  $this->clearSubtitle();
2365  $this->clearHTML();
2366  }
2367 
2380  public function showErrorPage( $title, $msg, $params = [] ) {
2381  if ( !$title instanceof Message ) {
2382  $title = $this->msg( $title );
2383  }
2384 
2385  $this->prepareErrorPage( $title );
2386 
2387  if ( $msg instanceof Message ) {
2388  if ( $params !== [] ) {
2389  trigger_error( 'Argument ignored: $params. The message parameters argument '
2390  . 'is discarded when the $msg argument is a Message object instead of '
2391  . 'a string.', E_USER_NOTICE );
2392  }
2393  $this->addHTML( $msg->parseAsBlock() );
2394  } else {
2395  $this->addWikiMsgArray( $msg, $params );
2396  }
2397 
2398  $this->returnToMain();
2399  }
2400 
2407  public function showPermissionsErrorPage( array $errors, $action = null ) {
2408  // For some action (read, edit, create and upload), display a "login to do this action"
2409  // error if all of the following conditions are met:
2410  // 1. the user is not logged in
2411  // 2. the only error is insufficient permissions (i.e. no block or something else)
2412  // 3. the error can be avoided simply by logging in
2413  if ( in_array( $action, [ 'read', 'edit', 'createpage', 'createtalk', 'upload' ] )
2414  && $this->getUser()->isAnon() && count( $errors ) == 1 && isset( $errors[0][0] )
2415  && ( $errors[0][0] == 'badaccess-groups' || $errors[0][0] == 'badaccess-group0' )
2416  && ( User::groupHasPermission( 'user', $action )
2417  || User::groupHasPermission( 'autoconfirmed', $action ) )
2418  ) {
2419  $displayReturnto = null;
2420 
2421  # Due to bug 32276, if a user does not have read permissions,
2422  # $this->getTitle() will just give Special:Badtitle, which is
2423  # not especially useful as a returnto parameter. Use the title
2424  # from the request instead, if there was one.
2425  $request = $this->getRequest();
2426  $returnto = Title::newFromText( $request->getVal( 'title', '' ) );
2427  if ( $action == 'edit' ) {
2428  $msg = 'whitelistedittext';
2429  $displayReturnto = $returnto;
2430  } elseif ( $action == 'createpage' || $action == 'createtalk' ) {
2431  $msg = 'nocreatetext';
2432  } elseif ( $action == 'upload' ) {
2433  $msg = 'uploadnologintext';
2434  } else { # Read
2435  $msg = 'loginreqpagetext';
2436  $displayReturnto = Title::newMainPage();
2437  }
2438 
2439  $query = [];
2440 
2441  if ( $returnto ) {
2442  $query['returnto'] = $returnto->getPrefixedText();
2443 
2444  if ( !$request->wasPosted() ) {
2445  $returntoquery = $request->getValues();
2446  unset( $returntoquery['title'] );
2447  unset( $returntoquery['returnto'] );
2448  unset( $returntoquery['returntoquery'] );
2449  $query['returntoquery'] = wfArrayToCgi( $returntoquery );
2450  }
2451  }
2452  $loginLink = Linker::linkKnown(
2453  SpecialPage::getTitleFor( 'Userlogin' ),
2454  $this->msg( 'loginreqlink' )->escaped(),
2455  [],
2456  $query
2457  );
2458 
2459  $this->prepareErrorPage( $this->msg( 'loginreqtitle' ) );
2460  $this->addHTML( $this->msg( $msg )->rawParams( $loginLink )->parse() );
2461 
2462  # Don't return to a page the user can't read otherwise
2463  # we'll end up in a pointless loop
2464  if ( $displayReturnto && $displayReturnto->userCan( 'read', $this->getUser() ) ) {
2465  $this->returnToMain( null, $displayReturnto );
2466  }
2467  } else {
2468  $this->prepareErrorPage( $this->msg( 'permissionserrors' ) );
2469  $this->addWikiText( $this->formatPermissionsErrorMessage( $errors, $action ) );
2470  }
2471  }
2472 
2479  public function versionRequired( $version ) {
2480  $this->prepareErrorPage( $this->msg( 'versionrequired', $version ) );
2481 
2482  $this->addWikiMsg( 'versionrequiredtext', $version );
2483  $this->returnToMain();
2484  }
2485 
2493  public function formatPermissionsErrorMessage( array $errors, $action = null ) {
2494  if ( $action == null ) {
2495  $text = $this->msg( 'permissionserrorstext', count( $errors ) )->plain() . "\n\n";
2496  } else {
2497  $action_desc = $this->msg( "action-$action" )->plain();
2498  $text = $this->msg(
2499  'permissionserrorstext-withaction',
2500  count( $errors ),
2501  $action_desc
2502  )->plain() . "\n\n";
2503  }
2504 
2505  if ( count( $errors ) > 1 ) {
2506  $text .= '<ul class="permissions-errors">' . "\n";
2507 
2508  foreach ( $errors as $error ) {
2509  $text .= '<li>';
2510  $text .= call_user_func_array( [ $this, 'msg' ], $error )->plain();
2511  $text .= "</li>\n";
2512  }
2513  $text .= '</ul>';
2514  } else {
2515  $text .= "<div class=\"permissions-errors\">\n" .
2516  call_user_func_array( [ $this, 'msg' ], reset( $errors ) )->plain() .
2517  "\n</div>";
2518  }
2519 
2520  return $text;
2521  }
2522 
2534  public function readOnlyPage() {
2535  if ( func_num_args() > 0 ) {
2536  throw new MWException( __METHOD__ . ' no longer accepts arguments since 1.25.' );
2537  }
2538 
2539  throw new ReadOnlyError;
2540  }
2541 
2548  public function rateLimited() {
2549  wfDeprecated( __METHOD__, '1.25' );
2550  throw new ThrottledError;
2551  }
2552 
2562  public function showLagWarning( $lag ) {
2563  $config = $this->getConfig();
2564  if ( $lag >= $config->get( 'SlaveLagWarning' ) ) {
2565  $message = $lag < $config->get( 'SlaveLagCritical' )
2566  ? 'lag-warn-normal'
2567  : 'lag-warn-high';
2568  $wrap = Html::rawElement( 'div', [ 'class' => "mw-{$message}" ], "\n$1\n" );
2569  $this->wrapWikiMsg( "$wrap\n", [ $message, $this->getLanguage()->formatNum( $lag ) ] );
2570  }
2571  }
2572 
2573  public function showFatalError( $message ) {
2574  $this->prepareErrorPage( $this->msg( 'internalerror' ) );
2575 
2576  $this->addHTML( $message );
2577  }
2578 
2579  public function showUnexpectedValueError( $name, $val ) {
2580  $this->showFatalError( $this->msg( 'unexpected', $name, $val )->text() );
2581  }
2582 
2583  public function showFileCopyError( $old, $new ) {
2584  $this->showFatalError( $this->msg( 'filecopyerror', $old, $new )->text() );
2585  }
2586 
2587  public function showFileRenameError( $old, $new ) {
2588  $this->showFatalError( $this->msg( 'filerenameerror', $old, $new )->text() );
2589  }
2590 
2591  public function showFileDeleteError( $name ) {
2592  $this->showFatalError( $this->msg( 'filedeleteerror', $name )->text() );
2593  }
2594 
2595  public function showFileNotFoundError( $name ) {
2596  $this->showFatalError( $this->msg( 'filenotfound', $name )->text() );
2597  }
2598 
2607  public function addReturnTo( $title, array $query = [], $text = null, $options = [] ) {
2608  $link = $this->msg( 'returnto' )->rawParams(
2609  Linker::link( $title, $text, [], $query, $options ) )->escaped();
2610  $this->addHTML( "<p id=\"mw-returnto\">{$link}</p>\n" );
2611  }
2612 
2621  public function returnToMain( $unused = null, $returnto = null, $returntoquery = null ) {
2622  if ( $returnto == null ) {
2623  $returnto = $this->getRequest()->getText( 'returnto' );
2624  }
2625 
2626  if ( $returntoquery == null ) {
2627  $returntoquery = $this->getRequest()->getText( 'returntoquery' );
2628  }
2629 
2630  if ( $returnto === '' ) {
2631  $returnto = Title::newMainPage();
2632  }
2633 
2634  if ( is_object( $returnto ) ) {
2635  $titleObj = $returnto;
2636  } else {
2637  $titleObj = Title::newFromText( $returnto );
2638  }
2639  if ( !is_object( $titleObj ) ) {
2640  $titleObj = Title::newMainPage();
2641  }
2642 
2643  $this->addReturnTo( $titleObj, wfCgiToArray( $returntoquery ) );
2644  }
2645 
2651  public function headElement( Skin $sk, $includeStyle = true ) {
2653 
2654  $userdir = $this->getLanguage()->getDir();
2655  $sitedir = $wgContLang->getDir();
2656 
2658 
2659  if ( $this->getHTMLTitle() == '' ) {
2660  $this->setHTMLTitle( $this->msg( 'pagetitle', $this->getPageTitle() )->inContentLanguage() );
2661  }
2662 
2663  $openHead = Html::openElement( 'head' );
2664  if ( $openHead ) {
2665  # Don't bother with the newline if $head == ''
2666  $ret .= "$openHead\n";
2667  }
2668 
2669  if ( !Html::isXmlMimeType( $this->getConfig()->get( 'MimeType' ) ) ) {
2670  // Add <meta charset="UTF-8">
2671  // This should be before <title> since it defines the charset used by
2672  // text including the text inside <title>.
2673  // The spec recommends defining XHTML5's charset using the XML declaration
2674  // instead of meta.
2675  // Our XML declaration is output by Html::htmlHeader.
2676  // http://www.whatwg.org/html/semantics.html#attr-meta-http-equiv-content-type
2677  // http://www.whatwg.org/html/semantics.html#charset
2678  $ret .= Html::element( 'meta', [ 'charset' => 'UTF-8' ] ) . "\n";
2679  }
2680 
2681  $ret .= Html::element( 'title', null, $this->getHTMLTitle() ) . "\n";
2682  $ret .= $this->getInlineHeadScripts() . "\n";
2683  $ret .= $this->buildCssLinks() . "\n";
2684  $ret .= $this->getExternalHeadScripts() . "\n";
2685 
2686  foreach ( $this->getHeadLinksArray() as $item ) {
2687  $ret .= $item . "\n";
2688  }
2689 
2690  foreach ( $this->mHeadItems as $item ) {
2691  $ret .= $item . "\n";
2692  }
2693 
2694  $closeHead = Html::closeElement( 'head' );
2695  if ( $closeHead ) {
2696  $ret .= "$closeHead\n";
2697  }
2698 
2699  $bodyClasses = [];
2700  $bodyClasses[] = 'mediawiki';
2701 
2702  # Classes for LTR/RTL directionality support
2703  $bodyClasses[] = $userdir;
2704  $bodyClasses[] = "sitedir-$sitedir";
2705 
2706  if ( $this->getLanguage()->capitalizeAllNouns() ) {
2707  # A <body> class is probably not the best way to do this . . .
2708  $bodyClasses[] = 'capitalize-all-nouns';
2709  }
2710 
2711  $bodyClasses[] = $sk->getPageClasses( $this->getTitle() );
2712  $bodyClasses[] = 'skin-' . Sanitizer::escapeClass( $sk->getSkinName() );
2713  $bodyClasses[] =
2714  'action-' . Sanitizer::escapeClass( Action::getActionName( $this->getContext() ) );
2715 
2716  $bodyAttrs = [];
2717  // While the implode() is not strictly needed, it's used for backwards compatibility
2718  // (this used to be built as a string and hooks likely still expect that).
2719  $bodyAttrs['class'] = implode( ' ', $bodyClasses );
2720 
2721  // Allow skins and extensions to add body attributes they need
2722  $sk->addToBodyAttributes( $this, $bodyAttrs );
2723  Hooks::run( 'OutputPageBodyAttributes', [ $this, $sk, &$bodyAttrs ] );
2724 
2725  $ret .= Html::openElement( 'body', $bodyAttrs ) . "\n";
2726 
2727  return $ret;
2728  }
2729 
2735  public function getResourceLoader() {
2736  if ( is_null( $this->mResourceLoader ) ) {
2737  $this->mResourceLoader = new ResourceLoader(
2738  $this->getConfig(),
2739  LoggerFactory::getInstance( 'resourceloader' )
2740  );
2741  }
2742  return $this->mResourceLoader;
2743  }
2744 
2755  public function makeResourceLoaderLink( $modules, $only, array $extraQuery = [] ) {
2756  $modules = (array)$modules;
2757 
2758  $links = [
2759  // List of html strings
2760  'html' => [],
2761  // Associative array of module names and their states
2762  'states' => [],
2763  ];
2764 
2765  if ( !count( $modules ) ) {
2766  return $links;
2767  }
2768 
2769  if ( count( $modules ) > 1 ) {
2770  // Remove duplicate module requests
2771  $modules = array_unique( $modules );
2772  // Sort module names so requests are more uniform
2773  sort( $modules );
2774 
2775  if ( ResourceLoader::inDebugMode() ) {
2776  // Recursively call us for every item
2777  foreach ( $modules as $name ) {
2778  $link = $this->makeResourceLoaderLink( $name, $only, $extraQuery );
2779  $links['html'] = array_merge( $links['html'], $link['html'] );
2780  $links['states'] += $link['states'];
2781  }
2782  return $links;
2783  }
2784  }
2785 
2786  if ( !is_null( $this->mTarget ) ) {
2787  $extraQuery['target'] = $this->mTarget;
2788  }
2789 
2790  // Create keyed-by-source and then keyed-by-group list of module objects from modules list
2791  $sortedModules = [];
2793  foreach ( $modules as $name ) {
2794  $module = $resourceLoader->getModule( $name );
2795  # Check that we're allowed to include this module on this page
2796  if ( !$module
2797  || ( $module->getOrigin() > $this->getAllowedModules( ResourceLoaderModule::TYPE_SCRIPTS )
2799  || ( $module->getOrigin() > $this->getAllowedModules( ResourceLoaderModule::TYPE_STYLES )
2800  && $only == ResourceLoaderModule::TYPE_STYLES )
2801  || ( $module->getOrigin() > $this->getAllowedModules( ResourceLoaderModule::TYPE_COMBINED )
2803  || ( $this->mTarget && !in_array( $this->mTarget, $module->getTargets() ) )
2804  ) {
2805  continue;
2806  }
2807 
2808  $sortedModules[$module->getSource()][$module->getGroup()][$name] = $module;
2809  }
2810 
2811  foreach ( $sortedModules as $source => $groups ) {
2812  foreach ( $groups as $group => $grpModules ) {
2813  // Special handling for user-specific groups
2814  $user = null;
2815  if ( ( $group === 'user' || $group === 'private' ) && $this->getUser()->isLoggedIn() ) {
2816  $user = $this->getUser()->getName();
2817  }
2818 
2819  // Create a fake request based on the one we are about to make so modules return
2820  // correct timestamp and emptiness data
2822  [], // modules; not determined yet
2823  $this->getLanguage()->getCode(),
2824  $this->getSkin()->getSkinName(),
2825  $user,
2826  null, // version; not determined yet
2828  $only === ResourceLoaderModule::TYPE_COMBINED ? null : $only,
2829  $this->isPrintable(),
2830  $this->getRequest()->getBool( 'handheld' ),
2831  $extraQuery
2832  );
2834 
2835  // Extract modules that know they're empty and see if we have one or more
2836  // raw modules
2837  $isRaw = false;
2838  foreach ( $grpModules as $key => $module ) {
2839  // Inline empty modules: since they're empty, just mark them as 'ready' (bug 46857)
2840  // If we're only getting the styles, we don't need to do anything for empty modules.
2841  if ( $module->isKnownEmpty( $context ) ) {
2842  unset( $grpModules[$key] );
2843  if ( $only !== ResourceLoaderModule::TYPE_STYLES ) {
2844  $links['states'][$key] = 'ready';
2845  }
2846  }
2847 
2848  $isRaw |= $module->isRaw();
2849  }
2850 
2851  // If there are no non-empty modules, skip this group
2852  if ( count( $grpModules ) === 0 ) {
2853  continue;
2854  }
2855 
2856  // Inline private modules. These can't be loaded through load.php for security
2857  // reasons, see bug 34907. Note that these modules should be loaded from
2858  // getExternalHeadScripts() before the first loader call. Otherwise other modules can't
2859  // properly use them as dependencies (bug 30914)
2860  if ( $group === 'private' ) {
2861  if ( $only == ResourceLoaderModule::TYPE_STYLES ) {
2862  $links['html'][] = Html::inlineStyle(
2863  $resourceLoader->makeModuleResponse( $context, $grpModules )
2864  );
2865  } else {
2866  $links['html'][] = ResourceLoader::makeInlineScript(
2867  $resourceLoader->makeModuleResponse( $context, $grpModules )
2868  );
2869  }
2870  continue;
2871  }
2872 
2873  // Special handling for the user group; because users might change their stuff
2874  // on-wiki like user pages, or user preferences; we need to find the highest
2875  // timestamp of these user-changeable modules so we can ensure cache misses on change
2876  // This should NOT be done for the site group (bug 27564) because anons get that too
2877  // and we shouldn't be putting timestamps in CDN-cached HTML
2878  $version = null;
2879  if ( $group === 'user' ) {
2880  $query['version'] = $resourceLoader->getCombinedVersion( $context, array_keys( $grpModules ) );
2881  }
2882 
2883  $query['modules'] = ResourceLoader::makePackedModulesString( array_keys( $grpModules ) );
2884  $moduleContext = new ResourceLoaderContext( $resourceLoader, new FauxRequest( $query ) );
2885  $url = $resourceLoader->createLoaderURL( $source, $moduleContext, $extraQuery );
2886 
2887  // Automatically select style/script elements
2888  if ( $only === ResourceLoaderModule::TYPE_STYLES ) {
2889  $link = Html::linkedStyle( $url );
2890  } else {
2891  if ( $context->getRaw() || $isRaw ) {
2892  // Startup module can't load itself, needs to use <script> instead of mw.loader.load
2893  $link = Html::element( 'script', [
2894  // In SpecialJavaScriptTest, QUnit must load synchronous
2895  'async' => !isset( $extraQuery['sync'] ),
2896  'src' => $url
2897  ] );
2898  } else {
2900  Xml::encodeJsCall( 'mw.loader.load', [ $url ] )
2901  );
2902  }
2903 
2904  // For modules requested directly in the html via <script> or mw.loader.load
2905  // tell mw.loader they are being loading to prevent duplicate requests.
2906  foreach ( $grpModules as $key => $module ) {
2907  // Don't output state=loading for the startup module.
2908  if ( $key !== 'startup' ) {
2909  $links['states'][$key] = 'loading';
2910  }
2911  }
2912  }
2913 
2914  if ( $group == 'noscript' ) {
2915  $links['html'][] = Html::rawElement( 'noscript', [], $link );
2916  } else {
2917  $links['html'][] = $link;
2918  }
2919  }
2920  }
2921 
2922  return $links;
2923  }
2924 
2930  protected static function getHtmlFromLoaderLinks( array $links ) {
2931  $html = [];
2932  $states = [];
2933  foreach ( $links as $link ) {
2934  if ( !is_array( $link ) ) {
2935  $html[] = $link;
2936  } else {
2937  $html = array_merge( $html, $link['html'] );
2938  $states += $link['states'];
2939  }
2940  }
2941  // Filter out empty values
2942  $html = array_filter( $html, 'strlen' );
2943 
2944  if ( count( $states ) ) {
2945  array_unshift( $html, ResourceLoader::makeInlineScript(
2947  ) );
2948  }
2949 
2950  return WrappedString::join( "\n", $html );
2951  }
2952 
2959  function getHeadScripts() {
2960  return $this->getInlineHeadScripts() . $this->getExternalHeadScripts();
2961  }
2962 
2970  $links = [];
2971 
2972  // Startup - this provides the client with the module
2973  // manifest and loads jquery and mediawiki base modules
2974  $links[] = $this->makeResourceLoaderLink( 'startup', ResourceLoaderModule::TYPE_SCRIPTS );
2975 
2976  return self::getHtmlFromLoaderLinks( $links );
2977  }
2978 
2985  $links = [];
2986 
2987  // Client profile classes for <html>. Allows for easy hiding/showing of UI components.
2988  // Must be done synchronously on every page to avoid flashes of wrong content.
2989  // Note: This class distinguishes MediaWiki-supported JavaScript from the rest.
2990  // The "rest" includes browsers that support JavaScript but not supported by our runtime.
2991  // For the performance benefit of the majority, this is added unconditionally here and is
2992  // then fixed up by the startup module for unsupported browsers.
2993  $links[] = Html::inlineScript(
2994  'document.documentElement.className = document.documentElement.className'
2995  . '.replace( /(^|\s)client-nojs(\s|$)/, "$1client-js$2" );'
2996  );
2997 
2998  // Load config before anything else
3001  );
3002 
3003  // Load embeddable private modules before any loader links
3004  // This needs to be TYPE_COMBINED so these modules are properly wrapped
3005  // in mw.loader.implement() calls and deferred until mw.user is available
3006  $embedScripts = [ 'user.options' ];
3007  $links[] = $this->makeResourceLoaderLink(
3008  $embedScripts,
3010  );
3011  // Separate user.tokens as otherwise caching will be allowed (T84960)
3012  $links[] = $this->makeResourceLoaderLink(
3013  'user.tokens',
3015  );
3016 
3017  // Modules requests - let the client calculate dependencies and batch requests as it likes
3018  // Only load modules that have marked themselves for loading at the top
3019  $modules = $this->getModules( true, 'top' );
3020  if ( $modules ) {
3022  Xml::encodeJsCall( 'mw.loader.load', [ $modules ] )
3023  );
3024  }
3025 
3026  // "Scripts only" modules marked for top inclusion
3027  $links[] = $this->makeResourceLoaderLink(
3028  $this->getModuleScripts( true, 'top' ),
3030  );
3031 
3032  return self::getHtmlFromLoaderLinks( $links );
3033  }
3034 
3044  function getScriptsForBottomQueue( $unused = null ) {
3045  // Scripts "only" requests marked for bottom inclusion
3046  // If we're in the <head>, use load() calls rather than <script src="..."> tags
3047  $links = [];
3048 
3049  $links[] = $this->makeResourceLoaderLink( $this->getModuleScripts( true, 'bottom' ),
3051  );
3052 
3053  // Modules requests - let the client calculate dependencies and batch requests as it likes
3054  // Only load modules that have marked themselves for loading at the bottom
3055  $modules = $this->getModules( true, 'bottom' );
3056  if ( $modules ) {
3058  Xml::encodeJsCall( 'mw.loader.load', [ $modules ] )
3059  );
3060  }
3061 
3062  // Legacy Scripts
3063  $links[] = $this->mScripts;
3064 
3065  // Add user JS if enabled
3066  // This must use TYPE_COMBINED instead of only=scripts so that its request is handled by
3067  // mw.loader.implement() which ensures that execution is scheduled after the "site" module.
3068  if ( $this->getConfig()->get( 'AllowUserJs' )
3069  && $this->getUser()->isLoggedIn()
3070  && $this->getTitle()
3071  && $this->getTitle()->isJsSubpage()
3072  && $this->userCanPreview()
3073  ) {
3074  // We're on a preview of a JS subpage. Exclude this page from the user module (T28283)
3075  // and include the draft contents as a raw script instead.
3077  [ 'excludepage' => $this->getTitle()->getPrefixedDBkey() ]
3078  );
3079  // Load the previewed JS
3081  Xml::encodeJsCall( 'mw.loader.using', [
3082  [ 'user', 'site' ],
3083  new XmlJsCode(
3084  'function () {'
3085  . Xml::encodeJsCall( '$.globalEval', [
3086  $this->getRequest()->getText( 'wpTextbox1' )
3087  ] )
3088  . '}'
3089  )
3090  ] )
3091  );
3092 
3093  // FIXME: If the user is previewing, say, ./vector.js, his ./common.js will be loaded
3094  // asynchronously and may arrive *after* the inline script here. So the previewed code
3095  // may execute before ./common.js runs. Normally, ./common.js runs before ./vector.js.
3096  // Similarly, when previewing ./common.js and the user module does arrive first,
3097  // it will arrive without common.js and the inline script runs after.
3098  // Thus running common after the excluded subpage.
3099  } else {
3100  // Include the user module normally, i.e., raw to avoid it being wrapped in a closure.
3101  $links[] = $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_COMBINED );
3102  }
3103 
3104  // Group JS is only enabled if site JS is enabled.
3105  $links[] = $this->makeResourceLoaderLink(
3106  'user.groups',
3108  );
3109 
3110  return self::getHtmlFromLoaderLinks( $links );
3111  }
3112 
3117  function getBottomScripts() {
3118  return $this->getScriptsForBottomQueue();
3119  }
3120 
3127  public function getJsConfigVars() {
3128  return $this->mJsConfigVars;
3129  }
3130 
3137  public function addJsConfigVars( $keys, $value = null ) {
3138  if ( is_array( $keys ) ) {
3139  foreach ( $keys as $key => $value ) {
3140  $this->mJsConfigVars[$key] = $value;
3141  }
3142  return;
3143  }
3144 
3145  $this->mJsConfigVars[$keys] = $value;
3146  }
3147 
3157  public function getJSVars() {
3159 
3160  $curRevisionId = 0;
3161  $articleId = 0;
3162  $canonicalSpecialPageName = false; # bug 21115
3163 
3164  $title = $this->getTitle();
3165  $ns = $title->getNamespace();
3166  $canonicalNamespace = MWNamespace::exists( $ns )
3168  : $title->getNsText();
3169 
3170  $sk = $this->getSkin();
3171  // Get the relevant title so that AJAX features can use the correct page name
3172  // when making API requests from certain special pages (bug 34972).
3173  $relevantTitle = $sk->getRelevantTitle();
3174  $relevantUser = $sk->getRelevantUser();
3175 
3176  if ( $ns == NS_SPECIAL ) {
3177  list( $canonicalSpecialPageName, /*...*/ ) =
3178  SpecialPageFactory::resolveAlias( $title->getDBkey() );
3179  } elseif ( $this->canUseWikiPage() ) {
3180  $wikiPage = $this->getWikiPage();
3181  $curRevisionId = $wikiPage->getLatest();
3182  $articleId = $wikiPage->getId();
3183  }
3184 
3185  $lang = $title->getPageViewLanguage();
3186 
3187  // Pre-process information
3188  $separatorTransTable = $lang->separatorTransformTable();
3189  $separatorTransTable = $separatorTransTable ? $separatorTransTable : [];
3190  $compactSeparatorTransTable = [
3191  implode( "\t", array_keys( $separatorTransTable ) ),
3192  implode( "\t", $separatorTransTable ),
3193  ];
3194  $digitTransTable = $lang->digitTransformTable();
3195  $digitTransTable = $digitTransTable ? $digitTransTable : [];
3196  $compactDigitTransTable = [
3197  implode( "\t", array_keys( $digitTransTable ) ),
3198  implode( "\t", $digitTransTable ),
3199  ];
3200 
3201  $user = $this->getUser();
3202 
3203  $vars = [
3204  'wgCanonicalNamespace' => $canonicalNamespace,
3205  'wgCanonicalSpecialPageName' => $canonicalSpecialPageName,
3206  'wgNamespaceNumber' => $title->getNamespace(),
3207  'wgPageName' => $title->getPrefixedDBkey(),
3208  'wgTitle' => $title->getText(),
3209  'wgCurRevisionId' => $curRevisionId,
3210  'wgRevisionId' => (int)$this->getRevisionId(),
3211  'wgArticleId' => $articleId,
3212  'wgIsArticle' => $this->isArticle(),
3213  'wgIsRedirect' => $title->isRedirect(),
3214  'wgAction' => Action::getActionName( $this->getContext() ),
3215  'wgUserName' => $user->isAnon() ? null : $user->getName(),
3216  'wgUserGroups' => $user->getEffectiveGroups(),
3217  'wgCategories' => $this->getCategories(),
3218  'wgBreakFrames' => $this->getFrameOptions() == 'DENY',
3219  'wgPageContentLanguage' => $lang->getCode(),
3220  'wgPageContentModel' => $title->getContentModel(),
3221  'wgSeparatorTransformTable' => $compactSeparatorTransTable,
3222  'wgDigitTransformTable' => $compactDigitTransTable,
3223  'wgDefaultDateFormat' => $lang->getDefaultDateFormat(),
3224  'wgMonthNames' => $lang->getMonthNamesArray(),
3225  'wgMonthNamesShort' => $lang->getMonthAbbreviationsArray(),
3226  'wgRelevantPageName' => $relevantTitle->getPrefixedDBkey(),
3227  'wgRelevantArticleId' => $relevantTitle->getArticleID(),
3228  'wgRequestId' => WebRequest::getRequestId(),
3229  ];
3230 
3231  if ( $user->isLoggedIn() ) {
3232  $vars['wgUserId'] = $user->getId();
3233  $vars['wgUserEditCount'] = $user->getEditCount();
3234  $userReg = wfTimestampOrNull( TS_UNIX, $user->getRegistration() );
3235  $vars['wgUserRegistration'] = $userReg !== null ? ( $userReg * 1000 ) : null;
3236  // Get the revision ID of the oldest new message on the user's talk
3237  // page. This can be used for constructing new message alerts on
3238  // the client side.
3239  $vars['wgUserNewMsgRevisionId'] = $user->getNewMessageRevisionId();
3240  }
3241 
3242  if ( $wgContLang->hasVariants() ) {
3243  $vars['wgUserVariant'] = $wgContLang->getPreferredVariant();
3244  }
3245  // Same test as SkinTemplate
3246  $vars['wgIsProbablyEditable'] = $title->quickUserCan( 'edit', $user )
3247  && ( $title->exists() || $title->quickUserCan( 'create', $user ) );
3248 
3249  foreach ( $title->getRestrictionTypes() as $type ) {
3250  $vars['wgRestriction' . ucfirst( $type )] = $title->getRestrictions( $type );
3251  }
3252 
3253  if ( $title->isMainPage() ) {
3254  $vars['wgIsMainPage'] = true;
3255  }
3256 
3257  if ( $this->mRedirectedFrom ) {
3258  $vars['wgRedirectedFrom'] = $this->mRedirectedFrom->getPrefixedDBkey();
3259  }
3260 
3261  if ( $relevantUser ) {
3262  $vars['wgRelevantUserName'] = $relevantUser->getName();
3263  }
3264 
3265  // Allow extensions to add their custom variables to the mw.config map.
3266  // Use the 'ResourceLoaderGetConfigVars' hook if the variable is not
3267  // page-dependant but site-wide (without state).
3268  // Alternatively, you may want to use OutputPage->addJsConfigVars() instead.
3269  Hooks::run( 'MakeGlobalVariablesScript', [ &$vars, $this ] );
3270 
3271  // Merge in variables from addJsConfigVars last
3272  return array_merge( $vars, $this->getJsConfigVars() );
3273  }
3274 
3284  public function userCanPreview() {
3285  $request = $this->getRequest();
3286  if (
3287  $request->getVal( 'action' ) !== 'submit' ||
3288  !$request->getCheck( 'wpPreview' ) ||
3289  !$request->wasPosted()
3290  ) {
3291  return false;
3292  }
3293 
3294  $user = $this->getUser();
3295  if ( !$user->matchEditToken( $request->getVal( 'wpEditToken' ) ) ) {
3296  return false;
3297  }
3298 
3299  $title = $this->getTitle();
3300  if ( !$title->isJsSubpage() && !$title->isCssSubpage() ) {
3301  return false;
3302  }
3303  if ( !$title->isSubpageOf( $user->getUserPage() ) ) {
3304  // Don't execute another user's CSS or JS on preview (T85855)
3305  return false;
3306  }
3307 
3308  $errors = $title->getUserPermissionsErrors( 'edit', $user );
3309  if ( count( $errors ) !== 0 ) {
3310  return false;
3311  }
3312 
3313  return true;
3314  }
3315 
3319  public function getHeadLinksArray() {
3321 
3322  $tags = [];
3323  $config = $this->getConfig();
3324 
3325  $canonicalUrl = $this->mCanonicalUrl;
3326 
3327  $tags['meta-generator'] = Html::element( 'meta', [
3328  'name' => 'generator',
3329  'content' => "MediaWiki $wgVersion",
3330  ] );
3331 
3332  if ( $config->get( 'ReferrerPolicy' ) !== false ) {
3333  $tags['meta-referrer'] = Html::element( 'meta', [
3334  'name' => 'referrer',
3335  'content' => $config->get( 'ReferrerPolicy' )
3336  ] );
3337  }
3338 
3339  $p = "{$this->mIndexPolicy},{$this->mFollowPolicy}";
3340  if ( $p !== 'index,follow' ) {
3341  // http://www.robotstxt.org/wc/meta-user.html
3342  // Only show if it's different from the default robots policy
3343  $tags['meta-robots'] = Html::element( 'meta', [
3344  'name' => 'robots',
3345  'content' => $p,
3346  ] );
3347  }
3348 
3349  foreach ( $this->mMetatags as $tag ) {
3350  if ( 0 == strcasecmp( 'http:', substr( $tag[0], 0, 5 ) ) ) {
3351  $a = 'http-equiv';
3352  $tag[0] = substr( $tag[0], 5 );
3353  } else {
3354  $a = 'name';
3355  }
3356  $tagName = "meta-{$tag[0]}";
3357  if ( isset( $tags[$tagName] ) ) {
3358  $tagName .= $tag[1];
3359  }
3360  $tags[$tagName] = Html::element( 'meta',
3361  [
3362  $a => $tag[0],
3363  'content' => $tag[1]
3364  ]
3365  );
3366  }
3367 
3368  foreach ( $this->mLinktags as $tag ) {
3369  $tags[] = Html::element( 'link', $tag );
3370  }
3371 
3372  # Universal edit button
3373  if ( $config->get( 'UniversalEditButton' ) && $this->isArticleRelated() ) {
3374  $user = $this->getUser();
3375  if ( $this->getTitle()->quickUserCan( 'edit', $user )
3376  && ( $this->getTitle()->exists() ||
3377  $this->getTitle()->quickUserCan( 'create', $user ) )
3378  ) {
3379  // Original UniversalEditButton
3380  $msg = $this->msg( 'edit' )->text();
3381  $tags['universal-edit-button'] = Html::element( 'link', [
3382  'rel' => 'alternate',
3383  'type' => 'application/x-wiki',
3384  'title' => $msg,
3385  'href' => $this->getTitle()->getEditURL(),
3386  ] );
3387  // Alternate edit link
3388  $tags['alternative-edit'] = Html::element( 'link', [
3389  'rel' => 'edit',
3390  'title' => $msg,
3391  'href' => $this->getTitle()->getEditURL(),
3392  ] );
3393  }
3394  }
3395 
3396  # Generally the order of the favicon and apple-touch-icon links
3397  # should not matter, but Konqueror (3.5.9 at least) incorrectly
3398  # uses whichever one appears later in the HTML source. Make sure
3399  # apple-touch-icon is specified first to avoid this.
3400  if ( $config->get( 'AppleTouchIcon' ) !== false ) {
3401  $tags['apple-touch-icon'] = Html::element( 'link', [
3402  'rel' => 'apple-touch-icon',
3403  'href' => $config->get( 'AppleTouchIcon' )
3404  ] );
3405  }
3406 
3407  if ( $config->get( 'Favicon' ) !== false ) {
3408  $tags['favicon'] = Html::element( 'link', [
3409  'rel' => 'shortcut icon',
3410  'href' => $config->get( 'Favicon' )
3411  ] );
3412  }
3413 
3414  # OpenSearch description link
3415  $tags['opensearch'] = Html::element( 'link', [
3416  'rel' => 'search',
3417  'type' => 'application/opensearchdescription+xml',
3418  'href' => wfScript( 'opensearch_desc' ),
3419  'title' => $this->msg( 'opensearch-desc' )->inContentLanguage()->text(),
3420  ] );
3421 
3422  if ( $config->get( 'EnableAPI' ) ) {
3423  # Real Simple Discovery link, provides auto-discovery information
3424  # for the MediaWiki API (and potentially additional custom API
3425  # support such as WordPress or Twitter-compatible APIs for a
3426  # blogging extension, etc)
3427  $tags['rsd'] = Html::element( 'link', [
3428  'rel' => 'EditURI',
3429  'type' => 'application/rsd+xml',
3430  // Output a protocol-relative URL here if $wgServer is protocol-relative.
3431  // Whether RSD accepts relative or protocol-relative URLs is completely
3432  // undocumented, though.
3433  'href' => wfExpandUrl( wfAppendQuery(
3434  wfScript( 'api' ),
3435  [ 'action' => 'rsd' ] ),
3437  ),
3438  ] );
3439  }
3440 
3441  # Language variants
3442  if ( !$config->get( 'DisableLangConversion' ) ) {
3443  $lang = $this->getTitle()->getPageLanguage();
3444  if ( $lang->hasVariants() ) {
3445  $variants = $lang->getVariants();
3446  foreach ( $variants as $variant ) {
3447  $tags["variant-$variant"] = Html::element( 'link', [
3448  'rel' => 'alternate',
3449  'hreflang' => wfBCP47( $variant ),
3450  'href' => $this->getTitle()->getLocalURL(
3451  [ 'variant' => $variant ] )
3452  ]
3453  );
3454  }
3455  # x-default link per https://support.google.com/webmasters/answer/189077?hl=en
3456  $tags["variant-x-default"] = Html::element( 'link', [
3457  'rel' => 'alternate',
3458  'hreflang' => 'x-default',
3459  'href' => $this->getTitle()->getLocalURL() ] );
3460  }
3461  }
3462 
3463  # Copyright
3464  if ( $this->copyrightUrl !== null ) {
3465  $copyright = $this->copyrightUrl;
3466  } else {
3467  $copyright = '';
3468  if ( $config->get( 'RightsPage' ) ) {
3469  $copy = Title::newFromText( $config->get( 'RightsPage' ) );
3470 
3471  if ( $copy ) {
3472  $copyright = $copy->getLocalURL();
3473  }
3474  }
3475 
3476  if ( !$copyright && $config->get( 'RightsUrl' ) ) {
3477  $copyright = $config->get( 'RightsUrl' );
3478  }
3479  }
3480 
3481  if ( $copyright ) {
3482  $tags['copyright'] = Html::element( 'link', [
3483  'rel' => 'copyright',
3484  'href' => $copyright ]
3485  );
3486  }
3487 
3488  # Feeds
3489  if ( $config->get( 'Feed' ) ) {
3490  $feedLinks = [];
3491 
3492  foreach ( $this->getSyndicationLinks() as $format => $link ) {
3493  # Use the page name for the title. In principle, this could
3494  # lead to issues with having the same name for different feeds
3495  # corresponding to the same page, but we can't avoid that at
3496  # this low a level.
3497 
3498  $feedLinks[] = $this->feedLink(
3499  $format,
3500  $link,
3501  # Used messages: 'page-rss-feed' and 'page-atom-feed' (for an easier grep)
3502  $this->msg(
3503  "page-{$format}-feed", $this->getTitle()->getPrefixedText()
3504  )->text()
3505  );
3506  }
3507 
3508  # Recent changes feed should appear on every page (except recentchanges,
3509  # that would be redundant). Put it after the per-page feed to avoid
3510  # changing existing behavior. It's still available, probably via a
3511  # menu in your browser. Some sites might have a different feed they'd
3512  # like to promote instead of the RC feed (maybe like a "Recent New Articles"
3513  # or "Breaking news" one). For this, we see if $wgOverrideSiteFeed is defined.
3514  # If so, use it instead.
3515  $sitename = $config->get( 'Sitename' );
3516  if ( $config->get( 'OverrideSiteFeed' ) ) {
3517  foreach ( $config->get( 'OverrideSiteFeed' ) as $type => $feedUrl ) {
3518  // Note, this->feedLink escapes the url.
3519  $feedLinks[] = $this->feedLink(
3520  $type,
3521  $feedUrl,
3522  $this->msg( "site-{$type}-feed", $sitename )->text()
3523  );
3524  }
3525  } elseif ( !$this->getTitle()->isSpecial( 'Recentchanges' ) ) {
3526  $rctitle = SpecialPage::getTitleFor( 'Recentchanges' );
3527  foreach ( $config->get( 'AdvertisedFeedTypes' ) as $format ) {
3528  $feedLinks[] = $this->feedLink(
3529  $format,
3530  $rctitle->getLocalURL( [ 'feed' => $format ] ),
3531  # For grep: 'site-rss-feed', 'site-atom-feed'
3532  $this->msg( "site-{$format}-feed", $sitename )->text()
3533  );
3534  }
3535  }
3536 
3537  # Allow extensions to change the list pf feeds. This hook is primarily for changing,
3538  # manipulating or removing existing feed tags. If you want to add new feeds, you should
3539  # use OutputPage::addFeedLink() instead.
3540  Hooks::run( 'AfterBuildFeedLinks', [ &$feedLinks ] );
3541 
3542  $tags += $feedLinks;
3543  }
3544 
3545  # Canonical URL
3546  if ( $config->get( 'EnableCanonicalServerLink' ) ) {
3547  if ( $canonicalUrl !== false ) {
3548  $canonicalUrl = wfExpandUrl( $canonicalUrl, PROTO_CANONICAL );
3549  } else {
3550  if ( $this->isArticleRelated() ) {
3551  // This affects all requests where "setArticleRelated" is true. This is
3552  // typically all requests that show content (query title, curid, oldid, diff),
3553  // and all wikipage actions (edit, delete, purge, info, history etc.).
3554  // It does not apply to File pages and Special pages.
3555  // 'history' and 'info' actions address page metadata rather than the page
3556  // content itself, so they may not be canonicalized to the view page url.
3557  // TODO: this ought to be better encapsulated in the Action class.
3558  $action = Action::getActionName( $this->getContext() );
3559  if ( in_array( $action, [ 'history', 'info' ] ) ) {
3560  $query = "action={$action}";
3561  } else {
3562  $query = '';
3563  }
3564  $canonicalUrl = $this->getTitle()->getCanonicalURL( $query );
3565  } else {
3566  $reqUrl = $this->getRequest()->getRequestURL();
3567  $canonicalUrl = wfExpandUrl( $reqUrl, PROTO_CANONICAL );
3568  }
3569  }
3570  }
3571  if ( $canonicalUrl !== false ) {
3572  $tags[] = Html::element( 'link', [
3573  'rel' => 'canonical',
3574  'href' => $canonicalUrl
3575  ] );
3576  }
3577 
3578  return $tags;
3579  }
3580 
3586  public function getHeadLinks() {
3587  wfDeprecated( __METHOD__, '1.24' );
3588  return implode( "\n", $this->getHeadLinksArray() );
3589  }
3590 
3599  private function feedLink( $type, $url, $text ) {
3600  return Html::element( 'link', [
3601  'rel' => 'alternate',
3602  'type' => "application/$type+xml",
3603  'title' => $text,
3604  'href' => $url ]
3605  );
3606  }
3607 
3617  public function addStyle( $style, $media = '', $condition = '', $dir = '' ) {
3618  $options = [];
3619  if ( $media ) {
3620  $options['media'] = $media;
3621  }
3622  if ( $condition ) {
3623  $options['condition'] = $condition;
3624  }
3625  if ( $dir ) {
3626  $options['dir'] = $dir;
3627  }
3628  $this->styles[$style] = $options;
3629  }
3630 
3638  public function addInlineStyle( $style_css, $flip = 'noflip' ) {
3639  if ( $flip === 'flip' && $this->getLanguage()->isRTL() ) {
3640  # If wanted, and the interface is right-to-left, flip the CSS
3641  $style_css = CSSJanus::transform( $style_css, true, false );
3642  }
3643  $this->mInlineStyles .= Html::inlineStyle( $style_css );
3644  }
3645 
3652  public function buildCssLinks() {
3654 
3655  $this->getSkin()->setupSkinUserCss( $this );
3656 
3657  // Add ResourceLoader styles
3658  // Split the styles into these groups
3659  $styles = [
3660  'other' => [],
3661  'user' => [],
3662  'site' => [],
3663  'private' => [],
3664  'noscript' => []
3665  ];
3666  $links = [];
3667  $otherTags = []; // Tags to append after the normal <link> tags
3669 
3670  $moduleStyles = $this->getModuleStyles();
3671 
3672  // Per-site custom styles
3673  $moduleStyles[] = 'site';
3674  $moduleStyles[] = 'noscript';
3675  $moduleStyles[] = 'user.groups';
3676 
3677  // Per-user custom styles
3678  if ( $this->getConfig()->get( 'AllowUserCss' ) && $this->getTitle()->isCssSubpage()
3679  && $this->userCanPreview()
3680  ) {
3681  // We're on a preview of a CSS subpage
3682  // Exclude this page from the user module in case it's in there (bug 26283)
3684  [ 'excludepage' => $this->getTitle()->getPrefixedDBkey() ]
3685  );
3686  $otherTags = array_merge( $otherTags, $link['html'] );
3687 
3688  // Load the previewed CSS
3689  // If needed, Janus it first. This is user-supplied CSS, so it's
3690  // assumed to be right for the content language directionality.
3691  $previewedCSS = $this->getRequest()->getText( 'wpTextbox1' );
3692  if ( $this->getLanguage()->getDir() !== $wgContLang->getDir() ) {
3693  $previewedCSS = CSSJanus::transform( $previewedCSS, true, false );
3694  }
3695  $otherTags[] = Html::inlineStyle( $previewedCSS );
3696  } else {
3697  // Load the user styles normally
3698  $moduleStyles[] = 'user';
3699  }
3700 
3701  // Per-user preference styles
3702  $moduleStyles[] = 'user.cssprefs';
3703 
3704  foreach ( $moduleStyles as $name ) {
3705  $module = $resourceLoader->getModule( $name );
3706  if ( !$module ) {
3707  continue;
3708  }
3709  if ( $name === 'site' ) {
3710  // HACK: The site module shouldn't be fragmented with a cache group and
3711  // http request. But in order to ensure its styles are separated and after the
3712  // ResourceLoaderDynamicStyles marker, pretend it is in a group called 'site'.
3713  // The scripts remain ungrouped and rides the bottom queue.
3714  $styles['site'][] = $name;
3715  continue;
3716  }
3717  $group = $module->getGroup();
3718  // Modules in groups other than the ones needing special treatment
3719  // (see $styles assignment)
3720  // will be placed in the "other" style category.
3721  $styles[isset( $styles[$group] ) ? $group : 'other'][] = $name;
3722  }
3723 
3724  // We want site, private and user styles to override dynamically added
3725  // styles from modules, but we want dynamically added styles to override
3726  // statically added styles from other modules. So the order has to be
3727  // other, dynamic, site, private, user. Add statically added styles for
3728  // other modules
3729  $links[] = $this->makeResourceLoaderLink(
3730  $styles['other'],
3732  );
3733  // Add normal styles added through addStyle()/addInlineStyle() here
3734  $links[] = implode( '', $this->buildCssLinksArray() ) . $this->mInlineStyles;
3735  // Add marker tag to mark the place where the client-side
3736  // loader should inject dynamic styles
3737  // We use a <meta> tag with a made-up name for this because that's valid HTML
3738  $links[] = Html::element(
3739  'meta',
3740  [ 'name' => 'ResourceLoaderDynamicStyles', 'content' => '' ]
3741  );
3742 
3743  // Add site-specific and user-specific styles
3744  // 'private' at present only contains user.options, so put that before 'user'
3745  // Any future private modules will likely have a similar user-specific character
3746  foreach ( [ 'site', 'noscript', 'private', 'user' ] as $group ) {
3747  $links[] = $this->makeResourceLoaderLink( $styles[$group],
3749  );
3750  }
3751 
3752  // Add stuff in $otherTags (previewed user CSS if applicable)
3753  return self::getHtmlFromLoaderLinks( $links ) . implode( '', $otherTags );
3754  }
3755 
3759  public function buildCssLinksArray() {
3760  $links = [];
3761 
3762  // Add any extension CSS
3763  foreach ( $this->mExtStyles as $url ) {
3764  $this->addStyle( $url );
3765  }
3766  $this->mExtStyles = [];
3767 
3768  foreach ( $this->styles as $file => $options ) {
3769  $link = $this->styleLink( $file, $options );
3770  if ( $link ) {
3771  $links[$file] = $link;
3772  }
3773  }
3774  return $links;
3775  }
3776 
3784  protected function styleLink( $style, array $options ) {
3785  if ( isset( $options['dir'] ) ) {
3786  if ( $this->getLanguage()->getDir() != $options['dir'] ) {
3787  return '';
3788  }
3789  }
3790 
3791  if ( isset( $options['media'] ) ) {
3792  $media = self::transformCssMedia( $options['media'] );
3793  if ( is_null( $media ) ) {
3794  return '';
3795  }
3796  } else {
3797  $media = 'all';
3798  }
3799 
3800  if ( substr( $style, 0, 1 ) == '/' ||
3801  substr( $style, 0, 5 ) == 'http:' ||
3802  substr( $style, 0, 6 ) == 'https:' ) {
3803  $url = $style;
3804  } else {
3805  $config = $this->getConfig();
3806  $url = $config->get( 'StylePath' ) . '/' . $style . '?' .
3807  $config->get( 'StyleVersion' );
3808  }
3809 
3810  $link = Html::linkedStyle( $url, $media );
3811 
3812  if ( isset( $options['condition'] ) ) {
3813  $condition = htmlspecialchars( $options['condition'] );
3814  $link = "<!--[if $condition]>$link<![endif]-->";
3815  }
3816  return $link;
3817  }
3818 
3840  public static function transformResourcePath( Config $config, $path ) {
3841  global $IP;
3842  $remotePathPrefix = $config->get( 'ResourceBasePath' );
3843  if ( $remotePathPrefix === '' ) {
3844  // The configured base path is required to be empty string for
3845  // wikis in the domain root
3846  $remotePath = '/';
3847  } else {
3848  $remotePath = $remotePathPrefix;
3849  }
3850  if ( strpos( $path, $remotePath ) !== 0 ) {
3851  // Path is outside wgResourceBasePath, ignore.
3852  return $path;
3853  }
3854  $path = RelPath\getRelativePath( $path, $remotePath );
3855  return self::transformFilePath( $remotePathPrefix, $IP, $path );
3856  }
3857 
3869  public static function transformFilePath( $remotePathPrefix, $localPath, $file ) {
3870  $hash = md5_file( "$localPath/$file" );
3871  if ( $hash === false ) {
3872  wfLogWarning( __METHOD__ . ": Failed to hash $localPath/$file" );
3873  $hash = '';
3874  }
3875  return "$remotePathPrefix/$file?" . substr( $hash, 0, 5 );
3876  }
3877 
3885  public static function transformCssMedia( $media ) {
3887 
3888  // http://www.w3.org/TR/css3-mediaqueries/#syntax
3889  $screenMediaQueryRegex = '/^(?:only\s+)?screen\b/i';
3890 
3891  // Switch in on-screen display for media testing
3892  $switches = [
3893  'printable' => 'print',
3894  'handheld' => 'handheld',
3895  ];
3896  foreach ( $switches as $switch => $targetMedia ) {
3897  if ( $wgRequest->getBool( $switch ) ) {
3898  if ( $media == $targetMedia ) {
3899  $media = '';
3900  } elseif ( preg_match( $screenMediaQueryRegex, $media ) === 1 ) {
3901  /* This regex will not attempt to understand a comma-separated media_query_list
3902  *
3903  * Example supported values for $media:
3904  * 'screen', 'only screen', 'screen and (min-width: 982px)' ),
3905  * Example NOT supported value for $media:
3906  * '3d-glasses, screen, print and resolution > 90dpi'
3907  *
3908  * If it's a print request, we never want any kind of screen stylesheets
3909  * If it's a handheld request (currently the only other choice with a switch),
3910  * we don't want simple 'screen' but we might want screen queries that
3911  * have a max-width or something, so we'll pass all others on and let the
3912  * client do the query.
3913  */
3914  if ( $targetMedia == 'print' || $media == 'screen' ) {
3915  return null;
3916  }
3917  }
3918  }
3919  }
3920 
3921  return $media;
3922  }
3923 
3930  public function addWikiMsg( /*...*/ ) {
3931  $args = func_get_args();
3932  $name = array_shift( $args );
3933  $this->addWikiMsgArray( $name, $args );
3934  }
3935 
3944  public function addWikiMsgArray( $name, $args ) {
3945  $this->addHTML( $this->msg( $name, $args )->parseAsBlock() );
3946  }
3947 
3973  public function wrapWikiMsg( $wrap /*, ...*/ ) {
3974  $msgSpecs = func_get_args();
3975  array_shift( $msgSpecs );
3976  $msgSpecs = array_values( $msgSpecs );
3977  $s = $wrap;
3978  foreach ( $msgSpecs as $n => $spec ) {
3979  if ( is_array( $spec ) ) {
3980  $args = $spec;
3981  $name = array_shift( $args );
3982  if ( isset( $args['options'] ) ) {
3983  unset( $args['options'] );
3984  wfDeprecated(
3985  'Adding "options" to ' . __METHOD__ . ' is no longer supported',
3986  '1.20'
3987  );
3988  }
3989  } else {
3990  $args = [];
3991  $name = $spec;
3992  }
3993  $s = str_replace( '$' . ( $n + 1 ), $this->msg( $name, $args )->plain(), $s );
3994  }
3995  $this->addWikiText( $s );
3996  }
3997 
4003  public function enableTOC( $flag = true ) {
4004  $this->mEnableTOC = $flag;
4005  }
4006 
4011  public function isTOCEnabled() {
4012  return $this->mEnableTOC;
4013  }
4014 
4020  public function enableSectionEditLinks( $flag = true ) {
4021  $this->mEnableSectionEditLinks = $flag;
4022  }
4023 
4028  public function sectionEditLinksEnabled() {
4030  }
4031 
4039  public static function setupOOUI( $skinName = '', $dir = 'ltr' ) {
4040  $themes = ExtensionRegistry::getInstance()->getAttribute( 'SkinOOUIThemes' );
4041  // Make keys (skin names) lowercase for case-insensitive matching.
4042  $themes = array_change_key_case( $themes, CASE_LOWER );
4043  $theme = isset( $themes[$skinName] ) ? $themes[$skinName] : 'MediaWiki';
4044  // For example, 'OOUI\MediaWikiTheme'.
4045  $themeClass = "OOUI\\{$theme}Theme";
4046  OOUI\Theme::setSingleton( new $themeClass() );
4047  OOUI\Element::setDefaultDir( $dir );
4048  }
4049 
4056  public function enableOOUI() {
4057  self::setupOOUI(
4058  strtolower( $this->getSkin()->getSkinName() ),
4059  $this->getLanguage()->getDir()
4060  );
4061  $this->addModuleStyles( [
4062  'oojs-ui-core.styles',
4063  'oojs-ui.styles.icons',
4064  'oojs-ui.styles.indicators',
4065  'oojs-ui.styles.textures',
4066  'mediawiki.widgets.styles',
4067  ] );
4068  // Used by 'skipFunction' of the four 'oojs-ui.styles.*' modules. Please don't treat this as a
4069  // public API or you'll be severely disappointed when T87871 is fixed and it disappears.
4070  $this->addMeta( 'X-OOUI-PHP', '1' );
4071  }
4072 }
getPreventClickjacking()
Get the prevent-clickjacking flag.
setContext(IContextSource $context)
Set the IContextSource object.
addInlineStyle($style_css, $flip= 'noflip')
Adds inline CSS styles Internal use only.
const TS_RFC2822
RFC 2822 format, for E-mail and HTTP headers.
prependHTML($text)
Prepend $text to the body HTML.
isDisabled()
Return whether the output will be completely disabled.
static closeElement($element)
Returns "".
Definition: Html.php:306
showFileRenameError($old, $new)
static newFromContext(IContextSource $context)
Get a ParserOptions object from a IContextSource object.
ResourceLoader $mResourceLoader
Definition: OutputPage.php:165
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses & $html
Definition: hooks.txt:1798
array $mTemplateIds
Definition: OutputPage.php:171
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition: deferred.txt:11
Interface for objects which can provide a MediaWiki context on request.
wfGetDB($db, $groups=[], $wiki=false)
Get a Database object.
getPageTitleActionText()
Get the value of the "action text".
Definition: OutputPage.php:915
getMetadataAttribute()
Get the value of the "rel" attribute for metadata links.
Definition: OutputPage.php:444
getHeadItemsArray()
Get an array of head items.
Definition: OutputPage.php:666
static inlineScript($contents)
Output a "".
Definition: Html.php:614
string null $mTarget
ResourceLoader target for load.php links.
Definition: OutputPage.php:291
getArticleBodyOnly()
Return whether the output will contain only the body of the article.
Definition: OutputPage.php:721
static makeConfigSetScript(array $configuration)
Returns JS code which will set the MediaWiki configuration array to the given value.
static escapeClass($class)
Given a value, escape it so that it can be used as a CSS class and return it.
Definition: Sanitizer.php:1208
addHelpLink($to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
filterModules(array $modules, $position=null, $type=ResourceLoaderModule::TYPE_COMBINED)
Filter an array of modules to remove insufficiently trustworthy members, and modules which are no lon...
Definition: OutputPage.php:530
string $mPageLinkTitle
Used by skin template.
Definition: OutputPage.php:150
addParserOutputContent($parserOutput)
Add the HTML and enhancements for it (like ResourceLoader modules) associated with a ParserOutput obj...
userCanPreview()
To make it harder for someone to slip a user a fake user-JavaScript or user-CSS preview, a random token is associated with the login session.
addParserOutputText($parserOutput)
Add the HTML associated with a ParserOutput object, without any metadata.
setPrintable()
Set the page as printable, i.e.
string null $copyrightUrl
The URL to send in a element with rel=copyright.
Definition: OutputPage.php:306
disable()
Disable output completely, i.e.
static exists($index)
Returns whether the specified namespace exists.
wfUrlencode($s)
We want some things to be included as literal characters in our title URLs for prettiness, which urlencode encodes by default.
setStatusCode($statusCode)
Set the HTTP status code to send with the output.
Definition: OutputPage.php:361
static newFromText($text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:277
this hook is for auditing only $response
Definition: hooks.txt:762
Represents a title within MediaWiki.
Definition: Title.php:34
addExtensionStyle($url)
Register and add a stylesheet from an extension directory.
Definition: OutputPage.php:475
static stripAllTags($text)
Take a fragment of (potentially invalid) HTML and return a version with any tags removed, encoded as plain text.
Definition: Sanitizer.php:1784
when a variable name is used in a it is silently declared as a new local masking the global
Definition: design.txt:93
wfExpandUrl($url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
formatPermissionsErrorMessage(array $errors, $action=null)
Format a list of error messages.
string $mRevisionTimestamp
Definition: OutputPage.php:249
array $mLanguageLinks
Array of Interwiki Prefixed (non DB key) Titles (e.g.
Definition: OutputPage.php:133
IContextSource $context
getFileSearchOptions()
Get the files used on this page.
setCategoryLinks(array $categories)
Reset the category links (but not the category list) and add $categories.
isSyndicated()
Should we output feed links for this page?
array $styles
An array of stylesheet filenames (relative from skins path), with options for CSS media...
Definition: OutputPage.php:262
isPrintable()
Return whether the page is "printable".
getTitle()
Get the Title object.
prepareErrorPage($pageTitle, $htmlTitle=false)
Prepare this object to display an error page; disable caching and indexing, clear the current text an...
$mProperties
Additional key => value data.
Definition: OutputPage.php:286
get($name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
getAllowedModules($type)
Show what level of JavaScript / CSS untrustworthiness is allowed on this page.
addElement($element, array $attribs=[], $contents= '')
Shortcut for adding an Html::element via addHTML.
array bool $mDoNothing
Whether output is disabled.
Definition: OutputPage.php:191
addModules($modules)
Add one or more modules recognized by ResourceLoader.
Definition: OutputPage.php:570
wfDebug($text, $dest= 'all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
reduceAllowedModules($type, $level)
Limit the highest level of CSS/JS untrustworthiness allowed.
setPageTitleActionText($text)
Set the new value of the "action text", this will be added to the "HTML title", separated from it wit...
Definition: OutputPage.php:906
bool $mPreventClickjacking
Controls if anti-clickjacking / frame-breaking headers will be sent.
Definition: OutputPage.php:243
addMetadataLink(array $linkarr)
Add a new \ with "rel" attribute set to "meta".
Definition: OutputPage.php:414
if($line===false) $args
Definition: cdb.php:64
the value to return A Title object or null for latest to be modified or replaced by the hook handler or if authentication is not possible after cache objects are set for highlighting & $link
Definition: hooks.txt:2581
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping $template
Definition: hooks.txt:762
preventClickjacking($enable=true)
Set a flag which will cause an X-Frame-Options header appropriate for edit pages to be sent...
enableClientCache($state)
Use enableClientCache(false) to force it to send nocache headers.
getCategories()
Get the list of category names this page belongs to.
array $mJsConfigVars
Definition: OutputPage.php:168
getJsConfigVars()
Get the javascript config vars to include on this page.
enableOOUI()
Add ResourceLoader module styles for OOUI and set up the PHP implementation of it for use with MediaW...
addParserOutput($parserOutput)
Add everything from a ParserOutput object.
bool $mPrintable
We have to set isPrintable().
Definition: OutputPage.php:92
static makeLoaderStateScript($name, $state=null)
Returns a JS call to mw.loader.state, which sets the state of a module or modules to a given value...
clearSubtitle()
Clear the subtitles.
Class representing a list of titles The execute() method checks them all for existence and adds them ...
Definition: LinkBatch.php:31
wfTimestamp($outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
getRequest()
Get the WebRequest object.
addWikiTextWithTitle($text, &$title, $linestart=true)
Add wikitext with a custom Title object.
getHeadScripts()
JS stuff to put in the "".
bool $mIsArticleRelated
Stores "article flag" toggle.
Definition: OutputPage.php:86
canUseWikiPage()
Check whether a WikiPage object can be get with getWikiPage().
getExternalHeadScripts()
tags to put in "".
addTemplate(&$template)
Add the output of a QuickTemplate to the output buffer.
clearHTML()
Clear the body HTML.
getFrameOptions()
Get the X-Frame-Options header value (without the name part), or false if there isn't one...
A wrapper class which causes Xml::encodeJsVar() and Xml::encodeJsCall() to interpret a given string a...
Definition: Xml.php:884
setCdnMaxage($maxage)
Set the value of the "s-maxage" part of the "Cache-control" HTTP header.
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses after processing after in associative array form externallinks including delete and has completed for all link tables whether this was an auto creation default is conds Array Extra conditions for the No matching items in log is displayed if loglist is empty msgKey Array If you want a nice box with a set this to the key of the message First element is the message additional optional elements are parameters for the key that are processed with wfMessage() -> params() ->parseAsBlock()-offset Set to overwrite offset parameter in $wgRequest set to ''to unsetoffset-wrap String Wrap the message in html(usually something like"&lt
enableSectionEditLinks($flag=true)
Enables/disables section edit links, doesn't override NOEDITSECTION
getIndicators()
Get the indicators associated with this page.
getContext()
Get the base IContextSource object.
addWikiMsg()
Add a wikitext-formatted message to the output.
static makePackedModulesString($modules)
Convert an array of module names to a packed query string.
$params
showNewSectionLink()
Show an "add new section" link?
const NS_CATEGORY
Definition: Defines.php:83
Title $mRedirectedFrom
If the current page was reached through a redirect, $mRedirectedFrom contains the Title of the redire...
Definition: OutputPage.php:281
and(b) You must cause any modified files to carry prominent notices stating that You changed the files
wfDeprecated($function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
string $mHTMLtitle
Stores contents of "" tag. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00077">OutputPage.php:77</a></div></div> <div class="ttc" id="classOutputPage_html_a3feffe321006a7b9c5eab9ac2c023bb5"><div class="ttname"><a href="classOutputPage.html#a3feffe321006a7b9c5eab9ac2c023bb5">OutputPage\$mHideNewSectionLink</a></div><div class="ttdeci">bool $mHideNewSectionLink</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00221">OutputPage.php:221</a></div></div> <div class="ttc" id="classOutputPage_html_a905182025f38e9304a183457c997e764"><div class="ttname"><a href="classOutputPage.html#a905182025f38e9304a183457c997e764">OutputPage\$mBodytext</a></div><div class="ttdeci">string $mBodytext</div><div class="ttdoc">Contains all of the "<body>" content. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00067">OutputPage.php:67</a></div></div> <div class="ttc" id="classTitle_html_acd8c320154e49f2bc750102b2219e55c"><div class="ttname"><a href="classTitle.html#acd8c320154e49f2bc750102b2219e55c">Title\makeTitleSafe</a></div><div class="ttdeci">static makeTitleSafe($ns, $title, $fragment= '', $interwiki= '')</div><div class="ttdoc">Create a new Title from a namespace index and a DB key. </div><div class="ttdef"><b>Definition:</b> <a href="Title_8php_source.html#l00548">Title.php:548</a></div></div> <div class="ttc" id="classOutputPage_html_ad0d7ef039708dd0d3cdc83ad3bd6f23e"><div class="ttname"><a href="classOutputPage.html#ad0d7ef039708dd0d3cdc83ad3bd6f23e">OutputPage\buildCssLinksArray</a></div><div class="ttdeci">buildCssLinksArray()</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l03759">OutputPage.php:3759</a></div></div> <div class="ttc" id="classOutputPage_html_a50507820b7fb637b0f4924f31d98600c"><div class="ttname"><a href="classOutputPage.html#a50507820b7fb637b0f4924f31d98600c">OutputPage\getModuleStyles</a></div><div class="ttdeci">getModuleStyles($filter=false, $position=null)</div><div class="ttdoc">Get the list of module CSS to include on this page. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00605">OutputPage.php:605</a></div></div> <div class="ttc" id="classOutputPage_html_aaa1c0ae62fd0a36703d1736b7ecc8c7c"><div class="ttname"><a href="classOutputPage.html#aaa1c0ae62fd0a36703d1736b7ecc8c7c">OutputPage\parseInline</a></div><div class="ttdeci">parseInline($text, $linestart=true, $interface=false)</div><div class="ttdoc">Parse wikitext, strip paragraphs, and return the HTML. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01921">OutputPage.php:1921</a></div></div> <div class="ttc" id="group__Constants_html_gaf9a09ab91a9583e960a610723f5f4330"><div class="ttname"><a href="group__Constants.html#gaf9a09ab91a9583e960a610723f5f4330">DB_SLAVE</a></div><div class="ttdeci">const DB_SLAVE</div><div class="ttdef"><b>Definition:</b> <a href="Defines_8php_source.html#l00046">Defines.php:46</a></div></div> <div class="ttc" id="classOutputPage_html_a0acf51550b84db556540479b7cc4fba5"><div class="ttname"><a href="classOutputPage.html#a0acf51550b84db556540479b7cc4fba5">OutputPage\styleLink</a></div><div class="ttdeci">styleLink($style, array $options)</div><div class="ttdoc">Generate \<link\> tags for stylesheets. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l03784">OutputPage.php:3784</a></div></div> <div class="ttc" id="classResourceLoader_html_a5e720bc042a40216b017b18ccf4af321"><div class="ttname"><a href="classResourceLoader.html#a5e720bc042a40216b017b18ccf4af321">ResourceLoader\makeInlineScript</a></div><div class="ttdeci">static makeInlineScript($script)</div><div class="ttdoc">Construct an inline script tag with given JS code. </div><div class="ttdef"><b>Definition:</b> <a href="ResourceLoader_8php_source.html#l01376">ResourceLoader.php:1376</a></div></div> <div class="ttc" id="classOutputPage_html_af355e999b051480b75e0ea4a334b5508"><div class="ttname"><a href="classOutputPage.html#af355e999b051480b75e0ea4a334b5508">OutputPage\$mETag</a></div><div class="ttdeci">$mETag</div><div class="ttdoc">Contains an HTTP Entity Tags (see RFC 2616 section 3.13) which is used as a unique identifier for the...</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00121">OutputPage.php:121</a></div></div> <div class="ttc" id="classSkin_html_a490d80986a84dc6cc98a9f389bb6f670"><div class="ttname"><a href="classSkin.html#a490d80986a84dc6cc98a9f389bb6f670">Skin\getHtmlElementAttributes</a></div><div class="ttdeci">getHtmlElementAttributes()</div><div class="ttdoc">Return values for <html> element. </div><div class="ttdef"><b>Definition:</b> <a href="Skin_8php_source.html#l00399">Skin.php:399</a></div></div> <div class="ttc" id="GlobalFunctions_8php_html_a8fc068abfbf5ce2e9ac658781b8e8659"><div class="ttname"><a href="GlobalFunctions_8php.html#a8fc068abfbf5ce2e9ac658781b8e8659">wfBCP47</a></div><div class="ttdeci">wfBCP47($code)</div><div class="ttdoc">Get the normalised IETF language tag See unit test for examples. </div><div class="ttdef"><b>Definition:</b> <a href="GlobalFunctions_8php_source.html#l03452">GlobalFunctions.php:3452</a></div></div> <div class="ttc" id="hooks_8txt_html_a82840e2424b6b7e1b1bfe79de4db9b00"><div class="ttname"><a href="hooks_8txt.html#a82840e2424b6b7e1b1bfe79de4db9b00">$title</a></div><div class="ttdeci">namespace and then decline to actually register it file or subcat img or subcat $title</div><div class="ttdef"><b>Definition:</b> <a href="hooks_8txt_source.html#l00912">hooks.txt:912</a></div></div> <div class="ttc" id="classMWDebug_html_a3538a8910feb064f85dc40a74ab19ec5"><div class="ttname"><a href="classMWDebug.html#a3538a8910feb064f85dc40a74ab19ec5">MWDebug\addModules</a></div><div class="ttdeci">static addModules(OutputPage $out)</div><div class="ttdoc">Add ResourceLoader modules to the OutputPage object if debugging is enabled. </div><div class="ttdef"><b>Definition:</b> <a href="MWDebug_8php_source.html#l00085">MWDebug.php:85</a></div></div> <div class="ttc" id="classOutputPage_html_a0a5a13c217ca4eed7a88945bd63ec730"><div class="ttname"><a href="classOutputPage.html#a0a5a13c217ca4eed7a88945bd63ec730">OutputPage\addLink</a></div><div class="ttdeci">addLink(array $linkarr)</div><div class="ttdoc">Add a new \<link\> tag to the page header. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00393">OutputPage.php:393</a></div></div> <div class="ttc" id="classOutputPage_html_a7a1e5451f23d157679422576a666912c"><div class="ttname"><a href="classOutputPage.html#a7a1e5451f23d157679422576a666912c">OutputPage\addStyle</a></div><div class="ttdeci">addStyle($style, $media= '', $condition= '', $dir= '')</div><div class="ttdoc">Add a local or specified stylesheet, with the given media options. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l03617">OutputPage.php:3617</a></div></div> <div class="ttc" id="classHtml_html_a7d66939a3f3ee87a5775e6de49939cf5"><div class="ttname"><a href="classHtml.html#a7d66939a3f3ee87a5775e6de49939cf5">Html\inlineStyle</a></div><div class="ttdeci">static inlineStyle($contents, $media= 'all')</div><div class="ttdoc">Output a "<style>" tag with the given contents for the given media type (if any). ...</div><div class="ttdef"><b>Definition:</b> <a href="Html_8php_source.html#l00629">Html.php:629</a></div></div> <div class="ttc" id="classHooks_html_a4d65939e05d81fe900cab2edf720040c"><div class="ttname"><a href="classHooks.html#a4d65939e05d81fe900cab2edf720040c">Hooks\run</a></div><div class="ttdeci">static run($event, array $args=[], $deprecatedVersion=null)</div><div class="ttdoc">Call hook functions defined in Hooks::register and $wgHooks. </div><div class="ttdef"><b>Definition:</b> <a href="Hooks_8php_source.html#l00131">Hooks.php:131</a></div></div> <div class="ttc" id="group__Constants_html_gabdf7fe8fc0c2bc5c556aebeccdd6c230"><div class="ttname"><a href="group__Constants.html#gabdf7fe8fc0c2bc5c556aebeccdd6c230">PROTO_RELATIVE</a></div><div class="ttdeci">const PROTO_RELATIVE</div><div class="ttdef"><b>Definition:</b> <a href="Defines_8php_source.html#l00263">Defines.php:263</a></div></div> <div class="ttc" id="design_8txt_html_aaa89c2ef41e614c0ab4f3149ebafe385"><div class="ttname"><a href="design_8txt.html#aaa89c2ef41e614c0ab4f3149ebafe385">text</a></div><div class="ttdeci">design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add text</div><div class="ttdef"><b>Definition:</b> <a href="design_8txt_source.html#l00012">design.txt:12</a></div></div> <div class="ttc" id="classOutputPage_html_af511b1bb037b8e436645fe15d3d3269a"><div class="ttname"><a href="classOutputPage.html#af511b1bb037b8e436645fe15d3d3269a">OutputPage\$mCategories</a></div><div class="ttdeci">array $mCategories</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00127">OutputPage.php:127</a></div></div> <div class="ttc" id="classAction_html_abdc62032f952f5976e6b43b8c6c47cc9"><div class="ttname"><a href="classAction.html#abdc62032f952f5976e6b43b8c6c47cc9">Action\getActionName</a></div><div class="ttdeci">static getActionName(IContextSource $context)</div><div class="ttdoc">Get the action that will be executed, not necessarily the one passed passed through the "action" requ...</div><div class="ttdef"><b>Definition:</b> <a href="Action_8php_source.html#l00122">Action.php:122</a></div></div> <div class="ttc" id="hooks_8txt_html_aa5c3decea0436db81bfd52a0ebcb3c22"><div class="ttname"><a href="hooks_8txt.html#aa5c3decea0436db81bfd52a0ebcb3c22">$tag</a></div><div class="ttdeci">this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books $tag</div><div class="ttdef"><b>Definition:</b> <a href="hooks_8txt_source.html#l00965">hooks.txt:965</a></div></div> <div class="ttc" id="classOutputPage_html_abdbd64e6df0ad5f5691bd0d63e5e32da"><div class="ttname"><a href="classOutputPage.html#abdbd64e6df0ad5f5691bd0d63e5e32da">OutputPage\showFileNotFoundError</a></div><div class="ttdeci">showFileNotFoundError($name)</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l02595">OutputPage.php:2595</a></div></div> <div class="ttc" id="classOutputPage_html_a6a3d84be750825d461e862b69f3c0857"><div class="ttname"><a href="classOutputPage.html#a6a3d84be750825d461e862b69f3c0857">OutputPage\setFollowPolicy</a></div><div class="ttdeci">setFollowPolicy($policy)</div><div class="ttdoc">Set the follow policy for the page, but leave the index policy un- touched. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00893">OutputPage.php:893</a></div></div> <div class="ttc" id="classOutputPage_html_a21a60c27ebc894ac4cb14919da84dc20"><div class="ttname"><a href="classOutputPage.html#a21a60c27ebc894ac4cb14919da84dc20">OutputPage\$mNewSectionLink</a></div><div class="ttdeci">bool $mNewSectionLink</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00218">OutputPage.php:218</a></div></div> <div class="ttc" id="classHtml_html_a575ca79447ccfad0975d02a77895e9aa"><div class="ttname"><a href="classHtml.html#a575ca79447ccfad0975d02a77895e9aa">Html\htmlHeader</a></div><div class="ttdeci">static htmlHeader(array $attribs=[])</div><div class="ttdoc">Constructs the opening html-tag with necessary doctypes depending on global variables. </div><div class="ttdef"><b>Definition:</b> <a href="Html_8php_source.html#l00910">Html.php:910</a></div></div> <div class="ttc" id="namespaceFauxRequest_html"><div class="ttname"><a href="namespaceFauxRequest.html">FauxRequest</a></div></div> <div class="ttc" id="classOutputPage_html_a671be7cc33f16ff0eb6c456c20227c6e"><div class="ttname"><a href="classOutputPage.html#a671be7cc33f16ff0eb6c456c20227c6e">OutputPage\$mVaryHeader</a></div><div class="ttdeci">$mVaryHeader</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00271">OutputPage.php:271</a></div></div> <div class="ttc" id="classSkin_html_af826daedb40661be82b88cf839aac9d1"><div class="ttname"><a href="classSkin.html#af826daedb40661be82b88cf839aac9d1">Skin\getPageClasses</a></div><div class="ttdeci">getPageClasses($title)</div><div class="ttdoc">TODO: document. </div><div class="ttdef"><b>Definition:</b> <a href="Skin_8php_source.html#l00371">Skin.php:371</a></div></div> <div class="ttc" id="distributors_8txt_html_a7b0adad6be9193b56d3beaec2672f963"><div class="ttname"><a href="distributors_8txt.html#a7b0adad6be9193b56d3beaec2672f963">as</a></div><div class="ttdeci">This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as</div><div class="ttdef"><b>Definition:</b> <a href="distributors_8txt_source.html#l00009">distributors.txt:9</a></div></div> <div class="ttc" id="classOutputPage_html_aa5e61919db9bcc577162509d3a4ecbad"><div class="ttname"><a href="classOutputPage.html#aa5e61919db9bcc577162509d3a4ecbad">OutputPage\addVaryHeader</a></div><div class="ttdeci">addVaryHeader($header, array $option=null)</div><div class="ttdoc">Add an HTTP header that will influence on the cache. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l02012">OutputPage.php:2012</a></div></div> <div class="ttc" id="hooks_8txt_html_aff741ced333f22e57bcc68c2c3adcc7e"><div class="ttname"><a href="hooks_8txt.html#aff741ced333f22e57bcc68c2c3adcc7e">$code</a></div><div class="ttdeci">this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output modifiable & $code</div><div class="ttdef"><b>Definition:</b> <a href="hooks_8txt_source.html#l00762">hooks.txt:762</a></div></div> <div class="ttc" id="classOutputPage_html"><div class="ttname"><a href="classOutputPage.html">OutputPage</a></div><div class="ttdoc">This class should be covered by a general architecture document which does not exist as of January 20...</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00042">OutputPage.php:42</a></div></div> <div class="ttc" id="classOutputPage_html_a8035589ca29e2a598e57cf1b4cc56d42"><div class="ttname"><a href="classOutputPage.html#a8035589ca29e2a598e57cf1b4cc56d42">OutputPage\parse</a></div><div class="ttdeci">parse($text, $linestart=true, $interface=false, $language=null)</div><div class="ttdoc">Parse wikitext and return the HTML. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01881">OutputPage.php:1881</a></div></div> <div class="ttc" id="classParserOptions_html_abbb45f7fd3d62e75fdeb1bd96f817abc"><div class="ttname"><a href="classParserOptions.html#abbb45f7fd3d62e75fdeb1bd96f817abc">ParserOptions\newFromAnon</a></div><div class="ttdeci">static newFromAnon()</div><div class="ttdoc">Get a ParserOptions object for an anonymous user. </div><div class="ttdef"><b>Definition:</b> <a href="ParserOptions_8php_source.html#l00607">ParserOptions.php:607</a></div></div> <div class="ttc" id="hooks_8txt_html_a25ba9c89b51c3382b9b86a7a63fd4405"><div class="ttname"><a href="hooks_8txt.html#a25ba9c89b51c3382b9b86a7a63fd4405">$user</a></div><div class="ttdeci">please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a local account $user</div><div class="ttdef"><b>Definition:</b> <a href="hooks_8txt_source.html#l00242">hooks.txt:242</a></div></div> <div class="ttc" id="classLinker_html_ad97e40cfea2343c5cae8307cf1fe47a4"><div class="ttname"><a href="classLinker.html#ad97e40cfea2343c5cae8307cf1fe47a4">Linker\link</a></div><div class="ttdeci">static link($target, $html=null, $customAttribs=[], $query=[], $options=[])</div><div class="ttdoc">This function returns an HTML link to the given target. </div><div class="ttdef"><b>Definition:</b> <a href="Linker_8php_source.html#l00195">Linker.php:195</a></div></div> <div class="ttc" id="classOutputPage_html_a5f860e2d3f13ff6790cf164a8127da2d"><div class="ttname"><a href="classOutputPage.html#a5f860e2d3f13ff6790cf164a8127da2d">OutputPage\getFeedAppendQuery</a></div><div class="ttdeci">getFeedAppendQuery()</div><div class="ttdoc">Will currently always return null. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01182">OutputPage.php:1182</a></div></div> <div class="ttc" id="classOutputPage_html_ae6a23b2345a86cf28131f4b4c8de891b"><div class="ttname"><a href="classOutputPage.html#ae6a23b2345a86cf28131f4b4c8de891b">OutputPage\$mCategoryLinks</a></div><div class="ttdeci">array $mCategoryLinks</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00124">OutputPage.php:124</a></div></div> <div class="ttc" id="classOutputPage_html_aed7f95440b43b300d7d5fab3403c1866"><div class="ttname"><a href="classOutputPage.html#aed7f95440b43b300d7d5fab3403c1866">OutputPage\setTarget</a></div><div class="ttdeci">setTarget($target)</div><div class="ttdoc">Sets ResourceLoader target for load.php links. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00657">OutputPage.php:657</a></div></div> <div class="ttc" id="classOutputPage_html_a3b0569a781829829e0875fe5969f6426"><div class="ttname"><a href="classOutputPage.html#a3b0569a781829829e0875fe5969f6426">OutputPage\setTitle</a></div><div class="ttdeci">setTitle(Title $t)</div><div class="ttdoc">Set the Title object to use. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00992">OutputPage.php:992</a></div></div> <div class="ttc" id="classOutputPage_html_ad13e795771bbce676a6841998abb09df"><div class="ttname"><a href="classOutputPage.html#ad13e795771bbce676a6841998abb09df">OutputPage\addBacklinkSubtitle</a></div><div class="ttdeci">addBacklinkSubtitle(Title $title, $query=[])</div><div class="ttdoc">Add a subtitle containing a backlink to a page. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01041">OutputPage.php:1041</a></div></div> <div class="ttc" id="classOutputPage_html_a1275bc698729b5f15e687b7ec49bd611"><div class="ttname"><a href="classOutputPage.html#a1275bc698729b5f15e687b7ec49bd611">OutputPage\$mStatusCode</a></div><div class="ttdeci">int $mStatusCode</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00104">OutputPage.php:104</a></div></div> <div class="ttc" id="classOutputPage_html_a030c036f1938af782222d925b21be9a5"><div class="ttname"><a href="classOutputPage.html#a030c036f1938af782222d925b21be9a5">OutputPage\$mCanonicalUrl</a></div><div class="ttdeci">bool $mCanonicalUrl</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00050">OutputPage.php:50</a></div></div> <div class="ttc" id="classOutputPage_html_a294d125150b7a095cf5529e1fc75fd54"><div class="ttname"><a href="classOutputPage.html#a294d125150b7a095cf5529e1fc75fd54">OutputPage\$mLinktags</a></div><div class="ttdeci">array $mLinktags</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00047">OutputPage.php:47</a></div></div> <div class="ttc" id="classOutputPage_html_a0b492edfed8cf9eafc32580008e26027"><div class="ttname"><a href="classOutputPage.html#a0b492edfed8cf9eafc32580008e26027">OutputPage\addMeta</a></div><div class="ttdeci">addMeta($name, $val)</div><div class="ttdoc">Add a new "<meta>" tag To add an http-equiv meta tag, precede the name with "http:". </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00372">OutputPage.php:372</a></div></div> <div class="ttc" id="GlobalFunctions_8php_html_abfeadc51b922aa4f32f1c5f6a3c2f5f2"><div class="ttname"><a href="GlobalFunctions_8php.html#abfeadc51b922aa4f32f1c5f6a3c2f5f2">TS_MW</a></div><div class="ttdeci">const TS_MW</div><div class="ttdoc">MediaWiki concatenated string timestamp (YYYYMMDDHHMMSS) </div><div class="ttdef"><b>Definition:</b> <a href="GlobalFunctions_8php_source.html#l01999">GlobalFunctions.php:1999</a></div></div> <div class="ttc" id="classOutputPage_html_add837040d9e9601c9ad7fd4855399b0b"><div class="ttname"><a href="classOutputPage.html#add837040d9e9601c9ad7fd4855399b0b">OutputPage\addLanguageLinks</a></div><div class="ttdeci">addLanguageLinks(array $newLinkArray)</div><div class="ttdoc">Add new language links. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01238">OutputPage.php:1238</a></div></div> <div class="ttc" id="classOutputPage_html_af352fd56bac015bc8277aad6072f5a27"><div class="ttname"><a href="classOutputPage.html#af352fd56bac015bc8277aad6072f5a27">OutputPage\getTarget</a></div><div class="ttdeci">getTarget()</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00648">OutputPage.php:648</a></div></div> <div class="ttc" id="GlobalFunctions_8php_html_a3767c8d03afbee6be3231add01d62ca1"><div class="ttname"><a href="GlobalFunctions_8php.html#a3767c8d03afbee6be3231add01d62ca1">wfGetAllCallers</a></div><div class="ttdeci">wfGetAllCallers($limit=3)</div><div class="ttdoc">Return a string consisting of callers in the stack. </div><div class="ttdef"><b>Definition:</b> <a href="GlobalFunctions_8php_source.html#l01587">GlobalFunctions.php:1587</a></div></div> <div class="ttc" id="hooks_8txt_html_a83cf8b3d1cb79bd9d116941793fb7964"><div class="ttname"><a href="hooks_8txt.html#a83cf8b3d1cb79bd9d116941793fb7964">messages</a></div><div class="ttdeci">this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context the output can only depend on parameters provided to this hook not on global state indicating whether full HTML should be generated If generation of HTML may be but other information should still be present in the ParserOutput object to manipulate or replace but no entry for that model exists in $wgContentHandlers if desired whether it is OK to use $contentModel on $title Handler functions that modify $ok should generally return false to prevent further hooks from further modifying $ok inclusive false for true for descending in case the handler function wants to provide a converted Content object Note that $result getContentModel() must return $toModel. 'CustomEditor'you ll need to handle error messages</div><div class="ttdef"><b>Definition:</b> <a href="hooks_8txt_source.html#l01099">hooks.txt:1099</a></div></div> <div class="ttc" id="classOutputPage_html_ac59084e3de662e92cff290d230b3fdce"><div class="ttname"><a href="classOutputPage.html#ac59084e3de662e92cff290d230b3fdce">OutputPage\$mLastModified</a></div><div class="ttdeci">string $mLastModified</div><div class="ttdoc">Variable mLastModified and mEtag are used for sending cache control. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00110">OutputPage.php:110</a></div></div> <div class="ttc" id="injection_8txt_html_a9be135e7ed50352b0681046d2258704d"><div class="ttname"><a href="injection_8txt.html#a9be135e7ed50352b0681046d2258704d">php</a></div><div class="ttdeci">injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php</div><div class="ttdef"><b>Definition:</b> <a href="injection_8txt_source.html#l00035">injection.txt:35</a></div></div> <div class="ttc" id="GlobalFunctions_8php_html_a79db634652da5a2541f9c1c69c73f20f"><div class="ttname"><a href="GlobalFunctions_8php.html#a79db634652da5a2541f9c1c69c73f20f">wfSetVar</a></div><div class="ttdeci">wfSetVar(&$dest, $source, $force=false)</div><div class="ttdoc">Sets dest to source and returns the original value of dest If source is NULL, it just returns the val...</div><div class="ttdef"><b>Definition:</b> <a href="GlobalFunctions_8php_source.html#l01717">GlobalFunctions.php:1717</a></div></div> <div class="ttc" id="classResourceLoaderModule_html_a52bc16ee3a7bd5ab6f9dce699ae0ba04"><div class="ttname"><a href="classResourceLoaderModule.html#a52bc16ee3a7bd5ab6f9dce699ae0ba04">ResourceLoaderModule\TYPE_STYLES</a></div><div class="ttdeci">const TYPE_STYLES</div><div class="ttdef"><b>Definition:</b> <a href="ResourceLoaderModule_8php_source.html#l00035">ResourceLoaderModule.php:35</a></div></div> <div class="ttc" id="classResourceLoader_html_a337cdcaa27834db6a2180bb7a8e5c754"><div class="ttname"><a href="classResourceLoader.html#a337cdcaa27834db6a2180bb7a8e5c754">ResourceLoader\inDebugMode</a></div><div class="ttdeci">static inDebugMode()</div><div class="ttdoc">Determine whether debug mode was requested Order of priority is 1) request param, 2) cookie...</div><div class="ttdef"><b>Definition:</b> <a href="ResourceLoader_8php_source.html#l01431">ResourceLoader.php:1431</a></div></div> <div class="ttc" id="opensearch__desc_8php_html_a3ad3a4240c0f97c7e85aff5c52a454d4"><div class="ttname"><a href="opensearch__desc_8php.html#a3ad3a4240c0f97c7e85aff5c52a454d4">print</a></div><div class="ttdeci">print</div><div class="ttdef"><b>Definition:</b> <a href="opensearch__desc_8php_source.html#l00041">opensearch_desc.php:41</a></div></div> <div class="ttc" id="classOutputPage_html_a3a5bf26cb814f42796b03302c2b1b4ad"><div class="ttname"><a href="classOutputPage.html#a3a5bf26cb814f42796b03302c2b1b4ad">OutputPage\addParserOutputNoText</a></div><div class="ttdeci">addParserOutputNoText($parserOutput)</div><div class="ttdoc">Add a ParserOutput object, but without Html. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01748">OutputPage.php:1748</a></div></div> <div class="ttc" id="group__Constants_html_ga1dfb07ffcecaf8578d3ea3b0784b9a0b"><div class="ttname"><a href="group__Constants.html#ga1dfb07ffcecaf8578d3ea3b0784b9a0b">PROTO_CANONICAL</a></div><div class="ttdeci">const PROTO_CANONICAL</div><div class="ttdef"><b>Definition:</b> <a href="Defines_8php_source.html#l00265">Defines.php:265</a></div></div> <div class="ttc" id="classResourceLoaderModule_html_a5a21480d171b8c5ab7e208c1595496a0"><div class="ttname"><a href="classResourceLoaderModule.html#a5a21480d171b8c5ab7e208c1595496a0">ResourceLoaderModule\TYPE_COMBINED</a></div><div class="ttdeci">const TYPE_COMBINED</div><div class="ttdef"><b>Definition:</b> <a href="ResourceLoaderModule_8php_source.html#l00036">ResourceLoaderModule.php:36</a></div></div> <div class="ttc" id="classOutputPage_html_af89070ecdf543e1e68be7918378ea6b4"><div class="ttname"><a href="classOutputPage.html#af89070ecdf543e1e68be7918378ea6b4">OutputPage\getHeadLinks</a></div><div class="ttdeci">getHeadLinks()</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l03586">OutputPage.php:3586</a></div></div> <div class="ttc" id="hooks_8txt_html_a9a91825f641ae063ec98b842676f4510"><div class="ttname"><a href="hooks_8txt.html#a9a91825f641ae063ec98b842676f4510">$request</a></div><div class="ttdeci">error also a ContextSource you ll probably need to make sure the header is varied on $request</div><div class="ttdef"><b>Definition:</b> <a href="hooks_8txt_source.html#l02418">hooks.txt:2418</a></div></div> <div class="ttc" id="classOutputPage_html_a433b8859b4eb6e96f46a9dbb8f5b21ec"><div class="ttname"><a href="classOutputPage.html#a433b8859b4eb6e96f46a9dbb8f5b21ec">OutputPage\$mRevisionId</a></div><div class="ttdeci">int $mRevisionId</div><div class="ttdoc">To include the variable {{REVISIONID}}. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00246">OutputPage.php:246</a></div></div> <div class="ttc" id="classOutputPage_html_af6953b51223474d812a669df88dc9dfd"><div class="ttname"><a href="classOutputPage.html#af6953b51223474d812a669df88dc9dfd">OutputPage\setSquidMaxage</a></div><div class="ttdeci">setSquidMaxage($maxage)</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01930">OutputPage.php:1930</a></div></div> <div class="ttc" id="classOutputPage_html_add6cc41891d878d9067c72b328e1de2f"><div class="ttname"><a href="classOutputPage.html#add6cc41891d878d9067c72b328e1de2f">OutputPage\setRevisionTimestamp</a></div><div class="ttdeci">setRevisionTimestamp($timestamp)</div><div class="ttdoc">Set the timestamp of the revision which will be displayed. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01605">OutputPage.php:1605</a></div></div> <div class="ttc" id="classOutputPage_html_a8a610730ab03ac9c6c711871b7363cbe"><div class="ttname"><a href="classOutputPage.html#a8a610730ab03ac9c6c711871b7363cbe">OutputPage\showFileCopyError</a></div><div class="ttdeci">showFileCopyError($old, $new)</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l02583">OutputPage.php:2583</a></div></div> <div class="ttc" id="classOutputPage_html_a1a35b75f40e8ee3e94ba08d1228f853a"><div class="ttname"><a href="classOutputPage.html#a1a35b75f40e8ee3e94ba08d1228f853a">OutputPage\getSyndicationLinks</a></div><div class="ttdeci">getSyndicationLinks()</div><div class="ttdoc">Return URLs for each supported syndication format for this page. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01173">OutputPage.php:1173</a></div></div> <div class="ttc" id="namespaceWrappedString_1_1WrappedString_html"><div class="ttname"><a href="namespaceWrappedString_1_1WrappedString.html">WrappedString</a></div></div> <div class="ttc" id="classOutputPage_html_a6de9ff4af88bdff421144b7c165c05c2"><div class="ttname"><a href="classOutputPage.html#a6de9ff4af88bdff421144b7c165c05c2">OutputPage\versionRequired</a></div><div class="ttdeci">versionRequired($version)</div><div class="ttdoc">Display an error page indicating that a given version of MediaWiki is required to use it...</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l02479">OutputPage.php:2479</a></div></div> <div class="ttc" id="classSpecialPageFactory_html_adcf9ed88afa106ddce0dcc7c8a8ef8ea"><div class="ttname"><a href="classSpecialPageFactory.html#adcf9ed88afa106ddce0dcc7c8a8ef8ea">SpecialPageFactory\resolveAlias</a></div><div class="ttdeci">static resolveAlias($alias)</div><div class="ttdoc">Given a special page name with a possible subpage, return an array where the first element is the spe...</div><div class="ttdef"><b>Definition:</b> <a href="SpecialPageFactory_8php_source.html#l00338">SpecialPageFactory.php:338</a></div></div> <div class="ttc" id="classOutputPage_html_a64723d91c439f469a1b4029f9aa4e221"><div class="ttname"><a href="classOutputPage.html#a64723d91c439f469a1b4029f9aa4e221">OutputPage\enableTOC</a></div><div class="ttdeci">enableTOC($flag=true)</div><div class="ttdoc">Enables/disables TOC, doesn't override NOTOC </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l04003">OutputPage.php:4003</a></div></div> <div class="ttc" id="classOutputPage_html_a25ce0e4633bcf074279838b727a67ff0"><div class="ttname"><a href="classOutputPage.html#a25ce0e4633bcf074279838b727a67ff0">OutputPage\transformCssMedia</a></div><div class="ttdeci">static transformCssMedia($media)</div><div class="ttdoc">Transform "media" attribute based on request parameters. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l03885">OutputPage.php:3885</a></div></div> <div class="ttc" id="classSanitizer_html_a7e83e99163ef9b2640ea5dbe82841a77"><div class="ttname"><a href="classSanitizer.html#a7e83e99163ef9b2640ea5dbe82841a77">Sanitizer\normalizeCharReferences</a></div><div class="ttdeci">static normalizeCharReferences($text)</div><div class="ttdoc">Ensure that any entities and character references are legal for XML and XHTML specifically. </div><div class="ttdef"><b>Definition:</b> <a href="Sanitizer_8php_source.html#l01361">Sanitizer.php:1361</a></div></div> <div class="ttc" id="classOutputPage_html_a2670a987a71116a9da67e0fff5aadc9b"><div class="ttname"><a href="classOutputPage.html#a2670a987a71116a9da67e0fff5aadc9b">OutputPage\setArticleBodyOnly</a></div><div class="ttdeci">setArticleBodyOnly($only)</div><div class="ttdoc">Set whether the output should only contain the body of the article, without any skin, sidebar, etc. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00712">OutputPage.php:712</a></div></div> <div class="ttc" id="classOutputPage_html_ad3c1c4a4229f4c06f5eaaa0fa7e6d5be"><div class="ttname"><a href="classOutputPage.html#ad3c1c4a4229f4c06f5eaaa0fa7e6d5be">OutputPage\getProperty</a></div><div class="ttdeci">getProperty($name)</div><div class="ttdoc">Get an additional output property. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00743">OutputPage.php:743</a></div></div> <div class="ttc" id="classOutputPage_html_ad5c85109e32f2955deef1c77f125bc51"><div class="ttname"><a href="classOutputPage.html#ad5c85109e32f2955deef1c77f125bc51">OutputPage\addModuleMessages</a></div><div class="ttdeci">addModuleMessages($modules)</div><div class="ttdoc">Load messages of one or more ResourceLoader modules. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00641">OutputPage.php:641</a></div></div> <div class="ttc" id="classOutputPage_html_ad37dc926166096712154a6e2e3ca33d8"><div class="ttname"><a href="classOutputPage.html#ad37dc926166096712154a6e2e3ca33d8">OutputPage\addHeadItem</a></div><div class="ttdeci">addHeadItem($name, $value)</div><div class="ttdoc">Add or replace an header item to the output. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00682">OutputPage.php:682</a></div></div> <div class="ttc" id="classOutputPage_html_a362b04977e72809c8ad671a801669fef"><div class="ttname"><a href="classOutputPage.html#a362b04977e72809c8ad671a801669fef">OutputPage\output</a></div><div class="ttdeci">output()</div><div class="ttdoc">Finally, all the text has been munged and accumulated into the object, let's actually output it: ...</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l02234">OutputPage.php:2234</a></div></div> <div class="ttc" id="classHtml_html_ada5267488ca8c4f1965d3539944059e5"><div class="ttname"><a href="classHtml.html#ada5267488ca8c4f1965d3539944059e5">Html\isXmlMimeType</a></div><div class="ttdeci">static isXmlMimeType($mimetype)</div><div class="ttdoc">Determines if the given MIME type is xml. </div><div class="ttdef"><b>Definition:</b> <a href="Html_8php_source.html#l00955">Html.php:955</a></div></div> <div class="ttc" id="classFile_html_a4487966efdadb09d367edeb6fe08a9c3"><div class="ttname"><a href="classFile.html#a4487966efdadb09d367edeb6fe08a9c3">File\exists</a></div><div class="ttdeci">exists()</div><div class="ttdoc">Returns true if file exists in the repository. </div><div class="ttdef"><b>Definition:</b> <a href="File_8php_source.html#l00876">File.php:876</a></div></div> <div class="ttc" id="GlobalFunctions_8php_html_aa1d453df706a70f66abdf47b6c0a221c"><div class="ttname"><a href="GlobalFunctions_8php.html#aa1d453df706a70f66abdf47b6c0a221c">wfArrayToCgi</a></div><div class="ttdeci">wfArrayToCgi($array1, $array2=null, $prefix= '')</div><div class="ttdoc">This function takes one or two arrays as input, and returns a CGI-style string, e.g. </div><div class="ttdef"><b>Definition:</b> <a href="GlobalFunctions_8php_source.html#l00405">GlobalFunctions.php:405</a></div></div> <div class="ttc" id="classOutputPage_html_ae3443d128fef247f051519ab4c4a7f6a"><div class="ttname"><a href="classOutputPage.html#ae3443d128fef247f051519ab4c4a7f6a">OutputPage\$mRedirectCode</a></div><div class="ttdeci">string $mRedirectCode</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00177">OutputPage.php:177</a></div></div> <div class="ttc" id="classOutputPage_html_a6c81739da3b9bc50554a7eda0e3ab042"><div class="ttname"><a href="classOutputPage.html#a6c81739da3b9bc50554a7eda0e3ab042">OutputPage\__construct</a></div><div class="ttdeci">__construct(IContextSource $context=null)</div><div class="ttdoc">Constructor for OutputPage. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00314">OutputPage.php:314</a></div></div> <div class="ttc" id="classOutputPage_html_a195b2f7c4021cadc450bf99fc20fb378"><div class="ttname"><a href="classOutputPage.html#a195b2f7c4021cadc450bf99fc20fb378">OutputPage\$mImageTimeKeys</a></div><div class="ttdeci">array $mImageTimeKeys</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00174">OutputPage.php:174</a></div></div> <div class="ttc" id="classOutputPage_html_a9585cc35248eda7efe8a8792ecf248dc"><div class="ttname"><a href="classOutputPage.html#a9585cc35248eda7efe8a8792ecf248dc">OutputPage\getResourceLoader</a></div><div class="ttdeci">getResourceLoader()</div><div class="ttdoc">Get a ResourceLoader object associated with this OutputPage. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l02735">OutputPage.php:2735</a></div></div> <div class="ttc" id="classOutputPage_html_acaa0afb71bf33d0aa188407794516c70"><div class="ttname"><a href="classOutputPage.html#acaa0afb71bf33d0aa188407794516c70">OutputPage\getRevisionId</a></div><div class="ttdeci">getRevisionId()</div><div class="ttdoc">Get the displayed revision ID. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01594">OutputPage.php:1594</a></div></div> <div class="ttc" id="classOutputPage_html_a25af79e53d58536bd343061ecc5398b7"><div class="ttname"><a href="classOutputPage.html#a25af79e53d58536bd343061ecc5398b7">OutputPage\setupOOUI</a></div><div class="ttdeci">static setupOOUI($skinName= '', $dir= 'ltr')</div><div class="ttdoc">Helper function to setup the PHP implementation of OOUI to use in this request. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l04039">OutputPage.php:4039</a></div></div> <div class="ttc" id="GlobalFunctions_8php_html_aa7ec0fc303580abed6ac798349db580c"><div class="ttname"><a href="GlobalFunctions_8php.html#aa7ec0fc303580abed6ac798349db580c">wfClearOutputBuffers</a></div><div class="ttdeci">wfClearOutputBuffers()</div><div class="ttdoc">More legible than passing a 'false' parameter to wfResetOutputBuffers(): </div><div class="ttdef"><b>Definition:</b> <a href="GlobalFunctions_8php_source.html#l01859">GlobalFunctions.php:1859</a></div></div> <div class="ttc" id="classOutputPage_html_a3e3c33a8aeff2ca5c1f48d97605259e7"><div class="ttname"><a href="classOutputPage.html#a3e3c33a8aeff2ca5c1f48d97605259e7">OutputPage\getFileVersion</a></div><div class="ttdeci">getFileVersion()</div><div class="ttdoc">Get the displayed file version. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01638">OutputPage.php:1638</a></div></div> <div class="ttc" id="design_8txt_html_a151e6372335f583233d859073a2aa100"><div class="ttname"><a href="design_8txt.html#a151e6372335f583233d859073a2aa100">$wgContLang</a></div><div class="ttdeci">this class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as and the local content language as $wgContLang</div><div class="ttdef"><b>Definition:</b> <a href="design_8txt_source.html#l00056">design.txt:56</a></div></div> <div class="ttc" id="classOutputPage_html_afb8cc09f33554842914ddeb78639aeed"><div class="ttname"><a href="classOutputPage.html#afb8cc09f33554842914ddeb78639aeed">OutputPage\setIndexPolicy</a></div><div class="ttdeci">setIndexPolicy($policy)</div><div class="ttdoc">Set the index policy for the page, but leave the follow policy un- touched. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00879">OutputPage.php:879</a></div></div> <div class="ttc" id="classOutputPage_html_aa1d24ab42262f8c082cffd01f4933102"><div class="ttname"><a href="classOutputPage.html#aa1d24ab42262f8c082cffd01f4933102">OutputPage\getScriptsForBottomQueue</a></div><div class="ttdeci">getScriptsForBottomQueue($unused=null)</div><div class="ttdoc">JS stuff to put at the 'bottom', which goes at the bottom of the <body>. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l03044">OutputPage.php:3044</a></div></div> <div class="ttc" id="classOutputPage_html_a2b5e49a97e61d2fee5c92c9524bf92ca"><div class="ttname"><a href="classOutputPage.html#a2b5e49a97e61d2fee5c92c9524bf92ca">OutputPage\setProperty</a></div><div class="ttdeci">setProperty($name, $value)</div><div class="ttdoc">Set an additional output property. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00732">OutputPage.php:732</a></div></div> <div class="ttc" id="classOutputPage_html_acec518bad61fc88f0c3deca963d855d8"><div class="ttname"><a href="classOutputPage.html#acec518bad61fc88f0c3deca963d855d8">OutputPage\forceHideNewSectionLink</a></div><div class="ttdeci">forceHideNewSectionLink()</div><div class="ttdoc">Forcibly hide the new section link? </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01108">OutputPage.php:1108</a></div></div> <div class="ttc" id="logger_8txt_html_a2d4dcfb81a3319f223f49e727b603cd8"><div class="ttname"><a href="logger_8txt.html#a2d4dcfb81a3319f223f49e727b603cd8">LoggerFactory</a></div><div class="ttdeci">MediaWiki Logger LoggerFactory implements a PSR[0] compatible message logging system Named Psr Log LoggerInterface instances can be obtained from the MediaWiki Logger LoggerFactory::getInstance() static method.MediaWiki\Logger\LoggerFactory expects a class implementing the MediaWiki\Logger\Spi interface to act as a factory for new Psr\Log\LoggerInterface instances.The"Spi"in MediaWiki\Logger\Spi stands for"service provider interface".An SPI is an API intended to be implemented or extended by a third party.This software design pattern is intended to enable framework extension and replaceable components.It is specifically used in the MediaWiki\Logger\LoggerFactory service to allow alternate PSR-3 logging implementations to be easily integrated with MediaWiki.The service provider interface allows the backend logging library to be implemented in multiple ways.The $wgMWLoggerDefaultSpi global provides the classname of the default MediaWiki\Logger\Spi implementation to be loaded at runtime.This can either be the name of a class implementing the MediaWiki\Logger\Spi with a zero argument const ructor or a callable that will return an MediaWiki\Logger\Spi instance.Alternately the MediaWiki\Logger\LoggerFactory MediaWiki Logger LoggerFactory</div><div class="ttdef"><b>Definition:</b> <a href="logger_8txt_source.html#l00005">logger.txt:5</a></div></div> <div class="ttc" id="classOutputPage_html_ac5edd2167a9f85e4d2257af9662652d2"><div class="ttname"><a href="classOutputPage.html#ac5edd2167a9f85e4d2257af9662652d2">OutputPage\wrapWikiMsg</a></div><div class="ttdeci">wrapWikiMsg($wrap)</div><div class="ttdoc">This function takes a number of message/argument specifications, wraps them in some overall structure...</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l03973">OutputPage.php:3973</a></div></div> <div class="ttc" id="classOutputPage_html_a1dbd46a260249138845ccb6bce086090"><div class="ttname"><a href="classOutputPage.html#a1dbd46a260249138845ccb6bce086090">OutputPage\$mIsarticle</a></div><div class="ttdeci">bool $mIsarticle</div><div class="ttdoc">Is the displayed content related to the source of the corresponding wiki article. ...</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00083">OutputPage.php:83</a></div></div> <div class="ttc" id="namespaceConfig_html"><div class="ttname"><a href="namespaceConfig.html">Config</a></div></div> <div class="ttc" id="classOutputPage_html_aebd9a6e15140d9129190b3143baa4fdf"><div class="ttname"><a href="classOutputPage.html#aebd9a6e15140d9129190b3143baa4fdf">OutputPage\getBottomScripts</a></div><div class="ttdeci">getBottomScripts()</div><div class="ttdoc">JS stuff to put at the bottom of the "<body>". </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l03117">OutputPage.php:3117</a></div></div> <div class="ttc" id="classOutputPage_html_a0f8a850bc9376a121f746edd3f90351f"><div class="ttname"><a href="classOutputPage.html#a0f8a850bc9376a121f746edd3f90351f">OutputPage\setFileVersion</a></div><div class="ttdeci">setFileVersion($file)</div><div class="ttdoc">Set the displayed file version. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01625">OutputPage.php:1625</a></div></div> <div class="ttc" id="classOutputPage_html_a32357beb62615652b97f2c416d805715"><div class="ttname"><a href="classOutputPage.html#a32357beb62615652b97f2c416d805715">OutputPage\getRedirect</a></div><div class="ttdeci">getRedirect()</div><div class="ttdoc">Get the URL to redirect to, or an empty string if not redirect URL set. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00340">OutputPage.php:340</a></div></div> <div class="ttc" id="classOutputPage_html_a73bd96a7dfd5ee922f734f5874caaf19"><div class="ttname"><a href="classOutputPage.html#a73bd96a7dfd5ee922f734f5874caaf19">OutputPage\addReturnTo</a></div><div class="ttdeci">addReturnTo($title, array $query=[], $text=null, $options=[])</div><div class="ttdoc">Add a "return to" link pointing to a specified title. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l02607">OutputPage.php:2607</a></div></div> <div class="ttc" id="classResourceLoader_html_a15b0fb203d740d80f7a8d9aa1996e052"><div class="ttname"><a href="classResourceLoader.html#a15b0fb203d740d80f7a8d9aa1996e052">ResourceLoader\makeLoaderQuery</a></div><div class="ttdeci">static makeLoaderQuery($modules, $lang, $skin, $user=null, $version=null, $debug=false, $only=null, $printable=false, $handheld=false, $extraQuery=[])</div><div class="ttdoc">Build a query array (array representation of query string) for load.php. </div><div class="ttdef"><b>Definition:</b> <a href="ResourceLoader_8php_source.html#l01539">ResourceLoader.php:1539</a></div></div> <div class="ttc" id="classOutputPage_html_ad836d88e679e1812c4a3d501377e5963"><div class="ttname"><a href="classOutputPage.html#ad836d88e679e1812c4a3d501377e5963">OutputPage\$mIndexPolicy</a></div><div class="ttdeci">$mIndexPolicy</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00269">OutputPage.php:269</a></div></div> <div class="ttc" id="classOutputPage_html_a8a195beaa4f23a362fc942b107d5a1a9"><div class="ttname"><a href="classOutputPage.html#a8a195beaa4f23a362fc942b107d5a1a9">OutputPage\setRevisionId</a></div><div class="ttdeci">setRevisionId($revid)</div><div class="ttdoc">Set the revision ID which will be seen by the wiki text parser for things such as embedded {{REVISION...</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01584">OutputPage.php:1584</a></div></div> <div class="ttc" id="classOutputPage_html_af0ba3170ef41dfefee04683f704944d8"><div class="ttname"><a href="classOutputPage.html#af0ba3170ef41dfefee04683f704944d8">OutputPage\getKeyHeader</a></div><div class="ttdeci">getKeyHeader()</div><div class="ttdoc">Get a complete Key header. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l02045">OutputPage.php:2045</a></div></div> <div class="ttc" id="parserTests_8php_html_a17c8948c68aa44fa9961ae169b6a8961"><div class="ttname"><a href="parserTests_8php.html#a17c8948c68aa44fa9961ae169b6a8961">$version</a></div><div class="ttdeci">$version</div><div class="ttdef"><b>Definition:</b> <a href="parserTests_8php_source.html#l00085">parserTests.php:85</a></div></div> <div class="ttc" id="classLinkBatch_html_af729dcb9268abd17b2948550ce3a21b9"><div class="ttname"><a href="classLinkBatch.html#af729dcb9268abd17b2948550ce3a21b9">LinkBatch\setArray</a></div><div class="ttdeci">setArray($array)</div><div class="ttdoc">Set the link list to a given 2-d array First key is the namespace, second is the DB key...</div><div class="ttdef"><b>Definition:</b> <a href="LinkBatch_8php_source.html#l00091">LinkBatch.php:91</a></div></div> <div class="ttc" id="classSanitizer_html_ade17d9e33f209a075f0f75ef91121f37"><div class="ttname"><a href="classSanitizer.html#ade17d9e33f209a075f0f75ef91121f37">Sanitizer\removeHTMLtags</a></div><div class="ttdeci">static removeHTMLtags($text, $processCallback=null, $args=[], $extratags=[], $removetags=[])</div><div class="ttdoc">Cleans up HTML, removes dangerous tags and attributes, and removes HTML comments. ...</div><div class="ttdef"><b>Definition:</b> <a href="Sanitizer_8php_source.html#l00455">Sanitizer.php:455</a></div></div> <div class="ttc" id="classOutputPage_html_aaaed566db54e8402875b9c83facb64c8"><div class="ttname"><a href="classOutputPage.html#aaaed566db54e8402875b9c83facb64c8">OutputPage\showUnexpectedValueError</a></div><div class="ttdeci">showUnexpectedValueError($name, $val)</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l02579">OutputPage.php:2579</a></div></div> <div class="ttc" id="GlobalFunctions_8php_html_ad0015ddead36d67a7eedcd20edb3474b"><div class="ttname"><a href="GlobalFunctions_8php.html#ad0015ddead36d67a7eedcd20edb3474b">wfLogWarning</a></div><div class="ttdeci">wfLogWarning($msg, $callerOffset=1, $level=E_USER_WARNING)</div><div class="ttdoc">Send a warning as a PHP error and the debug log. </div><div class="ttdef"><b>Definition:</b> <a href="GlobalFunctions_8php_source.html#l01152">GlobalFunctions.php:1152</a></div></div> <div class="ttc" id="GlobalFunctions_8php_html_ab463bbe9cfff3247e113ceec3fde2c63"><div class="ttname"><a href="GlobalFunctions_8php.html#ab463bbe9cfff3247e113ceec3fde2c63">TS_UNIX</a></div><div class="ttdeci">const TS_UNIX</div><div class="ttdoc">Unix time - the number of seconds since 1970-01-01 00:00:00 UTC. </div><div class="ttdef"><b>Definition:</b> <a href="GlobalFunctions_8php_source.html#l01994">GlobalFunctions.php:1994</a></div></div> <div class="ttc" id="classOutputPage_html_a925bb60cb941e1b5db0f0af194a19703"><div class="ttname"><a href="classOutputPage.html#a925bb60cb941e1b5db0f0af194a19703">OutputPage\$mSubtitle</a></div><div class="ttdeci">array $mSubtitle</div><div class="ttdoc">Contains the page subtitle. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00098">OutputPage.php:98</a></div></div> <div class="ttc" id="classOutputPage_html_a232bb330000336185e67afd7416ca284"><div class="ttname"><a href="classOutputPage.html#a232bb330000336185e67afd7416ca284">OutputPage\redirect</a></div><div class="ttdeci">redirect($url, $responsecode= '302')</div><div class="ttdoc">Redirect to $url rather than displaying the normal page. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00329">OutputPage.php:329</a></div></div> <div class="ttc" id="classOutputPage_html_a8156613bf23495bc76f27a88d6e63fa5"><div class="ttname"><a href="classOutputPage.html#a8156613bf23495bc76f27a88d6e63fa5">OutputPage\$mPagetitle</a></div><div class="ttdeci">string $mPagetitle</div><div class="ttdoc">Should be private - has getter and setter. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00061">OutputPage.php:61</a></div></div> <div class="ttc" id="classResourceLoaderModule_html_ad3f8b6431503c33669f565128495639e"><div class="ttname"><a href="classResourceLoaderModule.html#ad3f8b6431503c33669f565128495639e">ResourceLoaderModule\TYPE_SCRIPTS</a></div><div class="ttdeci">const TYPE_SCRIPTS</div><div class="ttdef"><b>Definition:</b> <a href="ResourceLoaderModule_8php_source.html#l00034">ResourceLoaderModule.php:34</a></div></div> <div class="ttc" id="classOutputPage_html_a4c104c224e6ee6fdc0760624f9ce7f72"><div class="ttname"><a href="classOutputPage.html#a4c104c224e6ee6fdc0760624f9ce7f72">OutputPage\getHtmlFromLoaderLinks</a></div><div class="ttdeci">static getHtmlFromLoaderLinks(array $links)</div><div class="ttdoc">Build html output from an array of links from makeResourceLoaderLink. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l02930">OutputPage.php:2930</a></div></div> <div class="ttc" id="NoLocalSettings_8php_html_a0a4baf0b22973c07685c3981f0d17fc4"><div class="ttname"><a href="NoLocalSettings_8php.html#a0a4baf0b22973c07685c3981f0d17fc4">$path</a></div><div class="ttdeci">$path</div><div class="ttdef"><b>Definition:</b> <a href="NoLocalSettings_8php_source.html#l00026">NoLocalSettings.php:26</a></div></div> <div class="ttc" id="classOutputPage_html_a7b65b571803fab1ddbab17573315a5bc"><div class="ttname"><a href="classOutputPage.html#a7b65b571803fab1ddbab17573315a5bc">OutputPage\showPermissionsErrorPage</a></div><div class="ttdeci">showPermissionsErrorPage(array $errors, $action=null)</div><div class="ttdoc">Output a standard permission error page. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l02407">OutputPage.php:2407</a></div></div> <div class="ttc" id="classOutputPage_html_abcd6bfe25a20e4f0a56126fc6efa51cf"><div class="ttname"><a href="classOutputPage.html#abcd6bfe25a20e4f0a56126fc6efa51cf">OutputPage\getCacheVaryCookies</a></div><div class="ttdeci">getCacheVaryCookies()</div><div class="ttdoc">Get the list of cookies that will influence on the cache. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01970">OutputPage.php:1970</a></div></div> <div class="ttc" id="classOutputPage_html_acc1fec08f2f1a2de0911f05cb64972b7"><div class="ttname"><a href="classOutputPage.html#acc1fec08f2f1a2de0911f05cb64972b7">OutputPage\getModuleMessages</a></div><div class="ttdeci">getModuleMessages($filter=false, $position=null)</div><div class="ttdoc">Get the list of module messages to include on this page. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00630">OutputPage.php:630</a></div></div> <div class="ttc" id="GlobalFunctions_8php_html_a0edae2a1c2224298a143303f97a1ea5c"><div class="ttname"><a href="GlobalFunctions_8php.html#a0edae2a1c2224298a143303f97a1ea5c">wfTimestampOrNull</a></div><div class="ttdeci">wfTimestampOrNull($outputtype=TS_UNIX, $ts=null)</div><div class="ttdoc">Return a formatted timestamp, or null if input is null. </div><div class="ttdef"><b>Definition:</b> <a href="GlobalFunctions_8php_source.html#l02068">GlobalFunctions.php:2068</a></div></div> <div class="ttc" id="classOutputPage_html_a7fa6a137980265694e6aa84198a0d8f5"><div class="ttname"><a href="classOutputPage.html#a7fa6a137980265694e6aa84198a0d8f5">OutputPage\setArticleFlag</a></div><div class="ttdeci">setArticleFlag($v)</div><div class="ttdoc">Set whether the displayed content is related to the source of the corresponding article on the wiki S...</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01193">OutputPage.php:1193</a></div></div> <div class="ttc" id="classOutputPage_html_ad843efcec1f915688d2a4d6c79b17e5c"><div class="ttname"><a href="classOutputPage.html#ad843efcec1f915688d2a4d6c79b17e5c">OutputPage\showFileDeleteError</a></div><div class="ttdeci">showFileDeleteError($name)</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l02591">OutputPage.php:2591</a></div></div> <div class="ttc" id="classXml_html_a60640cfebaa2daf82f1dfb70b846e040"><div class="ttname"><a href="classXml.html#a60640cfebaa2daf82f1dfb70b846e040">Xml\encodeJsCall</a></div><div class="ttdeci">static encodeJsCall($name, $args, $pretty=false)</div><div class="ttdoc">Create a call to a JavaScript function. </div><div class="ttdef"><b>Definition:</b> <a href="Xml_8php_source.html#l00682">Xml.php:682</a></div></div> <div class="ttc" id="classFile_html"><div class="ttname"><a href="classFile.html">File</a></div><div class="ttdoc">Implements some public methods and some protected utility functions which are required by multiple ch...</div><div class="ttdef"><b>Definition:</b> <a href="File_8php_source.html#l00050">File.php:50</a></div></div> <div class="ttc" id="classOutputPage_html_aa93ad6de2db94d9c22705906584893c5"><div class="ttname"><a href="classOutputPage.html#aa93ad6de2db94d9c22705906584893c5">OutputPage\addWikiTextTidy</a></div><div class="ttdeci">addWikiTextTidy($text, $linestart=true)</div><div class="ttdoc">Add wikitext with tidy enabled. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01707">OutputPage.php:1707</a></div></div> <div class="ttc" id="classOutputPage_html_a413856bad81088166dc6da5588895090"><div class="ttname"><a href="classOutputPage.html#a413856bad81088166dc6da5588895090">OutputPage\$mPageTitleActionText</a></div><div class="ttdeci">string $mPageTitleActionText</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00231">OutputPage.php:231</a></div></div> <div class="ttc" id="classResourceLoader_html"><div class="ttname"><a href="classResourceLoader.html">ResourceLoader</a></div><div class="ttdoc">Dynamic JavaScript and CSS resource loading system. </div><div class="ttdef"><b>Definition:</b> <a href="ResourceLoader_8php_source.html#l00036">ResourceLoader.php:36</a></div></div> <div class="ttc" id="classContextSource_html_aeec47883940f61b3fc268e8053a0a01a"><div class="ttname"><a href="classContextSource.html#aeec47883940f61b3fc268e8053a0a01a">ContextSource\getWikiPage</a></div><div class="ttdeci">getWikiPage()</div><div class="ttdoc">Get the WikiPage object. </div><div class="ttdef"><b>Definition:</b> <a href="ContextSource_8php_source.html#l00113">ContextSource.php:113</a></div></div> <div class="ttc" id="classSkin_html_a5224a834760245b3187149c58e00d335"><div class="ttname"><a href="classSkin.html#a5224a834760245b3187149c58e00d335">Skin\getSkinName</a></div><div class="ttdeci">getSkinName()</div><div class="ttdef"><b>Definition:</b> <a href="Skin_8php_source.html#l00137">Skin.php:137</a></div></div> <div class="ttc" id="classHtml_html_ae33b3a5c765550abd96775e4e44df7c3"><div class="ttname"><a href="classHtml.html#ae33b3a5c765550abd96775e4e44df7c3">Html\linkedStyle</a></div><div class="ttdeci">static linkedStyle($url, $media= 'all')</div><div class="ttdoc">Output a "<link rel=stylesheet>" linking to the given URL for the given media type (if any)...</div><div class="ttdef"><b>Definition:</b> <a href="Html_8php_source.html#l00647">Html.php:647</a></div></div> <div class="ttc" id="classHtml_html_a1c74fee14762ec4d50e09a94c94327ef"><div class="ttname"><a href="classHtml.html#a1c74fee14762ec4d50e09a94c94327ef">Html\element</a></div><div class="ttdeci">static element($element, $attribs=[], $contents= '')</div><div class="ttdoc">Identical to rawElement(), but HTML-escapes $contents (like Xml::element()). </div><div class="ttdef"><b>Definition:</b> <a href="Html_8php_source.html#l00230">Html.php:230</a></div></div> <div class="ttc" id="classOutputPage_html_acb7603b840f300086ee43e4071775843"><div class="ttname"><a href="classOutputPage.html#acb7603b840f300086ee43e4071775843">OutputPage\setIndicators</a></div><div class="ttdeci">setIndicators(array $indicators)</div><div class="ttdoc">Add an array of indicators, with their identifiers as array keys and HTML contents as values...</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01378">OutputPage.php:1378</a></div></div> <div class="ttc" id="classOutputPage_html_aacaccc2e7f9237d87a613f334e5f406e"><div class="ttname"><a href="classOutputPage.html#aacaccc2e7f9237d87a613f334e5f406e">OutputPage\disallowUserJs</a></div><div class="ttdeci">disallowUserJs()</div><div class="ttdoc">Do not allow scripts which can be modified by wiki users to load on this page; only allow scripts bun...</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01436">OutputPage.php:1436</a></div></div> <div class="ttc" id="classResourceLoaderModule_html_a913ce5b41905ee75a79435626a9cc4ef"><div class="ttname"><a href="classResourceLoaderModule.html#a913ce5b41905ee75a79435626a9cc4ef">ResourceLoaderModule\getOrigin</a></div><div class="ttdeci">getOrigin()</div><div class="ttdoc">Get this module's origin. </div><div class="ttdef"><b>Definition:</b> <a href="ResourceLoaderModule_8php_source.html#l00113">ResourceLoaderModule.php:113</a></div></div> <div class="ttc" id="testCompression_8php_html_af20635b6c08e03bfee9e3fc036fa80f3"><div class="ttname"><a href="testCompression_8php.html#af20635b6c08e03bfee9e3fc036fa80f3">$keys</a></div><div class="ttdeci">$keys</div><div class="ttdef"><b>Definition:</b> <a href="testCompression_8php_source.html#l00065">testCompression.php:65</a></div></div> <div class="ttc" id="classContextSource_html_a4a84d5f0344e114f266fef48c6558999"><div class="ttname"><a href="classContextSource.html#a4a84d5f0344e114f266fef48c6558999">ContextSource\getUser</a></div><div class="ttdeci">getUser()</div><div class="ttdoc">Get the User object. </div><div class="ttdef"><b>Definition:</b> <a href="ContextSource_8php_source.html#l00133">ContextSource.php:133</a></div></div> <div class="ttc" id="classOutputPage_html_ac43a3cad0175d6088d38af8248223678"><div class="ttname"><a href="classOutputPage.html#ac43a3cad0175d6088d38af8248223678">OutputPage\getVaryHeader</a></div><div class="ttdeci">getVaryHeader()</div><div class="ttdoc">Return a Vary: header on which to vary caches. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l02028">OutputPage.php:2028</a></div></div> <div class="ttc" id="hooks_8txt_html_a18cb89f02456c7d0191cae3c91e677de"><div class="ttname"><a href="hooks_8txt.html#a18cb89f02456c7d0191cae3c91e677de">$vars</a></div><div class="ttdeci">static configuration should be added through ResourceLoaderGetConfigVars instead & $vars</div><div class="ttdef"><b>Definition:</b> <a href="hooks_8txt_source.html#l01996">hooks.txt:1996</a></div></div> <div class="ttc" id="classOutputPage_html_a2a51d70a197223dd7ed9a288cc91ba85"><div class="ttname"><a href="classOutputPage.html#a2a51d70a197223dd7ed9a288cc91ba85">OutputPage\getModules</a></div><div class="ttdeci">getModules($filter=false, $position=null, $param= 'mModules')</div><div class="ttdoc">Get the list of modules to include on this page. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00556">OutputPage.php:556</a></div></div> <div class="ttc" id="Setup_8php_html_ae73859032483e19f0ee2b2e781b6ecbf"><div class="ttname"><a href="Setup_8php.html#ae73859032483e19f0ee2b2e781b6ecbf">$wgRequest</a></div><div class="ttdeci">if(is_null($wgLocalTZoffset)) if(!$wgDBerrorLogTZ) $wgRequest</div><div class="ttdef"><b>Definition:</b> <a href="Setup_8php_source.html#l00657">Setup.php:657</a></div></div> <div class="ttc" id="classThrottledError_html"><div class="ttname"><a href="classThrottledError.html">ThrottledError</a></div><div class="ttdoc">Show an error when the user hits a rate limit. </div><div class="ttdef"><b>Definition:</b> <a href="ThrottledError_8php_source.html#l00027">ThrottledError.php:27</a></div></div> <div class="ttc" id="hooks_8txt_html_a7f3af9b6dc4889b59c9971064987d675"><div class="ttname"><a href="hooks_8txt.html#a7f3af9b6dc4889b59c9971064987d675">$type</a></div><div class="ttdeci">do that in ParserLimitReportFormat instead use this to modify the parameters of the image and a DIV can begin in one section and end in another Make sure your code can handle that case gracefully See the EditSectionClearerLink extension for an example zero but section is usually empty its values are the globals values before the output is cached one of or reset my talk my contributions etc etc otherwise the built in rate limiting checks are if enabled allows for interception of redirect as a string mapping parameter names to values & $type</div><div class="ttdef"><b>Definition:</b> <a href="hooks_8txt_source.html#l02338">hooks.txt:2338</a></div></div> <div class="ttc" id="classOutputPage_html_a4829fa8b52d3e210d3d2214d4025e5ca"><div class="ttname"><a href="classOutputPage.html#a4829fa8b52d3e210d3d2214d4025e5ca">OutputPage\addModuleStyles</a></div><div class="ttdeci">addModuleStyles($modules)</div><div class="ttdoc">Add only CSS of one or more modules recognized by ResourceLoader. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00618">OutputPage.php:618</a></div></div> <div class="ttc" id="namespaceMWException_html"><div class="ttname"><a href="namespaceMWException.html">MWException</a></div></div> <div class="ttc" id="classOutputPage_html_a74be7ed873b6f223ab26c7619216eb7c"><div class="ttname"><a href="classOutputPage.html#a74be7ed873b6f223ab26c7619216eb7c">OutputPage\$mRedirect</a></div><div class="ttdeci">string $mRedirect</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00101">OutputPage.php:101</a></div></div> <div class="ttc" id="classOutputPage_html_a5c16e383a4603aa4b10a3d850d220f64"><div class="ttname"><a href="classOutputPage.html#a5c16e383a4603aa4b10a3d850d220f64">OutputPage\addModuleScripts</a></div><div class="ttdeci">addModuleScripts($modules)</div><div class="ttdoc">Add only JS of one or more modules recognized by ResourceLoader. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00593">OutputPage.php:593</a></div></div> <div class="ttc" id="classOutputPage_html_ac1ef46b27a8983bb52715b491dbff9ad"><div class="ttname"><a href="classOutputPage.html#ac1ef46b27a8983bb52715b491dbff9ad">OutputPage\setCanonicalUrl</a></div><div class="ttdeci">setCanonicalUrl($url)</div><div class="ttdoc">Set the URL to be used for the <link rel="canonical">. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00424">OutputPage.php:424</a></div></div> <div class="ttc" id="classOutputPage_html_a78717094923ded7d7f41340e0522c189"><div class="ttname"><a href="classOutputPage.html#a78717094923ded7d7f41340e0522c189">OutputPage\setLastModified</a></div><div class="ttdeci">setLastModified($timestamp)</div><div class="ttdoc">Override the last modified timestamp. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00849">OutputPage.php:849</a></div></div> <div class="ttc" id="hooks_8txt_html_a2d6f8f7fee75194210501c68760b4125"><div class="ttname"><a href="hooks_8txt.html#a2d6f8f7fee75194210501c68760b4125">$attribs</a></div><div class="ttdeci">null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses after processing & $attribs</div><div class="ttdef"><b>Definition:</b> <a href="hooks_8txt_source.html#l01798">hooks.txt:1798</a></div></div> <div class="ttc" id="classOutputPage_html_af1c117c7597a9d09ccb84cee9232b64c"><div class="ttname"><a href="classOutputPage.html#af1c117c7597a9d09ccb84cee9232b64c">OutputPage\setSyndicated</a></div><div class="ttdeci">setSyndicated($show=true)</div><div class="ttdoc">Add or remove feed links in the page header This is mainly kept for backward compatibility, see OutputPage::addFeedLink() for the new version. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01120">OutputPage.php:1120</a></div></div> <div class="ttc" id="classOutputPage_html_a54d111eb0e932e01a083f6c55a8804e3"><div class="ttname"><a href="classOutputPage.html#a54d111eb0e932e01a083f6c55a8804e3">OutputPage\getRevisionTimestamp</a></div><div class="ttdeci">getRevisionTimestamp()</div><div class="ttdoc">Get the timestamp of displayed revision. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01615">OutputPage.php:1615</a></div></div> <div class="ttc" id="classOutputPage_html_abfea8e505f0a8d95dc8beb316c4579d5"><div class="ttname"><a href="classOutputPage.html#abfea8e505f0a8d95dc8beb316c4579d5">OutputPage\getLinkTags</a></div><div class="ttdeci">getLinkTags()</div><div class="ttdoc">Returns the current <link> tags. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00403">OutputPage.php:403</a></div></div> <div class="ttc" id="classOutputPage_html_a009756705931a3399dbe89b257517730"><div class="ttname"><a href="classOutputPage.html#a009756705931a3399dbe89b257517730">OutputPage\isArticle</a></div><div class="ttdeci">isArticle()</div><div class="ttdoc">Return whether the content displayed page is related to the source of the corresponding article on th...</div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l01206">OutputPage.php:1206</a></div></div> <div class="ttc" id="classResourceLoaderContext_html"><div class="ttname"><a href="classResourceLoaderContext.html">ResourceLoaderContext</a></div><div class="ttdoc">Object passed around to modules which contains information about the state of a specific loader reque...</div><div class="ttdef"><b>Definition:</b> <a href="ResourceLoaderContext_8php_source.html#l00031">ResourceLoaderContext.php:31</a></div></div> <div class="ttc" id="classOutputPage_html_aaf8b7eebb1212345cd8b3b5fe77f2ba1"><div class="ttname"><a href="classOutputPage.html#aaf8b7eebb1212345cd8b3b5fe77f2ba1">OutputPage\$mParserOptions</a></div><div class="ttdeci">ParserOptions $mParserOptions</div><div class="ttdoc">lazy initialised, use parserOptions() </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l00202">OutputPage.php:202</a></div></div> <div class="ttc" id="namespaceException_html"><div class="ttname"><a href="namespaceException.html">Exception</a></div></div> <div class="ttc" id="classOutputPage_html_a81c86f0fc996076ed05467f63b3fb154"><div class="ttname"><a href="classOutputPage.html#a81c86f0fc996076ed05467f63b3fb154">OutputPage\addJsConfigVars</a></div><div class="ttdeci">addJsConfigVars($keys, $value=null)</div><div class="ttdoc">Add one or more variables to be set in mw.config in JavaScript. </div><div class="ttdef"><b>Definition:</b> <a href="OutputPage_8php_source.html#l03137">OutputPage.php:3137</a></div></div> <div class="ttc" id="hooks_8txt_html_ae2d36f45856c4960c998f6c76c83b7a8"><div class="ttname"><a href="hooks_8txt.html#ae2d36f45856c4960c998f6c76c83b7a8">$name</a></div><div class="ttdeci">Allows to change the fields on the form that will be generated $name</div><div class="ttdef"><b>Definition:</b> <a href="hooks_8txt_source.html#l00310">hooks.txt:310</a></div></div> <div class="ttc" id="classContextSource_html_a42220e4622a75fd36e754b0e632fdc09"><div class="ttname"><a href="classContextSource.html#a42220e4622a75fd36e754b0e632fdc09">ContextSource\getSkin</a></div><div class="ttdeci">getSkin()</div><div class="ttdoc">Get the Skin object. </div><div class="ttdef"><b>Definition:</b> <a href="ContextSource_8php_source.html#l00153">ContextSource.php:153</a></div></div> <div class="ttc" id="classArticle_html_a7d076b903fbfec072c74038be0b53a47"><div class="ttname"><a href="classArticle.html#a7d076b903fbfec072c74038be0b53a47">Article\formatRobotPolicy</a></div><div class="ttdeci">static formatRobotPolicy($policy)</div><div class="ttdoc">Converts a String robot policy into an associative array, to allow merging of several policies using ...</div><div class="ttdef"><b>Definition:</b> <a href="Article_8php_source.html#l00923">Article.php:923</a></div></div> </div><!-- fragment --></div><!-- contents --> </div><!-- doc-content --> <!-- start footer part --> <div id="nav-path" class="navpath"><!-- id is needed for treeview function! --> <ul> <li class="navelem"><a class="el" href="dir_b0f92a87ee026d34ca8fad24187d57bf.html">includes</a></li><li class="navelem"><a class="el" href="OutputPage_8php.html">OutputPage.php</a></li> <li class="footer">Generated on Fri Feb 17 2017 20:42:29 for MediaWiki by <a href="http://www.doxygen.org/index.html"> <img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.8 </li> </ul> </div> </body> </html>