MediaWiki  REL1_31
OutputPage.php
Go to the documentation of this file.
1 <?php
26 use Wikimedia\RelPath;
27 use Wikimedia\WrappedString;
28 use Wikimedia\WrappedStringList;
29 
45 class OutputPage extends ContextSource {
47  protected $mMetatags = [];
48 
50  protected $mLinktags = [];
51 
53  protected $mCanonicalUrl = false;
54 
58  public $mPagetitle = '';
59 
64  public $mBodytext = '';
65 
67  private $mHTMLtitle = '';
68 
73  private $mIsarticle = false;
74 
76  private $mIsArticleRelated = true;
77 
82  private $mPrintable = false;
83 
88  private $mSubtitle = [];
89 
91  public $mRedirect = '';
92 
94  protected $mStatusCode;
95 
100  protected $mLastModified = '';
101 
103  protected $mCategoryLinks = [];
104 
106  protected $mCategories = [
107  'hidden' => [],
108  'normal' => [],
109  ];
110 
112  protected $mIndicators = [];
113 
115  private $mLanguageLinks = [];
116 
123  private $mScripts = '';
124 
126  protected $mInlineStyles = '';
127 
132  public $mPageLinkTitle = '';
133 
135  protected $mHeadItems = [];
136 
138  protected $mAdditionalBodyClasses = [];
139 
141  protected $mModules = [];
142 
144  protected $mModuleScripts = [];
145 
147  protected $mModuleStyles = [];
148 
150  protected $mResourceLoader;
151 
153  private $rlClient;
154 
157 
160 
163 
165  protected $mJsConfigVars = [];
166 
168  protected $mTemplateIds = [];
169 
171  protected $mImageTimeKeys = [];
172 
174  public $mRedirectCode = '';
175 
176  protected $mFeedLinksAppendQuery = null;
177 
183  protected $mAllowedModules = [
185  ];
186 
188  protected $mDoNothing = false;
189 
190  // Parser related.
191 
193  protected $mContainsNewMagic = 0;
194 
199  protected $mParserOptions = null;
200 
206  private $mFeedLinks = [];
207 
208  // Gwicke work on squid caching? Roughly from 2003.
209  protected $mEnableClientCache = true;
210 
212  private $mArticleBodyOnly = false;
213 
215  protected $mNewSectionLink = false;
216 
218  protected $mHideNewSectionLink = false;
219 
225  public $mNoGallery = false;
226 
228  private $mPageTitleActionText = '';
229 
231  protected $mCdnMaxage = 0;
233  protected $mCdnMaxageLimit = INF;
234 
240  protected $mPreventClickjacking = true;
241 
243  private $mRevisionId = null;
244 
246  private $mRevisionTimestamp = null;
247 
249  protected $mFileVersion = null;
250 
259  protected $styles = [];
260 
261  private $mIndexPolicy = 'index';
262  private $mFollowPolicy = 'follow';
263  private $mVaryHeader = [
264  'Accept-Encoding' => [ 'match=gzip' ],
265  ];
266 
273  private $mRedirectedFrom = null;
274 
278  private $mProperties = [];
279 
283  private $mTarget = null;
284 
288  private $mEnableTOC = false;
289 
293  private $copyrightUrl;
294 
296  private $limitReportJSData = [];
297 
301  private $mLinkHeader = [];
302 
310  $this->setContext( $context );
311  }
312 
319  public function redirect( $url, $responsecode = '302' ) {
320  # Strip newlines as a paranoia check for header injection in PHP<5.1.2
321  $this->mRedirect = str_replace( "\n", '', $url );
322  $this->mRedirectCode = $responsecode;
323  }
324 
330  public function getRedirect() {
331  return $this->mRedirect;
332  }
333 
342  public function setCopyrightUrl( $url ) {
343  $this->copyrightUrl = $url;
344  }
345 
351  public function setStatusCode( $statusCode ) {
352  $this->mStatusCode = $statusCode;
353  }
354 
362  function addMeta( $name, $val ) {
363  array_push( $this->mMetatags, [ $name, $val ] );
364  }
365 
372  public function getMetaTags() {
373  return $this->mMetatags;
374  }
375 
383  function addLink( array $linkarr ) {
384  array_push( $this->mLinktags, $linkarr );
385  }
386 
393  public function getLinkTags() {
394  return $this->mLinktags;
395  }
396 
404  function addMetadataLink( array $linkarr ) {
405  $linkarr['rel'] = $this->getMetadataAttribute();
406  $this->addLink( $linkarr );
407  }
408 
414  function setCanonicalUrl( $url ) {
415  $this->mCanonicalUrl = $url;
416  }
417 
425  public function getCanonicalUrl() {
426  return $this->mCanonicalUrl;
427  }
428 
434  public function getMetadataAttribute() {
435  # note: buggy CC software only reads first "meta" link
436  static $haveMeta = false;
437  if ( $haveMeta ) {
438  return 'alternate meta';
439  } else {
440  $haveMeta = true;
441  return 'meta';
442  }
443  }
444 
452  function addScript( $script ) {
453  $this->mScripts .= $script;
454  }
455 
464  public function addScriptFile( $file, $version = null ) {
465  // See if $file parameter is an absolute URL or begins with a slash
466  if ( substr( $file, 0, 1 ) == '/' || preg_match( '#^[a-z]*://#i', $file ) ) {
467  $path = $file;
468  } else {
469  $path = $this->getConfig()->get( 'StylePath' ) . "/common/{$file}";
470  }
471  if ( is_null( $version ) ) {
472  $version = $this->getConfig()->get( 'StyleVersion' );
473  }
474  $this->addScript( Html::linkedScript( wfAppendQuery( $path, $version ) ) );
475  }
476 
483  public function addInlineScript( $script ) {
484  $this->mScripts .= Html::inlineScript( $script );
485  }
486 
495  protected function filterModules( array $modules, $position = null,
497  ) {
499  $filteredModules = [];
500  foreach ( $modules as $val ) {
501  $module = $resourceLoader->getModule( $val );
502  if ( $module instanceof ResourceLoaderModule
503  && $module->getOrigin() <= $this->getAllowedModules( $type )
504  ) {
505  if ( $this->mTarget && !in_array( $this->mTarget, $module->getTargets() ) ) {
506  $this->warnModuleTargetFilter( $module->getName() );
507  continue;
508  }
509  $filteredModules[] = $val;
510  }
511  }
512  return $filteredModules;
513  }
514 
515  private function warnModuleTargetFilter( $moduleName ) {
516  static $warnings = [];
517  if ( isset( $warnings[$this->mTarget][$moduleName] ) ) {
518  return;
519  }
520  $warnings[$this->mTarget][$moduleName] = true;
521  $this->getResourceLoader()->getLogger()->debug(
522  'Module "{module}" not loadable on target "{target}".',
523  [
524  'module' => $moduleName,
525  'target' => $this->mTarget,
526  ]
527  );
528  }
529 
539  public function getModules( $filter = false, $position = null, $param = 'mModules',
541  ) {
542  $modules = array_values( array_unique( $this->$param ) );
543  return $filter
544  ? $this->filterModules( $modules, null, $type )
545  : $modules;
546  }
547 
555  public function addModules( $modules ) {
556  $this->mModules = array_merge( $this->mModules, (array)$modules );
557  }
558 
566  public function getModuleScripts( $filter = false, $position = null ) {
567  return $this->getModules( $filter, null, 'mModuleScripts',
569  );
570  }
571 
579  public function addModuleScripts( $modules ) {
580  $this->mModuleScripts = array_merge( $this->mModuleScripts, (array)$modules );
581  }
582 
590  public function getModuleStyles( $filter = false, $position = null ) {
591  return $this->getModules( $filter, null, 'mModuleStyles',
593  );
594  }
595 
605  public function addModuleStyles( $modules ) {
606  $this->mModuleStyles = array_merge( $this->mModuleStyles, (array)$modules );
607  }
608 
612  public function getTarget() {
613  return $this->mTarget;
614  }
615 
621  public function setTarget( $target ) {
622  $this->mTarget = $target;
623  }
624 
630  function getHeadItemsArray() {
631  return $this->mHeadItems;
632  }
633 
646  public function addHeadItem( $name, $value ) {
647  $this->mHeadItems[$name] = $value;
648  }
649 
656  public function addHeadItems( $values ) {
657  $this->mHeadItems = array_merge( $this->mHeadItems, (array)$values );
658  }
659 
666  public function hasHeadItem( $name ) {
667  return isset( $this->mHeadItems[$name] );
668  }
669 
676  public function addBodyClasses( $classes ) {
677  $this->mAdditionalBodyClasses = array_merge( $this->mAdditionalBodyClasses, (array)$classes );
678  }
679 
687  public function setArticleBodyOnly( $only ) {
688  $this->mArticleBodyOnly = $only;
689  }
690 
696  public function getArticleBodyOnly() {
698  }
699 
707  public function setProperty( $name, $value ) {
708  $this->mProperties[$name] = $value;
709  }
710 
718  public function getProperty( $name ) {
719  if ( isset( $this->mProperties[$name] ) ) {
720  return $this->mProperties[$name];
721  } else {
722  return null;
723  }
724  }
725 
737  public function checkLastModified( $timestamp ) {
738  if ( !$timestamp || $timestamp == '19700101000000' ) {
739  wfDebug( __METHOD__ . ": CACHE DISABLED, NO TIMESTAMP\n" );
740  return false;
741  }
742  $config = $this->getConfig();
743  if ( !$config->get( 'CachePages' ) ) {
744  wfDebug( __METHOD__ . ": CACHE DISABLED\n" );
745  return false;
746  }
747 
748  $timestamp = wfTimestamp( TS_MW, $timestamp );
749  $modifiedTimes = [
750  'page' => $timestamp,
751  'user' => $this->getUser()->getTouched(),
752  'epoch' => $config->get( 'CacheEpoch' )
753  ];
754  if ( $config->get( 'UseSquid' ) ) {
755  // T46570: the core page itself may not change, but resources might
756  $modifiedTimes['sepoch'] = wfTimestamp( TS_MW, time() - $config->get( 'SquidMaxage' ) );
757  }
758  Hooks::run( 'OutputPageCheckLastModified', [ &$modifiedTimes, $this ] );
759 
760  $maxModified = max( $modifiedTimes );
761  $this->mLastModified = wfTimestamp( TS_RFC2822, $maxModified );
762 
763  $clientHeader = $this->getRequest()->getHeader( 'If-Modified-Since' );
764  if ( $clientHeader === false ) {
765  wfDebug( __METHOD__ . ": client did not send If-Modified-Since header", 'private' );
766  return false;
767  }
768 
769  # IE sends sizes after the date like this:
770  # Wed, 20 Aug 2003 06:51:19 GMT; length=5202
771  # this breaks strtotime().
772  $clientHeader = preg_replace( '/;.*$/', '', $clientHeader );
773 
774  Wikimedia\suppressWarnings(); // E_STRICT system time bitching
775  $clientHeaderTime = strtotime( $clientHeader );
776  Wikimedia\restoreWarnings();
777  if ( !$clientHeaderTime ) {
778  wfDebug( __METHOD__
779  . ": unable to parse the client's If-Modified-Since header: $clientHeader\n" );
780  return false;
781  }
782  $clientHeaderTime = wfTimestamp( TS_MW, $clientHeaderTime );
783 
784  # Make debug info
785  $info = '';
786  foreach ( $modifiedTimes as $name => $value ) {
787  if ( $info !== '' ) {
788  $info .= ', ';
789  }
790  $info .= "$name=" . wfTimestamp( TS_ISO_8601, $value );
791  }
792 
793  wfDebug( __METHOD__ . ": client sent If-Modified-Since: " .
794  wfTimestamp( TS_ISO_8601, $clientHeaderTime ), 'private' );
795  wfDebug( __METHOD__ . ": effective Last-Modified: " .
796  wfTimestamp( TS_ISO_8601, $maxModified ), 'private' );
797  if ( $clientHeaderTime < $maxModified ) {
798  wfDebug( __METHOD__ . ": STALE, $info", 'private' );
799  return false;
800  }
801 
802  # Not modified
803  # Give a 304 Not Modified response code and disable body output
804  wfDebug( __METHOD__ . ": NOT MODIFIED, $info", 'private' );
805  ini_set( 'zlib.output_compression', 0 );
806  $this->getRequest()->response()->statusHeader( 304 );
807  $this->sendCacheControl();
808  $this->disable();
809 
810  // Don't output a compressed blob when using ob_gzhandler;
811  // it's technically against HTTP spec and seems to confuse
812  // Firefox when the response gets split over two packets.
814 
815  return true;
816  }
817 
824  public function setLastModified( $timestamp ) {
825  $this->mLastModified = wfTimestamp( TS_RFC2822, $timestamp );
826  }
827 
836  public function setRobotPolicy( $policy ) {
837  $policy = Article::formatRobotPolicy( $policy );
838 
839  if ( isset( $policy['index'] ) ) {
840  $this->setIndexPolicy( $policy['index'] );
841  }
842  if ( isset( $policy['follow'] ) ) {
843  $this->setFollowPolicy( $policy['follow'] );
844  }
845  }
846 
854  public function setIndexPolicy( $policy ) {
855  $policy = trim( $policy );
856  if ( in_array( $policy, [ 'index', 'noindex' ] ) ) {
857  $this->mIndexPolicy = $policy;
858  }
859  }
860 
868  public function setFollowPolicy( $policy ) {
869  $policy = trim( $policy );
870  if ( in_array( $policy, [ 'follow', 'nofollow' ] ) ) {
871  $this->mFollowPolicy = $policy;
872  }
873  }
874 
881  public function setPageTitleActionText( $text ) {
882  $this->mPageTitleActionText = $text;
883  }
884 
890  public function getPageTitleActionText() {
892  }
893 
900  public function setHTMLTitle( $name ) {
901  if ( $name instanceof Message ) {
902  $this->mHTMLtitle = $name->setContext( $this->getContext() )->text();
903  } else {
904  $this->mHTMLtitle = $name;
905  }
906  }
907 
913  public function getHTMLTitle() {
914  return $this->mHTMLtitle;
915  }
916 
922  public function setRedirectedFrom( $t ) {
923  $this->mRedirectedFrom = $t;
924  }
925 
936  public function setPageTitle( $name ) {
937  if ( $name instanceof Message ) {
938  $name = $name->setContext( $this->getContext() )->text();
939  }
940 
941  # change "<script>foo&bar</script>" to "&lt;script&gt;foo&amp;bar&lt;/script&gt;"
942  # but leave "<i>foobar</i>" alone
944  $this->mPagetitle = $nameWithTags;
945 
946  # change "<i>foo&amp;bar</i>" to "foo&bar"
947  $this->setHTMLTitle(
948  $this->msg( 'pagetitle' )->rawParams( Sanitizer::stripAllTags( $nameWithTags ) )
949  ->inContentLanguage()
950  );
951  }
952 
958  public function getPageTitle() {
959  return $this->mPagetitle;
960  }
961 
967  public function setTitle( Title $t ) {
968  $this->getContext()->setTitle( $t );
969  }
970 
976  public function setSubtitle( $str ) {
977  $this->clearSubtitle();
978  $this->addSubtitle( $str );
979  }
980 
986  public function addSubtitle( $str ) {
987  if ( $str instanceof Message ) {
988  $this->mSubtitle[] = $str->setContext( $this->getContext() )->parse();
989  } else {
990  $this->mSubtitle[] = $str;
991  }
992  }
993 
1002  public static function buildBacklinkSubtitle( Title $title, $query = [] ) {
1003  if ( $title->isRedirect() ) {
1004  $query['redirect'] = 'no';
1005  }
1006  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
1007  return wfMessage( 'backlinksubtitle' )
1008  ->rawParams( $linkRenderer->makeLink( $title, null, [], $query ) );
1009  }
1010 
1017  public function addBacklinkSubtitle( Title $title, $query = [] ) {
1018  $this->addSubtitle( self::buildBacklinkSubtitle( $title, $query ) );
1019  }
1020 
1024  public function clearSubtitle() {
1025  $this->mSubtitle = [];
1026  }
1027 
1033  public function getSubtitle() {
1034  return implode( "<br />\n\t\t\t\t", $this->mSubtitle );
1035  }
1036 
1041  public function setPrintable() {
1042  $this->mPrintable = true;
1043  }
1044 
1050  public function isPrintable() {
1051  return $this->mPrintable;
1052  }
1053 
1057  public function disable() {
1058  $this->mDoNothing = true;
1059  }
1060 
1066  public function isDisabled() {
1067  return $this->mDoNothing;
1068  }
1069 
1075  public function showNewSectionLink() {
1076  return $this->mNewSectionLink;
1077  }
1078 
1084  public function forceHideNewSectionLink() {
1086  }
1087 
1096  public function setSyndicated( $show = true ) {
1097  if ( $show ) {
1098  $this->setFeedAppendQuery( false );
1099  } else {
1100  $this->mFeedLinks = [];
1101  }
1102  }
1103 
1113  public function setFeedAppendQuery( $val ) {
1114  $this->mFeedLinks = [];
1115 
1116  foreach ( $this->getConfig()->get( 'AdvertisedFeedTypes' ) as $type ) {
1117  $query = "feed=$type";
1118  if ( is_string( $val ) ) {
1119  $query .= '&' . $val;
1120  }
1121  $this->mFeedLinks[$type] = $this->getTitle()->getLocalURL( $query );
1122  }
1123  }
1124 
1131  public function addFeedLink( $format, $href ) {
1132  if ( in_array( $format, $this->getConfig()->get( 'AdvertisedFeedTypes' ) ) ) {
1133  $this->mFeedLinks[$format] = $href;
1134  }
1135  }
1136 
1141  public function isSyndicated() {
1142  return count( $this->mFeedLinks ) > 0;
1143  }
1144 
1149  public function getSyndicationLinks() {
1150  return $this->mFeedLinks;
1151  }
1152 
1158  public function getFeedAppendQuery() {
1160  }
1161 
1169  public function setArticleFlag( $v ) {
1170  $this->mIsarticle = $v;
1171  if ( $v ) {
1172  $this->mIsArticleRelated = $v;
1173  }
1174  }
1175 
1182  public function isArticle() {
1183  return $this->mIsarticle;
1184  }
1185 
1192  public function setArticleRelated( $v ) {
1193  $this->mIsArticleRelated = $v;
1194  if ( !$v ) {
1195  $this->mIsarticle = false;
1196  }
1197  }
1198 
1204  public function isArticleRelated() {
1205  return $this->mIsArticleRelated;
1206  }
1207 
1214  public function addLanguageLinks( array $newLinkArray ) {
1215  $this->mLanguageLinks += $newLinkArray;
1216  }
1217 
1224  public function setLanguageLinks( array $newLinkArray ) {
1225  $this->mLanguageLinks = $newLinkArray;
1226  }
1227 
1233  public function getLanguageLinks() {
1234  return $this->mLanguageLinks;
1235  }
1236 
1242  public function addCategoryLinks( array $categories ) {
1244 
1245  if ( !is_array( $categories ) || count( $categories ) == 0 ) {
1246  return;
1247  }
1248 
1249  $res = $this->addCategoryLinksToLBAndGetResult( $categories );
1250 
1251  # Set all the values to 'normal'.
1252  $categories = array_fill_keys( array_keys( $categories ), 'normal' );
1253 
1254  # Mark hidden categories
1255  foreach ( $res as $row ) {
1256  if ( isset( $row->pp_value ) ) {
1257  $categories[$row->page_title] = 'hidden';
1258  }
1259  }
1260 
1261  // Avoid PHP 7.1 warning of passing $this by reference
1262  $outputPage = $this;
1263  # Add the remaining categories to the skin
1264  if ( Hooks::run(
1265  'OutputPageMakeCategoryLinks',
1266  [ &$outputPage, $categories, &$this->mCategoryLinks ] )
1267  ) {
1268  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
1269  foreach ( $categories as $category => $type ) {
1270  // array keys will cast numeric category names to ints, so cast back to string
1271  $category = (string)$category;
1272  $origcategory = $category;
1273  $title = Title::makeTitleSafe( NS_CATEGORY, $category );
1274  if ( !$title ) {
1275  continue;
1276  }
1277  $wgContLang->findVariantLink( $category, $title, true );
1278  if ( $category != $origcategory && array_key_exists( $category, $categories ) ) {
1279  continue;
1280  }
1281  $text = $wgContLang->convertHtml( $title->getText() );
1282  $this->mCategories[$type][] = $title->getText();
1283  $this->mCategoryLinks[$type][] = $linkRenderer->makeLink( $title, new HtmlArmor( $text ) );
1284  }
1285  }
1286  }
1287 
1292  protected function addCategoryLinksToLBAndGetResult( array $categories ) {
1293  # Add the links to a LinkBatch
1294  $arr = [ NS_CATEGORY => $categories ];
1295  $lb = new LinkBatch;
1296  $lb->setArray( $arr );
1297 
1298  # Fetch existence plus the hiddencat property
1299  $dbr = wfGetDB( DB_REPLICA );
1300  $fields = array_merge(
1302  [ 'page_namespace', 'page_title', 'pp_value' ]
1303  );
1304 
1305  $res = $dbr->select( [ 'page', 'page_props' ],
1306  $fields,
1307  $lb->constructSet( 'page', $dbr ),
1308  __METHOD__,
1309  [],
1310  [ 'page_props' => [ 'LEFT JOIN', [
1311  'pp_propname' => 'hiddencat',
1312  'pp_page = page_id'
1313  ] ] ]
1314  );
1315 
1316  # Add the results to the link cache
1317  $lb->addResultToCache( LinkCache::singleton(), $res );
1318 
1319  return $res;
1320  }
1321 
1327  public function setCategoryLinks( array $categories ) {
1328  $this->mCategoryLinks = [];
1329  $this->addCategoryLinks( $categories );
1330  }
1331 
1340  public function getCategoryLinks() {
1341  return $this->mCategoryLinks;
1342  }
1343 
1353  public function getCategories( $type = 'all' ) {
1354  if ( $type === 'all' ) {
1355  $allCategories = [];
1356  foreach ( $this->mCategories as $categories ) {
1357  $allCategories = array_merge( $allCategories, $categories );
1358  }
1359  return $allCategories;
1360  }
1361  if ( !isset( $this->mCategories[$type] ) ) {
1362  throw new InvalidArgumentException( 'Invalid category type given: ' . $type );
1363  }
1364  return $this->mCategories[$type];
1365  }
1366 
1376  public function setIndicators( array $indicators ) {
1377  $this->mIndicators = $indicators + $this->mIndicators;
1378  // Keep ordered by key
1379  ksort( $this->mIndicators );
1380  }
1381 
1390  public function getIndicators() {
1391  return $this->mIndicators;
1392  }
1393 
1402  public function addHelpLink( $to, $overrideBaseUrl = false ) {
1403  $this->addModuleStyles( 'mediawiki.helplink' );
1404  $text = $this->msg( 'helppage-top-gethelp' )->escaped();
1405 
1406  if ( $overrideBaseUrl ) {
1407  $helpUrl = $to;
1408  } else {
1409  $toUrlencoded = wfUrlencode( str_replace( ' ', '_', $to ) );
1410  $helpUrl = "//www.mediawiki.org/wiki/Special:MyLanguage/$toUrlencoded";
1411  }
1412 
1414  'a',
1415  [
1416  'href' => $helpUrl,
1417  'target' => '_blank',
1418  'class' => 'mw-helplink',
1419  ],
1420  $text
1421  );
1422 
1423  $this->setIndicators( [ 'mw-helplink' => $link ] );
1424  }
1425 
1434  public function disallowUserJs() {
1435  $this->reduceAllowedModules(
1438  );
1439 
1440  // Site-wide styles are controlled by a config setting, see T73621
1441  // for background on why. User styles are never allowed.
1442  if ( $this->getConfig()->get( 'AllowSiteCSSOnRestrictedPages' ) ) {
1444  } else {
1446  }
1447  $this->reduceAllowedModules(
1449  $styleOrigin
1450  );
1451  }
1452 
1459  public function getAllowedModules( $type ) {
1461  return min( array_values( $this->mAllowedModules ) );
1462  } else {
1463  return isset( $this->mAllowedModules[$type] )
1464  ? $this->mAllowedModules[$type]
1466  }
1467  }
1468 
1478  public function reduceAllowedModules( $type, $level ) {
1479  $this->mAllowedModules[$type] = min( $this->getAllowedModules( $type ), $level );
1480  }
1481 
1487  public function prependHTML( $text ) {
1488  $this->mBodytext = $text . $this->mBodytext;
1489  }
1490 
1496  public function addHTML( $text ) {
1497  $this->mBodytext .= $text;
1498  }
1499 
1509  public function addElement( $element, array $attribs = [], $contents = '' ) {
1510  $this->addHTML( Html::element( $element, $attribs, $contents ) );
1511  }
1512 
1516  public function clearHTML() {
1517  $this->mBodytext = '';
1518  }
1519 
1525  public function getHTML() {
1526  return $this->mBodytext;
1527  }
1528 
1536  public function parserOptions( $options = null ) {
1537  if ( $options !== null ) {
1538  wfDeprecated( __METHOD__ . ' with non-null $options', '1.31' );
1539  }
1540 
1541  if ( $options !== null && !empty( $options->isBogus ) ) {
1542  // Someone is trying to set a bogus pre-$wgUser PO. Check if it has
1543  // been changed somehow, and keep it if so.
1544  $anonPO = ParserOptions::newFromAnon();
1545  $anonPO->setAllowUnsafeRawHtml( false );
1546  if ( !$options->matches( $anonPO ) ) {
1547  wfLogWarning( __METHOD__ . ': Setting a changed bogus ParserOptions: ' . wfGetAllCallers( 5 ) );
1548  $options->isBogus = false;
1549  }
1550  }
1551 
1552  if ( !$this->mParserOptions ) {
1553  if ( !$this->getContext()->getUser()->isSafeToLoad() ) {
1554  // $wgUser isn't unstubbable yet, so don't try to get a
1555  // ParserOptions for it. And don't cache this ParserOptions
1556  // either.
1558  $po->setAllowUnsafeRawHtml( false );
1559  $po->isBogus = true;
1560  if ( $options !== null ) {
1561  $this->mParserOptions = empty( $options->isBogus ) ? $options : null;
1562  }
1563  return $po;
1564  }
1565 
1566  $this->mParserOptions = ParserOptions::newFromContext( $this->getContext() );
1567  $this->mParserOptions->setAllowUnsafeRawHtml( false );
1568  }
1569 
1570  if ( $options !== null && !empty( $options->isBogus ) ) {
1571  // They're trying to restore the bogus pre-$wgUser PO. Do the right
1572  // thing.
1573  return wfSetVar( $this->mParserOptions, null, true );
1574  } else {
1575  return wfSetVar( $this->mParserOptions, $options );
1576  }
1577  }
1578 
1586  public function setRevisionId( $revid ) {
1587  $val = is_null( $revid ) ? null : intval( $revid );
1588  return wfSetVar( $this->mRevisionId, $val );
1589  }
1590 
1596  public function getRevisionId() {
1597  return $this->mRevisionId;
1598  }
1599 
1607  public function setRevisionTimestamp( $timestamp ) {
1608  return wfSetVar( $this->mRevisionTimestamp, $timestamp );
1609  }
1610 
1617  public function getRevisionTimestamp() {
1619  }
1620 
1627  public function setFileVersion( $file ) {
1628  $val = null;
1629  if ( $file instanceof File && $file->exists() ) {
1630  $val = [ 'time' => $file->getTimestamp(), 'sha1' => $file->getSha1() ];
1631  }
1632  return wfSetVar( $this->mFileVersion, $val, true );
1633  }
1634 
1640  public function getFileVersion() {
1641  return $this->mFileVersion;
1642  }
1643 
1650  public function getTemplateIds() {
1651  return $this->mTemplateIds;
1652  }
1653 
1660  public function getFileSearchOptions() {
1661  return $this->mImageTimeKeys;
1662  }
1663 
1673  public function addWikiText( $text, $linestart = true, $interface = true ) {
1674  $title = $this->getTitle(); // Work around E_STRICT
1675  if ( !$title ) {
1676  throw new MWException( 'Title is null' );
1677  }
1678  $this->addWikiTextTitle( $text, $title, $linestart, /*tidy*/false, $interface );
1679  }
1680 
1688  public function addWikiTextWithTitle( $text, &$title, $linestart = true ) {
1689  $this->addWikiTextTitle( $text, $title, $linestart );
1690  }
1691 
1699  function addWikiTextTitleTidy( $text, &$title, $linestart = true ) {
1700  $this->addWikiTextTitle( $text, $title, $linestart, true );
1701  }
1702 
1709  public function addWikiTextTidy( $text, $linestart = true ) {
1710  $title = $this->getTitle();
1711  $this->addWikiTextTitleTidy( $text, $title, $linestart );
1712  }
1713 
1724  public function addWikiTextTitle( $text, Title $title, $linestart,
1725  $tidy = false, $interface = false
1726  ) {
1727  global $wgParser;
1728 
1729  $popts = $this->parserOptions();
1730  $oldTidy = $popts->setTidy( $tidy );
1731  $popts->setInterfaceMessage( (bool)$interface );
1732 
1733  $parserOutput = $wgParser->getFreshParser()->parse(
1734  $text, $title, $popts,
1735  $linestart, true, $this->mRevisionId
1736  );
1737 
1738  $popts->setTidy( $oldTidy );
1739 
1740  $this->addParserOutput( $parserOutput, [
1741  'enableSectionEditLinks' => false,
1742  ] );
1743  }
1744 
1753  public function addParserOutputMetadata( $parserOutput ) {
1754  $this->mLanguageLinks += $parserOutput->getLanguageLinks();
1755  $this->addCategoryLinks( $parserOutput->getCategories() );
1756  $this->setIndicators( $parserOutput->getIndicators() );
1757  $this->mNewSectionLink = $parserOutput->getNewSection();
1758  $this->mHideNewSectionLink = $parserOutput->getHideNewSection();
1759 
1760  if ( !$parserOutput->isCacheable() ) {
1761  $this->enableClientCache( false );
1762  }
1763  $this->mNoGallery = $parserOutput->getNoGallery();
1764  $this->mHeadItems = array_merge( $this->mHeadItems, $parserOutput->getHeadItems() );
1765  $this->addModules( $parserOutput->getModules() );
1766  $this->addModuleScripts( $parserOutput->getModuleScripts() );
1767  $this->addModuleStyles( $parserOutput->getModuleStyles() );
1768  $this->addJsConfigVars( $parserOutput->getJsConfigVars() );
1769  $this->mPreventClickjacking = $this->mPreventClickjacking
1770  || $parserOutput->preventClickjacking();
1771 
1772  // Template versioning...
1773  foreach ( (array)$parserOutput->getTemplateIds() as $ns => $dbks ) {
1774  if ( isset( $this->mTemplateIds[$ns] ) ) {
1775  $this->mTemplateIds[$ns] = $dbks + $this->mTemplateIds[$ns];
1776  } else {
1777  $this->mTemplateIds[$ns] = $dbks;
1778  }
1779  }
1780  // File versioning...
1781  foreach ( (array)$parserOutput->getFileSearchOptions() as $dbk => $data ) {
1782  $this->mImageTimeKeys[$dbk] = $data;
1783  }
1784 
1785  // Hooks registered in the object
1786  $parserOutputHooks = $this->getConfig()->get( 'ParserOutputHooks' );
1787  foreach ( $parserOutput->getOutputHooks() as $hookInfo ) {
1788  list( $hookName, $data ) = $hookInfo;
1789  if ( isset( $parserOutputHooks[$hookName] ) ) {
1790  call_user_func( $parserOutputHooks[$hookName], $this, $parserOutput, $data );
1791  }
1792  }
1793 
1794  // Enable OOUI if requested via ParserOutput
1795  if ( $parserOutput->getEnableOOUI() ) {
1796  $this->enableOOUI();
1797  }
1798 
1799  // Include parser limit report
1800  if ( !$this->limitReportJSData ) {
1801  $this->limitReportJSData = $parserOutput->getLimitReportJSData();
1802  }
1803 
1804  // Link flags are ignored for now, but may in the future be
1805  // used to mark individual language links.
1806  $linkFlags = [];
1807  // Avoid PHP 7.1 warning of passing $this by reference
1808  $outputPage = $this;
1809  Hooks::run( 'LanguageLinks', [ $this->getTitle(), &$this->mLanguageLinks, &$linkFlags ] );
1810  Hooks::runWithoutAbort( 'OutputPageParserOutput', [ &$outputPage, $parserOutput ] );
1811 
1812  // This check must be after 'OutputPageParserOutput' runs in addParserOutputMetadata
1813  // so that extensions may modify ParserOutput to toggle TOC.
1814  // This cannot be moved to addParserOutputText because that is not
1815  // called by EditPage for Preview.
1816  if ( $parserOutput->getTOCHTML() ) {
1817  $this->mEnableTOC = true;
1818  }
1819  }
1820 
1829  public function addParserOutputContent( $parserOutput, $poOptions = [] ) {
1830  $this->addParserOutputText( $parserOutput, $poOptions );
1831 
1832  $this->addModules( $parserOutput->getModules() );
1833  $this->addModuleScripts( $parserOutput->getModuleScripts() );
1834  $this->addModuleStyles( $parserOutput->getModuleStyles() );
1835 
1836  $this->addJsConfigVars( $parserOutput->getJsConfigVars() );
1837  }
1838 
1846  public function addParserOutputText( $parserOutput, $poOptions = [] ) {
1847  $text = $parserOutput->getText( $poOptions );
1848  // Avoid PHP 7.1 warning of passing $this by reference
1849  $outputPage = $this;
1850  Hooks::runWithoutAbort( 'OutputPageBeforeHTML', [ &$outputPage, &$text ] );
1851  $this->addHTML( $text );
1852  }
1853 
1860  function addParserOutput( $parserOutput, $poOptions = [] ) {
1861  $this->addParserOutputMetadata( $parserOutput );
1862  $this->addParserOutputText( $parserOutput, $poOptions );
1863  }
1864 
1870  public function addTemplate( &$template ) {
1871  $this->addHTML( $template->getHTML() );
1872  }
1873 
1886  public function parse( $text, $linestart = true, $interface = false, $language = null ) {
1887  global $wgParser;
1888 
1889  if ( is_null( $this->getTitle() ) ) {
1890  throw new MWException( 'Empty $mTitle in ' . __METHOD__ );
1891  }
1892 
1893  $popts = $this->parserOptions();
1894  if ( $interface ) {
1895  $popts->setInterfaceMessage( true );
1896  }
1897  if ( $language !== null ) {
1898  $oldLang = $popts->setTargetLanguage( $language );
1899  }
1900 
1901  $parserOutput = $wgParser->getFreshParser()->parse(
1902  $text, $this->getTitle(), $popts,
1903  $linestart, true, $this->mRevisionId
1904  );
1905 
1906  if ( $interface ) {
1907  $popts->setInterfaceMessage( false );
1908  }
1909  if ( $language !== null ) {
1910  $popts->setTargetLanguage( $oldLang );
1911  }
1912 
1913  return $parserOutput->getText( [
1914  'enableSectionEditLinks' => false,
1915  ] );
1916  }
1917 
1928  public function parseInline( $text, $linestart = true, $interface = false ) {
1929  $parsed = $this->parse( $text, $linestart, $interface );
1930  return Parser::stripOuterParagraph( $parsed );
1931  }
1932 
1938  public function setCdnMaxage( $maxage ) {
1939  $this->mCdnMaxage = min( $maxage, $this->mCdnMaxageLimit );
1940  }
1941 
1948  public function lowerCdnMaxage( $maxage ) {
1949  $this->mCdnMaxageLimit = min( $maxage, $this->mCdnMaxageLimit );
1950  $this->setCdnMaxage( $this->mCdnMaxage );
1951  }
1952 
1966  public function adaptCdnTTL( $mtime, $minTTL = 0, $maxTTL = 0 ) {
1967  $minTTL = $minTTL ?: IExpiringStore::TTL_MINUTE;
1968  $maxTTL = $maxTTL ?: $this->getConfig()->get( 'SquidMaxage' );
1969 
1970  if ( $mtime === null || $mtime === false ) {
1971  return $minTTL; // entity does not exist
1972  }
1973 
1974  $age = time() - wfTimestamp( TS_UNIX, $mtime );
1975  $adaptiveTTL = max( 0.9 * $age, $minTTL );
1976  $adaptiveTTL = min( $adaptiveTTL, $maxTTL );
1977 
1978  $this->lowerCdnMaxage( (int)$adaptiveTTL );
1979 
1980  return $adaptiveTTL;
1981  }
1982 
1990  public function enableClientCache( $state ) {
1991  return wfSetVar( $this->mEnableClientCache, $state );
1992  }
1993 
1999  function getCacheVaryCookies() {
2000  static $cookies;
2001  if ( $cookies === null ) {
2002  $config = $this->getConfig();
2003  $cookies = array_merge(
2004  SessionManager::singleton()->getVaryCookies(),
2005  [
2006  'forceHTTPS',
2007  ],
2008  $config->get( 'CacheVaryCookies' )
2009  );
2010  Hooks::run( 'GetCacheVaryCookies', [ $this, &$cookies ] );
2011  }
2012  return $cookies;
2013  }
2014 
2022  $request = $this->getRequest();
2023  foreach ( $this->getCacheVaryCookies() as $cookieName ) {
2024  if ( $request->getCookie( $cookieName, '', '' ) !== '' ) {
2025  wfDebug( __METHOD__ . ": found $cookieName\n" );
2026  return true;
2027  }
2028  }
2029  wfDebug( __METHOD__ . ": no cache-varying cookies found\n" );
2030  return false;
2031  }
2032 
2041  public function addVaryHeader( $header, array $option = null ) {
2042  if ( !array_key_exists( $header, $this->mVaryHeader ) ) {
2043  $this->mVaryHeader[$header] = [];
2044  }
2045  if ( !is_array( $option ) ) {
2046  $option = [];
2047  }
2048  $this->mVaryHeader[$header] = array_unique( array_merge( $this->mVaryHeader[$header], $option ) );
2049  }
2050 
2057  public function getVaryHeader() {
2058  // If we vary on cookies, let's make sure it's always included here too.
2059  if ( $this->getCacheVaryCookies() ) {
2060  $this->addVaryHeader( 'Cookie' );
2061  }
2062 
2063  foreach ( SessionManager::singleton()->getVaryHeaders() as $header => $options ) {
2064  $this->addVaryHeader( $header, $options );
2065  }
2066  return 'Vary: ' . implode( ', ', array_keys( $this->mVaryHeader ) );
2067  }
2068 
2074  public function addLinkHeader( $header ) {
2075  $this->mLinkHeader[] = $header;
2076  }
2077 
2083  public function getLinkHeader() {
2084  if ( !$this->mLinkHeader ) {
2085  return false;
2086  }
2087 
2088  return 'Link: ' . implode( ',', $this->mLinkHeader );
2089  }
2090 
2096  public function getKeyHeader() {
2097  $cvCookies = $this->getCacheVaryCookies();
2098 
2099  $cookiesOption = [];
2100  foreach ( $cvCookies as $cookieName ) {
2101  $cookiesOption[] = 'param=' . $cookieName;
2102  }
2103  $this->addVaryHeader( 'Cookie', $cookiesOption );
2104 
2105  foreach ( SessionManager::singleton()->getVaryHeaders() as $header => $options ) {
2106  $this->addVaryHeader( $header, $options );
2107  }
2108 
2109  $headers = [];
2110  foreach ( $this->mVaryHeader as $header => $option ) {
2111  $newheader = $header;
2112  if ( is_array( $option ) && count( $option ) > 0 ) {
2113  $newheader .= ';' . implode( ';', $option );
2114  }
2115  $headers[] = $newheader;
2116  }
2117  $key = 'Key: ' . implode( ',', $headers );
2118 
2119  return $key;
2120  }
2121 
2130  function addAcceptLanguage() {
2131  $title = $this->getTitle();
2132  if ( !$title instanceof Title ) {
2133  return;
2134  }
2135 
2136  $lang = $title->getPageLanguage();
2137  if ( !$this->getRequest()->getCheck( 'variant' ) && $lang->hasVariants() ) {
2138  $variants = $lang->getVariants();
2139  $aloption = [];
2140  foreach ( $variants as $variant ) {
2141  if ( $variant === $lang->getCode() ) {
2142  continue;
2143  } else {
2144  $aloption[] = 'substr=' . $variant;
2145 
2146  // IE and some other browsers use BCP 47 standards in
2147  // their Accept-Language header, like "zh-CN" or "zh-Hant".
2148  // We should handle these too.
2149  $variantBCP47 = LanguageCode::bcp47( $variant );
2150  if ( $variantBCP47 !== $variant ) {
2151  $aloption[] = 'substr=' . $variantBCP47;
2152  }
2153  }
2154  }
2155  $this->addVaryHeader( 'Accept-Language', $aloption );
2156  }
2157  }
2158 
2169  public function preventClickjacking( $enable = true ) {
2170  $this->mPreventClickjacking = $enable;
2171  }
2172 
2178  public function allowClickjacking() {
2179  $this->mPreventClickjacking = false;
2180  }
2181 
2188  public function getPreventClickjacking() {
2190  }
2191 
2199  public function getFrameOptions() {
2200  $config = $this->getConfig();
2201  if ( $config->get( 'BreakFrames' ) ) {
2202  return 'DENY';
2203  } elseif ( $this->mPreventClickjacking && $config->get( 'EditPageFrameOptions' ) ) {
2204  return $config->get( 'EditPageFrameOptions' );
2205  }
2206  return false;
2207  }
2208 
2212  public function sendCacheControl() {
2213  $response = $this->getRequest()->response();
2214  $config = $this->getConfig();
2215 
2216  $this->addVaryHeader( 'Cookie' );
2217  $this->addAcceptLanguage();
2218 
2219  # don't serve compressed data to clients who can't handle it
2220  # maintain different caches for logged-in users and non-logged in ones
2221  $response->header( $this->getVaryHeader() );
2222 
2223  if ( $config->get( 'UseKeyHeader' ) ) {
2224  $response->header( $this->getKeyHeader() );
2225  }
2226 
2227  if ( $this->mEnableClientCache ) {
2228  if (
2229  $config->get( 'UseSquid' ) &&
2230  !$response->hasCookies() &&
2231  !SessionManager::getGlobalSession()->isPersistent() &&
2232  !$this->isPrintable() &&
2233  $this->mCdnMaxage != 0 &&
2234  !$this->haveCacheVaryCookies()
2235  ) {
2236  if ( $config->get( 'UseESI' ) ) {
2237  # We'll purge the proxy cache explicitly, but require end user agents
2238  # to revalidate against the proxy on each visit.
2239  # Surrogate-Control controls our CDN, Cache-Control downstream caches
2240  wfDebug( __METHOD__ .
2241  ": proxy caching with ESI; {$this->mLastModified} **", 'private' );
2242  # start with a shorter timeout for initial testing
2243  # header( 'Surrogate-Control: max-age=2678400+2678400, content="ESI/1.0"');
2244  $response->header(
2245  "Surrogate-Control: max-age={$config->get( 'SquidMaxage' )}" .
2246  "+{$this->mCdnMaxage}, content=\"ESI/1.0\""
2247  );
2248  $response->header( 'Cache-Control: s-maxage=0, must-revalidate, max-age=0' );
2249  } else {
2250  # We'll purge the proxy cache for anons explicitly, but require end user agents
2251  # to revalidate against the proxy on each visit.
2252  # IMPORTANT! The CDN needs to replace the Cache-Control header with
2253  # Cache-Control: s-maxage=0, must-revalidate, max-age=0
2254  wfDebug( __METHOD__ .
2255  ": local proxy caching; {$this->mLastModified} **", 'private' );
2256  # start with a shorter timeout for initial testing
2257  # header( "Cache-Control: s-maxage=2678400, must-revalidate, max-age=0" );
2258  $response->header( "Cache-Control: " .
2259  "s-maxage={$this->mCdnMaxage}, must-revalidate, max-age=0" );
2260  }
2261  } else {
2262  # We do want clients to cache if they can, but they *must* check for updates
2263  # on revisiting the page.
2264  wfDebug( __METHOD__ . ": private caching; {$this->mLastModified} **", 'private' );
2265  $response->header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', 0 ) . ' GMT' );
2266  $response->header( "Cache-Control: private, must-revalidate, max-age=0" );
2267  }
2268  if ( $this->mLastModified ) {
2269  $response->header( "Last-Modified: {$this->mLastModified}" );
2270  }
2271  } else {
2272  wfDebug( __METHOD__ . ": no caching **", 'private' );
2273 
2274  # In general, the absence of a last modified header should be enough to prevent
2275  # the client from using its cache. We send a few other things just to make sure.
2276  $response->header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', 0 ) . ' GMT' );
2277  $response->header( 'Cache-Control: no-cache, no-store, max-age=0, must-revalidate' );
2278  $response->header( 'Pragma: no-cache' );
2279  }
2280  }
2281 
2292  public function output( $return = false ) {
2294 
2295  if ( $this->mDoNothing ) {
2296  return $return ? '' : null;
2297  }
2298 
2299  $response = $this->getRequest()->response();
2300  $config = $this->getConfig();
2301 
2302  if ( $this->mRedirect != '' ) {
2303  # Standards require redirect URLs to be absolute
2304  $this->mRedirect = wfExpandUrl( $this->mRedirect, PROTO_CURRENT );
2305 
2306  $redirect = $this->mRedirect;
2308 
2309  if ( Hooks::run( "BeforePageRedirect", [ $this, &$redirect, &$code ] ) ) {
2310  if ( $code == '301' || $code == '303' ) {
2311  if ( !$config->get( 'DebugRedirects' ) ) {
2312  $response->statusHeader( $code );
2313  }
2314  $this->mLastModified = wfTimestamp( TS_RFC2822 );
2315  }
2316  if ( $config->get( 'VaryOnXFP' ) ) {
2317  $this->addVaryHeader( 'X-Forwarded-Proto' );
2318  }
2319  $this->sendCacheControl();
2320 
2321  $response->header( "Content-Type: text/html; charset=utf-8" );
2322  if ( $config->get( 'DebugRedirects' ) ) {
2323  $url = htmlspecialchars( $redirect );
2324  print "<!DOCTYPE html>\n<html>\n<head>\n<title>Redirect</title>\n</head>\n<body>\n";
2325  print "<p>Location: <a href=\"$url\">$url</a></p>\n";
2326  print "</body>\n</html>\n";
2327  } else {
2328  $response->header( 'Location: ' . $redirect );
2329  }
2330  }
2331 
2332  return $return ? '' : null;
2333  } elseif ( $this->mStatusCode ) {
2334  $response->statusHeader( $this->mStatusCode );
2335  }
2336 
2337  # Buffer output; final headers may depend on later processing
2338  ob_start();
2339 
2340  $response->header( 'Content-type: ' . $config->get( 'MimeType' ) . '; charset=UTF-8' );
2341  $response->header( 'Content-language: ' . $wgContLang->getHtmlCode() );
2342 
2343  // Avoid Internet Explorer "compatibility view" in IE 8-10, so that
2344  // jQuery etc. can work correctly.
2345  $response->header( 'X-UA-Compatible: IE=Edge' );
2346 
2347  if ( !$this->mArticleBodyOnly ) {
2348  $sk = $this->getSkin();
2349 
2350  if ( $sk->shouldPreloadLogo() ) {
2351  $this->addLogoPreloadLinkHeaders();
2352  }
2353  }
2354 
2355  $linkHeader = $this->getLinkHeader();
2356  if ( $linkHeader ) {
2357  $response->header( $linkHeader );
2358  }
2359 
2360  // Prevent framing, if requested
2361  $frameOptions = $this->getFrameOptions();
2362  if ( $frameOptions ) {
2363  $response->header( "X-Frame-Options: $frameOptions" );
2364  }
2365 
2366  if ( $this->mArticleBodyOnly ) {
2367  echo $this->mBodytext;
2368  } else {
2369  // Enable safe mode if requested
2370  if ( $this->getRequest()->getBool( 'safemode' ) ) {
2371  $this->disallowUserJs();
2372  }
2373 
2374  $sk = $this->getSkin();
2375  foreach ( $sk->getDefaultModules() as $group ) {
2376  $this->addModules( $group );
2377  }
2378 
2379  MWDebug::addModules( $this );
2380 
2381  // Avoid PHP 7.1 warning of passing $this by reference
2382  $outputPage = $this;
2383  // Hook that allows last minute changes to the output page, e.g.
2384  // adding of CSS or Javascript by extensions.
2385  Hooks::runWithoutAbort( 'BeforePageDisplay', [ &$outputPage, &$sk ] );
2386 
2387  try {
2388  $sk->outputPage();
2389  } catch ( Exception $e ) {
2390  ob_end_clean(); // bug T129657
2391  throw $e;
2392  }
2393  }
2394 
2395  try {
2396  // This hook allows last minute changes to final overall output by modifying output buffer
2397  Hooks::runWithoutAbort( 'AfterFinalPageOutput', [ $this ] );
2398  } catch ( Exception $e ) {
2399  ob_end_clean(); // bug T129657
2400  throw $e;
2401  }
2402 
2403  $this->sendCacheControl();
2404 
2405  if ( $return ) {
2406  return ob_get_clean();
2407  } else {
2408  ob_end_flush();
2409  return null;
2410  }
2411  }
2412 
2423  public function prepareErrorPage( $pageTitle, $htmlTitle = false ) {
2424  $this->setPageTitle( $pageTitle );
2425  if ( $htmlTitle !== false ) {
2426  $this->setHTMLTitle( $htmlTitle );
2427  }
2428  $this->setRobotPolicy( 'noindex,nofollow' );
2429  $this->setArticleRelated( false );
2430  $this->enableClientCache( false );
2431  $this->mRedirect = '';
2432  $this->clearSubtitle();
2433  $this->clearHTML();
2434  }
2435 
2448  public function showErrorPage( $title, $msg, $params = [] ) {
2449  if ( !$title instanceof Message ) {
2450  $title = $this->msg( $title );
2451  }
2452 
2453  $this->prepareErrorPage( $title );
2454 
2455  if ( $msg instanceof Message ) {
2456  if ( $params !== [] ) {
2457  trigger_error( 'Argument ignored: $params. The message parameters argument '
2458  . 'is discarded when the $msg argument is a Message object instead of '
2459  . 'a string.', E_USER_NOTICE );
2460  }
2461  $this->addHTML( $msg->parseAsBlock() );
2462  } else {
2463  $this->addWikiMsgArray( $msg, $params );
2464  }
2465 
2466  $this->returnToMain();
2467  }
2468 
2475  public function showPermissionsErrorPage( array $errors, $action = null ) {
2476  foreach ( $errors as $key => $error ) {
2477  $errors[$key] = (array)$error;
2478  }
2479 
2480  // For some action (read, edit, create and upload), display a "login to do this action"
2481  // error if all of the following conditions are met:
2482  // 1. the user is not logged in
2483  // 2. the only error is insufficient permissions (i.e. no block or something else)
2484  // 3. the error can be avoided simply by logging in
2485  if ( in_array( $action, [ 'read', 'edit', 'createpage', 'createtalk', 'upload' ] )
2486  && $this->getUser()->isAnon() && count( $errors ) == 1 && isset( $errors[0][0] )
2487  && ( $errors[0][0] == 'badaccess-groups' || $errors[0][0] == 'badaccess-group0' )
2488  && ( User::groupHasPermission( 'user', $action )
2489  || User::groupHasPermission( 'autoconfirmed', $action ) )
2490  ) {
2491  $displayReturnto = null;
2492 
2493  # Due to T34276, if a user does not have read permissions,
2494  # $this->getTitle() will just give Special:Badtitle, which is
2495  # not especially useful as a returnto parameter. Use the title
2496  # from the request instead, if there was one.
2497  $request = $this->getRequest();
2498  $returnto = Title::newFromText( $request->getVal( 'title', '' ) );
2499  if ( $action == 'edit' ) {
2500  $msg = 'whitelistedittext';
2501  $displayReturnto = $returnto;
2502  } elseif ( $action == 'createpage' || $action == 'createtalk' ) {
2503  $msg = 'nocreatetext';
2504  } elseif ( $action == 'upload' ) {
2505  $msg = 'uploadnologintext';
2506  } else { # Read
2507  $msg = 'loginreqpagetext';
2508  $displayReturnto = Title::newMainPage();
2509  }
2510 
2511  $query = [];
2512 
2513  if ( $returnto ) {
2514  $query['returnto'] = $returnto->getPrefixedText();
2515 
2516  if ( !$request->wasPosted() ) {
2517  $returntoquery = $request->getValues();
2518  unset( $returntoquery['title'] );
2519  unset( $returntoquery['returnto'] );
2520  unset( $returntoquery['returntoquery'] );
2521  $query['returntoquery'] = wfArrayToCgi( $returntoquery );
2522  }
2523  }
2524  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
2525  $loginLink = $linkRenderer->makeKnownLink(
2526  SpecialPage::getTitleFor( 'Userlogin' ),
2527  $this->msg( 'loginreqlink' )->text(),
2528  [],
2529  $query
2530  );
2531 
2532  $this->prepareErrorPage( $this->msg( 'loginreqtitle' ) );
2533  $this->addHTML( $this->msg( $msg )->rawParams( $loginLink )->parse() );
2534 
2535  # Don't return to a page the user can't read otherwise
2536  # we'll end up in a pointless loop
2537  if ( $displayReturnto && $displayReturnto->userCan( 'read', $this->getUser() ) ) {
2538  $this->returnToMain( null, $displayReturnto );
2539  }
2540  } else {
2541  $this->prepareErrorPage( $this->msg( 'permissionserrors' ) );
2542  $this->addWikiText( $this->formatPermissionsErrorMessage( $errors, $action ) );
2543  }
2544  }
2545 
2552  public function versionRequired( $version ) {
2553  $this->prepareErrorPage( $this->msg( 'versionrequired', $version ) );
2554 
2555  $this->addWikiMsg( 'versionrequiredtext', $version );
2556  $this->returnToMain();
2557  }
2558 
2566  public function formatPermissionsErrorMessage( array $errors, $action = null ) {
2567  if ( $action == null ) {
2568  $text = $this->msg( 'permissionserrorstext', count( $errors ) )->plain() . "\n\n";
2569  } else {
2570  $action_desc = $this->msg( "action-$action" )->plain();
2571  $text = $this->msg(
2572  'permissionserrorstext-withaction',
2573  count( $errors ),
2574  $action_desc
2575  )->plain() . "\n\n";
2576  }
2577 
2578  if ( count( $errors ) > 1 ) {
2579  $text .= '<ul class="permissions-errors">' . "\n";
2580 
2581  foreach ( $errors as $error ) {
2582  $text .= '<li>';
2583  $text .= call_user_func_array( [ $this, 'msg' ], $error )->plain();
2584  $text .= "</li>\n";
2585  }
2586  $text .= '</ul>';
2587  } else {
2588  $text .= "<div class=\"permissions-errors\">\n" .
2589  call_user_func_array( [ $this, 'msg' ], reset( $errors ) )->plain() .
2590  "\n</div>";
2591  }
2592 
2593  return $text;
2594  }
2595 
2605  public function showLagWarning( $lag ) {
2606  $config = $this->getConfig();
2607  if ( $lag >= $config->get( 'SlaveLagWarning' ) ) {
2608  $lag = floor( $lag ); // floor to avoid nano seconds to display
2609  $message = $lag < $config->get( 'SlaveLagCritical' )
2610  ? 'lag-warn-normal'
2611  : 'lag-warn-high';
2612  $wrap = Html::rawElement( 'div', [ 'class' => "mw-{$message}" ], "\n$1\n" );
2613  $this->wrapWikiMsg( "$wrap\n", [ $message, $this->getLanguage()->formatNum( $lag ) ] );
2614  }
2615  }
2616 
2617  public function showFatalError( $message ) {
2618  $this->prepareErrorPage( $this->msg( 'internalerror' ) );
2619 
2620  $this->addHTML( $message );
2621  }
2622 
2623  public function showUnexpectedValueError( $name, $val ) {
2624  $this->showFatalError( $this->msg( 'unexpected', $name, $val )->text() );
2625  }
2626 
2627  public function showFileCopyError( $old, $new ) {
2628  $this->showFatalError( $this->msg( 'filecopyerror', $old, $new )->text() );
2629  }
2630 
2631  public function showFileRenameError( $old, $new ) {
2632  $this->showFatalError( $this->msg( 'filerenameerror', $old, $new )->text() );
2633  }
2634 
2635  public function showFileDeleteError( $name ) {
2636  $this->showFatalError( $this->msg( 'filedeleteerror', $name )->text() );
2637  }
2638 
2639  public function showFileNotFoundError( $name ) {
2640  $this->showFatalError( $this->msg( 'filenotfound', $name )->text() );
2641  }
2642 
2651  public function addReturnTo( $title, array $query = [], $text = null, $options = [] ) {
2652  $linkRenderer = MediaWikiServices::getInstance()
2653  ->getLinkRendererFactory()->createFromLegacyOptions( $options );
2654  $link = $this->msg( 'returnto' )->rawParams(
2655  $linkRenderer->makeLink( $title, $text, [], $query ) )->escaped();
2656  $this->addHTML( "<p id=\"mw-returnto\">{$link}</p>\n" );
2657  }
2658 
2667  public function returnToMain( $unused = null, $returnto = null, $returntoquery = null ) {
2668  if ( $returnto == null ) {
2669  $returnto = $this->getRequest()->getText( 'returnto' );
2670  }
2671 
2672  if ( $returntoquery == null ) {
2673  $returntoquery = $this->getRequest()->getText( 'returntoquery' );
2674  }
2675 
2676  if ( $returnto === '' ) {
2677  $returnto = Title::newMainPage();
2678  }
2679 
2680  if ( is_object( $returnto ) ) {
2681  $titleObj = $returnto;
2682  } else {
2683  $titleObj = Title::newFromText( $returnto );
2684  }
2685  // We don't want people to return to external interwiki. That
2686  // might potentially be used as part of a phishing scheme
2687  if ( !is_object( $titleObj ) || $titleObj->isExternal() ) {
2688  $titleObj = Title::newMainPage();
2689  }
2690 
2691  $this->addReturnTo( $titleObj, wfCgiToArray( $returntoquery ) );
2692  }
2693 
2694  private function getRlClientContext() {
2695  if ( !$this->rlClientContext ) {
2697  [], // modules; not relevant
2698  $this->getLanguage()->getCode(),
2699  $this->getSkin()->getSkinName(),
2700  $this->getUser()->isLoggedIn() ? $this->getUser()->getName() : null,
2701  null, // version; not relevant
2703  null, // only; not relevant
2704  $this->isPrintable(),
2705  $this->getRequest()->getBool( 'handheld' )
2706  );
2707  $this->rlClientContext = new ResourceLoaderContext(
2708  $this->getResourceLoader(),
2709  new FauxRequest( $query )
2710  );
2711  }
2712  return $this->rlClientContext;
2713  }
2714 
2726  public function getRlClient() {
2727  if ( !$this->rlClient ) {
2728  $context = $this->getRlClientContext();
2729  $rl = $this->getResourceLoader();
2730  $this->addModules( [
2731  'user.options',
2732  'user.tokens',
2733  ] );
2734  $this->addModuleStyles( [
2735  'site.styles',
2736  'noscript',
2737  'user.styles',
2738  ] );
2739  $this->getSkin()->setupSkinUserCss( $this );
2740 
2741  // Prepare exempt modules for buildExemptModules()
2742  $exemptGroups = [ 'site' => [], 'noscript' => [], 'private' => [], 'user' => [] ];
2743  $exemptStates = [];
2744  $moduleStyles = $this->getModuleStyles( /*filter*/ true );
2745 
2746  // Preload getTitleInfo for isKnownEmpty calls below and in ResourceLoaderClientHtml
2747  // Separate user-specific batch for improved cache-hit ratio.
2748  $userBatch = [ 'user.styles', 'user' ];
2749  $siteBatch = array_diff( $moduleStyles, $userBatch );
2750  $dbr = wfGetDB( DB_REPLICA );
2753 
2754  // Filter out modules handled by buildExemptModules()
2755  $moduleStyles = array_filter( $moduleStyles,
2756  function ( $name ) use ( $rl, $context, &$exemptGroups, &$exemptStates ) {
2757  $module = $rl->getModule( $name );
2758  if ( $module ) {
2759  if ( $name === 'user.styles' && $this->isUserCssPreview() ) {
2760  $exemptStates[$name] = 'ready';
2761  // Special case in buildExemptModules()
2762  return false;
2763  }
2764  $group = $module->getGroup();
2765  if ( isset( $exemptGroups[$group] ) ) {
2766  $exemptStates[$name] = 'ready';
2767  if ( !$module->isKnownEmpty( $context ) ) {
2768  // E.g. Don't output empty <styles>
2769  $exemptGroups[$group][] = $name;
2770  }
2771  return false;
2772  }
2773  }
2774  return true;
2775  }
2776  );
2777  $this->rlExemptStyleModules = $exemptGroups;
2778 
2779  $isUserModuleFiltered = !$this->filterModules( [ 'user' ] );
2780  // If this page filters out 'user', makeResourceLoaderLink will drop it.
2781  // Avoid indefinite "loading" state or untrue "ready" state (T145368).
2782  if ( !$isUserModuleFiltered ) {
2783  // Manually handled by getBottomScripts()
2784  $userModule = $rl->getModule( 'user' );
2785  $userState = $userModule->isKnownEmpty( $context ) && !$this->isUserJsPreview()
2786  ? 'ready'
2787  : 'loading';
2788  $this->rlUserModuleState = $exemptStates['user'] = $userState;
2789  }
2790 
2792  'target' => $this->getTarget(),
2793  ] );
2794  $rlClient->setConfig( $this->getJSVars() );
2795  $rlClient->setModules( $this->getModules( /*filter*/ true ) );
2796  $rlClient->setModuleStyles( $moduleStyles );
2797  $rlClient->setModuleScripts( $this->getModuleScripts( /*filter*/ true ) );
2798  $rlClient->setExemptStates( $exemptStates );
2799  $this->rlClient = $rlClient;
2800  }
2801  return $this->rlClient;
2802  }
2803 
2809  public function headElement( Skin $sk, $includeStyle = true ) {
2811 
2812  $userdir = $this->getLanguage()->getDir();
2813  $sitedir = $wgContLang->getDir();
2814 
2815  $pieces = [];
2817  $this->getRlClient()->getDocumentAttributes(),
2819  ) );
2820  $pieces[] = Html::openElement( 'head' );
2821 
2822  if ( $this->getHTMLTitle() == '' ) {
2823  $this->setHTMLTitle( $this->msg( 'pagetitle', $this->getPageTitle() )->inContentLanguage() );
2824  }
2825 
2826  if ( !Html::isXmlMimeType( $this->getConfig()->get( 'MimeType' ) ) ) {
2827  // Add <meta charset="UTF-8">
2828  // This should be before <title> since it defines the charset used by
2829  // text including the text inside <title>.
2830  // The spec recommends defining XHTML5's charset using the XML declaration
2831  // instead of meta.
2832  // Our XML declaration is output by Html::htmlHeader.
2833  // https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-content-type
2834  // https://html.spec.whatwg.org/multipage/semantics.html#charset
2835  $pieces[] = Html::element( 'meta', [ 'charset' => 'UTF-8' ] );
2836  }
2837 
2838  $pieces[] = Html::element( 'title', null, $this->getHTMLTitle() );
2839  $pieces[] = $this->getRlClient()->getHeadHtml();
2840  $pieces[] = $this->buildExemptModules();
2841  $pieces = array_merge( $pieces, array_values( $this->getHeadLinksArray() ) );
2842  $pieces = array_merge( $pieces, array_values( $this->mHeadItems ) );
2843 
2844  // Use an IE conditional comment to serve the script only to old IE
2845  $pieces[] = '<!--[if lt IE 9]>' .
2848  [ 'html5shiv' ],
2850  [ 'sync' => true ]
2851  ) .
2852  '<![endif]-->';
2853 
2854  $pieces[] = Html::closeElement( 'head' );
2855 
2856  $bodyClasses = $this->mAdditionalBodyClasses;
2857  $bodyClasses[] = 'mediawiki';
2858 
2859  # Classes for LTR/RTL directionality support
2860  $bodyClasses[] = $userdir;
2861  $bodyClasses[] = "sitedir-$sitedir";
2862 
2863  $underline = $this->getUser()->getOption( 'underline' );
2864  if ( $underline < 2 ) {
2865  // The following classes can be used here:
2866  // * mw-underline-always
2867  // * mw-underline-never
2868  $bodyClasses[] = 'mw-underline-' . ( $underline ? 'always' : 'never' );
2869  }
2870 
2871  if ( $this->getLanguage()->capitalizeAllNouns() ) {
2872  # A <body> class is probably not the best way to do this . . .
2873  $bodyClasses[] = 'capitalize-all-nouns';
2874  }
2875 
2876  // Parser feature migration class
2877  // The idea is that this will eventually be removed, after the wikitext
2878  // which requires it is cleaned up.
2879  $bodyClasses[] = 'mw-hide-empty-elt';
2880 
2881  $bodyClasses[] = $sk->getPageClasses( $this->getTitle() );
2882  $bodyClasses[] = 'skin-' . Sanitizer::escapeClass( $sk->getSkinName() );
2883  $bodyClasses[] =
2884  'action-' . Sanitizer::escapeClass( Action::getActionName( $this->getContext() ) );
2885 
2886  $bodyAttrs = [];
2887  // While the implode() is not strictly needed, it's used for backwards compatibility
2888  // (this used to be built as a string and hooks likely still expect that).
2889  $bodyAttrs['class'] = implode( ' ', $bodyClasses );
2890 
2891  // Allow skins and extensions to add body attributes they need
2892  $sk->addToBodyAttributes( $this, $bodyAttrs );
2893  Hooks::run( 'OutputPageBodyAttributes', [ $this, $sk, &$bodyAttrs ] );
2894 
2895  $pieces[] = Html::openElement( 'body', $bodyAttrs );
2896 
2897  return self::combineWrappedStrings( $pieces );
2898  }
2899 
2905  public function getResourceLoader() {
2906  if ( is_null( $this->mResourceLoader ) ) {
2907  $this->mResourceLoader = new ResourceLoader(
2908  $this->getConfig(),
2909  LoggerFactory::getInstance( 'resourceloader' )
2910  );
2911  }
2912  return $this->mResourceLoader;
2913  }
2914 
2923  public function makeResourceLoaderLink( $modules, $only, array $extraQuery = [] ) {
2924  // Apply 'target' and 'origin' filters
2925  $modules = $this->filterModules( (array)$modules, null, $only );
2926 
2928  $this->getRlClientContext(),
2929  $modules,
2930  $only,
2931  $extraQuery
2932  );
2933  }
2934 
2941  protected static function combineWrappedStrings( array $chunks ) {
2942  // Filter out empty values
2943  $chunks = array_filter( $chunks, 'strlen' );
2944  return WrappedString::join( "\n", $chunks );
2945  }
2946 
2947  private function isUserJsPreview() {
2948  return $this->getConfig()->get( 'AllowUserJs' )
2949  && $this->getTitle()
2950  && $this->getTitle()->isUserJsConfigPage()
2951  && $this->userCanPreview();
2952  }
2953 
2954  protected function isUserCssPreview() {
2955  return $this->getConfig()->get( 'AllowUserCss' )
2956  && $this->getTitle()
2957  && $this->getTitle()->isUserCssConfigPage()
2958  && $this->userCanPreview();
2959  }
2960 
2967  public function getBottomScripts() {
2968  $chunks = [];
2969  $chunks[] = $this->getRlClient()->getBodyHtml();
2970 
2971  // Legacy non-ResourceLoader scripts
2972  $chunks[] = $this->mScripts;
2973 
2974  // Exempt 'user' module
2975  // - May need excludepages for live preview. (T28283)
2976  // - Must use TYPE_COMBINED so its response is handled by mw.loader.implement() which
2977  // ensures execution is scheduled after the "site" module.
2978  // - Don't load if module state is already resolved as "ready".
2979  if ( $this->rlUserModuleState === 'loading' ) {
2980  if ( $this->isUserJsPreview() ) {
2981  $chunks[] = $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_COMBINED,
2982  [ 'excludepage' => $this->getTitle()->getPrefixedDBkey() ]
2983  );
2985  Xml::encodeJsCall( 'mw.loader.using', [
2986  [ 'user', 'site' ],
2987  new XmlJsCode(
2988  'function () {'
2989  . Xml::encodeJsCall( '$.globalEval', [
2990  $this->getRequest()->getText( 'wpTextbox1' )
2991  ] )
2992  . '}'
2993  )
2994  ] )
2995  );
2996  // FIXME: If the user is previewing, say, ./vector.js, his ./common.js will be loaded
2997  // asynchronously and may arrive *after* the inline script here. So the previewed code
2998  // may execute before ./common.js runs. Normally, ./common.js runs before ./vector.js.
2999  // Similarly, when previewing ./common.js and the user module does arrive first,
3000  // it will arrive without common.js and the inline script runs after.
3001  // Thus running common after the excluded subpage.
3002  } else {
3003  // Load normally
3004  $chunks[] = $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_COMBINED );
3005  }
3006  }
3007 
3008  if ( $this->limitReportJSData ) {
3011  [ 'wgPageParseReport' => $this->limitReportJSData ]
3012  )
3013  );
3014  }
3015 
3016  return self::combineWrappedStrings( $chunks );
3017  }
3018 
3025  public function getJsConfigVars() {
3026  return $this->mJsConfigVars;
3027  }
3028 
3035  public function addJsConfigVars( $keys, $value = null ) {
3036  if ( is_array( $keys ) ) {
3037  foreach ( $keys as $key => $value ) {
3038  $this->mJsConfigVars[$key] = $value;
3039  }
3040  return;
3041  }
3042 
3043  $this->mJsConfigVars[$keys] = $value;
3044  }
3045 
3055  public function getJSVars() {
3057 
3058  $curRevisionId = 0;
3059  $articleId = 0;
3060  $canonicalSpecialPageName = false; # T23115
3061 
3062  $title = $this->getTitle();
3063  $ns = $title->getNamespace();
3064  $canonicalNamespace = MWNamespace::exists( $ns )
3066  : $title->getNsText();
3067 
3068  $sk = $this->getSkin();
3069  // Get the relevant title so that AJAX features can use the correct page name
3070  // when making API requests from certain special pages (T36972).
3071  $relevantTitle = $sk->getRelevantTitle();
3072  $relevantUser = $sk->getRelevantUser();
3073 
3074  if ( $ns == NS_SPECIAL ) {
3075  list( $canonicalSpecialPageName, /*...*/ ) =
3077  } elseif ( $this->canUseWikiPage() ) {
3078  $wikiPage = $this->getWikiPage();
3079  $curRevisionId = $wikiPage->getLatest();
3080  $articleId = $wikiPage->getId();
3081  }
3082 
3083  $lang = $title->getPageViewLanguage();
3084 
3085  // Pre-process information
3086  $separatorTransTable = $lang->separatorTransformTable();
3087  $separatorTransTable = $separatorTransTable ? $separatorTransTable : [];
3088  $compactSeparatorTransTable = [
3089  implode( "\t", array_keys( $separatorTransTable ) ),
3090  implode( "\t", $separatorTransTable ),
3091  ];
3092  $digitTransTable = $lang->digitTransformTable();
3093  $digitTransTable = $digitTransTable ? $digitTransTable : [];
3094  $compactDigitTransTable = [
3095  implode( "\t", array_keys( $digitTransTable ) ),
3096  implode( "\t", $digitTransTable ),
3097  ];
3098 
3099  $user = $this->getUser();
3100 
3101  $vars = [
3102  'wgCanonicalNamespace' => $canonicalNamespace,
3103  'wgCanonicalSpecialPageName' => $canonicalSpecialPageName,
3104  'wgNamespaceNumber' => $title->getNamespace(),
3105  'wgPageName' => $title->getPrefixedDBkey(),
3106  'wgTitle' => $title->getText(),
3107  'wgCurRevisionId' => $curRevisionId,
3108  'wgRevisionId' => (int)$this->getRevisionId(),
3109  'wgArticleId' => $articleId,
3110  'wgIsArticle' => $this->isArticle(),
3111  'wgIsRedirect' => $title->isRedirect(),
3112  'wgAction' => Action::getActionName( $this->getContext() ),
3113  'wgUserName' => $user->isAnon() ? null : $user->getName(),
3114  'wgUserGroups' => $user->getEffectiveGroups(),
3115  'wgCategories' => $this->getCategories(),
3116  'wgBreakFrames' => $this->getFrameOptions() == 'DENY',
3117  'wgPageContentLanguage' => $lang->getCode(),
3118  'wgPageContentModel' => $title->getContentModel(),
3119  'wgSeparatorTransformTable' => $compactSeparatorTransTable,
3120  'wgDigitTransformTable' => $compactDigitTransTable,
3121  'wgDefaultDateFormat' => $lang->getDefaultDateFormat(),
3122  'wgMonthNames' => $lang->getMonthNamesArray(),
3123  'wgMonthNamesShort' => $lang->getMonthAbbreviationsArray(),
3124  'wgRelevantPageName' => $relevantTitle->getPrefixedDBkey(),
3125  'wgRelevantArticleId' => $relevantTitle->getArticleID(),
3126  'wgRequestId' => WebRequest::getRequestId(),
3127  ];
3128 
3129  if ( $user->isLoggedIn() ) {
3130  $vars['wgUserId'] = $user->getId();
3131  $vars['wgUserEditCount'] = $user->getEditCount();
3132  $userReg = $user->getRegistration();
3133  $vars['wgUserRegistration'] = $userReg ? wfTimestamp( TS_UNIX, $userReg ) * 1000 : null;
3134  // Get the revision ID of the oldest new message on the user's talk
3135  // page. This can be used for constructing new message alerts on
3136  // the client side.
3137  $vars['wgUserNewMsgRevisionId'] = $user->getNewMessageRevisionId();
3138  }
3139 
3140  if ( $wgContLang->hasVariants() ) {
3141  $vars['wgUserVariant'] = $wgContLang->getPreferredVariant();
3142  }
3143  // Same test as SkinTemplate
3144  $vars['wgIsProbablyEditable'] = $title->quickUserCan( 'edit', $user )
3145  && ( $title->exists() || $title->quickUserCan( 'create', $user ) );
3146 
3147  $vars['wgRelevantPageIsProbablyEditable'] = $relevantTitle
3148  && $relevantTitle->quickUserCan( 'edit', $user )
3149  && ( $relevantTitle->exists() || $relevantTitle->quickUserCan( 'create', $user ) );
3150 
3151  foreach ( $title->getRestrictionTypes() as $type ) {
3152  // Following keys are set in $vars:
3153  // wgRestrictionCreate, wgRestrictionEdit, wgRestrictionMove, wgRestrictionUpload
3154  $vars['wgRestriction' . ucfirst( $type )] = $title->getRestrictions( $type );
3155  }
3156 
3157  if ( $title->isMainPage() ) {
3158  $vars['wgIsMainPage'] = true;
3159  }
3160 
3161  if ( $this->mRedirectedFrom ) {
3162  $vars['wgRedirectedFrom'] = $this->mRedirectedFrom->getPrefixedDBkey();
3163  }
3164 
3165  if ( $relevantUser ) {
3166  $vars['wgRelevantUserName'] = $relevantUser->getName();
3167  }
3168 
3169  // Allow extensions to add their custom variables to the mw.config map.
3170  // Use the 'ResourceLoaderGetConfigVars' hook if the variable is not
3171  // page-dependant but site-wide (without state).
3172  // Alternatively, you may want to use OutputPage->addJsConfigVars() instead.
3173  Hooks::run( 'MakeGlobalVariablesScript', [ &$vars, $this ] );
3174 
3175  // Merge in variables from addJsConfigVars last
3176  return array_merge( $vars, $this->getJsConfigVars() );
3177  }
3178 
3188  public function userCanPreview() {
3189  $request = $this->getRequest();
3190  if (
3191  $request->getVal( 'action' ) !== 'submit' ||
3192  !$request->getCheck( 'wpPreview' ) ||
3193  !$request->wasPosted()
3194  ) {
3195  return false;
3196  }
3197 
3198  $user = $this->getUser();
3199 
3200  if ( !$user->isLoggedIn() ) {
3201  // Anons have predictable edit tokens
3202  return false;
3203  }
3204  if ( !$user->matchEditToken( $request->getVal( 'wpEditToken' ) ) ) {
3205  return false;
3206  }
3207 
3208  $title = $this->getTitle();
3209  if (
3210  !$title->isUserJsConfigPage()
3211  && !$title->isUserCssConfigPage()
3212  ) {
3213  return false;
3214  }
3215  if ( !$title->isSubpageOf( $user->getUserPage() ) ) {
3216  // Don't execute another user's CSS or JS on preview (T85855)
3217  return false;
3218  }
3219 
3220  $errors = $title->getUserPermissionsErrors( 'edit', $user );
3221  if ( count( $errors ) !== 0 ) {
3222  return false;
3223  }
3224 
3225  return true;
3226  }
3227 
3231  public function getHeadLinksArray() {
3233 
3234  $tags = [];
3235  $config = $this->getConfig();
3236 
3237  $canonicalUrl = $this->mCanonicalUrl;
3238 
3239  $tags['meta-generator'] = Html::element( 'meta', [
3240  'name' => 'generator',
3241  'content' => "MediaWiki $wgVersion",
3242  ] );
3243 
3244  if ( $config->get( 'ReferrerPolicy' ) !== false ) {
3245  // Per https://w3c.github.io/webappsec-referrer-policy/#unknown-policy-values
3246  // fallbacks should come before the primary value so we need to reverse the array.
3247  foreach ( array_reverse( (array)$config->get( 'ReferrerPolicy' ) ) as $i => $policy ) {
3248  $tags["meta-referrer-$i"] = Html::element( 'meta', [
3249  'name' => 'referrer',
3250  'content' => $policy,
3251  ] );
3252  }
3253  }
3254 
3255  $p = "{$this->mIndexPolicy},{$this->mFollowPolicy}";
3256  if ( $p !== 'index,follow' ) {
3257  // http://www.robotstxt.org/wc/meta-user.html
3258  // Only show if it's different from the default robots policy
3259  $tags['meta-robots'] = Html::element( 'meta', [
3260  'name' => 'robots',
3261  'content' => $p,
3262  ] );
3263  }
3264 
3265  foreach ( $this->mMetatags as $tag ) {
3266  if ( strncasecmp( $tag[0], 'http:', 5 ) === 0 ) {
3267  $a = 'http-equiv';
3268  $tag[0] = substr( $tag[0], 5 );
3269  } elseif ( strncasecmp( $tag[0], 'og:', 3 ) === 0 ) {
3270  $a = 'property';
3271  } else {
3272  $a = 'name';
3273  }
3274  $tagName = "meta-{$tag[0]}";
3275  if ( isset( $tags[$tagName] ) ) {
3276  $tagName .= $tag[1];
3277  }
3278  $tags[$tagName] = Html::element( 'meta',
3279  [
3280  $a => $tag[0],
3281  'content' => $tag[1]
3282  ]
3283  );
3284  }
3285 
3286  foreach ( $this->mLinktags as $tag ) {
3287  $tags[] = Html::element( 'link', $tag );
3288  }
3289 
3290  # Universal edit button
3291  if ( $config->get( 'UniversalEditButton' ) && $this->isArticleRelated() ) {
3292  $user = $this->getUser();
3293  if ( $this->getTitle()->quickUserCan( 'edit', $user )
3294  && ( $this->getTitle()->exists() ||
3295  $this->getTitle()->quickUserCan( 'create', $user ) )
3296  ) {
3297  // Original UniversalEditButton
3298  $msg = $this->msg( 'edit' )->text();
3299  $tags['universal-edit-button'] = Html::element( 'link', [
3300  'rel' => 'alternate',
3301  'type' => 'application/x-wiki',
3302  'title' => $msg,
3303  'href' => $this->getTitle()->getEditURL(),
3304  ] );
3305  // Alternate edit link
3306  $tags['alternative-edit'] = Html::element( 'link', [
3307  'rel' => 'edit',
3308  'title' => $msg,
3309  'href' => $this->getTitle()->getEditURL(),
3310  ] );
3311  }
3312  }
3313 
3314  # Generally the order of the favicon and apple-touch-icon links
3315  # should not matter, but Konqueror (3.5.9 at least) incorrectly
3316  # uses whichever one appears later in the HTML source. Make sure
3317  # apple-touch-icon is specified first to avoid this.
3318  if ( $config->get( 'AppleTouchIcon' ) !== false ) {
3319  $tags['apple-touch-icon'] = Html::element( 'link', [
3320  'rel' => 'apple-touch-icon',
3321  'href' => $config->get( 'AppleTouchIcon' )
3322  ] );
3323  }
3324 
3325  if ( $config->get( 'Favicon' ) !== false ) {
3326  $tags['favicon'] = Html::element( 'link', [
3327  'rel' => 'shortcut icon',
3328  'href' => $config->get( 'Favicon' )
3329  ] );
3330  }
3331 
3332  # OpenSearch description link
3333  $tags['opensearch'] = Html::element( 'link', [
3334  'rel' => 'search',
3335  'type' => 'application/opensearchdescription+xml',
3336  'href' => wfScript( 'opensearch_desc' ),
3337  'title' => $this->msg( 'opensearch-desc' )->inContentLanguage()->text(),
3338  ] );
3339 
3340  if ( $config->get( 'EnableAPI' ) ) {
3341  # Real Simple Discovery link, provides auto-discovery information
3342  # for the MediaWiki API (and potentially additional custom API
3343  # support such as WordPress or Twitter-compatible APIs for a
3344  # blogging extension, etc)
3345  $tags['rsd'] = Html::element( 'link', [
3346  'rel' => 'EditURI',
3347  'type' => 'application/rsd+xml',
3348  // Output a protocol-relative URL here if $wgServer is protocol-relative.
3349  // Whether RSD accepts relative or protocol-relative URLs is completely
3350  // undocumented, though.
3351  'href' => wfExpandUrl( wfAppendQuery(
3352  wfScript( 'api' ),
3353  [ 'action' => 'rsd' ] ),
3355  ),
3356  ] );
3357  }
3358 
3359  # Language variants
3360  if ( !$config->get( 'DisableLangConversion' ) ) {
3361  $lang = $this->getTitle()->getPageLanguage();
3362  if ( $lang->hasVariants() ) {
3363  $variants = $lang->getVariants();
3364  foreach ( $variants as $variant ) {
3365  $tags["variant-$variant"] = Html::element( 'link', [
3366  'rel' => 'alternate',
3367  'hreflang' => LanguageCode::bcp47( $variant ),
3368  'href' => $this->getTitle()->getLocalURL(
3369  [ 'variant' => $variant ] )
3370  ]
3371  );
3372  }
3373  # x-default link per https://support.google.com/webmasters/answer/189077?hl=en
3374  $tags["variant-x-default"] = Html::element( 'link', [
3375  'rel' => 'alternate',
3376  'hreflang' => 'x-default',
3377  'href' => $this->getTitle()->getLocalURL() ] );
3378  }
3379  }
3380 
3381  # Copyright
3382  if ( $this->copyrightUrl !== null ) {
3383  $copyright = $this->copyrightUrl;
3384  } else {
3385  $copyright = '';
3386  if ( $config->get( 'RightsPage' ) ) {
3387  $copy = Title::newFromText( $config->get( 'RightsPage' ) );
3388 
3389  if ( $copy ) {
3390  $copyright = $copy->getLocalURL();
3391  }
3392  }
3393 
3394  if ( !$copyright && $config->get( 'RightsUrl' ) ) {
3395  $copyright = $config->get( 'RightsUrl' );
3396  }
3397  }
3398 
3399  if ( $copyright ) {
3400  $tags['copyright'] = Html::element( 'link', [
3401  'rel' => 'license',
3402  'href' => $copyright ]
3403  );
3404  }
3405 
3406  # Feeds
3407  if ( $config->get( 'Feed' ) ) {
3408  $feedLinks = [];
3409 
3410  foreach ( $this->getSyndicationLinks() as $format => $link ) {
3411  # Use the page name for the title. In principle, this could
3412  # lead to issues with having the same name for different feeds
3413  # corresponding to the same page, but we can't avoid that at
3414  # this low a level.
3415 
3416  $feedLinks[] = $this->feedLink(
3417  $format,
3418  $link,
3419  # Used messages: 'page-rss-feed' and 'page-atom-feed' (for an easier grep)
3420  $this->msg(
3421  "page-{$format}-feed", $this->getTitle()->getPrefixedText()
3422  )->text()
3423  );
3424  }
3425 
3426  # Recent changes feed should appear on every page (except recentchanges,
3427  # that would be redundant). Put it after the per-page feed to avoid
3428  # changing existing behavior. It's still available, probably via a
3429  # menu in your browser. Some sites might have a different feed they'd
3430  # like to promote instead of the RC feed (maybe like a "Recent New Articles"
3431  # or "Breaking news" one). For this, we see if $wgOverrideSiteFeed is defined.
3432  # If so, use it instead.
3433  $sitename = $config->get( 'Sitename' );
3434  if ( $config->get( 'OverrideSiteFeed' ) ) {
3435  foreach ( $config->get( 'OverrideSiteFeed' ) as $type => $feedUrl ) {
3436  // Note, this->feedLink escapes the url.
3437  $feedLinks[] = $this->feedLink(
3438  $type,
3439  $feedUrl,
3440  $this->msg( "site-{$type}-feed", $sitename )->text()
3441  );
3442  }
3443  } elseif ( !$this->getTitle()->isSpecial( 'Recentchanges' ) ) {
3444  $rctitle = SpecialPage::getTitleFor( 'Recentchanges' );
3445  foreach ( $config->get( 'AdvertisedFeedTypes' ) as $format ) {
3446  $feedLinks[] = $this->feedLink(
3447  $format,
3448  $rctitle->getLocalURL( [ 'feed' => $format ] ),
3449  # For grep: 'site-rss-feed', 'site-atom-feed'
3450  $this->msg( "site-{$format}-feed", $sitename )->text()
3451  );
3452  }
3453  }
3454 
3455  # Allow extensions to change the list pf feeds. This hook is primarily for changing,
3456  # manipulating or removing existing feed tags. If you want to add new feeds, you should
3457  # use OutputPage::addFeedLink() instead.
3458  Hooks::run( 'AfterBuildFeedLinks', [ &$feedLinks ] );
3459 
3460  $tags += $feedLinks;
3461  }
3462 
3463  # Canonical URL
3464  if ( $config->get( 'EnableCanonicalServerLink' ) ) {
3465  if ( $canonicalUrl !== false ) {
3466  $canonicalUrl = wfExpandUrl( $canonicalUrl, PROTO_CANONICAL );
3467  } else {
3468  if ( $this->isArticleRelated() ) {
3469  // This affects all requests where "setArticleRelated" is true. This is
3470  // typically all requests that show content (query title, curid, oldid, diff),
3471  // and all wikipage actions (edit, delete, purge, info, history etc.).
3472  // It does not apply to File pages and Special pages.
3473  // 'history' and 'info' actions address page metadata rather than the page
3474  // content itself, so they may not be canonicalized to the view page url.
3475  // TODO: this ought to be better encapsulated in the Action class.
3476  $action = Action::getActionName( $this->getContext() );
3477  if ( in_array( $action, [ 'history', 'info' ] ) ) {
3478  $query = "action={$action}";
3479  } else {
3480  $query = '';
3481  }
3482  $canonicalUrl = $this->getTitle()->getCanonicalURL( $query );
3483  } else {
3484  $reqUrl = $this->getRequest()->getRequestURL();
3485  $canonicalUrl = wfExpandUrl( $reqUrl, PROTO_CANONICAL );
3486  }
3487  }
3488  }
3489  if ( $canonicalUrl !== false ) {
3490  $tags[] = Html::element( 'link', [
3491  'rel' => 'canonical',
3492  'href' => $canonicalUrl
3493  ] );
3494  }
3495 
3496  return $tags;
3497  }
3498 
3507  private function feedLink( $type, $url, $text ) {
3508  return Html::element( 'link', [
3509  'rel' => 'alternate',
3510  'type' => "application/$type+xml",
3511  'title' => $text,
3512  'href' => $url ]
3513  );
3514  }
3515 
3525  public function addStyle( $style, $media = '', $condition = '', $dir = '' ) {
3526  $options = [];
3527  if ( $media ) {
3528  $options['media'] = $media;
3529  }
3530  if ( $condition ) {
3531  $options['condition'] = $condition;
3532  }
3533  if ( $dir ) {
3534  $options['dir'] = $dir;
3535  }
3536  $this->styles[$style] = $options;
3537  }
3538 
3546  public function addInlineStyle( $style_css, $flip = 'noflip' ) {
3547  if ( $flip === 'flip' && $this->getLanguage()->isRTL() ) {
3548  # If wanted, and the interface is right-to-left, flip the CSS
3549  $style_css = CSSJanus::transform( $style_css, true, false );
3550  }
3551  $this->mInlineStyles .= Html::inlineStyle( $style_css );
3552  }
3553 
3559  protected function buildExemptModules() {
3561 
3562  $chunks = [];
3563  // Things that go after the ResourceLoaderDynamicStyles marker
3564  $append = [];
3565 
3566  // Exempt 'user' styles module (may need 'excludepages' for live preview)
3567  if ( $this->isUserCssPreview() ) {
3568  $append[] = $this->makeResourceLoaderLink(
3569  'user.styles',
3571  [ 'excludepage' => $this->getTitle()->getPrefixedDBkey() ]
3572  );
3573 
3574  // Load the previewed CSS. Janus it if needed.
3575  // User-supplied CSS is assumed to in the wiki's content language.
3576  $previewedCSS = $this->getRequest()->getText( 'wpTextbox1' );
3577  if ( $this->getLanguage()->getDir() !== $wgContLang->getDir() ) {
3578  $previewedCSS = CSSJanus::transform( $previewedCSS, true, false );
3579  }
3580  $append[] = Html::inlineStyle( $previewedCSS );
3581  }
3582 
3583  // We want site, private and user styles to override dynamically added styles from
3584  // general modules, but we want dynamically added styles to override statically added
3585  // style modules. So the order has to be:
3586  // - page style modules (formatted by ResourceLoaderClientHtml::getHeadHtml())
3587  // - dynamically loaded styles (added by mw.loader before ResourceLoaderDynamicStyles)
3588  // - ResourceLoaderDynamicStyles marker
3589  // - site/private/user styles
3590 
3591  // Add legacy styles added through addStyle()/addInlineStyle() here
3592  $chunks[] = implode( '', $this->buildCssLinksArray() ) . $this->mInlineStyles;
3593 
3594  $chunks[] = Html::element(
3595  'meta',
3596  [ 'name' => 'ResourceLoaderDynamicStyles', 'content' => '' ]
3597  );
3598 
3599  $separateReq = [ 'site.styles', 'user.styles' ];
3600  foreach ( $this->rlExemptStyleModules as $group => $moduleNames ) {
3601  // Combinable modules
3602  $chunks[] = $this->makeResourceLoaderLink(
3603  array_diff( $moduleNames, $separateReq ),
3605  );
3606 
3607  foreach ( array_intersect( $moduleNames, $separateReq ) as $name ) {
3608  // These require their own dedicated request in order to support "@import"
3609  // syntax, which is incompatible with concatenation. (T147667, T37562)
3610  $chunks[] = $this->makeResourceLoaderLink( $name,
3612  );
3613  }
3614  }
3615 
3616  return self::combineWrappedStrings( array_merge( $chunks, $append ) );
3617  }
3618 
3622  public function buildCssLinksArray() {
3623  $links = [];
3624 
3625  foreach ( $this->styles as $file => $options ) {
3626  $link = $this->styleLink( $file, $options );
3627  if ( $link ) {
3628  $links[$file] = $link;
3629  }
3630  }
3631  return $links;
3632  }
3633 
3641  protected function styleLink( $style, array $options ) {
3642  if ( isset( $options['dir'] ) ) {
3643  if ( $this->getLanguage()->getDir() != $options['dir'] ) {
3644  return '';
3645  }
3646  }
3647 
3648  if ( isset( $options['media'] ) ) {
3649  $media = self::transformCssMedia( $options['media'] );
3650  if ( is_null( $media ) ) {
3651  return '';
3652  }
3653  } else {
3654  $media = 'all';
3655  }
3656 
3657  if ( substr( $style, 0, 1 ) == '/' ||
3658  substr( $style, 0, 5 ) == 'http:' ||
3659  substr( $style, 0, 6 ) == 'https:' ) {
3660  $url = $style;
3661  } else {
3662  $config = $this->getConfig();
3663  $url = $config->get( 'StylePath' ) . '/' . $style . '?' .
3664  $config->get( 'StyleVersion' );
3665  }
3666 
3667  $link = Html::linkedStyle( $url, $media );
3668 
3669  if ( isset( $options['condition'] ) ) {
3670  $condition = htmlspecialchars( $options['condition'] );
3671  $link = "<!--[if $condition]>$link<![endif]-->";
3672  }
3673  return $link;
3674  }
3675 
3697  public static function transformResourcePath( Config $config, $path ) {
3698  global $IP;
3699 
3700  $localDir = $IP;
3701  $remotePathPrefix = $config->get( 'ResourceBasePath' );
3702  if ( $remotePathPrefix === '' ) {
3703  // The configured base path is required to be empty string for
3704  // wikis in the domain root
3705  $remotePath = '/';
3706  } else {
3707  $remotePath = $remotePathPrefix;
3708  }
3709  if ( strpos( $path, $remotePath ) !== 0 || substr( $path, 0, 2 ) === '//' ) {
3710  // - Path is outside wgResourceBasePath, ignore.
3711  // - Path is protocol-relative. Fixes T155310. Not supported by RelPath lib.
3712  return $path;
3713  }
3714  // For files in resources, extensions/ or skins/, ResourceBasePath is preferred here.
3715  // For other misc files in $IP, we'll fallback to that as well. There is, however, a fourth
3716  // supported dir/path pair in the configuration (wgUploadDirectory, wgUploadPath)
3717  // which is not expected to be in wgResourceBasePath on CDNs. (T155146)
3718  $uploadPath = $config->get( 'UploadPath' );
3719  if ( strpos( $path, $uploadPath ) === 0 ) {
3720  $localDir = $config->get( 'UploadDirectory' );
3721  $remotePathPrefix = $remotePath = $uploadPath;
3722  }
3723 
3724  $path = RelPath::getRelativePath( $path, $remotePath );
3725  return self::transformFilePath( $remotePathPrefix, $localDir, $path );
3726  }
3727 
3739  public static function transformFilePath( $remotePathPrefix, $localPath, $file ) {
3740  $hash = md5_file( "$localPath/$file" );
3741  if ( $hash === false ) {
3742  wfLogWarning( __METHOD__ . ": Failed to hash $localPath/$file" );
3743  $hash = '';
3744  }
3745  return "$remotePathPrefix/$file?" . substr( $hash, 0, 5 );
3746  }
3747 
3755  public static function transformCssMedia( $media ) {
3757 
3758  // https://www.w3.org/TR/css3-mediaqueries/#syntax
3759  $screenMediaQueryRegex = '/^(?:only\s+)?screen\b/i';
3760 
3761  // Switch in on-screen display for media testing
3762  $switches = [
3763  'printable' => 'print',
3764  'handheld' => 'handheld',
3765  ];
3766  foreach ( $switches as $switch => $targetMedia ) {
3767  if ( $wgRequest->getBool( $switch ) ) {
3768  if ( $media == $targetMedia ) {
3769  $media = '';
3770  } elseif ( preg_match( $screenMediaQueryRegex, $media ) === 1 ) {
3771  /* This regex will not attempt to understand a comma-separated media_query_list
3772  *
3773  * Example supported values for $media:
3774  * 'screen', 'only screen', 'screen and (min-width: 982px)' ),
3775  * Example NOT supported value for $media:
3776  * '3d-glasses, screen, print and resolution > 90dpi'
3777  *
3778  * If it's a print request, we never want any kind of screen stylesheets
3779  * If it's a handheld request (currently the only other choice with a switch),
3780  * we don't want simple 'screen' but we might want screen queries that
3781  * have a max-width or something, so we'll pass all others on and let the
3782  * client do the query.
3783  */
3784  if ( $targetMedia == 'print' || $media == 'screen' ) {
3785  return null;
3786  }
3787  }
3788  }
3789  }
3790 
3791  return $media;
3792  }
3793 
3800  public function addWikiMsg( /*...*/ ) {
3801  $args = func_get_args();
3802  $name = array_shift( $args );
3803  $this->addWikiMsgArray( $name, $args );
3804  }
3805 
3814  public function addWikiMsgArray( $name, $args ) {
3815  $this->addHTML( $this->msg( $name, $args )->parseAsBlock() );
3816  }
3817 
3843  public function wrapWikiMsg( $wrap /*, ...*/ ) {
3844  $msgSpecs = func_get_args();
3845  array_shift( $msgSpecs );
3846  $msgSpecs = array_values( $msgSpecs );
3847  $s = $wrap;
3848  foreach ( $msgSpecs as $n => $spec ) {
3849  if ( is_array( $spec ) ) {
3850  $args = $spec;
3851  $name = array_shift( $args );
3852  if ( isset( $args['options'] ) ) {
3853  unset( $args['options'] );
3854  wfDeprecated(
3855  'Adding "options" to ' . __METHOD__ . ' is no longer supported',
3856  '1.20'
3857  );
3858  }
3859  } else {
3860  $args = [];
3861  $name = $spec;
3862  }
3863  $s = str_replace( '$' . ( $n + 1 ), $this->msg( $name, $args )->plain(), $s );
3864  }
3865  $this->addWikiText( $s );
3866  }
3867 
3873  public function isTOCEnabled() {
3874  return $this->mEnableTOC;
3875  }
3876 
3883  public function enableSectionEditLinks( $flag = true ) {
3884  wfDeprecated( __METHOD__, '1.31' );
3885  }
3886 
3892  public function sectionEditLinksEnabled() {
3893  wfDeprecated( __METHOD__, '1.31' );
3894  return true;
3895  }
3896 
3904  public static function setupOOUI( $skinName = 'default', $dir = 'ltr' ) {
3906  $theme = isset( $themes[$skinName] ) ? $themes[$skinName] : $themes['default'];
3907  // For example, 'OOUI\WikimediaUITheme'.
3908  $themeClass = "OOUI\\{$theme}Theme";
3909  OOUI\Theme::setSingleton( new $themeClass() );
3910  OOUI\Element::setDefaultDir( $dir );
3911  }
3912 
3919  public function enableOOUI() {
3921  strtolower( $this->getSkin()->getSkinName() ),
3922  $this->getLanguage()->getDir()
3923  );
3924  $this->addModuleStyles( [
3925  'oojs-ui-core.styles',
3926  'oojs-ui.styles.indicators',
3927  'oojs-ui.styles.textures',
3928  'mediawiki.widgets.styles',
3929  'oojs-ui.styles.icons-content',
3930  'oojs-ui.styles.icons-alerts',
3931  'oojs-ui.styles.icons-interactions',
3932  ] );
3933  }
3934 
3940  protected function addLogoPreloadLinkHeaders() {
3941  $logo = ResourceLoaderSkinModule::getLogo( $this->getConfig() );
3942 
3943  $tags = [];
3944  $logosPerDppx = [];
3945  $logos = [];
3946 
3947  if ( !is_array( $logo ) ) {
3948  // No media queries required if we only have one variant
3949  $this->addLinkHeader( '<' . $logo . '>;rel=preload;as=image' );
3950  return;
3951  }
3952 
3953  if ( isset( $logo['svg'] ) ) {
3954  // No media queries required if we only have a 1x and svg variant
3955  // because all preload-capable browsers support SVGs
3956  $this->addLinkHeader( '<' . $logo['svg'] . '>;rel=preload;as=image' );
3957  return;
3958  }
3959 
3960  foreach ( $logo as $dppx => $src ) {
3961  // Keys are in this format: "1.5x"
3962  $dppx = substr( $dppx, 0, -1 );
3963  $logosPerDppx[$dppx] = $src;
3964  }
3965 
3966  // Because PHP can't have floats as array keys
3967  uksort( $logosPerDppx, function ( $a , $b ) {
3968  $a = floatval( $a );
3969  $b = floatval( $b );
3970 
3971  if ( $a == $b ) {
3972  return 0;
3973  }
3974  // Sort from smallest to largest (e.g. 1x, 1.5x, 2x)
3975  return ( $a < $b ) ? -1 : 1;
3976  } );
3977 
3978  foreach ( $logosPerDppx as $dppx => $src ) {
3979  $logos[] = [ 'dppx' => $dppx, 'src' => $src ];
3980  }
3981 
3982  $logosCount = count( $logos );
3983  // Logic must match ResourceLoaderSkinModule:
3984  // - 1x applies to resolution < 1.5dppx
3985  // - 1.5x applies to resolution >= 1.5dppx && < 2dppx
3986  // - 2x applies to resolution >= 2dppx
3987  // Note that min-resolution and max-resolution are both inclusive.
3988  for ( $i = 0; $i < $logosCount; $i++ ) {
3989  if ( $i === 0 ) {
3990  // Smallest dppx
3991  // min-resolution is ">=" (larger than or equal to)
3992  // "not min-resolution" is essentially "<"
3993  $media_query = 'not all and (min-resolution: ' . $logos[ 1 ]['dppx'] . 'dppx)';
3994  } elseif ( $i !== $logosCount - 1 ) {
3995  // In between
3996  // Media query expressions can only apply "not" to the entire expression
3997  // (e.g. can't express ">= 1.5 and not >= 2).
3998  // Workaround: Use <= 1.9999 in place of < 2.
3999  $upper_bound = floatval( $logos[ $i + 1 ]['dppx'] ) - 0.000001;
4000  $media_query = '(min-resolution: ' . $logos[ $i ]['dppx'] .
4001  'dppx) and (max-resolution: ' . $upper_bound . 'dppx)';
4002  } else {
4003  // Largest dppx
4004  $media_query = '(min-resolution: ' . $logos[ $i ]['dppx'] . 'dppx)';
4005  }
4006 
4007  $this->addLinkHeader(
4008  '<' . $logos[$i]['src'] . '>;rel=preload;as=image;media=' . $media_query
4009  );
4010  }
4011  }
4012 }
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:2169
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:2292
OutputPage\$mCategories
array $mCategories
Definition: OutputPage.php:106
$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:247
OutputPage\addBacklinkSubtitle
addBacklinkSubtitle(Title $title, $query=[])
Add a subtitle containing a backlink to a page.
Definition: OutputPage.php:1017
OutputPage\$mLastModified
string $mLastModified
Used for sending cache control.
Definition: OutputPage.php:100
ParserOptions
Set options of the Parser.
Definition: ParserOptions.php:40
OutputPage\getCategoryLinks
getCategoryLinks()
Get the list of category links, in a 2-D array with the following format: $arr[$type][] = $link,...
Definition: OutputPage.php:1340
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:362
ContextSource\$context
IContextSource $context
Definition: ContextSource.php:33
ContextSource\getConfig
getConfig()
Definition: ContextSource.php:63
OutputPage\getTarget
getTarget()
Definition: OutputPage.php:612
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:1192
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:1033
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:1990
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:273
OutputPage\addWikiMsg
addWikiMsg()
Add a wikitext-formatted message to the output.
Definition: OutputPage.php:3800
ContextSource\getContext
getContext()
Get the base IContextSource object.
Definition: ContextSource.php:40
OutputPage\getLanguageLinks
getLanguageLinks()
Get the list of language links.
Definition: OutputPage.php:1233
OutputPage\buildBacklinkSubtitle
static buildBacklinkSubtitle(Title $title, $query=[])
Build message object for a subtitle containing a backlink to a page.
Definition: OutputPage.php:1002
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:1478
PROTO_CANONICAL
const PROTO_CANONICAL
Definition: Defines.php:233
OutputPage\$mModuleStyles
array $mModuleStyles
Definition: OutputPage.php:147
OutputPage\addSubtitle
addSubtitle( $str)
Add $str to the subtitle.
Definition: OutputPage.php:986
OutputPage\addAcceptLanguage
addAcceptLanguage()
T23672: Add Accept-Language to Vary and Key headers if there's no 'variant' parameter existed in GET.
Definition: OutputPage.php:2130
Article\formatRobotPolicy
static formatRobotPolicy( $policy)
Converts a String robot policy into an associative array, to allow merging of several policies using ...
Definition: Article.php:833
OutputPage\getJSVars
getJSVars()
Get an array containing the variables to be set in mw.config in JavaScript.
Definition: OutputPage.php:3055
ResourceLoader\makeConfigSetScript
static makeConfigSetScript(array $configuration)
Returns JS code which will set the MediaWiki configuration array to the given value.
Definition: ResourceLoader.php:1522
use
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
Definition: APACHE-LICENSE-2.0.txt:10
ResourceLoaderContext\newDummyContext
static newDummyContext()
Return a dummy ResourceLoaderContext object suitable for passing into things that don't "really" need...
Definition: ResourceLoaderContext.php:138
OutputPage\showFileRenameError
showFileRenameError( $old, $new)
Definition: OutputPage.php:2631
OutputPage\getRlClientContext
getRlClientContext()
Definition: OutputPage.php:2694
OutputPage\$mRedirectedFrom
Title $mRedirectedFrom
If the current page was reached through a redirect, $mRedirectedFrom contains the Title of the redire...
Definition: OutputPage.php:273
Sanitizer\stripAllTags
static stripAllTags( $html)
Take a fragment of (potentially invalid) HTML and return a version with any tags removed,...
Definition: Sanitizer.php:1981
$wgParser
$wgParser
Definition: Setup.php:917
OutputPage\setTitle
setTitle(Title $t)
Set the Title object to use.
Definition: OutputPage.php:967
ResourceLoaderModule\TYPE_COMBINED
const TYPE_COMBINED
Definition: ResourceLoaderModule.php:39
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:383
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\addCategoryLinksToLBAndGetResult
addCategoryLinksToLBAndGetResult(array $categories)
Definition: OutputPage.php:1292
$response
this hook is for auditing only $response
Definition: hooks.txt:783
array
the array() calling protocol came about after MediaWiki 1.4rc1.
OutputPage\hasHeadItem
hasHeadItem( $name)
Check if the header item $name is already set.
Definition: OutputPage.php:666
plain
either a plain
Definition: hooks.txt:2056
OutputPage\$mCanonicalUrl
bool $mCanonicalUrl
Definition: OutputPage.php:53
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:33
OutputPage\getMetaTags
getMetaTags()
Returns the current <meta> tags.
Definition: OutputPage.php:372
OutputPage\addParserOutput
addParserOutput( $parserOutput, $poOptions=[])
Add everything from a ParserOutput object.
Definition: OutputPage.php:1860
OutputPage\addLanguageLinks
addLanguageLinks(array $newLinkArray)
Add new language links.
Definition: OutputPage.php:1214
OutputPage\addLinkHeader
addLinkHeader( $header)
Add an HTTP Link: header.
Definition: OutputPage.php:2074
OutputPage\addModuleStyles
addModuleStyles( $modules)
Add only CSS of one or more modules recognized by ResourceLoader.
Definition: OutputPage.php:605
OutputPage\$mNewSectionLink
bool $mNewSectionLink
Definition: OutputPage.php:215
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:1699
OutputPage\isArticleRelated
isArticleRelated()
Return whether this page is related an article on the wiki.
Definition: OutputPage.php:1204
OutputPage\enableSectionEditLinks
enableSectionEditLinks( $flag=true)
Enables/disables section edit links, doesn't override NOEDITSECTION
Definition: OutputPage.php:3883
ResourceLoaderModule\ORIGIN_USER_SITEWIDE
const ORIGIN_USER_SITEWIDE
Definition: ResourceLoaderModule.php:55
OutputPage\setArticleBodyOnly
setArticleBodyOnly( $only)
Set whether the output should only contain the body of the article, without any skin,...
Definition: OutputPage.php:687
OutputPage\getFrameOptions
getFrameOptions()
Get the X-Frame-Options header value (without the name part), or false if there isn't one.
Definition: OutputPage.php:2199
OutputPage\__construct
__construct(IContextSource $context)
Constructor for OutputPage.
Definition: OutputPage.php:309
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:18
OutputPage\$mRedirectCode
string $mRedirectCode
Definition: OutputPage.php:174
ContextSource\msg
msg( $key)
Get a Message object with context set Parameters are the same as wfMessage()
Definition: ContextSource.php:168
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:181
OutputPage\getRevisionId
getRevisionId()
Get the displayed revision ID.
Definition: OutputPage.php:1596
ResourceLoaderClientHtml\setModuleScripts
setModuleScripts(array $modules)
Ensure the scripts of one or more modules are loaded.
Definition: ResourceLoaderClientHtml.php:104
OutputPage\addWikiTextTitleTidy
addWikiTextTitleTidy( $text, &$title, $linestart=true)
Add wikitext with a custom Title object and tidy enabled.
Definition: OutputPage.php:1699
OutputPage\clearHTML
clearHTML()
Clear the body HTML.
Definition: OutputPage.php:1516
Title\newMainPage
static newMainPage()
Create a new Title for the Main Page.
Definition: Title.php:586
OutputPage\addScript
addScript( $script)
Add raw HTML to the list of scripts (including <script> tag, etc.) Internal use only.
Definition: OutputPage.php:452
OutputPage\$mIsarticle
bool $mIsarticle
Is the displayed content related to the source of the corresponding wiki article.
Definition: OutputPage.php:73
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1980
$wgVersion
$wgVersion
MediaWiki version number.
Definition: DefaultSettings.php:75
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:2667
OutputPage\buildCssLinksArray
buildCssLinksArray()
Definition: OutputPage.php:3622
OutputPage\combineWrappedStrings
static combineWrappedStrings(array $chunks)
Combine WrappedString chunks and filter out empty ones.
Definition: OutputPage.php:2941
Sanitizer\mergeAttributes
static mergeAttributes( $a, $b)
Merge two sets of HTML attributes.
Definition: Sanitizer.php:910
$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:831
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:881
OutputPage\$mHideNewSectionLink
bool $mHideNewSectionLink
Definition: OutputPage.php:218
OutputPage\$mBodytext
string $mBodytext
Contains all of the "<body>" content.
Definition: OutputPage.php:64
wfUrlencode
wfUrlencode( $s)
We want some things to be included as literal characters in our title URLs for prettiness,...
Definition: GlobalFunctions.php:340
OutputPage\getBottomScripts
getBottomScripts()
JS stuff to put at the bottom of the <body>.
Definition: OutputPage.php:2967
OutputPage\showFileNotFoundError
showFileNotFoundError( $name)
Definition: OutputPage.php:2639
OutputPage\$mPagetitle
string $mPagetitle
Should be private - has getter and setter.
Definition: OutputPage.php:58
ParserOptions\newFromAnon
static newFromAnon()
Get a ParserOptions object for an anonymous user.
Definition: ParserOptions.php:963
OutputPage\addHeadItems
addHeadItems( $values)
Add one or more head items to the output.
Definition: OutputPage.php:656
OutputPage\getModuleStyles
getModuleStyles( $filter=false, $position=null)
Get the list of module CSS to include on this page.
Definition: OutputPage.php:590
$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:935
Skin\addToBodyAttributes
addToBodyAttributes( $out, &$bodyAttrs)
This will be called by OutputPage::headElement when it is creating the "<body>" tag,...
Definition: Skin.php:468
OutputPage\versionRequired
versionRequired( $version)
Display an error page indicating that a given version of MediaWiki is required to use it.
Definition: OutputPage.php:2552
ResourceLoaderClientHtml\setExemptStates
setExemptStates(array $states)
Set state of special modules that are handled by the caller manually.
Definition: ResourceLoaderClientHtml.php:115
OutputPage\parseInline
parseInline( $text, $linestart=true, $interface=false)
Parse wikitext, strip paragraphs, and return the HTML.
Definition: OutputPage.php:1928
OutputPage\addScriptFile
addScriptFile( $file, $version=null)
Add a JavaScript file out of skins/common, or a given relative path.
Definition: OutputPage.php:464
$s
$s
Definition: mergeMessageFileList.php:187
OutputPage\parserOptions
parserOptions( $options=null)
Get/set the ParserOptions object to use for wikitext parsing.
Definition: OutputPage.php:1536
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
Sanitizer\escapeClass
static escapeClass( $class)
Given a value, escape it so that it can be used as a CSS class and return it.
Definition: Sanitizer.php:1402
OutputPage\getFileVersion
getFileVersion()
Get the displayed file version.
Definition: OutputPage.php:1640
OutputPage\getSyndicationLinks
getSyndicationLinks()
Return URLs for each supported syndication format for this page.
Definition: OutputPage.php:1149
OutputPage\$mVaryHeader
$mVaryHeader
Definition: OutputPage.php:263
ContextSource\canUseWikiPage
canUseWikiPage()
Check whether a WikiPage object can be get with getWikiPage().
Definition: ContextSource.php:91
wfLogWarning
wfLogWarning( $msg, $callerOffset=1, $level=E_USER_WARNING)
Send a warning as a PHP error and the debug log.
Definition: GlobalFunctions.php:1150
$res
$res
Definition: database.txt:21
ContextSource\getRequest
getRequest()
Definition: ContextSource.php:71
IExpiringStore\TTL_MINUTE
const TTL_MINUTE
Definition: IExpiringStore.php:34
OutputPage\$mRevisionId
int $mRevisionId
To include the variable {{REVISIONID}}.
Definition: OutputPage.php:243
User\groupHasPermission
static groupHasPermission( $group, $role)
Check, if the given group has the given permission.
Definition: User.php:4991
OutputPage\getRedirect
getRedirect()
Get the URL to redirect to, or an empty string if not redirect URL set.
Definition: OutputPage.php:330
$resourceLoader
do that in ParserLimitReportFormat instead use this to modify the parameters of the image all existing parser cache entries will be invalid To avoid you ll need to handle that somehow(e.g. with the RejectParserCacheValue hook) because MediaWiki won 't do it for you. & $defaults also a ContextSource after deleting those rows but within the same transaction 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:2818
OutputPage\setCanonicalUrl
setCanonicalUrl( $url)
Set the URL to be used for the <link rel=canonical>>.
Definition: OutputPage.php:414
$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:2056
ContextSource\getUser
getUser()
Definition: ContextSource.php:120
ContextSource\getTitle
getTitle()
Definition: ContextSource.php:79
OutputPage\$mLinktags
array $mLinktags
Definition: OutputPage.php:50
OutputPage\$mIndexPolicy
$mIndexPolicy
Definition: OutputPage.php:261
Skin\getHtmlElementAttributes
getHtmlElementAttributes()
Return values for <html> element.
Definition: Skin.php:452
Html\inlineScript
static inlineScript( $contents)
Output a "<script>" tag with the given contents.
Definition: Html.php:562
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:97
OutputPage\setIndicators
setIndicators(array $indicators)
Add an array of indicators, with their identifiers as array keys and HTML contents as values.
Definition: OutputPage.php:1376
LinkCache\getSelectFields
static getSelectFields()
Fields that LinkCache needs to select.
Definition: LinkCache.php:213
OutputPage\showFileDeleteError
showFileDeleteError( $name)
Definition: OutputPage.php:2635
OutputPage\addHTML
addHTML( $text)
Append $text to the body HTML.
Definition: OutputPage.php:1496
OutputPage\addParserOutputText
addParserOutputText( $parserOutput, $poOptions=[])
Add the HTML associated with a ParserOutput object, without any metadata.
Definition: OutputPage.php:1846
OutputPage\addHeadItem
addHeadItem( $name, $value)
Add or replace a head item to the output.
Definition: OutputPage.php:646
OutputPage\addWikiTextTidy
addWikiTextTidy( $text, $linestart=true)
Add wikitext with tidy enabled.
Definition: OutputPage.php:1709
OutputPage\getModuleScripts
getModuleScripts( $filter=false, $position=null)
Get the list of module JS to include on this page.
Definition: OutputPage.php:566
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:37
File\exists
exists()
Returns true if file exists in the repository.
Definition: File.php:896
OutputPage\getRevisionTimestamp
getRevisionTimestamp()
Get the timestamp of displayed revision.
Definition: OutputPage.php:1617
OutputPage\addWikiMsgArray
addWikiMsgArray( $name, $args)
Add a wikitext-formatted message to the output.
Definition: OutputPage.php:3814
OutputPage\transformCssMedia
static transformCssMedia( $media)
Transform "media" attribute based on request parameters.
Definition: OutputPage.php:3755
OutputPage\setLastModified
setLastModified( $timestamp)
Override the last modified timestamp.
Definition: OutputPage.php:824
$dbr
$dbr
Definition: testCompression.php:50
ResourceLoaderClientHtml\setConfig
setConfig(array $vars)
Set mw.config variables.
Definition: ResourceLoaderClientHtml.php:73
ContextSource\getLanguage
getLanguage()
Definition: ContextSource.php:128
OutputPage\$mPageTitleActionText
string $mPageTitleActionText
Definition: OutputPage.php:228
OutputPage\$mImageTimeKeys
array $mImageTimeKeys
Definition: OutputPage.php:171
OutputPage\showPermissionsErrorPage
showPermissionsErrorPage(array $errors, $action=null)
Output a standard permission error page.
Definition: OutputPage.php:2475
OutputPage\$rlUserModuleState
string $rlUserModuleState
Definition: OutputPage.php:159
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:469
XmlJsCode
A wrapper class which causes Xml::encodeJsVar() and Xml::encodeJsCall() to interpret a given string a...
Definition: XmlJsCode.php:39
OutputPage\getLinkTags
getLinkTags()
Returns the current <link> tags.
Definition: OutputPage.php:393
OutputPage\forceHideNewSectionLink
forceHideNewSectionLink()
Forcibly hide the new section link?
Definition: OutputPage.php:1084
OutputPage\addWikiTextWithTitle
addWikiTextWithTitle( $text, &$title, $linestart=true)
Add wikitext with a custom Title object.
Definition: OutputPage.php:1688
Html\closeElement
static closeElement( $element)
Returns "</$element>".
Definition: Html.php:309
Xml\encodeJsCall
static encodeJsCall( $name, $args, $pretty=false)
Create a call to a JavaScript function.
Definition: Xml.php:678
OutputPage\$rlClientContext
ResourceLoaderContext $rlClientContext
Definition: OutputPage.php:156
Html\isXmlMimeType
static isXmlMimeType( $mimetype)
Determines if the given MIME type is xml.
Definition: Html.php:974
OutputPage\addElement
addElement( $element, array $attribs=[], $contents='')
Shortcut for adding an Html::element via addHTML.
Definition: OutputPage.php:1509
Config
Interface for configuration instances.
Definition: Config.php:28
NS_SPECIAL
const NS_SPECIAL
Definition: Defines.php:63
OutputPage\addParserOutputMetadata
addParserOutputMetadata( $parserOutput)
Add all metadata associated with a ParserOutput object, but without the actual HTML.
Definition: OutputPage.php:1753
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:3507
OutputPage\getKeyHeader
getKeyHeader()
Get a complete Key header.
Definition: OutputPage.php:2096
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:539
OutputPage\addStyle
addStyle( $style, $media='', $condition='', $dir='')
Add a local or specified stylesheet, with the given media options.
Definition: OutputPage.php:3525
OutputPage\sendCacheControl
sendCacheControl()
Send cache control HTTP headers.
Definition: OutputPage.php:2212
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:1275
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
Definition: GlobalFunctions.php:1123
OutputPage\$mCdnMaxageLimit
int $mCdnMaxageLimit
Upper limit on mCdnMaxage.
Definition: OutputPage.php:233
OutputPage\$mTemplateIds
array $mTemplateIds
Definition: OutputPage.php:168
wfScript
wfScript( $script='index')
Get the path to a specified script file, respecting file extensions; this is a wrapper around $wgScri...
Definition: GlobalFunctions.php:2890
ResourceLoaderWikiModule\preloadTitleInfo
static preloadTitleInfo(ResourceLoaderContext $context, IDatabase $db, array $moduleNames)
Definition: ResourceLoaderWikiModule.php:360
OutputPage\styleLink
styleLink( $style, array $options)
Generate <link> tags for stylesheets.
Definition: OutputPage.php:3641
OutputPage\$mEnableTOC
bool $mEnableTOC
Whether parser output contains a table of contents.
Definition: OutputPage.php:288
Config\get
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
OutputPage\$mSubtitle
array $mSubtitle
Contains the page subtitle.
Definition: OutputPage.php:88
OutputPage\setFileVersion
setFileVersion( $file)
Set the displayed file version.
Definition: OutputPage.php:1627
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:2812
OutputPage\showUnexpectedValueError
showUnexpectedValueError( $name, $val)
Definition: OutputPage.php:2623
OutputPage\getLinkHeader
getLinkHeader()
Return a Link: header.
Definition: OutputPage.php:2083
OutputPage\getResourceLoader
getResourceLoader()
Get a ResourceLoader object associated with this OutputPage.
Definition: OutputPage.php:2905
OutputPage\isTOCEnabled
isTOCEnabled()
Whether the output has a table of contents.
Definition: OutputPage.php:3873
ContextSource
The simplest way of implementing IContextSource is to hold a RequestContext as a member variable and ...
Definition: ContextSource.php:29
Html\linkedScript
static linkedScript( $url)
Output a "<script>" tag linking to the given URL, e.g., "<script src=foo.js></script>".
Definition: Html.php:579
ContextSource\getWikiPage
getWikiPage()
Get the WikiPage object.
Definition: ContextSource.php:104
OutputPage\setFeedAppendQuery
setFeedAppendQuery( $val)
Add default feeds to the page header This is mainly kept for backward compatibility,...
Definition: OutputPage.php:1113
$modules
$modules
Definition: HTMLFormElement.php:12
OutputPage\isDisabled
isDisabled()
Return whether the output will be completely disabled.
Definition: OutputPage.php:1066
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:1586
PROTO_CURRENT
const PROTO_CURRENT
Definition: Defines.php:232
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:1169
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:1434
ContextSource\getSkin
getSkin()
Definition: ContextSource.php:136
ResourceLoaderModule\TYPE_SCRIPTS
const TYPE_SCRIPTS
Definition: ResourceLoaderModule.php:37
OutputPage\setSubtitle
setSubtitle( $str)
Replace the subtitle with $str.
Definition: OutputPage.php:976
OutputPage\$mInlineStyles
string $mInlineStyles
Inline CSS styles.
Definition: OutputPage.php:126
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:1673
wfCgiToArray
wfCgiToArray( $query)
This is the logical opposite of wfArrayToCgi(): it accepts a query string as its argument and returns...
Definition: GlobalFunctions.php:422
OutputPage\addLogoPreloadLinkHeaders
addLogoPreloadLinkHeaders()
Add Link headers for preloading the wiki's logo.
Definition: OutputPage.php:3940
OutputPage\getVaryHeader
getVaryHeader()
Return a Vary: header on which to vary caches.
Definition: OutputPage.php:2057
OutputPage\addModules
addModules( $modules)
Add one or more modules recognized by ResourceLoader.
Definition: OutputPage.php:555
OutputPage\showLagWarning
showLagWarning( $lag)
Show a warning about replica DB lag.
Definition: OutputPage.php:2605
$link
usually copyright or history_copyright This message must be in HTML not wikitext & $link
Definition: hooks.txt:3021
$title
namespace and then decline to actually register it file or subcat img or subcat $title
Definition: hooks.txt:964
OutputPage\getPageTitleActionText
getPageTitleActionText()
Get the value of the "action text".
Definition: OutputPage.php:890
OutputPage\getCacheVaryCookies
getCacheVaryCookies()
Get the list of cookies that will influence on the cache.
Definition: OutputPage.php:1999
OutputPage\setCopyrightUrl
setCopyrightUrl( $url)
Set the copyright URL to send with the output.
Definition: OutputPage.php:342
ResourceLoaderSkinModule\getLogo
static getLogo(Config $conf)
Definition: ResourceLoaderSkinModule.php:111
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:95
OutputPage\$mFollowPolicy
$mFollowPolicy
Definition: OutputPage.php:262
OutputPage\$rlClient
ResourceLoaderClientHtml $rlClient
Definition: OutputPage.php:153
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
NS_CATEGORY
const NS_CATEGORY
Definition: Defines.php:88
OutputPage\addBodyClasses
addBodyClasses( $classes)
Add a class to the <body> element.
Definition: OutputPage.php:676
ResourceLoaderModule\getOrigin
getOrigin()
Get this module's origin.
Definition: ResourceLoaderModule.php:123
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:994
ContextSource\setContext
setContext(IContextSource $context)
Definition: ContextSource.php:55
OutputPage\isArticle
isArticle()
Return whether the content displayed page is related to the source of the corresponding article on th...
Definition: OutputPage.php:1182
OutputPage
This class should be covered by a general architecture document which does not exist as of January 20...
Definition: OutputPage.php:45
OutputPage\showErrorPage
showErrorPage( $title, $msg, $params=[])
Output a standard error page.
Definition: OutputPage.php:2448
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
OutputPage\$mParserOptions
ParserOptions $mParserOptions
lazy initialised, use parserOptions()
Definition: OutputPage.php:199
OutputPage\$mContainsNewMagic
int $mContainsNewMagic
Definition: OutputPage.php:193
OutputPage\$limitReportJSData
array $limitReportJSData
Profiling data.
Definition: OutputPage.php:296
OutputPage\addInlineScript
addInlineScript( $script)
Add a self-contained script tag with the given contents Internal use only.
Definition: OutputPage.php:483
OutputPage\getArticleBodyOnly
getArticleBodyOnly()
Return whether the output will contain only the body of the article.
Definition: OutputPage.php:696
OutputPage\getPreventClickjacking
getPreventClickjacking()
Get the prevent-clickjacking flag.
Definition: OutputPage.php:2188
OutputPage\$mModules
array $mModules
Definition: OutputPage.php:141
$options
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 & $options
Definition: hooks.txt:2001
OutputPage\getCanonicalUrl
getCanonicalUrl()
Returns the URL to be used for the <link rel=canonical>> if one is set.
Definition: OutputPage.php:425
OutputPage\setStatusCode
setStatusCode( $statusCode)
Set the HTTP status code to send with the output.
Definition: OutputPage.php:351
OutputPage\$mRedirect
string $mRedirect
Definition: OutputPage.php:91
Html\inlineStyle
static inlineStyle( $contents, $media='all', $attribs=[])
Output a "<style>" tag with the given contents for the given media type (if any).
Definition: Html.php:597
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:2021
OutputPage\getPageTitle
getPageTitle()
Return the "page title", i.e.
Definition: OutputPage.php:958
$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:2014
OutputPage\disable
disable()
Disable output completely, i.e.
Definition: OutputPage.php:1057
OutputPage\sectionEditLinksEnabled
sectionEditLinksEnabled()
Definition: OutputPage.php:3892
OutputPage\setIndexPolicy
setIndexPolicy( $policy)
Set the index policy for the page, but leave the follow policy un- touched.
Definition: OutputPage.php:854
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:562
OutputPage\$mResourceLoader
ResourceLoader $mResourceLoader
Definition: OutputPage.php:150
Hooks\runWithoutAbort
static runWithoutAbort( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:234
OutputPage\$mMetatags
array $mMetatags
Should be private.
Definition: OutputPage.php:47
Skin\getPageClasses
getPageClasses( $title)
TODO: document.
Definition: Skin.php:424
OutputPage\addCategoryLinks
addCategoryLinks(array $categories)
Add an array of categories, with names in the keys.
Definition: OutputPage.php:1242
OutputPage\setRevisionTimestamp
setRevisionTimestamp( $timestamp)
Set the timestamp of the revision which will be displayed.
Definition: OutputPage.php:1607
OutputPage\getHeadItemsArray
getHeadItemsArray()
Get an array of head items.
Definition: OutputPage.php:630
wfClearOutputBuffers
wfClearOutputBuffers()
More legible than passing a 'false' parameter to wfResetOutputBuffers():
Definition: GlobalFunctions.php:1842
$value
$value
Definition: styleTest.css.php:45
OutputPage\$mModuleScripts
array $mModuleScripts
Definition: OutputPage.php:144
OutputPage\addReturnTo
addReturnTo( $title, array $query=[], $text=null, $options=[])
Add a "return to" link pointing to a specified title.
Definition: OutputPage.php:2651
OutputPage\buildExemptModules
buildExemptModules()
Build exempt modules and legacy non-ResourceLoader styles.
Definition: OutputPage.php:3559
OutputPage\$copyrightUrl
string null $copyrightUrl
The URL to send in a <link> element with rel=license.
Definition: OutputPage.php:293
OutputPage\getProperty
getProperty( $name)
Get an additional output property.
Definition: OutputPage.php:718
ParserOptions\newFromContext
static newFromContext(IContextSource $context)
Get a ParserOptions object from a IContextSource object.
Definition: ParserOptions.php:1005
$header
$header
Definition: updateCredits.php:35
OutputPage\addHelpLink
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Definition: OutputPage.php:1402
OutputPage\formatPermissionsErrorMessage
formatPermissionsErrorMessage(array $errors, $action=null)
Format a list of error messages.
Definition: OutputPage.php:2566
OutputPage\$mIndicators
array $mIndicators
Definition: OutputPage.php:112
OutputPage\setTarget
setTarget( $target)
Sets ResourceLoader target for load.php links.
Definition: OutputPage.php:621
MediaWiki\Session\SessionManager
This serves as the entry point to the MediaWiki session handling system.
Definition: SessionManager.php:50
OutputPage\setHTMLTitle
setHTMLTitle( $name)
"HTML title" means the contents of "<title>".
Definition: OutputPage.php:900
OutputPage\addParserOutputContent
addParserOutputContent( $parserOutput, $poOptions=[])
Add the HTML and enhancements for it (like ResourceLoader modules) associated with a ParserOutput obj...
Definition: OutputPage.php:1829
OutputPage\setLanguageLinks
setLanguageLinks(array $newLinkArray)
Reset the language links and add new language links.
Definition: OutputPage.php:1224
OutputPage\setupOOUI
static setupOOUI( $skinName='default', $dir='ltr')
Helper function to setup the PHP implementation of OOUI to use in this request.
Definition: OutputPage.php:3904
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:328
OutputPage\$rlExemptStyleModules
array $rlExemptStyleModules
Definition: OutputPage.php:162
and
and(b) You must cause any modified files to carry prominent notices stating that You changed the files
OutputPage\$mProperties
$mProperties
Additional key => value data.
Definition: OutputPage.php:278
PROTO_RELATIVE
const PROTO_RELATIVE
Definition: Defines.php:231
OutputPage\wrapWikiMsg
wrapWikiMsg( $wrap)
This function takes a number of message/argument specifications, wraps them in some overall structure...
Definition: OutputPage.php:3843
OutputPage\prependHTML
prependHTML( $text)
Prepend $text to the body HTML.
Definition: OutputPage.php:1487
MWNamespace\exists
static exists( $index)
Returns whether the specified namespace exists.
Definition: MWNamespace.php:182
OutputPage\$mEnableClientCache
$mEnableClientCache
Definition: OutputPage.php:209
OutputPage\getHTMLTitle
getHTMLTitle()
Return the "HTML title", i.e.
Definition: OutputPage.php:913
OutputPage\showFileCopyError
showFileCopyError( $old, $new)
Definition: OutputPage.php:2627
ResourceLoaderModule\ORIGIN_CORE_INDIVIDUAL
const ORIGIN_CORE_INDIVIDUAL
Definition: ResourceLoaderModule.php:51
OutputPage\clearSubtitle
clearSubtitle()
Clear the subtitles.
Definition: OutputPage.php:1024
OutputPage\warnModuleTargetFilter
warnModuleTargetFilter( $moduleName)
Definition: OutputPage.php:515
OutputPage\getMetadataAttribute
getMetadataAttribute()
Get the value of the "rel" attribute for metadata links.
Definition: OutputPage.php:434
OutputPage\isUserJsPreview
isUserJsPreview()
Definition: OutputPage.php:2947
OutputPage\$mCdnMaxage
int $mCdnMaxage
Cache stuff.
Definition: OutputPage.php:231
OutputPage\enableOOUI
enableOOUI()
Add ResourceLoader module styles for OOUI and set up the PHP implementation of it for use with MediaW...
Definition: OutputPage.php:3919
OutputPage\$mScripts
$mScripts
Used for JavaScript (predates ResourceLoader)
Definition: OutputPage.php:123
OutputPage\$mAllowedModules
array $mAllowedModules
What level of 'untrustworthiness' is allowed in CSS/JS modules loaded on this page?
Definition: OutputPage.php:183
getSkinThemeMap
static getSkinThemeMap()
Return a map of skin names (in lowercase) to OOUI theme names, defining which theme a given skin shou...
Definition: ResourceLoaderOOUIModule.php:74
OutputPage\$mPrintable
bool $mPrintable
We have to set isPrintable().
Definition: OutputPage.php:82
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:53
ResourceLoaderModule\ORIGIN_ALL
const ORIGIN_ALL
Definition: ResourceLoaderModule.php:61
OutputPage\$mLanguageLinks
array $mLanguageLinks
Array of Interwiki Prefixed (non DB key) Titles (e.g.
Definition: OutputPage.php:115
wfGetAllCallers
wfGetAllCallers( $limit=3)
Return a string consisting of callers in the stack.
Definition: GlobalFunctions.php:1563
OutputPage\setCategoryLinks
setCategoryLinks(array $categories)
Reset the category links (but not the category list) and add $categories.
Definition: OutputPage.php:1327
OutputPage\setFollowPolicy
setFollowPolicy( $policy)
Set the follow policy for the page, but leave the index policy un- touched.
Definition: OutputPage.php:868
OutputPage\setPageTitle
setPageTitle( $name)
"Page title" means the contents of <h1>.
Definition: OutputPage.php:936
OutputPage\getRlClient
getRlClient()
Call this to freeze the module queue and JS config and create a formatter.
Definition: OutputPage.php:2726
OutputPage\$mFileVersion
array $mFileVersion
Definition: OutputPage.php:249
OutputPage\checkLastModified
checkLastModified( $timestamp)
checkLastModified tells the client to use the client-cached page if possible.
Definition: OutputPage.php:737
OutputPage\$mNoGallery
bool $mNoGallery
Comes from the parser.
Definition: OutputPage.php:225
ResourceLoaderClientHtml\makeLoad
static makeLoad(ResourceLoaderContext $mainContext, array $modules, $only, array $extraQuery=[])
Explicily load or embed modules on a page.
Definition: ResourceLoaderClientHtml.php:366
OutputPage\$mHeadItems
array $mHeadItems
Array of elements in "<head>".
Definition: OutputPage.php:135
$args
if( $line===false) $args
Definition: cdb.php:64
OutputPage\$mRevisionTimestamp
string $mRevisionTimestamp
Definition: OutputPage.php:246
print
print
Definition: opensearch_desc.php:46
Title
Represents a title within MediaWiki.
Definition: Title.php:39
$name
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:302
ResourceLoaderModule
Abstraction for ResourceLoader modules, with name registration and maxage functionality.
Definition: ResourceLoaderModule.php:35
OutputPage\setCdnMaxage
setCdnMaxage( $maxage)
Set the value of the "s-maxage" part of the "Cache-control" HTTP header.
Definition: OutputPage.php:1938
Parser\stripOuterParagraph
static stripOuterParagraph( $html)
Strip outer.
Definition: Parser.php:6141
OutputPage\getAllowedModules
getAllowedModules( $type)
Show what level of JavaScript / CSS untrustworthiness is allowed on this page.
Definition: OutputPage.php:1459
ResourceLoader
Dynamic JavaScript and CSS resource loading system.
Definition: ResourceLoader.php:38
OutputPage\addVaryHeader
addVaryHeader( $header, array $option=null)
Add an HTTP header that will influence on the cache.
Definition: OutputPage.php:2041
OutputPage\setProperty
setProperty( $name, $value)
Set an additional output property.
Definition: OutputPage.php:707
OutputPage\isPrintable
isPrintable()
Return whether the page is "printable".
Definition: OutputPage.php:1050
OutputPage\setSyndicated
setSyndicated( $show=true)
Add or remove feed links in the page header This is mainly kept for backward compatibility,...
Definition: OutputPage.php:1096
OutputPage\$mTarget
string null $mTarget
ResourceLoader target for load.php links.
Definition: OutputPage.php:283
OutputPage\addInlineStyle
addInlineStyle( $style_css, $flip='noflip')
Adds inline CSS styles Internal use only.
Definition: OutputPage.php:3546
ResourceLoaderClientHtml\setModules
setModules(array $modules)
Ensure one or more modules are loaded.
Definition: ResourceLoaderClientHtml.php:84
$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:865
OutputPage\userCanPreview
userCanPreview()
To make it harder for someone to slip a user a fake user-JavaScript or user-CSS preview,...
Definition: OutputPage.php:3188
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:626
ResourceLoader\inDebugMode
static inDebugMode()
Determine whether debug mode was requested Order of priority is 1) request param, 2) cookie,...
Definition: ResourceLoader.php:1565
OutputPage\setRedirectedFrom
setRedirectedFrom( $t)
Set $mRedirectedFrom, the Title of the page which redirected us to the current page.
Definition: OutputPage.php:922
ResourceLoaderClientHtml\setModuleStyles
setModuleStyles(array $modules)
Ensure the styles of one or more modules are loaded.
Definition: ResourceLoaderClientHtml.php:94
OutputPage\addWikiTextTitle
addWikiTextTitle( $text, Title $title, $linestart, $tidy=false, $interface=false)
Add wikitext with a custom Title object.
Definition: OutputPage.php:1724
OutputPage\addMetadataLink
addMetadataLink(array $linkarr)
Add a new <link> with "rel" attribute set to "meta".
Definition: OutputPage.php:404
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:495
WebRequest\getRequestId
static getRequestId()
Get the unique request ID.
Definition: WebRequest.php:271
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:319
OutputPage\$mJsConfigVars
array $mJsConfigVars
Definition: OutputPage.php:165
$path
$path
Definition: NoLocalSettings.php:25
OutputPage\isUserCssPreview
isUserCssPreview()
Definition: OutputPage.php:2954
OutputPage\setPrintable
setPrintable()
Set the page as printable, i.e.
Definition: OutputPage.php:1041
OutputPage\getHeadLinksArray
getHeadLinksArray()
Definition: OutputPage.php:3231
OutputPage\adaptCdnTTL
adaptCdnTTL( $mtime, $minTTL=0, $maxTTL=0)
Get TTL in [$minTTL,$maxTTL] in pass it to lowerCdnMaxage()
Definition: OutputPage.php:1966
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:22
OutputPage\addModuleScripts
addModuleScripts( $modules)
Add only JS of one or more modules recognized by ResourceLoader.
Definition: OutputPage.php:579
OutputPage\allowClickjacking
allowClickjacking()
Turn off frame-breaking.
Definition: OutputPage.php:2178
LanguageCode\bcp47
static bcp47( $code)
Get the normalised IETF language tag See unit test for examples.
Definition: LanguageCode.php:94
OutputPage\showFatalError
showFatalError( $message)
Definition: OutputPage.php:2617
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
OutputPage\getHTML
getHTML()
Get the body HTML.
Definition: OutputPage.php:1525
Message
The Message class provides methods which fulfil two basic services:
Definition: Message.php:159
OutputPage\$mLinkHeader
$mLinkHeader
Link: header contents.
Definition: OutputPage.php:301
$keys
$keys
Definition: testCompression.php:67
OutputPage\$styles
array $styles
An array of stylesheet filenames (relative from skins path), with options for CSS media,...
Definition: OutputPage.php:259
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:38
Sanitizer\normalizeCharReferences
static normalizeCharReferences( $text)
Ensure that any entities and character references are legal for XML and XHTML specifically.
Definition: Sanitizer.php:1547
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:1075
OutputPage\parse
parse( $text, $linestart=true, $interface=false, $language=null)
Parse wikitext and return the HTML.
Definition: OutputPage.php:1886
OutputPage\$mPageLinkTitle
string $mPageLinkTitle
Used by skin template.
Definition: OutputPage.php:132
OutputPage\makeResourceLoaderLink
makeResourceLoaderLink( $modules, $only, array $extraQuery=[])
Explicily load or embed modules on a page.
Definition: OutputPage.php:2923
OutputPage\getIndicators
getIndicators()
Get the indicators associated with this page.
Definition: OutputPage.php:1390
$t
$t
Definition: testCompression.php:69
$request
do that in ParserLimitReportFormat instead use this to modify the parameters of the image all existing parser cache entries will be invalid To avoid you ll need to handle that somehow(e.g. with the RejectParserCacheValue hook) because MediaWiki won 't do it for you. & $defaults also a ContextSource after deleting those rows but within the same transaction you ll probably need to make sure the header is varied on $request
Definition: hooks.txt:2806
$vars
static configuration should be added through ResourceLoaderGetConfigVars instead & $vars
Definition: hooks.txt:2228
$wgRequest
if(! $wgDBerrorLogTZ) $wgRequest
Definition: Setup.php:737
Html\element
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:231
ResourceLoader\makeLoaderQuery
static makeLoaderQuery( $modules, $lang, $skin, $user=null, $version=null, $debug=false, $only=null, $printable=false, $handheld=false, $extraQuery=[])
Build a query array (array representation of query string) for load.php.
Definition: ResourceLoader.php:1645
Skin\getSkinName
getSkinName()
Definition: Skin.php:153
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:25
OutputPage\addJsConfigVars
addJsConfigVars( $keys, $value=null)
Add one or more variables to be set in mw.config in JavaScript.
Definition: OutputPage.php:3035
OutputPage\$mPreventClickjacking
bool $mPreventClickjacking
Controls if anti-clickjacking / frame-breaking headers will be sent.
Definition: OutputPage.php:240
Skin
The main skin class which provides methods and properties for all other skins.
Definition: Skin.php:36
$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:1620
OutputPage\getCategories
getCategories( $type='all')
Get the list of category names this page belongs to.
Definition: OutputPage.php:1353
OutputPage\getJsConfigVars
getJsConfigVars()
Get the javascript config vars to include on this page.
Definition: OutputPage.php:3025
OutputPage\getTemplateIds
getTemplateIds()
Get the templates used on this page.
Definition: OutputPage.php:1650
$IP
$IP
Definition: WebStart.php:52
OutputPage\$mIsArticleRelated
bool $mIsArticleRelated
Stores "article flag" toggle.
Definition: OutputPage.php:76
Hooks\run
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:203
OutputPage\isSyndicated
isSyndicated()
Should we output feed links for this page?
Definition: OutputPage.php:1141
OutputPage\$mFeedLinksAppendQuery
$mFeedLinksAppendQuery
Definition: OutputPage.php:176
OutputPage\getFileSearchOptions
getFileSearchOptions()
Get the files used on this page.
Definition: OutputPage.php:1660
OutputPage\$mFeedLinks
$mFeedLinks
Handles the Atom / RSS links.
Definition: OutputPage.php:206
OutputPage\$mDoNothing
bool $mDoNothing
Whether output is disabled.
Definition: OutputPage.php:188
OutputPage\$mArticleBodyOnly
bool $mArticleBodyOnly
Flag if output should only contain the body of the article.
Definition: OutputPage.php:212
OutputPage\$mAdditionalBodyClasses
array $mAdditionalBodyClasses
Additional <body> classes; there are also <body> classes from other sources.
Definition: OutputPage.php:138
MWNamespace\getCanonicalName
static getCanonicalName( $index)
Returns the canonical (English) name for a given index.
Definition: MWNamespace.php:255
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:2423
ResourceLoader\makeInlineScript
static makeInlineScript( $script)
Returns an HTML script tag that runs given JS code after startup and base modules.
Definition: ResourceLoader.php:1506
OutputPage\addTemplate
addTemplate(&$template)
Add the output of a QuickTemplate to the output buffer.
Definition: OutputPage.php:1870
OutputPage\getFeedAppendQuery
getFeedAppendQuery()
Will currently always return null.
Definition: OutputPage.php:1158
OutputPage\lowerCdnMaxage
lowerCdnMaxage( $maxage)
Lower the value of the "s-maxage" part of the "Cache-control" HTTP header.
Definition: OutputPage.php:1948
OutputPage\$mHTMLtitle
string $mHTMLtitle
Stores contents of "<title>" tag.
Definition: OutputPage.php:67
wfExpandUrl
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
Definition: GlobalFunctions.php:521
OutputPage\addFeedLink
addFeedLink( $format, $href)
Add a feed link to the page header.
Definition: OutputPage.php:1131
$e
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException' returning false will NOT prevent logging $e
Definition: hooks.txt:2171
OutputPage\$mCategoryLinks
array $mCategoryLinks
Definition: OutputPage.php:103
OutputPage\transformResourcePath
static transformResourcePath(Config $config, $path)
Transform path to web-accessible static resource.
Definition: OutputPage.php:3697
Sanitizer\removeHTMLtags
static removeHTMLtags( $text, $processCallback=null, $args=[], $extratags=[], $removetags=[], $warnCallback=null)
Cleans up HTML, removes dangerous tags and attributes, and removes HTML comments.
Definition: Sanitizer.php:477
OutputPage\setRobotPolicy
setRobotPolicy( $policy)
Set the robot policy for the page: http://www.robotstxt.org/meta.html
Definition: OutputPage.php:836
$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:57
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:377
OutputPage\transformFilePath
static transformFilePath( $remotePathPrefix, $localPath, $file)
Utility method for transformResourceFilePath().
Definition: OutputPage.php:3739
OutputPage\headElement
headElement(Skin $sk, $includeStyle=true)
Definition: OutputPage.php:2809
$type
$type
Definition: testCompression.php:48
OutputPage\$mStatusCode
int $mStatusCode
Definition: OutputPage.php:94