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