summaryrefslogtreecommitdiff
path: root/includes/OutputPage.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/OutputPage.php')
-rw-r--r--includes/OutputPage.php1761
1 files changed, 975 insertions, 786 deletions
diff --git a/includes/OutputPage.php b/includes/OutputPage.php
index e6d4339f..2f8094ab 100644
--- a/includes/OutputPage.php
+++ b/includes/OutputPage.php
@@ -36,20 +36,31 @@
* @todo document
*/
class OutputPage extends ContextSource {
- /// Should be private. Used with addMeta() which adds "<meta>"
- var $mMetatags = array();
+ /** @var array Should be private. Used with addMeta() which adds "<meta>" */
+ protected $mMetatags = array();
- var $mLinktags = array();
- var $mCanonicalUrl = false;
+ /** @var array */
+ protected $mLinktags = array();
- /// Additional stylesheets. Looks like this is for extensions. Might be replaced by resource loader.
- var $mExtStyles = array();
+ /** @var bool */
+ protected $mCanonicalUrl = false;
- /// Should be private - has getter and setter. Contains the HTML title
- var $mPagetitle = '';
+ /**
+ * @var array Additional stylesheets. Looks like this is for extensions.
+ * Might be replaced by resource loader.
+ */
+ protected $mExtStyles = array();
- /// Contains all of the "<body>" content. Should be private we got set/get accessors and the append() method.
- var $mBodytext = '';
+ /**
+ * @var string Should be private - has getter and setter. Contains
+ * the HTML title */
+ public $mPagetitle = '';
+
+ /**
+ * @var string Contains all of the "<body>" content. Should be private we
+ * got set/get accessors and the append() method.
+ */
+ public $mBodytext = '';
/**
* Holds the debug lines that will be output as comments in page source if
@@ -58,43 +69,43 @@ class OutputPage extends ContextSource {
*/
public $mDebugtext = '';
- /// Should be private. Stores contents of "<title>" tag
- var $mHTMLtitle = '';
-
- /// Should be private. Is the displayed content related to the source of the corresponding wiki article.
- var $mIsarticle = false;
+ /** @var string Stores contents of "<title>" tag */
+ private $mHTMLtitle = '';
/**
- * Should be private. Has get/set methods properly documented.
- * Stores "article flag" toggle.
+ * @var bool Is the displayed content related to the source of the
+ * corresponding wiki article.
*/
- var $mIsArticleRelated = true;
+ private $mIsarticle = false;
+
+ /** @var bool Stores "article flag" toggle. */
+ private $mIsArticleRelated = true;
/**
- * Should be private. We have to set isPrintable(). Some pages should
+ * @var bool We have to set isPrintable(). Some pages should
* never be printed (ex: redirections).
*/
- var $mPrintable = false;
+ private $mPrintable = false;
/**
- * Should be private. We have set/get/append methods.
- *
- * Contains the page subtitle. Special pages usually have some links here.
- * Don't confuse with site subtitle added by skins.
+ * @var array Contains the page subtitle. Special pages usually have some
+ * links here. Don't confuse with site subtitle added by skins.
*/
private $mSubtitle = array();
- var $mRedirect = '';
- var $mStatusCode;
+ /** @var string */
+ public $mRedirect = '';
+
+ /** @var int */
+ protected $mStatusCode;
/**
- * mLastModified and mEtag are used for sending cache control.
- * The whole caching system should probably be moved into its own class.
+ * @var string Variable mLastModified and mEtag are used for sending cache control.
+ * The whole caching system should probably be moved into its own class.
*/
- var $mLastModified = '';
+ protected $mLastModified = '';
/**
- * Should be private. No getter but used in sendCacheControl();
* Contains an HTTP Entity Tags (see RFC 2616 section 3.13) which is used
* as a unique identifier for the content. It is later used by the client
* to compare its cached version with the server version. Client sends
@@ -103,53 +114,70 @@ class OutputPage extends ContextSource {
* To get more information, you will have to look at HTTP/1.1 protocol which
* is properly described in RFC 2616 : http://tools.ietf.org/html/rfc2616
*/
- var $mETag = false;
+ private $mETag = false;
- var $mCategoryLinks = array();
- var $mCategories = array();
+ /** @var array */
+ protected $mCategoryLinks = array();
- /// Should be private. Array of Interwiki Prefixed (non DB key) Titles (e.g. 'fr:Test page')
- var $mLanguageLinks = array();
+ /** @var array */
+ protected $mCategories = array();
+
+ /** @var array Array of Interwiki Prefixed (non DB key) Titles (e.g. 'fr:Test page') */
+ private $mLanguageLinks = array();
/**
- * Should be private. Used for JavaScript (pre resource loader)
- * We should split js / css.
+ * Used for JavaScript (pre resource loader)
+ * @todo We should split JS / CSS.
* mScripts content is inserted as is in "<head>" by Skin. This might
- * contains either a link to a stylesheet or inline css.
+ * contain either a link to a stylesheet or inline CSS.
*/
- var $mScripts = '';
+ private $mScripts = '';
- /**
- * Inline CSS styles. Use addInlineStyle() sparingly
- */
- var $mInlineStyles = '';
+ /** @var string Inline CSS styles. Use addInlineStyle() sparingly */
+ protected $mInlineStyles = '';
- //
- var $mLinkColours;
+ /** @todo Unused? */
+ private $mLinkColours;
/**
- * Used by skin template.
+ * @var string Used by skin template.
* Example: $tpl->set( 'displaytitle', $out->mPageLinkTitle );
*/
- var $mPageLinkTitle = '';
+ public $mPageLinkTitle = '';
+
+ /** @var array Array of elements in "<head>". Parser might add its own headers! */
+ protected $mHeadItems = array();
+
+ // @todo FIXME: Next 5 variables probably come from the resource loader
+
+ /** @var array */
+ protected $mModules = array();
+
+ /** @var array */
+ protected $mModuleScripts = array();
+
+ /** @var array */
+ protected $mModuleStyles = array();
+
+ /** @var array */
+ protected $mModuleMessages = array();
- /// Array of elements in "<head>". Parser might add its own headers!
- var $mHeadItems = array();
+ /** @var ResourceLoader */
+ protected $mResourceLoader;
- // @todo FIXME: Next variables probably comes from the resource loader
- var $mModules = array(), $mModuleScripts = array(), $mModuleStyles = array(), $mModuleMessages = array();
- var $mResourceLoader;
- var $mJsConfigVars = array();
+ /** @var array */
+ protected $mJsConfigVars = array();
- /** @todo FIXME: Is this still used ?*/
- var $mInlineMsg = array();
+ /** @var array */
+ protected $mTemplateIds = array();
- var $mTemplateIds = array();
- var $mImageTimeKeys = array();
+ /** @var array */
+ protected $mImageTimeKeys = array();
- var $mRedirectCode = '';
+ /** @var string */
+ public $mRedirectCode = '';
- var $mFeedLinksAppendQuery = null;
+ protected $mFeedLinksAppendQuery = null;
/** @var array
* What level of 'untrustworthiness' is allowed in CSS/JS modules loaded on this page?
@@ -160,14 +188,19 @@ class OutputPage extends ContextSource {
ResourceLoaderModule::TYPE_COMBINED => ResourceLoaderModule::ORIGIN_ALL,
);
+ /** @var bool Whether output is disabled. If this is true, the 'output' method will do nothing. */
+ protected $mDoNothing = false;
+
+ // Parser related.
+
/**
- * @EasterEgg I just love the name for this self documenting variable.
- * @todo document
+ * @var int
+ * @todo Unused?
*/
- var $mDoNothing = false;
+ private $mContainsOldMagic = 0;
- // Parser related.
- var $mContainsOldMagic = 0, $mContainsNewMagic = 0;
+ /** @var int */
+ protected $mContainsNewMagic = 0;
/**
* lazy initialised, use parserOptions()
@@ -176,57 +209,64 @@ class OutputPage extends ContextSource {
protected $mParserOptions = null;
/**
- * Handles the atom / rss links.
- * We probably only support atom in 2011.
- * Looks like a private variable.
+ * Handles the Atom / RSS links.
+ * We probably only support Atom in 2011.
* @see $wgAdvertisedFeedTypes
*/
- var $mFeedLinks = array();
+ private $mFeedLinks = array();
// Gwicke work on squid caching? Roughly from 2003.
- var $mEnableClientCache = true;
+ protected $mEnableClientCache = true;
- /**
- * Flag if output should only contain the body of the article.
- * Should be private.
- */
- var $mArticleBodyOnly = false;
+ /** @var bool Flag if output should only contain the body of the article. */
+ private $mArticleBodyOnly = false;
+
+ /** @var bool */
+ protected $mNewSectionLink = false;
- var $mNewSectionLink = false;
- var $mHideNewSectionLink = false;
+ /** @var bool */
+ protected $mHideNewSectionLink = false;
/**
- * Comes from the parser. This was probably made to load CSS/JS only
- * if we had "<gallery>". Used directly in CategoryPage.php
+ * @var bool Comes from the parser. This was probably made to load CSS/JS
+ * only if we had "<gallery>". Used directly in CategoryPage.php.
* Looks like resource loader can replace this.
*/
- var $mNoGallery = false;
+ public $mNoGallery = false;
+
+ /** @var string */
+ private $mPageTitleActionText = '';
+
+ /** @var array */
+ private $mParseWarnings = array();
- // should be private.
- var $mPageTitleActionText = '';
- var $mParseWarnings = array();
+ /** @var int Cache stuff. Looks like mEnableClientCache */
+ protected $mSquidMaxage = 0;
- // Cache stuff. Looks like mEnableClientCache
- var $mSquidMaxage = 0;
+ /**
+ * @var bool
+ * @todo Document
+ */
+ protected $mPreventClickjacking = true;
- // @todo document
- var $mPreventClickjacking = true;
+ /** @var int To include the variable {{REVISIONID}} */
+ private $mRevisionId = null;
- /// should be private. To include the variable {{REVISIONID}}
- var $mRevisionId = null;
+ /** @var string */
private $mRevisionTimestamp = null;
- var $mFileVersion = null;
+ /** @var array */
+ protected $mFileVersion = null;
/**
- * An array of stylesheet filenames (relative from skins path), with options
- * for CSS media, IE conditions, and RTL/LTR direction.
+ * @var array An array of stylesheet filenames (relative from skins path),
+ * with options for CSS media, IE conditions, and RTL/LTR direction.
* For internal use; add settings in the skin via $this->addStyle()
*
* Style again! This seems like a code duplication since we already have
- * mStyles. This is what makes OpenSource amazing.
+ * mStyles. This is what makes Open Source amazing.
*/
- var $styles = array();
+ protected $styles = array();
/**
* Whether jQuery is already handled.
@@ -253,19 +293,25 @@ class OutputPage extends ContextSource {
private $mProperties = array();
/**
- * @var string|null: ResourceLoader target for load.php links. If null, will be omitted
+ * @var string|null ResourceLoader target for load.php links. If null, will be omitted
*/
private $mTarget = null;
/**
- * @var bool: Whether output should contain table of contents
+ * @var bool Whether parser output should contain table of contents
*/
private $mEnableTOC = true;
/**
+ * @var bool Whether parser output should contain section edit links
+ */
+ private $mEnableSectionEditLinks = true;
+
+ /**
* Constructor for OutputPage. This should not be called directly.
* Instead a new RequestContext should be created and it will implicitly create
* a OutputPage tied to that context.
+ * @param IContextSource|null $context
*/
function __construct( IContextSource $context = null ) {
if ( $context === null ) {
@@ -291,7 +337,7 @@ class OutputPage extends ContextSource {
/**
* Get the URL to redirect to, or an empty string if not redirect URL set
*
- * @return String
+ * @return string
*/
public function getRedirect() {
return $this->mRedirect;
@@ -300,7 +346,7 @@ class OutputPage extends ContextSource {
/**
* Set the HTTP status code to send with the output.
*
- * @param $statusCode Integer
+ * @param int $statusCode
*/
public function setStatusCode( $statusCode ) {
$this->mStatusCode = $statusCode;
@@ -310,32 +356,52 @@ class OutputPage extends ContextSource {
* Add a new "<meta>" tag
* To add an http-equiv meta tag, precede the name with "http:"
*
- * @param string $name tag name
- * @param string $val tag value
+ * @param string $name Tag name
+ * @param string $val Tag value
*/
function addMeta( $name, $val ) {
array_push( $this->mMetatags, array( $name, $val ) );
}
/**
+ * Returns the current <meta> tags
+ *
+ * @since 1.25
+ * @return array
+ */
+ public function getMetaTags() {
+ return $this->mMetatags;
+ }
+
+ /**
* Add a new \<link\> tag to the page header.
*
* Note: use setCanonicalUrl() for rel=canonical.
*
- * @param array $linkarr associative array of attributes.
+ * @param array $linkarr Associative array of attributes.
*/
- function addLink( $linkarr ) {
+ function addLink( array $linkarr ) {
array_push( $this->mLinktags, $linkarr );
}
/**
+ * Returns the current <link> tags
+ *
+ * @since 1.25
+ * @return array
+ */
+ public function getLinkTags() {
+ return $this->mLinktags;
+ }
+
+ /**
* Add a new \<link\> with "rel" attribute set to "meta"
*
- * @param array $linkarr associative array mapping attribute names to their
+ * @param array $linkarr Associative array mapping attribute names to their
* values, both keys and values will be escaped, and the
* "rel" attribute will be automatically added
*/
- function addMetadataLink( $linkarr ) {
+ function addMetadataLink( array $linkarr ) {
$linkarr['rel'] = $this->getMetadataAttribute();
$this->addLink( $linkarr );
}
@@ -343,15 +409,27 @@ class OutputPage extends ContextSource {
/**
* Set the URL to be used for the <link rel=canonical>. This should be used
* in preference to addLink(), to avoid duplicate link tags.
+ * @param string $url
*/
function setCanonicalUrl( $url ) {
$this->mCanonicalUrl = $url;
}
/**
+ * Returns the URL to be used for the <link rel=canonical> if
+ * one is set.
+ *
+ * @since 1.25
+ * @return bool|string
+ */
+ public function getCanonicalUrl() {
+ return $this->mCanonicalUrl;
+ }
+
+ /**
* Get the value of the "rel" attribute for metadata links
*
- * @return String
+ * @return string
*/
public function getMetadataAttribute() {
# note: buggy CC software only reads first "meta" link
@@ -367,7 +445,7 @@ class OutputPage extends ContextSource {
/**
* Add raw HTML to the list of scripts (including \<script\> tag, etc.)
*
- * @param string $script raw HTML
+ * @param string $script Raw HTML
*/
function addScript( $script ) {
$this->mScripts .= $script . "\n";
@@ -376,7 +454,7 @@ class OutputPage extends ContextSource {
/**
* Register and add a stylesheet from an extension directory.
*
- * @param string $url path to sheet. Provide either a full url (beginning
+ * @param string $url Path to sheet. Provide either a full url (beginning
* with 'http', etc) or a relative path from the document root
* (beginning with '/'). Otherwise it behaves identically to
* addStyle() and draws from the /skins folder.
@@ -388,7 +466,7 @@ class OutputPage extends ContextSource {
/**
* Get all styles added by extensions
*
- * @return Array
+ * @return array
*/
function getExtStyle() {
return $this->mExtStyles;
@@ -397,20 +475,19 @@ class OutputPage extends ContextSource {
/**
* Add a JavaScript file out of skins/common, or a given relative path.
*
- * @param string $file filename in skins/common or complete on-server path
+ * @param string $file Filename in skins/common or complete on-server path
* (/foo/bar.js)
- * @param string $version style version of the file. Defaults to $wgStyleVersion
+ * @param string $version Style version of the file. Defaults to $wgStyleVersion
*/
public function addScriptFile( $file, $version = null ) {
- global $wgStylePath, $wgStyleVersion;
// See if $file parameter is an absolute URL or begins with a slash
if ( substr( $file, 0, 1 ) == '/' || preg_match( '#^[a-z]*://#i', $file ) ) {
$path = $file;
} else {
- $path = "{$wgStylePath}/common/{$file}";
+ $path = $this->getConfig()->get( 'StylePath' ) . "/common/{$file}";
}
if ( is_null( $version ) ) {
- $version = $wgStyleVersion;
+ $version = $this->getConfig()->get( 'StyleVersion' );
}
$this->addScript( Html::linkedScript( wfAppendQuery( $path, $version ) ) );
}
@@ -427,21 +504,25 @@ class OutputPage extends ContextSource {
/**
* Get all registered JS and CSS tags for the header.
*
- * @return String
+ * @return string
+ * @deprecated since 1.24 Use OutputPage::headElement to build the full header.
*/
function getScript() {
+ wfDeprecated( __METHOD__, '1.24' );
return $this->mScripts . $this->getHeadItems();
}
/**
* Filter an array of modules to remove insufficiently trustworthy members, and modules
* which are no longer registered (eg a page is cached before an extension is disabled)
- * @param $modules Array
- * @param string $position if not null, only return modules with this position
- * @param $type string
- * @return Array
+ * @param array $modules
+ * @param string|null $position If not null, only return modules with this position
+ * @param string $type
+ * @return array
*/
- protected function filterModules( $modules, $position = null, $type = ResourceLoaderModule::TYPE_COMBINED ) {
+ protected function filterModules( array $modules, $position = null,
+ $type = ResourceLoaderModule::TYPE_COMBINED
+ ) {
$resourceLoader = $this->getResourceLoader();
$filteredModules = array();
foreach ( $modules as $val ) {
@@ -449,8 +530,8 @@ class OutputPage extends ContextSource {
if ( $module instanceof ResourceLoaderModule
&& $module->getOrigin() <= $this->getAllowedModules( $type )
&& ( is_null( $position ) || $module->getPosition() == $position )
- && ( !$this->mTarget || in_array( $this->mTarget, $module->getTargets() ) ) )
- {
+ && ( !$this->mTarget || in_array( $this->mTarget, $module->getTargets() ) )
+ ) {
$filteredModules[] = $val;
}
}
@@ -460,10 +541,10 @@ class OutputPage extends ContextSource {
/**
* Get the list of modules to include on this page
*
- * @param bool $filter whether to filter out insufficiently trustworthy modules
- * @param string $position if not null, only return modules with this position
- * @param $param string
- * @return Array of module names
+ * @param bool $filter Whether to filter out insufficiently trustworthy modules
+ * @param string|null $position If not null, only return modules with this position
+ * @param string $param
+ * @return array Array of module names
*/
public function getModules( $filter = false, $position = null, $param = 'mModules' ) {
$modules = array_values( array_unique( $this->$param ) );
@@ -477,7 +558,7 @@ class OutputPage extends ContextSource {
* through this function will be loaded by the resource loader when the
* page loads.
*
- * @param $modules Mixed: module name (string) or array of module names
+ * @param string|array $modules Module name (string) or array of module names
*/
public function addModules( $modules ) {
$this->mModules = array_merge( $this->mModules, (array)$modules );
@@ -486,10 +567,10 @@ class OutputPage extends ContextSource {
/**
* Get the list of module JS to include on this page
*
- * @param $filter
- * @param $position
+ * @param bool $filter
+ * @param string|null $position
*
- * @return array of module names
+ * @return array Array of module names
*/
public function getModuleScripts( $filter = false, $position = null ) {
return $this->getModules( $filter, $position, 'mModuleScripts' );
@@ -500,7 +581,7 @@ class OutputPage extends ContextSource {
* scripts added through this function will be loaded by the resource loader when
* the page loads.
*
- * @param $modules Mixed: module name (string) or array of module names
+ * @param string|array $modules Module name (string) or array of module names
*/
public function addModuleScripts( $modules ) {
$this->mModuleScripts = array_merge( $this->mModuleScripts, (array)$modules );
@@ -509,10 +590,10 @@ class OutputPage extends ContextSource {
/**
* Get the list of module CSS to include on this page
*
- * @param $filter
- * @param $position
+ * @param bool $filter
+ * @param string|null $position
*
- * @return Array of module names
+ * @return array Array of module names
*/
public function getModuleStyles( $filter = false, $position = null ) {
return $this->getModules( $filter, $position, 'mModuleStyles' );
@@ -525,7 +606,7 @@ class OutputPage extends ContextSource {
* tags, rather than as a combined Javascript and CSS package. Thus, they will
* load when JavaScript is disabled (unless CSS also happens to be disabled).
*
- * @param $modules Mixed: module name (string) or array of module names
+ * @param string|array $modules Module name (string) or array of module names
*/
public function addModuleStyles( $modules ) {
$this->mModuleStyles = array_merge( $this->mModuleStyles, (array)$modules );
@@ -534,10 +615,10 @@ class OutputPage extends ContextSource {
/**
* Get the list of module messages to include on this page
*
- * @param $filter
- * @param $position
+ * @param bool $filter
+ * @param string|null $position
*
- * @return Array of module names
+ * @return array Array of module names
*/
public function getModuleMessages( $filter = false, $position = null ) {
return $this->getModules( $filter, $position, 'mModuleMessages' );
@@ -548,14 +629,14 @@ class OutputPage extends ContextSource {
* Module messages added through this function will be loaded by the resource
* loader when the page loads.
*
- * @param $modules Mixed: module name (string) or array of module names
+ * @param string|array $modules Module name (string) or array of module names
*/
public function addModuleMessages( $modules ) {
$this->mModuleMessages = array_merge( $this->mModuleMessages, (array)$modules );
}
/**
- * @return null|string: ResourceLoader target
+ * @return null|string ResourceLoader target
*/
public function getTarget() {
return $this->mTarget;
@@ -564,7 +645,7 @@ class OutputPage extends ContextSource {
/**
* Sets ResourceLoader target for load.php links. If null, will be omitted
*
- * @param $target string|null
+ * @param string|null $target
*/
public function setTarget( $target ) {
$this->mTarget = $target;
@@ -573,7 +654,7 @@ class OutputPage extends ContextSource {
/**
* Get an array of head items
*
- * @return Array
+ * @return array
*/
function getHeadItemsArray() {
return $this->mHeadItems;
@@ -582,9 +663,12 @@ class OutputPage extends ContextSource {
/**
* Get all header items in a string
*
- * @return String
+ * @return string
+ * @deprecated since 1.24 Use OutputPage::headElement or
+ * if absolutely necessary use OutputPage::getHeadItemsArray
*/
function getHeadItems() {
+ wfDeprecated( __METHOD__, '1.24' );
$s = '';
foreach ( $this->mHeadItems as $item ) {
$s .= $item;
@@ -595,8 +679,8 @@ class OutputPage extends ContextSource {
/**
* Add or replace an header item to the output
*
- * @param string $name item name
- * @param string $value raw HTML
+ * @param string $name Item name
+ * @param string $value Raw HTML
*/
public function addHeadItem( $name, $value ) {
$this->mHeadItems[$name] = $value;
@@ -605,8 +689,8 @@ class OutputPage extends ContextSource {
/**
* Check if the header item $name is already set
*
- * @param string $name item name
- * @return Boolean
+ * @param string $name Item name
+ * @return bool
*/
public function hasHeadItem( $name ) {
return isset( $this->mHeadItems[$name] );
@@ -615,7 +699,7 @@ class OutputPage extends ContextSource {
/**
* Set the value of the ETag HTTP header, only used if $wgUseETag is true
*
- * @param string $tag value of "ETag" header
+ * @param string $tag Value of "ETag" header
*/
function setETag( $tag ) {
$this->mETag = $tag;
@@ -626,7 +710,7 @@ class OutputPage extends ContextSource {
* without any skin, sidebar, etc.
* Used e.g. when calling with "action=render".
*
- * @param $only Boolean: whether to output only the body of the article
+ * @param bool $only Whether to output only the body of the article
*/
public function setArticleBodyOnly( $only ) {
$this->mArticleBodyOnly = $only;
@@ -635,7 +719,7 @@ class OutputPage extends ContextSource {
/**
* Return whether the output will contain only the body of the article
*
- * @return Boolean
+ * @return bool
*/
public function getArticleBodyOnly() {
return $this->mArticleBodyOnly;
@@ -656,8 +740,8 @@ class OutputPage extends ContextSource {
* Get an additional output property
* @since 1.21
*
- * @param $name
- * @return mixed: Property value or null if not found
+ * @param string $name
+ * @return mixed Property value or null if not found
*/
public function getProperty( $name ) {
if ( isset( $this->mProperties[$name] ) ) {
@@ -674,23 +758,18 @@ class OutputPage extends ContextSource {
*
* Side effect: sets mLastModified for Last-Modified header
*
- * @param $timestamp string
+ * @param string $timestamp
*
- * @return Boolean: true if cache-ok headers was sent.
+ * @return bool True if cache-ok headers was sent.
*/
public function checkLastModified( $timestamp ) {
- global $wgCachePages, $wgCacheEpoch, $wgUseSquid, $wgSquidMaxage;
-
if ( !$timestamp || $timestamp == '19700101000000' ) {
wfDebug( __METHOD__ . ": CACHE DISABLED, NO TIMESTAMP\n" );
return false;
}
- if ( !$wgCachePages ) {
- wfDebug( __METHOD__ . ": CACHE DISABLED\n", false );
- return false;
- }
- if ( $this->getUser()->getOption( 'nocache' ) ) {
- wfDebug( __METHOD__ . ": USER DISABLED CACHE\n", false );
+ $config = $this->getConfig();
+ if ( !$config->get( 'CachePages' ) ) {
+ wfDebug( __METHOD__ . ": CACHE DISABLED\n" );
return false;
}
@@ -698,11 +777,11 @@ class OutputPage extends ContextSource {
$modifiedTimes = array(
'page' => $timestamp,
'user' => $this->getUser()->getTouched(),
- 'epoch' => $wgCacheEpoch
+ 'epoch' => $config->get( 'CacheEpoch' )
);
- if ( $wgUseSquid ) {
+ if ( $config->get( 'UseSquid' ) ) {
// bug 44570: the core page itself may not change, but resources might
- $modifiedTimes['sepoch'] = wfTimestamp( TS_MW, time() - $wgSquidMaxage );
+ $modifiedTimes['sepoch'] = wfTimestamp( TS_MW, time() - $config->get( 'SquidMaxage' ) );
}
wfRunHooks( 'OutputPageCheckLastModified', array( &$modifiedTimes ) );
@@ -711,7 +790,7 @@ class OutputPage extends ContextSource {
$clientHeader = $this->getRequest()->getHeader( 'If-Modified-Since' );
if ( $clientHeader === false ) {
- wfDebug( __METHOD__ . ": client did not send If-Modified-Since header\n", false );
+ wfDebug( __METHOD__ . ": client did not send If-Modified-Since header\n", 'log' );
return false;
}
@@ -724,7 +803,8 @@ class OutputPage extends ContextSource {
$clientHeaderTime = strtotime( $clientHeader );
wfRestoreWarnings();
if ( !$clientHeaderTime ) {
- wfDebug( __METHOD__ . ": unable to parse the client's If-Modified-Since header: $clientHeader\n" );
+ wfDebug( __METHOD__
+ . ": unable to parse the client's If-Modified-Since header: $clientHeader\n" );
return false;
}
$clientHeaderTime = wfTimestamp( TS_MW, $clientHeaderTime );
@@ -739,17 +819,17 @@ class OutputPage extends ContextSource {
}
wfDebug( __METHOD__ . ": client sent If-Modified-Since: " .
- wfTimestamp( TS_ISO_8601, $clientHeaderTime ) . "\n", false );
+ wfTimestamp( TS_ISO_8601, $clientHeaderTime ) . "\n", 'log' );
wfDebug( __METHOD__ . ": effective Last-Modified: " .
- wfTimestamp( TS_ISO_8601, $maxModified ) . "\n", false );
+ wfTimestamp( TS_ISO_8601, $maxModified ) . "\n", 'log' );
if ( $clientHeaderTime < $maxModified ) {
- wfDebug( __METHOD__ . ": STALE, $info\n", false );
+ wfDebug( __METHOD__ . ": STALE, $info\n", 'log' );
return false;
}
# Not modified
# Give a 304 response code and disable body output
- wfDebug( __METHOD__ . ": NOT MODIFIED, $info\n", false );
+ wfDebug( __METHOD__ . ": NOT MODIFIED, $info\n", 'log' );
ini_set( 'zlib.output_compression', 0 );
$this->getRequest()->response()->header( "HTTP/1.1 304 Not Modified" );
$this->sendCacheControl();
@@ -766,7 +846,7 @@ class OutputPage extends ContextSource {
/**
* Override the last modified timestamp
*
- * @param string $timestamp new timestamp, in a format readable by
+ * @param string $timestamp New timestamp, in a format readable by
* wfTimestamp()
*/
public function setLastModified( $timestamp ) {
@@ -776,7 +856,7 @@ class OutputPage extends ContextSource {
/**
* Set the robot policy for the page: <http://www.robotstxt.org/meta.html>
*
- * @param string $policy the literal string to output as the contents of
+ * @param string $policy The literal string to output as the contents of
* the meta tag. Will be parsed according to the spec and output in
* standardized form.
* @return null
@@ -810,7 +890,7 @@ class OutputPage extends ContextSource {
* Set the follow policy for the page, but leave the index policy un-
* touched.
*
- * @param string $policy either 'follow' or 'nofollow'.
+ * @param string $policy Either 'follow' or 'nofollow'.
* @return null
*/
public function setFollowPolicy( $policy ) {
@@ -824,7 +904,7 @@ class OutputPage extends ContextSource {
* Set the new value of the "action text", this will be added to the
* "HTML title", separated from it with " - ".
*
- * @param string $text new value of the "action text"
+ * @param string $text New value of the "action text"
*/
public function setPageTitleActionText( $text ) {
$this->mPageTitleActionText = $text;
@@ -833,20 +913,17 @@ class OutputPage extends ContextSource {
/**
* Get the value of the "action text"
*
- * @return String
+ * @return string
*/
public function getPageTitleActionText() {
- if ( isset( $this->mPageTitleActionText ) ) {
- return $this->mPageTitleActionText;
- }
- return '';
+ return $this->mPageTitleActionText;
}
/**
* "HTML title" means the contents of "<title>".
* It is stored as plain, unescaped text and will be run through htmlspecialchars in the skin file.
*
- * @param $name string
+ * @param string|Message $name
*/
public function setHTMLTitle( $name ) {
if ( $name instanceof Message ) {
@@ -859,7 +936,7 @@ class OutputPage extends ContextSource {
/**
* Return the "HTML title", i.e. the content of the "<title>" tag.
*
- * @return String
+ * @return string
*/
public function getHTMLTitle() {
return $this->mHTMLtitle;
@@ -868,19 +945,21 @@ class OutputPage extends ContextSource {
/**
* Set $mRedirectedFrom, the Title of the page which redirected us to the current page.
*
- * @param $t Title
+ * @param Title $t
*/
public function setRedirectedFrom( $t ) {
$this->mRedirectedFrom = $t;
}
/**
- * "Page title" means the contents of \<h1\>. It is stored as a valid HTML fragment.
- * This function allows good tags like \<sup\> in the \<h1\> tag, but not bad tags like \<script\>.
- * This function automatically sets \<title\> to the same content as \<h1\> but with all tags removed.
- * Bad tags that were escaped in \<h1\> will still be escaped in \<title\>, and good tags like \<i\> will be dropped entirely.
+ * "Page title" means the contents of \<h1\>. It is stored as a valid HTML
+ * fragment. This function allows good tags like \<sup\> in the \<h1\> tag,
+ * but not bad tags like \<script\>. This function automatically sets
+ * \<title\> to the same content as \<h1\> but with all tags removed. Bad
+ * tags that were escaped in \<h1\> will still be escaped in \<title\>, and
+ * good tags like \<i\> will be dropped entirely.
*
- * @param $name string|Message
+ * @param string|Message $name
*/
public function setPageTitle( $name ) {
if ( $name instanceof Message ) {
@@ -893,13 +972,16 @@ class OutputPage extends ContextSource {
$this->mPagetitle = $nameWithTags;
# change "<i>foo&amp;bar</i>" to "foo&bar"
- $this->setHTMLTitle( $this->msg( 'pagetitle' )->rawParams( Sanitizer::stripAllTags( $nameWithTags ) ) );
+ $this->setHTMLTitle(
+ $this->msg( 'pagetitle' )->rawParams( Sanitizer::stripAllTags( $nameWithTags ) )
+ ->inContentLanguage()
+ );
}
/**
* Return the "page title", i.e. the content of the \<h1\> tag.
*
- * @return String
+ * @return string
*/
public function getPageTitle() {
return $this->mPagetitle;
@@ -908,7 +990,7 @@ class OutputPage extends ContextSource {
/**
* Set the Title object to use
*
- * @param $t Title object
+ * @param Title $t
*/
public function setTitle( Title $t ) {
$this->getContext()->setTitle( $t );
@@ -917,7 +999,7 @@ class OutputPage extends ContextSource {
/**
* Replace the subtitle with $str
*
- * @param string|Message $str new value of the subtitle. String should be safe HTML.
+ * @param string|Message $str New value of the subtitle. String should be safe HTML.
*/
public function setSubtitle( $str ) {
$this->clearSubtitle();
@@ -927,8 +1009,8 @@ class OutputPage extends ContextSource {
/**
* Add $str to the subtitle
*
- * @deprecated in 1.19; use addSubtitle() instead
- * @param string|Message $str to add to the subtitle
+ * @deprecated since 1.19; use addSubtitle() instead
+ * @param string|Message $str String or Message to add to the subtitle
*/
public function appendSubtitle( $str ) {
$this->addSubtitle( $str );
@@ -937,7 +1019,7 @@ class OutputPage extends ContextSource {
/**
* Add $str to the subtitle
*
- * @param string|Message $str to add to the subtitle. String should be safe HTML.
+ * @param string|Message $str String or Message to add to the subtitle. String should be safe HTML.
*/
public function addSubtitle( $str ) {
if ( $str instanceof Message ) {
@@ -950,14 +1032,15 @@ class OutputPage extends ContextSource {
/**
* Add a subtitle containing a backlink to a page
*
- * @param $title Title to link to
+ * @param Title $title Title to link to
+ * @param array $query Array of additional parameters to include in the link
*/
- public function addBacklinkSubtitle( Title $title ) {
- $query = array();
+ public function addBacklinkSubtitle( Title $title, $query = array() ) {
if ( $title->isRedirect() ) {
$query['redirect'] = 'no';
}
- $this->addSubtitle( $this->msg( 'backlinksubtitle' )->rawParams( Linker::link( $title, null, array(), $query ) ) );
+ $this->addSubtitle( $this->msg( 'backlinksubtitle' )
+ ->rawParams( Linker::link( $title, null, array(), $query ) ) );
}
/**
@@ -970,7 +1053,7 @@ class OutputPage extends ContextSource {
/**
* Get the subtitle
*
- * @return String
+ * @return string
*/
public function getSubtitle() {
return implode( "<br />\n\t\t\t\t", $this->mSubtitle );
@@ -987,7 +1070,7 @@ class OutputPage extends ContextSource {
/**
* Return whether the page is "printable"
*
- * @return Boolean
+ * @return bool
*/
public function isPrintable() {
return $this->mPrintable;
@@ -1003,7 +1086,7 @@ class OutputPage extends ContextSource {
/**
* Return whether the output will be completely disabled
*
- * @return Boolean
+ * @return bool
*/
public function isDisabled() {
return $this->mDoNothing;
@@ -1012,7 +1095,7 @@ class OutputPage extends ContextSource {
/**
* Show an "add new section" link?
*
- * @return Boolean
+ * @return bool
*/
public function showNewSectionLink() {
return $this->mNewSectionLink;
@@ -1021,7 +1104,7 @@ class OutputPage extends ContextSource {
/**
* Forcibly hide the new section link?
*
- * @return Boolean
+ * @return bool
*/
public function forceHideNewSectionLink() {
return $this->mHideNewSectionLink;
@@ -1033,7 +1116,7 @@ class OutputPage extends ContextSource {
* for the new version
* @see addFeedLink()
*
- * @param $show Boolean: true: add default feeds, false: remove all feeds
+ * @param bool $show True: add default feeds, false: remove all feeds
*/
public function setSyndicated( $show = true ) {
if ( $show ) {
@@ -1049,15 +1132,13 @@ class OutputPage extends ContextSource {
* for the new version
* @see addFeedLink()
*
- * @param string $val query to append to feed links or false to output
+ * @param string $val Query to append to feed links or false to output
* default links
*/
public function setFeedAppendQuery( $val ) {
- global $wgAdvertisedFeedTypes;
-
$this->mFeedLinks = array();
- foreach ( $wgAdvertisedFeedTypes as $type ) {
+ foreach ( $this->getConfig()->get( 'AdvertisedFeedTypes' ) as $type ) {
$query = "feed=$type";
if ( is_string( $val ) ) {
$query .= '&' . $val;
@@ -1069,20 +1150,18 @@ class OutputPage extends ContextSource {
/**
* Add a feed link to the page header
*
- * @param string $format feed type, should be a key of $wgFeedClasses
+ * @param string $format Feed type, should be a key of $wgFeedClasses
* @param string $href URL
*/
public function addFeedLink( $format, $href ) {
- global $wgAdvertisedFeedTypes;
-
- if ( in_array( $format, $wgAdvertisedFeedTypes ) ) {
+ if ( in_array( $format, $this->getConfig()->get( 'AdvertisedFeedTypes' ) ) ) {
$this->mFeedLinks[$format] = $href;
}
}
/**
* Should we output feed links for this page?
- * @return Boolean
+ * @return bool
*/
public function isSyndicated() {
return count( $this->mFeedLinks ) > 0;
@@ -1090,7 +1169,7 @@ class OutputPage extends ContextSource {
/**
* Return URLs for each supported syndication format for this page.
- * @return array associating format keys with URLs
+ * @return array Associating format keys with URLs
*/
public function getSyndicationLinks() {
return $this->mFeedLinks;
@@ -1110,7 +1189,7 @@ class OutputPage extends ContextSource {
* corresponding article on the wiki
* Setting true will cause the change "article related" toggle to true
*
- * @param $v Boolean
+ * @param bool $v
*/
public function setArticleFlag( $v ) {
$this->mIsarticle = $v;
@@ -1123,7 +1202,7 @@ class OutputPage extends ContextSource {
* Return whether the content displayed page is related to the source of
* the corresponding article on the wiki
*
- * @return Boolean
+ * @return bool
*/
public function isArticle() {
return $this->mIsarticle;
@@ -1133,7 +1212,7 @@ class OutputPage extends ContextSource {
* Set whether this page is related an article on the wiki
* Setting false will cause the change of "article flag" toggle to false
*
- * @param $v Boolean
+ * @param bool $v
*/
public function setArticleRelated( $v ) {
$this->mIsArticleRelated = $v;
@@ -1145,7 +1224,7 @@ class OutputPage extends ContextSource {
/**
* Return whether this page is related an article on the wiki
*
- * @return Boolean
+ * @return bool
*/
public function isArticleRelated() {
return $this->mIsArticleRelated;
@@ -1157,7 +1236,7 @@ class OutputPage extends ContextSource {
* @param array $newLinkArray Associative array mapping language code to the page
* name
*/
- public function addLanguageLinks( $newLinkArray ) {
+ public function addLanguageLinks( array $newLinkArray ) {
$this->mLanguageLinks += $newLinkArray;
}
@@ -1167,14 +1246,14 @@ class OutputPage extends ContextSource {
* @param array $newLinkArray Associative array mapping language code to the page
* name
*/
- public function setLanguageLinks( $newLinkArray ) {
+ public function setLanguageLinks( array $newLinkArray ) {
$this->mLanguageLinks = $newLinkArray;
}
/**
* Get the list of language links
*
- * @return Array of Interwiki Prefixed (non DB key) Titles (e.g. 'fr:Test page')
+ * @return array Array of Interwiki Prefixed (non DB key) Titles (e.g. 'fr:Test page')
*/
public function getLanguageLinks() {
return $this->mLanguageLinks;
@@ -1183,9 +1262,9 @@ class OutputPage extends ContextSource {
/**
* Add an array of categories, with names in the keys
*
- * @param array $categories mapping category name => sort key
+ * @param array $categories Mapping category name => sort key
*/
- public function addCategoryLinks( $categories ) {
+ public function addCategoryLinks( array $categories ) {
global $wgContLang;
if ( !is_array( $categories ) || count( $categories ) == 0 ) {
@@ -1199,22 +1278,29 @@ class OutputPage extends ContextSource {
# Fetch existence plus the hiddencat property
$dbr = wfGetDB( DB_SLAVE );
+ $fields = array( 'page_id', 'page_namespace', 'page_title', 'page_len',
+ 'page_is_redirect', 'page_latest', 'pp_value' );
+
+ if ( $this->getConfig()->get( 'ContentHandlerUseDB' ) ) {
+ $fields[] = 'page_content_model';
+ }
+
$res = $dbr->select( array( 'page', 'page_props' ),
- array( 'page_id', 'page_namespace', 'page_title', 'page_len', 'page_is_redirect', 'page_latest', 'pp_value' ),
+ $fields,
$lb->constructSet( 'page', $dbr ),
__METHOD__,
array(),
- array( 'page_props' => array( 'LEFT JOIN', array( 'pp_propname' => 'hiddencat', 'pp_page = page_id' ) ) )
+ array( 'page_props' => array( 'LEFT JOIN', array(
+ 'pp_propname' => 'hiddencat',
+ 'pp_page = page_id'
+ ) ) )
);
# Add the results to the link cache
$lb->addResultToCache( LinkCache::singleton(), $res );
- # Set all the values to 'normal'. This can be done with array_fill_keys in PHP 5.2.0+
- $categories = array_combine(
- array_keys( $categories ),
- array_fill( 0, count( $categories ), 'normal' )
- );
+ # Set all the values to 'normal'.
+ $categories = array_fill_keys( array_keys( $categories ), 'normal' );
# Mark hidden categories
foreach ( $res as $row ) {
@@ -1224,15 +1310,19 @@ class OutputPage extends ContextSource {
}
# Add the remaining categories to the skin
- if ( wfRunHooks( 'OutputPageMakeCategoryLinks', array( &$this, $categories, &$this->mCategoryLinks ) ) ) {
+ if ( wfRunHooks(
+ 'OutputPageMakeCategoryLinks',
+ array( &$this, $categories, &$this->mCategoryLinks ) )
+ ) {
foreach ( $categories as $category => $type ) {
$origcategory = $category;
$title = Title::makeTitleSafe( NS_CATEGORY, $category );
+ if ( !$title ) {
+ continue;
+ }
$wgContLang->findVariantLink( $category, $title, true );
- if ( $category != $origcategory ) {
- if ( array_key_exists( $category, $categories ) ) {
- continue;
- }
+ if ( $category != $origcategory && array_key_exists( $category, $categories ) ) {
+ continue;
}
$text = $wgContLang->convertHtml( $title->getText() );
$this->mCategories[] = $title->getText();
@@ -1244,9 +1334,9 @@ class OutputPage extends ContextSource {
/**
* Reset the category links (but not the category list) and add $categories
*
- * @param array $categories mapping category name => sort key
+ * @param array $categories Mapping category name => sort key
*/
- public function setCategoryLinks( $categories ) {
+ public function setCategoryLinks( array $categories ) {
$this->mCategoryLinks = array();
$this->addCategoryLinks( $categories );
}
@@ -1257,7 +1347,7 @@ class OutputPage extends ContextSource {
* hidden categories) and $link a HTML fragment with a link to the category
* page
*
- * @return Array
+ * @return array
*/
public function getCategoryLinks() {
return $this->mCategoryLinks;
@@ -1266,7 +1356,7 @@ class OutputPage extends ContextSource {
/**
* Get the list of category names this page belongs to
*
- * @return Array of strings
+ * @return array Array of strings
*/
public function getCategories() {
return $this->mCategories;
@@ -1281,7 +1371,6 @@ class OutputPage extends ContextSource {
* @todo this should be given a more accurate name
*/
public function disallowUserJs() {
- global $wgAllowSiteCSSOnRestrictedPages;
$this->reduceAllowedModules(
ResourceLoaderModule::TYPE_SCRIPTS,
ResourceLoaderModule::ORIGIN_CORE_INDIVIDUAL
@@ -1289,7 +1378,7 @@ class OutputPage extends ContextSource {
// Site-wide styles are controlled by a config setting, see bug 71621
// for background on why. User styles are never allowed.
- if ( $wgAllowSiteCSSOnRestrictedPages ) {
+ if ( $this->getConfig()->get( 'AllowSiteCSSOnRestrictedPages' ) ) {
$styleOrigin = ResourceLoaderModule::ORIGIN_USER_SITEWIDE;
} else {
$styleOrigin = ResourceLoaderModule::ORIGIN_CORE_INDIVIDUAL;
@@ -1301,19 +1390,7 @@ class OutputPage extends ContextSource {
}
/**
- * Return whether user JavaScript is allowed for this page
- * @deprecated since 1.18 Load modules with ResourceLoader, and origin and
- * trustworthiness is identified and enforced automagically.
- * @return Boolean
- */
- public function isUserJsAllowed() {
- wfDeprecated( __METHOD__, '1.18' );
- return $this->getAllowedModules( ResourceLoaderModule::TYPE_SCRIPTS ) >= ResourceLoaderModule::ORIGIN_USER_INDIVIDUAL;
- }
-
- /**
- * Get the level of JavaScript / CSS untrustworthiness allowed on this page.
- *
+ * Show what level of JavaScript / CSS untrustworthiness is allowed on this page
* @see ResourceLoaderModule::$origin
* @param string $type ResourceLoaderModule TYPE_ constant
* @return int ResourceLoaderModule ORIGIN_ class constant
@@ -1333,7 +1410,6 @@ class OutputPage extends ContextSource {
*
* @deprecated since 1.24 Raising level of allowed untrusted content is no longer supported.
* Use reduceAllowedModules() instead
- *
* @param string $type ResourceLoaderModule TYPE_ constant
* @param int $level ResourceLoaderModule class constant
*/
@@ -1378,11 +1454,11 @@ class OutputPage extends ContextSource {
*
* @since 1.19
*
- * @param $element string
- * @param $attribs array
- * @param $contents string
+ * @param string $element
+ * @param array $attribs
+ * @param string $contents
*/
- public function addElement( $element, $attribs = array(), $contents = '' ) {
+ public function addElement( $element, array $attribs = array(), $contents = '' ) {
$this->addHTML( Html::element( $element, $attribs, $contents ) );
}
@@ -1396,7 +1472,7 @@ class OutputPage extends ContextSource {
/**
* Get the body HTML
*
- * @return String: HTML
+ * @return string HTML
*/
public function getHTML() {
return $this->mBodytext;
@@ -1405,9 +1481,9 @@ class OutputPage extends ContextSource {
/**
* Get/set the ParserOptions object to use for wikitext parsing
*
- * @param $options ParserOptions|null either the ParserOption to use or null to only get the
- * current ParserOption object
- * @return ParserOptions object
+ * @param ParserOptions|null $options Either the ParserOption to use or null to only get the
+ * current ParserOption object
+ * @return ParserOptions
*/
public function parserOptions( $options = null ) {
if ( !$this->mParserOptions ) {
@@ -1421,8 +1497,8 @@ class OutputPage extends ContextSource {
* Set the revision ID which will be seen by the wiki text parser
* for things such as embedded {{REVISIONID}} variable use.
*
- * @param $revid Mixed: an positive integer, or null
- * @return Mixed: previous value
+ * @param int|null $revid An positive integer, or null
+ * @return mixed Previous value
*/
public function setRevisionId( $revid ) {
$val = is_null( $revid ) ? null : intval( $revid );
@@ -1432,7 +1508,7 @@ class OutputPage extends ContextSource {
/**
* Get the displayed revision ID
*
- * @return Integer
+ * @return int
*/
public function getRevisionId() {
return $this->mRevisionId;
@@ -1442,8 +1518,8 @@ class OutputPage extends ContextSource {
* Set the timestamp of the revision which will be displayed. This is used
* to avoid a extra DB call in Skin::lastModified().
*
- * @param $timestamp Mixed: string, or null
- * @return Mixed: previous value
+ * @param string|null $timestamp
+ * @return mixed Previous value
*/
public function setRevisionTimestamp( $timestamp ) {
return wfSetVar( $this->mRevisionTimestamp, $timestamp );
@@ -1453,7 +1529,7 @@ class OutputPage extends ContextSource {
* Get the timestamp of displayed revision.
* This will be null if not filled by setRevisionTimestamp().
*
- * @return String or null
+ * @return string|null
*/
public function getRevisionTimestamp() {
return $this->mRevisionTimestamp;
@@ -1462,8 +1538,8 @@ class OutputPage extends ContextSource {
/**
* Set the displayed file version
*
- * @param $file File|bool
- * @return Mixed: previous value
+ * @param File|bool $file
+ * @return mixed Previous value
*/
public function setFileVersion( $file ) {
$val = null;
@@ -1476,7 +1552,7 @@ class OutputPage extends ContextSource {
/**
* Get the displayed file version
*
- * @return Array|null ('time' => MW timestamp, 'sha1' => sha1)
+ * @return array|null ('time' => MW timestamp, 'sha1' => sha1)
*/
public function getFileVersion() {
return $this->mFileVersion;
@@ -1485,7 +1561,7 @@ class OutputPage extends ContextSource {
/**
* Get the templates used on this page
*
- * @return Array (namespace => dbKey => revId)
+ * @return array (namespace => dbKey => revId)
* @since 1.18
*/
public function getTemplateIds() {
@@ -1495,7 +1571,7 @@ class OutputPage extends ContextSource {
/**
* Get the files used on this page
*
- * @return Array (dbKey => array('time' => MW timestamp or null, 'sha1' => sha1 or ''))
+ * @return array (dbKey => array('time' => MW timestamp or null, 'sha1' => sha1 or ''))
* @since 1.18
*/
public function getFileSearchOptions() {
@@ -1506,9 +1582,9 @@ class OutputPage extends ContextSource {
* Convert wikitext to HTML and add it to the buffer
* Default assumes that the current page title will be used.
*
- * @param $text String
- * @param $linestart Boolean: is this the start of a line?
- * @param $interface Boolean: is this text in the user interface language?
+ * @param string $text
+ * @param bool $linestart Is this the start of a line?
+ * @param bool $interface Is this text in the user interface language?
*/
public function addWikiText( $text, $linestart = true, $interface = true ) {
$title = $this->getTitle(); // Work around E_STRICT
@@ -1521,9 +1597,9 @@ class OutputPage extends ContextSource {
/**
* Add wikitext with a custom Title object
*
- * @param string $text wikitext
- * @param $title Title object
- * @param $linestart Boolean: is this the start of a line?
+ * @param string $text Wikitext
+ * @param Title $title
+ * @param bool $linestart Is this the start of a line?
*/
public function addWikiTextWithTitle( $text, &$title, $linestart = true ) {
$this->addWikiTextTitle( $text, $title, $linestart );
@@ -1532,9 +1608,9 @@ class OutputPage extends ContextSource {
/**
* Add wikitext with a custom Title object and tidy enabled.
*
- * @param string $text wikitext
- * @param $title Title object
- * @param $linestart Boolean: is this the start of a line?
+ * @param string $text Wikitext
+ * @param Title $title
+ * @param bool $linestart Is this the start of a line?
*/
function addWikiTextTitleTidy( $text, &$title, $linestart = true ) {
$this->addWikiTextTitle( $text, $title, $linestart, true );
@@ -1543,8 +1619,8 @@ class OutputPage extends ContextSource {
/**
* Add wikitext with tidy enabled
*
- * @param string $text wikitext
- * @param $linestart Boolean: is this the start of a line?
+ * @param string $text Wikitext
+ * @param bool $linestart Is this the start of a line?
*/
public function addWikiTextTidy( $text, $linestart = true ) {
$title = $this->getTitle();
@@ -1554,14 +1630,16 @@ class OutputPage extends ContextSource {
/**
* Add wikitext with a custom Title object
*
- * @param string $text wikitext
- * @param $title Title object
- * @param $linestart Boolean: is this the start of a line?
- * @param $tidy Boolean: whether to use tidy
- * @param $interface Boolean: whether it is an interface message
- * (for example disables conversion)
+ * @param string $text Wikitext
+ * @param Title $title
+ * @param bool $linestart Is this the start of a line?
+ * @param bool $tidy Whether to use tidy
+ * @param bool $interface Whether it is an interface message
+ * (for example disables conversion)
*/
- public function addWikiTextTitle( $text, Title $title, $linestart, $tidy = false, $interface = false ) {
+ public function addWikiTextTitle( $text, Title $title, $linestart,
+ $tidy = false, $interface = false
+ ) {
global $wgParser;
wfProfileIn( __METHOD__ );
@@ -1570,7 +1648,7 @@ class OutputPage extends ContextSource {
$oldTidy = $popts->setTidy( $tidy );
$popts->setInterfaceMessage( (bool)$interface );
- $parserOutput = $wgParser->parse(
+ $parserOutput = $wgParser->getFreshParser()->parse(
$text, $title, $popts,
$linestart, true, $this->mRevisionId
);
@@ -1583,11 +1661,24 @@ class OutputPage extends ContextSource {
}
/**
- * Add a ParserOutput object, but without Html
+ * Add a ParserOutput object, but without Html.
+ *
+ * @deprecated since 1.24, use addParserOutputMetadata() instead.
+ * @param ParserOutput $parserOutput
+ */
+ public function addParserOutputNoText( $parserOutput ) {
+ $this->addParserOutputMetadata( $parserOutput );
+ }
+
+ /**
+ * Add all metadata associated with a ParserOutput object, but without the actual HTML. This
+ * includes categories, language links, ResourceLoader modules, effects of certain magic words,
+ * and so on.
*
- * @param $parserOutput ParserOutput object
+ * @since 1.24
+ * @param ParserOutput $parserOutput
*/
- public function addParserOutputNoText( &$parserOutput ) {
+ public function addParserOutputMetadata( $parserOutput ) {
$this->mLanguageLinks += $parserOutput->getLanguageLinks();
$this->addCategoryLinks( $parserOutput->getCategories() );
$this->mNewSectionLink = $parserOutput->getNewSection();
@@ -1603,6 +1694,7 @@ class OutputPage extends ContextSource {
$this->addModuleScripts( $parserOutput->getModuleScripts() );
$this->addModuleStyles( $parserOutput->getModuleStyles() );
$this->addModuleMessages( $parserOutput->getModuleMessages() );
+ $this->addJsConfigVars( $parserOutput->getJsConfigVars() );
$this->mPreventClickjacking = $this->mPreventClickjacking
|| $parserOutput->preventClickjacking();
@@ -1620,11 +1712,11 @@ class OutputPage extends ContextSource {
}
// Hooks registered in the object
- global $wgParserOutputHooks;
+ $parserOutputHooks = $this->getConfig()->get( 'ParserOutputHooks' );
foreach ( $parserOutput->getOutputHooks() as $hookInfo ) {
list( $hookName, $data ) = $hookInfo;
- if ( isset( $wgParserOutputHooks[$hookName] ) ) {
- call_user_func( $wgParserOutputHooks[$hookName], $this, $parserOutput, $data );
+ if ( isset( $parserOutputHooks[$hookName] ) ) {
+ call_user_func( $parserOutputHooks[$hookName], $this, $parserOutput, $data );
}
}
@@ -1636,43 +1728,72 @@ class OutputPage extends ContextSource {
}
/**
- * Add a ParserOutput object
+ * Add the HTML and enhancements for it (like ResourceLoader modules) associated with a
+ * ParserOutput object, without any other metadata.
*
- * @param $parserOutput ParserOutput
+ * @since 1.24
+ * @param ParserOutput $parserOutput
*/
- function addParserOutput( &$parserOutput ) {
- $this->addParserOutputNoText( $parserOutput );
- $parserOutput->setTOCEnabled( $this->mEnableTOC );
+ public function addParserOutputContent( $parserOutput ) {
+ $this->addParserOutputText( $parserOutput );
+
+ $this->addModules( $parserOutput->getModules() );
+ $this->addModuleScripts( $parserOutput->getModuleScripts() );
+ $this->addModuleStyles( $parserOutput->getModuleStyles() );
+ $this->addModuleMessages( $parserOutput->getModuleMessages() );
+
+ $this->addJsConfigVars( $parserOutput->getJsConfigVars() );
+ }
+
+ /**
+ * Add the HTML associated with a ParserOutput object, without any metadata.
+ *
+ * @since 1.24
+ * @param ParserOutput $parserOutput
+ */
+ public function addParserOutputText( $parserOutput ) {
$text = $parserOutput->getText();
wfRunHooks( 'OutputPageBeforeHTML', array( &$this, &$text ) );
$this->addHTML( $text );
}
/**
+ * Add everything from a ParserOutput object.
+ *
+ * @param ParserOutput $parserOutput
+ */
+ function addParserOutput( $parserOutput ) {
+ $this->addParserOutputMetadata( $parserOutput );
+ $parserOutput->setTOCEnabled( $this->mEnableTOC );
+
+ // Touch section edit links only if not previously disabled
+ if ( $parserOutput->getEditSectionTokens() ) {
+ $parserOutput->setEditSectionTokens( $this->mEnableSectionEditLinks );
+ }
+
+ $this->addParserOutputText( $parserOutput );
+ }
+
+ /**
* Add the output of a QuickTemplate to the output buffer
*
- * @param $template QuickTemplate
+ * @param QuickTemplate $template
*/
public function addTemplate( &$template ) {
- ob_start();
- $template->execute();
- $this->addHTML( ob_get_contents() );
- ob_end_clean();
+ $this->addHTML( $template->getHTML() );
}
/**
* Parse wikitext and return the HTML.
*
- * @param $text String
- * @param $linestart Boolean: is this the start of a line?
- * @param $interface Boolean: use interface language ($wgLang instead of
- * $wgContLang) while parsing language sensitive magic
- * words like GRAMMAR and PLURAL. This also disables
- * LanguageConverter.
- * @param $language Language object: target language object, will override
- * $interface
+ * @param string $text
+ * @param bool $linestart Is this the start of a line?
+ * @param bool $interface Use interface language ($wgLang instead of
+ * $wgContLang) while parsing language sensitive magic words like GRAMMAR and PLURAL.
+ * This also disables LanguageConverter.
+ * @param Language $language Target language object, will override $interface
* @throws MWException
- * @return String: HTML
+ * @return string HTML
*/
public function parse( $text, $linestart = true, $interface = false, $language = null ) {
global $wgParser;
@@ -1689,7 +1810,7 @@ class OutputPage extends ContextSource {
$oldLang = $popts->setTargetLanguage( $language );
}
- $parserOutput = $wgParser->parse(
+ $parserOutput = $wgParser->getFreshParser()->parse(
$text, $this->getTitle(), $popts,
$linestart, true, $this->mRevisionId
);
@@ -1707,28 +1828,22 @@ class OutputPage extends ContextSource {
/**
* Parse wikitext, strip paragraphs, and return the HTML.
*
- * @param $text String
- * @param $linestart Boolean: is this the start of a line?
- * @param $interface Boolean: use interface language ($wgLang instead of
- * $wgContLang) while parsing language sensitive magic
- * words like GRAMMAR and PLURAL
- * @return String: HTML
+ * @param string $text
+ * @param bool $linestart Is this the start of a line?
+ * @param bool $interface Use interface language ($wgLang instead of
+ * $wgContLang) while parsing language sensitive magic
+ * words like GRAMMAR and PLURAL
+ * @return string HTML
*/
public function parseInline( $text, $linestart = true, $interface = false ) {
$parsed = $this->parse( $text, $linestart, $interface );
-
- $m = array();
- if ( preg_match( '/^<p>(.*)\n?<\/p>\n?/sU', $parsed, $m ) ) {
- $parsed = $m[1];
- }
-
- return $parsed;
+ return Parser::stripOuterParagraph( $parsed );
}
/**
* Set the value of the "s-maxage" part of the "Cache-control" HTTP header
*
- * @param $maxage Integer: maximum cache time on the Squid, in seconds.
+ * @param int $maxage Maximum cache time on the Squid, in seconds.
*/
public function setSquidMaxage( $maxage ) {
$this->mSquidMaxage = $maxage;
@@ -1737,7 +1852,7 @@ class OutputPage extends ContextSource {
/**
* Use enableClientCache(false) to force it to send nocache headers
*
- * @param $state bool
+ * @param bool $state
*
* @return bool
*/
@@ -1748,20 +1863,20 @@ class OutputPage extends ContextSource {
/**
* Get the list of cookies that will influence on the cache
*
- * @return Array
+ * @return array
*/
function getCacheVaryCookies() {
- global $wgCookiePrefix, $wgCacheVaryCookies;
static $cookies;
if ( $cookies === null ) {
+ $config = $this->getConfig();
$cookies = array_merge(
array(
- "{$wgCookiePrefix}Token",
- "{$wgCookiePrefix}LoggedOut",
+ $config->get( 'CookiePrefix' ) . 'Token',
+ $config->get( 'CookiePrefix' ) . 'LoggedOut',
"forceHTTPS",
session_name()
),
- $wgCacheVaryCookies
+ $config->get( 'CacheVaryCookies' )
);
wfRunHooks( 'GetCacheVaryCookies', array( $this, &$cookies ) );
}
@@ -1772,7 +1887,7 @@ class OutputPage extends ContextSource {
* Check if the request has a cache-varying cookie header
* If it does, it's very important that we don't allow public caching
*
- * @return Boolean
+ * @return bool
*/
function haveCacheVaryCookies() {
$cookieHeader = $this->getRequest()->getHeader( 'cookie' );
@@ -1794,8 +1909,8 @@ class OutputPage extends ContextSource {
/**
* Add an HTTP header that will influence on the cache
*
- * @param string $header header name
- * @param $option Array|null
+ * @param string $header Header name
+ * @param array|null $option
* @todo FIXME: Document the $option parameter; it appears to be for
* X-Vary-Options but what format is acceptable?
*/
@@ -1816,7 +1931,7 @@ class OutputPage extends ContextSource {
* Return a Vary: header on which to vary caches. Based on the keys of $mVaryHeader,
* such as Accept-Encoding or Cookie
*
- * @return String
+ * @return string
*/
public function getVaryHeader() {
return 'Vary: ' . join( ', ', array_keys( $this->mVaryHeader ) );
@@ -1825,7 +1940,7 @@ class OutputPage extends ContextSource {
/**
* Get a complete X-Vary-Options header
*
- * @return String
+ * @return string
*/
public function getXVO() {
$cvCookies = $this->getCacheVaryCookies();
@@ -1858,7 +1973,12 @@ class OutputPage extends ContextSource {
* /w/index.php?title=Main_page&variant=zh-cn should never be served.
*/
function addAcceptLanguage() {
- $lang = $this->getTitle()->getPageLanguage();
+ $title = $this->getTitle();
+ if ( !$title instanceof Title ) {
+ return;
+ }
+
+ $lang = $title->getPageLanguage();
if ( !$this->getRequest()->getCheck( 'variant' ) && $lang->hasVariants() ) {
$variants = $lang->getVariants();
$aloption = array();
@@ -1889,7 +2009,7 @@ class OutputPage extends ContextSource {
* This is the default for special pages. If you display a CSRF-protected
* form on an ordinary view page, then you need to call this function.
*
- * @param $enable bool
+ * @param bool $enable
*/
public function preventClickjacking( $enable = true ) {
$this->mPreventClickjacking = $enable;
@@ -1908,7 +2028,7 @@ class OutputPage extends ContextSource {
* Get the prevent-clickjacking flag
*
* @since 1.24
- * @return boolean
+ * @return bool
*/
public function getPreventClickjacking() {
return $this->mPreventClickjacking;
@@ -1922,11 +2042,11 @@ class OutputPage extends ContextSource {
* @return string
*/
public function getFrameOptions() {
- global $wgBreakFrames, $wgEditPageFrameOptions;
- if ( $wgBreakFrames ) {
+ $config = $this->getConfig();
+ if ( $config->get( 'BreakFrames' ) ) {
return 'DENY';
- } elseif ( $this->mPreventClickjacking && $wgEditPageFrameOptions ) {
- return $wgEditPageFrameOptions;
+ } elseif ( $this->mPreventClickjacking && $config->get( 'EditPageFrameOptions' ) ) {
+ return $config->get( 'EditPageFrameOptions' );
}
return false;
}
@@ -1935,10 +2055,9 @@ class OutputPage extends ContextSource {
* Send cache control HTTP headers
*/
public function sendCacheControl() {
- global $wgUseSquid, $wgUseESI, $wgUseETag, $wgSquidMaxage, $wgUseXVO;
-
$response = $this->getRequest()->response();
- if ( $wgUseETag && $this->mETag ) {
+ $config = $this->getConfig();
+ if ( $config->get( 'UseETag' ) && $this->mETag ) {
$response->header( "ETag: $this->mETag" );
}
@@ -1949,39 +2068,41 @@ class OutputPage extends ContextSource {
# maintain different caches for logged-in users and non-logged in ones
$response->header( $this->getVaryHeader() );
- if ( $wgUseXVO ) {
+ if ( $config->get( 'UseXVO' ) ) {
# Add an X-Vary-Options header for Squid with Wikimedia patches
$response->header( $this->getXVO() );
}
if ( $this->mEnableClientCache ) {
if (
- $wgUseSquid && session_id() == '' && !$this->isPrintable() &&
+ $config->get( 'UseSquid' ) && session_id() == '' && !$this->isPrintable() &&
$this->mSquidMaxage != 0 && !$this->haveCacheVaryCookies()
) {
- if ( $wgUseESI ) {
+ if ( $config->get( 'UseESI' ) ) {
# We'll purge the proxy cache explicitly, but require end user agents
# to revalidate against the proxy on each visit.
# Surrogate-Control controls our Squid, Cache-Control downstream caches
- wfDebug( __METHOD__ . ": proxy caching with ESI; {$this->mLastModified} **\n", false );
+ wfDebug( __METHOD__ . ": proxy caching with ESI; {$this->mLastModified} **\n", 'log' );
# start with a shorter timeout for initial testing
# header( 'Surrogate-Control: max-age=2678400+2678400, content="ESI/1.0"');
- $response->header( 'Surrogate-Control: max-age=' . $wgSquidMaxage . '+' . $this->mSquidMaxage . ', content="ESI/1.0"' );
+ $response->header( 'Surrogate-Control: max-age=' . $config->get( 'SquidMaxage' )
+ . '+' . $this->mSquidMaxage . ', content="ESI/1.0"' );
$response->header( 'Cache-Control: s-maxage=0, must-revalidate, max-age=0' );
} else {
# We'll purge the proxy cache for anons explicitly, but require end user agents
# to revalidate against the proxy on each visit.
# IMPORTANT! The Squid needs to replace the Cache-Control header with
# Cache-Control: s-maxage=0, must-revalidate, max-age=0
- wfDebug( __METHOD__ . ": local proxy caching; {$this->mLastModified} **\n", false );
+ wfDebug( __METHOD__ . ": local proxy caching; {$this->mLastModified} **\n", 'log' );
# start with a shorter timeout for initial testing
# header( "Cache-Control: s-maxage=2678400, must-revalidate, max-age=0" );
- $response->header( 'Cache-Control: s-maxage=' . $this->mSquidMaxage . ', must-revalidate, max-age=0' );
+ $response->header( 'Cache-Control: s-maxage=' . $this->mSquidMaxage
+ . ', must-revalidate, max-age=0' );
}
} else {
# We do want clients to cache if they can, but they *must* check for updates
# on revisiting the page.
- wfDebug( __METHOD__ . ": private caching; {$this->mLastModified} **\n", false );
+ wfDebug( __METHOD__ . ": private caching; {$this->mLastModified} **\n", 'log' );
$response->header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', 0 ) . ' GMT' );
$response->header( "Cache-Control: private, must-revalidate, max-age=0" );
}
@@ -1989,7 +2110,7 @@ class OutputPage extends ContextSource {
$response->header( "Last-Modified: {$this->mLastModified}" );
}
} else {
- wfDebug( __METHOD__ . ": no caching **\n", false );
+ wfDebug( __METHOD__ . ": no caching **\n", 'log' );
# In general, the absence of a last modified header should be enough to prevent
# the client from using its cache. We send a few other things just to make sure.
@@ -2000,26 +2121,11 @@ class OutputPage extends ContextSource {
}
/**
- * Get the message associated with the HTTP response code $code
- *
- * @param $code Integer: status code
- * @return String or null: message or null if $code is not in the list of
- * messages
- *
- * @deprecated since 1.18 Use HttpStatus::getMessage() instead.
- */
- public static function getStatusMessage( $code ) {
- wfDeprecated( __METHOD__, '1.18' );
- return HttpStatus::getMessage( $code );
- }
-
- /**
* Finally, all the text has been munged and accumulated into
* the object, let's actually output it:
*/
public function output() {
- global $wgLanguageCode, $wgDebugRedirects, $wgMimeType, $wgVaryOnXFP,
- $wgUseAjax, $wgResponsiveImages;
+ global $wgLanguageCode;
if ( $this->mDoNothing ) {
return;
@@ -2028,6 +2134,7 @@ class OutputPage extends ContextSource {
wfProfileIn( __METHOD__ );
$response = $this->getRequest()->response();
+ $config = $this->getConfig();
if ( $this->mRedirect != '' ) {
# Standards require redirect URLs to be absolute
@@ -2038,19 +2145,19 @@ class OutputPage extends ContextSource {
if ( wfRunHooks( "BeforePageRedirect", array( $this, &$redirect, &$code ) ) ) {
if ( $code == '301' || $code == '303' ) {
- if ( !$wgDebugRedirects ) {
+ if ( !$config->get( 'DebugRedirects' ) ) {
$message = HttpStatus::getMessage( $code );
$response->header( "HTTP/1.1 $code $message" );
}
$this->mLastModified = wfTimestamp( TS_RFC2822 );
}
- if ( $wgVaryOnXFP ) {
+ if ( $config->get( 'VaryOnXFP' ) ) {
$this->addVaryHeader( 'X-Forwarded-Proto' );
}
$this->sendCacheControl();
$response->header( "Content-Type: text/html; charset=utf-8" );
- if ( $wgDebugRedirects ) {
+ if ( $config->get( 'DebugRedirects' ) ) {
$url = htmlspecialchars( $redirect );
print "<html>\n<head>\n<title>Redirect</title>\n</head>\n<body>\n";
print "<p>Location: <a href=\"$url\">$url</a></p>\n";
@@ -2072,9 +2179,13 @@ class OutputPage extends ContextSource {
# Buffer output; final headers may depend on later processing
ob_start();
- $response->header( "Content-type: $wgMimeType; charset=UTF-8" );
+ $response->header( 'Content-type: ' . $config->get( 'MimeType' ) . '; charset=UTF-8' );
$response->header( 'Content-language: ' . $wgLanguageCode );
+ // Avoid Internet Explorer "compatibility view" in IE 8-10, so that
+ // jQuery etc. can work correctly.
+ $response->header( 'X-UA-Compatible: IE=Edge' );
+
// Prevent framing, if requested
$frameOptions = $this->getFrameOptions();
if ( $frameOptions ) {
@@ -2097,7 +2208,7 @@ class OutputPage extends ContextSource {
);
// Support for high-density display images if enabled
- if ( $wgResponsiveImages ) {
+ if ( $config->get( 'ResponsiveImages' ) ) {
$coreModules[] = 'mediawiki.hidpi';
}
@@ -2106,10 +2217,6 @@ class OutputPage extends ContextSource {
$this->addModules( $group );
}
MWDebug::addModules( $this );
- if ( $wgUseAjax ) {
- // FIXME: deprecate? - not clear why this is useful
- wfRunHooks( 'AjaxAddScript', array( &$this ) );
- }
// Hook that allows last minute changes to the output page, e.g.
// adding of CSS or Javascript by extensions.
@@ -2133,7 +2240,7 @@ class OutputPage extends ContextSource {
/**
* Actually output something with print.
*
- * @param string $ins the string to output
+ * @param string $ins The string to output
* @deprecated since 1.22 Use echo yourself.
*/
public function out( $ins ) {
@@ -2154,8 +2261,8 @@ class OutputPage extends ContextSource {
* indexing, clear the current text and redirect, set the page's title
* and optionally an custom HTML title (content of the "<title>" tag).
*
- * @param string|Message $pageTitle will be passed directly to setPageTitle()
- * @param string|Message $htmlTitle will be passed directly to setHTMLTitle();
+ * @param string|Message $pageTitle Will be passed directly to setPageTitle()
+ * @param string|Message $htmlTitle Will be passed directly to setHTMLTitle();
* optional, if not passed the "<title>" attribute will be
* based on $pageTitle
*/
@@ -2175,13 +2282,14 @@ class OutputPage extends ContextSource {
/**
* Output a standard error page
*
+ * showErrorPage( 'titlemsg', 'pagetextmsg' );
* showErrorPage( 'titlemsg', 'pagetextmsg', array( 'param1', 'param2' ) );
* showErrorPage( 'titlemsg', $messageObject );
- * showErrorPage( $titleMessageObj, $messageObject );
+ * showErrorPage( $titleMessageObject, $messageObject );
*
- * @param $title Mixed: message key (string) for page title, or a Message object
- * @param $msg Mixed: message key (string) for page text, or a Message object
- * @param array $params message parameters; ignored if $msg is a Message object
+ * @param string|Message $title Message key (string) for page title, or a Message object
+ * @param string|Message $msg Message key (string) for page text, or a Message object
+ * @param array $params Message parameters; ignored if $msg is a Message object
*/
public function showErrorPage( $title, $msg, $params = array() ) {
if ( !$title instanceof Message ) {
@@ -2191,6 +2299,11 @@ class OutputPage extends ContextSource {
$this->prepareErrorPage( $title );
if ( $msg instanceof Message ) {
+ if ( $params !== array() ) {
+ trigger_error( 'Argument ignored: $params. The message parameters argument '
+ . 'is discarded when the $msg argument is a Message object instead of '
+ . 'a string.', E_USER_NOTICE );
+ }
$this->addHTML( $msg->parseAsBlock() );
} else {
$this->addWikiMsgArray( $msg, $params );
@@ -2202,10 +2315,10 @@ class OutputPage extends ContextSource {
/**
* Output a standard permission error page
*
- * @param array $errors error message keys
- * @param string $action action that was denied or null if unknown
+ * @param array $errors Error message keys
+ * @param string $action Action that was denied or null if unknown
*/
- public function showPermissionsErrorPage( $errors, $action = null ) {
+ public function showPermissionsErrorPage( array $errors, $action = null ) {
// For some action (read, edit, create and upload), display a "login to do this action"
// error if all of the following conditions are met:
// 1. the user is not logged in
@@ -2275,7 +2388,7 @@ class OutputPage extends ContextSource {
* Display an error page indicating that a given version of MediaWiki is
* required to use it
*
- * @param $version Mixed: the version of MediaWiki needed to use the page
+ * @param mixed $version The version of MediaWiki needed to use the page
*/
public function versionRequired( $version ) {
$this->prepareErrorPage( $this->msg( 'versionrequired', $version ) );
@@ -2287,7 +2400,7 @@ class OutputPage extends ContextSource {
/**
* Display an error page noting that a given permission bit is required.
* @deprecated since 1.18, just throw the exception directly
- * @param string $permission key required
+ * @param string $permission Key required
* @throws PermissionsError
*/
public function permissionRequired( $permission ) {
@@ -2297,7 +2410,7 @@ class OutputPage extends ContextSource {
/**
* Produce the stock "please login to use the wiki" page
*
- * @deprecated in 1.19; throw the exception directly
+ * @deprecated since 1.19; throw the exception directly
*/
public function loginToUse() {
throw new PermissionsError( 'read' );
@@ -2306,11 +2419,11 @@ class OutputPage extends ContextSource {
/**
* Format a list of error messages
*
- * @param array $errors of arrays returned by Title::getUserPermissionsErrors
- * @param string $action action that was denied or null if unknown
- * @return String: the wikitext error-messages, formatted into a list.
+ * @param array $errors Array of arrays returned by Title::getUserPermissionsErrors
+ * @param string $action Action that was denied or null if unknown
+ * @return string The wikitext error-messages, formatted into a list.
*/
- public function formatPermissionsErrorMessage( $errors, $action = null ) {
+ public function formatPermissionsErrorMessage( array $errors, $action = null ) {
if ( $action == null ) {
$text = $this->msg( 'permissionserrorstext', count( $errors ) )->plain() . "\n\n";
} else {
@@ -2355,13 +2468,16 @@ class OutputPage extends ContextSource {
*
* @todo Needs to be split into multiple functions.
*
- * @param $source String: source code to show (or null).
- * @param $protected Boolean: is this a permissions error?
- * @param $reasons Array: list of reasons for this error, as returned by Title::getUserPermissionsErrors().
- * @param $action String: action that was denied or null if unknown
+ * @param string $source Source code to show (or null).
+ * @param bool $protected Is this a permissions error?
+ * @param array $reasons List of reasons for this error, as returned by
+ * Title::getUserPermissionsErrors().
+ * @param string $action Action that was denied or null if unknown
* @throws ReadOnlyError
*/
- public function readOnlyPage( $source = null, $protected = false, $reasons = array(), $action = null ) {
+ public function readOnlyPage( $source = null, $protected = false,
+ array $reasons = array(), $action = null
+ ) {
$this->setRobotPolicy( 'noindex,nofollow' );
$this->setArticleRelated( false );
@@ -2432,12 +2548,12 @@ $templates
* then the warning is a bit more obvious. If the lag is
* lower than $wgSlaveLagWarning, then no warning is shown.
*
- * @param $lag Integer: slave lag
+ * @param int $lag Slave lag
*/
public function showLagWarning( $lag ) {
- global $wgSlaveLagWarning, $wgSlaveLagCritical;
- if ( $lag >= $wgSlaveLagWarning ) {
- $message = $lag < $wgSlaveLagCritical
+ $config = $this->getConfig();
+ if ( $lag >= $config->get( 'SlaveLagWarning' ) ) {
+ $message = $lag < $config->get( 'SlaveLagCritical' )
? 'lag-warn-normal'
: 'lag-warn-high';
$wrap = Html::rawElement( 'div', array( 'class' => "mw-{$message}" ), "\n$1\n" );
@@ -2474,12 +2590,12 @@ $templates
/**
* Add a "return to" link pointing to a specified title
*
- * @param $title Title to link
- * @param array $query query string parameters
- * @param string $text text of the link (input is not escaped)
- * @param $options Options array to pass to Linker
+ * @param Title $title Title to link
+ * @param array $query Query string parameters
+ * @param string $text Text of the link (input is not escaped)
+ * @param array $options Options array to pass to Linker
*/
- public function addReturnTo( $title, $query = array(), $text = null, $options = array() ) {
+ public function addReturnTo( $title, array $query = array(), $text = null, $options = array() ) {
$link = $this->msg( 'returnto' )->rawParams(
Linker::link( $title, $text, array(), $query, $options ) )->escaped();
$this->addHTML( "<p id=\"mw-returnto\">{$link}</p>\n" );
@@ -2489,9 +2605,9 @@ $templates
* Add a "return to" link pointing to a specified title,
* or the title indicated in the request, or else the main page
*
- * @param $unused
- * @param $returnto Title or String to return to
- * @param string $returntoquery query string for the return to link
+ * @param mixed $unused
+ * @param Title|string $returnto Title or String to return to
+ * @param string $returntoquery Query string for the return to link
*/
public function returnToMain( $unused = null, $returnto = null, $returntoquery = null ) {
if ( $returnto == null ) {
@@ -2519,20 +2635,20 @@ $templates
}
/**
- * @param $sk Skin The given Skin
- * @param $includeStyle Boolean: unused
- * @return String: The doctype, opening "<html>", and head element.
+ * @param Skin $sk The given Skin
+ * @param bool $includeStyle Unused
+ * @return string The doctype, opening "<html>", and head element.
*/
public function headElement( Skin $sk, $includeStyle = true ) {
- global $wgContLang, $wgMimeType;
+ global $wgContLang;
$userdir = $this->getLanguage()->getDir();
$sitedir = $wgContLang->getDir();
- $ret = Html::htmlHeader( array( 'lang' => $this->getLanguage()->getHtmlCode(), 'dir' => $userdir, 'class' => 'client-nojs' ) );
+ $ret = Html::htmlHeader( $sk->getHtmlElementAttributes() );
if ( $this->getHTMLTitle() == '' ) {
- $this->setHTMLTitle( $this->msg( 'pagetitle', $this->getPageTitle() ) );
+ $this->setHTMLTitle( $this->msg( 'pagetitle', $this->getPageTitle() )->inContentLanguage() );
}
$openHead = Html::openElement( 'head' );
@@ -2541,7 +2657,7 @@ $templates
$ret .= "$openHead\n";
}
- if ( !Html::isXmlMimeType( $wgMimeType ) ) {
+ if ( !Html::isXmlMimeType( $this->getConfig()->get( 'MimeType' ) ) ) {
// Add <meta charset="UTF-8">
// This should be before <title> since it defines the charset used by
// text including the text inside <title>.
@@ -2550,17 +2666,23 @@ $templates
// Our XML declaration is output by Html::htmlHeader.
// http://www.whatwg.org/html/semantics.html#attr-meta-http-equiv-content-type
// http://www.whatwg.org/html/semantics.html#charset
- $ret .= Html::element( 'meta', array( 'charset' => 'UTF-8' ) );
+ $ret .= Html::element( 'meta', array( 'charset' => 'UTF-8' ) ) . "\n";
}
$ret .= Html::element( 'title', null, $this->getHTMLTitle() ) . "\n";
- $ret .= implode( "\n", array(
- $this->getHeadLinks(),
- $this->buildCssLinks(),
- $this->getHeadScripts(),
- $this->getHeadItems()
- ) );
+ foreach ( $this->getHeadLinksArray() as $item ) {
+ $ret .= $item . "\n";
+ }
+
+ // No newline after buildCssLinks since makeResourceLoaderLink did that already
+ $ret .= $this->buildCssLinks();
+
+ $ret .= $this->getHeadScripts() . "\n";
+
+ foreach ( $this->mHeadItems as $item ) {
+ $ret .= $item . "\n";
+ }
$closeHead = Html::closeElement( 'head' );
if ( $closeHead ) {
@@ -2581,7 +2703,8 @@ $templates
$bodyClasses[] = $sk->getPageClasses( $this->getTitle() );
$bodyClasses[] = 'skin-' . Sanitizer::escapeClass( $sk->getSkinName() );
- $bodyClasses[] = 'action-' . Sanitizer::escapeClass( Action::getActionName( $this->getContext() ) );
+ $bodyClasses[] =
+ 'action-' . Sanitizer::escapeClass( Action::getActionName( $this->getContext() ) );
$bodyAttrs = array();
// While the implode() is not strictly needed, it's used for backwards compatibility
@@ -2604,27 +2727,34 @@ $templates
*/
public function getResourceLoader() {
if ( is_null( $this->mResourceLoader ) ) {
- $this->mResourceLoader = new ResourceLoader();
+ $this->mResourceLoader = new ResourceLoader( $this->getConfig() );
}
return $this->mResourceLoader;
}
/**
- * TODO: Document
- * @param $modules Array/string with the module name(s)
+ * @todo Document
+ * @param array|string $modules One or more module names
* @param string $only ResourceLoaderModule TYPE_ class constant
- * @param $useESI boolean
- * @param array $extraQuery with extra query parameters to add to each request. array( param => value )
- * @param $loadCall boolean If true, output an (asynchronous) mw.loader.load() call rather than a "<script src='...'>" tag
- * @return string html "<script>" and "<style>" tags
- */
- protected function makeResourceLoaderLink( $modules, $only, $useESI = false, array $extraQuery = array(), $loadCall = false ) {
- global $wgResourceLoaderUseESI;
-
+ * @param bool $useESI
+ * @param array $extraQuery Array with extra query parameters to add to each
+ * request. array( param => value ).
+ * @param bool $loadCall If true, output an (asynchronous) mw.loader.load()
+ * call rather than a "<script src='...'>" tag.
+ * @return string The html "<script>", "<link>" and "<style>" tags
+ */
+ protected function makeResourceLoaderLink( $modules, $only, $useESI = false,
+ array $extraQuery = array(), $loadCall = false
+ ) {
$modules = (array)$modules;
+ $links = array(
+ 'html' => '',
+ 'states' => array(),
+ );
+
if ( !count( $modules ) ) {
- return '';
+ return $links;
}
if ( count( $modules ) > 1 ) {
@@ -2635,20 +2765,23 @@ $templates
if ( ResourceLoader::inDebugMode() ) {
// Recursively call us for every item
- $links = '';
foreach ( $modules as $name ) {
- $links .= $this->makeResourceLoaderLink( $name, $only, $useESI );
+ $link = $this->makeResourceLoaderLink( $name, $only, $useESI );
+ $links['html'] .= $link['html'];
+ $links['states'] += $link['states'];
}
return $links;
}
}
+
if ( !is_null( $this->mTarget ) ) {
$extraQuery['target'] = $this->mTarget;
}
- // Create keyed-by-group list of module objects from modules list
- $groups = array();
+ // Create keyed-by-source and then keyed-by-group list of module objects from modules list
+ $sortedModules = array();
$resourceLoader = $this->getResourceLoader();
+ $resourceLoaderUseESI = $this->getConfig()->get( 'ResourceLoaderUseESI' );
foreach ( $modules as $name ) {
$module = $resourceLoader->getModule( $name );
# Check that we're allowed to include this module on this page
@@ -2657,156 +2790,196 @@ $templates
&& $only == ResourceLoaderModule::TYPE_SCRIPTS )
|| ( $module->getOrigin() > $this->getAllowedModules( ResourceLoaderModule::TYPE_STYLES )
&& $only == ResourceLoaderModule::TYPE_STYLES )
+ || ( $module->getOrigin() > $this->getAllowedModules( ResourceLoaderModule::TYPE_COMBINED )
+ && $only == ResourceLoaderModule::TYPE_COMBINED )
|| ( $this->mTarget && !in_array( $this->mTarget, $module->getTargets() ) )
) {
continue;
}
- $group = $module->getGroup();
- if ( !isset( $groups[$group] ) ) {
- $groups[$group] = array();
- }
- $groups[$group][$name] = $module;
+ $sortedModules[$module->getSource()][$module->getGroup()][$name] = $module;
}
- $links = '';
- foreach ( $groups as $group => $grpModules ) {
- // Special handling for user-specific groups
- $user = null;
- if ( ( $group === 'user' || $group === 'private' ) && $this->getUser()->isLoggedIn() ) {
- $user = $this->getUser()->getName();
- }
+ foreach ( $sortedModules as $source => $groups ) {
+ foreach ( $groups as $group => $grpModules ) {
+ // Special handling for user-specific groups
+ $user = null;
+ if ( ( $group === 'user' || $group === 'private' ) && $this->getUser()->isLoggedIn() ) {
+ $user = $this->getUser()->getName();
+ }
- // Create a fake request based on the one we are about to make so modules return
- // correct timestamp and emptiness data
- $query = ResourceLoader::makeLoaderQuery(
- array(), // modules; not determined yet
- $this->getLanguage()->getCode(),
- $this->getSkin()->getSkinName(),
- $user,
- null, // version; not determined yet
- ResourceLoader::inDebugMode(),
- $only === ResourceLoaderModule::TYPE_COMBINED ? null : $only,
- $this->isPrintable(),
- $this->getRequest()->getBool( 'handheld' ),
- $extraQuery
- );
- $context = new ResourceLoaderContext( $resourceLoader, new FauxRequest( $query ) );
- // Extract modules that know they're empty
- $emptyModules = array();
- foreach ( $grpModules as $key => $module ) {
- if ( $module->isKnownEmpty( $context ) ) {
- $emptyModules[$key] = 'ready';
- unset( $grpModules[$key] );
+ // Create a fake request based on the one we are about to make so modules return
+ // correct timestamp and emptiness data
+ $query = ResourceLoader::makeLoaderQuery(
+ array(), // modules; not determined yet
+ $this->getLanguage()->getCode(),
+ $this->getSkin()->getSkinName(),
+ $user,
+ null, // version; not determined yet
+ ResourceLoader::inDebugMode(),
+ $only === ResourceLoaderModule::TYPE_COMBINED ? null : $only,
+ $this->isPrintable(),
+ $this->getRequest()->getBool( 'handheld' ),
+ $extraQuery
+ );
+ $context = new ResourceLoaderContext( $resourceLoader, new FauxRequest( $query ) );
+
+
+ // Extract modules that know they're empty and see if we have one or more
+ // raw modules
+ $isRaw = false;
+ foreach ( $grpModules as $key => $module ) {
+ // Inline empty modules: since they're empty, just mark them as 'ready' (bug 46857)
+ // If we're only getting the styles, we don't need to do anything for empty modules.
+ if ( $module->isKnownEmpty( $context ) ) {
+ unset( $grpModules[$key] );
+ if ( $only !== ResourceLoaderModule::TYPE_STYLES ) {
+ $links['states'][$key] = 'ready';
+ }
+ }
+
+ $isRaw |= $module->isRaw();
}
- }
- // Inline empty modules: since they're empty, just mark them as 'ready'
- if ( count( $emptyModules ) > 0 && $only !== ResourceLoaderModule::TYPE_STYLES ) {
- // If we're only getting the styles, we don't need to do anything for empty modules.
- $links .= Html::inlineScript(
- ResourceLoader::makeLoaderConditionalScript(
- ResourceLoader::makeLoaderStateScript( $emptyModules )
- )
- ) . "\n";
- }
- // If there are no modules left, skip this group
- if ( count( $grpModules ) === 0 ) {
- continue;
- }
+ // If there are no non-empty modules, skip this group
+ if ( count( $grpModules ) === 0 ) {
+ continue;
+ }
- // Inline private modules. These can't be loaded through load.php for security
- // reasons, see bug 34907. Note that these modules should be loaded from
- // getHeadScripts() before the first loader call. Otherwise other modules can't
- // properly use them as dependencies (bug 30914)
- if ( $group === 'private' ) {
- if ( $only == ResourceLoaderModule::TYPE_STYLES ) {
- $links .= Html::inlineStyle(
- $resourceLoader->makeModuleResponse( $context, $grpModules )
- );
- } else {
- $links .= Html::inlineScript(
- ResourceLoader::makeLoaderConditionalScript(
+ // Inline private modules. These can't be loaded through load.php for security
+ // reasons, see bug 34907. Note that these modules should be loaded from
+ // getHeadScripts() before the first loader call. Otherwise other modules can't
+ // properly use them as dependencies (bug 30914)
+ if ( $group === 'private' ) {
+ if ( $only == ResourceLoaderModule::TYPE_STYLES ) {
+ $links['html'] .= Html::inlineStyle(
$resourceLoader->makeModuleResponse( $context, $grpModules )
- )
- );
+ );
+ } else {
+ $links['html'] .= Html::inlineScript(
+ ResourceLoader::makeLoaderConditionalScript(
+ $resourceLoader->makeModuleResponse( $context, $grpModules )
+ )
+ );
+ }
+ $links['html'] .= "\n";
+ continue;
}
- $links .= "\n";
- continue;
- }
- // Special handling for the user group; because users might change their stuff
- // on-wiki like user pages, or user preferences; we need to find the highest
- // timestamp of these user-changeable modules so we can ensure cache misses on change
- // This should NOT be done for the site group (bug 27564) because anons get that too
- // and we shouldn't be putting timestamps in Squid-cached HTML
- $version = null;
- if ( $group === 'user' ) {
- // Get the maximum timestamp
- $timestamp = 1;
- foreach ( $grpModules as $module ) {
- $timestamp = max( $timestamp, $module->getModifiedTime( $context ) );
+
+ // Special handling for the user group; because users might change their stuff
+ // on-wiki like user pages, or user preferences; we need to find the highest
+ // timestamp of these user-changeable modules so we can ensure cache misses on change
+ // This should NOT be done for the site group (bug 27564) because anons get that too
+ // and we shouldn't be putting timestamps in Squid-cached HTML
+ $version = null;
+ if ( $group === 'user' ) {
+ // Get the maximum timestamp
+ $timestamp = 1;
+ foreach ( $grpModules as $module ) {
+ $timestamp = max( $timestamp, $module->getModifiedTime( $context ) );
+ }
+ // Add a version parameter so cache will break when things change
+ $query['version'] = wfTimestamp( TS_ISO_8601_BASIC, $timestamp );
}
- // Add a version parameter so cache will break when things change
- $version = wfTimestamp( TS_ISO_8601_BASIC, $timestamp );
- }
- $url = ResourceLoader::makeLoaderURL(
- array_keys( $grpModules ),
- $this->getLanguage()->getCode(),
- $this->getSkin()->getSkinName(),
- $user,
- $version,
- ResourceLoader::inDebugMode(),
- $only === ResourceLoaderModule::TYPE_COMBINED ? null : $only,
- $this->isPrintable(),
- $this->getRequest()->getBool( 'handheld' ),
- $extraQuery
- );
- if ( $useESI && $wgResourceLoaderUseESI ) {
- $esi = Xml::element( 'esi:include', array( 'src' => $url ) );
- if ( $only == ResourceLoaderModule::TYPE_STYLES ) {
- $link = Html::inlineStyle( $esi );
+ $query['modules'] = ResourceLoader::makePackedModulesString( array_keys( $grpModules ) );
+ $moduleContext = new ResourceLoaderContext( $resourceLoader, new FauxRequest( $query ) );
+ $url = $resourceLoader->createLoaderURL( $source, $moduleContext, $extraQuery );
+
+ if ( $useESI && $resourceLoaderUseESI ) {
+ $esi = Xml::element( 'esi:include', array( 'src' => $url ) );
+ if ( $only == ResourceLoaderModule::TYPE_STYLES ) {
+ $link = Html::inlineStyle( $esi );
+ } else {
+ $link = Html::inlineScript( $esi );
+ }
} else {
- $link = Html::inlineScript( $esi );
+ // Automatically select style/script elements
+ if ( $only === ResourceLoaderModule::TYPE_STYLES ) {
+ $link = Html::linkedStyle( $url );
+ } elseif ( $loadCall ) {
+ $link = Html::inlineScript(
+ ResourceLoader::makeLoaderConditionalScript(
+ Xml::encodeJsCall( 'mw.loader.load', array( $url, 'text/javascript', true ) )
+ )
+ );
+ } else {
+ $link = Html::linkedScript( $url );
+ if ( $context->getOnly() === 'scripts' && !$context->getRaw() && !$isRaw ) {
+ // Wrap only=script requests in a conditional as browsers not supported
+ // by the startup module would unconditionally execute this module.
+ // Otherwise users will get "ReferenceError: mw is undefined" or
+ // "jQuery is undefined" from e.g. a "site" module.
+ $link = Html::inlineScript(
+ ResourceLoader::makeLoaderConditionalScript(
+ Xml::encodeJsCall( 'document.write', array( $link ) )
+ )
+ );
+ }
+
+ // For modules requested directly in the html via <link> or <script>,
+ // tell mw.loader they are being loading to prevent duplicate requests.
+ foreach ( $grpModules as $key => $module ) {
+ // Don't output state=loading for the startup module..
+ if ( $key !== 'startup' ) {
+ $links['states'][$key] = 'loading';
+ }
+ }
+ }
}
- } else {
- // Automatically select style/script elements
- if ( $only === ResourceLoaderModule::TYPE_STYLES ) {
- $link = Html::linkedStyle( $url );
- } elseif ( $loadCall ) {
- $link = Html::inlineScript(
- ResourceLoader::makeLoaderConditionalScript(
- Xml::encodeJsCall( 'mw.loader.load', array( $url, 'text/javascript', true ) )
- )
- );
+
+ if ( $group == 'noscript' ) {
+ $links['html'] .= Html::rawElement( 'noscript', array(), $link ) . "\n";
} else {
- $link = Html::linkedScript( $url );
+ $links['html'] .= $link . "\n";
}
}
+ }
- if ( $group == 'noscript' ) {
- $links .= Html::rawElement( 'noscript', array(), $link ) . "\n";
+ return $links;
+ }
+
+ /**
+ * Build html output from an array of links from makeResourceLoaderLink.
+ * @param array $links
+ * @return string HTML
+ */
+ protected static function getHtmlFromLoaderLinks( array $links ) {
+ $html = '';
+ $states = array();
+ foreach ( $links as $link ) {
+ if ( !is_array( $link ) ) {
+ $html .= $link;
} else {
- $links .= $link . "\n";
+ $html .= $link['html'];
+ $states += $link['states'];
}
}
- return $links;
+
+ if ( count( $states ) ) {
+ $html = Html::inlineScript(
+ ResourceLoader::makeLoaderConditionalScript(
+ ResourceLoader::makeLoaderStateScript( $states )
+ )
+ ) . "\n" . $html;
+ }
+
+ return $html;
}
/**
* JS stuff to put in the "<head>". This is the startup module, config
* vars and modules marked with position 'top'
*
- * @return String: HTML fragment
+ * @return string HTML fragment
*/
function getHeadScripts() {
- global $wgResourceLoaderExperimentalAsyncLoading;
-
// Startup - this will immediately load jquery and mediawiki modules
- $scripts = $this->makeResourceLoaderLink( 'startup', ResourceLoaderModule::TYPE_SCRIPTS, true );
+ $links = array();
+ $links[] = $this->makeResourceLoaderLink( 'startup', ResourceLoaderModule::TYPE_SCRIPTS, true );
// Load config before anything else
- $scripts .= Html::inlineScript(
+ $links[] = Html::inlineScript(
ResourceLoader::makeLoaderConditionalScript(
ResourceLoader::makeConfigSetScript( $this->getJSVars() )
)
@@ -2816,51 +2989,58 @@ $templates
// This needs to be TYPE_COMBINED so these modules are properly wrapped
// in mw.loader.implement() calls and deferred until mw.user is available
$embedScripts = array( 'user.options', 'user.tokens' );
- $scripts .= $this->makeResourceLoaderLink( $embedScripts, ResourceLoaderModule::TYPE_COMBINED );
+ $links[] = $this->makeResourceLoaderLink( $embedScripts, ResourceLoaderModule::TYPE_COMBINED );
- // Script and Messages "only" requests marked for top inclusion
+ // Scripts and messages "only" requests marked for top inclusion
// Messages should go first
- $scripts .= $this->makeResourceLoaderLink( $this->getModuleMessages( true, 'top' ), ResourceLoaderModule::TYPE_MESSAGES );
- $scripts .= $this->makeResourceLoaderLink( $this->getModuleScripts( true, 'top' ), ResourceLoaderModule::TYPE_SCRIPTS );
+ $links[] = $this->makeResourceLoaderLink(
+ $this->getModuleMessages( true, 'top' ),
+ ResourceLoaderModule::TYPE_MESSAGES
+ );
+ $links[] = $this->makeResourceLoaderLink(
+ $this->getModuleScripts( true, 'top' ),
+ ResourceLoaderModule::TYPE_SCRIPTS
+ );
// Modules requests - let the client calculate dependencies and batch requests as it likes
// Only load modules that have marked themselves for loading at the top
$modules = $this->getModules( true, 'top' );
if ( $modules ) {
- $scripts .= Html::inlineScript(
+ $links[] = Html::inlineScript(
ResourceLoader::makeLoaderConditionalScript(
Xml::encodeJsCall( 'mw.loader.load', array( $modules ) )
)
);
}
- if ( $wgResourceLoaderExperimentalAsyncLoading ) {
- $scripts .= $this->getScriptsForBottomQueue( true );
+ if ( $this->getConfig()->get( 'ResourceLoaderExperimentalAsyncLoading' ) ) {
+ $links[] = $this->getScriptsForBottomQueue( true );
}
- return $scripts;
+ return self::getHtmlFromLoaderLinks( $links );
}
/**
- * JS stuff to put at the 'bottom', which can either be the bottom of the "<body>"
- * or the bottom of the "<head>" depending on $wgResourceLoaderExperimentalAsyncLoading:
- * modules marked with position 'bottom', legacy scripts ($this->mScripts),
- * user preferences, site JS and user JS
+ * JS stuff to put at the 'bottom', which can either be the bottom of the
+ * "<body>" or the bottom of the "<head>" depending on
+ * $wgResourceLoaderExperimentalAsyncLoading: modules marked with position
+ * 'bottom', legacy scripts ($this->mScripts), user preferences, site JS
+ * and user JS.
*
- * @param $inHead boolean If true, this HTML goes into the "<head>", if false it goes into the "<body>"
+ * @param bool $inHead If true, this HTML goes into the "<head>",
+ * if false it goes into the "<body>".
* @return string
*/
function getScriptsForBottomQueue( $inHead ) {
- global $wgUseSiteJs, $wgAllowUserJs;
-
- // Script and Messages "only" requests marked for bottom inclusion
+ // Scripts and messages "only" requests marked for bottom inclusion
// If we're in the <head>, use load() calls rather than <script src="..."> tags
// Messages should go first
- $scripts = $this->makeResourceLoaderLink( $this->getModuleMessages( true, 'bottom' ),
+ $links = array();
+ $links[] = $this->makeResourceLoaderLink( $this->getModuleMessages( true, 'bottom' ),
ResourceLoaderModule::TYPE_MESSAGES, /* $useESI = */ false, /* $extraQuery = */ array(),
/* $loadCall = */ $inHead
);
- $scripts .= $this->makeResourceLoaderLink( $this->getModuleScripts( true, 'bottom' ),
+ $links[] = $this->makeResourceLoaderLink( $this->getModuleScripts( true, 'bottom' ),
ResourceLoaderModule::TYPE_SCRIPTS, /* $useESI = */ false, /* $extraQuery = */ array(),
/* $loadCall = */ $inHead
);
@@ -2869,7 +3049,7 @@ $templates
// Only load modules that have marked themselves for loading at the bottom
$modules = $this->getModules( true, 'bottom' );
if ( $modules ) {
- $scripts .= Html::inlineScript(
+ $links[] = Html::inlineScript(
ResourceLoader::makeLoaderConditionalScript(
Xml::encodeJsCall( 'mw.loader.load', array( $modules, null, true ) )
)
@@ -2877,88 +3057,46 @@ $templates
}
// Legacy Scripts
- $scripts .= "\n" . $this->mScripts;
-
- $defaultModules = array();
+ $links[] = "\n" . $this->mScripts;
// Add site JS if enabled
- if ( $wgUseSiteJs ) {
- $scripts .= $this->makeResourceLoaderLink( 'site', ResourceLoaderModule::TYPE_SCRIPTS,
- /* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
- );
- $defaultModules['site'] = 'loading';
- } else {
- // Site module is empty, save request by marking ready in advance (bug 46857)
- $defaultModules['site'] = 'ready';
- }
+ $links[] = $this->makeResourceLoaderLink( 'site', ResourceLoaderModule::TYPE_SCRIPTS,
+ /* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
+ );
// Add user JS if enabled
- if ( $wgAllowUserJs ) {
- if ( $this->getUser()->isLoggedIn() ) {
- if ( $this->getTitle() && $this->getTitle()->isJsSubpage() && $this->userCanPreview() ) {
- # XXX: additional security check/prompt?
- // We're on a preview of a JS subpage
- // Exclude this page from the user module in case it's in there (bug 26283)
- $scripts .= $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_SCRIPTS, false,
- array( 'excludepage' => $this->getTitle()->getPrefixedDBkey() ), $inHead
- );
- // Load the previewed JS
- $scripts .= Html::inlineScript( "\n" . $this->getRequest()->getText( 'wpTextbox1' ) . "\n" ) . "\n";
- // FIXME: If the user is previewing, say, ./vector.js, his ./common.js will be loaded
- // asynchronously and may arrive *after* the inline script here. So the previewed code
- // may execute before ./common.js runs. Normally, ./common.js runs before ./vector.js...
- } else {
- // Include the user module normally, i.e., raw to avoid it being wrapped in a closure.
- $scripts .= $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_SCRIPTS,
- /* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
- );
- }
- $defaultModules['user'] = 'loading';
- } else {
- // Non-logged-in users have an empty user module.
- // Save request by marking ready in advance (bug 46857)
- $defaultModules['user'] = 'ready';
- }
+ if ( $this->getConfig()->get( 'AllowUserJs' )
+ && $this->getUser()->isLoggedIn()
+ && $this->getTitle()
+ && $this->getTitle()->isJsSubpage()
+ && $this->userCanPreview()
+ ) {
+ # XXX: additional security check/prompt?
+ // We're on a preview of a JS subpage
+ // Exclude this page from the user module in case it's in there (bug 26283)
+ $links[] = $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_SCRIPTS, false,
+ array( 'excludepage' => $this->getTitle()->getPrefixedDBkey() ), $inHead
+ );
+ // Load the previewed JS
+ $links[] = Html::inlineScript( "\n"
+ . $this->getRequest()->getText( 'wpTextbox1' ) . "\n" ) . "\n";
+
+ // FIXME: If the user is previewing, say, ./vector.js, his ./common.js will be loaded
+ // asynchronously and may arrive *after* the inline script here. So the previewed code
+ // may execute before ./common.js runs. Normally, ./common.js runs before ./vector.js...
} else {
- // User modules are disabled on this wiki.
- // Save request by marking ready in advance (bug 46857)
- $defaultModules['user'] = 'ready';
+ // Include the user module normally, i.e., raw to avoid it being wrapped in a closure.
+ $links[] = $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_SCRIPTS,
+ /* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
+ );
}
// Group JS is only enabled if site JS is enabled.
- if ( $wgUseSiteJs ) {
- if ( $this->getUser()->isLoggedIn() ) {
- $scripts .= $this->makeResourceLoaderLink( 'user.groups', ResourceLoaderModule::TYPE_COMBINED,
- /* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
- );
- $defaultModules['user.groups'] = 'loading';
- } else {
- // Non-logged-in users have no user.groups module.
- // Save request by marking ready in advance (bug 46857)
- $defaultModules['user.groups'] = 'ready';
- }
- } else {
- // Site (and group JS) disabled
- $defaultModules['user.groups'] = 'ready';
- }
+ $links[] = $this->makeResourceLoaderLink( 'user.groups', ResourceLoaderModule::TYPE_COMBINED,
+ /* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
+ );
- $loaderInit = '';
- if ( $inHead ) {
- // We generate loader calls anyway, so no need to fix the client-side loader's state to 'loading'.
- foreach ( $defaultModules as $m => $state ) {
- if ( $state == 'loading' ) {
- unset( $defaultModules[$m] );
- }
- }
- }
- if ( count( $defaultModules ) > 0 ) {
- $loaderInit = Html::inlineScript(
- ResourceLoader::makeLoaderConditionalScript(
- ResourceLoader::makeLoaderStateScript( $defaultModules )
- )
- ) . "\n";
- }
- return $loaderInit . $scripts;
+ return self::getHtmlFromLoaderLinks( $links );
}
/**
@@ -2966,15 +3104,13 @@ $templates
* @return string
*/
function getBottomScripts() {
- global $wgResourceLoaderExperimentalAsyncLoading;
-
// Optimise jQuery ready event cross-browser.
// This also enforces $.isReady to be true at </body> which fixes the
// mw.loader bug in Firefox with using document.write between </body>
// and the DOMContentReady event (bug 47457).
$html = Html::inlineScript( 'window.jQuery && jQuery.ready();' );
- if ( !$wgResourceLoaderExperimentalAsyncLoading ) {
+ if ( !$this->getConfig()->get( 'ResourceLoaderExperimentalAsyncLoading' ) ) {
$html .= $this->getScriptsForBottomQueue( false );
}
@@ -2982,10 +3118,20 @@ $templates
}
/**
- * Add one or more variables to be set in mw.config in JavaScript.
+ * Get the javascript config vars to include on this page
+ *
+ * @return array Array of javascript config vars
+ * @since 1.23
+ */
+ public function getJsConfigVars() {
+ return $this->mJsConfigVars;
+ }
+
+ /**
+ * Add one or more variables to be set in mw.config in JavaScript
*
- * @param $keys {String|Array} Key or array of key/value pairs.
- * @param $value {Mixed} [optional] Value of the configuration variable.
+ * @param string|array $keys Key or array of key/value pairs
+ * @param mixed $value [optional] Value of the configuration variable
*/
public function addJsConfigVars( $keys, $value = null ) {
if ( is_array( $keys ) ) {
@@ -3001,16 +3147,13 @@ $templates
/**
* Get an array containing the variables to be set in mw.config in JavaScript.
*
- * DO NOT CALL THIS FROM OUTSIDE OF THIS CLASS OR Skin::makeGlobalVariablesScript().
- * This is only public until that function is removed. You have been warned.
- *
* Do not add things here which can be evaluated in ResourceLoaderStartUpModule
* - in other words, page-independent/site-wide variables (without state).
* You will only be adding bloat to the html page and causing page caches to
* have to be purged on configuration changes.
* @return array
*/
- public function getJSVars() {
+ private function getJSVars() {
global $wgContLang;
$curRevisionId = 0;
@@ -3019,14 +3162,19 @@ $templates
$title = $this->getTitle();
$ns = $title->getNamespace();
- $canonicalNamespace = MWNamespace::exists( $ns ) ? MWNamespace::getCanonicalName( $ns ) : $title->getNsText();
+ $canonicalNamespace = MWNamespace::exists( $ns )
+ ? MWNamespace::getCanonicalName( $ns )
+ : $title->getNsText();
+ $sk = $this->getSkin();
// Get the relevant title so that AJAX features can use the correct page name
// when making API requests from certain special pages (bug 34972).
- $relevantTitle = $this->getSkin()->getRelevantTitle();
+ $relevantTitle = $sk->getRelevantTitle();
+ $relevantUser = $sk->getRelevantUser();
if ( $ns == NS_SPECIAL ) {
- list( $canonicalSpecialPageName, /*...*/ ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
+ list( $canonicalSpecialPageName, /*...*/ ) =
+ SpecialPageFactory::resolveAlias( $title->getDBkey() );
} elseif ( $this->canUseWikiPage() ) {
$wikiPage = $this->getWikiPage();
$curRevisionId = $wikiPage->getLatest();
@@ -3076,6 +3224,7 @@ $templates
'wgMonthNamesShort' => $lang->getMonthAbbreviationsArray(),
'wgRelevantPageName' => $relevantTitle->getPrefixedDBkey(),
);
+
if ( $user->isLoggedIn() ) {
$vars['wgUserId'] = $user->getId();
$vars['wgUserEditCount'] = $user->getEditCount();
@@ -3086,21 +3235,30 @@ $templates
// the client side.
$vars['wgUserNewMsgRevisionId'] = $user->getNewMessageRevisionId();
}
+
if ( $wgContLang->hasVariants() ) {
$vars['wgUserVariant'] = $wgContLang->getPreferredVariant();
}
// Same test as SkinTemplate
- $vars['wgIsProbablyEditable'] = $title->quickUserCan( 'edit', $user ) && ( $title->exists() || $title->quickUserCan( 'create', $user ) );
+ $vars['wgIsProbablyEditable'] = $title->quickUserCan( 'edit', $user )
+ && ( $title->exists() || $title->quickUserCan( 'create', $user ) );
+
foreach ( $title->getRestrictionTypes() as $type ) {
$vars['wgRestriction' . ucfirst( $type )] = $title->getRestrictions( $type );
}
+
if ( $title->isMainPage() ) {
$vars['wgIsMainPage'] = true;
}
+
if ( $this->mRedirectedFrom ) {
$vars['wgRedirectedFrom'] = $this->mRedirectedFrom->getPrefixedDBkey();
}
+ if ( $relevantUser ) {
+ $vars['wgRelevantUserName'] = $relevantUser->getName();
+ }
+
// Allow extensions to add their custom variables to the mw.config map.
// Use the 'ResourceLoaderGetConfigVars' hook if the variable is not
// page-dependant but site-wide (without state).
@@ -3108,7 +3266,7 @@ $templates
wfRunHooks( 'MakeGlobalVariablesScript', array( &$vars, $this ) );
// Merge in variables from addJsConfigVars last
- return array_merge( $vars, $this->mJsConfigVars );
+ return array_merge( $vars, $this->getJsConfigVars() );
}
/**
@@ -3136,16 +3294,13 @@ $templates
}
/**
- * @return array in format "link name or number => 'link html'".
+ * @return array Array in format "link name or number => 'link html'".
*/
public function getHeadLinksArray() {
- global $wgUniversalEditButton, $wgFavicon, $wgAppleTouchIcon, $wgEnableAPI,
- $wgSitename, $wgVersion,
- $wgFeed, $wgOverrideSiteFeed, $wgAdvertisedFeedTypes,
- $wgDisableLangConversion, $wgCanonicalLanguageLinks,
- $wgRightsPage, $wgRightsUrl;
+ global $wgVersion;
$tags = array();
+ $config = $this->getConfig();
$canonicalUrl = $this->mCanonicalUrl;
@@ -3188,7 +3343,7 @@ $templates
}
# Universal edit button
- if ( $wgUniversalEditButton && $this->isArticleRelated() ) {
+ if ( $config->get( 'UniversalEditButton' ) && $this->isArticleRelated() ) {
$user = $this->getUser();
if ( $this->getTitle()->quickUserCan( 'edit', $user )
&& ( $this->getTitle()->exists() || $this->getTitle()->quickUserCan( 'create', $user ) ) ) {
@@ -3198,13 +3353,13 @@ $templates
'rel' => 'alternate',
'type' => 'application/x-wiki',
'title' => $msg,
- 'href' => $this->getTitle()->getLocalURL( 'action=edit' )
+ 'href' => $this->getTitle()->getEditURL(),
) );
// Alternate edit link
$tags['alternative-edit'] = Html::element( 'link', array(
'rel' => 'edit',
'title' => $msg,
- 'href' => $this->getTitle()->getLocalURL( 'action=edit' )
+ 'href' => $this->getTitle()->getEditURL(),
) );
}
}
@@ -3213,12 +3368,18 @@ $templates
# should not matter, but Konqueror (3.5.9 at least) incorrectly
# uses whichever one appears later in the HTML source. Make sure
# apple-touch-icon is specified first to avoid this.
- if ( $wgAppleTouchIcon !== false ) {
- $tags['apple-touch-icon'] = Html::element( 'link', array( 'rel' => 'apple-touch-icon', 'href' => $wgAppleTouchIcon ) );
+ if ( $config->get( 'AppleTouchIcon' ) !== false ) {
+ $tags['apple-touch-icon'] = Html::element( 'link', array(
+ 'rel' => 'apple-touch-icon',
+ 'href' => $config->get( 'AppleTouchIcon' )
+ ) );
}
- if ( $wgFavicon !== false ) {
- $tags['favicon'] = Html::element( 'link', array( 'rel' => 'shortcut icon', 'href' => $wgFavicon ) );
+ if ( $config->get( 'Favicon' ) !== false ) {
+ $tags['favicon'] = Html::element( 'link', array(
+ 'rel' => 'shortcut icon',
+ 'href' => $config->get( 'Favicon' )
+ ) );
}
# OpenSearch description link
@@ -3229,7 +3390,7 @@ $templates
'title' => $this->msg( 'opensearch-desc' )->inContentLanguage()->text(),
) );
- if ( $wgEnableAPI ) {
+ if ( $config->get( 'EnableAPI' ) ) {
# Real Simple Discovery link, provides auto-discovery information
# for the MediaWiki API (and potentially additional custom API
# support such as WordPress or Twitter-compatible APIs for a
@@ -3239,44 +3400,46 @@ $templates
'type' => 'application/rsd+xml',
// Output a protocol-relative URL here if $wgServer is protocol-relative
// Whether RSD accepts relative or protocol-relative URLs is completely undocumented, though
- 'href' => wfExpandUrl( wfAppendQuery( wfScript( 'api' ), array( 'action' => 'rsd' ) ), PROTO_RELATIVE ),
+ 'href' => wfExpandUrl( wfAppendQuery(
+ wfScript( 'api' ),
+ array( 'action' => 'rsd' ) ),
+ PROTO_RELATIVE
+ ),
) );
}
# Language variants
- if ( !$wgDisableLangConversion && $wgCanonicalLanguageLinks ) {
+ if ( !$config->get( 'DisableLangConversion' ) ) {
$lang = $this->getTitle()->getPageLanguage();
if ( $lang->hasVariants() ) {
-
- $urlvar = $lang->getURLVariant();
-
- if ( !$urlvar ) {
- $variants = $lang->getVariants();
- foreach ( $variants as $_v ) {
- $tags["variant-$_v"] = Html::element( 'link', array(
- 'rel' => 'alternate',
- 'hreflang' => wfBCP47( $_v ),
- 'href' => $this->getTitle()->getLocalURL( array( 'variant' => $_v ) ) )
- );
- }
- } else {
- $canonicalUrl = $this->getTitle()->getLocalURL();
+ $variants = $lang->getVariants();
+ foreach ( $variants as $_v ) {
+ $tags["variant-$_v"] = Html::element( 'link', array(
+ 'rel' => 'alternate',
+ 'hreflang' => wfBCP47( $_v ),
+ 'href' => $this->getTitle()->getLocalURL( array( 'variant' => $_v ) ) )
+ );
}
}
+ # x-default link per https://support.google.com/webmasters/answer/189077?hl=en
+ $tags["variant-x-default"] = Html::element( 'link', array(
+ 'rel' => 'alternate',
+ 'hreflang' => 'x-default',
+ 'href' => $this->getTitle()->getLocalURL() ) );
}
# Copyright
$copyright = '';
- if ( $wgRightsPage ) {
- $copy = Title::newFromText( $wgRightsPage );
+ if ( $config->get( 'RightsPage' ) ) {
+ $copy = Title::newFromText( $config->get( 'RightsPage' ) );
if ( $copy ) {
$copyright = $copy->getLocalURL();
}
}
- if ( !$copyright && $wgRightsUrl ) {
- $copyright = $wgRightsUrl;
+ if ( !$copyright && $config->get( 'RightsUrl' ) ) {
+ $copyright = $config->get( 'RightsUrl' );
}
if ( $copyright ) {
@@ -3287,7 +3450,7 @@ $templates
}
# Feeds
- if ( $wgFeed ) {
+ if ( $config->get( 'Feed' ) ) {
foreach ( $this->getSyndicationLinks() as $format => $link ) {
# Use the page name for the title. In principle, this could
# lead to issues with having the same name for different feeds
@@ -3309,30 +3472,31 @@ $templates
# like to promote instead of the RC feed (maybe like a "Recent New Articles"
# or "Breaking news" one). For this, we see if $wgOverrideSiteFeed is defined.
# If so, use it instead.
- if ( $wgOverrideSiteFeed ) {
- foreach ( $wgOverrideSiteFeed as $type => $feedUrl ) {
+ $sitename = $config->get( 'Sitename' );
+ if ( $config->get( 'OverrideSiteFeed' ) ) {
+ foreach ( $config->get( 'OverrideSiteFeed' ) as $type => $feedUrl ) {
// Note, this->feedLink escapes the url.
$tags[] = $this->feedLink(
$type,
$feedUrl,
- $this->msg( "site-{$type}-feed", $wgSitename )->text()
+ $this->msg( "site-{$type}-feed", $sitename )->text()
);
}
} elseif ( !$this->getTitle()->isSpecial( 'Recentchanges' ) ) {
$rctitle = SpecialPage::getTitleFor( 'Recentchanges' );
- foreach ( $wgAdvertisedFeedTypes as $format ) {
+ foreach ( $config->get( 'AdvertisedFeedTypes' ) as $format ) {
$tags[] = $this->feedLink(
$format,
$rctitle->getLocalURL( array( 'feed' => $format ) ),
- $this->msg( "site-{$format}-feed", $wgSitename )->text() # For grep: 'site-rss-feed', 'site-atom-feed'.
+ # For grep: 'site-rss-feed', 'site-atom-feed'
+ $this->msg( "site-{$format}-feed", $sitename )->text()
);
}
}
}
# Canonical URL
- global $wgEnableCanonicalServerLink;
- if ( $wgEnableCanonicalServerLink ) {
+ if ( $config->get( 'EnableCanonicalServerLink' ) ) {
if ( $canonicalUrl !== false ) {
$canonicalUrl = wfExpandUrl( $canonicalUrl, PROTO_CANONICAL );
} else {
@@ -3352,18 +3516,21 @@ $templates
/**
* @return string HTML tag links to be put in the header.
+ * @deprecated since 1.24 Use OutputPage::headElement or if you have to,
+ * OutputPage::getHeadLinksArray directly.
*/
public function getHeadLinks() {
+ wfDeprecated( __METHOD__, '1.24' );
return implode( "\n", $this->getHeadLinksArray() );
}
/**
* Generate a "<link rel/>" for a feed.
*
- * @param string $type feed type
+ * @param string $type Feed type
* @param string $url URL to the feed
- * @param string $text value of the "title" attribute
- * @return String: HTML fragment
+ * @param string $text Value of the "title" attribute
+ * @return string HTML fragment
*/
private function feedLink( $type, $url, $text ) {
return Html::element( 'link', array(
@@ -3379,9 +3546,9 @@ $templates
* Meant primarily for internal use...
*
* @param string $style URL to the file
- * @param string $media to specify a media type, 'screen', 'printable', 'handheld' or any.
- * @param string $condition for IE conditional comments, specifying an IE version
- * @param string $dir set to 'rtl' or 'ltr' for direction-specific sheets
+ * @param string $media To specify a media type, 'screen', 'printable', 'handheld' or any.
+ * @param string $condition For IE conditional comments, specifying an IE version
+ * @param string $dir Set to 'rtl' or 'ltr' for direction-specific sheets
*/
public function addStyle( $style, $media = '', $condition = '', $dir = '' ) {
$options = array();
@@ -3401,7 +3568,7 @@ $templates
/**
* Adds inline CSS styles
- * @param $style_css Mixed: inline CSS
+ * @param mixed $style_css Inline CSS
* @param string $flip Set to 'flip' to flip the CSS if needed
*/
public function addInlineStyle( $style_css, $flip = 'noflip' ) {
@@ -3409,7 +3576,7 @@ $templates
# If wanted, and the interface is right-to-left, flip the CSS
$style_css = CSSJanus::transform( $style_css, true, false );
}
- $this->mInlineStyles .= Html::inlineStyle( $style_css );
+ $this->mInlineStyles .= Html::inlineStyle( $style_css ) . "\n";
}
/**
@@ -3419,54 +3586,54 @@ $templates
* @return string
*/
public function buildCssLinks() {
- global $wgUseSiteCss, $wgAllowUserCss, $wgAllowUserCssPrefs, $wgContLang;
+ global $wgContLang;
$this->getSkin()->setupSkinUserCss( $this );
// Add ResourceLoader styles
- // Split the styles into four groups
- $styles = array( 'other' => array(), 'user' => array(), 'site' => array(), 'private' => array(), 'noscript' => array() );
+ // Split the styles into these groups
+ $styles = array(
+ 'other' => array(),
+ 'user' => array(),
+ 'site' => array(),
+ 'private' => array(),
+ 'noscript' => array()
+ );
+ $links = array();
$otherTags = ''; // Tags to append after the normal <link> tags
$resourceLoader = $this->getResourceLoader();
$moduleStyles = $this->getModuleStyles();
// Per-site custom styles
- if ( $wgUseSiteCss ) {
- $moduleStyles[] = 'site';
- $moduleStyles[] = 'noscript';
- if ( $this->getUser()->isLoggedIn() ) {
- $moduleStyles[] = 'user.groups';
- }
- }
+ $moduleStyles[] = 'site';
+ $moduleStyles[] = 'noscript';
+ $moduleStyles[] = 'user.groups';
// Per-user custom styles
- if ( $wgAllowUserCss ) {
- if ( $this->getTitle()->isCssSubpage() && $this->userCanPreview() ) {
- // We're on a preview of a CSS subpage
- // Exclude this page from the user module in case it's in there (bug 26283)
- $otherTags .= $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_STYLES, false,
- array( 'excludepage' => $this->getTitle()->getPrefixedDBkey() )
- );
-
- // Load the previewed CSS
- // If needed, Janus it first. This is user-supplied CSS, so it's
- // assumed to be right for the content language directionality.
- $previewedCSS = $this->getRequest()->getText( 'wpTextbox1' );
- if ( $this->getLanguage()->getDir() !== $wgContLang->getDir() ) {
- $previewedCSS = CSSJanus::transform( $previewedCSS, true, false );
- }
- $otherTags .= Html::inlineStyle( $previewedCSS );
- } else {
- // Load the user styles normally
- $moduleStyles[] = 'user';
+ if ( $this->getConfig()->get( 'AllowUserCss' ) && $this->getTitle()->isCssSubpage() && $this->userCanPreview() ) {
+ // We're on a preview of a CSS subpage
+ // Exclude this page from the user module in case it's in there (bug 26283)
+ $link = $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_STYLES, false,
+ array( 'excludepage' => $this->getTitle()->getPrefixedDBkey() )
+ );
+ $otherTags .= $link['html'];
+
+ // Load the previewed CSS
+ // If needed, Janus it first. This is user-supplied CSS, so it's
+ // assumed to be right for the content language directionality.
+ $previewedCSS = $this->getRequest()->getText( 'wpTextbox1' );
+ if ( $this->getLanguage()->getDir() !== $wgContLang->getDir() ) {
+ $previewedCSS = CSSJanus::transform( $previewedCSS, true, false );
}
+ $otherTags .= Html::inlineStyle( $previewedCSS ) . "\n";
+ } else {
+ // Load the user styles normally
+ $moduleStyles[] = 'user';
}
// Per-user preference styles
- if ( $wgAllowUserCssPrefs ) {
- $moduleStyles[] = 'user.cssprefs';
- }
+ $moduleStyles[] = 'user.cssprefs';
foreach ( $moduleStyles as $name ) {
$module = $resourceLoader->getModule( $name );
@@ -3474,38 +3641,41 @@ $templates
continue;
}
$group = $module->getGroup();
- // Modules in groups named "other" or anything different than "user", "site" or "private"
+ // Modules in groups different than the ones listed on top (see $styles assignment)
// will be placed in the "other" group
$styles[isset( $styles[$group] ) ? $group : 'other'][] = $name;
}
- // We want site, private and user styles to override dynamically added styles from modules, but we want
- // dynamically added styles to override statically added styles from other modules. So the order
- // has to be other, dynamic, site, private, user
- // Add statically added styles for other modules
- $ret = $this->makeResourceLoaderLink( $styles['other'], ResourceLoaderModule::TYPE_STYLES );
+ // We want site, private and user styles to override dynamically added
+ // styles from modules, but we want dynamically added styles to override
+ // statically added styles from other modules. So the order has to be
+ // other, dynamic, site, private, user. Add statically added styles for
+ // other modules
+ $links[] = $this->makeResourceLoaderLink( $styles['other'], ResourceLoaderModule::TYPE_STYLES );
// Add normal styles added through addStyle()/addInlineStyle() here
- $ret .= implode( "\n", $this->buildCssLinksArray() ) . $this->mInlineStyles;
+ $links[] = implode( "\n", $this->buildCssLinksArray() ) . $this->mInlineStyles;
// Add marker tag to mark the place where the client-side loader should inject dynamic styles
// We use a <meta> tag with a made-up name for this because that's valid HTML
- $ret .= Html::element( 'meta', array( 'name' => 'ResourceLoaderDynamicStyles', 'content' => '' ) ) . "\n";
+ $links[] = Html::element(
+ 'meta',
+ array( 'name' => 'ResourceLoaderDynamicStyles', 'content' => '' )
+ ) . "\n";
// Add site, private and user styles
// 'private' at present only contains user.options, so put that before 'user'
// Any future private modules will likely have a similar user-specific character
foreach ( array( 'site', 'noscript', 'private', 'user' ) as $group ) {
- $ret .= $this->makeResourceLoaderLink( $styles[$group],
- ResourceLoaderModule::TYPE_STYLES
+ $links[] = $this->makeResourceLoaderLink( $styles[$group],
+ ResourceLoaderModule::TYPE_STYLES
);
}
// Add stuff in $otherTags (previewed user CSS if applicable)
- $ret .= $otherTags;
- return $ret;
+ return self::getHtmlFromLoaderLinks( $links ) . $otherTags;
}
/**
- * @return Array
+ * @return array
*/
public function buildCssLinksArray() {
$links = array();
@@ -3529,11 +3699,10 @@ $templates
* Generate \<link\> tags for stylesheets
*
* @param string $style URL to the file
- * @param array $options option, can contain 'condition', 'dir', 'media'
- * keys
- * @return String: HTML fragment
+ * @param array $options Option, can contain 'condition', 'dir', 'media' keys
+ * @return string HTML fragment
*/
- protected function styleLink( $style, $options ) {
+ protected function styleLink( $style, array $options ) {
if ( isset( $options['dir'] ) ) {
if ( $this->getLanguage()->getDir() != $options['dir'] ) {
return '';
@@ -3554,8 +3723,8 @@ $templates
substr( $style, 0, 6 ) == 'https:' ) {
$url = $style;
} else {
- global $wgStylePath, $wgStyleVersion;
- $url = $wgStylePath . '/' . $style . '?' . $wgStyleVersion;
+ $config = $this->getConfig();
+ $url = $config->get( 'StylePath' ) . '/' . $style . '?' . $config->get( 'StyleVersion' );
}
$link = Html::linkedStyle( $url, $media );
@@ -3570,8 +3739,8 @@ $templates
/**
* Transform "media" attribute based on request parameters
*
- * @param string $media current value of the "media" attribute
- * @return String: modified value of the "media" attribute, or null to skip
+ * @param string $media Current value of the "media" attribute
+ * @return string Modified value of the "media" attribute, or null to skip
* this stylesheet
*/
public static function transformCssMedia( $media ) {
@@ -3592,8 +3761,10 @@ $templates
} elseif ( preg_match( $screenMediaQueryRegex, $media ) === 1 ) {
// This regex will not attempt to understand a comma-separated media_query_list
//
- // Example supported values for $media: 'screen', 'only screen', 'screen and (min-width: 982px)' ),
- // Example NOT supported value for $media: '3d-glasses, screen, print and resolution > 90dpi'
+ // Example supported values for $media:
+ // 'screen', 'only screen', 'screen and (min-width: 982px)' ),
+ // Example NOT supported value for $media:
+ // '3d-glasses, screen, print and resolution > 90dpi'
//
// If it's a print request, we never want any kind of screen stylesheets
// If it's a handheld request (currently the only other choice with a switch),
@@ -3627,8 +3798,8 @@ $templates
* Like addWikiMsg() except the parameters are taken as an array
* instead of a variable argument list.
*
- * @param $name string
- * @param $args array
+ * @param string $name
+ * @param array $args
*/
public function addWikiMsgArray( $name, $args ) {
$this->addHTML( $this->msg( $name, $args )->parseAsBlock() );
@@ -3651,11 +3822,12 @@ $templates
*
* Is equivalent to:
*
- * $wgOut->addWikiText( "<div class='error'>\n" . wfMessage( 'some-error' )->plain() . "\n</div>" );
+ * $wgOut->addWikiText( "<div class='error'>\n"
+ * . wfMessage( 'some-error' )->plain() . "\n</div>" );
*
* The newline after opening div is needed in some wikitext. See bug 19226.
*
- * @param $wrap string
+ * @param string $wrap
*/
public function wrapWikiMsg( $wrap /*, ...*/ ) {
$msgSpecs = func_get_args();
@@ -3686,12 +3858,12 @@ $templates
* Include jQuery core. Use this to avoid loading it multiple times
* before we get a usable script loader.
*
- * @param array $modules list of jQuery modules which should be loaded
- * @return Array: the list of modules which were not loaded.
+ * @param array $modules List of jQuery modules which should be loaded
+ * @return array The list of modules which were not loaded.
* @since 1.16
* @deprecated since 1.17
*/
- public function includeJQuery( $modules = array() ) {
+ public function includeJQuery( array $modules = array() ) {
return array();
}
@@ -3711,4 +3883,21 @@ $templates
public function isTOCEnabled() {
return $this->mEnableTOC;
}
+
+ /**
+ * Enables/disables section edit links, doesn't override __NOEDITSECTION__
+ * @param bool $flag
+ * @since 1.23
+ */
+ public function enableSectionEditLinks( $flag = true ) {
+ $this->mEnableSectionEditLinks = $flag;
+ }
+
+ /**
+ * @return bool
+ * @since 1.23
+ */
+ public function sectionEditLinksEnabled() {
+ return $this->mEnableSectionEditLinks;
+ }
}