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