MediaWiki  master
OutputPage.php
Go to the documentation of this file.
1 <?php
23 use MediaWiki\HookContainer\ProtectedHookAccessorTrait;
28 use Wikimedia\RelPath;
29 use Wikimedia\WrappedString;
30 use Wikimedia\WrappedStringList;
31 
47 class OutputPage extends ContextSource {
48  use ProtectedHookAccessorTrait;
49 
51  protected $mMetatags = [];
52 
54  protected $mLinktags = [];
55 
57  protected $mCanonicalUrl = false;
58 
62  private $mPageTitle = '';
63 
71  private $displayTitle;
72 
74  private $cacheIsFinal = false;
75 
80  public $mBodytext = '';
81 
83  private $mHTMLtitle = '';
84 
89  private $mIsArticle = false;
90 
92  private $mIsArticleRelated = true;
93 
95  private $mHasCopyright = false;
96 
101  private $mPrintable = false;
102 
107  private $mSubtitle = [];
108 
110  public $mRedirect = '';
111 
113  protected $mStatusCode;
114 
119  protected $mLastModified = '';
120 
122  protected $mCategoryLinks = [];
123 
125  protected $mCategories = [
126  'hidden' => [],
127  'normal' => [],
128  ];
129 
131  protected $mIndicators = [];
132 
134  private $mLanguageLinks = [];
135 
142  private $mScripts = '';
143 
145  protected $mInlineStyles = '';
146 
151  public $mPageLinkTitle = '';
152 
157  protected $mAdditionalHtmlClasses = [];
158 
160  protected $mHeadItems = [];
161 
163  protected $mAdditionalBodyClasses = [];
164 
166  protected $mModules = [];
167 
169  protected $mModuleStyles = [];
170 
172  protected $mResourceLoader;
173 
175  private $rlClient;
176 
179 
182 
184  protected $mJsConfigVars = [];
185 
187  protected $mTemplateIds = [];
188 
190  protected $mImageTimeKeys = [];
191 
193  public $mRedirectCode = '';
194 
195  protected $mFeedLinksAppendQuery = null;
196 
202  protected $mAllowedModules = [
203  ResourceLoaderModule::TYPE_COMBINED => ResourceLoaderModule::ORIGIN_ALL,
204  ];
205 
207  protected $mDoNothing = false;
208 
209  // Parser related.
210 
212  protected $mContainsNewMagic = 0;
213 
218  protected $mParserOptions = null;
219 
225  private $mFeedLinks = [];
226 
228  protected $mEnableClientCache = true;
229 
231  private $mArticleBodyOnly = false;
232 
234  protected $mNewSectionLink = false;
235 
237  protected $mHideNewSectionLink = false;
238 
244  public $mNoGallery = false;
245 
247  protected $mCdnMaxage = 0;
249  protected $mCdnMaxageLimit = INF;
250 
256  protected $mPreventClickjacking = true;
257 
259  private $mRevisionId = null;
260 
262  private $mRevisionTimestamp = null;
263 
265  protected $mFileVersion = null;
266 
275  protected $styles = [];
276 
277  private $mIndexPolicy = 'index';
278  private $mFollowPolicy = 'follow';
279 
285  private $mVaryHeader = [
286  'Accept-Encoding' => null,
287  ];
288 
295  private $mRedirectedFrom = null;
296 
300  private $mProperties = [];
301 
305  private $mTarget = null;
306 
310  private $mEnableTOC = false;
311 
315  private $copyrightUrl;
316 
318  private $limitReportJSData = [];
319 
321  private $contentOverrides = [];
322 
325 
329  private $mLinkHeader = [];
330 
334  private $CSP;
335 
339  private static $cacheVaryCookies = null;
340 
347  public function __construct( IContextSource $context ) {
348  $this->setContext( $context );
349  $this->CSP = new ContentSecurityPolicy(
350  $context->getRequest()->response(),
351  $context->getConfig(),
352  $this->getHookContainer()
353  );
354  }
355 
362  public function redirect( $url, $responsecode = '302' ) {
363  # Strip newlines as a paranoia check for header injection in PHP<5.1.2
364  $this->mRedirect = str_replace( "\n", '', $url );
365  $this->mRedirectCode = (string)$responsecode;
366  }
367 
373  public function getRedirect() {
374  return $this->mRedirect;
375  }
376 
385  public function setCopyrightUrl( $url ) {
386  $this->copyrightUrl = $url;
387  }
388 
394  public function setStatusCode( $statusCode ) {
395  $this->mStatusCode = $statusCode;
396  }
397 
405  public function addMeta( $name, $val ) {
406  $this->mMetatags[] = [ $name, $val ];
407  }
408 
415  public function getMetaTags() {
416  return $this->mMetatags;
417  }
418 
426  public function addLink( array $linkarr ) {
427  $this->mLinktags[] = $linkarr;
428  }
429 
436  public function getLinkTags() {
437  return $this->mLinktags;
438  }
439 
445  public function setCanonicalUrl( $url ) {
446  $this->mCanonicalUrl = $url;
447  }
448 
456  public function getCanonicalUrl() {
457  return $this->mCanonicalUrl;
458  }
459 
467  public function addScript( $script ) {
468  $this->mScripts .= $script;
469  }
470 
479  public function addScriptFile( $file, $unused = null ) {
480  $this->addScript( Html::linkedScript( $file, $this->CSP->getNonce() ) );
481  }
482 
489  public function addInlineScript( $script ) {
490  $this->mScripts .= Html::inlineScript( "\n$script\n", $this->CSP->getNonce() ) . "\n";
491  }
492 
501  protected function filterModules( array $modules, $position = null,
502  $type = ResourceLoaderModule::TYPE_COMBINED
503  ) {
504  $resourceLoader = $this->getResourceLoader();
505  $filteredModules = [];
506  foreach ( $modules as $val ) {
507  $module = $resourceLoader->getModule( $val );
508  if ( $module instanceof ResourceLoaderModule
509  && $module->getOrigin() <= $this->getAllowedModules( $type )
510  ) {
511  if ( $this->mTarget && !in_array( $this->mTarget, $module->getTargets() ) ) {
512  $this->warnModuleTargetFilter( $module->getName() );
513  continue;
514  }
515  $filteredModules[] = $val;
516  }
517  }
518  return $filteredModules;
519  }
520 
521  private function warnModuleTargetFilter( $moduleName ) {
522  static $warnings = [];
523  if ( isset( $warnings[$this->mTarget][$moduleName] ) ) {
524  return;
525  }
526  $warnings[$this->mTarget][$moduleName] = true;
527  $this->getResourceLoader()->getLogger()->debug(
528  'Module "{module}" not loadable on target "{target}".',
529  [
530  'module' => $moduleName,
531  'target' => $this->mTarget,
532  ]
533  );
534  }
535 
545  public function getModules( $filter = false, $position = null, $param = 'mModules',
546  $type = ResourceLoaderModule::TYPE_COMBINED
547  ) {
548  $modules = array_values( array_unique( $this->$param ) );
549  return $filter
550  ? $this->filterModules( $modules, null, $type )
551  : $modules;
552  }
553 
559  public function addModules( $modules ) {
560  $this->mModules = array_merge( $this->mModules, (array)$modules );
561  }
562 
570  public function getModuleStyles( $filter = false, $position = null ) {
571  return $this->getModules( $filter, null, 'mModuleStyles',
572  ResourceLoaderModule::TYPE_STYLES
573  );
574  }
575 
585  public function addModuleStyles( $modules ) {
586  $this->mModuleStyles = array_merge( $this->mModuleStyles, (array)$modules );
587  }
588 
592  public function getTarget() {
593  return $this->mTarget;
594  }
595 
601  public function setTarget( $target ) {
602  $this->mTarget = $target;
603  }
604 
612  public function addContentOverride( LinkTarget $target, Content $content ) {
613  if ( !$this->contentOverrides ) {
614  // Register a callback for $this->contentOverrides on the first call
615  $this->addContentOverrideCallback( function ( LinkTarget $target ) {
616  $key = $target->getNamespace() . ':' . $target->getDBkey();
617  return $this->contentOverrides[$key] ?? null;
618  } );
619  }
620 
621  $key = $target->getNamespace() . ':' . $target->getDBkey();
622  $this->contentOverrides[$key] = $content;
623  }
624 
632  public function addContentOverrideCallback( callable $callback ) {
633  $this->contentOverrideCallbacks[] = $callback;
634  }
635 
643  public function addHtmlClasses( $classes ) {
644  $this->mAdditionalHtmlClasses = array_merge( $this->mAdditionalHtmlClasses, (array)$classes );
645  }
646 
652  public function getHeadItemsArray() {
653  return $this->mHeadItems;
654  }
655 
668  public function addHeadItem( $name, $value ) {
669  $this->mHeadItems[$name] = $value;
670  }
671 
678  public function addHeadItems( $values ) {
679  $this->mHeadItems = array_merge( $this->mHeadItems, (array)$values );
680  }
681 
688  public function hasHeadItem( $name ) {
689  return isset( $this->mHeadItems[$name] );
690  }
691 
698  public function addBodyClasses( $classes ) {
699  $this->mAdditionalBodyClasses = array_merge( $this->mAdditionalBodyClasses, (array)$classes );
700  }
701 
709  public function setArticleBodyOnly( $only ) {
710  $this->mArticleBodyOnly = $only;
711  }
712 
718  public function getArticleBodyOnly() {
720  }
721 
729  public function setProperty( $name, $value ) {
730  $this->mProperties[$name] = $value;
731  }
732 
740  public function getProperty( $name ) {
741  return $this->mProperties[$name] ?? null;
742  }
743 
755  public function checkLastModified( $timestamp ) {
756  if ( !$timestamp || $timestamp == '19700101000000' ) {
757  wfDebug( __METHOD__ . ": CACHE DISABLED, NO TIMESTAMP" );
758  return false;
759  }
760  $config = $this->getConfig();
761  if ( !$config->get( 'CachePages' ) ) {
762  wfDebug( __METHOD__ . ": CACHE DISABLED" );
763  return false;
764  }
765 
766  $timestamp = wfTimestamp( TS_MW, $timestamp );
767  $modifiedTimes = [
768  'page' => $timestamp,
769  'user' => $this->getUser()->getTouched(),
770  'epoch' => $config->get( 'CacheEpoch' )
771  ];
772  if ( $config->get( 'UseCdn' ) ) {
773  $modifiedTimes['sepoch'] = wfTimestamp( TS_MW, $this->getCdnCacheEpoch(
774  time(),
775  $config->get( 'CdnMaxAge' )
776  ) );
777  }
778  $this->getHookRunner()->onOutputPageCheckLastModified( $modifiedTimes, $this );
779 
780  $maxModified = max( $modifiedTimes );
781  $this->mLastModified = wfTimestamp( TS_RFC2822, $maxModified );
782 
783  $clientHeader = $this->getRequest()->getHeader( 'If-Modified-Since' );
784  if ( $clientHeader === false ) {
785  wfDebug( __METHOD__ . ": client did not send If-Modified-Since header", 'private' );
786  return false;
787  }
788 
789  # IE sends sizes after the date like this:
790  # Wed, 20 Aug 2003 06:51:19 GMT; length=5202
791  # this breaks strtotime().
792  $clientHeader = preg_replace( '/;.*$/', '', $clientHeader );
793 
794  Wikimedia\suppressWarnings(); // E_STRICT system time warnings
795  $clientHeaderTime = strtotime( $clientHeader );
796  Wikimedia\restoreWarnings();
797  if ( !$clientHeaderTime ) {
798  wfDebug( __METHOD__
799  . ": unable to parse the client's If-Modified-Since header: $clientHeader" );
800  return false;
801  }
802  $clientHeaderTime = wfTimestamp( TS_MW, $clientHeaderTime );
803 
804  # Make debug info
805  $info = '';
806  foreach ( $modifiedTimes as $name => $value ) {
807  if ( $info !== '' ) {
808  $info .= ', ';
809  }
810  $info .= "$name=" . wfTimestamp( TS_ISO_8601, $value );
811  }
812 
813  wfDebug( __METHOD__ . ": client sent If-Modified-Since: " .
814  wfTimestamp( TS_ISO_8601, $clientHeaderTime ), 'private' );
815  wfDebug( __METHOD__ . ": effective Last-Modified: " .
816  wfTimestamp( TS_ISO_8601, $maxModified ), 'private' );
817  if ( $clientHeaderTime < $maxModified ) {
818  wfDebug( __METHOD__ . ": STALE, $info", 'private' );
819  return false;
820  }
821 
822  # Not modified
823  # Give a 304 Not Modified response code and disable body output
824  wfDebug( __METHOD__ . ": NOT MODIFIED, $info", 'private' );
825  ini_set( 'zlib.output_compression', 0 );
826  $this->getRequest()->response()->statusHeader( 304 );
827  $this->sendCacheControl();
828  $this->disable();
829 
830  // Don't output a compressed blob when using ob_gzhandler;
831  // it's technically against HTTP spec and seems to confuse
832  // Firefox when the response gets split over two packets.
833  wfResetOutputBuffers( false );
834 
835  return true;
836  }
837 
843  private function getCdnCacheEpoch( $reqTime, $maxAge ) {
844  // Ensure Last-Modified is never more than $wgCdnMaxAge in the past,
845  // because even if the wiki page content hasn't changed since, static
846  // resources may have changed (skin HTML, interface messages, urls, etc.)
847  // and must roll-over in a timely manner (T46570)
848  return $reqTime - $maxAge;
849  }
850 
857  public function setLastModified( $timestamp ) {
858  $this->mLastModified = wfTimestamp( TS_RFC2822, $timestamp );
859  }
860 
868  public function setRobotPolicy( $policy ) {
869  $policy = Article::formatRobotPolicy( $policy );
870 
871  if ( isset( $policy['index'] ) ) {
872  $this->setIndexPolicy( $policy['index'] );
873  }
874  if ( isset( $policy['follow'] ) ) {
875  $this->setFollowPolicy( $policy['follow'] );
876  }
877  }
878 
885  public function getRobotPolicy() {
886  return "{$this->mIndexPolicy},{$this->mFollowPolicy}";
887  }
888 
895  public function setIndexPolicy( $policy ) {
896  $policy = trim( $policy );
897  if ( in_array( $policy, [ 'index', 'noindex' ] ) ) {
898  $this->mIndexPolicy = $policy;
899  }
900  }
901 
907  public function getIndexPolicy() {
908  return $this->mIndexPolicy;
909  }
910 
917  public function setFollowPolicy( $policy ) {
918  $policy = trim( $policy );
919  if ( in_array( $policy, [ 'follow', 'nofollow' ] ) ) {
920  $this->mFollowPolicy = $policy;
921  }
922  }
923 
929  public function getFollowPolicy() {
930  return $this->mFollowPolicy;
931  }
932 
939  public function setHTMLTitle( $name ) {
940  if ( $name instanceof Message ) {
941  $this->mHTMLtitle = $name->setContext( $this->getContext() )->text();
942  } else {
943  $this->mHTMLtitle = $name;
944  }
945  }
946 
952  public function getHTMLTitle() {
953  return $this->mHTMLtitle;
954  }
955 
961  public function setRedirectedFrom( $t ) {
962  $this->mRedirectedFrom = $t;
963  }
964 
977  public function setPageTitle( $name ) {
978  if ( $name instanceof Message ) {
979  $name = $name->setContext( $this->getContext() )->text();
980  }
981 
982  # change "<script>foo&bar</script>" to "&lt;script&gt;foo&amp;bar&lt;/script&gt;"
983  # but leave "<i>foobar</i>" alone
985  $this->mPageTitle = $nameWithTags;
986 
987  # change "<i>foo&amp;bar</i>" to "foo&bar"
988  $this->setHTMLTitle(
989  $this->msg( 'pagetitle' )->plaintextParams( Sanitizer::stripAllTags( $nameWithTags ) )
990  ->inContentLanguage()
991  );
992  }
993 
999  public function getPageTitle() {
1000  return $this->mPageTitle;
1001  }
1002 
1010  public function setDisplayTitle( $html ) {
1011  $this->displayTitle = $html;
1012  }
1013 
1022  public function getDisplayTitle() {
1023  $html = $this->displayTitle;
1024  if ( $html === null ) {
1025  $html = $this->getTitle()->getPrefixedText();
1026  }
1027 
1029  }
1030 
1037  public function getUnprefixedDisplayTitle() {
1038  $text = $this->getDisplayTitle();
1039  $nsPrefix = $this->getTitle()->getNsText() . ':';
1040  $prefix = preg_quote( $nsPrefix, '/' );
1041 
1042  return preg_replace( "/^$prefix/i", '', $text );
1043  }
1044 
1050  public function setTitle( Title $t ) {
1051  // @phan-suppress-next-next-line PhanUndeclaredMethod
1052  // @fixme Not all implementations of IContextSource have this method!
1053  $this->getContext()->setTitle( $t );
1054  }
1055 
1061  public function setSubtitle( $str ) {
1062  $this->clearSubtitle();
1063  $this->addSubtitle( $str );
1064  }
1065 
1071  public function addSubtitle( $str ) {
1072  if ( $str instanceof Message ) {
1073  $this->mSubtitle[] = $str->setContext( $this->getContext() )->parse();
1074  } else {
1075  $this->mSubtitle[] = $str;
1076  }
1077  }
1078 
1087  public static function buildBacklinkSubtitle( Title $title, $query = [] ) {
1088  if ( $title->isRedirect() ) {
1089  $query['redirect'] = 'no';
1090  }
1091  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
1092  return wfMessage( 'backlinksubtitle' )
1093  ->rawParams( $linkRenderer->makeLink( $title, null, [], $query ) );
1094  }
1095 
1102  public function addBacklinkSubtitle( Title $title, $query = [] ) {
1103  $this->addSubtitle( self::buildBacklinkSubtitle( $title, $query ) );
1104  }
1105 
1109  public function clearSubtitle() {
1110  $this->mSubtitle = [];
1111  }
1112 
1116  public function getSubtitle() {
1117  return implode( "<br />\n\t\t\t\t", $this->mSubtitle );
1118  }
1119 
1124  public function setPrintable() {
1125  $this->mPrintable = true;
1126  }
1127 
1133  public function isPrintable() {
1134  return $this->mPrintable;
1135  }
1136 
1140  public function disable() {
1141  $this->mDoNothing = true;
1142  }
1143 
1149  public function isDisabled() {
1150  return $this->mDoNothing;
1151  }
1152 
1158  public function showNewSectionLink() {
1159  return $this->mNewSectionLink;
1160  }
1161 
1167  public function forceHideNewSectionLink() {
1169  }
1170 
1179  public function setSyndicated( $show = true ) {
1180  if ( $show ) {
1181  $this->setFeedAppendQuery( false );
1182  } else {
1183  $this->mFeedLinks = [];
1184  }
1185  }
1186 
1193  protected function getAdvertisedFeedTypes() {
1194  if ( $this->getConfig()->get( 'Feed' ) ) {
1195  return $this->getConfig()->get( 'AdvertisedFeedTypes' );
1196  } else {
1197  return [];
1198  }
1199  }
1200 
1210  public function setFeedAppendQuery( $val ) {
1211  $this->mFeedLinks = [];
1212 
1213  foreach ( $this->getAdvertisedFeedTypes() as $type ) {
1214  $query = "feed=$type";
1215  if ( is_string( $val ) ) {
1216  $query .= '&' . $val;
1217  }
1218  $this->mFeedLinks[$type] = $this->getTitle()->getLocalURL( $query );
1219  }
1220  }
1221 
1228  public function addFeedLink( $format, $href ) {
1229  if ( in_array( $format, $this->getAdvertisedFeedTypes() ) ) {
1230  $this->mFeedLinks[$format] = $href;
1231  }
1232  }
1233 
1238  public function isSyndicated() {
1239  return count( $this->mFeedLinks ) > 0;
1240  }
1241 
1246  public function getSyndicationLinks() {
1247  return $this->mFeedLinks;
1248  }
1249 
1255  public function getFeedAppendQuery() {
1257  }
1258 
1266  public function setArticleFlag( $newVal ) {
1267  $this->mIsArticle = $newVal;
1268  if ( $newVal ) {
1269  $this->mIsArticleRelated = $newVal;
1270  }
1271  }
1272 
1279  public function isArticle() {
1280  return $this->mIsArticle;
1281  }
1282 
1289  public function setArticleRelated( $newVal ) {
1290  $this->mIsArticleRelated = $newVal;
1291  if ( !$newVal ) {
1292  $this->mIsArticle = false;
1293  }
1294  }
1295 
1301  public function isArticleRelated() {
1302  return $this->mIsArticleRelated;
1303  }
1304 
1310  public function setCopyright( $hasCopyright ) {
1311  $this->mHasCopyright = $hasCopyright;
1312  }
1313 
1323  public function showsCopyright() {
1324  return $this->isArticle() || $this->mHasCopyright;
1325  }
1326 
1333  public function addLanguageLinks( array $newLinkArray ) {
1334  $this->mLanguageLinks = array_merge( $this->mLanguageLinks, $newLinkArray );
1335  }
1336 
1343  public function setLanguageLinks( array $newLinkArray ) {
1344  $this->mLanguageLinks = $newLinkArray;
1345  }
1346 
1352  public function getLanguageLinks() {
1353  return $this->mLanguageLinks;
1354  }
1355 
1361  public function addCategoryLinks( array $categories ) {
1362  if ( !$categories ) {
1363  return;
1364  }
1365 
1366  $res = $this->addCategoryLinksToLBAndGetResult( $categories );
1367 
1368  # Set all the values to 'normal'.
1369  $categories = array_fill_keys( array_keys( $categories ), 'normal' );
1370 
1371  # Mark hidden categories
1372  foreach ( $res as $row ) {
1373  if ( isset( $row->pp_value ) ) {
1374  $categories[$row->page_title] = 'hidden';
1375  }
1376  }
1377 
1378  # Add the remaining categories to the skin
1379  if ( $this->getHookRunner()->onOutputPageMakeCategoryLinks(
1380  $this, $categories, $this->mCategoryLinks )
1381  ) {
1382  $services = MediaWikiServices::getInstance();
1383  $linkRenderer = $services->getLinkRenderer();
1384  $languageConverter = $services->getLanguageConverterFactory()
1385  ->getLanguageConverter( $services->getContentLanguage() );
1386  foreach ( $categories as $category => $type ) {
1387  // array keys will cast numeric category names to ints, so cast back to string
1388  $category = (string)$category;
1389  $origcategory = $category;
1390  $title = Title::makeTitleSafe( NS_CATEGORY, $category );
1391  if ( !$title ) {
1392  continue;
1393  }
1394  $languageConverter->findVariantLink( $category, $title, true );
1395 
1396  if ( $category != $origcategory && array_key_exists( $category, $categories ) ) {
1397  continue;
1398  }
1399  $text = $languageConverter->convertHtml( $title->getText() );
1400  $this->mCategories[$type][] = $title->getText();
1401  $this->mCategoryLinks[$type][] = $linkRenderer->makeLink( $title, new HtmlArmor( $text ) );
1402  }
1403  }
1404  }
1405 
1410  protected function addCategoryLinksToLBAndGetResult( array $categories ) {
1411  # Add the links to a LinkBatch
1412  $arr = [ NS_CATEGORY => $categories ];
1413  $linkBatchFactory = MediaWikiServices::getInstance()->getLinkBatchFactory();
1414  $lb = $linkBatchFactory->newLinkBatch();
1415  $lb->setArray( $arr );
1416 
1417  # Fetch existence plus the hiddencat property
1418  $dbr = wfGetDB( DB_REPLICA );
1419  $fields = array_merge(
1421  [ 'page_namespace', 'page_title', 'pp_value' ]
1422  );
1423 
1424  $res = $dbr->select( [ 'page', 'page_props' ],
1425  $fields,
1426  $lb->constructSet( 'page', $dbr ),
1427  __METHOD__,
1428  [],
1429  [ 'page_props' => [ 'LEFT JOIN', [
1430  'pp_propname' => 'hiddencat',
1431  'pp_page = page_id'
1432  ] ] ]
1433  );
1434 
1435  # Add the results to the link cache
1436  $linkCache = MediaWikiServices::getInstance()->getLinkCache();
1437  $lb->addResultToCache( $linkCache, $res );
1438 
1439  return $res;
1440  }
1441 
1447  public function setCategoryLinks( array $categories ) {
1448  $this->mCategoryLinks = [];
1449  $this->addCategoryLinks( $categories );
1450  }
1451 
1460  public function getCategoryLinks() {
1461  return $this->mCategoryLinks;
1462  }
1463 
1473  public function getCategories( $type = 'all' ) {
1474  if ( $type === 'all' ) {
1475  $allCategories = [];
1476  foreach ( $this->mCategories as $categories ) {
1477  $allCategories = array_merge( $allCategories, $categories );
1478  }
1479  return $allCategories;
1480  }
1481  if ( !isset( $this->mCategories[$type] ) ) {
1482  throw new InvalidArgumentException( 'Invalid category type given: ' . $type );
1483  }
1484  return $this->mCategories[$type];
1485  }
1486 
1496  public function setIndicators( array $indicators ) {
1497  $this->mIndicators = $indicators + $this->mIndicators;
1498  // Keep ordered by key
1499  ksort( $this->mIndicators );
1500  }
1501 
1510  public function getIndicators() {
1511  return $this->mIndicators;
1512  }
1513 
1522  public function addHelpLink( $to, $overrideBaseUrl = false ) {
1523  $this->addModuleStyles( 'mediawiki.helplink' );
1524  $text = $this->msg( 'helppage-top-gethelp' )->escaped();
1525 
1526  if ( $overrideBaseUrl ) {
1527  $helpUrl = $to;
1528  } else {
1529  $toUrlencoded = wfUrlencode( str_replace( ' ', '_', $to ) );
1530  $helpUrl = "https://www.mediawiki.org/wiki/Special:MyLanguage/$toUrlencoded";
1531  }
1532 
1533  $link = Html::rawElement(
1534  'a',
1535  [
1536  'href' => $helpUrl,
1537  'target' => '_blank',
1538  'class' => 'mw-helplink',
1539  ],
1540  $text
1541  );
1542 
1543  $this->setIndicators( [ 'mw-helplink' => $link ] );
1544  }
1545 
1554  public function disallowUserJs() {
1555  $this->reduceAllowedModules(
1556  ResourceLoaderModule::TYPE_SCRIPTS,
1557  ResourceLoaderModule::ORIGIN_CORE_INDIVIDUAL
1558  );
1559 
1560  // Site-wide styles are controlled by a config setting, see T73621
1561  // for background on why. User styles are never allowed.
1562  if ( $this->getConfig()->get( 'AllowSiteCSSOnRestrictedPages' ) ) {
1563  $styleOrigin = ResourceLoaderModule::ORIGIN_USER_SITEWIDE;
1564  } else {
1565  $styleOrigin = ResourceLoaderModule::ORIGIN_CORE_INDIVIDUAL;
1566  }
1567  $this->reduceAllowedModules(
1568  ResourceLoaderModule::TYPE_STYLES,
1569  $styleOrigin
1570  );
1571  }
1572 
1579  public function getAllowedModules( $type ) {
1580  if ( $type == ResourceLoaderModule::TYPE_COMBINED ) {
1581  return min( array_values( $this->mAllowedModules ) );
1582  } else {
1583  return $this->mAllowedModules[$type] ?? ResourceLoaderModule::ORIGIN_ALL;
1584  }
1585  }
1586 
1596  public function reduceAllowedModules( $type, $level ) {
1597  $this->mAllowedModules[$type] = min( $this->getAllowedModules( $type ), $level );
1598  }
1599 
1605  public function prependHTML( $text ) {
1606  $this->mBodytext = $text . $this->mBodytext;
1607  }
1608 
1614  public function addHTML( $text ) {
1615  $this->mBodytext .= $text;
1616  }
1617 
1627  public function addElement( $element, array $attribs = [], $contents = '' ) {
1628  $this->addHTML( Html::element( $element, $attribs, $contents ) );
1629  }
1630 
1634  public function clearHTML() {
1635  $this->mBodytext = '';
1636  }
1637 
1643  public function getHTML() {
1644  return $this->mBodytext;
1645  }
1646 
1653  public function parserOptions() {
1654  if ( !$this->mParserOptions ) {
1655  if ( !$this->getUser()->isSafeToLoad() ) {
1656  // Context user isn't unstubbable yet, so don't try to get a
1657  // ParserOptions for it. And don't cache this ParserOptions
1658  // either.
1660  $po->setAllowUnsafeRawHtml( false );
1661  $po->isBogus = true;
1662  return $po;
1663  }
1664 
1665  $this->mParserOptions = ParserOptions::newFromContext( $this->getContext() );
1666  $this->mParserOptions->setAllowUnsafeRawHtml( false );
1667  }
1668 
1669  return $this->mParserOptions;
1670  }
1671 
1679  public function setRevisionId( $revid ) {
1680  $val = $revid === null ? null : intval( $revid );
1681  return wfSetVar( $this->mRevisionId, $val, true );
1682  }
1683 
1689  public function getRevisionId() {
1690  return $this->mRevisionId;
1691  }
1692 
1699  public function isRevisionCurrent() {
1700  return $this->mRevisionId == 0 || $this->mRevisionId == $this->getTitle()->getLatestRevID();
1701  }
1702 
1710  public function setRevisionTimestamp( $timestamp ) {
1711  return wfSetVar( $this->mRevisionTimestamp, $timestamp, true );
1712  }
1713 
1720  public function getRevisionTimestamp() {
1722  }
1723 
1730  public function setFileVersion( $file ) {
1731  $val = null;
1732  if ( $file instanceof File && $file->exists() ) {
1733  $val = [ 'time' => $file->getTimestamp(), 'sha1' => $file->getSha1() ];
1734  }
1735  return wfSetVar( $this->mFileVersion, $val, true );
1736  }
1737 
1743  public function getFileVersion() {
1744  return $this->mFileVersion;
1745  }
1746 
1753  public function getTemplateIds() {
1754  return $this->mTemplateIds;
1755  }
1756 
1763  public function getFileSearchOptions() {
1764  return $this->mImageTimeKeys;
1765  }
1766 
1783  public function addWikiTextAsInterface(
1784  $text, $linestart = true, Title $title = null
1785  ) {
1786  if ( $title === null ) {
1787  $title = $this->getTitle();
1788  }
1789  if ( !$title ) {
1790  throw new MWException( 'Title is null' );
1791  }
1792  $this->addWikiTextTitleInternal( $text, $title, $linestart, /*interface*/true );
1793  }
1794 
1808  public function wrapWikiTextAsInterface(
1809  $wrapperClass, $text
1810  ) {
1811  $this->addWikiTextTitleInternal(
1812  $text, $this->getTitle(),
1813  /*linestart*/true, /*interface*/true,
1814  $wrapperClass
1815  );
1816  }
1817 
1833  public function addWikiTextAsContent(
1834  $text, $linestart = true, Title $title = null
1835  ) {
1836  if ( $title === null ) {
1837  $title = $this->getTitle();
1838  }
1839  if ( !$title ) {
1840  throw new MWException( 'Title is null' );
1841  }
1842  $this->addWikiTextTitleInternal( $text, $title, $linestart, /*interface*/false );
1843  }
1844 
1857  private function addWikiTextTitleInternal(
1858  $text, Title $title, $linestart, $interface, $wrapperClass = null
1859  ) {
1860  $parserOutput = $this->parseInternal(
1861  $text, $title, $linestart, $interface
1862  );
1863 
1864  $this->addParserOutput( $parserOutput, [
1865  'enableSectionEditLinks' => false,
1866  'wrapperDivClass' => $wrapperClass ?? '',
1867  ] );
1868  }
1869 
1878  public function addParserOutputMetadata( ParserOutput $parserOutput ) {
1879  $this->mLanguageLinks =
1880  array_merge( $this->mLanguageLinks, $parserOutput->getLanguageLinks() );
1881  $this->addCategoryLinks( $parserOutput->getCategories() );
1882  $this->setIndicators( $parserOutput->getIndicators() );
1883  $this->mNewSectionLink = $parserOutput->getNewSection();
1884  $this->mHideNewSectionLink = $parserOutput->getHideNewSection();
1885 
1886  if ( !$parserOutput->isCacheable() ) {
1887  $this->enableClientCache( false );
1888  }
1889  $this->mNoGallery = $parserOutput->getNoGallery();
1890  $this->mHeadItems = array_merge( $this->mHeadItems, $parserOutput->getHeadItems() );
1891  $this->addModules( $parserOutput->getModules() );
1892  $this->addModuleStyles( $parserOutput->getModuleStyles() );
1893  $this->addJsConfigVars( $parserOutput->getJsConfigVars() );
1894  $this->mPreventClickjacking = $this->mPreventClickjacking
1895  || $parserOutput->preventClickjacking();
1896  $scriptSrcs = $parserOutput->getExtraCSPScriptSrcs();
1897  foreach ( $scriptSrcs as $src ) {
1898  $this->getCSP()->addScriptSrc( $src );
1899  }
1900  $defaultSrcs = $parserOutput->getExtraCSPDefaultSrcs();
1901  foreach ( $defaultSrcs as $src ) {
1902  $this->getCSP()->addDefaultSrc( $src );
1903  }
1904  $styleSrcs = $parserOutput->getExtraCSPStyleSrcs();
1905  foreach ( $styleSrcs as $src ) {
1906  $this->getCSP()->addStyleSrc( $src );
1907  }
1908 
1909  // If $wgImagePreconnect is true, and if the output contains
1910  // images, give the user-agent a hint about foreign repos from
1911  // which those images may be served. See T123582.
1912  //
1913  // TODO: We don't have an easy way to know from which remote(s)
1914  // the image(s) will be served. For now, we only hint the first
1915  // valid one.
1916  if ( $this->getConfig()->get( 'ImagePreconnect' ) && count( $parserOutput->getImages() ) ) {
1917  $preconnect = [];
1918  $repoGroup = MediaWikiServices::getInstance()->getRepoGroup();
1919  $repoGroup->forEachForeignRepo( static function ( $repo ) use ( &$preconnect ) {
1920  $preconnect[] = wfParseUrl( $repo->getZoneUrl( 'thumb' ) )['host'];
1921  } );
1922  $preconnect[] = wfParseUrl( $repoGroup->getLocalRepo()->getZoneUrl( 'thumb' ) )['host'];
1923  foreach ( $preconnect as $host ) {
1924  if ( $host ) {
1925  $this->addLink( [ 'rel' => 'preconnect', 'href' => '//' . $host ] );
1926  break;
1927  }
1928  }
1929  }
1930 
1931  // Template versioning...
1932  foreach ( (array)$parserOutput->getTemplateIds() as $ns => $dbks ) {
1933  if ( isset( $this->mTemplateIds[$ns] ) ) {
1934  $this->mTemplateIds[$ns] = $dbks + $this->mTemplateIds[$ns];
1935  } else {
1936  $this->mTemplateIds[$ns] = $dbks;
1937  }
1938  }
1939  // File versioning...
1940  foreach ( (array)$parserOutput->getFileSearchOptions() as $dbk => $data ) {
1941  $this->mImageTimeKeys[$dbk] = $data;
1942  }
1943 
1944  // Hooks registered in the object
1945  $parserOutputHooks = $this->getConfig()->get( 'ParserOutputHooks' );
1946  foreach ( $parserOutput->getOutputHooks() as $hookInfo ) {
1947  list( $hookName, $data ) = $hookInfo;
1948  if ( isset( $parserOutputHooks[$hookName] ) ) {
1949  $parserOutputHooks[$hookName]( $this, $parserOutput, $data );
1950  }
1951  }
1952 
1953  // Enable OOUI if requested via ParserOutput
1954  if ( $parserOutput->getEnableOOUI() ) {
1955  $this->enableOOUI();
1956  }
1957 
1958  // Include parser limit report
1959  if ( !$this->limitReportJSData ) {
1960  $this->limitReportJSData = $parserOutput->getLimitReportJSData();
1961  }
1962 
1963  // Link flags are ignored for now, but may in the future be
1964  // used to mark individual language links.
1965  $linkFlags = [];
1966  $this->getHookRunner()->onLanguageLinks( $this->getTitle(), $this->mLanguageLinks, $linkFlags );
1967  $this->getHookRunner()->onOutputPageParserOutput( $this, $parserOutput );
1968 
1969  // This check must be after 'OutputPageParserOutput' runs in addParserOutputMetadata
1970  // so that extensions may modify ParserOutput to toggle TOC.
1971  // This cannot be moved to addParserOutputText because that is not
1972  // called by EditPage for Preview.
1973  if ( $parserOutput->getTOCHTML() ) {
1974  $this->mEnableTOC = true;
1975  }
1976  }
1977 
1986  public function addParserOutputContent( ParserOutput $parserOutput, $poOptions = [] ) {
1987  $this->addParserOutputText( $parserOutput, $poOptions );
1988 
1989  $this->addModules( $parserOutput->getModules() );
1990  $this->addModuleStyles( $parserOutput->getModuleStyles() );
1991 
1992  $this->addJsConfigVars( $parserOutput->getJsConfigVars() );
1993  }
1994 
2002  public function addParserOutputText( ParserOutput $parserOutput, $poOptions = [] ) {
2003  $text = $parserOutput->getText( $poOptions );
2004  $this->getHookRunner()->onOutputPageBeforeHTML( $this, $text );
2005  $this->addHTML( $text );
2006  }
2007 
2014  public function addParserOutput( ParserOutput $parserOutput, $poOptions = [] ) {
2015  $this->addParserOutputMetadata( $parserOutput );
2016  $this->addParserOutputText( $parserOutput, $poOptions );
2017  }
2018 
2024  public function addTemplate( &$template ) {
2025  $this->addHTML( $template->getHTML() );
2026  }
2027 
2039  public function parseAsContent( $text, $linestart = true ) {
2040  return $this->parseInternal(
2041  $text, $this->getTitle(), $linestart, /*interface*/false
2042  )->getText( [
2043  'enableSectionEditLinks' => false,
2044  'wrapperDivClass' => ''
2045  ] );
2046  }
2047 
2060  public function parseAsInterface( $text, $linestart = true ) {
2061  return $this->parseInternal(
2062  $text, $this->getTitle(), $linestart, /*interface*/true
2063  )->getText( [
2064  'enableSectionEditLinks' => false,
2065  'wrapperDivClass' => ''
2066  ] );
2067  }
2068 
2083  public function parseInlineAsInterface( $text, $linestart = true ) {
2085  $this->parseAsInterface( $text, $linestart )
2086  );
2087  }
2088 
2101  private function parseInternal( $text, $title, $linestart, $interface ) {
2102  if ( $title === null ) {
2103  throw new MWException( 'Empty $mTitle in ' . __METHOD__ );
2104  }
2105 
2106  $popts = $this->parserOptions();
2107 
2108  $oldInterface = $popts->setInterfaceMessage( (bool)$interface );
2109 
2110  $parserOutput = MediaWikiServices::getInstance()->getParser()->getFreshParser()->parse(
2111  $text, $title, $popts,
2112  $linestart, true, $this->mRevisionId
2113  );
2114 
2115  $popts->setInterfaceMessage( $oldInterface );
2116 
2117  return $parserOutput;
2118  }
2119 
2125  public function setCdnMaxage( $maxage ) {
2126  $this->mCdnMaxage = min( $maxage, $this->mCdnMaxageLimit );
2127  }
2128 
2138  public function lowerCdnMaxage( $maxage ) {
2139  $this->mCdnMaxageLimit = min( $maxage, $this->mCdnMaxageLimit );
2140  $this->setCdnMaxage( $this->mCdnMaxage );
2141  }
2142 
2155  public function adaptCdnTTL( $mtime, $minTTL = 0, $maxTTL = 0 ) {
2156  $minTTL = $minTTL ?: IExpiringStore::TTL_MINUTE;
2157  $maxTTL = $maxTTL ?: $this->getConfig()->get( 'CdnMaxAge' );
2158 
2159  if ( $mtime === null || $mtime === false ) {
2160  return; // entity does not exist
2161  }
2162 
2163  $age = MWTimestamp::time() - (int)wfTimestamp( TS_UNIX, $mtime );
2164  $adaptiveTTL = max( 0.9 * $age, $minTTL );
2165  $adaptiveTTL = min( $adaptiveTTL, $maxTTL );
2166 
2167  $this->lowerCdnMaxage( (int)$adaptiveTTL );
2168  }
2169 
2177  public function enableClientCache( $state ) {
2178  return wfSetVar( $this->mEnableClientCache, $state );
2179  }
2180 
2187  public function couldBePublicCached() {
2188  if ( !$this->cacheIsFinal ) {
2189  // - The entry point handles its own caching and/or doesn't use OutputPage.
2190  // (such as load.php, AjaxDispatcher, or MediaWiki\Rest\EntryPoint).
2191  //
2192  // - Or, we haven't finished processing the main part of the request yet
2193  // (e.g. Action::show, SpecialPage::execute), and the state may still
2194  // change via enableClientCache().
2195  return true;
2196  }
2197  // e.g. various error-type pages disable all client caching
2199  }
2200 
2210  public function considerCacheSettingsFinal() {
2211  $this->cacheIsFinal = true;
2212  }
2213 
2219  public function getCacheVaryCookies() {
2220  if ( self::$cacheVaryCookies === null ) {
2221  $config = $this->getConfig();
2222  self::$cacheVaryCookies = array_values( array_unique( array_merge(
2223  SessionManager::singleton()->getVaryCookies(),
2224  [
2225  'forceHTTPS',
2226  ],
2227  $config->get( 'CacheVaryCookies' )
2228  ) ) );
2229  $this->getHookRunner()->onGetCacheVaryCookies( $this, self::$cacheVaryCookies );
2230  }
2231  return self::$cacheVaryCookies;
2232  }
2233 
2240  public function haveCacheVaryCookies() {
2241  $request = $this->getRequest();
2242  foreach ( $this->getCacheVaryCookies() as $cookieName ) {
2243  if ( $request->getCookie( $cookieName, '', '' ) !== '' ) {
2244  wfDebug( __METHOD__ . ": found $cookieName" );
2245  return true;
2246  }
2247  }
2248  wfDebug( __METHOD__ . ": no cache-varying cookies found" );
2249  return false;
2250  }
2251 
2261  public function addVaryHeader( $header, array $option = null ) {
2262  if ( $option !== null && count( $option ) > 0 ) {
2264  'The $option parameter to addVaryHeader is ignored since MediaWiki 1.34',
2265  '1.34' );
2266  }
2267  if ( !array_key_exists( $header, $this->mVaryHeader ) ) {
2268  $this->mVaryHeader[$header] = null;
2269  }
2270  }
2271 
2278  public function getVaryHeader() {
2279  // If we vary on cookies, let's make sure it's always included here too.
2280  if ( $this->getCacheVaryCookies() ) {
2281  $this->addVaryHeader( 'Cookie' );
2282  }
2283 
2284  foreach ( SessionManager::singleton()->getVaryHeaders() as $header => $options ) {
2285  $this->addVaryHeader( $header, $options );
2286  }
2287  return 'Vary: ' . implode( ', ', array_keys( $this->mVaryHeader ) );
2288  }
2289 
2295  public function addLinkHeader( $header ) {
2296  $this->mLinkHeader[] = $header;
2297  }
2298 
2304  public function getLinkHeader() {
2305  if ( !$this->mLinkHeader ) {
2306  return false;
2307  }
2308 
2309  return 'Link: ' . implode( ',', $this->mLinkHeader );
2310  }
2311 
2319  private function addAcceptLanguage() {
2320  $title = $this->getTitle();
2321  if ( !$title instanceof Title ) {
2322  return;
2323  }
2324 
2325  $languageConverter = MediaWikiServices::getInstance()->getLanguageConverterFactory()
2326  ->getLanguageConverter( $title->getPageLanguage() );
2327  if ( !$this->getRequest()->getCheck( 'variant' ) && $languageConverter->hasVariants() ) {
2328  $this->addVaryHeader( 'Accept-Language' );
2329  }
2330  }
2331 
2342  public function preventClickjacking( $enable = true ) {
2343  $this->mPreventClickjacking = $enable;
2344  }
2345 
2351  public function allowClickjacking() {
2352  $this->mPreventClickjacking = false;
2353  }
2354 
2361  public function getPreventClickjacking() {
2363  }
2364 
2372  public function getFrameOptions() {
2373  $config = $this->getConfig();
2374  if ( $config->get( 'BreakFrames' ) ) {
2375  return 'DENY';
2376  } elseif ( $this->mPreventClickjacking && $config->get( 'EditPageFrameOptions' ) ) {
2377  return $config->get( 'EditPageFrameOptions' );
2378  }
2379  return false;
2380  }
2381 
2388  private function getOriginTrials() {
2389  $config = $this->getConfig();
2390 
2391  return $config->get( 'OriginTrials' );
2392  }
2393 
2394  private function getReportTo() {
2395  $config = $this->getConfig();
2396 
2397  $expiry = $config->get( 'ReportToExpiry' );
2398 
2399  if ( !$expiry ) {
2400  return false;
2401  }
2402 
2403  $endpoints = $config->get( 'ReportToEndpoints' );
2404 
2405  if ( !$endpoints ) {
2406  return false;
2407  }
2408 
2409  $output = [ 'max_age' => $expiry, 'endpoints' => [] ];
2410 
2411  foreach ( $endpoints as $endpoint ) {
2412  $output['endpoints'][] = [ 'url' => $endpoint ];
2413  }
2414 
2415  return json_encode( $output, JSON_UNESCAPED_SLASHES );
2416  }
2417 
2418  private function getFeaturePolicyReportOnly() {
2419  $config = $this->getConfig();
2420 
2421  $features = $config->get( 'FeaturePolicyReportOnly' );
2422  return implode( ';', $features );
2423  }
2424 
2428  public function sendCacheControl() {
2429  $response = $this->getRequest()->response();
2430  $config = $this->getConfig();
2431 
2432  $this->addVaryHeader( 'Cookie' );
2433  $this->addAcceptLanguage();
2434 
2435  # don't serve compressed data to clients who can't handle it
2436  # maintain different caches for logged-in users and non-logged in ones
2437  $response->header( $this->getVaryHeader() );
2438 
2439  if ( $this->mEnableClientCache ) {
2440  if ( !$config->get( 'UseCdn' ) ) {
2441  $privateReason = 'config';
2442  } elseif ( $response->hasCookies() ) {
2443  $privateReason = 'set-cookies';
2444  // The client might use methods other than cookies to appear logged-in.
2445  // E.g. HTTP headers, or query parameter tokens, OAuth, etc.
2446  } elseif ( SessionManager::getGlobalSession()->isPersistent() ) {
2447  $privateReason = 'session';
2448  } elseif ( $this->isPrintable() ) {
2449  $privateReason = 'printable';
2450  } elseif ( $this->mCdnMaxage == 0 ) {
2451  $privateReason = 'no-maxage';
2452  } elseif ( $this->haveCacheVaryCookies() ) {
2453  $privateReason = 'cache-vary-cookies';
2454  } else {
2455  $privateReason = false;
2456  }
2457 
2458  if ( $privateReason === false ) {
2459  # We'll purge the proxy cache for anons explicitly, but require end user agents
2460  # to revalidate against the proxy on each visit.
2461  # IMPORTANT! The CDN needs to replace the Cache-Control header with
2462  # Cache-Control: s-maxage=0, must-revalidate, max-age=0
2463  wfDebug( __METHOD__ .
2464  ": local proxy caching; {$this->mLastModified} **", 'private' );
2465  # start with a shorter timeout for initial testing
2466  # header( "Cache-Control: s-maxage=2678400, must-revalidate, max-age=0" );
2467  $response->header( "Cache-Control: " .
2468  "s-maxage={$this->mCdnMaxage}, must-revalidate, max-age=0" );
2469  } else {
2470  # We do want clients to cache if they can, but they *must* check for updates
2471  # on revisiting the page, after the max-age period.
2472  wfDebug( __METHOD__ . ": private caching ($privateReason); {$this->mLastModified} **", 'private' );
2473 
2474  if ( $response->hasCookies() || SessionManager::getGlobalSession()->isPersistent() ) {
2475  $response->header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', 0 ) . ' GMT' );
2476  $response->header( "Cache-Control: private, must-revalidate, max-age=0" );
2477  } else {
2478  $response->header(
2479  'Expires: ' . gmdate( 'D, d M Y H:i:s', time() + $config->get( 'LoggedOutMaxAge' ) ) . ' GMT'
2480  );
2481  $response->header(
2482  "Cache-Control: private, must-revalidate, max-age={$config->get( 'LoggedOutMaxAge' )}"
2483  );
2484  }
2485  }
2486  if ( $this->mLastModified ) {
2487  $response->header( "Last-Modified: {$this->mLastModified}" );
2488  }
2489  } else {
2490  wfDebug( __METHOD__ . ": no caching **", 'private' );
2491 
2492  # In general, the absence of a last modified header should be enough to prevent
2493  # the client from using its cache. We send a few other things just to make sure.
2494  $response->header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', 0 ) . ' GMT' );
2495  $response->header( 'Cache-Control: no-cache, no-store, max-age=0, must-revalidate' );
2496  $response->header( 'Pragma: no-cache' );
2497  }
2498  }
2499 
2505  public function loadSkinModules( $sk ) {
2506  foreach ( $sk->getDefaultModules() as $group => $modules ) {
2507  if ( $group === 'styles' ) {
2508  foreach ( $modules as $key => $moduleMembers ) {
2509  $this->addModuleStyles( $moduleMembers );
2510  }
2511  } else {
2512  $this->addModules( $modules );
2513  }
2514  }
2515  }
2516 
2527  public function output( $return = false ) {
2528  if ( $this->mDoNothing ) {
2529  return $return ? '' : null;
2530  }
2531 
2532  $response = $this->getRequest()->response();
2533  $config = $this->getConfig();
2534 
2535  if ( $this->mRedirect != '' ) {
2536  # Standards require redirect URLs to be absolute
2537  $this->mRedirect = wfExpandUrl( $this->mRedirect, PROTO_CURRENT );
2538 
2539  $redirect = $this->mRedirect;
2540  $code = $this->mRedirectCode;
2541  $content = '';
2542 
2543  if ( $this->getHookRunner()->onBeforePageRedirect( $this, $redirect, $code ) ) {
2544  if ( $code == '301' || $code == '303' ) {
2545  if ( !$config->get( 'DebugRedirects' ) ) {
2546  $response->statusHeader( $code );
2547  }
2548  $this->mLastModified = wfTimestamp( TS_RFC2822 );
2549  }
2550  if ( $config->get( 'VaryOnXFP' ) ) {
2551  $this->addVaryHeader( 'X-Forwarded-Proto' );
2552  }
2553  $this->sendCacheControl();
2554 
2555  $response->header( "Content-Type: text/html; charset=utf-8" );
2556  if ( $config->get( 'DebugRedirects' ) ) {
2557  $url = htmlspecialchars( $redirect );
2558  $content = "<!DOCTYPE html>\n<html>\n<head>\n"
2559  . "<title>Redirect</title>\n</head>\n<body>\n"
2560  . "<p>Location: <a href=\"$url\">$url</a></p>\n"
2561  . "</body>\n</html>\n";
2562 
2563  if ( !$return ) {
2564  print $content;
2565  }
2566 
2567  } else {
2568  $response->header( 'Location: ' . $redirect );
2569  }
2570  }
2571 
2572  return $return ? $content : null;
2573  } elseif ( $this->mStatusCode ) {
2574  $response->statusHeader( $this->mStatusCode );
2575  }
2576 
2577  # Buffer output; final headers may depend on later processing
2578  ob_start();
2579 
2580  $response->header( 'Content-type: ' . $config->get( 'MimeType' ) . '; charset=UTF-8' );
2581  $response->header( 'Content-language: ' .
2582  MediaWikiServices::getInstance()->getContentLanguage()->getHtmlCode() );
2583 
2584  $linkHeader = $this->getLinkHeader();
2585  if ( $linkHeader ) {
2586  $response->header( $linkHeader );
2587  }
2588 
2589  // Prevent framing, if requested
2590  $frameOptions = $this->getFrameOptions();
2591  if ( $frameOptions ) {
2592  $response->header( "X-Frame-Options: $frameOptions" );
2593  }
2594 
2595  $originTrials = $this->getOriginTrials();
2596  foreach ( $originTrials as $originTrial ) {
2597  $response->header( "Origin-Trial: $originTrial", false );
2598  }
2599 
2600  $reportTo = $this->getReportTo();
2601  if ( $reportTo ) {
2602  $response->header( "Report-To: $reportTo" );
2603  }
2604 
2605  $featurePolicyReportOnly = $this->getFeaturePolicyReportOnly();
2606  if ( $featurePolicyReportOnly ) {
2607  $response->header( "Feature-Policy-Report-Only: $featurePolicyReportOnly" );
2608  }
2609 
2610  if ( $this->mArticleBodyOnly ) {
2611  $this->CSP->sendHeaders();
2612  echo $this->mBodytext;
2613  } else {
2614  // Enable safe mode if requested (T152169)
2615  if ( $this->getRequest()->getBool( 'safemode' ) ) {
2616  $this->disallowUserJs();
2617  }
2618 
2619  $sk = $this->getSkin();
2620  $this->loadSkinModules( $sk );
2621 
2622  MWDebug::addModules( $this );
2623 
2624  // Hook that allows last minute changes to the output page, e.g.
2625  // adding of CSS or Javascript by extensions, adding CSP sources.
2626  $this->getHookRunner()->onBeforePageDisplay( $this, $sk );
2627 
2628  $this->CSP->sendHeaders();
2629 
2630  try {
2631  $sk->outputPage();
2632  } catch ( Exception $e ) {
2633  ob_end_clean(); // bug T129657
2634  throw $e;
2635  }
2636  }
2637 
2638  try {
2639  // This hook allows last minute changes to final overall output by modifying output buffer
2640  $this->getHookRunner()->onAfterFinalPageOutput( $this );
2641  } catch ( Exception $e ) {
2642  ob_end_clean(); // bug T129657
2643  throw $e;
2644  }
2645 
2646  $this->sendCacheControl();
2647 
2648  if ( $return ) {
2649  return ob_get_clean();
2650  } else {
2651  ob_end_flush();
2652  return null;
2653  }
2654  }
2655 
2666  public function prepareErrorPage( $pageTitle, $htmlTitle = false ) {
2667  $this->setPageTitle( $pageTitle );
2668  if ( $htmlTitle !== false ) {
2669  $this->setHTMLTitle( $htmlTitle );
2670  }
2671  $this->setRobotPolicy( 'noindex,nofollow' );
2672  $this->setArticleRelated( false );
2673  $this->enableClientCache( false );
2674  $this->mRedirect = '';
2675  $this->clearSubtitle();
2676  $this->clearHTML();
2677  }
2678 
2691  public function showErrorPage( $title, $msg, $params = [] ) {
2692  if ( !$title instanceof Message ) {
2693  $title = $this->msg( $title );
2694  }
2695 
2696  $this->prepareErrorPage( $title );
2697 
2698  if ( $msg instanceof Message ) {
2699  if ( $params !== [] ) {
2700  trigger_error( 'Argument ignored: $params. The message parameters argument '
2701  . 'is discarded when the $msg argument is a Message object instead of '
2702  . 'a string.', E_USER_NOTICE );
2703  }
2704  $this->addHTML( $msg->parseAsBlock() );
2705  } else {
2706  $this->addWikiMsgArray( $msg, $params );
2707  }
2708 
2709  $this->returnToMain();
2710  }
2711 
2718  public function showPermissionsErrorPage( array $errors, $action = null ) {
2719  $services = MediaWikiServices::getInstance();
2720  $permissionManager = $services->getPermissionManager();
2721  foreach ( $errors as $key => $error ) {
2722  $errors[$key] = (array)$error;
2723  }
2724 
2725  // For some action (read, edit, create and upload), display a "login to do this action"
2726  // error if all of the following conditions are met:
2727  // 1. the user is not logged in
2728  // 2. the only error is insufficient permissions (i.e. no block or something else)
2729  // 3. the error can be avoided simply by logging in
2730 
2731  if ( in_array( $action, [ 'read', 'edit', 'createpage', 'createtalk', 'upload' ] )
2732  && $this->getUser()->isAnon() && count( $errors ) == 1 && isset( $errors[0][0] )
2733  && ( $errors[0][0] == 'badaccess-groups' || $errors[0][0] == 'badaccess-group0' )
2734  && ( $permissionManager->groupHasPermission( 'user', $action )
2735  || $permissionManager->groupHasPermission( 'autoconfirmed', $action ) )
2736  ) {
2737  $displayReturnto = null;
2738 
2739  # Due to T34276, if a user does not have read permissions,
2740  # $this->getTitle() will just give Special:Badtitle, which is
2741  # not especially useful as a returnto parameter. Use the title
2742  # from the request instead, if there was one.
2743  $request = $this->getRequest();
2744  $returnto = Title::newFromText( $request->getVal( 'title', '' ) );
2745  if ( $action == 'edit' ) {
2746  $msg = 'whitelistedittext';
2747  $displayReturnto = $returnto;
2748  } elseif ( $action == 'createpage' || $action == 'createtalk' ) {
2749  $msg = 'nocreatetext';
2750  } elseif ( $action == 'upload' ) {
2751  $msg = 'uploadnologintext';
2752  } else { # Read
2753  $msg = 'loginreqpagetext';
2754  $displayReturnto = Title::newMainPage();
2755  }
2756 
2757  $query = [];
2758 
2759  if ( $returnto ) {
2760  $query['returnto'] = $returnto->getPrefixedText();
2761 
2762  if ( !$request->wasPosted() ) {
2763  $returntoquery = $request->getValues();
2764  unset( $returntoquery['title'] );
2765  unset( $returntoquery['returnto'] );
2766  unset( $returntoquery['returntoquery'] );
2767  $query['returntoquery'] = wfArrayToCgi( $returntoquery );
2768  }
2769  }
2770 
2771  $title = SpecialPage::getTitleFor( 'Userlogin' );
2772  $linkRenderer = $services->getLinkRenderer();
2773  $loginUrl = $title->getLinkURL( $query, false, PROTO_RELATIVE );
2774  $loginLink = $linkRenderer->makeKnownLink(
2775  $title,
2776  $this->msg( 'loginreqlink' )->text(),
2777  [],
2778  $query
2779  );
2780 
2781  $this->prepareErrorPage( $this->msg( 'loginreqtitle' ) );
2782  $this->addHTML( $this->msg( $msg )->rawParams( $loginLink )->params( $loginUrl )->parse() );
2783 
2784  # Don't return to a page the user can't read otherwise
2785  # we'll end up in a pointless loop
2786  if ( $displayReturnto && $permissionManager->userCan(
2787  'read', $this->getUser(), $displayReturnto
2788  ) ) {
2789  $this->returnToMain( null, $displayReturnto );
2790  }
2791  } else {
2792  $this->prepareErrorPage( $this->msg( 'permissionserrors' ) );
2793  $this->addWikiTextAsInterface( $this->formatPermissionsErrorMessage( $errors, $action ) );
2794  }
2795  }
2796 
2803  public function versionRequired( $version ) {
2804  $this->prepareErrorPage( $this->msg( 'versionrequired', $version ) );
2805 
2806  $this->addWikiMsg( 'versionrequiredtext', $version );
2807  $this->returnToMain();
2808  }
2809 
2817  public function formatPermissionsErrorMessage( array $errors, $action = null ) {
2818  if ( $action == null ) {
2819  $text = $this->msg( 'permissionserrorstext', count( $errors ) )->plain() . "\n\n";
2820  } else {
2821  $action_desc = $this->msg( "action-$action" )->plain();
2822  $text = $this->msg(
2823  'permissionserrorstext-withaction',
2824  count( $errors ),
2825  $action_desc
2826  )->plain() . "\n\n";
2827  }
2828 
2829  if ( count( $errors ) > 1 ) {
2830  $text .= '<ul class="permissions-errors">' . "\n";
2831 
2832  foreach ( $errors as $error ) {
2833  $text .= '<li>';
2834  $text .= $this->msg( ...$error )->plain();
2835  $text .= "</li>\n";
2836  }
2837  $text .= '</ul>';
2838  } else {
2839  $text .= "<div class=\"permissions-errors\">\n" .
2840  $this->msg( ...reset( $errors ) )->plain() .
2841  "\n</div>";
2842  }
2843 
2844  return $text;
2845  }
2846 
2856  public function showLagWarning( $lag ) {
2857  $config = $this->getConfig();
2858  if ( $lag >= $config->get( 'SlaveLagWarning' ) ) {
2859  $lag = floor( $lag ); // floor to avoid nano seconds to display
2860  $message = $lag < $config->get( 'SlaveLagCritical' )
2861  ? 'lag-warn-normal'
2862  : 'lag-warn-high';
2863  // For grep: mw-lag-warn-normal, mw-lag-warn-high
2864  $wrap = Html::rawElement( 'div', [ 'class' => "mw-{$message}" ], "\n$1\n" );
2865  $this->wrapWikiMsg( "$wrap\n", [ $message, $this->getLanguage()->formatNum( $lag ) ] );
2866  }
2867  }
2868 
2875  public function showFatalError( $message ) {
2876  $this->prepareErrorPage( $this->msg( 'internalerror' ) );
2877 
2878  $this->addHTML( $message );
2879  }
2880 
2889  public function addReturnTo( $title, array $query = [], $text = null, $options = [] ) {
2890  $linkRenderer = MediaWikiServices::getInstance()
2891  ->getLinkRendererFactory()->createFromLegacyOptions( $options );
2892  $link = $this->msg( 'returnto' )->rawParams(
2893  $linkRenderer->makeLink( $title, $text, [], $query ) )->escaped();
2894  $this->addHTML( "<p id=\"mw-returnto\">{$link}</p>\n" );
2895  }
2896 
2905  public function returnToMain( $unused = null, $returnto = null, $returntoquery = null ) {
2906  if ( $returnto == null ) {
2907  $returnto = $this->getRequest()->getText( 'returnto' );
2908  }
2909 
2910  if ( $returntoquery == null ) {
2911  $returntoquery = $this->getRequest()->getText( 'returntoquery' );
2912  }
2913 
2914  if ( $returnto === '' ) {
2915  $returnto = Title::newMainPage();
2916  }
2917 
2918  if ( is_object( $returnto ) ) {
2919  $titleObj = $returnto;
2920  } else {
2921  $titleObj = Title::newFromText( $returnto );
2922  }
2923  // We don't want people to return to external interwiki. That
2924  // might potentially be used as part of a phishing scheme
2925  if ( !is_object( $titleObj ) || $titleObj->isExternal() ) {
2926  $titleObj = Title::newMainPage();
2927  }
2928 
2929  $this->addReturnTo( $titleObj, wfCgiToArray( $returntoquery ) );
2930  }
2931 
2932  private function getRlClientContext() {
2933  if ( !$this->rlClientContext ) {
2935  [], // modules; not relevant
2936  $this->getLanguage()->getCode(),
2937  $this->getSkin()->getSkinName(),
2938  $this->getUser()->isRegistered() ? $this->getUser()->getName() : null,
2939  null, // version; not relevant
2941  null, // only; not relevant
2942  $this->isPrintable(),
2943  $this->getRequest()->getBool( 'handheld' )
2944  );
2945  $this->rlClientContext = new ResourceLoaderContext(
2946  $this->getResourceLoader(),
2947  new FauxRequest( $query )
2948  );
2949  if ( $this->contentOverrideCallbacks ) {
2950  $this->rlClientContext = new DerivativeResourceLoaderContext( $this->rlClientContext );
2951  $this->rlClientContext->setContentOverrideCallback( function ( Title $title ) {
2952  foreach ( $this->contentOverrideCallbacks as $callback ) {
2953  $content = $callback( $title );
2954  if ( $content !== null ) {
2956  if ( strpos( $text, '</script>' ) !== false ) {
2957  // Proactively replace this so that we can display a message
2958  // to the user, instead of letting it go to Html::inlineScript(),
2959  // where it would be considered a server-side issue.
2960  $titleFormatted = $title->getPrefixedText();
2962  Xml::encodeJsCall( 'mw.log.error', [
2963  "Cannot preview $titleFormatted due to script-closing tag."
2964  ] )
2965  );
2966  }
2967  return $content;
2968  }
2969  }
2970  return null;
2971  } );
2972  }
2973  }
2974  return $this->rlClientContext;
2975  }
2976 
2988  public function getRlClient() {
2989  if ( !$this->rlClient ) {
2990  $context = $this->getRlClientContext();
2991  $rl = $this->getResourceLoader();
2992  $this->addModules( [
2993  'user',
2994  'user.options',
2995  ] );
2996  $this->addModuleStyles( [
2997  'site.styles',
2998  'noscript',
2999  'user.styles',
3000  ] );
3001  $this->getSkin()->doSetupSkinUserCss( $this );
3002 
3003  // Prepare exempt modules for buildExemptModules()
3004  $exemptGroups = [ 'site' => [], 'noscript' => [], 'private' => [], 'user' => [] ];
3005  $exemptStates = [];
3006  $moduleStyles = $this->getModuleStyles( /*filter*/ true );
3007 
3008  // Preload getTitleInfo for isKnownEmpty calls below and in ResourceLoaderClientHtml
3009  // Separate user-specific batch for improved cache-hit ratio.
3010  $userBatch = [ 'user.styles', 'user' ];
3011  $siteBatch = array_diff( $moduleStyles, $userBatch );
3012  $dbr = wfGetDB( DB_REPLICA );
3015 
3016  // Filter out modules handled by buildExemptModules()
3017  $moduleStyles = array_filter( $moduleStyles,
3018  static function ( $name ) use ( $rl, $context, &$exemptGroups, &$exemptStates ) {
3019  $module = $rl->getModule( $name );
3020  if ( $module ) {
3021  $group = $module->getGroup();
3022  if ( isset( $exemptGroups[$group] ) ) {
3023  $exemptStates[$name] = 'ready';
3024  if ( !$module->isKnownEmpty( $context ) ) {
3025  // E.g. Don't output empty <styles>
3026  $exemptGroups[$group][] = $name;
3027  }
3028  return false;
3029  }
3030  }
3031  return true;
3032  }
3033  );
3034  $this->rlExemptStyleModules = $exemptGroups;
3035 
3037  'target' => $this->getTarget(),
3038  'nonce' => $this->CSP->getNonce(),
3039  // When 'safemode', disallowUserJs(), or reduceAllowedModules() is used
3040  // to only restrict modules to ORIGIN_CORE (ie. disallow ORIGIN_USER), the list of
3041  // modules enqueud for loading on this page is filtered to just those.
3042  // However, to make sure we also apply the restriction to dynamic dependencies and
3043  // lazy-loaded modules at run-time on the client-side, pass 'safemode' down to the
3044  // StartupModule so that the client-side registry will not contain any restricted
3045  // modules either. (T152169, T185303)
3046  'safemode' => ( $this->getAllowedModules( ResourceLoaderModule::TYPE_COMBINED )
3047  <= ResourceLoaderModule::ORIGIN_CORE_INDIVIDUAL
3048  ) ? '1' : null,
3049  ] );
3050  $rlClient->setConfig( $this->getJSVars() );
3051  $rlClient->setModules( $this->getModules( /*filter*/ true ) );
3052  $rlClient->setModuleStyles( $moduleStyles );
3053  $rlClient->setExemptStates( $exemptStates );
3054  $this->rlClient = $rlClient;
3055  }
3056  return $this->rlClient;
3057  }
3058 
3064  public function headElement( Skin $sk, $includeStyle = true ) {
3065  $config = $this->getConfig();
3066  $userdir = $this->getLanguage()->getDir();
3067  $services = MediaWikiServices::getInstance();
3068  $sitedir = $services->getContentLanguage()->getDir();
3069 
3070  $pieces = [];
3072  $this->getRlClient()->getDocumentAttributes(),
3074  ), [ 'class' => implode( ' ', $this->mAdditionalHtmlClasses ) ] );
3075  $pieces[] = Html::htmlHeader( $htmlAttribs );
3076  $pieces[] = Html::openElement( 'head' );
3077 
3078  if ( $this->getHTMLTitle() == '' ) {
3079  $this->setHTMLTitle( $this->msg( 'pagetitle', $this->getPageTitle() )->inContentLanguage() );
3080  }
3081 
3082  if ( !Html::isXmlMimeType( $config->get( 'MimeType' ) ) ) {
3083  // Add <meta charset="UTF-8">
3084  // This should be before <title> since it defines the charset used by
3085  // text including the text inside <title>.
3086  // The spec recommends defining XHTML5's charset using the XML declaration
3087  // instead of meta.
3088  // Our XML declaration is output by Html::htmlHeader.
3089  // https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-content-type
3090  // https://html.spec.whatwg.org/multipage/semantics.html#charset
3091  $pieces[] = Html::element( 'meta', [ 'charset' => 'UTF-8' ] );
3092  }
3093 
3094  $pieces[] = Html::element( 'title', null, $this->getHTMLTitle() );
3095  $pieces[] = $this->getRlClient()->getHeadHtml( $htmlAttribs['class'] ?? null );
3096  $pieces[] = $this->buildExemptModules();
3097  $pieces = array_merge( $pieces, array_values( $this->getHeadLinksArray() ) );
3098  $pieces = array_merge( $pieces, array_values( $this->mHeadItems ) );
3099 
3100  $pieces[] = Html::closeElement( 'head' );
3101 
3102  $bodyClasses = $this->mAdditionalBodyClasses;
3103  $bodyClasses[] = 'mediawiki';
3104 
3105  # Classes for LTR/RTL directionality support
3106  $bodyClasses[] = $userdir;
3107  $bodyClasses[] = "sitedir-$sitedir";
3108 
3109  $underline = $services->getUserOptionsLookup()->getOption( $this->getUser(), 'underline' );
3110  if ( $underline < 2 ) {
3111  // The following classes can be used here:
3112  // * mw-underline-always
3113  // * mw-underline-never
3114  $bodyClasses[] = 'mw-underline-' . ( $underline ? 'always' : 'never' );
3115  }
3116 
3117  if ( $this->getLanguage()->capitalizeAllNouns() ) {
3118  # A <body> class is probably not the best way to do this . . .
3119  $bodyClasses[] = 'capitalize-all-nouns';
3120  }
3121 
3122  // Parser feature migration class
3123  // The idea is that this will eventually be removed, after the wikitext
3124  // which requires it is cleaned up.
3125  $bodyClasses[] = 'mw-hide-empty-elt';
3126 
3127  $bodyClasses[] = $sk->getPageClasses( $this->getTitle() );
3128  $bodyClasses[] = 'skin-' . Sanitizer::escapeClass( $sk->getSkinName() );
3129  $bodyClasses[] =
3130  'action-' . Sanitizer::escapeClass( Action::getActionName( $this->getContext() ) );
3131 
3132  if ( $sk->isResponsive() ) {
3133  $bodyClasses[] = 'skin--responsive';
3134  }
3135 
3136  $bodyAttrs = [];
3137  // While the implode() is not strictly needed, it's used for backwards compatibility
3138  // (this used to be built as a string and hooks likely still expect that).
3139  $bodyAttrs['class'] = implode( ' ', $bodyClasses );
3140 
3141  // Allow skins and extensions to add body attributes they need
3142  // Get ones from deprecated method
3143  if ( method_exists( $sk, 'addToBodyAttributes' ) ) {
3145  $sk->addToBodyAttributes( $this, $bodyAttrs );
3146  wfDeprecated( 'Skin::addToBodyAttributes method to add body attributes', '1.35' );
3147  }
3148 
3149  // Then run the hook, the recommended way of adding body attributes now
3150  $this->getHookRunner()->onOutputPageBodyAttributes( $this, $sk, $bodyAttrs );
3151 
3152  $pieces[] = Html::openElement( 'body', $bodyAttrs );
3153 
3154  return self::combineWrappedStrings( $pieces );
3155  }
3156 
3162  public function getResourceLoader() {
3163  if ( $this->mResourceLoader === null ) {
3164  // Lazy-initialise as needed
3165  $this->mResourceLoader = MediaWikiServices::getInstance()->getResourceLoader();
3166  }
3167  return $this->mResourceLoader;
3168  }
3169 
3178  public function makeResourceLoaderLink( $modules, $only, array $extraQuery = [] ) {
3179  // Apply 'target' and 'origin' filters
3180  $modules = $this->filterModules( (array)$modules, null, $only );
3181 
3183  $this->getRlClientContext(),
3184  $modules,
3185  $only,
3186  $extraQuery,
3187  $this->CSP->getNonce()
3188  );
3189  }
3190 
3197  protected static function combineWrappedStrings( array $chunks ) {
3198  // Filter out empty values
3199  $chunks = array_filter( $chunks, 'strlen' );
3200  return WrappedString::join( "\n", $chunks );
3201  }
3202 
3209  public function getBottomScripts() {
3210  $chunks = [];
3211  $chunks[] = $this->getRlClient()->getBodyHtml();
3212 
3213  // Legacy non-ResourceLoader scripts
3214  $chunks[] = $this->mScripts;
3215 
3216  if ( $this->limitReportJSData ) {
3219  [ 'wgPageParseReport' => $this->limitReportJSData ]
3220  ),
3221  $this->CSP->getNonce()
3222  );
3223  }
3224 
3225  return self::combineWrappedStrings( $chunks );
3226  }
3227 
3234  public function getJsConfigVars() {
3235  return $this->mJsConfigVars;
3236  }
3237 
3244  public function addJsConfigVars( $keys, $value = null ) {
3245  if ( is_array( $keys ) ) {
3246  foreach ( $keys as $key => $value ) {
3247  $this->mJsConfigVars[$key] = $value;
3248  }
3249  return;
3250  }
3251 
3252  $this->mJsConfigVars[$keys] = $value;
3253  }
3254 
3264  public function getJSVars() {
3265  $curRevisionId = 0;
3266  $articleId = 0;
3267  $canonicalSpecialPageName = false; # T23115
3268  $services = MediaWikiServices::getInstance();
3269 
3270  $title = $this->getTitle();
3271  $ns = $title->getNamespace();
3272  $nsInfo = $services->getNamespaceInfo();
3273  $canonicalNamespace = $nsInfo->exists( $ns )
3274  ? $nsInfo->getCanonicalName( $ns )
3275  : $title->getNsText();
3276 
3277  $sk = $this->getSkin();
3278  // Get the relevant title so that AJAX features can use the correct page name
3279  // when making API requests from certain special pages (T36972).
3280  $relevantTitle = $sk->getRelevantTitle();
3281  $relevantUser = $sk->getRelevantUser();
3282 
3283  if ( $ns === NS_SPECIAL ) {
3284  list( $canonicalSpecialPageName, /*...*/ ) =
3285  $services->getSpecialPageFactory()->
3286  resolveAlias( $title->getDBkey() );
3287  } elseif ( $this->canUseWikiPage() ) {
3288  $wikiPage = $this->getWikiPage();
3289  $curRevisionId = $wikiPage->getLatest();
3290  $articleId = $wikiPage->getId();
3291  }
3292 
3293  $lang = $title->getPageViewLanguage();
3294 
3295  // Pre-process information
3296  $separatorTransTable = $lang->separatorTransformTable();
3297  $separatorTransTable = $separatorTransTable ?: [];
3298  $compactSeparatorTransTable = [
3299  implode( "\t", array_keys( $separatorTransTable ) ),
3300  implode( "\t", $separatorTransTable ),
3301  ];
3302  $digitTransTable = $lang->digitTransformTable();
3303  $digitTransTable = $digitTransTable ?: [];
3304  $compactDigitTransTable = [
3305  implode( "\t", array_keys( $digitTransTable ) ),
3306  implode( "\t", $digitTransTable ),
3307  ];
3308 
3309  $user = $this->getUser();
3310 
3311  // Internal variables for MediaWiki core
3312  $vars = [
3313  // @internal For mediawiki.page.ready
3314  'wgBreakFrames' => $this->getFrameOptions() == 'DENY',
3315 
3316  // @internal For jquery.tablesorter
3317  'wgSeparatorTransformTable' => $compactSeparatorTransTable,
3318  'wgDigitTransformTable' => $compactDigitTransTable,
3319  'wgDefaultDateFormat' => $lang->getDefaultDateFormat(),
3320  'wgMonthNames' => $lang->getMonthNamesArray(),
3321 
3322  // @internal For debugging purposes
3323  'wgRequestId' => WebRequest::getRequestId(),
3324 
3325  // @internal For mw.loader
3326  'wgCSPNonce' => $this->CSP->getNonce(),
3327  ];
3328 
3329  // Start of supported and stable config vars (for use by extensions/gadgets).
3330  $vars += [
3331  'wgCanonicalNamespace' => $canonicalNamespace,
3332  'wgCanonicalSpecialPageName' => $canonicalSpecialPageName,
3333  'wgNamespaceNumber' => $title->getNamespace(),
3334  'wgPageName' => $title->getPrefixedDBkey(),
3335  'wgTitle' => $title->getText(),
3336  'wgCurRevisionId' => $curRevisionId,
3337  'wgRevisionId' => (int)$this->getRevisionId(),
3338  'wgArticleId' => $articleId,
3339  'wgIsArticle' => $this->isArticle(),
3340  'wgIsRedirect' => $title->isRedirect(),
3341  'wgAction' => Action::getActionName( $this->getContext() ),
3342  'wgUserName' => $user->isAnon() ? null : $user->getName(),
3343  'wgUserGroups' => $services->getUserGroupManager()->getUserEffectiveGroups( $user ),
3344  'wgCategories' => $this->getCategories(),
3345  'wgPageContentLanguage' => $lang->getCode(),
3346  'wgPageContentModel' => $title->getContentModel(),
3347  'wgRelevantPageName' => $relevantTitle->getPrefixedDBkey(),
3348  'wgRelevantArticleId' => $relevantTitle->getArticleID(),
3349  ];
3350  if ( $user->isRegistered() ) {
3351  $vars['wgUserId'] = $user->getId();
3352  $vars['wgUserEditCount'] = $user->getEditCount();
3353  $userReg = $user->getRegistration();
3354  $vars['wgUserRegistration'] = $userReg ? (int)wfTimestamp( TS_UNIX, $userReg ) * 1000 : null;
3355  // Get the revision ID of the oldest new message on the user's talk
3356  // page. This can be used for constructing new message alerts on
3357  // the client side.
3358  $userNewMsgRevId = $this->getLastSeenUserTalkRevId();
3359  // Only occupy precious space in the <head> when it is non-null (T53640)
3360  // mw.config.get returns null by default.
3361  if ( $userNewMsgRevId ) {
3362  $vars['wgUserNewMsgRevisionId'] = $userNewMsgRevId;
3363  }
3364  }
3365  $languageConverter = $services->getLanguageConverterFactory()
3366  ->getLanguageConverter( $services->getContentLanguage() );
3367  if ( $languageConverter->hasVariants() ) {
3368  $vars['wgUserVariant'] = $languageConverter->getPreferredVariant();
3369  }
3370  // Same test as SkinTemplate
3371  $vars['wgIsProbablyEditable'] = $this->userCanEditOrCreate( $user, $title );
3372  $vars['wgRelevantPageIsProbablyEditable'] = $relevantTitle &&
3373  $this->userCanEditOrCreate( $user, $relevantTitle );
3374  foreach ( $title->getRestrictionTypes() as $type ) {
3375  // Following keys are set in $vars:
3376  // wgRestrictionCreate, wgRestrictionEdit, wgRestrictionMove, wgRestrictionUpload
3377  $vars['wgRestriction' . ucfirst( $type )] = $title->getRestrictions( $type );
3378  }
3379  if ( $title->isMainPage() ) {
3380  $vars['wgIsMainPage'] = true;
3381  }
3382  if ( $relevantUser && ( !$relevantUser->isHidden() ||
3383  $services->getPermissionManager()->userHasRight( $user, 'hideuser' ) )
3384  ) {
3385  // T120883 if the user is hidden and the viewer cannot see
3386  // hidden users, pretend like it does not exist at all.
3387  $vars['wgRelevantUserName'] = $relevantUser->getName();
3388  }
3389  // End of stable config vars
3390 
3391  if ( $this->mRedirectedFrom ) {
3392  // @internal For skin JS
3393  $vars['wgRedirectedFrom'] = $this->mRedirectedFrom->getPrefixedDBkey();
3394  }
3395 
3396  // Allow extensions to add their custom variables to the mw.config map.
3397  // Use the 'ResourceLoaderGetConfigVars' hook if the variable is not
3398  // page-dependent but site-wide (without state).
3399  // Alternatively, you may want to use OutputPage->addJsConfigVars() instead.
3400  $this->getHookRunner()->onMakeGlobalVariablesScript( $vars, $this );
3401 
3402  // Merge in variables from addJsConfigVars last
3403  return array_merge( $vars, $this->getJsConfigVars() );
3404  }
3405 
3411  private function getLastSeenUserTalkRevId() {
3412  $services = MediaWikiServices::getInstance();
3413  $user = $this->getUser();
3414  $userHasNewMessages = $services
3415  ->getTalkPageNotificationManager()
3416  ->userHasNewMessages( $user );
3417  if ( !$userHasNewMessages ) {
3418  return null;
3419  }
3420 
3421  $timestamp = $services
3422  ->getTalkPageNotificationManager()
3423  ->getLatestSeenMessageTimestamp( $user );
3424 
3425  if ( !$timestamp ) {
3426  return null;
3427  }
3428 
3429  $revRecord = $services->getRevisionLookup()->getRevisionByTimestamp(
3430  $user->getTalkPage(),
3431  $timestamp
3432  );
3433 
3434  if ( !$revRecord ) {
3435  return null;
3436  }
3437 
3438  return $revRecord->getId();
3439  }
3440 
3450  public function userCanPreview() {
3451  $request = $this->getRequest();
3452  if (
3453  $request->getVal( 'action' ) !== 'submit' ||
3454  !$request->wasPosted()
3455  ) {
3456  return false;
3457  }
3458 
3459  $user = $this->getUser();
3460 
3461  if ( !$user->isRegistered() ) {
3462  // Anons have predictable edit tokens
3463  return false;
3464  }
3465  if ( !$user->matchEditToken( $request->getVal( 'wpEditToken' ) ) ) {
3466  return false;
3467  }
3468 
3469  $title = $this->getTitle();
3470  $errors = MediaWikiServices::getInstance()->getPermissionManager()
3471  ->getPermissionErrors( 'edit', $user, $title );
3472  if ( count( $errors ) !== 0 ) {
3473  return false;
3474  }
3475 
3476  return true;
3477  }
3478 
3484  private function userCanEditOrCreate(
3485  User $user,
3487  ) {
3488  $pm = MediaWikiServices::getInstance()->getPermissionManager();
3489  return $pm->quickUserCan( 'edit', $user, $title )
3490  && ( $this->getTitle()->exists() ||
3491  $pm->quickUserCan( 'create', $user, $title ) );
3492  }
3493 
3497  public function getHeadLinksArray() {
3498  $tags = [];
3499  $config = $this->getConfig();
3500 
3501  $canonicalUrl = $this->mCanonicalUrl;
3502 
3503  $tags['meta-generator'] = Html::element( 'meta', [
3504  'name' => 'generator',
3505  'content' => 'MediaWiki ' . MW_VERSION,
3506  ] );
3507 
3508  if ( $config->get( 'ReferrerPolicy' ) !== false ) {
3509  // Per https://w3c.github.io/webappsec-referrer-policy/#unknown-policy-values
3510  // fallbacks should come before the primary value so we need to reverse the array.
3511  foreach ( array_reverse( (array)$config->get( 'ReferrerPolicy' ) ) as $i => $policy ) {
3512  $tags["meta-referrer-$i"] = Html::element( 'meta', [
3513  'name' => 'referrer',
3514  'content' => $policy,
3515  ] );
3516  }
3517  }
3518 
3519  $p = "{$this->mIndexPolicy},{$this->mFollowPolicy}";
3520  if ( $p !== 'index,follow' ) {
3521  // http://www.robotstxt.org/wc/meta-user.html
3522  // Only show if it's different from the default robots policy
3523  $tags['meta-robots'] = Html::element( 'meta', [
3524  'name' => 'robots',
3525  'content' => $p,
3526  ] );
3527  }
3528 
3529  foreach ( $this->mMetatags as $tag ) {
3530  if ( strncasecmp( $tag[0], 'http:', 5 ) === 0 ) {
3531  $a = 'http-equiv';
3532  $tag[0] = substr( $tag[0], 5 );
3533  } elseif ( strncasecmp( $tag[0], 'og:', 3 ) === 0 ) {
3534  $a = 'property';
3535  } else {
3536  $a = 'name';
3537  }
3538  $tagName = "meta-{$tag[0]}";
3539  if ( isset( $tags[$tagName] ) ) {
3540  $tagName .= $tag[1];
3541  }
3542  $tags[$tagName] = Html::element( 'meta',
3543  [
3544  $a => $tag[0],
3545  'content' => $tag[1]
3546  ]
3547  );
3548  }
3549 
3550  foreach ( $this->mLinktags as $tag ) {
3551  $tags[] = Html::element( 'link', $tag );
3552  }
3553 
3554  # Universal edit button
3555  if ( $config->get( 'UniversalEditButton' ) && $this->isArticleRelated() ) {
3556  if ( $this->userCanEditOrCreate( $this->getUser(), $this->getTitle() ) ) {
3557  // Original UniversalEditButton
3558  $msg = $this->msg( 'edit' )->text();
3559  $tags['universal-edit-button'] = Html::element( 'link', [
3560  'rel' => 'alternate',
3561  'type' => 'application/x-wiki',
3562  'title' => $msg,
3563  'href' => $this->getTitle()->getEditURL(),
3564  ] );
3565  // Alternate edit link
3566  $tags['alternative-edit'] = Html::element( 'link', [
3567  'rel' => 'edit',
3568  'title' => $msg,
3569  'href' => $this->getTitle()->getEditURL(),
3570  ] );
3571  }
3572  }
3573 
3574  # Generally the order of the favicon and apple-touch-icon links
3575  # should not matter, but Konqueror (3.5.9 at least) incorrectly
3576  # uses whichever one appears later in the HTML source. Make sure
3577  # apple-touch-icon is specified first to avoid this.
3578  if ( $config->get( 'AppleTouchIcon' ) !== false ) {
3579  $tags['apple-touch-icon'] = Html::element( 'link', [
3580  'rel' => 'apple-touch-icon',
3581  'href' => $config->get( 'AppleTouchIcon' )
3582  ] );
3583  }
3584 
3585  if ( $config->get( 'Favicon' ) !== false ) {
3586  $tags['favicon'] = Html::element( 'link', [
3587  'rel' => 'shortcut icon',
3588  'href' => $config->get( 'Favicon' )
3589  ] );
3590  }
3591 
3592  # OpenSearch description link
3593  $tags['opensearch'] = Html::element( 'link', [
3594  'rel' => 'search',
3595  'type' => 'application/opensearchdescription+xml',
3596  'href' => wfScript( 'opensearch_desc' ),
3597  'title' => $this->msg( 'opensearch-desc' )->inContentLanguage()->text(),
3598  ] );
3599 
3600  # Real Simple Discovery link, provides auto-discovery information
3601  # for the MediaWiki API (and potentially additional custom API
3602  # support such as WordPress or Twitter-compatible APIs for a
3603  # blogging extension, etc)
3604  $tags['rsd'] = Html::element( 'link', [
3605  'rel' => 'EditURI',
3606  'type' => 'application/rsd+xml',
3607  // Output a protocol-relative URL here if $wgServer is protocol-relative.
3608  // Whether RSD accepts relative or protocol-relative URLs is completely
3609  // undocumented, though.
3610  'href' => wfExpandUrl( wfAppendQuery(
3611  wfScript( 'api' ),
3612  [ 'action' => 'rsd' ] ),
3614  ),
3615  ] );
3616 
3617  # Language variants
3618  $services = MediaWikiServices::getInstance();
3619  $languageConverterFactory = $services->getLanguageConverterFactory();
3620  $disableLangConversion = $languageConverterFactory->isConversionDisabled();
3621  if ( !$disableLangConversion ) {
3622  $lang = $this->getTitle()->getPageLanguage();
3623  $languageConverter = $languageConverterFactory->getLanguageConverter( $lang );
3624  if ( $languageConverter->hasVariants() ) {
3625  $variants = $languageConverter->getVariants();
3626  foreach ( $variants as $variant ) {
3627  $tags["variant-$variant"] = Html::element( 'link', [
3628  'rel' => 'alternate',
3629  'hreflang' => LanguageCode::bcp47( $variant ),
3630  'href' => $this->getTitle()->getLocalURL(
3631  [ 'variant' => $variant ] )
3632  ]
3633  );
3634  }
3635  # x-default link per https://support.google.com/webmasters/answer/189077?hl=en
3636  $tags["variant-x-default"] = Html::element( 'link', [
3637  'rel' => 'alternate',
3638  'hreflang' => 'x-default',
3639  'href' => $this->getTitle()->getLocalURL() ] );
3640  }
3641  }
3642 
3643  # Copyright
3644  if ( $this->copyrightUrl !== null ) {
3645  $copyright = $this->copyrightUrl;
3646  } else {
3647  $copyright = '';
3648  if ( $config->get( 'RightsPage' ) ) {
3649  $copy = Title::newFromText( $config->get( 'RightsPage' ) );
3650 
3651  if ( $copy ) {
3652  $copyright = $copy->getLocalURL();
3653  }
3654  }
3655 
3656  if ( !$copyright && $config->get( 'RightsUrl' ) ) {
3657  $copyright = $config->get( 'RightsUrl' );
3658  }
3659  }
3660 
3661  if ( $copyright ) {
3662  $tags['copyright'] = Html::element( 'link', [
3663  'rel' => 'license',
3664  'href' => $copyright ]
3665  );
3666  }
3667 
3668  # Feeds
3669  if ( $config->get( 'Feed' ) ) {
3670  $feedLinks = [];
3671 
3672  foreach ( $this->getSyndicationLinks() as $format => $link ) {
3673  # Use the page name for the title. In principle, this could
3674  # lead to issues with having the same name for different feeds
3675  # corresponding to the same page, but we can't avoid that at
3676  # this low a level.
3677 
3678  $feedLinks[] = $this->feedLink(
3679  $format,
3680  $link,
3681  # Used messages: 'page-rss-feed' and 'page-atom-feed' (for an easier grep)
3682  $this->msg(
3683  "page-{$format}-feed", $this->getTitle()->getPrefixedText()
3684  )->text()
3685  );
3686  }
3687 
3688  # Recent changes feed should appear on every page (except recentchanges,
3689  # that would be redundant). Put it after the per-page feed to avoid
3690  # changing existing behavior. It's still available, probably via a
3691  # menu in your browser. Some sites might have a different feed they'd
3692  # like to promote instead of the RC feed (maybe like a "Recent New Articles"
3693  # or "Breaking news" one). For this, we see if $wgOverrideSiteFeed is defined.
3694  # If so, use it instead.
3695  $sitename = $config->get( 'Sitename' );
3696  $overrideSiteFeed = $config->get( 'OverrideSiteFeed' );
3697  if ( $overrideSiteFeed ) {
3698  foreach ( $overrideSiteFeed as $type => $feedUrl ) {
3699  // Note, this->feedLink escapes the url.
3700  $feedLinks[] = $this->feedLink(
3701  $type,
3702  $feedUrl,
3703  $this->msg( "site-{$type}-feed", $sitename )->text()
3704  );
3705  }
3706  } elseif ( !$this->getTitle()->isSpecial( 'Recentchanges' ) ) {
3707  $rctitle = SpecialPage::getTitleFor( 'Recentchanges' );
3708  foreach ( $this->getAdvertisedFeedTypes() as $format ) {
3709  $feedLinks[] = $this->feedLink(
3710  $format,
3711  $rctitle->getLocalURL( [ 'feed' => $format ] ),
3712  # For grep: 'site-rss-feed', 'site-atom-feed'
3713  $this->msg( "site-{$format}-feed", $sitename )->text()
3714  );
3715  }
3716  }
3717 
3718  # Allow extensions to change the list pf feeds. This hook is primarily for changing,
3719  # manipulating or removing existing feed tags. If you want to add new feeds, you should
3720  # use OutputPage::addFeedLink() instead.
3721  $this->getHookRunner()->onAfterBuildFeedLinks( $feedLinks );
3722 
3723  $tags += $feedLinks;
3724  }
3725 
3726  # Canonical URL
3727  if ( $config->get( 'EnableCanonicalServerLink' ) ) {
3728  if ( $canonicalUrl !== false ) {
3729  $canonicalUrl = wfExpandUrl( $canonicalUrl, PROTO_CANONICAL );
3730  } elseif ( $this->isArticleRelated() ) {
3731  // This affects all requests where "setArticleRelated" is true. This is
3732  // typically all requests that show content (query title, curid, oldid, diff),
3733  // and all wikipage actions (edit, delete, purge, info, history etc.).
3734  // It does not apply to File pages and Special pages.
3735  // 'history' and 'info' actions address page metadata rather than the page
3736  // content itself, so they may not be canonicalized to the view page url.
3737  // TODO: this ought to be better encapsulated in the Action class.
3738  $action = Action::getActionName( $this->getContext() );
3739  if ( in_array( $action, [ 'history', 'info' ] ) ) {
3740  $query = "action={$action}";
3741  } else {
3742  $query = '';
3743  }
3744  $canonicalUrl = $this->getTitle()->getCanonicalURL( $query );
3745  } else {
3746  $reqUrl = $this->getRequest()->getRequestURL();
3747  $canonicalUrl = wfExpandUrl( $reqUrl, PROTO_CANONICAL );
3748  }
3749  }
3750  if ( $canonicalUrl !== false ) {
3751  $tags[] = Html::element( 'link', [
3752  'rel' => 'canonical',
3753  'href' => $canonicalUrl
3754  ] );
3755  }
3756 
3757  // Allow extensions to add, remove and/or otherwise manipulate these links
3758  // If you want only to *add* <head> links, please use the addHeadItem()
3759  // (or addHeadItems() for multiple items) method instead.
3760  // This hook is provided as a last resort for extensions to modify these
3761  // links before the output is sent to client.
3762  $this->getHookRunner()->onOutputPageAfterGetHeadLinksArray( $tags, $this );
3763 
3764  return $tags;
3765  }
3766 
3775  private function feedLink( $type, $url, $text ) {
3776  return Html::element( 'link', [
3777  'rel' => 'alternate',
3778  'type' => "application/$type+xml",
3779  'title' => $text,
3780  'href' => $url ]
3781  );
3782  }
3783 
3793  public function addStyle( $style, $media = '', $condition = '', $dir = '' ) {
3794  $options = [];
3795  if ( $media ) {
3796  $options['media'] = $media;
3797  }
3798  if ( $condition ) {
3799  $options['condition'] = $condition;
3800  }
3801  if ( $dir ) {
3802  $options['dir'] = $dir;
3803  }
3804  $this->styles[$style] = $options;
3805  }
3806 
3814  public function addInlineStyle( $style_css, $flip = 'noflip' ) {
3815  if ( $flip === 'flip' && $this->getLanguage()->isRTL() ) {
3816  # If wanted, and the interface is right-to-left, flip the CSS
3817  $style_css = CSSJanus::transform( $style_css, true, false );
3818  }
3819  $this->mInlineStyles .= Html::inlineStyle( $style_css );
3820  }
3821 
3827  protected function buildExemptModules() {
3828  $chunks = [];
3829 
3830  // Requirements:
3831  // - Within modules provided by the software (core, skin, extensions),
3832  // styles from skin stylesheets should be overridden by styles
3833  // from modules dynamically loaded with JavaScript.
3834  // - Styles from site-specific, private, and user modules should override
3835  // both of the above.
3836  //
3837  // The effective order for stylesheets must thus be:
3838  // 1. Page style modules, formatted server-side by ResourceLoaderClientHtml.
3839  // 2. Dynamically-loaded styles, inserted client-side by mw.loader.
3840  // 3. Styles that are site-specific, private or from the user, formatted
3841  // server-side by this function.
3842  //
3843  // The 'ResourceLoaderDynamicStyles' marker helps JavaScript know where
3844  // point #2 is.
3845 
3846  // Add legacy styles added through addStyle()/addInlineStyle() here
3847  $chunks[] = implode( '', $this->buildCssLinksArray() ) . $this->mInlineStyles;
3848 
3849  // Things that go after the ResourceLoaderDynamicStyles marker
3850  $append = [];
3851  $separateReq = [ 'site.styles', 'user.styles' ];
3852  foreach ( $this->rlExemptStyleModules as $group => $moduleNames ) {
3853  if ( $moduleNames ) {
3854  $append[] = $this->makeResourceLoaderLink(
3855  array_diff( $moduleNames, $separateReq ),
3856  ResourceLoaderModule::TYPE_STYLES
3857  );
3858 
3859  foreach ( array_intersect( $moduleNames, $separateReq ) as $name ) {
3860  // These require their own dedicated request in order to support "@import"
3861  // syntax, which is incompatible with concatenation. (T147667, T37562)
3862  $append[] = $this->makeResourceLoaderLink( $name,
3863  ResourceLoaderModule::TYPE_STYLES
3864  );
3865  }
3866  }
3867  }
3868  if ( $append ) {
3869  $chunks[] = Html::element(
3870  'meta',
3871  [ 'name' => 'ResourceLoaderDynamicStyles', 'content' => '' ]
3872  );
3873  $chunks = array_merge( $chunks, $append );
3874  }
3875 
3876  return self::combineWrappedStrings( $chunks );
3877  }
3878 
3882  public function buildCssLinksArray() {
3883  $links = [];
3884 
3885  foreach ( $this->styles as $file => $options ) {
3886  $link = $this->styleLink( $file, $options );
3887  if ( $link ) {
3888  $links[$file] = $link;
3889  }
3890  }
3891  return $links;
3892  }
3893 
3901  protected function styleLink( $style, array $options ) {
3902  if ( isset( $options['dir'] ) && $this->getLanguage()->getDir() != $options['dir'] ) {
3903  return '';
3904  }
3905 
3906  if ( isset( $options['media'] ) ) {
3907  $media = self::transformCssMedia( $options['media'] );
3908  if ( $media === null ) {
3909  return '';
3910  }
3911  } else {
3912  $media = 'all';
3913  }
3914 
3915  if ( substr( $style, 0, 1 ) == '/' ||
3916  substr( $style, 0, 5 ) == 'http:' ||
3917  substr( $style, 0, 6 ) == 'https:' ) {
3918  $url = $style;
3919  } else {
3920  $config = $this->getConfig();
3921  // Append file hash as query parameter
3923  $config,
3924  $config->get( 'StylePath' ) . '/' . $style
3925  );
3926  }
3927 
3928  $link = Html::linkedStyle( $url, $media );
3929 
3930  if ( isset( $options['condition'] ) ) {
3931  $condition = htmlspecialchars( $options['condition'] );
3932  $link = "<!--[if $condition]>$link<![endif]-->";
3933  }
3934  return $link;
3935  }
3936 
3958  public static function transformResourcePath( Config $config, $path ) {
3959  global $IP;
3960 
3961  $localDir = $IP;
3962  $remotePathPrefix = $config->get( 'ResourceBasePath' );
3963  if ( $remotePathPrefix === '' ) {
3964  // The configured base path is required to be empty string for
3965  // wikis in the domain root
3966  $remotePath = '/';
3967  } else {
3968  $remotePath = $remotePathPrefix;
3969  }
3970  if ( strpos( $path, $remotePath ) !== 0 || substr( $path, 0, 2 ) === '//' ) {
3971  // - Path is outside wgResourceBasePath, ignore.
3972  // - Path is protocol-relative. Fixes T155310. Not supported by RelPath lib.
3973  return $path;
3974  }
3975  // For files in resources, extensions/ or skins/, ResourceBasePath is preferred here.
3976  // For other misc files in $IP, we'll fallback to that as well. There is, however, a fourth
3977  // supported dir/path pair in the configuration (wgUploadDirectory, wgUploadPath)
3978  // which is not expected to be in wgResourceBasePath on CDNs. (T155146)
3979  $uploadPath = $config->get( 'UploadPath' );
3980  if ( strpos( $path, $uploadPath ) === 0 ) {
3981  $localDir = $config->get( 'UploadDirectory' );
3982  $remotePathPrefix = $remotePath = $uploadPath;
3983  }
3984 
3985  $path = RelPath::getRelativePath( $path, $remotePath );
3986  return self::transformFilePath( $remotePathPrefix, $localDir, $path );
3987  }
3988 
4000  public static function transformFilePath( $remotePathPrefix, $localPath, $file ) {
4001  // This MUST match the equivalent logic in CSSMin::remapOne()
4002  $hash = md5_file( "$localPath/$file" );
4003  if ( $hash === false ) {
4004  wfLogWarning( __METHOD__ . ": Failed to hash $localPath/$file" );
4005  $hash = '';
4006  }
4007  return "$remotePathPrefix/$file?" . substr( $hash, 0, 5 );
4008  }
4009 
4017  public static function transformCssMedia( $media ) {
4018  global $wgRequest;
4019 
4020  // https://www.w3.org/TR/css3-mediaqueries/#syntax
4021  $screenMediaQueryRegex = '/^(?:only\s+)?screen\b/i';
4022 
4023  // Switch in on-screen display for media testing
4024  $switches = [
4025  'printable' => 'print',
4026  'handheld' => 'handheld',
4027  ];
4028  foreach ( $switches as $switch => $targetMedia ) {
4029  if ( $wgRequest->getBool( $switch ) ) {
4030  if ( $media == $targetMedia ) {
4031  $media = '';
4032  } elseif ( preg_match( $screenMediaQueryRegex, $media ) === 1 ) {
4033  /* This regex will not attempt to understand a comma-separated media_query_list
4034  *
4035  * Example supported values for $media:
4036  * 'screen', 'only screen', 'screen and (min-width: 982px)' ),
4037  * Example NOT supported value for $media:
4038  * '3d-glasses, screen, print and resolution > 90dpi'
4039  *
4040  * If it's a print request, we never want any kind of screen stylesheets
4041  * If it's a handheld request (currently the only other choice with a switch),
4042  * we don't want simple 'screen' but we might want screen queries that
4043  * have a max-width or something, so we'll pass all others on and let the
4044  * client do the query.
4045  */
4046  if ( $targetMedia == 'print' || $media == 'screen' ) {
4047  return null;
4048  }
4049  }
4050  }
4051  }
4052 
4053  return $media;
4054  }
4055 
4064  public function addWikiMsg( ...$args ) {
4065  $name = array_shift( $args );
4066  $this->addWikiMsgArray( $name, $args );
4067  }
4068 
4077  public function addWikiMsgArray( $name, $args ) {
4078  $this->addHTML( $this->msg( $name, $args )->parseAsBlock() );
4079  }
4080 
4107  public function wrapWikiMsg( $wrap, ...$msgSpecs ) {
4108  $s = $wrap;
4109  foreach ( $msgSpecs as $n => $spec ) {
4110  if ( is_array( $spec ) ) {
4111  $args = $spec;
4112  $name = array_shift( $args );
4113  } else {
4114  $args = [];
4115  $name = $spec;
4116  }
4117  $s = str_replace( '$' . ( $n + 1 ), $this->msg( $name, $args )->plain(), $s );
4118  }
4119  $this->addWikiTextAsInterface( $s );
4120  }
4121 
4127  public function isTOCEnabled() {
4128  return $this->mEnableTOC;
4129  }
4130 
4138  public static function setupOOUI( $skinName = 'default', $dir = 'ltr' ) {
4140  $theme = $themes[$skinName] ?? $themes['default'];
4141  // For example, 'OOUI\WikimediaUITheme'.
4142  $themeClass = "OOUI\\{$theme}Theme";
4143  OOUI\Theme::setSingleton( new $themeClass() );
4144  OOUI\Element::setDefaultDir( $dir );
4145  }
4146 
4153  public function enableOOUI() {
4155  strtolower( $this->getSkin()->getSkinName() ),
4156  $this->getLanguage()->getDir()
4157  );
4158  $this->addModuleStyles( [
4159  'oojs-ui-core.styles',
4160  'oojs-ui.styles.indicators',
4161  'mediawiki.widgets.styles',
4162  'oojs-ui-core.icons',
4163  ] );
4164  }
4165 
4176  public function getCSPNonce() {
4177  return $this->CSP->getNonce();
4178  }
4179 
4186  public function getCSP() {
4187  return $this->CSP;
4188  }
4189 }
Action\getActionName
static getActionName(IContextSource $context)
Get the action that will be executed, not necessarily the one passed passed through the "action" requ...
Definition: Action.php:154
OutputPage\preventClickjacking
preventClickjacking( $enable=true)
Set a flag which will cause an X-Frame-Options header appropriate for edit pages to be sent.
Definition: OutputPage.php:2342
OutputPage\output
output( $return=false)
Finally, all the text has been munged and accumulated into the object, let's actually output it:
Definition: OutputPage.php:2527
ParserOutput\getEnableOOUI
getEnableOOUI()
Definition: ParserOutput.php:693
OutputPage\addBacklinkSubtitle
addBacklinkSubtitle(Title $title, $query=[])
Add a subtitle containing a backlink to a page.
Definition: OutputPage.php:1102
OutputPage\$mCategoryLinks
string[][] $mCategoryLinks
Definition: OutputPage.php:122
OutputPage\$mLastModified
string $mLastModified
Used for sending cache control.
Definition: OutputPage.php:119
ParserOptions
Set options of the Parser.
Definition: ParserOptions.php:44
OutputPage\getCategoryLinks
getCategoryLinks()
Get the list of category links, in a 2-D array with the following format: $arr[$type][] = $link,...
Definition: OutputPage.php:1460
OutputPage\addMeta
addMeta( $name, $val)
Add a new "<meta>" tag To add an http-equiv meta tag, precede the name with "http:".
Definition: OutputPage.php:405
ContextSource\$context
IContextSource $context
Definition: ContextSource.php:38
ContextSource\getConfig
getConfig()
Definition: ContextSource.php:71
OutputPage\getTarget
getTarget()
Definition: OutputPage.php:592
ResourceLoaderContext
Context object that contains information about the state of a specific ResourceLoader web request.
Definition: ResourceLoaderContext.php:33
OutputPage\getSubtitle
getSubtitle()
Definition: OutputPage.php:1116
OutputPage\parseAsInterface
parseAsInterface( $text, $linestart=true)
Parse wikitext in the user interface language and return the HTML.
Definition: OutputPage.php:2060
FauxRequest
WebRequest clone which takes values from a provided array.
Definition: FauxRequest.php:35
OutputPage\enableClientCache
enableClientCache( $state)
Use enableClientCache(false) to force it to send nocache headers.
Definition: OutputPage.php:2177
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:363
ContextSource\getContext
getContext()
Get the base IContextSource object.
Definition: ContextSource.php:46
wfResetOutputBuffers
wfResetOutputBuffers( $resetGzipEncoding=true)
Clear away any user-level output buffers, discarding contents.
Definition: GlobalFunctions.php:1653
OutputPage\getLanguageLinks
getLanguageLinks()
Get the list of language links.
Definition: OutputPage.php:1352
OutputPage\buildBacklinkSubtitle
static buildBacklinkSubtitle(Title $title, $query=[])
Build message object for a subtitle containing a backlink to a page.
Definition: OutputPage.php:1087
HtmlArmor
Marks HTML that shouldn't be escaped.
Definition: HtmlArmor.php:30
ResourceLoaderClientHtml
Load and configure a ResourceLoader client on an HTML page.
Definition: ResourceLoaderClientHtml.php:30
OutputPage\reduceAllowedModules
reduceAllowedModules( $type, $level)
Limit the highest level of CSS/JS untrustworthiness allowed.
Definition: OutputPage.php:1596
OutputPage\$mModuleStyles
array $mModuleStyles
Definition: OutputPage.php:169
OutputPage\addSubtitle
addSubtitle( $str)
Add $str to the subtitle.
Definition: OutputPage.php:1071
OutputPage\addScriptFile
addScriptFile( $file, $unused=null)
Add a JavaScript file to be loaded as <script> on this page.
Definition: OutputPage.php:479
OutputPage\addAcceptLanguage
addAcceptLanguage()
T23672: Add Accept-Language to Vary header if there's no 'variant' parameter in GET.
Definition: OutputPage.php:2319
ParserOutput
Definition: ParserOutput.php:31
Article\formatRobotPolicy
static formatRobotPolicy( $policy)
Converts a String robot policy into an associative array, to allow merging of several policies using ...
Definition: Article.php:1028
OutputPage\getJSVars
getJSVars()
Get an array containing the variables to be set in mw.config in JavaScript.
Definition: OutputPage.php:3264
ResourceLoader\makeConfigSetScript
static makeConfigSetScript(array $configuration)
Return JS code which will set the MediaWiki configuration array to the given value.
Definition: ResourceLoader.php:1671
OutputPage\getRlClientContext
getRlClientContext()
Definition: OutputPage.php:2932
OutputPage\getDisplayTitle
getDisplayTitle()
Returns page display title.
Definition: OutputPage.php:1022
OutputPage\$mRedirectedFrom
Title $mRedirectedFrom
If the current page was reached through a redirect, $mRedirectedFrom contains the Title of the redire...
Definition: OutputPage.php:295
Sanitizer\stripAllTags
static stripAllTags( $html)
Take a fragment of (potentially invalid) HTML and return a version with any tags removed,...
Definition: Sanitizer.php:1571
OutputPage\setTitle
setTitle(Title $t)
Set the Title object to use.
Definition: OutputPage.php:1050
OutputPage\$mVaryHeader
array $mVaryHeader
Headers that cause the cache to vary.
Definition: OutputPage.php:285
OutputPage\showsCopyright
showsCopyright()
Return whether the standard copyright should be shown for the current page.
Definition: OutputPage.php:1323
OutputPage\addLink
addLink(array $linkarr)
Add a new <link> tag to the page header.
Definition: OutputPage.php:426
OutputPage\addContentOverride
addContentOverride(LinkTarget $target, Content $content)
Add a mapping from a LinkTarget to a Content, for things like page preview.
Definition: OutputPage.php:612
OutputPage\addCategoryLinksToLBAndGetResult
addCategoryLinksToLBAndGetResult(array $categories)
Definition: OutputPage.php:1410
OutputPage\parserOptions
parserOptions()
Get/set the ParserOptions object to use for wikitext parsing.
Definition: OutputPage.php:1653
OutputPage\hasHeadItem
hasHeadItem( $name)
Check if the header item $name is already set.
Definition: OutputPage.php:688
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:172
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
OutputPage\getMetaTags
getMetaTags()
Returns the current <meta> tags.
Definition: OutputPage.php:415
OutputPage\addLanguageLinks
addLanguageLinks(array $newLinkArray)
Add new language links.
Definition: OutputPage.php:1333
OutputPage\addLinkHeader
addLinkHeader( $header)
Add an HTTP Link: header.
Definition: OutputPage.php:2295
OutputPage\addModuleStyles
addModuleStyles( $modules)
Load the styles of one or more style-only ResourceLoader modules on this page.
Definition: OutputPage.php:585
OutputPage\$mNewSectionLink
bool $mNewSectionLink
Definition: OutputPage.php:234
wfSetVar
wfSetVar(&$dest, $source, $force=false)
Sets dest to source and returns the original value of dest If source is NULL, it just returns the val...
Definition: GlobalFunctions.php:1561
OutputPage\getCSP
getCSP()
Get the ContentSecurityPolicy object.
Definition: OutputPage.php:4186
OutputPage\isArticleRelated
isArticleRelated()
Return whether this page is related an article on the wiki.
Definition: OutputPage.php:1301
OutputPage\setArticleBodyOnly
setArticleBodyOnly( $only)
Set whether the output should only contain the body of the article, without any skin,...
Definition: OutputPage.php:709
OutputPage\getFrameOptions
getFrameOptions()
Get the X-Frame-Options header value (without the name part), or false if there isn't one.
Definition: OutputPage.php:2372
OutputPage\__construct
__construct(IContextSource $context)
Constructor for OutputPage.
Definition: OutputPage.php:347
ResourceLoader\makeInlineScript
static makeInlineScript( $script, $nonce=null)
Make an HTML script that runs given JS code after startup and base modules.
Definition: ResourceLoader.php:1644
OutputPage\$mRedirectCode
string $mRedirectCode
Definition: OutputPage.php:193
Sanitizer\removeHTMLtags
static removeHTMLtags( $text, $processCallback=null, $args=[], $extratags=[], $removetags=[])
Cleans up HTML, removes dangerous tags and attributes, and removes HTML comments.
Definition: Sanitizer.php:239
OutputPage\getRevisionId
getRevisionId()
Get the displayed revision ID.
Definition: OutputPage.php:1689
OutputPage\clearHTML
clearHTML()
Clear the body HTML.
Definition: OutputPage.php:1634
OutputPage\addScript
addScript( $script)
Add raw HTML to the list of scripts (including <script> tag, etc.) Internal use only.
Definition: OutputPage.php:467
ParserOutput\getModules
getModules()
Definition: ParserOutput.php:646
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1832
ParserOutput\getImages
& getImages()
Definition: ParserOutput.php:622
OutputPage\returnToMain
returnToMain( $unused=null, $returnto=null, $returntoquery=null)
Add a "return to" link pointing to a specified title, or the title indicated in the request,...
Definition: OutputPage.php:2905
OutputPage\buildCssLinksArray
buildCssLinksArray()
Definition: OutputPage.php:3882
OutputPage\addParserOutputMetadata
addParserOutputMetadata(ParserOutput $parserOutput)
Add all metadata associated with a ParserOutput object, but without the actual HTML.
Definition: OutputPage.php:1878
OutputPage\combineWrappedStrings
static combineWrappedStrings(array $chunks)
Combine WrappedString chunks and filter out empty ones.
Definition: OutputPage.php:3197
Sanitizer\mergeAttributes
static mergeAttributes( $a, $b)
Merge two sets of HTML attributes.
Definition: Sanitizer.php:541
MW_VERSION
const MW_VERSION
The running version of MediaWiki.
Definition: Defines.php:36
OutputPage\$mHideNewSectionLink
bool $mHideNewSectionLink
Definition: OutputPage.php:237
OutputPage\$contentOverrides
array $contentOverrides
Map Title to Content.
Definition: OutputPage.php:321
OutputPage\$mBodytext
string $mBodytext
Contains all of the "<body>" content.
Definition: OutputPage.php:80
OutputPage\getOriginTrials
getOriginTrials()
Get the Origin-Trial header values.
Definition: OutputPage.php:2388
ParserOutput\getJsConfigVars
getJsConfigVars()
Definition: ParserOutput.php:658
wfUrlencode
wfUrlencode( $s)
We want some things to be included as literal characters in our title URLs for prettiness,...
Definition: GlobalFunctions.php:313
OutputPage\getBottomScripts
getBottomScripts()
JS stuff to put at the bottom of the <body>.
Definition: OutputPage.php:3209
OutputPage\$mEnableClientCache
bool $mEnableClientCache
Gwicke work on squid caching? Roughly from 2003.
Definition: OutputPage.php:228
ParserOptions\newFromAnon
static newFromAnon()
Get a ParserOptions object for an anonymous user.
Definition: ParserOptions.php:1117
OutputPage\couldBePublicCached
couldBePublicCached()
Whether the output might become publicly cached.
Definition: OutputPage.php:2187
OutputPage\addHeadItems
addHeadItems( $values)
Add one or more head items to the output.
Definition: OutputPage.php:678
OutputPage\getModuleStyles
getModuleStyles( $filter=false, $position=null)
Get the list of style-only modules to load on this page.
Definition: OutputPage.php:570
OutputPage\getFeaturePolicyReportOnly
getFeaturePolicyReportOnly()
Definition: OutputPage.php:2418
$file
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
Html\htmlHeader
static htmlHeader(array $attribs=[])
Constructs the opening html-tag with necessary doctypes depending on global variables.
Definition: Html.php:968
OutputPage\versionRequired
versionRequired( $version)
Display an error page indicating that a given version of MediaWiki is required to use it.
Definition: OutputPage.php:2803
ResourceLoaderClientHtml\setExemptStates
setExemptStates(array $states)
Set state of special modules that are handled by the caller manually.
Definition: ResourceLoaderClientHtml.php:108
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1231
SpecialPage\getTitleFor
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
Definition: SpecialPage.php:107
Sanitizer\escapeClass
static escapeClass( $class)
Given a value, escape it so that it can be used as a CSS class and return it.
Definition: Sanitizer.php:973
OutputPage\getFileVersion
getFileVersion()
Get the displayed file version.
Definition: OutputPage.php:1743
OutputPage\getSyndicationLinks
getSyndicationLinks()
Return URLs for each supported syndication format for this page.
Definition: OutputPage.php:1246
ContextSource\canUseWikiPage
canUseWikiPage()
Check whether a WikiPage object can be get with getWikiPage().
Definition: ContextSource.php:102
wfLogWarning
wfLogWarning( $msg, $callerOffset=1, $level=E_USER_WARNING)
Send a warning as a PHP error and the debug log.
Definition: GlobalFunctions.php:1094
ContextSource\getRequest
getRequest()
Definition: ContextSource.php:80
Title\newMainPage
static newMainPage(MessageLocalizer $localizer=null)
Create a new Title for the Main Page.
Definition: Title.php:688
OutputPage\getRedirect
getRedirect()
Get the URL to redirect to, or an empty string if not redirect URL set.
Definition: OutputPage.php:373
OutputPage\setCanonicalUrl
setCanonicalUrl( $url)
Set the URL to be used for the <link rel=canonical>>.
Definition: OutputPage.php:445
$res
$res
Definition: testCompression.php:57
ParserOutput\getHeadItems
getHeadItems()
Definition: ParserOutput.php:642
ContextSource\getUser
getUser()
Stable to override.
Definition: ContextSource.php:135
ContextSource\getTitle
getTitle()
Definition: ContextSource.php:89
OutputPage\$mLinktags
array $mLinktags
Definition: OutputPage.php:54
OutputPage\$mIndexPolicy
$mIndexPolicy
Definition: OutputPage.php:277
Skin\getHtmlElementAttributes
getHtmlElementAttributes()
Return values for <html> element.
Definition: Skin.php:544
OutputPage\setIndicators
setIndicators(array $indicators)
Add an array of indicators, with their identifiers as array keys and HTML contents as values.
Definition: OutputPage.php:1496
LinkCache\getSelectFields
static getSelectFields()
Fields that LinkCache needs to select.
Definition: LinkCache.php:231
OutputPage\addHTML
addHTML( $text)
Append $text to the body HTML.
Definition: OutputPage.php:1614
OutputPage\parseInternal
parseInternal( $text, $title, $linestart, $interface)
Parse wikitext and return the HTML (internal implementation helper)
Definition: OutputPage.php:2101
OutputPage\getReportTo
getReportTo()
Definition: OutputPage.php:2394
OutputPage\addHeadItem
addHeadItem( $name, $value)
Add or replace a head item to the output.
Definition: OutputPage.php:668
OutputPage\addContentOverrideCallback
addContentOverrideCallback(callable $callback)
Add a callback for mapping from a Title to a Content object, for things like page preview.
Definition: OutputPage.php:632
OutputPage\getRevisionTimestamp
getRevisionTimestamp()
Get the timestamp of displayed revision.
Definition: OutputPage.php:1720
OutputPage\addWikiMsgArray
addWikiMsgArray( $name, $args)
Add a wikitext-formatted message to the output.
Definition: OutputPage.php:4077
OutputPage\transformCssMedia
static transformCssMedia( $media)
Transform "media" attribute based on request parameters.
Definition: OutputPage.php:4017
OutputPage\setLastModified
setLastModified( $timestamp)
Override the last modified timestamp.
Definition: OutputPage.php:857
$dbr
$dbr
Definition: testCompression.php:54
ResourceLoaderClientHtml\setConfig
setConfig(array $vars)
Set mw.config variables.
Definition: ResourceLoaderClientHtml.php:77
ContextSource\getLanguage
getLanguage()
Definition: ContextSource.php:151
OutputPage\$mImageTimeKeys
array $mImageTimeKeys
Definition: OutputPage.php:190
NS_SPECIAL
const NS_SPECIAL
Definition: Defines.php:53
OutputPage\showPermissionsErrorPage
showPermissionsErrorPage(array $errors, $action=null)
Output a standard permission error page.
Definition: OutputPage.php:2718
wfAppendQuery
wfAppendQuery( $url, $query)
Append a query string to an existing URL, which may or may not already have query string parameters a...
Definition: GlobalFunctions.php:443
ParserOutput\getModuleStyles
getModuleStyles()
Definition: ParserOutput.php:650
OutputPage\getLinkTags
getLinkTags()
Returns the current <link> tags.
Definition: OutputPage.php:436
OutputPage\forceHideNewSectionLink
forceHideNewSectionLink()
Forcibly hide the new section link?
Definition: OutputPage.php:1167
Html\closeElement
static closeElement( $element)
Returns "</$element>".
Definition: Html.php:318
Xml\encodeJsCall
static encodeJsCall( $name, $args, $pretty=false)
Create a call to a JavaScript function.
Definition: Xml.php:690
OutputPage\$rlClientContext
ResourceLoaderContext $rlClientContext
Definition: OutputPage.php:178
Html\isXmlMimeType
static isXmlMimeType( $mimetype)
Determines if the given MIME type is xml.
Definition: Html.php:1006
OutputPage\setArticleRelated
setArticleRelated( $newVal)
Set whether this page is related an article on the wiki Setting false will cause the change of "artic...
Definition: OutputPage.php:1289
OutputPage\addElement
addElement( $element, array $attribs=[], $contents='')
Shortcut for adding an Html::element via addHTML.
Definition: OutputPage.php:1627
OutputPage\addParserOutputContent
addParserOutputContent(ParserOutput $parserOutput, $poOptions=[])
Add the HTML and enhancements for it (like ResourceLoader modules) associated with a ParserOutput obj...
Definition: OutputPage.php:1986
Config
Interface for configuration instances.
Definition: Config.php:30
ParserOutput\getExtraCSPDefaultSrcs
getExtraCSPDefaultSrcs()
Get extra Content-Security-Policy 'default-src' directives.
Definition: ParserOutput.php:702
MediaWiki\Linker\LinkTarget\getNamespace
getNamespace()
Get the namespace index.
OutputPage\userCanEditOrCreate
userCanEditOrCreate(User $user, LinkTarget $title)
Definition: OutputPage.php:3484
wfParseUrl
wfParseUrl( $url)
parse_url() work-alike, but non-broken.
Definition: GlobalFunctions.php:797
PROTO_RELATIVE
const PROTO_RELATIVE
Definition: Defines.php:205
File
Implements some public methods and some protected utility functions which are required by multiple ch...
Definition: File.php:63
ParserOutput\getLimitReportJSData
getLimitReportJSData()
Definition: ParserOutput.php:689
Html\linkedScript
static linkedScript( $url, $nonce=null)
Output a "<script>" tag linking to the given URL, e.g., "<script src=foo.js></script>".
Definition: Html.php:599
OutputPage\feedLink
feedLink( $type, $url, $text)
Generate a "<link rel/>" for a feed.
Definition: OutputPage.php:3775
wfDeprecatedMsg
wfDeprecatedMsg( $msg, $version=false, $component=false, $callerOffset=2)
Log a deprecation warning with arbitrary message text.
Definition: GlobalFunctions.php:1066
OutputPage\addWikiTextAsInterface
addWikiTextAsInterface( $text, $linestart=true, Title $title=null)
Convert wikitext in the user interface language to HTML and add it to the buffer.
Definition: OutputPage.php:1783
MWException
MediaWiki exception.
Definition: MWException.php:29
OutputPage\considerCacheSettingsFinal
considerCacheSettingsFinal()
Set the expectation that cache control will not change after this point.
Definition: OutputPage.php:2210
OutputPage\getModules
getModules( $filter=false, $position=null, $param='mModules', $type=ResourceLoaderModule::TYPE_COMBINED)
Get the list of modules to include on this page.
Definition: OutputPage.php:545
OutputPage\addStyle
addStyle( $style, $media='', $condition='', $dir='')
Add a local or specified stylesheet, with the given media options.
Definition: OutputPage.php:3793
OutputPage\sendCacheControl
sendCacheControl()
Send cache control HTTP headers.
Definition: OutputPage.php:2428
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
Definition: GlobalFunctions.php:1034
OutputPage\$mCdnMaxageLimit
int $mCdnMaxageLimit
Upper limit on mCdnMaxage.
Definition: OutputPage.php:249
OutputPage\getLastSeenUserTalkRevId
getLastSeenUserTalkRevId()
Get the revision ID for the last user talk page revision viewed by the talk page owner.
Definition: OutputPage.php:3411
OutputPage\$mTemplateIds
array $mTemplateIds
Definition: OutputPage.php:187
wfScript
wfScript( $script='index')
Get the path to a specified script file, respecting file extensions; this is a wrapper around $wgScri...
Definition: GlobalFunctions.php:2534
Wikimedia\Rdbms\IResultWrapper
Result wrapper for grabbing data queried from an IDatabase object.
Definition: IResultWrapper.php:24
ResourceLoaderWikiModule\preloadTitleInfo
static preloadTitleInfo(ResourceLoaderContext $context, IDatabase $db, array $moduleNames)
Definition: ResourceLoaderWikiModule.php:464
OutputPage\styleLink
styleLink( $style, array $options)
Generate <link> tags for stylesheets.
Definition: OutputPage.php:3901
OutputPage\$mEnableTOC
bool $mEnableTOC
Whether parser output contains a table of contents.
Definition: OutputPage.php:310
Config\get
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
OutputPage\$mSubtitle
array $mSubtitle
Contains the page subtitle.
Definition: OutputPage.php:107
OutputPage\setFileVersion
setFileVersion( $file)
Set the displayed file version.
Definition: OutputPage.php:1730
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:2467
OutputPage\getLinkHeader
getLinkHeader()
Return a Link: header.
Definition: OutputPage.php:2304
OutputPage\getResourceLoader
getResourceLoader()
Get a ResourceLoader object associated with this OutputPage.
Definition: OutputPage.php:3162
OutputPage\isTOCEnabled
isTOCEnabled()
Whether the output has a table of contents.
Definition: OutputPage.php:4127
ContextSource
The simplest way of implementing IContextSource is to hold a RequestContext as a member variable and ...
Definition: ContextSource.php:32
ContextSource\getWikiPage
getWikiPage()
Get the WikiPage object.
Definition: ContextSource.php:116
OutputPage\setFeedAppendQuery
setFeedAppendQuery( $val)
Add default feeds to the page header This is mainly kept for backward compatibility,...
Definition: OutputPage.php:1210
OutputPage\setDisplayTitle
setDisplayTitle( $html)
Same as page title but only contains name of the page, not any other text.
Definition: OutputPage.php:1010
$modules
$modules
Definition: HTMLFormElement.php:15
OutputPage\isDisabled
isDisabled()
Return whether the output will be completely disabled.
Definition: OutputPage.php:1149
OutputPage\setRevisionId
setRevisionId( $revid)
Set the revision ID which will be seen by the wiki text parser for things such as embedded {{REVISION...
Definition: OutputPage.php:1679
OutputPage\$mCategories
string[][] $mCategories
Definition: OutputPage.php:125
OutputPage\setArticleFlag
setArticleFlag( $newVal)
Set whether the displayed content is related to the source of the corresponding article on the wiki S...
Definition: OutputPage.php:1266
OutputPage\disallowUserJs
disallowUserJs()
Do not allow scripts which can be modified by wiki users to load on this page; only allow scripts bun...
Definition: OutputPage.php:1554
ContextSource\getSkin
getSkin()
Definition: ContextSource.php:160
OutputPage\setSubtitle
setSubtitle( $str)
Replace the subtitle with $str.
Definition: OutputPage.php:1061
$args
if( $line===false) $args
Definition: mcc.php:124
OutputPage\$mInlineStyles
string $mInlineStyles
Inline CSS styles.
Definition: OutputPage.php:145
wfCgiToArray
wfCgiToArray( $query)
This is the logical opposite of wfArrayToCgi(): it accepts a query string as its argument and returns...
Definition: GlobalFunctions.php:396
OutputPage\getVaryHeader
getVaryHeader()
Return a Vary: header on which to vary caches.
Definition: OutputPage.php:2278
OutputPage\addModules
addModules( $modules)
Load one or more ResourceLoader modules on this page.
Definition: OutputPage.php:559
OutputPage\showLagWarning
showLagWarning( $lag)
Show a warning about replica DB lag.
Definition: OutputPage.php:2856
$title
$title
Definition: testCompression.php:38
OutputPage\getCacheVaryCookies
getCacheVaryCookies()
Get the list of cookie names that will influence the cache.
Definition: OutputPage.php:2219
OutputPage\setCopyrightUrl
setCopyrightUrl( $url)
Set the copyright URL to send with the output.
Definition: OutputPage.php:385
OutputPage\$mFollowPolicy
$mFollowPolicy
Definition: OutputPage.php:278
OutputPage\$rlClient
ResourceLoaderClientHtml $rlClient
Definition: OutputPage.php:175
OutputPage\addHtmlClasses
addHtmlClasses( $classes)
Add a class to the <html> element.
Definition: OutputPage.php:643
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
PROTO_CANONICAL
const PROTO_CANONICAL
Definition: Defines.php:207
ResourceLoader\makeLoaderQuery
static makeLoaderQuery(array $modules, $lang, $skin, $user=null, $version=null, $debug=ResourceLoaderContext::DEBUG_OFF, $only=null, $printable=false, $handheld=false, array $extraQuery=[])
Build a query array (array representation of query string) for load.php.
Definition: ResourceLoader.php:1847
OutputPage\getIndexPolicy
getIndexPolicy()
Get the current index policy for the page as a string.
Definition: OutputPage.php:907
OutputPage\addBodyClasses
addBodyClasses( $classes)
Add a class to the <body> element.
Definition: OutputPage.php:698
ParserOutput\getIndicators
getIndicators()
Definition: ParserOutput.php:590
ResourceLoaderModule\getOrigin
getOrigin()
Get this module's origin.
Definition: ResourceLoaderModule.php:148
wfDebug
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:915
ContextSource\setContext
setContext(IContextSource $context)
Definition: ContextSource.php:62
OutputPage\isArticle
isArticle()
Return whether the content displayed page is related to the source of the corresponding article on th...
Definition: OutputPage.php:1279
OutputPage
This is one of the Core classes and should be read at least once by any new developers.
Definition: OutputPage.php:47
ParserOutput\getLanguageLinks
& getLanguageLinks()
Definition: ParserOutput.php:570
OutputPage\showErrorPage
showErrorPage( $title, $msg, $params=[])
Output a standard error page.
Definition: OutputPage.php:2691
OutputPage\addParserOutputText
addParserOutputText(ParserOutput $parserOutput, $poOptions=[])
Add the HTML associated with a ParserOutput object, without any metadata.
Definition: OutputPage.php:2002
OutputPage\getCSPNonce
getCSPNonce()
Get (and set if not yet set) the CSP nonce.
Definition: OutputPage.php:4176
OutputPage\$mParserOptions
ParserOptions $mParserOptions
lazy initialised, use parserOptions()
Definition: OutputPage.php:218
OutputPage\$mContainsNewMagic
int $mContainsNewMagic
Definition: OutputPage.php:212
JavaScriptContent
Content for JavaScript pages.
Definition: JavaScriptContent.php:36
OutputPage\$limitReportJSData
array $limitReportJSData
Profiling data.
Definition: OutputPage.php:318
OutputPage\addInlineScript
addInlineScript( $script)
Add a self-contained script tag with the given contents Internal use only.
Definition: OutputPage.php:489
ParserOutput\getTemplateIds
& getTemplateIds()
Definition: ParserOutput.php:618
OutputPage\getArticleBodyOnly
getArticleBodyOnly()
Return whether the output will contain only the body of the article.
Definition: OutputPage.php:718
OutputPage\getPreventClickjacking
getPreventClickjacking()
Get the prevent-clickjacking flag.
Definition: OutputPage.php:2361
ParserOutput\getTOCHTML
getTOCHTML()
Definition: ParserOutput.php:674
OutputPage\$mModules
array $mModules
Definition: OutputPage.php:166
OutputPage\addWikiTextAsContent
addWikiTextAsContent( $text, $linestart=true, Title $title=null)
Convert wikitext in the page content language to HTML and add it to the buffer.
Definition: OutputPage.php:1833
ParserOutput\getExtraCSPScriptSrcs
getExtraCSPScriptSrcs()
Get extra Content-Security-Policy 'script-src' directives.
Definition: ParserOutput.php:711
OutputPage\getCanonicalUrl
getCanonicalUrl()
Returns the URL to be used for the <link rel=canonical>> if one is set.
Definition: OutputPage.php:456
OutputPage\wrapWikiMsg
wrapWikiMsg( $wrap,... $msgSpecs)
This function takes a number of message/argument specifications, wraps them in some overall structure...
Definition: OutputPage.php:4107
OutputPage\setStatusCode
setStatusCode( $statusCode)
Set the HTTP status code to send with the output.
Definition: OutputPage.php:394
PROTO_CURRENT
const PROTO_CURRENT
Definition: Defines.php:206
OutputPage\$mRedirect
string $mRedirect
Definition: OutputPage.php:110
Html\inlineStyle
static inlineStyle( $contents, $media='all', $attribs=[])
Output a "<style>" tag with the given contents for the given media type (if any).
Definition: Html.php:622
ContextSource\msg
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Definition: ContextSource.php:195
OutputPage\$mIsArticle
bool $mIsArticle
Is the displayed content related to the source of the corresponding wiki article.
Definition: OutputPage.php:89
OutputPage\haveCacheVaryCookies
haveCacheVaryCookies()
Check if the request has a cache-varying cookie header If it does, it's very important that we don't ...
Definition: OutputPage.php:2240
OutputPage\getPageTitle
getPageTitle()
Return the "page title", i.e.
Definition: OutputPage.php:999
OutputPage\disable
disable()
Disable output completely, i.e.
Definition: OutputPage.php:1140
OutputPage\setIndexPolicy
setIndexPolicy( $policy)
Set the index policy for the page, but leave the follow policy un- touched.
Definition: OutputPage.php:895
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:652
OutputPage\$mResourceLoader
ResourceLoader $mResourceLoader
Definition: OutputPage.php:172
ParserOutput\getNewSection
getNewSection()
Definition: ParserOutput.php:804
$content
$content
Definition: router.php:76
Skin\getPageClasses
getPageClasses( $title)
TODO: document.
Definition: Skin.php:509
OutputPage\addCategoryLinks
addCategoryLinks(array $categories)
Add an array of categories, with names in the keys.
Definition: OutputPage.php:1361
OutputPage\setRevisionTimestamp
setRevisionTimestamp( $timestamp)
Set the timestamp of the revision which will be displayed.
Definition: OutputPage.php:1710
$s
foreach( $mmfl['setupFiles'] as $fileName) if( $queue) if(empty( $mmfl['quiet'])) $s
Definition: mergeMessageFileList.php:188
OutputPage\getHeadItemsArray
getHeadItemsArray()
Get an array of head items.
Definition: OutputPage.php:652
OutputPage\$CSP
ContentSecurityPolicy $CSP
Definition: OutputPage.php:334
OutputPage\addReturnTo
addReturnTo( $title, array $query=[], $text=null, $options=[])
Add a "return to" link pointing to a specified title.
Definition: OutputPage.php:2889
OutputPage\buildExemptModules
buildExemptModules()
Build exempt modules and legacy non-ResourceLoader styles.
Definition: OutputPage.php:3827
OutputPage\$copyrightUrl
string null $copyrightUrl
The URL to send in a <link> element with rel=license.
Definition: OutputPage.php:315
OutputPage\getProperty
getProperty( $name)
Get an additional output property.
Definition: OutputPage.php:740
ParserOptions\newFromContext
static newFromContext(IContextSource $context)
Get a ParserOptions object from a IContextSource object.
Definition: ParserOptions.php:1156
OutputPage\addWikiMsg
addWikiMsg(... $args)
Add a wikitext-formatted message to the output.
Definition: OutputPage.php:4064
Html\inlineScript
static inlineScript( $contents, $nonce=null)
Output an HTML script tag with the given contents.
Definition: Html.php:575
$header
$header
Definition: updateCredits.php:37
OutputPage\addHelpLink
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Definition: OutputPage.php:1522
OutputPage\formatPermissionsErrorMessage
formatPermissionsErrorMessage(array $errors, $action=null)
Format a list of error messages.
Definition: OutputPage.php:2817
ParserOutput\getOutputHooks
getOutputHooks()
Definition: ParserOutput.php:662
OutputPage\setTarget
setTarget( $target)
Sets ResourceLoader target for load.php links.
Definition: OutputPage.php:601
OutputPage\getRobotPolicy
getRobotPolicy()
Get the current robot policy for the page as a string in the form <index policy>,<follow policy>.
Definition: OutputPage.php:885
ParserOutput\getHideNewSection
getHideNewSection()
Definition: ParserOutput.php:800
MediaWiki\Session\SessionManager
This serves as the entry point to the MediaWiki session handling system.
Definition: SessionManager.php:53
OutputPage\$contentOverrideCallbacks
callable[] $contentOverrideCallbacks
Definition: OutputPage.php:324
OutputPage\setHTMLTitle
setHTMLTitle( $name)
"HTML title" means the contents of "<title>".
Definition: OutputPage.php:939
DerivativeResourceLoaderContext
A mutable version of ResourceLoaderContext.
Definition: DerivativeResourceLoaderContext.php:33
MediaWiki\Linker\LinkTarget\getDBkey
getDBkey()
Get the main part with underscores.
OutputPage\$mMetatags
string[][] $mMetatags
Should be private.
Definition: OutputPage.php:51
OutputPage\setLanguageLinks
setLanguageLinks(array $newLinkArray)
Reset the language links and add new language links.
Definition: OutputPage.php:1343
OutputPage\setupOOUI
static setupOOUI( $skinName='default', $dir='ltr')
Helper function to setup the PHP implementation of OOUI to use in this request.
Definition: OutputPage.php:4138
OutputPage\$rlExemptStyleModules
array $rlExemptStyleModules
Definition: OutputPage.php:181
OutputPage\$mAdditionalHtmlClasses
array $mAdditionalHtmlClasses
Additional <html> classes; This should be rarely modified; prefer mAdditionalBodyClasses.
Definition: OutputPage.php:157
OutputPage\$mProperties
$mProperties
Additional key => value data.
Definition: OutputPage.php:300
OutputPage\prependHTML
prependHTML( $text)
Prepend $text to the body HTML.
Definition: OutputPage.php:1605
ParserOutput\getNoGallery
getNoGallery()
Definition: ParserOutput.php:638
OutputPage\getHTMLTitle
getHTMLTitle()
Return the "HTML title", i.e.
Definition: OutputPage.php:952
OutputPage\$cacheIsFinal
bool $cacheIsFinal
See OutputPage::couldBePublicCached.
Definition: OutputPage.php:74
OutputPage\clearSubtitle
clearSubtitle()
Clear the subtitles.
Definition: OutputPage.php:1109
OutputPage\warnModuleTargetFilter
warnModuleTargetFilter( $moduleName)
Definition: OutputPage.php:521
OutputPage\$mCdnMaxage
int $mCdnMaxage
Cache stuff.
Definition: OutputPage.php:247
OutputPage\enableOOUI
enableOOUI()
Add ResourceLoader module styles for OOUI and set up the PHP implementation of it for use with MediaW...
Definition: OutputPage.php:4153
OutputPage\$cacheVaryCookies
static array $cacheVaryCookies
A cache of the names of the cookies that will influence the cache.
Definition: OutputPage.php:339
OutputPage\$mScripts
$mScripts
Used for JavaScript (predates ResourceLoader)
Definition: OutputPage.php:142
OutputPage\$mAllowedModules
array $mAllowedModules
What level of 'untrustworthiness' is allowed in CSS/JS modules loaded on this page?
Definition: OutputPage.php:202
getSkinThemeMap
static getSkinThemeMap()
Return a map of skin names (in lowercase) to OOUI theme names, defining which theme a given skin shou...
Definition: ResourceLoaderOOUIModule.php:76
OutputPage\$mPrintable
bool $mPrintable
We have to set isPrintable().
Definition: OutputPage.php:101
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:57
OutputPage\$mLanguageLinks
array $mLanguageLinks
Array of Interwiki Prefixed (non DB key) Titles (e.g.
Definition: OutputPage.php:134
OutputPage\setCategoryLinks
setCategoryLinks(array $categories)
Reset the category links (but not the category list) and add $categories.
Definition: OutputPage.php:1447
OutputPage\setFollowPolicy
setFollowPolicy( $policy)
Set the follow policy for the page, but leave the index policy un- touched.
Definition: OutputPage.php:917
Content
Base interface for content objects.
Definition: Content.php:35
OutputPage\setPageTitle
setPageTitle( $name)
"Page title" means the contents of <h1>.
Definition: OutputPage.php:977
OutputPage\getRlClient
getRlClient()
Call this to freeze the module queue and JS config and create a formatter.
Definition: OutputPage.php:2988
ResourceLoaderClientHtml\makeLoad
static makeLoad(ResourceLoaderContext $mainContext, array $modules, $only, array $extraQuery=[], $nonce=null)
Explicitly load or embed modules on a page.
Definition: ResourceLoaderClientHtml.php:388
OutputPage\$mFileVersion
array $mFileVersion
Definition: OutputPage.php:265
OutputPage\checkLastModified
checkLastModified( $timestamp)
checkLastModified tells the client to use the client-cached page if possible.
Definition: OutputPage.php:755
OutputPage\$mNoGallery
bool $mNoGallery
Comes from the parser.
Definition: OutputPage.php:244
OutputPage\$mHeadItems
array $mHeadItems
Array of elements in "<head>".
Definition: OutputPage.php:160
OutputPage\$mRevisionTimestamp
string $mRevisionTimestamp
Definition: OutputPage.php:262
OutputPage\$displayTitle
string $displayTitle
The displayed title of the page.
Definition: OutputPage.php:71
ParserOutput\getFileSearchOptions
& getFileSearchOptions()
Definition: ParserOutput.php:626
Title
Represents a title within MediaWiki.
Definition: Title.php:46
ResourceLoaderModule
Abstraction for ResourceLoader modules, with name registration and maxage functionality.
Definition: ResourceLoaderModule.php:39
OutputPage\setCdnMaxage
setCdnMaxage( $maxage)
Set the value of the "s-maxage" part of the "Cache-control" HTTP header.
Definition: OutputPage.php:2125
Parser\stripOuterParagraph
static stripOuterParagraph( $html)
Strip outer.
Definition: Parser.php:6288
OutputPage\getAllowedModules
getAllowedModules( $type)
Show what level of JavaScript / CSS untrustworthiness is allowed on this page.
Definition: OutputPage.php:1579
ResourceLoader
ResourceLoader is a loading system for JavaScript and CSS resources.
Definition: ResourceLoader.php:58
OutputPage\addVaryHeader
addVaryHeader( $header, array $option=null)
Add an HTTP header that will influence on the cache.
Definition: OutputPage.php:2261
ContentHandler\getContentText
static getContentText(Content $content=null)
Convenience function for getting flat text from a Content object.
Definition: ContentHandler.php:91
OutputPage\setProperty
setProperty( $name, $value)
Set an additional output property.
Definition: OutputPage.php:729
OutputPage\isPrintable
isPrintable()
Return whether the page is "printable".
Definition: OutputPage.php:1133
OutputPage\setSyndicated
setSyndicated( $show=true)
Add or remove feed links in the page header This is mainly kept for backward compatibility,...
Definition: OutputPage.php:1179
OutputPage\wrapWikiTextAsInterface
wrapWikiTextAsInterface( $wrapperClass, $text)
Convert wikitext in the user interface language to HTML and add it to the buffer with a <div class="$...
Definition: OutputPage.php:1808
OutputPage\$mTarget
string null $mTarget
ResourceLoader target for load.php links.
Definition: OutputPage.php:305
OutputPage\addInlineStyle
addInlineStyle( $style_css, $flip='noflip')
Adds inline CSS styles Internal use only.
Definition: OutputPage.php:3814
ResourceLoaderClientHtml\setModules
setModules(array $modules)
Ensure one or more modules are loaded.
Definition: ResourceLoaderClientHtml.php:88
OutputPage\userCanPreview
userCanPreview()
To make it harder for someone to slip a user a fake JavaScript or CSS preview, a random token is asso...
Definition: OutputPage.php:3450
Html\linkedStyle
static linkedStyle( $url, $media='all')
Output a "<link rel=stylesheet>" linking to the given URL for the given media type (if any).
Definition: Html.php:651
OutputPage\$mPageTitle
string $mPageTitle
The contents of.
Definition: OutputPage.php:62
ResourceLoader\inDebugMode
static inDebugMode()
Determine whether debug mode is on.
Definition: ResourceLoader.php:1762
OutputPage\setRedirectedFrom
setRedirectedFrom( $t)
Set $mRedirectedFrom, the Title of the page which redirected us to the current page.
Definition: OutputPage.php:961
ResourceLoaderClientHtml\setModuleStyles
setModuleStyles(array $modules)
Ensure the styles of one or more modules are loaded.
Definition: ResourceLoaderClientHtml.php:97
OutputPage\filterModules
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:501
WebRequest\getRequestId
static getRequestId()
Get the current request ID.
Definition: WebRequest.php:330
OutputPage\redirect
redirect( $url, $responsecode='302')
Redirect to $url rather than displaying the normal page.
Definition: OutputPage.php:362
OutputPage\getUnprefixedDisplayTitle
getUnprefixedDisplayTitle()
Returns page display title without namespace prefix if possible.
Definition: OutputPage.php:1037
IContextSource\getConfig
getConfig()
Get the site configuration.
OutputPage\$mJsConfigVars
array $mJsConfigVars
Definition: OutputPage.php:184
$path
$path
Definition: NoLocalSettings.php:25
ParserOutput\getCategories
& getCategories()
Definition: ParserOutput.php:582
OutputPage\setPrintable
setPrintable()
Set the page as printable, i.e.
Definition: OutputPage.php:1124
OutputPage\getHeadLinksArray
getHeadLinksArray()
Definition: OutputPage.php:3497
OutputPage\adaptCdnTTL
adaptCdnTTL( $mtime, $minTTL=0, $maxTTL=0)
Get TTL in [$minTTL,$maxTTL] and pass it to lowerCdnMaxage()
Definition: OutputPage.php:2155
OutputPage\getCdnCacheEpoch
getCdnCacheEpoch( $reqTime, $maxAge)
Definition: OutputPage.php:843
OutputPage\allowClickjacking
allowClickjacking()
Turn off frame-breaking.
Definition: OutputPage.php:2351
LanguageCode\bcp47
static bcp47( $code)
Get the normalised IETF language tag See unit test for examples.
Definition: LanguageCode.php:175
OutputPage\loadSkinModules
loadSkinModules( $sk)
Transfer styles and JavaScript modules from skin.
Definition: OutputPage.php:2505
OutputPage\showFatalError
showFatalError( $message)
Output an error page.
Definition: OutputPage.php:2875
Html\openElement
static openElement( $element, $attribs=[])
Identical to rawElement(), but has no third parameter and omits the end tag (and the self-closing '/'...
Definition: Html.php:254
Html\rawElement
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:212
OutputPage\getHTML
getHTML()
Get the body HTML.
Definition: OutputPage.php:1643
Message
The Message class deals with fetching and processing of interface message into a variety of formats.
Definition: Message.php:161
OutputPage\$mRevisionId
int null $mRevisionId
To include the variable {{REVISIONID}}.
Definition: OutputPage.php:259
OutputPage\parseInlineAsInterface
parseInlineAsInterface( $text, $linestart=true)
Parse wikitext in the user interface language, strip paragraph wrapper, and return the HTML.
Definition: OutputPage.php:2083
OutputPage\$mLinkHeader
$mLinkHeader
Link: header contents.
Definition: OutputPage.php:329
NS_CATEGORY
const NS_CATEGORY
Definition: Defines.php:78
$keys
$keys
Definition: testCompression.php:72
OutputPage\$styles
array $styles
An array of stylesheet filenames (relative from skins path), with options for CSS media,...
Definition: OutputPage.php:275
OutputPage\isRevisionCurrent
isRevisionCurrent()
Whether the revision displayed is the latest revision of the page.
Definition: OutputPage.php:1699
Sanitizer\normalizeCharReferences
static normalizeCharReferences( $text)
Ensure that any entities and character references are legal for XML and XHTML specifically.
Definition: Sanitizer.php:1124
MWDebug\addModules
static addModules(OutputPage $out)
Add ResourceLoader modules to the OutputPage object if debugging is enabled.
Definition: MWDebug.php:125
CacheTime\isCacheable
isCacheable()
Definition: CacheTime.php:164
IContextSource\getRequest
getRequest()
OutputPage\showNewSectionLink
showNewSectionLink()
Show an "add new section" link?
Definition: OutputPage.php:1158
OutputPage\$mPageLinkTitle
string $mPageLinkTitle
Used by skin template.
Definition: OutputPage.php:151
ParserOutput\getText
getText( $options=[])
Get the output HTML.
Definition: ParserOutput.php:350
OutputPage\$mCanonicalUrl
string bool $mCanonicalUrl
Definition: OutputPage.php:57
OutputPage\makeResourceLoaderLink
makeResourceLoaderLink( $modules, $only, array $extraQuery=[])
Explicily load or embed modules on a page.
Definition: OutputPage.php:3178
OutputPage\addWikiTextTitleInternal
addWikiTextTitleInternal( $text, Title $title, $linestart, $interface, $wrapperClass=null)
Add wikitext with a custom Title object.
Definition: OutputPage.php:1857
OutputPage\getIndicators
getIndicators()
Get the indicators associated with this page.
Definition: OutputPage.php:1510
$t
$t
Definition: testCompression.php:74
$wgRequest
if(! $wgDBerrorLogTZ) $wgRequest
Definition: Setup.php:651
Html\element
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:234
Skin\getSkinName
getSkinName()
Definition: Skin.php:185
MediaWiki\Linker\LinkTarget
Definition: LinkTarget.php:26
OutputPage\addJsConfigVars
addJsConfigVars( $keys, $value=null)
Add one or more variables to be set in mw.config in JavaScript.
Definition: OutputPage.php:3244
OutputPage\$mPreventClickjacking
bool $mPreventClickjacking
Controls if anti-clickjacking / frame-breaking headers will be sent.
Definition: OutputPage.php:256
Skin
The main skin class which provides methods and properties for all other skins.
Definition: Skin.php:42
OutputPage\getFollowPolicy
getFollowPolicy()
Get the current follow policy for the page as a string.
Definition: OutputPage.php:929
OutputPage\getCategories
getCategories( $type='all')
Get the list of category names this page belongs to.
Definition: OutputPage.php:1473
OutputPage\getJsConfigVars
getJsConfigVars()
Get the javascript config vars to include on this page.
Definition: OutputPage.php:3234
OutputPage\setCopyright
setCopyright( $hasCopyright)
Set whether the standard copyright should be shown for the current page.
Definition: OutputPage.php:1310
OutputPage\getTemplateIds
getTemplateIds()
Get the templates used on this page.
Definition: OutputPage.php:1753
$IP
$IP
Definition: WebStart.php:49
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:66
OutputPage\$mIsArticleRelated
bool $mIsArticleRelated
Stores "article flag" toggle.
Definition: OutputPage.php:92
Skin\isResponsive
isResponsive()
Indicates if this skin is responsive.
Definition: Skin.php:198
OutputPage\isSyndicated
isSyndicated()
Should we output feed links for this page?
Definition: OutputPage.php:1238
OutputPage\$mFeedLinksAppendQuery
$mFeedLinksAppendQuery
Definition: OutputPage.php:195
OutputPage\getFileSearchOptions
getFileSearchOptions()
Get the files used on this page.
Definition: OutputPage.php:1763
OutputPage\$mFeedLinks
$mFeedLinks
Handles the Atom / RSS links.
Definition: OutputPage.php:225
OutputPage\$mDoNothing
bool $mDoNothing
Whether output is disabled.
Definition: OutputPage.php:207
OutputPage\$mArticleBodyOnly
bool $mArticleBodyOnly
Flag if output should only contain the body of the article.
Definition: OutputPage.php:231
OutputPage\$mHasCopyright
bool $mHasCopyright
Is the content subject to copyright.
Definition: OutputPage.php:95
OutputPage\addParserOutput
addParserOutput(ParserOutput $parserOutput, $poOptions=[])
Add everything from a ParserOutput object.
Definition: OutputPage.php:2014
OutputPage\$mAdditionalBodyClasses
array $mAdditionalBodyClasses
Additional <body> classes; there are also <body> classes from other sources.
Definition: OutputPage.php:163
ContentSecurityPolicy
Definition: ContentSecurityPolicy.php:32
OutputPage\prepareErrorPage
prepareErrorPage( $pageTitle, $htmlTitle=false)
Prepare this object to display an error page; disable caching and indexing, clear the current text an...
Definition: OutputPage.php:2666
OutputPage\addTemplate
addTemplate(&$template)
Add the output of a QuickTemplate to the output buffer.
Definition: OutputPage.php:2024
OutputPage\$mIndicators
string[] $mIndicators
Definition: OutputPage.php:131
OutputPage\getFeedAppendQuery
getFeedAppendQuery()
Will currently always return null.
Definition: OutputPage.php:1255
OutputPage\lowerCdnMaxage
lowerCdnMaxage( $maxage)
Set the value of the "s-maxage" part of the "Cache-control" HTTP header to $maxage if that is lower t...
Definition: OutputPage.php:2138
OutputPage\$mHTMLtitle
string $mHTMLtitle
Stores contents of "<title>" tag.
Definition: OutputPage.php:83
ParserOutput\getExtraCSPStyleSrcs
getExtraCSPStyleSrcs()
Get extra Content-Security-Policy 'style-src' directives.
Definition: ParserOutput.php:720
wfExpandUrl
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
Definition: GlobalFunctions.php:495
OutputPage\addFeedLink
addFeedLink( $format, $href)
Add a feed link to the page header.
Definition: OutputPage.php:1228
ParserOutput\preventClickjacking
preventClickjacking( $flag=null)
Get or set the prevent-clickjacking flag.
Definition: ParserOutput.php:1353
OutputPage\transformResourcePath
static transformResourcePath(Config $config, $path)
Transform path to web-accessible static resource.
Definition: OutputPage.php:3958
OutputPage\parseAsContent
parseAsContent( $text, $linestart=true)
Parse wikitext in the page content language and return the HTML.
Definition: OutputPage.php:2039
OutputPage\getAdvertisedFeedTypes
getAdvertisedFeedTypes()
Return effective list of advertised feed types.
Definition: OutputPage.php:1193
OutputPage\setRobotPolicy
setRobotPolicy( $policy)
Set the robot policy for the page: http://www.robotstxt.org/meta.html
Definition: OutputPage.php:868
wfArrayToCgi
wfArrayToCgi( $array1, $array2=null, $prefix='')
This function takes one or two arrays as input, and returns a CGI-style string, e....
Definition: GlobalFunctions.php:351
OutputPage\transformFilePath
static transformFilePath( $remotePathPrefix, $localPath, $file)
Utility method for transformResourceFilePath().
Definition: OutputPage.php:4000
OutputPage\headElement
headElement(Skin $sk, $includeStyle=true)
Definition: OutputPage.php:3064
$type
$type
Definition: testCompression.php:52
OutputPage\$mStatusCode
int $mStatusCode
Definition: OutputPage.php:113