/**
* Add a foreign source of modules.
- *
+ *
* Source properties:
* 'loadScript': URL (either fully-qualified or protocol-relative) of load.php for this source
- *
+ *
* @param $id Mixed: source ID (string), or array( id1 => props1, id2 => props2, ... )
* @param $properties Array: source properties
*/
/**
* Get the list of sources
- *
+ *
* @return Array: array( id => array of properties, .. )
*/
public function getSources() {
// the last modified time
$mtime = wfTimestamp( TS_UNIX, $wgCacheEpoch );
foreach ( $modules as $module ) {
+ /**
+ * @var $module ResourceLoaderModule
+ */
try {
// Bypass Squid and other shared caches if the request includes any private modules
if ( $module->getGroup() === 'private' ) {
$this->sendResponseHeaders( $context, $ts, false );
// If there's an If-Modified-Since header, respond with a 304 appropriately
if ( $this->tryRespondLastModified( $context, $ts ) ) {
- return; // output handled (buffers cleared)
+ return false; // output handled (buffers cleared)
}
$response = $fileCache->fetchText();
// Remove the output buffer and output the response
// Generate output
foreach ( $modules as $name => $module ) {
+ /**
+ * @var $module ResourceLoaderModule
+ */
+
wfProfileIn( __METHOD__ . '-' . $name );
try {
$scripts = '';
/**
* Returns JS code which calls mw.loader.addSource() with the given
* parameters. Has two calling conventions:
- *
+ *
* - ResourceLoader::makeLoaderSourcesScript( $id, $properties ):
* Register a single source
- *
+ *
* - ResourceLoader::makeLoaderSourcesScript( array( $id1 => $props1, $id2 => $props2, ... ) );
* Register sources with the given IDs and properties.
- *
+ *
* @param $id String: source ID
* @param $properties Array: source properties (see addSource())
*
$query = self::makeLoaderQuery( $modules, $lang, $skin, $user, $version, $debug,
$only, $printable, $handheld, $extraQuery
);
-
+
// Prevent the IE6 extension check from being triggered (bug 28840)
// by appending a character that's invalid in Windows extensions ('*')
return wfExpandUrl( wfAppendQuery( $wgLoadScript, $query ) . '&*', PROTO_RELATIVE );
$query['handheld'] = 1;
}
$query += $extraQuery;
-
+
// Make queries uniform in order
ksort( $query );
return $query;
*/
/**
- * Object passed around to modules which contains information about the state
+ * Object passed around to modules which contains information about the state
* of a specific loader request
*/
class ResourceLoaderContext {
/* Methods */
+ /**
+ * @param $resourceLoader ResourceLoader
+ * @param $request WebRequest
+ */
public function __construct( $resourceLoader, WebRequest $request ) {
global $wgDefaultSkin, $wgResourceLoaderDebug;
$this->skin = $wgDefaultSkin;
}
}
-
+
/**
* Expand a string of the form jquery.foo,bar|jquery.ui.baz,quux to
* an array of module names like array( 'jquery.foo', 'jquery.bar',
}
return $retval;
}
-
+
/**
* Return a dummy ResourceLoaderContext object suitable for passing into things that don't "really" need a context
+ * @return ResourceLoaderContext
*/
public static function newDummyContext() {
return new self( null, new FauxRequest( array() ) );
public function getHash() {
if ( !isset( $this->hash ) ) {
$this->hash = implode( '|', array(
- $this->getLanguage(), $this->getDirection(), $this->skin, $this->user,
+ $this->getLanguage(), $this->getDirection(), $this->skin, $this->user,
$this->debug, $this->only, $this->version
) );
}
$files = $this->getScriptFiles( $context );
return $this->readScriptFiles( $files );
}
-
+
+ /**
+ * @param $context ResourceLoaderContext
+ * @return array
+ */
public function getScriptURLsForDebug( ResourceLoaderContext $context ) {
$urls = array();
foreach ( $this->getScriptFiles( $context ) as $file ) {
return $urls;
}
+ /**
+ * @return bool
+ */
public function supportsURLLoading() {
return $this->debugRaw;
}
return $styles;
}
+ /**
+ * @param $context ResourceLoaderContext
+ * @return array
+ */
public function getStyleURLsForDebug( ResourceLoaderContext $context ) {
$urls = array();
foreach ( $this->getStyleFiles( $context ) as $mediaType => $list ) {
$style, $dir, $remoteDir, true
);
}
-
+
/**
* Safe version of filemtime(), which doesn't throw a PHP warning if the file doesn't exist
* but returns 1 instead.
<?php
-/*
+/**
* ResourceLoader definition for MediaWiki:Filepage.css
*/
class ResourceLoaderFilePageModule extends ResourceLoaderWikiModule {
+
+ /**
+ * @param $context ResourceLoaderContext
+ * @return array
+ */
protected function getPages( ResourceLoaderContext $context ) {
return array(
'MediaWiki:Filepage.css' => array( 'type' => 'style' ),
# limit the types of scripts and styles we allow to load on, say, sensitive special
# pages like Special:UserLogin and Special:Preferences
protected $origin = self::ORIGIN_CORE_SITEWIDE;
-
+
/* Protected Members */
protected $name = null;
-
+
// In-object cache for file dependencies
protected $fileDeps = array();
// In-object cache for message blob mtime
// Stub, override expected
return '';
}
-
+
/**
* Get the URL or URLs to load for this module's JS in debug mode.
* The default behavior is to return a load.php?only=scripts URL for
* the module, but file-based modules will want to override this to
* load the files directly.
- *
+ *
* This function is called only when 1) we're in debug mode, 2) there
* is no only= parameter and 3) supportsURLLoading() returns true.
* #2 is important to prevent an infinite loop, therefore this function
* MUST return either an only= URL or a non-load.php URL.
- *
+ *
* @param $context ResourceLoaderContext: Context object
* @return Array of URLs
*/
);
return array( $url );
}
-
+
/**
* Whether this module supports URL loading. If this function returns false,
* getScript() will be used even in cases (debug mode, no only param) where
// Stub, override expected
return array();
}
-
+
/**
* Get the URL or URLs to load for this module's CSS in debug mode.
* The default behavior is to return a load.php?only=styles URL for
* the module, but file-based modules will want to override this to
* load the files directly. See also getScriptURLsForDebug()
- *
+ *
* @param $context ResourceLoaderContext: Context object
* @return Array: array( mediaType => array( URL1, URL2, ... ), ... )
*/
// Stub, override expected
return array();
}
-
+
/**
* Get the group this module is in.
- *
+ *
* @return String: Group name
*/
public function getGroup() {
/**
* Get the origin of this module. Should only be overridden for foreign modules.
- *
+ *
* @return String: Origin name, 'local' for local modules
*/
public function getSource() {
// Stub, override expected
return 'local';
}
-
+
/**
* Where on the HTML page should this module's JS be loaded?
* 'top': in the <head>
// Stub, override expected
return array();
}
-
+
/**
* Get the files this module depends on indirectly for a given skin.
* Currently these are only image files referenced by the module's CSS.
}
return $this->fileDeps[$skin];
}
-
+
/**
* Set preloaded file dependency information. Used so we can load this
* information for all modules at once.
public function setFileDependencies( $skin, $deps ) {
$this->fileDeps[$skin] = $deps;
}
-
+
/**
* Get the last modification timestamp of the message blob for this
* module in a given language.
if ( !isset( $this->msgBlobMtime[$lang] ) ) {
if ( !count( $this->getMessages() ) )
return 0;
-
+
$dbr = wfGetDB( DB_SLAVE );
$msgBlobMtime = $dbr->selectField( 'msg_resource', 'mr_timestamp', array(
'mr_resource' => $this->getName(),
}
return $this->msgBlobMtime[$lang];
}
-
+
/**
* Set a preloaded message blob last modification timestamp. Used so we
* can load this information for all modules at once.
public function setMsgBlobMtime( $lang, $mtime ) {
$this->msgBlobMtime[$lang] = $mtime;
}
-
+
/* Abstract Methods */
-
+
/**
* Get this module's last modification timestamp for a given
* combination of language, skin and debug mode flag. This is typically
// 0 would mean now
return 1;
}
-
+
/**
* Check whether this module is known to be empty. If a child class
* has an easy and cheap way to determine that this module is
$err = $e->getMessage();
$result = "throw new Error(" . Xml::encodeJsVar("JavaScript parse error: $err") . ");";
}
-
+
$cache->set( $key, $result );
return $result;
} else {
}
}
+ /**
+ * @return JSParser
+ */
protected static function javaScriptParser() {
if ( !self::$jsParser ) {
self::$jsParser = new JSParser();
return $out;
}
+ /**
+ * @return bool
+ */
public function supportsURLLoading() {
return false;
}
$username = $context->getUser();
$userpageTitle = Title::makeTitleSafe( NS_USER, $username );
$userpage = $userpageTitle->getPrefixedDBkey(); // Needed so $excludepages works
-
+
$pages = array(
"$userpage/common.js" => array( 'type' => 'script' ),
- "$userpage/" . $context->getSkin() . '.js' =>
+ "$userpage/" . $context->getSkin() . '.js' =>
array( 'type' => 'script' ),
"$userpage/common.css" => array( 'type' => 'style' ),
- "$userpage/" . $context->getSkin() . '.css' =>
+ "$userpage/" . $context->getSkin() . '.css' =>
array( 'type' => 'style' ),
);
-
+
// Hack for bug 26283: if we're on a preview page for a CSS/JS page,
// we need to exclude that page from this module. In that case, the excludepage
// parameter will be set to the name of the page we need to exclude.
/**
* Fetch the context's user options, or if it doesn't match current user,
* the default options.
- *
+ *
* @param $context ResourceLoaderContext: Context object
* @return Array: List of user options keyed by option name
*/
* @return string
*/
public function getScript( ResourceLoaderContext $context ) {
- return Xml::encodeJsCall( 'mw.user.options.set',
+ return Xml::encodeJsCall( 'mw.user.options.set',
array( $this->contextUserOptions( $context ) ) );
}
// Underline: 2 = browser default, 1 = always, 0 = never
if ( $options['underline'] < 2 ) {
- $rules[] = "a { text-decoration: " .
+ $rules[] = "a { text-decoration: " .
( $options['underline'] ? 'underline !important' : 'none' ) . "; }";
}
if ( $options['highlightbroken'] ) {
public function getGroup() {
return 'private';
}
-
+
+ /**
+ * @return array
+ */
public function getDependencies() {
return array( 'mediawiki.user' );
}
/**
* Fetch the tokens for the current user.
- *
+ *
* @param $context ResourceLoaderContext: Context object
* @return Array: List of tokens keyed by token type
*/
* @return string
*/
public function getScript( ResourceLoaderContext $context ) {
- return Xml::encodeJsCall( 'mw.user.tokens.set',
+ return Xml::encodeJsCall( 'mw.user.tokens.set',
array( $this->contextUserTokens( $context ) ) );
}
public function getGroup() {
return 'private';
}
-
+
+ /**
+ * @return array
+ */
public function getDependencies() {
return array( 'mediawiki.user' );
}
/**
* Abstraction for resource loader modules which pull from wiki pages
- *
- * This can only be used for wiki pages in the MediaWiki and User namespaces,
- * because of its dependence on the functionality of
+ *
+ * This can only be used for wiki pages in the MediaWiki and User namespaces,
+ * because of its dependence on the functionality of
* Title::isValidCssJsSubpage.
*/
abstract class ResourceLoaderWikiModule extends ResourceLoaderModule {
-
+
/* Protected Members */
# Origin is user-supplied code
protected $origin = self::ORIGIN_USER_SITEWIDE;
-
+
// In-object cache for title mtimes
protected $titleMtimes = array();
-
+
/* Abstract Protected Methods */
-
+
+ /**
+ * @abstract
+ * @param $context ResourceLoaderContext
+ */
abstract protected function getPages( ResourceLoaderContext $context );
-
+
/* Protected Methods */
-
+
/**
* Get the Database object used in getTitleMTimes(). Defaults to the local slave DB
* but subclasses may want to override this to return a remote DB object.
- *
+ *
* NOTE: This ONLY works for getTitleMTimes() and getModifiedTime(), NOT FOR ANYTHING ELSE.
* In particular, it doesn't work for getting the content of JS and CSS pages. That functionality
* will use the local DB irrespective of the return value of this method.
- *
+ *
* @return DatabaseBase
*/
protected function getDB() {
}
return $revision->getRawText();
}
-
+
/* Methods */
/**
*/
public function getStyles( ResourceLoaderContext $context ) {
global $wgScriptPath;
-
+
$styles = array();
foreach ( $this->getPages( $context ) as $titleText => $options ) {
if ( $options['type'] !== 'style' ) {
$title = Title::newFromText( $titleText );
if ( !$title || $title->isRedirect() ) {
continue;
- }
+ }
$media = isset( $options['media'] ) ? $options['media'] : 'all';
$style = $this->getContent( $title );
if ( strval( $style ) === '' ) {
if ( isset( $this->titleMtimes[$hash] ) ) {
return $this->titleMtimes[$hash];
}
-
+
$this->titleMtimes[$hash] = array();
$batch = new LinkBatch;
foreach ( $this->getPages( $context ) as $titleText => $options ) {
$batch->addObj( Title::newFromText( $titleText ) );
}
-
+
if ( !$batch->isEmpty() ) {
$dbr = $this->getDB();
$res = $dbr->select( 'page',