MediaWiki  1.29.1
OutputPage.php
Go to the documentation of this file.
1 <?php
26 use WrappedString\WrappedString;
27 use WrappedString\WrappedStringList;
28 
44 class OutputPage extends ContextSource {
46  protected $mMetatags = [];
47 
49  protected $mLinktags = [];
50 
52  protected $mCanonicalUrl = false;
53 
58  protected $mExtStyles = [];
59 
63  public $mPagetitle = '';
64 
69  public $mBodytext = '';
70 
72  private $mHTMLtitle = '';
73 
78  private $mIsarticle = false;
79 
81  private $mIsArticleRelated = true;
82 
87  private $mPrintable = false;
88 
93  private $mSubtitle = [];
94 
96  public $mRedirect = '';
97 
99  protected $mStatusCode;
100 
105  protected $mLastModified = '';
106 
108  protected $mCategoryLinks = [];
109 
111  protected $mCategories = [
112  'hidden' => [],
113  'normal' => [],
114  ];
115 
117  protected $mIndicators = [];
118 
120  private $mLanguageLinks = [];
121 
128  private $mScripts = '';
129 
131  protected $mInlineStyles = '';
132 
137  public $mPageLinkTitle = '';
138 
140  protected $mHeadItems = [];
141 
143  protected $mModules = [];
144 
146  protected $mModuleScripts = [];
147 
149  protected $mModuleStyles = [];
150 
152  protected $mResourceLoader;
153 
155  private $rlClient;
156 
159 
162 
165 
167  protected $mJsConfigVars = [];
168 
170  protected $mTemplateIds = [];
171 
173  protected $mImageTimeKeys = [];
174 
176  public $mRedirectCode = '';
177 
178  protected $mFeedLinksAppendQuery = null;
179 
185  protected $mAllowedModules = [
187  ];
188 
190  protected $mDoNothing = false;
191 
192  // Parser related.
193 
195  protected $mContainsNewMagic = 0;
196 
201  protected $mParserOptions = null;
202 
208  private $mFeedLinks = [];
209 
210  // Gwicke work on squid caching? Roughly from 2003.
211  protected $mEnableClientCache = true;
212 
214  private $mArticleBodyOnly = false;
215 
217  protected $mNewSectionLink = false;
218 
220  protected $mHideNewSectionLink = false;
221 
227  public $mNoGallery = false;
228 
230  private $mPageTitleActionText = '';
231 
233  protected $mCdnMaxage = 0;
235  protected $mCdnMaxageLimit = INF;
236 
242  protected $mPreventClickjacking = true;
243 
245  private $mRevisionId = null;
246 
248  private $mRevisionTimestamp = null;
249 
251  protected $mFileVersion = null;
252 
261  protected $styles = [];
262 
263  private $mIndexPolicy = 'index';
264  private $mFollowPolicy = 'follow';
265  private $mVaryHeader = [
266  'Accept-Encoding' => [ 'match=gzip' ],
267  ];
268 
275  private $mRedirectedFrom = null;
276 
280  private $mProperties = [];
281 
285  private $mTarget = null;
286 
290  private $mEnableTOC = true;
291 
295  private $mEnableSectionEditLinks = true;
296 
300  private $copyrightUrl;
301 
303  private $limitReportJSData = [];
304 
308  private $mLinkHeader = [];
309 
316  function __construct( IContextSource $context = null ) {
317  if ( $context === null ) {
318  # Extensions should use `new RequestContext` instead of `new OutputPage` now.
319  wfDeprecated( __METHOD__, '1.18' );
320  } else {
321  $this->setContext( $context );
322  }
323  }
324 
331  public function redirect( $url, $responsecode = '302' ) {
332  # Strip newlines as a paranoia check for header injection in PHP<5.1.2
333  $this->mRedirect = str_replace( "\n", '', $url );
334  $this->mRedirectCode = $responsecode;
335  }
336 
342  public function getRedirect() {
343  return $this->mRedirect;
344  }
345 
354  public function setCopyrightUrl( $url ) {
355  $this->copyrightUrl = $url;
356  }
357 
363  public function setStatusCode( $statusCode ) {
364  $this->mStatusCode = $statusCode;
365  }
366 
374  function addMeta( $name, $val ) {
375  array_push( $this->mMetatags, [ $name, $val ] );
376  }
377 
384  public function getMetaTags() {
385  return $this->mMetatags;
386  }
387 
395  function addLink( array $linkarr ) {
396  array_push( $this->mLinktags, $linkarr );
397  }
398 
405  public function getLinkTags() {
406  return $this->mLinktags;
407  }
408 
416  function addMetadataLink( array $linkarr ) {
417  $linkarr['rel'] = $this->getMetadataAttribute();
418  $this->addLink( $linkarr );
419  }
420 
426  function setCanonicalUrl( $url ) {
427  $this->mCanonicalUrl = $url;
428  }
429 
437  public function getCanonicalUrl() {
438  return $this->mCanonicalUrl;
439  }
440 
446  public function getMetadataAttribute() {
447  # note: buggy CC software only reads first "meta" link
448  static $haveMeta = false;
449  if ( $haveMeta ) {
450  return 'alternate meta';
451  } else {
452  $haveMeta = true;
453  return 'meta';
454  }
455  }
456 
464  function addScript( $script ) {
465  $this->mScripts .= $script;
466  }
467 
477  public function addExtensionStyle( $url ) {
478  wfDeprecated( __METHOD__, '1.27' );
479  array_push( $this->mExtStyles, $url );
480  }
481 
488  function getExtStyle() {
489  wfDeprecated( __METHOD__, '1.27' );
490  return $this->mExtStyles;
491  }
492 
501  public function addScriptFile( $file, $version = null ) {
502  // See if $file parameter is an absolute URL or begins with a slash
503  if ( substr( $file, 0, 1 ) == '/' || preg_match( '#^[a-z]*://#i', $file ) ) {
504  $path = $file;
505  } else {
506  $path = $this->getConfig()->get( 'StylePath' ) . "/common/{$file}";
507  }
508  if ( is_null( $version ) ) {
509  $version = $this->getConfig()->get( 'StyleVersion' );
510  }
511  $this->addScript( Html::linkedScript( wfAppendQuery( $path, $version ) ) );
512  }
513 
520  public function addInlineScript( $script ) {
521  $this->mScripts .= Html::inlineScript( $script );
522  }
523 
532  protected function filterModules( array $modules, $position = null,
534  ) {
536  $filteredModules = [];
537  foreach ( $modules as $val ) {
538  $module = $resourceLoader->getModule( $val );
539  if ( $module instanceof ResourceLoaderModule
540  && $module->getOrigin() <= $this->getAllowedModules( $type )
541  && ( is_null( $position ) || $module->getPosition() == $position )
542  ) {
543  if ( $this->mTarget && !in_array( $this->mTarget, $module->getTargets() ) ) {
544  $this->warnModuleTargetFilter( $module->getName() );
545  continue;
546  }
547  $filteredModules[] = $val;
548  }
549  }
550  return $filteredModules;
551  }
552 
553  private function warnModuleTargetFilter( $moduleName ) {
554  static $warnings = [];
555  if ( isset( $warnings[$this->mTarget][$moduleName] ) ) {
556  return;
557  }
558  $warnings[$this->mTarget][$moduleName] = true;
559  $this->getResourceLoader()->getLogger()->debug(
560  'Module "{module}" not loadable on target "{target}".',
561  [
562  'module' => $moduleName,
563  'target' => $this->mTarget,
564  ]
565  );
566  }
567 
576  public function getModules( $filter = false, $position = null, $param = 'mModules',
578  ) {
579  $modules = array_values( array_unique( $this->$param ) );
580  return $filter
581  ? $this->filterModules( $modules, $position, $type )
582  : $modules;
583  }
584 
592  public function addModules( $modules ) {
593  $this->mModules = array_merge( $this->mModules, (array)$modules );
594  }
595 
603  public function getModuleScripts( $filter = false, $position = null ) {
604  return $this->getModules( $filter, $position, 'mModuleScripts',
606  );
607  }
608 
616  public function addModuleScripts( $modules ) {
617  $this->mModuleScripts = array_merge( $this->mModuleScripts, (array)$modules );
618  }
619 
627  public function getModuleStyles( $filter = false, $position = null ) {
628  return $this->getModules( $filter, $position, 'mModuleStyles',
630  );
631  }
632 
642  public function addModuleStyles( $modules ) {
643  $this->mModuleStyles = array_merge( $this->mModuleStyles, (array)$modules );
644  }
645 
649  public function getTarget() {
650  return $this->mTarget;
651  }
652 
658  public function setTarget( $target ) {
659  $this->mTarget = $target;
660  }
661 
667  function getHeadItemsArray() {
668  return $this->mHeadItems;
669  }
670 
683  public function addHeadItem( $name, $value ) {
684  $this->mHeadItems[$name] = $value;
685  }
686 
693  public function addHeadItems( $values ) {
694  $this->mHeadItems = array_merge( $this->mHeadItems, (array)$values );
695  }
696 
703  public function hasHeadItem( $name ) {
704  return isset( $this->mHeadItems[$name] );
705  }
706 
711  public function setETag( $tag ) {
712  }
713 
721  public function setArticleBodyOnly( $only ) {
722  $this->mArticleBodyOnly = $only;
723  }
724 
730  public function getArticleBodyOnly() {
732  }
733 
741  public function setProperty( $name, $value ) {
742  $this->mProperties[$name] = $value;
743  }
744 
752  public function getProperty( $name ) {
753  if ( isset( $this->mProperties[$name] ) ) {
754  return $this->mProperties[$name];
755  } else {
756  return null;
757  }
758  }
759 
771  public function checkLastModified( $timestamp ) {
772  if ( !$timestamp || $timestamp == '19700101000000' ) {
773  wfDebug( __METHOD__ . ": CACHE DISABLED, NO TIMESTAMP\n" );
774  return false;
775  }
776  $config = $this->getConfig();
777  if ( !$config->get( 'CachePages' ) ) {
778  wfDebug( __METHOD__ . ": CACHE DISABLED\n" );
779  return false;
780  }
781 
782  $timestamp = wfTimestamp( TS_MW, $timestamp );
783  $modifiedTimes = [
784  'page' => $timestamp,
785  'user' => $this->getUser()->getTouched(),
786  'epoch' => $config->get( 'CacheEpoch' )
787  ];
788  if ( $config->get( 'UseSquid' ) ) {
789  // T46570: the core page itself may not change, but resources might
790  $modifiedTimes['sepoch'] = wfTimestamp( TS_MW, time() - $config->get( 'SquidMaxage' ) );
791  }
792  Hooks::run( 'OutputPageCheckLastModified', [ &$modifiedTimes, $this ] );
793 
794  $maxModified = max( $modifiedTimes );
795  $this->mLastModified = wfTimestamp( TS_RFC2822, $maxModified );
796 
797  $clientHeader = $this->getRequest()->getHeader( 'If-Modified-Since' );
798  if ( $clientHeader === false ) {
799  wfDebug( __METHOD__ . ": client did not send If-Modified-Since header", 'private' );
800  return false;
801  }
802 
803  # IE sends sizes after the date like this:
804  # Wed, 20 Aug 2003 06:51:19 GMT; length=5202
805  # this breaks strtotime().
806  $clientHeader = preg_replace( '/;.*$/', '', $clientHeader );
807 
808  MediaWiki\suppressWarnings(); // E_STRICT system time bitching
809  $clientHeaderTime = strtotime( $clientHeader );
810  MediaWiki\restoreWarnings();
811  if ( !$clientHeaderTime ) {
812  wfDebug( __METHOD__
813  . ": unable to parse the client's If-Modified-Since header: $clientHeader\n" );
814  return false;
815  }
816  $clientHeaderTime = wfTimestamp( TS_MW, $clientHeaderTime );
817 
818  # Make debug info
819  $info = '';
820  foreach ( $modifiedTimes as $name => $value ) {
821  if ( $info !== '' ) {
822  $info .= ', ';
823  }
824  $info .= "$name=" . wfTimestamp( TS_ISO_8601, $value );
825  }
826 
827  wfDebug( __METHOD__ . ": client sent If-Modified-Since: " .
828  wfTimestamp( TS_ISO_8601, $clientHeaderTime ), 'private' );
829  wfDebug( __METHOD__ . ": effective Last-Modified: " .
830  wfTimestamp( TS_ISO_8601, $maxModified ), 'private' );
831  if ( $clientHeaderTime < $maxModified ) {
832  wfDebug( __METHOD__ . ": STALE, $info", 'private' );
833  return false;
834  }
835 
836  # Not modified
837  # Give a 304 Not Modified response code and disable body output
838  wfDebug( __METHOD__ . ": NOT MODIFIED, $info", 'private' );
839  ini_set( 'zlib.output_compression', 0 );
840  $this->getRequest()->response()->statusHeader( 304 );
841  $this->sendCacheControl();
842  $this->disable();
843 
844  // Don't output a compressed blob when using ob_gzhandler;
845  // it's technically against HTTP spec and seems to confuse
846  // Firefox when the response gets split over two packets.
848 
849  return true;
850  }
851 
858  public function setLastModified( $timestamp ) {
859  $this->mLastModified = wfTimestamp( TS_RFC2822, $timestamp );
860  }
861 
870  public function setRobotPolicy( $policy ) {
871  $policy = Article::formatRobotPolicy( $policy );
872 
873  if ( isset( $policy['index'] ) ) {
874  $this->setIndexPolicy( $policy['index'] );
875  }
876  if ( isset( $policy['follow'] ) ) {
877  $this->setFollowPolicy( $policy['follow'] );
878  }
879  }
880 
888  public function setIndexPolicy( $policy ) {
889  $policy = trim( $policy );
890  if ( in_array( $policy, [ 'index', 'noindex' ] ) ) {
891  $this->mIndexPolicy = $policy;
892  }
893  }
894 
902  public function setFollowPolicy( $policy ) {
903  $policy = trim( $policy );
904  if ( in_array( $policy, [ 'follow', 'nofollow' ] ) ) {
905  $this->mFollowPolicy = $policy;
906  }
907  }
908 
915  public function setPageTitleActionText( $text ) {
916  $this->mPageTitleActionText = $text;
917  }
918 
924  public function getPageTitleActionText() {
926  }
927 
934  public function setHTMLTitle( $name ) {
935  if ( $name instanceof Message ) {
936  $this->mHTMLtitle = $name->setContext( $this->getContext() )->text();
937  } else {
938  $this->mHTMLtitle = $name;
939  }
940  }
941 
947  public function getHTMLTitle() {
948  return $this->mHTMLtitle;
949  }
950 
956  public function setRedirectedFrom( $t ) {
957  $this->mRedirectedFrom = $t;
958  }
959 
970  public function setPageTitle( $name ) {
971  if ( $name instanceof Message ) {
972  $name = $name->setContext( $this->getContext() )->text();
973  }
974 
975  # change "<script>foo&bar</script>" to "&lt;script&gt;foo&amp;bar&lt;/script&gt;"
976  # but leave "<i>foobar</i>" alone
977  $nameWithTags = Sanitizer::normalizeCharReferences( Sanitizer::removeHTMLtags( $name ) );
978  $this->mPagetitle = $nameWithTags;
979 
980  # change "<i>foo&amp;bar</i>" to "foo&bar"
981  $this->setHTMLTitle(
982  $this->msg( 'pagetitle' )->rawParams( Sanitizer::stripAllTags( $nameWithTags ) )
983  ->inContentLanguage()
984  );
985  }
986 
992  public function getPageTitle() {
993  return $this->mPagetitle;
994  }
995 
1001  public function setTitle( Title $t ) {
1002  $this->getContext()->setTitle( $t );
1003  }
1004 
1010  public function setSubtitle( $str ) {
1011  $this->clearSubtitle();
1012  $this->addSubtitle( $str );
1013  }
1014 
1020  public function addSubtitle( $str ) {
1021  if ( $str instanceof Message ) {
1022  $this->mSubtitle[] = $str->setContext( $this->getContext() )->parse();
1023  } else {
1024  $this->mSubtitle[] = $str;
1025  }
1026  }
1027 
1036  public static function buildBacklinkSubtitle( Title $title, $query = [] ) {
1037  if ( $title->isRedirect() ) {
1038  $query['redirect'] = 'no';
1039  }
1040  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
1041  return wfMessage( 'backlinksubtitle' )
1042  ->rawParams( $linkRenderer->makeLink( $title, null, [], $query ) );
1043  }
1044 
1051  public function addBacklinkSubtitle( Title $title, $query = [] ) {
1052  $this->addSubtitle( self::buildBacklinkSubtitle( $title, $query ) );
1053  }
1054 
1058  public function clearSubtitle() {
1059  $this->mSubtitle = [];
1060  }
1061 
1067  public function getSubtitle() {
1068  return implode( "<br />\n\t\t\t\t", $this->mSubtitle );
1069  }
1070 
1075  public function setPrintable() {
1076  $this->mPrintable = true;
1077  }
1078 
1084  public function isPrintable() {
1085  return $this->mPrintable;
1086  }
1087 
1091  public function disable() {
1092  $this->mDoNothing = true;
1093  }
1094 
1100  public function isDisabled() {
1101  return $this->mDoNothing;
1102  }
1103 
1109  public function showNewSectionLink() {
1110  return $this->mNewSectionLink;
1111  }
1112 
1118  public function forceHideNewSectionLink() {
1120  }
1121 
1130  public function setSyndicated( $show = true ) {
1131  if ( $show ) {
1132  $this->setFeedAppendQuery( false );
1133  } else {
1134  $this->mFeedLinks = [];
1135  }
1136  }
1137 
1147  public function setFeedAppendQuery( $val ) {
1148  $this->mFeedLinks = [];
1149 
1150  foreach ( $this->getConfig()->get( 'AdvertisedFeedTypes' ) as $type ) {
1151  $query = "feed=$type";
1152  if ( is_string( $val ) ) {
1153  $query .= '&' . $val;
1154  }
1155  $this->mFeedLinks[$type] = $this->getTitle()->getLocalURL( $query );
1156  }
1157  }
1158 
1165  public function addFeedLink( $format, $href ) {
1166  if ( in_array( $format, $this->getConfig()->get( 'AdvertisedFeedTypes' ) ) ) {
1167  $this->mFeedLinks[$format] = $href;
1168  }
1169  }
1170 
1175  public function isSyndicated() {
1176  return count( $this->mFeedLinks ) > 0;
1177  }
1178 
1183  public function getSyndicationLinks() {
1184  return $this->mFeedLinks;
1185  }
1186 
1192  public function getFeedAppendQuery() {
1194  }
1195 
1203  public function setArticleFlag( $v ) {
1204  $this->mIsarticle = $v;
1205  if ( $v ) {
1206  $this->mIsArticleRelated = $v;
1207  }
1208  }
1209 
1216  public function isArticle() {
1217  return $this->mIsarticle;
1218  }
1219 
1226  public function setArticleRelated( $v ) {
1227  $this->mIsArticleRelated = $v;
1228  if ( !$v ) {
1229  $this->mIsarticle = false;
1230  }
1231  }
1232 
1238  public function isArticleRelated() {
1239  return $this->mIsArticleRelated;
1240  }
1241 
1248  public function addLanguageLinks( array $newLinkArray ) {
1249  $this->mLanguageLinks += $newLinkArray;
1250  }
1251 
1258  public function setLanguageLinks( array $newLinkArray ) {
1259  $this->mLanguageLinks = $newLinkArray;
1260  }
1261 
1267  public function getLanguageLinks() {
1268  return $this->mLanguageLinks;
1269  }
1270 
1276  public function addCategoryLinks( array $categories ) {
1278 
1279  if ( !is_array( $categories ) || count( $categories ) == 0 ) {
1280  return;
1281  }
1282 
1283  $res = $this->addCategoryLinksToLBAndGetResult( $categories );
1284 
1285  # Set all the values to 'normal'.
1286  $categories = array_fill_keys( array_keys( $categories ), 'normal' );
1287 
1288  # Mark hidden categories
1289  foreach ( $res as $row ) {
1290  if ( isset( $row->pp_value ) ) {
1291  $categories[$row->page_title] = 'hidden';
1292  }
1293  }
1294 
1295  // Avoid PHP 7.1 warning of passing $this by reference
1296  $outputPage = $this;
1297  # Add the remaining categories to the skin
1298  if ( Hooks::run(
1299  'OutputPageMakeCategoryLinks',
1300  [ &$outputPage, $categories, &$this->mCategoryLinks ] )
1301  ) {
1302  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
1303  foreach ( $categories as $category => $type ) {
1304  // array keys will cast numeric category names to ints, so cast back to string
1305  $category = (string)$category;
1306  $origcategory = $category;
1307  $title = Title::makeTitleSafe( NS_CATEGORY, $category );
1308  if ( !$title ) {
1309  continue;
1310  }
1311  $wgContLang->findVariantLink( $category, $title, true );
1312  if ( $category != $origcategory && array_key_exists( $category, $categories ) ) {
1313  continue;
1314  }
1315  $text = $wgContLang->convertHtml( $title->getText() );
1316  $this->mCategories[$type][] = $title->getText();
1317  $this->mCategoryLinks[$type][] = $linkRenderer->makeLink( $title, new HtmlArmor( $text ) );
1318  }
1319  }
1320  }
1321 
1326  protected function addCategoryLinksToLBAndGetResult( array $categories ) {
1327  # Add the links to a LinkBatch
1328  $arr = [ NS_CATEGORY => $categories ];
1329  $lb = new LinkBatch;
1330  $lb->setArray( $arr );
1331 
1332  # Fetch existence plus the hiddencat property
1333  $dbr = wfGetDB( DB_REPLICA );
1334  $fields = array_merge(
1336  [ 'page_namespace', 'page_title', 'pp_value' ]
1337  );
1338 
1339  $res = $dbr->select( [ 'page', 'page_props' ],
1340  $fields,
1341  $lb->constructSet( 'page', $dbr ),
1342  __METHOD__,
1343  [],
1344  [ 'page_props' => [ 'LEFT JOIN', [
1345  'pp_propname' => 'hiddencat',
1346  'pp_page = page_id'
1347  ] ] ]
1348  );
1349 
1350  # Add the results to the link cache
1351  $lb->addResultToCache( LinkCache::singleton(), $res );
1352 
1353  return $res;
1354  }
1355 
1361  public function setCategoryLinks( array $categories ) {
1362  $this->mCategoryLinks = [];
1363  $this->addCategoryLinks( $categories );
1364  }
1365 
1374  public function getCategoryLinks() {
1375  return $this->mCategoryLinks;
1376  }
1377 
1387  public function getCategories( $type = 'all' ) {
1388  if ( $type === 'all' ) {
1389  $allCategories = [];
1390  foreach ( $this->mCategories as $categories ) {
1391  $allCategories = array_merge( $allCategories, $categories );
1392  }
1393  return $allCategories;
1394  }
1395  if ( !isset( $this->mCategories[$type] ) ) {
1396  throw new InvalidArgumentException( 'Invalid category type given: ' . $type );
1397  }
1398  return $this->mCategories[$type];
1399  }
1400 
1410  public function setIndicators( array $indicators ) {
1411  $this->mIndicators = $indicators + $this->mIndicators;
1412  // Keep ordered by key
1413  ksort( $this->mIndicators );
1414  }
1415 
1424  public function getIndicators() {
1425  return $this->mIndicators;
1426  }
1427 
1436  public function addHelpLink( $to, $overrideBaseUrl = false ) {
1437  $this->addModuleStyles( 'mediawiki.helplink' );
1438  $text = $this->msg( 'helppage-top-gethelp' )->escaped();
1439 
1440  if ( $overrideBaseUrl ) {
1441  $helpUrl = $to;
1442  } else {
1443  $toUrlencoded = wfUrlencode( str_replace( ' ', '_', $to ) );
1444  $helpUrl = "//www.mediawiki.org/wiki/Special:MyLanguage/$toUrlencoded";
1445  }
1446 
1448  'a',
1449  [
1450  'href' => $helpUrl,
1451  'target' => '_blank',
1452  'class' => 'mw-helplink',
1453  ],
1454  $text
1455  );
1456 
1457  $this->setIndicators( [ 'mw-helplink' => $link ] );
1458  }
1459 
1468  public function disallowUserJs() {
1469  $this->reduceAllowedModules(
1472  );
1473 
1474  // Site-wide styles are controlled by a config setting, see T73621
1475  // for background on why. User styles are never allowed.
1476  if ( $this->getConfig()->get( 'AllowSiteCSSOnRestrictedPages' ) ) {
1478  } else {
1480  }
1481  $this->reduceAllowedModules(
1483  $styleOrigin
1484  );
1485  }
1486 
1493  public function getAllowedModules( $type ) {
1495  return min( array_values( $this->mAllowedModules ) );
1496  } else {
1497  return isset( $this->mAllowedModules[$type] )
1498  ? $this->mAllowedModules[$type]
1500  }
1501  }
1502 
1512  public function reduceAllowedModules( $type, $level ) {
1513  $this->mAllowedModules[$type] = min( $this->getAllowedModules( $type ), $level );
1514  }
1515 
1521  public function prependHTML( $text ) {
1522  $this->mBodytext = $text . $this->mBodytext;
1523  }
1524 
1530  public function addHTML( $text ) {
1531  $this->mBodytext .= $text;
1532  }
1533 
1543  public function addElement( $element, array $attribs = [], $contents = '' ) {
1544  $this->addHTML( Html::element( $element, $attribs, $contents ) );
1545  }
1546 
1550  public function clearHTML() {
1551  $this->mBodytext = '';
1552  }
1553 
1559  public function getHTML() {
1560  return $this->mBodytext;
1561  }
1562 
1570  public function parserOptions( $options = null ) {
1571  if ( $options !== null && !empty( $options->isBogus ) ) {
1572  // Someone is trying to set a bogus pre-$wgUser PO. Check if it has
1573  // been changed somehow, and keep it if so.
1574  $anonPO = ParserOptions::newFromAnon();
1575  $anonPO->setEditSection( false );
1576  $anonPO->setAllowUnsafeRawHtml( false );
1577  if ( !$options->matches( $anonPO ) ) {
1578  wfLogWarning( __METHOD__ . ': Setting a changed bogus ParserOptions: ' . wfGetAllCallers( 5 ) );
1579  $options->isBogus = false;
1580  }
1581  }
1582 
1583  if ( !$this->mParserOptions ) {
1584  if ( !$this->getContext()->getUser()->isSafeToLoad() ) {
1585  // $wgUser isn't unstubbable yet, so don't try to get a
1586  // ParserOptions for it. And don't cache this ParserOptions
1587  // either.
1589  $po->setEditSection( false );
1590  $po->setAllowUnsafeRawHtml( false );
1591  $po->isBogus = true;
1592  if ( $options !== null ) {
1593  $this->mParserOptions = empty( $options->isBogus ) ? $options : null;
1594  }
1595  return $po;
1596  }
1597 
1598  $this->mParserOptions = ParserOptions::newFromContext( $this->getContext() );
1599  $this->mParserOptions->setEditSection( false );
1600  $this->mParserOptions->setAllowUnsafeRawHtml( false );
1601  }
1602 
1603  if ( $options !== null && !empty( $options->isBogus ) ) {
1604  // They're trying to restore the bogus pre-$wgUser PO. Do the right
1605  // thing.
1606  return wfSetVar( $this->mParserOptions, null, true );
1607  } else {
1608  return wfSetVar( $this->mParserOptions, $options );
1609  }
1610  }
1611 
1619  public function setRevisionId( $revid ) {
1620  $val = is_null( $revid ) ? null : intval( $revid );
1621  return wfSetVar( $this->mRevisionId, $val );
1622  }
1623 
1629  public function getRevisionId() {
1630  return $this->mRevisionId;
1631  }
1632 
1640  public function setRevisionTimestamp( $timestamp ) {
1641  return wfSetVar( $this->mRevisionTimestamp, $timestamp );
1642  }
1643 
1650  public function getRevisionTimestamp() {
1652  }
1653 
1660  public function setFileVersion( $file ) {
1661  $val = null;
1662  if ( $file instanceof File && $file->exists() ) {
1663  $val = [ 'time' => $file->getTimestamp(), 'sha1' => $file->getSha1() ];
1664  }
1665  return wfSetVar( $this->mFileVersion, $val, true );
1666  }
1667 
1673  public function getFileVersion() {
1674  return $this->mFileVersion;
1675  }
1676 
1683  public function getTemplateIds() {
1684  return $this->mTemplateIds;
1685  }
1686 
1693  public function getFileSearchOptions() {
1694  return $this->mImageTimeKeys;
1695  }
1696 
1706  public function addWikiText( $text, $linestart = true, $interface = true ) {
1707  $title = $this->getTitle(); // Work around E_STRICT
1708  if ( !$title ) {
1709  throw new MWException( 'Title is null' );
1710  }
1711  $this->addWikiTextTitle( $text, $title, $linestart, /*tidy*/false, $interface );
1712  }
1713 
1721  public function addWikiTextWithTitle( $text, &$title, $linestart = true ) {
1722  $this->addWikiTextTitle( $text, $title, $linestart );
1723  }
1724 
1732  function addWikiTextTitleTidy( $text, &$title, $linestart = true ) {
1733  $this->addWikiTextTitle( $text, $title, $linestart, true );
1734  }
1735 
1742  public function addWikiTextTidy( $text, $linestart = true ) {
1743  $title = $this->getTitle();
1744  $this->addWikiTextTitleTidy( $text, $title, $linestart );
1745  }
1746 
1757  public function addWikiTextTitle( $text, Title $title, $linestart,
1758  $tidy = false, $interface = false
1759  ) {
1760  global $wgParser;
1761 
1762  $popts = $this->parserOptions();
1763  $oldTidy = $popts->setTidy( $tidy );
1764  $popts->setInterfaceMessage( (bool)$interface );
1765 
1766  $parserOutput = $wgParser->getFreshParser()->parse(
1767  $text, $title, $popts,
1768  $linestart, true, $this->mRevisionId
1769  );
1770 
1771  $popts->setTidy( $oldTidy );
1772 
1773  $this->addParserOutput( $parserOutput );
1774  }
1775 
1783  wfDeprecated( __METHOD__, '1.24' );
1785  }
1786 
1796  $this->mLanguageLinks += $parserOutput->getLanguageLinks();
1797  $this->addCategoryLinks( $parserOutput->getCategories() );
1798  $this->setIndicators( $parserOutput->getIndicators() );
1799  $this->mNewSectionLink = $parserOutput->getNewSection();
1800  $this->mHideNewSectionLink = $parserOutput->getHideNewSection();
1801 
1802  if ( !$parserOutput->isCacheable() ) {
1803  $this->enableClientCache( false );
1804  }
1805  $this->mNoGallery = $parserOutput->getNoGallery();
1806  $this->mHeadItems = array_merge( $this->mHeadItems, $parserOutput->getHeadItems() );
1807  $this->addModules( $parserOutput->getModules() );
1808  $this->addModuleScripts( $parserOutput->getModuleScripts() );
1809  $this->addModuleStyles( $parserOutput->getModuleStyles() );
1810  $this->addJsConfigVars( $parserOutput->getJsConfigVars() );
1811  $this->mPreventClickjacking = $this->mPreventClickjacking
1812  || $parserOutput->preventClickjacking();
1813 
1814  // Template versioning...
1815  foreach ( (array)$parserOutput->getTemplateIds() as $ns => $dbks ) {
1816  if ( isset( $this->mTemplateIds[$ns] ) ) {
1817  $this->mTemplateIds[$ns] = $dbks + $this->mTemplateIds[$ns];
1818  } else {
1819  $this->mTemplateIds[$ns] = $dbks;
1820  }
1821  }
1822  // File versioning...
1823  foreach ( (array)$parserOutput->getFileSearchOptions() as $dbk => $data ) {
1824  $this->mImageTimeKeys[$dbk] = $data;
1825  }
1826 
1827  // Hooks registered in the object
1828  $parserOutputHooks = $this->getConfig()->get( 'ParserOutputHooks' );
1829  foreach ( $parserOutput->getOutputHooks() as $hookInfo ) {
1830  list( $hookName, $data ) = $hookInfo;
1831  if ( isset( $parserOutputHooks[$hookName] ) ) {
1832  call_user_func( $parserOutputHooks[$hookName], $this, $parserOutput, $data );
1833  }
1834  }
1835 
1836  // Enable OOUI if requested via ParserOutput
1837  if ( $parserOutput->getEnableOOUI() ) {
1838  $this->enableOOUI();
1839  }
1840 
1841  // Include parser limit report
1842  if ( !$this->limitReportJSData ) {
1843  $this->limitReportJSData = $parserOutput->getLimitReportJSData();
1844  }
1845 
1846  // Link flags are ignored for now, but may in the future be
1847  // used to mark individual language links.
1848  $linkFlags = [];
1849  // Avoid PHP 7.1 warning of passing $this by reference
1850  $outputPage = $this;
1851  Hooks::run( 'LanguageLinks', [ $this->getTitle(), &$this->mLanguageLinks, &$linkFlags ] );
1852  Hooks::run( 'OutputPageParserOutput', [ &$outputPage, $parserOutput ] );
1853  }
1854 
1864 
1865  $this->addModules( $parserOutput->getModules() );
1866  $this->addModuleScripts( $parserOutput->getModuleScripts() );
1867  $this->addModuleStyles( $parserOutput->getModuleStyles() );
1868 
1869  $this->addJsConfigVars( $parserOutput->getJsConfigVars() );
1870  }
1871 
1878  public function addParserOutputText( $parserOutput ) {
1879  $text = $parserOutput->getText();
1880  // Avoid PHP 7.1 warning of passing $this by reference
1881  $outputPage = $this;
1882  Hooks::run( 'OutputPageBeforeHTML', [ &$outputPage, &$text ] );
1883  $this->addHTML( $text );
1884  }
1885 
1893  $parserOutput->setTOCEnabled( $this->mEnableTOC );
1894 
1895  // Touch section edit links only if not previously disabled
1896  if ( $parserOutput->getEditSectionTokens() ) {
1897  $parserOutput->setEditSectionTokens( $this->mEnableSectionEditLinks );
1898  }
1899 
1901  }
1902 
1908  public function addTemplate( &$template ) {
1909  $this->addHTML( $template->getHTML() );
1910  }
1911 
1924  public function parse( $text, $linestart = true, $interface = false, $language = null ) {
1925  global $wgParser;
1926 
1927  if ( is_null( $this->getTitle() ) ) {
1928  throw new MWException( 'Empty $mTitle in ' . __METHOD__ );
1929  }
1930 
1931  $popts = $this->parserOptions();
1932  if ( $interface ) {
1933  $popts->setInterfaceMessage( true );
1934  }
1935  if ( $language !== null ) {
1936  $oldLang = $popts->setTargetLanguage( $language );
1937  }
1938 
1939  $parserOutput = $wgParser->getFreshParser()->parse(
1940  $text, $this->getTitle(), $popts,
1941  $linestart, true, $this->mRevisionId
1942  );
1943 
1944  if ( $interface ) {
1945  $popts->setInterfaceMessage( false );
1946  }
1947  if ( $language !== null ) {
1948  $popts->setTargetLanguage( $oldLang );
1949  }
1950 
1951  return $parserOutput->getText();
1952  }
1953 
1964  public function parseInline( $text, $linestart = true, $interface = false ) {
1965  $parsed = $this->parse( $text, $linestart, $interface );
1966  return Parser::stripOuterParagraph( $parsed );
1967  }
1968 
1973  public function setSquidMaxage( $maxage ) {
1974  $this->setCdnMaxage( $maxage );
1975  }
1976 
1982  public function setCdnMaxage( $maxage ) {
1983  $this->mCdnMaxage = min( $maxage, $this->mCdnMaxageLimit );
1984  }
1985 
1992  public function lowerCdnMaxage( $maxage ) {
1993  $this->mCdnMaxageLimit = min( $maxage, $this->mCdnMaxageLimit );
1994  $this->setCdnMaxage( $this->mCdnMaxage );
1995  }
1996 
2010  public function adaptCdnTTL( $mtime, $minTTL = 0, $maxTTL = 0 ) {
2011  $minTTL = $minTTL ?: IExpiringStore::TTL_MINUTE;
2012  $maxTTL = $maxTTL ?: $this->getConfig()->get( 'SquidMaxage' );
2013 
2014  if ( $mtime === null || $mtime === false ) {
2015  return $minTTL; // entity does not exist
2016  }
2017 
2018  $age = time() - wfTimestamp( TS_UNIX, $mtime );
2019  $adaptiveTTL = max( .9 * $age, $minTTL );
2020  $adaptiveTTL = min( $adaptiveTTL, $maxTTL );
2021 
2022  $this->lowerCdnMaxage( (int)$adaptiveTTL );
2023 
2024  return $adaptiveTTL;
2025  }
2026 
2034  public function enableClientCache( $state ) {
2035  return wfSetVar( $this->mEnableClientCache, $state );
2036  }
2037 
2043  function getCacheVaryCookies() {
2044  static $cookies;
2045  if ( $cookies === null ) {
2046  $config = $this->getConfig();
2047  $cookies = array_merge(
2048  SessionManager::singleton()->getVaryCookies(),
2049  [
2050  'forceHTTPS',
2051  ],
2052  $config->get( 'CacheVaryCookies' )
2053  );
2054  Hooks::run( 'GetCacheVaryCookies', [ $this, &$cookies ] );
2055  }
2056  return $cookies;
2057  }
2058 
2066  $request = $this->getRequest();
2067  foreach ( $this->getCacheVaryCookies() as $cookieName ) {
2068  if ( $request->getCookie( $cookieName, '', '' ) !== '' ) {
2069  wfDebug( __METHOD__ . ": found $cookieName\n" );
2070  return true;
2071  }
2072  }
2073  wfDebug( __METHOD__ . ": no cache-varying cookies found\n" );
2074  return false;
2075  }
2076 
2085  public function addVaryHeader( $header, array $option = null ) {
2086  if ( !array_key_exists( $header, $this->mVaryHeader ) ) {
2087  $this->mVaryHeader[$header] = [];
2088  }
2089  if ( !is_array( $option ) ) {
2090  $option = [];
2091  }
2092  $this->mVaryHeader[$header] = array_unique( array_merge( $this->mVaryHeader[$header], $option ) );
2093  }
2094 
2101  public function getVaryHeader() {
2102  // If we vary on cookies, let's make sure it's always included here too.
2103  if ( $this->getCacheVaryCookies() ) {
2104  $this->addVaryHeader( 'Cookie' );
2105  }
2106 
2107  foreach ( SessionManager::singleton()->getVaryHeaders() as $header => $options ) {
2108  $this->addVaryHeader( $header, $options );
2109  }
2110  return 'Vary: ' . implode( ', ', array_keys( $this->mVaryHeader ) );
2111  }
2112 
2118  public function addLinkHeader( $header ) {
2119  $this->mLinkHeader[] = $header;
2120  }
2121 
2127  public function getLinkHeader() {
2128  if ( !$this->mLinkHeader ) {
2129  return false;
2130  }
2131 
2132  return 'Link: ' . implode( ',', $this->mLinkHeader );
2133  }
2134 
2140  public function getKeyHeader() {
2141  $cvCookies = $this->getCacheVaryCookies();
2142 
2143  $cookiesOption = [];
2144  foreach ( $cvCookies as $cookieName ) {
2145  $cookiesOption[] = 'param=' . $cookieName;
2146  }
2147  $this->addVaryHeader( 'Cookie', $cookiesOption );
2148 
2149  foreach ( SessionManager::singleton()->getVaryHeaders() as $header => $options ) {
2150  $this->addVaryHeader( $header, $options );
2151  }
2152 
2153  $headers = [];
2154  foreach ( $this->mVaryHeader as $header => $option ) {
2155  $newheader = $header;
2156  if ( is_array( $option ) && count( $option ) > 0 ) {
2157  $newheader .= ';' . implode( ';', $option );
2158  }
2159  $headers[] = $newheader;
2160  }
2161  $key = 'Key: ' . implode( ',', $headers );
2162 
2163  return $key;
2164  }
2165 
2174  function addAcceptLanguage() {
2175  $title = $this->getTitle();
2176  if ( !$title instanceof Title ) {
2177  return;
2178  }
2179 
2180  $lang = $title->getPageLanguage();
2181  if ( !$this->getRequest()->getCheck( 'variant' ) && $lang->hasVariants() ) {
2182  $variants = $lang->getVariants();
2183  $aloption = [];
2184  foreach ( $variants as $variant ) {
2185  if ( $variant === $lang->getCode() ) {
2186  continue;
2187  } else {
2188  $aloption[] = 'substr=' . $variant;
2189 
2190  // IE and some other browsers use BCP 47 standards in
2191  // their Accept-Language header, like "zh-CN" or "zh-Hant".
2192  // We should handle these too.
2193  $variantBCP47 = wfBCP47( $variant );
2194  if ( $variantBCP47 !== $variant ) {
2195  $aloption[] = 'substr=' . $variantBCP47;
2196  }
2197  }
2198  }
2199  $this->addVaryHeader( 'Accept-Language', $aloption );
2200  }
2201  }
2202 
2213  public function preventClickjacking( $enable = true ) {
2214  $this->mPreventClickjacking = $enable;
2215  }
2216 
2222  public function allowClickjacking() {
2223  $this->mPreventClickjacking = false;
2224  }
2225 
2232  public function getPreventClickjacking() {
2234  }
2235 
2243  public function getFrameOptions() {
2244  $config = $this->getConfig();
2245  if ( $config->get( 'BreakFrames' ) ) {
2246  return 'DENY';
2247  } elseif ( $this->mPreventClickjacking && $config->get( 'EditPageFrameOptions' ) ) {
2248  return $config->get( 'EditPageFrameOptions' );
2249  }
2250  return false;
2251  }
2252 
2256  public function sendCacheControl() {
2257  $response = $this->getRequest()->response();
2258  $config = $this->getConfig();
2259 
2260  $this->addVaryHeader( 'Cookie' );
2261  $this->addAcceptLanguage();
2262 
2263  # don't serve compressed data to clients who can't handle it
2264  # maintain different caches for logged-in users and non-logged in ones
2265  $response->header( $this->getVaryHeader() );
2266 
2267  if ( $config->get( 'UseKeyHeader' ) ) {
2268  $response->header( $this->getKeyHeader() );
2269  }
2270 
2271  if ( $this->mEnableClientCache ) {
2272  if (
2273  $config->get( 'UseSquid' ) &&
2274  !$response->hasCookies() &&
2275  !SessionManager::getGlobalSession()->isPersistent() &&
2276  !$this->isPrintable() &&
2277  $this->mCdnMaxage != 0 &&
2278  !$this->haveCacheVaryCookies()
2279  ) {
2280  if ( $config->get( 'UseESI' ) ) {
2281  # We'll purge the proxy cache explicitly, but require end user agents
2282  # to revalidate against the proxy on each visit.
2283  # Surrogate-Control controls our CDN, Cache-Control downstream caches
2284  wfDebug( __METHOD__ .
2285  ": proxy caching with ESI; {$this->mLastModified} **", 'private' );
2286  # start with a shorter timeout for initial testing
2287  # header( 'Surrogate-Control: max-age=2678400+2678400, content="ESI/1.0"');
2288  $response->header(
2289  "Surrogate-Control: max-age={$config->get( 'SquidMaxage' )}" .
2290  "+{$this->mCdnMaxage}, content=\"ESI/1.0\""
2291  );
2292  $response->header( 'Cache-Control: s-maxage=0, must-revalidate, max-age=0' );
2293  } else {
2294  # We'll purge the proxy cache for anons explicitly, but require end user agents
2295  # to revalidate against the proxy on each visit.
2296  # IMPORTANT! The CDN needs to replace the Cache-Control header with
2297  # Cache-Control: s-maxage=0, must-revalidate, max-age=0
2298  wfDebug( __METHOD__ .
2299  ": local proxy caching; {$this->mLastModified} **", 'private' );
2300  # start with a shorter timeout for initial testing
2301  # header( "Cache-Control: s-maxage=2678400, must-revalidate, max-age=0" );
2302  $response->header( "Cache-Control: " .
2303  "s-maxage={$this->mCdnMaxage}, must-revalidate, max-age=0" );
2304  }
2305  } else {
2306  # We do want clients to cache if they can, but they *must* check for updates
2307  # on revisiting the page.
2308  wfDebug( __METHOD__ . ": private caching; {$this->mLastModified} **", 'private' );
2309  $response->header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', 0 ) . ' GMT' );
2310  $response->header( "Cache-Control: private, must-revalidate, max-age=0" );
2311  }
2312  if ( $this->mLastModified ) {
2313  $response->header( "Last-Modified: {$this->mLastModified}" );
2314  }
2315  } else {
2316  wfDebug( __METHOD__ . ": no caching **", 'private' );
2317 
2318  # In general, the absence of a last modified header should be enough to prevent
2319  # the client from using its cache. We send a few other things just to make sure.
2320  $response->header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', 0 ) . ' GMT' );
2321  $response->header( 'Cache-Control: no-cache, no-store, max-age=0, must-revalidate' );
2322  $response->header( 'Pragma: no-cache' );
2323  }
2324  }
2325 
2336  public function output( $return = false ) {
2338 
2339  if ( $this->mDoNothing ) {
2340  return $return ? '' : null;
2341  }
2342 
2343  $response = $this->getRequest()->response();
2344  $config = $this->getConfig();
2345 
2346  if ( $this->mRedirect != '' ) {
2347  # Standards require redirect URLs to be absolute
2348  $this->mRedirect = wfExpandUrl( $this->mRedirect, PROTO_CURRENT );
2349 
2350  $redirect = $this->mRedirect;
2352 
2353  if ( Hooks::run( "BeforePageRedirect", [ $this, &$redirect, &$code ] ) ) {
2354  if ( $code == '301' || $code == '303' ) {
2355  if ( !$config->get( 'DebugRedirects' ) ) {
2356  $response->statusHeader( $code );
2357  }
2358  $this->mLastModified = wfTimestamp( TS_RFC2822 );
2359  }
2360  if ( $config->get( 'VaryOnXFP' ) ) {
2361  $this->addVaryHeader( 'X-Forwarded-Proto' );
2362  }
2363  $this->sendCacheControl();
2364 
2365  $response->header( "Content-Type: text/html; charset=utf-8" );
2366  if ( $config->get( 'DebugRedirects' ) ) {
2367  $url = htmlspecialchars( $redirect );
2368  print "<!DOCTYPE html>\n<html>\n<head>\n<title>Redirect</title>\n</head>\n<body>\n";
2369  print "<p>Location: <a href=\"$url\">$url</a></p>\n";
2370  print "</body>\n</html>\n";
2371  } else {
2372  $response->header( 'Location: ' . $redirect );
2373  }
2374  }
2375 
2376  return $return ? '' : null;
2377  } elseif ( $this->mStatusCode ) {
2378  $response->statusHeader( $this->mStatusCode );
2379  }
2380 
2381  # Buffer output; final headers may depend on later processing
2382  ob_start();
2383 
2384  $response->header( 'Content-type: ' . $config->get( 'MimeType' ) . '; charset=UTF-8' );
2385  $response->header( 'Content-language: ' . $wgContLang->getHtmlCode() );
2386 
2387  // Avoid Internet Explorer "compatibility view" in IE 8-10, so that
2388  // jQuery etc. can work correctly.
2389  $response->header( 'X-UA-Compatible: IE=Edge' );
2390 
2391  $this->addLogoPreloadLinkHeaders();
2392  $linkHeader = $this->getLinkHeader();
2393  if ( $linkHeader ) {
2394  $response->header( $linkHeader );
2395  }
2396 
2397  // Prevent framing, if requested
2398  $frameOptions = $this->getFrameOptions();
2399  if ( $frameOptions ) {
2400  $response->header( "X-Frame-Options: $frameOptions" );
2401  }
2402 
2403  if ( $this->mArticleBodyOnly ) {
2404  echo $this->mBodytext;
2405  } else {
2406  // Enable safe mode if requested
2407  if ( $this->getRequest()->getBool( 'safemode' ) ) {
2408  $this->disallowUserJs();
2409  }
2410 
2411  $sk = $this->getSkin();
2412  // add skin specific modules
2413  $modules = $sk->getDefaultModules();
2414 
2415  // Enforce various default modules for all pages and all skins
2416  $coreModules = [
2417  // Keep this list as small as possible
2418  'site',
2419  'mediawiki.page.startup',
2420  'mediawiki.user',
2421  ];
2422 
2423  // Support for high-density display images if enabled
2424  if ( $config->get( 'ResponsiveImages' ) ) {
2425  $coreModules[] = 'mediawiki.hidpi';
2426  }
2427 
2428  $this->addModules( $coreModules );
2429  foreach ( $modules as $group ) {
2430  $this->addModules( $group );
2431  }
2432  MWDebug::addModules( $this );
2433 
2434  // Avoid PHP 7.1 warning of passing $this by reference
2435  $outputPage = $this;
2436  // Hook that allows last minute changes to the output page, e.g.
2437  // adding of CSS or Javascript by extensions.
2438  Hooks::run( 'BeforePageDisplay', [ &$outputPage, &$sk ] );
2439 
2440  try {
2441  $sk->outputPage();
2442  } catch ( Exception $e ) {
2443  ob_end_clean(); // bug T129657
2444  throw $e;
2445  }
2446  }
2447 
2448  try {
2449  // This hook allows last minute changes to final overall output by modifying output buffer
2450  Hooks::run( 'AfterFinalPageOutput', [ $this ] );
2451  } catch ( Exception $e ) {
2452  ob_end_clean(); // bug T129657
2453  throw $e;
2454  }
2455 
2456  $this->sendCacheControl();
2457 
2458  if ( $return ) {
2459  return ob_get_clean();
2460  } else {
2461  ob_end_flush();
2462  return null;
2463  }
2464  }
2465 
2476  public function prepareErrorPage( $pageTitle, $htmlTitle = false ) {
2477  $this->setPageTitle( $pageTitle );
2478  if ( $htmlTitle !== false ) {
2479  $this->setHTMLTitle( $htmlTitle );
2480  }
2481  $this->setRobotPolicy( 'noindex,nofollow' );
2482  $this->setArticleRelated( false );
2483  $this->enableClientCache( false );
2484  $this->mRedirect = '';
2485  $this->clearSubtitle();
2486  $this->clearHTML();
2487  }
2488 
2501  public function showErrorPage( $title, $msg, $params = [] ) {
2502  if ( !$title instanceof Message ) {
2503  $title = $this->msg( $title );
2504  }
2505 
2506  $this->prepareErrorPage( $title );
2507 
2508  if ( $msg instanceof Message ) {
2509  if ( $params !== [] ) {
2510  trigger_error( 'Argument ignored: $params. The message parameters argument '
2511  . 'is discarded when the $msg argument is a Message object instead of '
2512  . 'a string.', E_USER_NOTICE );
2513  }
2514  $this->addHTML( $msg->parseAsBlock() );
2515  } else {
2516  $this->addWikiMsgArray( $msg, $params );
2517  }
2518 
2519  $this->returnToMain();
2520  }
2521 
2528  public function showPermissionsErrorPage( array $errors, $action = null ) {
2529  foreach ( $errors as $key => $error ) {
2530  $errors[$key] = (array)$error;
2531  }
2532 
2533  // For some action (read, edit, create and upload), display a "login to do this action"
2534  // error if all of the following conditions are met:
2535  // 1. the user is not logged in
2536  // 2. the only error is insufficient permissions (i.e. no block or something else)
2537  // 3. the error can be avoided simply by logging in
2538  if ( in_array( $action, [ 'read', 'edit', 'createpage', 'createtalk', 'upload' ] )
2539  && $this->getUser()->isAnon() && count( $errors ) == 1 && isset( $errors[0][0] )
2540  && ( $errors[0][0] == 'badaccess-groups' || $errors[0][0] == 'badaccess-group0' )
2541  && ( User::groupHasPermission( 'user', $action )
2542  || User::groupHasPermission( 'autoconfirmed', $action ) )
2543  ) {
2544  $displayReturnto = null;
2545 
2546  # Due to T34276, if a user does not have read permissions,
2547  # $this->getTitle() will just give Special:Badtitle, which is
2548  # not especially useful as a returnto parameter. Use the title
2549  # from the request instead, if there was one.
2550  $request = $this->getRequest();
2551  $returnto = Title::newFromText( $request->getVal( 'title', '' ) );
2552  if ( $action == 'edit' ) {
2553  $msg = 'whitelistedittext';
2554  $displayReturnto = $returnto;
2555  } elseif ( $action == 'createpage' || $action == 'createtalk' ) {
2556  $msg = 'nocreatetext';
2557  } elseif ( $action == 'upload' ) {
2558  $msg = 'uploadnologintext';
2559  } else { # Read
2560  $msg = 'loginreqpagetext';
2561  $displayReturnto = Title::newMainPage();
2562  }
2563 
2564  $query = [];
2565 
2566  if ( $returnto ) {
2567  $query['returnto'] = $returnto->getPrefixedText();
2568 
2569  if ( !$request->wasPosted() ) {
2570  $returntoquery = $request->getValues();
2571  unset( $returntoquery['title'] );
2572  unset( $returntoquery['returnto'] );
2573  unset( $returntoquery['returntoquery'] );
2574  $query['returntoquery'] = wfArrayToCgi( $returntoquery );
2575  }
2576  }
2577  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
2578  $loginLink = $linkRenderer->makeKnownLink(
2579  SpecialPage::getTitleFor( 'Userlogin' ),
2580  $this->msg( 'loginreqlink' )->text(),
2581  [],
2582  $query
2583  );
2584 
2585  $this->prepareErrorPage( $this->msg( 'loginreqtitle' ) );
2586  $this->addHTML( $this->msg( $msg )->rawParams( $loginLink )->parse() );
2587 
2588  # Don't return to a page the user can't read otherwise
2589  # we'll end up in a pointless loop
2590  if ( $displayReturnto && $displayReturnto->userCan( 'read', $this->getUser() ) ) {
2591  $this->returnToMain( null, $displayReturnto );
2592  }
2593  } else {
2594  $this->prepareErrorPage( $this->msg( 'permissionserrors' ) );
2595  $this->addWikiText( $this->formatPermissionsErrorMessage( $errors, $action ) );
2596  }
2597  }
2598 
2605  public function versionRequired( $version ) {
2606  $this->prepareErrorPage( $this->msg( 'versionrequired', $version ) );
2607 
2608  $this->addWikiMsg( 'versionrequiredtext', $version );
2609  $this->returnToMain();
2610  }
2611 
2619  public function formatPermissionsErrorMessage( array $errors, $action = null ) {
2620  if ( $action == null ) {
2621  $text = $this->msg( 'permissionserrorstext', count( $errors ) )->plain() . "\n\n";
2622  } else {
2623  $action_desc = $this->msg( "action-$action" )->plain();
2624  $text = $this->msg(
2625  'permissionserrorstext-withaction',
2626  count( $errors ),
2627  $action_desc
2628  )->plain() . "\n\n";
2629  }
2630 
2631  if ( count( $errors ) > 1 ) {
2632  $text .= '<ul class="permissions-errors">' . "\n";
2633 
2634  foreach ( $errors as $error ) {
2635  $text .= '<li>';
2636  $text .= call_user_func_array( [ $this, 'msg' ], $error )->plain();
2637  $text .= "</li>\n";
2638  }
2639  $text .= '</ul>';
2640  } else {
2641  $text .= "<div class=\"permissions-errors\">\n" .
2642  call_user_func_array( [ $this, 'msg' ], reset( $errors ) )->plain() .
2643  "\n</div>";
2644  }
2645 
2646  return $text;
2647  }
2648 
2660  public function readOnlyPage() {
2661  if ( func_num_args() > 0 ) {
2662  throw new MWException( __METHOD__ . ' no longer accepts arguments since 1.25.' );
2663  }
2664 
2665  throw new ReadOnlyError;
2666  }
2667 
2674  public function rateLimited() {
2675  wfDeprecated( __METHOD__, '1.25' );
2676  throw new ThrottledError;
2677  }
2678 
2688  public function showLagWarning( $lag ) {
2689  $config = $this->getConfig();
2690  if ( $lag >= $config->get( 'SlaveLagWarning' ) ) {
2691  $lag = floor( $lag ); // floor to avoid nano seconds to display
2692  $message = $lag < $config->get( 'SlaveLagCritical' )
2693  ? 'lag-warn-normal'
2694  : 'lag-warn-high';
2695  $wrap = Html::rawElement( 'div', [ 'class' => "mw-{$message}" ], "\n$1\n" );
2696  $this->wrapWikiMsg( "$wrap\n", [ $message, $this->getLanguage()->formatNum( $lag ) ] );
2697  }
2698  }
2699 
2700  public function showFatalError( $message ) {
2701  $this->prepareErrorPage( $this->msg( 'internalerror' ) );
2702 
2703  $this->addHTML( $message );
2704  }
2705 
2706  public function showUnexpectedValueError( $name, $val ) {
2707  $this->showFatalError( $this->msg( 'unexpected', $name, $val )->text() );
2708  }
2709 
2710  public function showFileCopyError( $old, $new ) {
2711  $this->showFatalError( $this->msg( 'filecopyerror', $old, $new )->text() );
2712  }
2713 
2714  public function showFileRenameError( $old, $new ) {
2715  $this->showFatalError( $this->msg( 'filerenameerror', $old, $new )->text() );
2716  }
2717 
2718  public function showFileDeleteError( $name ) {
2719  $this->showFatalError( $this->msg( 'filedeleteerror', $name )->text() );
2720  }
2721 
2722  public function showFileNotFoundError( $name ) {
2723  $this->showFatalError( $this->msg( 'filenotfound', $name )->text() );
2724  }
2725 
2734  public function addReturnTo( $title, array $query = [], $text = null, $options = [] ) {
2735  $linkRenderer = MediaWikiServices::getInstance()
2736  ->getLinkRendererFactory()->createFromLegacyOptions( $options );
2737  $link = $this->msg( 'returnto' )->rawParams(
2738  $linkRenderer->makeLink( $title, $text, [], $query ) )->escaped();
2739  $this->addHTML( "<p id=\"mw-returnto\">{$link}</p>\n" );
2740  }
2741 
2750  public function returnToMain( $unused = null, $returnto = null, $returntoquery = null ) {
2751  if ( $returnto == null ) {
2752  $returnto = $this->getRequest()->getText( 'returnto' );
2753  }
2754 
2755  if ( $returntoquery == null ) {
2756  $returntoquery = $this->getRequest()->getText( 'returntoquery' );
2757  }
2758 
2759  if ( $returnto === '' ) {
2760  $returnto = Title::newMainPage();
2761  }
2762 
2763  if ( is_object( $returnto ) ) {
2764  $titleObj = $returnto;
2765  } else {
2766  $titleObj = Title::newFromText( $returnto );
2767  }
2768  // We don't want people to return to external interwiki. That
2769  // might potentially be used as part of a phishing scheme
2770  if ( !is_object( $titleObj ) || $titleObj->isExternal() ) {
2771  $titleObj = Title::newMainPage();
2772  }
2773 
2774  $this->addReturnTo( $titleObj, wfCgiToArray( $returntoquery ) );
2775  }
2776 
2777  private function getRlClientContext() {
2778  if ( !$this->rlClientContext ) {
2779  $query = ResourceLoader::makeLoaderQuery(
2780  [], // modules; not relevant
2781  $this->getLanguage()->getCode(),
2782  $this->getSkin()->getSkinName(),
2783  $this->getUser()->isLoggedIn() ? $this->getUser()->getName() : null,
2784  null, // version; not relevant
2785  ResourceLoader::inDebugMode(),
2786  null, // only; not relevant
2787  $this->isPrintable(),
2788  $this->getRequest()->getBool( 'handheld' )
2789  );
2790  $this->rlClientContext = new ResourceLoaderContext(
2791  $this->getResourceLoader(),
2792  new FauxRequest( $query )
2793  );
2794  }
2795  return $this->rlClientContext;
2796  }
2797 
2809  public function getRlClient() {
2810  if ( !$this->rlClient ) {
2811  $context = $this->getRlClientContext();
2812  $rl = $this->getResourceLoader();
2813  $this->addModules( [
2814  'user.options',
2815  'user.tokens',
2816  ] );
2817  $this->addModuleStyles( [
2818  'site.styles',
2819  'noscript',
2820  'user.styles',
2821  ] );
2822  $this->getSkin()->setupSkinUserCss( $this );
2823 
2824  // Prepare exempt modules for buildExemptModules()
2825  $exemptGroups = [ 'site' => [], 'noscript' => [], 'private' => [], 'user' => [] ];
2826  $exemptStates = [];
2827  $moduleStyles = $this->getModuleStyles( /*filter*/ true );
2828 
2829  // Preload getTitleInfo for isKnownEmpty calls below and in ResourceLoaderClientHtml
2830  // Separate user-specific batch for improved cache-hit ratio.
2831  $userBatch = [ 'user.styles', 'user' ];
2832  $siteBatch = array_diff( $moduleStyles, $userBatch );
2833  $dbr = wfGetDB( DB_REPLICA );
2836 
2837  // Filter out modules handled by buildExemptModules()
2838  $moduleStyles = array_filter( $moduleStyles,
2839  function ( $name ) use ( $rl, $context, &$exemptGroups, &$exemptStates ) {
2840  $module = $rl->getModule( $name );
2841  if ( $module ) {
2842  if ( $name === 'user.styles' && $this->isUserCssPreview() ) {
2843  $exemptStates[$name] = 'ready';
2844  // Special case in buildExemptModules()
2845  return false;
2846  }
2847  $group = $module->getGroup();
2848  if ( isset( $exemptGroups[$group] ) ) {
2849  $exemptStates[$name] = 'ready';
2850  if ( !$module->isKnownEmpty( $context ) ) {
2851  // E.g. Don't output empty <styles>
2852  $exemptGroups[$group][] = $name;
2853  }
2854  return false;
2855  }
2856  }
2857  return true;
2858  }
2859  );
2860  $this->rlExemptStyleModules = $exemptGroups;
2861 
2862  $isUserModuleFiltered = !$this->filterModules( [ 'user' ] );
2863  // If this page filters out 'user', makeResourceLoaderLink will drop it.
2864  // Avoid indefinite "loading" state or untrue "ready" state (T145368).
2865  if ( !$isUserModuleFiltered ) {
2866  // Manually handled by getBottomScripts()
2867  $userModule = $rl->getModule( 'user' );
2868  $userState = $userModule->isKnownEmpty( $context ) && !$this->isUserJsPreview()
2869  ? 'ready'
2870  : 'loading';
2871  $this->rlUserModuleState = $exemptStates['user'] = $userState;
2872  }
2873 
2875  $rlClient->setConfig( $this->getJSVars() );
2876  $rlClient->setModules( $this->getModules( /*filter*/ true ) );
2877  $rlClient->setModuleStyles( $moduleStyles );
2878  $rlClient->setModuleScripts( $this->getModuleScripts( /*filter*/ true ) );
2879  $rlClient->setExemptStates( $exemptStates );
2880  $this->rlClient = $rlClient;
2881  }
2882  return $this->rlClient;
2883  }
2884 
2890  public function headElement( Skin $sk, $includeStyle = true ) {
2892 
2893  $userdir = $this->getLanguage()->getDir();
2894  $sitedir = $wgContLang->getDir();
2895 
2896  $pieces = [];
2897  $pieces[] = Html::htmlHeader( Sanitizer::mergeAttributes(
2898  $this->getRlClient()->getDocumentAttributes(),
2900  ) );
2901  $pieces[] = Html::openElement( 'head' );
2902 
2903  if ( $this->getHTMLTitle() == '' ) {
2904  $this->setHTMLTitle( $this->msg( 'pagetitle', $this->getPageTitle() )->inContentLanguage() );
2905  }
2906 
2907  if ( !Html::isXmlMimeType( $this->getConfig()->get( 'MimeType' ) ) ) {
2908  // Add <meta charset="UTF-8">
2909  // This should be before <title> since it defines the charset used by
2910  // text including the text inside <title>.
2911  // The spec recommends defining XHTML5's charset using the XML declaration
2912  // instead of meta.
2913  // Our XML declaration is output by Html::htmlHeader.
2914  // https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-content-type
2915  // https://html.spec.whatwg.org/multipage/semantics.html#charset
2916  $pieces[] = Html::element( 'meta', [ 'charset' => 'UTF-8' ] );
2917  }
2918 
2919  $pieces[] = Html::element( 'title', null, $this->getHTMLTitle() );
2920  $pieces[] = $this->getRlClient()->getHeadHtml();
2921  $pieces[] = $this->buildExemptModules();
2922  $pieces = array_merge( $pieces, array_values( $this->getHeadLinksArray() ) );
2923  $pieces = array_merge( $pieces, array_values( $this->mHeadItems ) );
2924  $pieces[] = Html::closeElement( 'head' );
2925 
2926  $bodyClasses = [];
2927  $bodyClasses[] = 'mediawiki';
2928 
2929  # Classes for LTR/RTL directionality support
2930  $bodyClasses[] = $userdir;
2931  $bodyClasses[] = "sitedir-$sitedir";
2932 
2933  $underline = $this->getUser()->getOption( 'underline' );
2934  if ( $underline < 2 ) {
2935  // The following classes can be used here:
2936  // * mw-underline-always
2937  // * mw-underline-never
2938  $bodyClasses[] = 'mw-underline-' . ( $underline ? 'always' : 'never' );
2939  }
2940 
2941  if ( $this->getLanguage()->capitalizeAllNouns() ) {
2942  # A <body> class is probably not the best way to do this . . .
2943  $bodyClasses[] = 'capitalize-all-nouns';
2944  }
2945 
2946  // Parser feature migration class
2947  // The idea is that this will eventually be removed, after the wikitext
2948  // which requires it is cleaned up.
2949  $bodyClasses[] = 'mw-hide-empty-elt';
2950 
2951  $bodyClasses[] = $sk->getPageClasses( $this->getTitle() );
2952  $bodyClasses[] = 'skin-' . Sanitizer::escapeClass( $sk->getSkinName() );
2953  $bodyClasses[] =
2954  'action-' . Sanitizer::escapeClass( Action::getActionName( $this->getContext() ) );
2955 
2956  $bodyAttrs = [];
2957  // While the implode() is not strictly needed, it's used for backwards compatibility
2958  // (this used to be built as a string and hooks likely still expect that).
2959  $bodyAttrs['class'] = implode( ' ', $bodyClasses );
2960 
2961  // Allow skins and extensions to add body attributes they need
2962  $sk->addToBodyAttributes( $this, $bodyAttrs );
2963  Hooks::run( 'OutputPageBodyAttributes', [ $this, $sk, &$bodyAttrs ] );
2964 
2965  $pieces[] = Html::openElement( 'body', $bodyAttrs );
2966 
2967  return self::combineWrappedStrings( $pieces );
2968  }
2969 
2975  public function getResourceLoader() {
2976  if ( is_null( $this->mResourceLoader ) ) {
2977  $this->mResourceLoader = new ResourceLoader(
2978  $this->getConfig(),
2979  LoggerFactory::getInstance( 'resourceloader' )
2980  );
2981  }
2982  return $this->mResourceLoader;
2983  }
2984 
2993  public function makeResourceLoaderLink( $modules, $only, array $extraQuery = [] ) {
2994  // Apply 'target' and 'origin' filters
2995  $modules = $this->filterModules( (array)$modules, null, $only );
2996 
2998  $this->getRlClientContext(),
2999  $modules,
3000  $only,
3001  $extraQuery
3002  );
3003  }
3004 
3011  protected static function combineWrappedStrings( array $chunks ) {
3012  // Filter out empty values
3013  $chunks = array_filter( $chunks, 'strlen' );
3014  return WrappedString::join( "\n", $chunks );
3015  }
3016 
3017  private function isUserJsPreview() {
3018  return $this->getConfig()->get( 'AllowUserJs' )
3019  && $this->getTitle()
3020  && $this->getTitle()->isJsSubpage()
3021  && $this->userCanPreview();
3022  }
3023 
3024  private function isUserCssPreview() {
3025  return $this->getConfig()->get( 'AllowUserCss' )
3026  && $this->getTitle()
3027  && $this->getTitle()->isCssSubpage()
3028  && $this->userCanPreview();
3029  }
3030 
3037  public function getBottomScripts() {
3038  $chunks = [];
3039  $chunks[] = $this->getRlClient()->getBodyHtml();
3040 
3041  // Legacy non-ResourceLoader scripts
3042  $chunks[] = $this->mScripts;
3043 
3044  // Exempt 'user' module
3045  // - May need excludepages for live preview. (T28283)
3046  // - Must use TYPE_COMBINED so its response is handled by mw.loader.implement() which
3047  // ensures execution is scheduled after the "site" module.
3048  // - Don't load if module state is already resolved as "ready".
3049  if ( $this->rlUserModuleState === 'loading' ) {
3050  if ( $this->isUserJsPreview() ) {
3051  $chunks[] = $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_COMBINED,
3052  [ 'excludepage' => $this->getTitle()->getPrefixedDBkey() ]
3053  );
3054  $chunks[] = ResourceLoader::makeInlineScript(
3055  Xml::encodeJsCall( 'mw.loader.using', [
3056  [ 'user', 'site' ],
3057  new XmlJsCode(
3058  'function () {'
3059  . Xml::encodeJsCall( '$.globalEval', [
3060  $this->getRequest()->getText( 'wpTextbox1' )
3061  ] )
3062  . '}'
3063  )
3064  ] )
3065  );
3066  // FIXME: If the user is previewing, say, ./vector.js, his ./common.js will be loaded
3067  // asynchronously and may arrive *after* the inline script here. So the previewed code
3068  // may execute before ./common.js runs. Normally, ./common.js runs before ./vector.js.
3069  // Similarly, when previewing ./common.js and the user module does arrive first,
3070  // it will arrive without common.js and the inline script runs after.
3071  // Thus running common after the excluded subpage.
3072  } else {
3073  // Load normally
3074  $chunks[] = $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_COMBINED );
3075  }
3076  }
3077 
3078  if ( $this->limitReportJSData ) {
3079  $chunks[] = ResourceLoader::makeInlineScript(
3080  ResourceLoader::makeConfigSetScript(
3081  [ 'wgPageParseReport' => $this->limitReportJSData ]
3082  )
3083  );
3084  }
3085 
3086  return self::combineWrappedStrings( $chunks );
3087  }
3088 
3095  public function getJsConfigVars() {
3096  return $this->mJsConfigVars;
3097  }
3098 
3105  public function addJsConfigVars( $keys, $value = null ) {
3106  if ( is_array( $keys ) ) {
3107  foreach ( $keys as $key => $value ) {
3108  $this->mJsConfigVars[$key] = $value;
3109  }
3110  return;
3111  }
3112 
3113  $this->mJsConfigVars[$keys] = $value;
3114  }
3115 
3125  public function getJSVars() {
3127 
3128  $curRevisionId = 0;
3129  $articleId = 0;
3130  $canonicalSpecialPageName = false; # T23115
3131 
3132  $title = $this->getTitle();
3133  $ns = $title->getNamespace();
3134  $canonicalNamespace = MWNamespace::exists( $ns )
3136  : $title->getNsText();
3137 
3138  $sk = $this->getSkin();
3139  // Get the relevant title so that AJAX features can use the correct page name
3140  // when making API requests from certain special pages (T36972).
3141  $relevantTitle = $sk->getRelevantTitle();
3142  $relevantUser = $sk->getRelevantUser();
3143 
3144  if ( $ns == NS_SPECIAL ) {
3145  list( $canonicalSpecialPageName, /*...*/ ) =
3147  } elseif ( $this->canUseWikiPage() ) {
3148  $wikiPage = $this->getWikiPage();
3149  $curRevisionId = $wikiPage->getLatest();
3150  $articleId = $wikiPage->getId();
3151  }
3152 
3153  $lang = $title->getPageViewLanguage();
3154 
3155  // Pre-process information
3156  $separatorTransTable = $lang->separatorTransformTable();
3157  $separatorTransTable = $separatorTransTable ? $separatorTransTable : [];
3158  $compactSeparatorTransTable = [
3159  implode( "\t", array_keys( $separatorTransTable ) ),
3160  implode( "\t", $separatorTransTable ),
3161  ];
3162  $digitTransTable = $lang->digitTransformTable();
3163  $digitTransTable = $digitTransTable ? $digitTransTable : [];
3164  $compactDigitTransTable = [
3165  implode( "\t", array_keys( $digitTransTable ) ),
3166  implode( "\t", $digitTransTable ),
3167  ];
3168 
3169  $user = $this->getUser();
3170 
3171  $vars = [
3172  'wgCanonicalNamespace' => $canonicalNamespace,
3173  'wgCanonicalSpecialPageName' => $canonicalSpecialPageName,
3174  'wgNamespaceNumber' => $title->getNamespace(),
3175  'wgPageName' => $title->getPrefixedDBkey(),
3176  'wgTitle' => $title->getText(),
3177  'wgCurRevisionId' => $curRevisionId,
3178  'wgRevisionId' => (int)$this->getRevisionId(),
3179  'wgArticleId' => $articleId,
3180  'wgIsArticle' => $this->isArticle(),
3181  'wgIsRedirect' => $title->isRedirect(),
3182  'wgAction' => Action::getActionName( $this->getContext() ),
3183  'wgUserName' => $user->isAnon() ? null : $user->getName(),
3184  'wgUserGroups' => $user->getEffectiveGroups(),
3185  'wgCategories' => $this->getCategories(),
3186  'wgBreakFrames' => $this->getFrameOptions() == 'DENY',
3187  'wgPageContentLanguage' => $lang->getCode(),
3188  'wgPageContentModel' => $title->getContentModel(),
3189  'wgSeparatorTransformTable' => $compactSeparatorTransTable,
3190  'wgDigitTransformTable' => $compactDigitTransTable,
3191  'wgDefaultDateFormat' => $lang->getDefaultDateFormat(),
3192  'wgMonthNames' => $lang->getMonthNamesArray(),
3193  'wgMonthNamesShort' => $lang->getMonthAbbreviationsArray(),
3194  'wgRelevantPageName' => $relevantTitle->getPrefixedDBkey(),
3195  'wgRelevantArticleId' => $relevantTitle->getArticleID(),
3196  'wgRequestId' => WebRequest::getRequestId(),
3197  ];
3198 
3199  if ( $user->isLoggedIn() ) {
3200  $vars['wgUserId'] = $user->getId();
3201  $vars['wgUserEditCount'] = $user->getEditCount();
3202  $userReg = $user->getRegistration();
3203  $vars['wgUserRegistration'] = $userReg ? wfTimestamp( TS_UNIX, $userReg ) * 1000 : null;
3204  // Get the revision ID of the oldest new message on the user's talk
3205  // page. This can be used for constructing new message alerts on
3206  // the client side.
3207  $vars['wgUserNewMsgRevisionId'] = $user->getNewMessageRevisionId();
3208  }
3209 
3210  if ( $wgContLang->hasVariants() ) {
3211  $vars['wgUserVariant'] = $wgContLang->getPreferredVariant();
3212  }
3213  // Same test as SkinTemplate
3214  $vars['wgIsProbablyEditable'] = $title->quickUserCan( 'edit', $user )
3215  && ( $title->exists() || $title->quickUserCan( 'create', $user ) );
3216 
3217  foreach ( $title->getRestrictionTypes() as $type ) {
3218  $vars['wgRestriction' . ucfirst( $type )] = $title->getRestrictions( $type );
3219  }
3220 
3221  if ( $title->isMainPage() ) {
3222  $vars['wgIsMainPage'] = true;
3223  }
3224 
3225  if ( $this->mRedirectedFrom ) {
3226  $vars['wgRedirectedFrom'] = $this->mRedirectedFrom->getPrefixedDBkey();
3227  }
3228 
3229  if ( $relevantUser ) {
3230  $vars['wgRelevantUserName'] = $relevantUser->getName();
3231  }
3232 
3233  // Allow extensions to add their custom variables to the mw.config map.
3234  // Use the 'ResourceLoaderGetConfigVars' hook if the variable is not
3235  // page-dependant but site-wide (without state).
3236  // Alternatively, you may want to use OutputPage->addJsConfigVars() instead.
3237  Hooks::run( 'MakeGlobalVariablesScript', [ &$vars, $this ] );
3238 
3239  // Merge in variables from addJsConfigVars last
3240  return array_merge( $vars, $this->getJsConfigVars() );
3241  }
3242 
3252  public function userCanPreview() {
3253  $request = $this->getRequest();
3254  if (
3255  $request->getVal( 'action' ) !== 'submit' ||
3256  !$request->getCheck( 'wpPreview' ) ||
3257  !$request->wasPosted()
3258  ) {
3259  return false;
3260  }
3261 
3262  $user = $this->getUser();
3263 
3264  if ( !$user->isLoggedIn() ) {
3265  // Anons have predictable edit tokens
3266  return false;
3267  }
3268  if ( !$user->matchEditToken( $request->getVal( 'wpEditToken' ) ) ) {
3269  return false;
3270  }
3271 
3272  $title = $this->getTitle();
3273  if ( !$title->isJsSubpage() && !$title->isCssSubpage() ) {
3274  return false;
3275  }
3276  if ( !$title->isSubpageOf( $user->getUserPage() ) ) {
3277  // Don't execute another user's CSS or JS on preview (T85855)
3278  return false;
3279  }
3280 
3281  $errors = $title->getUserPermissionsErrors( 'edit', $user );
3282  if ( count( $errors ) !== 0 ) {
3283  return false;
3284  }
3285 
3286  return true;
3287  }
3288 
3292  public function getHeadLinksArray() {
3294 
3295  $tags = [];
3296  $config = $this->getConfig();
3297 
3298  $canonicalUrl = $this->mCanonicalUrl;
3299 
3300  $tags['meta-generator'] = Html::element( 'meta', [
3301  'name' => 'generator',
3302  'content' => "MediaWiki $wgVersion",
3303  ] );
3304 
3305  if ( $config->get( 'ReferrerPolicy' ) !== false ) {
3306  $tags['meta-referrer'] = Html::element( 'meta', [
3307  'name' => 'referrer',
3308  'content' => $config->get( 'ReferrerPolicy' )
3309  ] );
3310  }
3311 
3312  $p = "{$this->mIndexPolicy},{$this->mFollowPolicy}";
3313  if ( $p !== 'index,follow' ) {
3314  // http://www.robotstxt.org/wc/meta-user.html
3315  // Only show if it's different from the default robots policy
3316  $tags['meta-robots'] = Html::element( 'meta', [
3317  'name' => 'robots',
3318  'content' => $p,
3319  ] );
3320  }
3321 
3322  foreach ( $this->mMetatags as $tag ) {
3323  if ( strncasecmp( $tag[0], 'http:', 5 ) === 0 ) {
3324  $a = 'http-equiv';
3325  $tag[0] = substr( $tag[0], 5 );
3326  } elseif ( strncasecmp( $tag[0], 'og:', 3 ) === 0 ) {
3327  $a = 'property';
3328  } else {
3329  $a = 'name';
3330  }
3331  $tagName = "meta-{$tag[0]}";
3332  if ( isset( $tags[$tagName] ) ) {
3333  $tagName .= $tag[1];
3334  }
3335  $tags[$tagName] = Html::element( 'meta',
3336  [
3337  $a => $tag[0],
3338  'content' => $tag[1]
3339  ]
3340  );
3341  }
3342 
3343  foreach ( $this->mLinktags as $tag ) {
3344  $tags[] = Html::element( 'link', $tag );
3345  }
3346 
3347  # Universal edit button
3348  if ( $config->get( 'UniversalEditButton' ) && $this->isArticleRelated() ) {
3349  $user = $this->getUser();
3350  if ( $this->getTitle()->quickUserCan( 'edit', $user )
3351  && ( $this->getTitle()->exists() ||
3352  $this->getTitle()->quickUserCan( 'create', $user ) )
3353  ) {
3354  // Original UniversalEditButton
3355  $msg = $this->msg( 'edit' )->text();
3356  $tags['universal-edit-button'] = Html::element( 'link', [
3357  'rel' => 'alternate',
3358  'type' => 'application/x-wiki',
3359  'title' => $msg,
3360  'href' => $this->getTitle()->getEditURL(),
3361  ] );
3362  // Alternate edit link
3363  $tags['alternative-edit'] = Html::element( 'link', [
3364  'rel' => 'edit',
3365  'title' => $msg,
3366  'href' => $this->getTitle()->getEditURL(),
3367  ] );
3368  }
3369  }
3370 
3371  # Generally the order of the favicon and apple-touch-icon links
3372  # should not matter, but Konqueror (3.5.9 at least) incorrectly
3373  # uses whichever one appears later in the HTML source. Make sure
3374  # apple-touch-icon is specified first to avoid this.
3375  if ( $config->get( 'AppleTouchIcon' ) !== false ) {
3376  $tags['apple-touch-icon'] = Html::element( 'link', [
3377  'rel' => 'apple-touch-icon',
3378  'href' => $config->get( 'AppleTouchIcon' )
3379  ] );
3380  }
3381 
3382  if ( $config->get( 'Favicon' ) !== false ) {
3383  $tags['favicon'] = Html::element( 'link', [
3384  'rel' => 'shortcut icon',
3385  'href' => $config->get( 'Favicon' )
3386  ] );
3387  }
3388 
3389  # OpenSearch description link
3390  $tags['opensearch'] = Html::element( 'link', [
3391  'rel' => 'search',
3392  'type' => 'application/opensearchdescription+xml',
3393  'href' => wfScript( 'opensearch_desc' ),
3394  'title' => $this->msg( 'opensearch-desc' )->inContentLanguage()->text(),
3395  ] );
3396 
3397  if ( $config->get( 'EnableAPI' ) ) {
3398  # Real Simple Discovery link, provides auto-discovery information
3399  # for the MediaWiki API (and potentially additional custom API
3400  # support such as WordPress or Twitter-compatible APIs for a
3401  # blogging extension, etc)
3402  $tags['rsd'] = Html::element( 'link', [
3403  'rel' => 'EditURI',
3404  'type' => 'application/rsd+xml',
3405  // Output a protocol-relative URL here if $wgServer is protocol-relative.
3406  // Whether RSD accepts relative or protocol-relative URLs is completely
3407  // undocumented, though.
3408  'href' => wfExpandUrl( wfAppendQuery(
3409  wfScript( 'api' ),
3410  [ 'action' => 'rsd' ] ),
3412  ),
3413  ] );
3414  }
3415 
3416  # Language variants
3417  if ( !$config->get( 'DisableLangConversion' ) ) {
3418  $lang = $this->getTitle()->getPageLanguage();
3419  if ( $lang->hasVariants() ) {
3420  $variants = $lang->getVariants();
3421  foreach ( $variants as $variant ) {
3422  $tags["variant-$variant"] = Html::element( 'link', [
3423  'rel' => 'alternate',
3424  'hreflang' => wfBCP47( $variant ),
3425  'href' => $this->getTitle()->getLocalURL(
3426  [ 'variant' => $variant ] )
3427  ]
3428  );
3429  }
3430  # x-default link per https://support.google.com/webmasters/answer/189077?hl=en
3431  $tags["variant-x-default"] = Html::element( 'link', [
3432  'rel' => 'alternate',
3433  'hreflang' => 'x-default',
3434  'href' => $this->getTitle()->getLocalURL() ] );
3435  }
3436  }
3437 
3438  # Copyright
3439  if ( $this->copyrightUrl !== null ) {
3440  $copyright = $this->copyrightUrl;
3441  } else {
3442  $copyright = '';
3443  if ( $config->get( 'RightsPage' ) ) {
3444  $copy = Title::newFromText( $config->get( 'RightsPage' ) );
3445 
3446  if ( $copy ) {
3447  $copyright = $copy->getLocalURL();
3448  }
3449  }
3450 
3451  if ( !$copyright && $config->get( 'RightsUrl' ) ) {
3452  $copyright = $config->get( 'RightsUrl' );
3453  }
3454  }
3455 
3456  if ( $copyright ) {
3457  $tags['copyright'] = Html::element( 'link', [
3458  'rel' => 'copyright',
3459  'href' => $copyright ]
3460  );
3461  }
3462 
3463  # Feeds
3464  if ( $config->get( 'Feed' ) ) {
3465  $feedLinks = [];
3466 
3467  foreach ( $this->getSyndicationLinks() as $format => $link ) {
3468  # Use the page name for the title. In principle, this could
3469  # lead to issues with having the same name for different feeds
3470  # corresponding to the same page, but we can't avoid that at
3471  # this low a level.
3472 
3473  $feedLinks[] = $this->feedLink(
3474  $format,
3475  $link,
3476  # Used messages: 'page-rss-feed' and 'page-atom-feed' (for an easier grep)
3477  $this->msg(
3478  "page-{$format}-feed", $this->getTitle()->getPrefixedText()
3479  )->text()
3480  );
3481  }
3482 
3483  # Recent changes feed should appear on every page (except recentchanges,
3484  # that would be redundant). Put it after the per-page feed to avoid
3485  # changing existing behavior. It's still available, probably via a
3486  # menu in your browser. Some sites might have a different feed they'd
3487  # like to promote instead of the RC feed (maybe like a "Recent New Articles"
3488  # or "Breaking news" one). For this, we see if $wgOverrideSiteFeed is defined.
3489  # If so, use it instead.
3490  $sitename = $config->get( 'Sitename' );
3491  if ( $config->get( 'OverrideSiteFeed' ) ) {
3492  foreach ( $config->get( 'OverrideSiteFeed' ) as $type => $feedUrl ) {
3493  // Note, this->feedLink escapes the url.
3494  $feedLinks[] = $this->feedLink(
3495  $type,
3496  $feedUrl,
3497  $this->msg( "site-{$type}-feed", $sitename )->text()
3498  );
3499  }
3500  } elseif ( !$this->getTitle()->isSpecial( 'Recentchanges' ) ) {
3501  $rctitle = SpecialPage::getTitleFor( 'Recentchanges' );
3502  foreach ( $config->get( 'AdvertisedFeedTypes' ) as $format ) {
3503  $feedLinks[] = $this->feedLink(
3504  $format,
3505  $rctitle->getLocalURL( [ 'feed' => $format ] ),
3506  # For grep: 'site-rss-feed', 'site-atom-feed'
3507  $this->msg( "site-{$format}-feed", $sitename )->text()
3508  );
3509  }
3510  }
3511 
3512  # Allow extensions to change the list pf feeds. This hook is primarily for changing,
3513  # manipulating or removing existing feed tags. If you want to add new feeds, you should
3514  # use OutputPage::addFeedLink() instead.
3515  Hooks::run( 'AfterBuildFeedLinks', [ &$feedLinks ] );
3516 
3517  $tags += $feedLinks;
3518  }
3519 
3520  # Canonical URL
3521  if ( $config->get( 'EnableCanonicalServerLink' ) ) {
3522  if ( $canonicalUrl !== false ) {
3523  $canonicalUrl = wfExpandUrl( $canonicalUrl, PROTO_CANONICAL );
3524  } else {
3525  if ( $this->isArticleRelated() ) {
3526  // This affects all requests where "setArticleRelated" is true. This is
3527  // typically all requests that show content (query title, curid, oldid, diff),
3528  // and all wikipage actions (edit, delete, purge, info, history etc.).
3529  // It does not apply to File pages and Special pages.
3530  // 'history' and 'info' actions address page metadata rather than the page
3531  // content itself, so they may not be canonicalized to the view page url.
3532  // TODO: this ought to be better encapsulated in the Action class.
3533  $action = Action::getActionName( $this->getContext() );
3534  if ( in_array( $action, [ 'history', 'info' ] ) ) {
3535  $query = "action={$action}";
3536  } else {
3537  $query = '';
3538  }
3539  $canonicalUrl = $this->getTitle()->getCanonicalURL( $query );
3540  } else {
3541  $reqUrl = $this->getRequest()->getRequestURL();
3542  $canonicalUrl = wfExpandUrl( $reqUrl, PROTO_CANONICAL );
3543  }
3544  }
3545  }
3546  if ( $canonicalUrl !== false ) {
3547  $tags[] = Html::element( 'link', [
3548  'rel' => 'canonical',
3549  'href' => $canonicalUrl
3550  ] );
3551  }
3552 
3553  return $tags;
3554  }
3555 
3561  public function getHeadLinks() {
3562  wfDeprecated( __METHOD__, '1.24' );
3563  return implode( "\n", $this->getHeadLinksArray() );
3564  }
3565 
3574  private function feedLink( $type, $url, $text ) {
3575  return Html::element( 'link', [
3576  'rel' => 'alternate',
3577  'type' => "application/$type+xml",
3578  'title' => $text,
3579  'href' => $url ]
3580  );
3581  }
3582 
3592  public function addStyle( $style, $media = '', $condition = '', $dir = '' ) {
3593  $options = [];
3594  if ( $media ) {
3595  $options['media'] = $media;
3596  }
3597  if ( $condition ) {
3598  $options['condition'] = $condition;
3599  }
3600  if ( $dir ) {
3601  $options['dir'] = $dir;
3602  }
3603  $this->styles[$style] = $options;
3604  }
3605 
3613  public function addInlineStyle( $style_css, $flip = 'noflip' ) {
3614  if ( $flip === 'flip' && $this->getLanguage()->isRTL() ) {
3615  # If wanted, and the interface is right-to-left, flip the CSS
3616  $style_css = CSSJanus::transform( $style_css, true, false );
3617  }
3618  $this->mInlineStyles .= Html::inlineStyle( $style_css );
3619  }
3620 
3626  protected function buildExemptModules() {
3628 
3629  $chunks = [];
3630  // Things that go after the ResourceLoaderDynamicStyles marker
3631  $append = [];
3632 
3633  // Exempt 'user' styles module (may need 'excludepages' for live preview)
3634  if ( $this->isUserCssPreview() ) {
3635  $append[] = $this->makeResourceLoaderLink(
3636  'user.styles',
3638  [ 'excludepage' => $this->getTitle()->getPrefixedDBkey() ]
3639  );
3640 
3641  // Load the previewed CSS. Janus it if needed.
3642  // User-supplied CSS is assumed to in the wiki's content language.
3643  $previewedCSS = $this->getRequest()->getText( 'wpTextbox1' );
3644  if ( $this->getLanguage()->getDir() !== $wgContLang->getDir() ) {
3645  $previewedCSS = CSSJanus::transform( $previewedCSS, true, false );
3646  }
3647  $append[] = Html::inlineStyle( $previewedCSS );
3648  }
3649 
3650  // We want site, private and user styles to override dynamically added styles from
3651  // general modules, but we want dynamically added styles to override statically added
3652  // style modules. So the order has to be:
3653  // - page style modules (formatted by ResourceLoaderClientHtml::getHeadHtml())
3654  // - dynamically loaded styles (added by mw.loader before ResourceLoaderDynamicStyles)
3655  // - ResourceLoaderDynamicStyles marker
3656  // - site/private/user styles
3657 
3658  // Add legacy styles added through addStyle()/addInlineStyle() here
3659  $chunks[] = implode( '', $this->buildCssLinksArray() ) . $this->mInlineStyles;
3660 
3661  $chunks[] = Html::element(
3662  'meta',
3663  [ 'name' => 'ResourceLoaderDynamicStyles', 'content' => '' ]
3664  );
3665 
3666  foreach ( $this->rlExemptStyleModules as $group => $moduleNames ) {
3667  $chunks[] = $this->makeResourceLoaderLink( $moduleNames,
3669  );
3670  }
3671 
3672  return self::combineWrappedStrings( array_merge( $chunks, $append ) );
3673  }
3674 
3678  public function buildCssLinksArray() {
3679  $links = [];
3680 
3681  // Add any extension CSS
3682  foreach ( $this->mExtStyles as $url ) {
3683  $this->addStyle( $url );
3684  }
3685  $this->mExtStyles = [];
3686 
3687  foreach ( $this->styles as $file => $options ) {
3688  $link = $this->styleLink( $file, $options );
3689  if ( $link ) {
3690  $links[$file] = $link;
3691  }
3692  }
3693  return $links;
3694  }
3695 
3703  protected function styleLink( $style, array $options ) {
3704  if ( isset( $options['dir'] ) ) {
3705  if ( $this->getLanguage()->getDir() != $options['dir'] ) {
3706  return '';
3707  }
3708  }
3709 
3710  if ( isset( $options['media'] ) ) {
3711  $media = self::transformCssMedia( $options['media'] );
3712  if ( is_null( $media ) ) {
3713  return '';
3714  }
3715  } else {
3716  $media = 'all';
3717  }
3718 
3719  if ( substr( $style, 0, 1 ) == '/' ||
3720  substr( $style, 0, 5 ) == 'http:' ||
3721  substr( $style, 0, 6 ) == 'https:' ) {
3722  $url = $style;
3723  } else {
3724  $config = $this->getConfig();
3725  $url = $config->get( 'StylePath' ) . '/' . $style . '?' .
3726  $config->get( 'StyleVersion' );
3727  }
3728 
3729  $link = Html::linkedStyle( $url, $media );
3730 
3731  if ( isset( $options['condition'] ) ) {
3732  $condition = htmlspecialchars( $options['condition'] );
3733  $link = "<!--[if $condition]>$link<![endif]-->";
3734  }
3735  return $link;
3736  }
3737 
3759  public static function transformResourcePath( Config $config, $path ) {
3760  global $IP;
3761 
3762  $localDir = $IP;
3763  $remotePathPrefix = $config->get( 'ResourceBasePath' );
3764  if ( $remotePathPrefix === '' ) {
3765  // The configured base path is required to be empty string for
3766  // wikis in the domain root
3767  $remotePath = '/';
3768  } else {
3769  $remotePath = $remotePathPrefix;
3770  }
3771  if ( strpos( $path, $remotePath ) !== 0 || substr( $path, 0, 2 ) === '//' ) {
3772  // - Path is outside wgResourceBasePath, ignore.
3773  // - Path is protocol-relative. Fixes T155310. Not supported by RelPath lib.
3774  return $path;
3775  }
3776  // For files in resources, extensions/ or skins/, ResourceBasePath is preferred here.
3777  // For other misc files in $IP, we'll fallback to that as well. There is, however, a fourth
3778  // supported dir/path pair in the configuration (wgUploadDirectory, wgUploadPath)
3779  // which is not expected to be in wgResourceBasePath on CDNs. (T155146)
3780  $uploadPath = $config->get( 'UploadPath' );
3781  if ( strpos( $path, $uploadPath ) === 0 ) {
3782  $localDir = $config->get( 'UploadDirectory' );
3783  $remotePathPrefix = $remotePath = $uploadPath;
3784  }
3785 
3786  $path = RelPath\getRelativePath( $path, $remotePath );
3787  return self::transformFilePath( $remotePathPrefix, $localDir, $path );
3788  }
3789 
3801  public static function transformFilePath( $remotePathPrefix, $localPath, $file ) {
3802  $hash = md5_file( "$localPath/$file" );
3803  if ( $hash === false ) {
3804  wfLogWarning( __METHOD__ . ": Failed to hash $localPath/$file" );
3805  $hash = '';
3806  }
3807  return "$remotePathPrefix/$file?" . substr( $hash, 0, 5 );
3808  }
3809 
3817  public static function transformCssMedia( $media ) {
3819 
3820  // https://www.w3.org/TR/css3-mediaqueries/#syntax
3821  $screenMediaQueryRegex = '/^(?:only\s+)?screen\b/i';
3822 
3823  // Switch in on-screen display for media testing
3824  $switches = [
3825  'printable' => 'print',
3826  'handheld' => 'handheld',
3827  ];
3828  foreach ( $switches as $switch => $targetMedia ) {
3829  if ( $wgRequest->getBool( $switch ) ) {
3830  if ( $media == $targetMedia ) {
3831  $media = '';
3832  } elseif ( preg_match( $screenMediaQueryRegex, $media ) === 1 ) {
3833  /* This regex will not attempt to understand a comma-separated media_query_list
3834  *
3835  * Example supported values for $media:
3836  * 'screen', 'only screen', 'screen and (min-width: 982px)' ),
3837  * Example NOT supported value for $media:
3838  * '3d-glasses, screen, print and resolution > 90dpi'
3839  *
3840  * If it's a print request, we never want any kind of screen stylesheets
3841  * If it's a handheld request (currently the only other choice with a switch),
3842  * we don't want simple 'screen' but we might want screen queries that
3843  * have a max-width or something, so we'll pass all others on and let the
3844  * client do the query.
3845  */
3846  if ( $targetMedia == 'print' || $media == 'screen' ) {
3847  return null;
3848  }
3849  }
3850  }
3851  }
3852 
3853  return $media;
3854  }
3855 
3862  public function addWikiMsg( /*...*/ ) {
3863  $args = func_get_args();
3864  $name = array_shift( $args );
3865  $this->addWikiMsgArray( $name, $args );
3866  }
3867 
3876  public function addWikiMsgArray( $name, $args ) {
3877  $this->addHTML( $this->msg( $name, $args )->parseAsBlock() );
3878  }
3879 
3905  public function wrapWikiMsg( $wrap /*, ...*/ ) {
3906  $msgSpecs = func_get_args();
3907  array_shift( $msgSpecs );
3908  $msgSpecs = array_values( $msgSpecs );
3909  $s = $wrap;
3910  foreach ( $msgSpecs as $n => $spec ) {
3911  if ( is_array( $spec ) ) {
3912  $args = $spec;
3913  $name = array_shift( $args );
3914  if ( isset( $args['options'] ) ) {
3915  unset( $args['options'] );
3916  wfDeprecated(
3917  'Adding "options" to ' . __METHOD__ . ' is no longer supported',
3918  '1.20'
3919  );
3920  }
3921  } else {
3922  $args = [];
3923  $name = $spec;
3924  }
3925  $s = str_replace( '$' . ( $n + 1 ), $this->msg( $name, $args )->plain(), $s );
3926  }
3927  $this->addWikiText( $s );
3928  }
3929 
3935  public function enableTOC( $flag = true ) {
3936  $this->mEnableTOC = $flag;
3937  }
3938 
3943  public function isTOCEnabled() {
3944  return $this->mEnableTOC;
3945  }
3946 
3952  public function enableSectionEditLinks( $flag = true ) {
3953  $this->mEnableSectionEditLinks = $flag;
3954  }
3955 
3960  public function sectionEditLinksEnabled() {
3962  }
3963 
3971  public static function setupOOUI( $skinName = '', $dir = 'ltr' ) {
3972  $themes = ExtensionRegistry::getInstance()->getAttribute( 'SkinOOUIThemes' );
3973  // Make keys (skin names) lowercase for case-insensitive matching.
3974  $themes = array_change_key_case( $themes, CASE_LOWER );
3975  $theme = isset( $themes[$skinName] ) ? $themes[$skinName] : 'MediaWiki';
3976  // For example, 'OOUI\MediaWikiTheme'.
3977  $themeClass = "OOUI\\{$theme}Theme";
3978  OOUI\Theme::setSingleton( new $themeClass() );
3979  OOUI\Element::setDefaultDir( $dir );
3980  }
3981 
3988  public function enableOOUI() {
3990  strtolower( $this->getSkin()->getSkinName() ),
3991  $this->getLanguage()->getDir()
3992  );
3993  $this->addModuleStyles( [
3994  'oojs-ui-core.styles',
3995  'oojs-ui.styles.icons',
3996  'oojs-ui.styles.indicators',
3997  'oojs-ui.styles.textures',
3998  'mediawiki.widgets.styles',
3999  ] );
4000  }
4001 
4007  protected function addLogoPreloadLinkHeaders() {
4008  $logo = ResourceLoaderSkinModule::getLogo( $this->getConfig() );
4009 
4010  $tags = [];
4011  $logosPerDppx = [];
4012  $logos = [];
4013 
4014  if ( !is_array( $logo ) ) {
4015  // No media queries required if we only have one variant
4016  $this->addLinkHeader( '<' . $logo . '>;rel=preload;as=image' );
4017  return;
4018  }
4019 
4020  foreach ( $logo as $dppx => $src ) {
4021  // Keys are in this format: "1.5x"
4022  $dppx = substr( $dppx, 0, -1 );
4023  $logosPerDppx[$dppx] = $src;
4024  }
4025 
4026  // Because PHP can't have floats as array keys
4027  uksort( $logosPerDppx, function ( $a , $b ) {
4028  $a = floatval( $a );
4029  $b = floatval( $b );
4030 
4031  if ( $a == $b ) {
4032  return 0;
4033  }
4034  // Sort from smallest to largest (e.g. 1x, 1.5x, 2x)
4035  return ( $a < $b ) ? -1 : 1;
4036  } );
4037 
4038  foreach ( $logosPerDppx as $dppx => $src ) {
4039  $logos[] = [ 'dppx' => $dppx, 'src' => $src ];
4040  }
4041 
4042  $logosCount = count( $logos );
4043  // Logic must match ResourceLoaderSkinModule:
4044  // - 1x applies to resolution < 1.5dppx
4045  // - 1.5x applies to resolution >= 1.5dppx && < 2dppx
4046  // - 2x applies to resolution >= 2dppx
4047  // Note that min-resolution and max-resolution are both inclusive.
4048  for ( $i = 0; $i < $logosCount; $i++ ) {
4049  if ( $i === 0 ) {
4050  // Smallest dppx
4051  // min-resolution is ">=" (larger than or equal to)
4052  // "not min-resolution" is essentially "<"
4053  $media_query = 'not all and (min-resolution: ' . $logos[ 1 ]['dppx'] . 'dppx)';
4054  } elseif ( $i !== $logosCount - 1 ) {
4055  // In between
4056  // Media query expressions can only apply "not" to the entire expression
4057  // (e.g. can't express ">= 1.5 and not >= 2).
4058  // Workaround: Use <= 1.9999 in place of < 2.
4059  $upper_bound = floatval( $logos[ $i + 1 ]['dppx'] ) - 0.000001;
4060  $media_query = '(min-resolution: ' . $logos[ $i ]['dppx'] .
4061  'dppx) and (max-resolution: ' . $upper_bound . 'dppx)';
4062  } else {
4063  // Largest dppx
4064  $media_query = '(min-resolution: ' . $logos[ $i ]['dppx'] . 'dppx)';
4065  }
4066 
4067  $this->addLinkHeader(
4068  '<' . $logos[$i]['src'] . '>;rel=preload;as=image;media=' . $media_query
4069  );
4070  }
4071  }
4072 }
ReadOnlyError
Show an error when the wiki is locked/read-only and the user tries to do something that requires writ...
Definition: ReadOnlyError.php:28
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:122
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:2213
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:2336
OutputPage\$mCategories
array $mCategories
Definition: OutputPage.php:111
OutputPage\addBacklinkSubtitle
addBacklinkSubtitle(Title $title, $query=[])
Add a subtitle containing a backlink to a page.
Definition: OutputPage.php:1051
OutputPage\$mLastModified
string $mLastModified
Used for sending cache control.
Definition: OutputPage.php:105
ParserOptions
Set options of the Parser.
Definition: ParserOptions.php:33
OutputPage\getCategoryLinks
getCategoryLinks()
Get the list of category links, in a 2-D array with the following format: $arr[$type][] = $link,...
Definition: OutputPage.php:1374
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:374
ContextSource\$context
IContextSource $context
Definition: ContextSource.php:34
ContextSource\getConfig
getConfig()
Get the Config object.
Definition: ContextSource.php:68
OutputPage\getTarget
getTarget()
Definition: OutputPage.php:649
OutputPage\setArticleRelated
setArticleRelated( $v)
Set whether this page is related an article on the wiki Setting false will cause the change of "artic...
Definition: OutputPage.php:1226
ResourceLoaderContext
Object passed around to modules which contains information about the state of a specific loader reque...
Definition: ResourceLoaderContext.php:32
OutputPage\getSubtitle
getSubtitle()
Get the subtitle.
Definition: OutputPage.php:1067
FauxRequest
WebRequest clone which takes values from a provided array.
Definition: FauxRequest.php:33
OutputPage\enableClientCache
enableClientCache( $state)
Use enableClientCache(false) to force it to send nocache headers.
Definition: OutputPage.php:2034
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:265
$template
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping $template
Definition: hooks.txt:783
OutputPage\addWikiMsg
addWikiMsg()
Add a wikitext-formatted message to the output.
Definition: OutputPage.php:3862
ContextSource\getContext
getContext()
Get the base IContextSource object.
Definition: ContextSource.php:41
OutputPage\getLanguageLinks
getLanguageLinks()
Get the list of language links.
Definition: OutputPage.php:1267
OutputPage\buildBacklinkSubtitle
static buildBacklinkSubtitle(Title $title, $query=[])
Build message object for a subtitle containing a backlink to a page.
Definition: OutputPage.php:1036
HtmlArmor
Marks HTML that shouldn't be escaped.
Definition: HtmlArmor.php:28
ResourceLoaderClientHtml
Bootstrap a ResourceLoader client on an HTML page.
Definition: ResourceLoaderClientHtml.php:28
OutputPage\reduceAllowedModules
reduceAllowedModules( $type, $level)
Limit the highest level of CSS/JS untrustworthiness allowed.
Definition: OutputPage.php:1512
PROTO_CANONICAL
const PROTO_CANONICAL
Definition: Defines.php:221
wfBCP47
wfBCP47( $code)
Get the normalised IETF language tag See unit test for examples.
Definition: GlobalFunctions.php:3370
$request
error also a ContextSource you ll probably need to make sure the header is varied on $request
Definition: hooks.txt:2612
OutputPage\$mModuleStyles
array $mModuleStyles
Definition: OutputPage.php:149
OutputPage\addSubtitle
addSubtitle( $str)
Add $str to the subtitle.
Definition: OutputPage.php:1020
OutputPage\addAcceptLanguage
addAcceptLanguage()
T23672: Add Accept-Language to Vary and Key headers if there's no 'variant' parameter existed in GET.
Definition: OutputPage.php:2174
OutputPage\$mEnableSectionEditLinks
bool $mEnableSectionEditLinks
Whether parser output should contain section edit links.
Definition: OutputPage.php:295
false
processing should stop and the error should be shown to the user * false
Definition: hooks.txt:189
Article\formatRobotPolicy
static formatRobotPolicy( $policy)
Converts a String robot policy into an associative array, to allow merging of several policies using ...
Definition: Article.php:805
OutputPage\getJSVars
getJSVars()
Get an array containing the variables to be set in mw.config in JavaScript.
Definition: OutputPage.php:3125
OutputPage\showFileRenameError
showFileRenameError( $old, $new)
Definition: OutputPage.php:2714
OutputPage\getRlClientContext
getRlClientContext()
Definition: OutputPage.php:2777
OutputPage\$mRedirectedFrom
Title $mRedirectedFrom
If the current page was reached through a redirect, $mRedirectedFrom contains the Title of the redire...
Definition: OutputPage.php:275
$wgParser
$wgParser
Definition: Setup.php:796
OutputPage\setTitle
setTitle(Title $t)
Set the Title object to use.
Definition: OutputPage.php:1001
ResourceLoaderModule\TYPE_COMBINED
const TYPE_COMBINED
Definition: ResourceLoaderModule.php:38
ContextSource\msg
msg()
Get a Message object with context set Parameters are the same as wfMessage()
Definition: ContextSource.php:187
LinkBatch
Class representing a list of titles The execute() method checks them all for existence and adds them ...
Definition: LinkBatch.php:34
OutputPage\addLink
addLink(array $linkarr)
Add a new <link> tag to the page header.
Definition: OutputPage.php:395
OutputPage\addCategoryLinksToLBAndGetResult
addCategoryLinksToLBAndGetResult(array $categories)
Definition: OutputPage.php:1326
OutputPage\hasHeadItem
hasHeadItem( $name)
Check if the header item $name is already set.
Definition: OutputPage.php:703
OutputPage\__construct
__construct(IContextSource $context=null)
Constructor for OutputPage.
Definition: OutputPage.php:316
OutputPage\$mCanonicalUrl
bool $mCanonicalUrl
Definition: OutputPage.php:52
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:33
OutputPage\getMetaTags
getMetaTags()
Returns the current <meta> tags.
Definition: OutputPage.php:384
OutputPage\addLanguageLinks
addLanguageLinks(array $newLinkArray)
Add new language links.
Definition: OutputPage.php:1248
OutputPage\addLinkHeader
addLinkHeader( $header)
Add an HTTP Link: header.
Definition: OutputPage.php:2118
OutputPage\addModuleStyles
addModuleStyles( $modules)
Add only CSS of one or more modules recognized by ResourceLoader.
Definition: OutputPage.php:642
OutputPage\$mNewSectionLink
bool $mNewSectionLink
Definition: OutputPage.php:217
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:1713
OutputPage\isArticleRelated
isArticleRelated()
Return whether this page is related an article on the wiki.
Definition: OutputPage.php:1238
captcha-old.count
count
Definition: captcha-old.py:225
OutputPage\enableSectionEditLinks
enableSectionEditLinks( $flag=true)
Enables/disables section edit links, doesn't override NOEDITSECTION
Definition: OutputPage.php:3952
ResourceLoaderModule\ORIGIN_USER_SITEWIDE
const ORIGIN_USER_SITEWIDE
Definition: ResourceLoaderModule.php:54
OutputPage\setArticleBodyOnly
setArticleBodyOnly( $only)
Set whether the output should only contain the body of the article, without any skin,...
Definition: OutputPage.php:721
OutputPage\getFrameOptions
getFrameOptions()
Get the X-Frame-Options header value (without the name part), or false if there isn't one.
Definition: OutputPage.php:2243
text
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add text
Definition: design.txt:12
OutputPage\$mRedirectCode
string $mRedirectCode
Definition: OutputPage.php:176
OutputPage\getRevisionId
getRevisionId()
Get the displayed revision ID.
Definition: OutputPage.php:1629
ResourceLoaderClientHtml\setModuleScripts
setModuleScripts(array $modules)
Ensure the scripts of one or more modules are loaded.
Definition: ResourceLoaderClientHtml.php:103
OutputPage\addWikiTextTitleTidy
addWikiTextTitleTidy( $text, &$title, $linestart=true)
Add wikitext with a custom Title object and tidy enabled.
Definition: OutputPage.php:1732
OutputPage\clearHTML
clearHTML()
Clear the body HTML.
Definition: OutputPage.php:1550
Title\newMainPage
static newMainPage()
Create a new Title for the Main Page.
Definition: Title.php:559
OutputPage\addScript
addScript( $script)
Add raw HTML to the list of scripts (including <script> tag, etc.) Internal use only.
Definition: OutputPage.php:464
OutputPage\$mIsarticle
bool $mIsarticle
Is the displayed content related to the source of the corresponding wiki article.
Definition: OutputPage.php:78
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1994
$wgVersion
$wgVersion
MediaWiki version number.
Definition: DefaultSettings.php:78
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:2750
OutputPage\buildCssLinksArray
buildCssLinksArray()
Definition: OutputPage.php:3678
OutputPage\combineWrappedStrings
static combineWrappedStrings(array $chunks)
Combine WrappedString chunks and filter out empty ones.
Definition: OutputPage.php:3011
OutputPage\setupOOUI
static setupOOUI( $skinName='', $dir='ltr')
Helper function to setup the PHP implementation of OOUI to use in this request.
Definition: OutputPage.php:3971
OutputPage\setPageTitleActionText
setPageTitleActionText( $text)
Set the new value of the "action text", this will be added to the "HTML title", separated from it wit...
Definition: OutputPage.php:915
OutputPage\$mHideNewSectionLink
bool $mHideNewSectionLink
Definition: OutputPage.php:220
OutputPage\$mBodytext
string $mBodytext
Contains all of the "<body>" content.
Definition: OutputPage.php:69
use
as see the revision history and available at free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to use
Definition: MIT-LICENSE.txt:10
wfUrlencode
wfUrlencode( $s)
We want some things to be included as literal characters in our title URLs for prettiness,...
Definition: GlobalFunctions.php:371
$user
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a account $user
Definition: hooks.txt:246
OutputPage\getBottomScripts
getBottomScripts()
JS stuff to put at the bottom of the <body>.
Definition: OutputPage.php:3037
OutputPage\addParserOutputContent
addParserOutputContent( $parserOutput)
Add the HTML and enhancements for it (like ResourceLoader modules) associated with a ParserOutput obj...
Definition: OutputPage.php:1862
OutputPage\showFileNotFoundError
showFileNotFoundError( $name)
Definition: OutputPage.php:2722
OutputPage\$mPagetitle
string $mPagetitle
Should be private - has getter and setter.
Definition: OutputPage.php:63
ParserOptions\newFromAnon
static newFromAnon()
Get a ParserOptions object for an anonymous user.
Definition: ParserOptions.php:693
OutputPage\addHeadItems
addHeadItems( $values)
Add one or more head items to the output.
Definition: OutputPage.php:693
OutputPage\getModuleStyles
getModuleStyles( $filter=false, $position=null)
Get the list of module CSS to include on this page.
Definition: OutputPage.php:627
$params
$params
Definition: styleTest.css.php:40
Html\htmlHeader
static htmlHeader(array $attribs=[])
Constructs the opening html-tag with necessary doctypes depending on global variables.
Definition: Html.php:907
OutputPage\getHeadLinks
getHeadLinks()
Definition: OutputPage.php:3561
Skin\addToBodyAttributes
addToBodyAttributes( $out, &$bodyAttrs)
This will be called by OutputPage::headElement when it is creating the "<body>" tag,...
Definition: Skin.php:434
OutputPage\versionRequired
versionRequired( $version)
Display an error page indicating that a given version of MediaWiki is required to use it.
Definition: OutputPage.php:2605
ResourceLoaderClientHtml\setExemptStates
setExemptStates(array $states)
Set state of special modules that are handled by the caller manually.
Definition: ResourceLoaderClientHtml.php:114
OutputPage\parseInline
parseInline( $text, $linestart=true, $interface=false)
Parse wikitext, strip paragraphs, and return the HTML.
Definition: OutputPage.php:1964
OutputPage\addScriptFile
addScriptFile( $file, $version=null)
Add a JavaScript file out of skins/common, or a given relative path.
Definition: OutputPage.php:501
$s
$s
Definition: mergeMessageFileList.php:188
$linkRenderer
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses after processing after in associative array form before processing starts Return false to skip default processing and return $ret $linkRenderer
Definition: hooks.txt:1956
OutputPage\parserOptions
parserOptions( $options=null)
Get/set the ParserOptions object to use for wikitext parsing.
Definition: OutputPage.php:1570
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:82
OutputPage\getFileVersion
getFileVersion()
Get the displayed file version.
Definition: OutputPage.php:1673
OutputPage\getSyndicationLinks
getSyndicationLinks()
Return URLs for each supported syndication format for this page.
Definition: OutputPage.php:1183
OutputPage\$mVaryHeader
$mVaryHeader
Definition: OutputPage.php:265
ContextSource\canUseWikiPage
canUseWikiPage()
Check whether a WikiPage object can be get with getWikiPage().
Definition: ContextSource.php:100
wfLogWarning
wfLogWarning( $msg, $callerOffset=1, $level=E_USER_WARNING)
Send a warning as a PHP error and the debug log.
Definition: GlobalFunctions.php:1155
$res
$res
Definition: database.txt:21
$name
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:304
ContextSource\getRequest
getRequest()
Get the WebRequest object.
Definition: ContextSource.php:78
IExpiringStore\TTL_MINUTE
const TTL_MINUTE
Definition: IExpiringStore.php:33
OutputPage\addParserOutput
addParserOutput( $parserOutput)
Add everything from a ParserOutput object.
Definition: OutputPage.php:1891
OutputPage\$mRevisionId
int $mRevisionId
To include the variable {{REVISIONID}}.
Definition: OutputPage.php:245
User\groupHasPermission
static groupHasPermission( $group, $role)
Check, if the given group has the given permission.
Definition: User.php:4766
$type
do that in ParserLimitReportFormat instead use this to modify the parameters of the image and a DIV can begin in one section and end in another Make sure your code can handle that case gracefully See the EditSectionClearerLink extension for an example zero but section is usually empty its values are the globals values before the output is cached my talk my contributions etc etc otherwise the built in rate limiting checks are if enabled allows for interception of redirect as a string mapping parameter names to values & $type
Definition: hooks.txt:2536
OutputPage\getRedirect
getRedirect()
Get the URL to redirect to, or an empty string if not redirect URL set.
Definition: OutputPage.php:342
OutputPage\setCanonicalUrl
setCanonicalUrl( $url)
Set the URL to be used for the <link rel="canonical">.
Definition: OutputPage.php:426
ContextSource\getUser
getUser()
Get the User object.
Definition: ContextSource.php:133
ContextSource\getTitle
getTitle()
Get the Title object.
Definition: ContextSource.php:88
OutputPage\$mLinktags
array $mLinktags
Definition: OutputPage.php:49
OutputPage\$mIndexPolicy
$mIndexPolicy
Definition: OutputPage.php:263
Skin\getHtmlElementAttributes
getHtmlElementAttributes()
Return values for <html> element.
Definition: Skin.php:418
Html\inlineScript
static inlineScript( $contents)
Output a "<script>" tag with the given contents.
Definition: Html.php:583
LinkBatch\setArray
setArray( $array)
Set the link list to a given 2-d array First key is the namespace, second is the DB key,...
Definition: LinkBatch.php:98
OutputPage\setIndicators
setIndicators(array $indicators)
Add an array of indicators, with their identifiers as array keys and HTML contents as values.
Definition: OutputPage.php:1410
LinkCache\getSelectFields
static getSelectFields()
Fields that LinkCache needs to select.
Definition: LinkCache.php:213
OutputPage\showFileDeleteError
showFileDeleteError( $name)
Definition: OutputPage.php:2718
OutputPage\addHTML
addHTML( $text)
Append $text to the body HTML.
Definition: OutputPage.php:1530
OutputPage\addHeadItem
addHeadItem( $name, $value)
Add or replace a head item to the output.
Definition: OutputPage.php:683
OutputPage\addWikiTextTidy
addWikiTextTidy( $text, $linestart=true)
Add wikitext with tidy enabled.
Definition: OutputPage.php:1742
OutputPage\getModuleScripts
getModuleScripts( $filter=false, $position=null)
Get the list of module JS to include on this page.
Definition: OutputPage.php:603
php
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
File\exists
exists()
Returns true if file exists in the repository.
Definition: File.php:877
OutputPage\getRevisionTimestamp
getRevisionTimestamp()
Get the timestamp of displayed revision.
Definition: OutputPage.php:1650
OutputPage\addWikiMsgArray
addWikiMsgArray( $name, $args)
Add a wikitext-formatted message to the output.
Definition: OutputPage.php:3876
OutputPage\enableTOC
enableTOC( $flag=true)
Enables/disables TOC, doesn't override NOTOC
Definition: OutputPage.php:3935
OutputPage\transformCssMedia
static transformCssMedia( $media)
Transform "media" attribute based on request parameters.
Definition: OutputPage.php:3817
OutputPage\setLastModified
setLastModified( $timestamp)
Override the last modified timestamp.
Definition: OutputPage.php:858
ResourceLoaderClientHtml\setConfig
setConfig(array $vars)
Set mw.config variables.
Definition: ResourceLoaderClientHtml.php:72
ContextSource\getLanguage
getLanguage()
Get the Language object.
Definition: ContextSource.php:143
OutputPage\$mPageTitleActionText
string $mPageTitleActionText
Definition: OutputPage.php:230
OutputPage\$mImageTimeKeys
array $mImageTimeKeys
Definition: OutputPage.php:173
OutputPage\showPermissionsErrorPage
showPermissionsErrorPage(array $errors, $action=null)
Output a standard permission error page.
Definition: OutputPage.php:2528
OutputPage\$rlUserModuleState
string $rlUserModuleState
Definition: OutputPage.php:161
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:500
XmlJsCode
A wrapper class which causes Xml::encodeJsVar() and Xml::encodeJsCall() to interpret a given string a...
Definition: Xml.php:847
OutputPage\getLinkTags
getLinkTags()
Returns the current <link> tags.
Definition: OutputPage.php:405
OutputPage\forceHideNewSectionLink
forceHideNewSectionLink()
Forcibly hide the new section link?
Definition: OutputPage.php:1118
OutputPage\addWikiTextWithTitle
addWikiTextWithTitle( $text, &$title, $linestart=true)
Add wikitext with a custom Title object.
Definition: OutputPage.php:1721
Html\closeElement
static closeElement( $element)
Returns "</$element>".
Definition: Html.php:309
ExtensionRegistry\getInstance
static getInstance()
Definition: ExtensionRegistry.php:80
Xml\encodeJsCall
static encodeJsCall( $name, $args, $pretty=false)
Create a call to a JavaScript function.
Definition: Xml.php:645
OutputPage\$rlClientContext
ResourceLoaderContext $rlClientContext
Definition: OutputPage.php:158
Html\isXmlMimeType
static isXmlMimeType( $mimetype)
Determines if the given MIME type is xml.
Definition: Html.php:946
OutputPage\addElement
addElement( $element, array $attribs=[], $contents='')
Shortcut for adding an Html::element via addHTML.
Definition: OutputPage.php:1543
$query
null for the wiki Added should default to null in handler for backwards compatibility add a value to it if you want to add a cookie that have to vary cache options can modify $query
Definition: hooks.txt:1572
NS_SPECIAL
const NS_SPECIAL
Definition: Defines.php:51
OutputPage\addParserOutputMetadata
addParserOutputMetadata( $parserOutput)
Add all metadata associated with a ParserOutput object, but without the actual HTML.
Definition: OutputPage.php:1795
File
Implements some public methods and some protected utility functions which are required by multiple ch...
Definition: File.php:51
OutputPage\feedLink
feedLink( $type, $url, $text)
Generate a "<link rel/>" for a feed.
Definition: OutputPage.php:3574
OutputPage\getKeyHeader
getKeyHeader()
Get a complete Key header.
Definition: OutputPage.php:2140
MWException
MediaWiki exception.
Definition: MWException.php:26
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:576
OutputPage\addStyle
addStyle( $style, $media='', $condition='', $dir='')
Add a local or specified stylesheet, with the given media options.
Definition: OutputPage.php:3592
$title
namespace and then decline to actually register it file or subcat img or subcat $title
Definition: hooks.txt:934
OutputPage\sendCacheControl
sendCacheControl()
Send cache control HTTP headers.
Definition: OutputPage.php:2256
OutputPage\setETag
setETag( $tag)
Definition: OutputPage.php:711
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
Definition: GlobalFunctions.php:1128
OutputPage\$mCdnMaxageLimit
int $mCdnMaxageLimit
Upper limit on mCdnMaxage.
Definition: OutputPage.php:235
OutputPage\$mTemplateIds
array $mTemplateIds
Definition: OutputPage.php:170
wfScript
wfScript( $script='index')
Get the path to a specified script file, respecting file extensions; this is a wrapper around $wgScri...
Definition: GlobalFunctions.php:3138
ResourceLoaderWikiModule\preloadTitleInfo
static preloadTitleInfo(ResourceLoaderContext $context, IDatabase $db, array $moduleNames)
Definition: ResourceLoaderWikiModule.php:362
OutputPage\styleLink
styleLink( $style, array $options)
Generate <link> tags for stylesheets.
Definition: OutputPage.php:3703
OutputPage\$mEnableTOC
bool $mEnableTOC
Whether parser output should contain table of contents.
Definition: OutputPage.php:290
OutputPage\$mSubtitle
array $mSubtitle
Contains the page subtitle.
Definition: OutputPage.php:93
OutputPage\setFileVersion
setFileVersion( $file)
Set the displayed file version.
Definition: OutputPage.php:1660
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:3060
OutputPage\showUnexpectedValueError
showUnexpectedValueError( $name, $val)
Definition: OutputPage.php:2706
OutputPage\getLinkHeader
getLinkHeader()
Return a Link: header.
Definition: OutputPage.php:2127
$tag
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist and Watchlist you will want to construct new ChangesListBooleanFilter or ChangesListStringOptionsFilter objects When constructing you specify which group they belong to You can reuse existing or create your you must register them with $special registerFilterGroup removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books $tag
Definition: hooks.txt:1028
OutputPage\getResourceLoader
getResourceLoader()
Get a ResourceLoader object associated with this OutputPage.
Definition: OutputPage.php:2975
OutputPage\isTOCEnabled
isTOCEnabled()
Definition: OutputPage.php:3943
ContextSource
The simplest way of implementing IContextSource is to hold a RequestContext as a member variable and ...
Definition: ContextSource.php:30
Html\linkedScript
static linkedScript( $url)
Output a "<script>" tag linking to the given URL, e.g., "<script src=foo.js></script>".
Definition: Html.php:600
ContextSource\getWikiPage
getWikiPage()
Get the WikiPage object.
Definition: ContextSource.php:113
OutputPage\setFeedAppendQuery
setFeedAppendQuery( $val)
Add default feeds to the page header This is mainly kept for backward compatibility,...
Definition: OutputPage.php:1147
$attribs
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses after processing & $attribs
Definition: hooks.txt:1956
$modules
$modules
Definition: HTMLFormElement.php:12
OutputPage\isDisabled
isDisabled()
Return whether the output will be completely disabled.
Definition: OutputPage.php:1100
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:1619
OutputPage\addParserOutputText
addParserOutputText( $parserOutput)
Add the HTML associated with a ParserOutput object, without any metadata.
Definition: OutputPage.php:1878
$IP
$IP
Definition: update.php:3
PROTO_CURRENT
const PROTO_CURRENT
Definition: Defines.php:220
OutputPage\setArticleFlag
setArticleFlag( $v)
Set whether the displayed content is related to the source of the corresponding article on the wiki S...
Definition: OutputPage.php:1203
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:1468
ContextSource\getSkin
getSkin()
Get the Skin object.
Definition: ContextSource.php:153
ResourceLoaderModule\TYPE_SCRIPTS
const TYPE_SCRIPTS
Definition: ResourceLoaderModule.php:36
OutputPage\setSubtitle
setSubtitle( $str)
Replace the subtitle with $str.
Definition: OutputPage.php:1010
OutputPage\$mInlineStyles
string $mInlineStyles
Inline CSS styles.
Definition: OutputPage.php:131
OutputPage\addWikiText
addWikiText( $text, $linestart=true, $interface=true)
Convert wikitext to HTML and add it to the buffer Default assumes that the current page title will be...
Definition: OutputPage.php:1706
ThrottledError
Show an error when the user hits a rate limit.
Definition: ThrottledError.php:27
wfCgiToArray
wfCgiToArray( $query)
This is the logical opposite of wfArrayToCgi(): it accepts a query string as its argument and returns...
Definition: GlobalFunctions.php:453
OutputPage\addLogoPreloadLinkHeaders
addLogoPreloadLinkHeaders()
Add Link headers for preloading the wiki's logo.
Definition: OutputPage.php:4007
OutputPage\getVaryHeader
getVaryHeader()
Return a Vary: header on which to vary caches.
Definition: OutputPage.php:2101
OutputPage\addModules
addModules( $modules)
Add one or more modules recognized by ResourceLoader.
Definition: OutputPage.php:592
OutputPage\showLagWarning
showLagWarning( $lag)
Show a warning about replica DB lag.
Definition: OutputPage.php:2688
OutputPage\getPageTitleActionText
getPageTitleActionText()
Get the value of the "action text".
Definition: OutputPage.php:924
OutputPage\getCacheVaryCookies
getCacheVaryCookies()
Get the list of cookies that will influence on the cache.
Definition: OutputPage.php:2043
OutputPage\setCopyrightUrl
setCopyrightUrl( $url)
Set the copyright URL to send with the output.
Definition: OutputPage.php:354
ResourceLoaderSkinModule\getLogo
static getLogo(Config $conf)
Definition: ResourceLoaderSkinModule.php:71
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:93
$vars
static configuration should be added through ResourceLoaderGetConfigVars instead & $vars
Definition: hooks.txt:2179
OutputPage\$mFollowPolicy
$mFollowPolicy
Definition: OutputPage.php:264
OutputPage\$rlClient
ResourceLoaderClientHtml $rlClient
Definition: OutputPage.php:155
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
NS_CATEGORY
const NS_CATEGORY
Definition: Defines.php:76
ResourceLoaderModule\getOrigin
getOrigin()
Get this module's origin.
Definition: ResourceLoaderModule.php:126
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:999
string
This code would result in ircNotify being run twice when an article is and once for brion Hooks can return three possible true was required This is the default since MediaWiki *some string
Definition: hooks.txt:177
ContextSource\setContext
setContext(IContextSource $context)
Set the IContextSource object.
Definition: ContextSource.php:58
OutputPage\isArticle
isArticle()
Return whether the content displayed page is related to the source of the corresponding article on th...
Definition: OutputPage.php:1216
OutputPage
This class should be covered by a general architecture document which does not exist as of January 20...
Definition: OutputPage.php:44
OutputPage\showErrorPage
showErrorPage( $title, $msg, $params=[])
Output a standard error page.
Definition: OutputPage.php:2501
list
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition: deferred.txt:11
$dir
$dir
Definition: Autoload.php:8
OutputPage\$mParserOptions
ParserOptions $mParserOptions
lazy initialised, use parserOptions()
Definition: OutputPage.php:201
OutputPage\$mContainsNewMagic
int $mContainsNewMagic
Definition: OutputPage.php:195
OutputPage\$limitReportJSData
array $limitReportJSData
Profiling data.
Definition: OutputPage.php:303
OutputPage\addParserOutputNoText
addParserOutputNoText( $parserOutput)
Add a ParserOutput object, but without Html.
Definition: OutputPage.php:1782
OutputPage\addInlineScript
addInlineScript( $script)
Add a self-contained script tag with the given contents Internal use only.
Definition: OutputPage.php:520
OutputPage\getArticleBodyOnly
getArticleBodyOnly()
Return whether the output will contain only the body of the article.
Definition: OutputPage.php:730
OutputPage\getPreventClickjacking
getPreventClickjacking()
Get the prevent-clickjacking flag.
Definition: OutputPage.php:2232
OutputPage\$mModules
array $mModules
Definition: OutputPage.php:143
OutputPage\getCanonicalUrl
getCanonicalUrl()
Returns the URL to be used for the <link rel="canonical"> if one is set.
Definition: OutputPage.php:437
OutputPage\getExtStyle
getExtStyle()
Get all styles added by extensions.
Definition: OutputPage.php:488
OutputPage\setStatusCode
setStatusCode( $statusCode)
Set the HTTP status code to send with the output.
Definition: OutputPage.php:363
OutputPage\$mRedirect
string $mRedirect
Definition: OutputPage.php:96
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:2065
OutputPage\getPageTitle
getPageTitle()
Return the "page title", i.e.
Definition: OutputPage.php:992
OutputPage\disable
disable()
Disable output completely, i.e.
Definition: OutputPage.php:1091
OutputPage\sectionEditLinksEnabled
sectionEditLinksEnabled()
Definition: OutputPage.php:3960
OutputPage\setIndexPolicy
setIndexPolicy( $policy)
Set the index policy for the page, but leave the follow policy un- touched.
Definition: OutputPage.php:888
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:538
OutputPage\$mResourceLoader
ResourceLoader $mResourceLoader
Definition: OutputPage.php:152
OutputPage\$mMetatags
array $mMetatags
Should be private.
Definition: OutputPage.php:46
Skin\getPageClasses
getPageClasses( $title)
TODO: document.
Definition: Skin.php:390
$e
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException' returning false will NOT prevent logging $e
Definition: hooks.txt:2122
OutputPage\addCategoryLinks
addCategoryLinks(array $categories)
Add an array of categories, with names in the keys.
Definition: OutputPage.php:1276
OutputPage\setRevisionTimestamp
setRevisionTimestamp( $timestamp)
Set the timestamp of the revision which will be displayed.
Definition: OutputPage.php:1640
OutputPage\getHeadItemsArray
getHeadItemsArray()
Get an array of head items.
Definition: OutputPage.php:667
wfClearOutputBuffers
wfClearOutputBuffers()
More legible than passing a 'false' parameter to wfResetOutputBuffers():
Definition: GlobalFunctions.php:1856
OutputPage\rateLimited
rateLimited()
Turn off regular page output and return an error response for when rate limiting has triggered.
Definition: OutputPage.php:2674
$value
$value
Definition: styleTest.css.php:45
OutputPage\$mModuleScripts
array $mModuleScripts
Definition: OutputPage.php:146
OutputPage\addReturnTo
addReturnTo( $title, array $query=[], $text=null, $options=[])
Add a "return to" link pointing to a specified title.
Definition: OutputPage.php:2734
OutputPage\buildExemptModules
buildExemptModules()
Build exempt modules and legacy non-ResourceLoader styles.
Definition: OutputPage.php:3626
OutputPage\$copyrightUrl
string null $copyrightUrl
The URL to send in a <link> element with rel=copyright.
Definition: OutputPage.php:300
OutputPage\getProperty
getProperty( $name)
Get an additional output property.
Definition: OutputPage.php:752
ParserOptions\newFromContext
static newFromContext(IContextSource $context)
Get a ParserOptions object from a IContextSource object.
Definition: ParserOptions.php:726
OutputPage\setSquidMaxage
setSquidMaxage( $maxage)
Definition: OutputPage.php:1973
$header
$header
Definition: updateCredits.php:35
OutputPage\addHelpLink
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Definition: OutputPage.php:1436
OutputPage\formatPermissionsErrorMessage
formatPermissionsErrorMessage(array $errors, $action=null)
Format a list of error messages.
Definition: OutputPage.php:2619
OutputPage\$mIndicators
array $mIndicators
Definition: OutputPage.php:117
OutputPage\$mExtStyles
array $mExtStyles
Additional stylesheets.
Definition: OutputPage.php:58
OutputPage\setTarget
setTarget( $target)
Sets ResourceLoader target for load.php links.
Definition: OutputPage.php:658
MediaWiki\Session\SessionManager
This serves as the entry point to the MediaWiki session handling system.
Definition: SessionManager.php:49
OutputPage\setHTMLTitle
setHTMLTitle( $name)
"HTML title" means the contents of "<title>".
Definition: OutputPage.php:934
OutputPage\setLanguageLinks
setLanguageLinks(array $newLinkArray)
Reset the language links and add new language links.
Definition: OutputPage.php:1258
SpecialPageFactory\resolveAlias
static resolveAlias( $alias)
Given a special page name with a possible subpage, return an array where the first element is the spe...
Definition: SpecialPageFactory.php:338
OutputPage\$rlExemptStyleModules
array $rlExemptStyleModules
Definition: OutputPage.php:164
OutputPage\$mProperties
$mProperties
Additional key => value data.
Definition: OutputPage.php:280
PROTO_RELATIVE
const PROTO_RELATIVE
Definition: Defines.php:219
OutputPage\wrapWikiMsg
wrapWikiMsg( $wrap)
This function takes a number of message/argument specifications, wraps them in some overall structure...
Definition: OutputPage.php:3905
Html\inlineStyle
static inlineStyle( $contents, $media='all')
Output a "<style>" tag with the given contents for the given media type (if any).
Definition: Html.php:615
OutputPage\prependHTML
prependHTML( $text)
Prepend $text to the body HTML.
Definition: OutputPage.php:1521
MWNamespace\exists
static exists( $index)
Returns whether the specified namespace exists.
Definition: MWNamespace.php:160
OutputPage\$mEnableClientCache
$mEnableClientCache
Definition: OutputPage.php:211
OutputPage\getHTMLTitle
getHTMLTitle()
Return the "HTML title", i.e.
Definition: OutputPage.php:947
OutputPage\showFileCopyError
showFileCopyError( $old, $new)
Definition: OutputPage.php:2710
ResourceLoaderModule\ORIGIN_CORE_INDIVIDUAL
const ORIGIN_CORE_INDIVIDUAL
Definition: ResourceLoaderModule.php:50
OutputPage\clearSubtitle
clearSubtitle()
Clear the subtitles.
Definition: OutputPage.php:1058
OutputPage\warnModuleTargetFilter
warnModuleTargetFilter( $moduleName)
Definition: OutputPage.php:553
OutputPage\getMetadataAttribute
getMetadataAttribute()
Get the value of the "rel" attribute for metadata links.
Definition: OutputPage.php:446
OutputPage\isUserJsPreview
isUserJsPreview()
Definition: OutputPage.php:3017
OutputPage\$mCdnMaxage
int $mCdnMaxage
Cache stuff.
Definition: OutputPage.php:233
OutputPage\enableOOUI
enableOOUI()
Add ResourceLoader module styles for OOUI and set up the PHP implementation of it for use with MediaW...
Definition: OutputPage.php:3988
plain
either a plain
Definition: hooks.txt:2007
OutputPage\$mScripts
$mScripts
Used for JavaScript (predates ResourceLoader)
Definition: OutputPage.php:128
OutputPage\$mAllowedModules
array $mAllowedModules
What level of 'untrustworthiness' is allowed in CSS/JS modules loaded on this page?
Definition: OutputPage.php:185
OutputPage\$mPrintable
bool $mPrintable
We have to set isPrintable().
Definition: OutputPage.php:87
$response
this hook is for auditing only $response
Definition: hooks.txt:783
$resourceLoader
error also a ContextSource you ll probably need to make sure the header is varied on and they can depend only on the ResourceLoaderContext such as when responding to a resource loader request or generating HTML output & $resourceLoader
Definition: hooks.txt:2612
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:55
ResourceLoaderModule\ORIGIN_ALL
const ORIGIN_ALL
Definition: ResourceLoaderModule.php:60
OutputPage\$mLanguageLinks
array $mLanguageLinks
Array of Interwiki Prefixed (non DB key) Titles (e.g.
Definition: OutputPage.php:120
wfGetAllCallers
wfGetAllCallers( $limit=3)
Return a string consisting of callers in the stack.
Definition: GlobalFunctions.php:1577
OutputPage\setCategoryLinks
setCategoryLinks(array $categories)
Reset the category links (but not the category list) and add $categories.
Definition: OutputPage.php:1361
OutputPage\setFollowPolicy
setFollowPolicy( $policy)
Set the follow policy for the page, but leave the index policy un- touched.
Definition: OutputPage.php:902
OutputPage\setPageTitle
setPageTitle( $name)
"Page title" means the contents of <h1>.
Definition: OutputPage.php:970
OutputPage\getRlClient
getRlClient()
Call this to freeze the module queue and JS config and create a formatter.
Definition: OutputPage.php:2809
OutputPage\$mFileVersion
array $mFileVersion
Definition: OutputPage.php:251
OutputPage\checkLastModified
checkLastModified( $timestamp)
checkLastModified tells the client to use the client-cached page if possible.
Definition: OutputPage.php:771
OutputPage\$mNoGallery
bool $mNoGallery
Comes from the parser.
Definition: OutputPage.php:227
ResourceLoaderClientHtml\makeLoad
static makeLoad(ResourceLoaderContext $mainContext, array $modules, $only, array $extraQuery=[])
Explicily load or embed modules on a page.
Definition: ResourceLoaderClientHtml.php:362
OutputPage\$mHeadItems
array $mHeadItems
Array of elements in "<head>".
Definition: OutputPage.php:140
$args
if( $line===false) $args
Definition: cdb.php:63
OutputPage\$mRevisionTimestamp
string $mRevisionTimestamp
Definition: OutputPage.php:248
Title
Represents a title within MediaWiki.
Definition: Title.php:39
ResourceLoaderModule
Abstraction for ResourceLoader modules, with name registration and maxage functionality.
Definition: ResourceLoaderModule.php:34
OutputPage\setCdnMaxage
setCdnMaxage( $maxage)
Set the value of the "s-maxage" part of the "Cache-control" HTTP header.
Definition: OutputPage.php:1982
OutputPage\getAllowedModules
getAllowedModules( $type)
Show what level of JavaScript / CSS untrustworthiness is allowed on this page.
Definition: OutputPage.php:1493
and
and that you know you can do these things To protect your we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights These restrictions translate to certain responsibilities for you if you distribute copies of the or if you modify it For if you distribute copies of such a whether gratis or for a you must give the recipients all the rights that you have You must make sure that receive or can get the source code And you must show them these terms so they know their rights We protect your rights with two and(2) offer you this license which gives you legal permission to copy
OutputPage\addVaryHeader
addVaryHeader( $header, array $option=null)
Add an HTTP header that will influence on the cache.
Definition: OutputPage.php:2085
OutputPage\setProperty
setProperty( $name, $value)
Set an additional output property.
Definition: OutputPage.php:741
OutputPage\isPrintable
isPrintable()
Return whether the page is "printable".
Definition: OutputPage.php:1084
OutputPage\setSyndicated
setSyndicated( $show=true)
Add or remove feed links in the page header This is mainly kept for backward compatibility,...
Definition: OutputPage.php:1130
$dbr
if(! $regexes) $dbr
Definition: cleanup.php:94
OutputPage\$mTarget
string null $mTarget
ResourceLoader target for load.php links.
Definition: OutputPage.php:285
OutputPage\addInlineStyle
addInlineStyle( $style_css, $flip='noflip')
Adds inline CSS styles Internal use only.
Definition: OutputPage.php:3613
ResourceLoaderClientHtml\setModules
setModules(array $modules)
Ensure one or more modules are loaded.
Definition: ResourceLoaderClientHtml.php:83
OutputPage\userCanPreview
userCanPreview()
To make it harder for someone to slip a user a fake user-JavaScript or user-CSS preview,...
Definition: OutputPage.php:3252
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:644
OutputPage\addExtensionStyle
addExtensionStyle( $url)
Register and add a stylesheet from an extension directory.
Definition: OutputPage.php:477
$code
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output modifiable & $code
Definition: hooks.txt:783
OutputPage\setRedirectedFrom
setRedirectedFrom( $t)
Set $mRedirectedFrom, the Title of the page which redirected us to the current page.
Definition: OutputPage.php:956
ResourceLoaderClientHtml\setModuleStyles
setModuleStyles(array $modules)
Ensure the styles of one or more modules are loaded.
Definition: ResourceLoaderClientHtml.php:93
OutputPage\addWikiTextTitle
addWikiTextTitle( $text, Title $title, $linestart, $tidy=false, $interface=false)
Add wikitext with a custom Title object.
Definition: OutputPage.php:1757
OutputPage\addMetadataLink
addMetadataLink(array $linkarr)
Add a new <link> with "rel" attribute set to "meta".
Definition: OutputPage.php:416
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:532
WebRequest\getRequestId
static getRequestId()
Get the unique request ID.
Definition: WebRequest.php:272
LinkCache\singleton
static singleton()
Get an instance of this class.
Definition: LinkCache.php:67
OutputPage\redirect
redirect( $url, $responsecode='302')
Redirect to $url rather than displaying the normal page.
Definition: OutputPage.php:331
OutputPage\$mJsConfigVars
array $mJsConfigVars
Definition: OutputPage.php:167
$path
$path
Definition: NoLocalSettings.php:26
OutputPage\isUserCssPreview
isUserCssPreview()
Definition: OutputPage.php:3024
OutputPage\setPrintable
setPrintable()
Set the page as printable, i.e.
Definition: OutputPage.php:1075
OutputPage\getHeadLinksArray
getHeadLinksArray()
Definition: OutputPage.php:3292
OutputPage\readOnlyPage
readOnlyPage()
Display a page stating that the Wiki is in read-only mode.
Definition: OutputPage.php:2660
OutputPage\adaptCdnTTL
adaptCdnTTL( $mtime, $minTTL=0, $maxTTL=0)
Get TTL in [$minTTL,$maxTTL] in pass it to lowerCdnMaxage()
Definition: OutputPage.php:2010
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
OutputPage\addModuleScripts
addModuleScripts( $modules)
Add only JS of one or more modules recognized by ResourceLoader.
Definition: OutputPage.php:616
OutputPage\allowClickjacking
allowClickjacking()
Turn off frame-breaking.
Definition: OutputPage.php:2222
OutputPage\showFatalError
showFatalError( $message)
Definition: OutputPage.php:2700
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:251
Html\rawElement
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:209
messages
passed in as a query string parameter to the various URLs constructed here(i.e. $prevlink) $ldel you ll need to handle error messages
Definition: hooks.txt:1252
OutputPage\getHTML
getHTML()
Get the body HTML.
Definition: OutputPage.php:1559
OutputPage\$mLinkHeader
$mLinkHeader
Link: header contents.
Definition: OutputPage.php:308
$keys
$keys
Definition: testCompression.php:65
$link
usually copyright or history_copyright This message must be in HTML not wikitext & $link
Definition: hooks.txt:2929
OutputPage\$styles
array $styles
An array of stylesheet filenames (relative from skins path), with options for CSS media,...
Definition: OutputPage.php:261
LoggerFactory
MediaWiki Logger LoggerFactory implements a PSR[0] compatible message logging system Named Psr Log LoggerInterface instances can be obtained from the MediaWiki Logger LoggerFactory::getInstance() static method. MediaWiki\Logger\LoggerFactory expects a class implementing the MediaWiki\Logger\Spi interface to act as a factory for new Psr\Log\LoggerInterface instances. The "Spi" in MediaWiki\Logger\Spi stands for "service provider interface". An SPI is an API intended to be implemented or extended by a third party. This software design pattern is intended to enable framework extension and replaceable components. It is specifically used in the MediaWiki\Logger\LoggerFactory service to allow alternate PSR-3 logging implementations to be easily integrated with MediaWiki. The service provider interface allows the backend logging library to be implemented in multiple ways. The $wgMWLoggerDefaultSpi global provides the classname of the default MediaWiki\Logger\Spi implementation to be loaded at runtime. This can either be the name of a class implementing the MediaWiki\Logger\Spi with a zero argument const ructor or a callable that will return an MediaWiki\Logger\Spi instance. Alternately the MediaWiki\Logger\LoggerFactory MediaWiki Logger LoggerFactory
Definition: logger.txt:5
ResourceLoaderModule\TYPE_STYLES
const TYPE_STYLES
Definition: ResourceLoaderModule.php:37
MWDebug\addModules
static addModules(OutputPage $out)
Add ResourceLoader modules to the OutputPage object if debugging is enabled.
Definition: MWDebug.php:96
OutputPage\showNewSectionLink
showNewSectionLink()
Show an "add new section" link?
Definition: OutputPage.php:1109
OutputPage\parse
parse( $text, $linestart=true, $interface=false, $language=null)
Parse wikitext and return the HTML.
Definition: OutputPage.php:1924
wfMessage
either a unescaped string or a HtmlArmor object after in associative array form externallinks including delete and has completed for all link tables whether this was an auto creation default is conds Array Extra conditions for the No matching items in log is displayed if loglist is empty msgKey Array If you want a nice box with a set this to the key of the message First element is the message additional optional elements are parameters for the key that are processed with wfMessage() -> params() ->parseAsBlock() - offset Set to overwrite offset parameter in $wgRequest set to '' to unset offset - wrap String Wrap the message in html(usually something like "&lt
OutputPage\$mPageLinkTitle
string $mPageLinkTitle
Used by skin template.
Definition: OutputPage.php:137
OutputPage\makeResourceLoaderLink
makeResourceLoaderLink( $modules, $only, array $extraQuery=[])
Explicily load or embed modules on a page.
Definition: OutputPage.php:2993
OutputPage\getIndicators
getIndicators()
Get the indicators associated with this page.
Definition: OutputPage.php:1424
$t
$t
Definition: testCompression.php:67
$wgRequest
if(! $wgDBerrorLogTZ) $wgRequest
Definition: Setup.php:639
Html\element
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:231
Skin\getSkinName
getSkinName()
Definition: Skin.php:137
MediaWikiServices
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency MediaWikiServices
Definition: injection.txt:23
OutputPage\addJsConfigVars
addJsConfigVars( $keys, $value=null)
Add one or more variables to be set in mw.config in JavaScript.
Definition: OutputPage.php:3105
OutputPage\$mPreventClickjacking
bool $mPreventClickjacking
Controls if anti-clickjacking / frame-breaking headers will be sent.
Definition: OutputPage.php:242
Skin
The main skin class which provides methods and properties for all other skins.
Definition: Skin.php:34
OutputPage\getCategories
getCategories( $type='all')
Get the list of category names this page belongs to.
Definition: OutputPage.php:1387
OutputPage\getJsConfigVars
getJsConfigVars()
Get the javascript config vars to include on this page.
Definition: OutputPage.php:3095
OutputPage\getTemplateIds
getTemplateIds()
Get the templates used on this page.
Definition: OutputPage.php:1683
OutputPage\$mIsArticleRelated
bool $mIsArticleRelated
Stores "article flag" toggle.
Definition: OutputPage.php:81
Hooks\run
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:131
OutputPage\isSyndicated
isSyndicated()
Should we output feed links for this page?
Definition: OutputPage.php:1175
OutputPage\$mFeedLinksAppendQuery
$mFeedLinksAppendQuery
Definition: OutputPage.php:178
OutputPage\getFileSearchOptions
getFileSearchOptions()
Get the files used on this page.
Definition: OutputPage.php:1693
OutputPage\$mFeedLinks
$mFeedLinks
Handles the Atom / RSS links.
Definition: OutputPage.php:208
OutputPage\$mDoNothing
bool $mDoNothing
Whether output is disabled.
Definition: OutputPage.php:190
OutputPage\$mArticleBodyOnly
bool $mArticleBodyOnly
Flag if output should only contain the body of the article.
Definition: OutputPage.php:214
$options
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist and Watchlist you will want to construct new ChangesListBooleanFilter or ChangesListStringOptionsFilter objects When constructing you specify which group they belong to You can reuse existing or create your you must register them with $special registerFilterGroup removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context $options
Definition: hooks.txt:1049
MWNamespace\getCanonicalName
static getCanonicalName( $index)
Returns the canonical (English) name for a given index.
Definition: MWNamespace.php:228
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:2476
OutputPage\addTemplate
addTemplate(&$template)
Add the output of a QuickTemplate to the output buffer.
Definition: OutputPage.php:1908
$parserOutput
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist and Watchlist you will want to construct new ChangesListBooleanFilter or ChangesListStringOptionsFilter objects When constructing you specify which group they belong to You can reuse existing or create your you must register them with $special registerFilterGroup removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context $parserOutput
Definition: hooks.txt:1049
OutputPage\getFeedAppendQuery
getFeedAppendQuery()
Will currently always return null.
Definition: OutputPage.php:1192
OutputPage\lowerCdnMaxage
lowerCdnMaxage( $maxage)
Lower the value of the "s-maxage" part of the "Cache-control" HTTP header.
Definition: OutputPage.php:1992
OutputPage\$mHTMLtitle
string $mHTMLtitle
Stores contents of "<title>" tag.
Definition: OutputPage.php:72
wfExpandUrl
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
Definition: GlobalFunctions.php:552
array
the array() calling protocol came about after MediaWiki 1.4rc1.
OutputPage\addFeedLink
addFeedLink( $format, $href)
Add a feed link to the page header.
Definition: OutputPage.php:1165
OutputPage\$mCategoryLinks
array $mCategoryLinks
Definition: OutputPage.php:108
OutputPage\transformResourcePath
static transformResourcePath(Config $config, $path)
Transform path to web-accessible static resource.
Definition: OutputPage.php:3759
OutputPage\setRobotPolicy
setRobotPolicy( $policy)
Set the robot policy for the page: http://www.robotstxt.org/meta.html
Definition: OutputPage.php:870
$wgContLang
this class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as and the content language as $wgContLang
Definition: design.txt:56
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:408
OutputPage\transformFilePath
static transformFilePath( $remotePathPrefix, $localPath, $file)
Utility method for transformResourceFilePath().
Definition: OutputPage.php:3801
OutputPage\headElement
headElement(Skin $sk, $includeStyle=true)
Definition: OutputPage.php:2890
OutputPage\$mStatusCode
int $mStatusCode
Definition: OutputPage.php:99