summaryrefslogtreecommitdiff
path: root/includes/resourceloader
diff options
context:
space:
mode:
Diffstat (limited to 'includes/resourceloader')
-rw-r--r--includes/resourceloader/ResourceLoader.php93
-rw-r--r--includes/resourceloader/ResourceLoaderContext.php18
-rw-r--r--includes/resourceloader/ResourceLoaderFileModule.php139
-rw-r--r--includes/resourceloader/ResourceLoaderLanguageDataModule.php34
-rw-r--r--includes/resourceloader/ResourceLoaderModule.php56
-rw-r--r--includes/resourceloader/ResourceLoaderNoscriptModule.php2
-rw-r--r--includes/resourceloader/ResourceLoaderSiteModule.php6
-rw-r--r--includes/resourceloader/ResourceLoaderStartUpModule.php55
-rw-r--r--includes/resourceloader/ResourceLoaderUserCSSPrefsModule.php2
-rw-r--r--includes/resourceloader/ResourceLoaderUserTokensModule.php3
-rw-r--r--includes/resourceloader/ResourceLoaderWikiModule.php36
11 files changed, 260 insertions, 184 deletions
diff --git a/includes/resourceloader/ResourceLoader.php b/includes/resourceloader/ResourceLoader.php
index 7b87f9d4..27f682c2 100644
--- a/includes/resourceloader/ResourceLoader.php
+++ b/includes/resourceloader/ResourceLoader.php
@@ -39,7 +39,7 @@ class ResourceLoader {
/** Associative array mapping module name to info associative array */
protected $moduleInfos = array();
-
+
/** Associative array mapping framework ids to a list of names of test suite modules */
/** like array( 'qunit' => array( 'mediawiki.tests.qunit.suites', 'ext.foo.tests', .. ), .. ) */
protected $testModuleNames = array();
@@ -60,7 +60,7 @@ class ResourceLoader {
* requests its own information. This sacrifice of modularity yields a substantial
* performance improvement.
*
- * @param $modules Array: List of module names to preload information for
+ * @param array $modules List of module names to preload information for
* @param $context ResourceLoaderContext: Context to load the information within
*/
public function preloadModuleInfo( array $modules, ResourceLoaderContext $context ) {
@@ -127,8 +127,8 @@ class ResourceLoader {
* If $data is empty, only contains whitespace or the filter was unknown,
* $data is returned unmodified.
*
- * @param $filter String: Name of filter to run
- * @param $data String: Text to filter, such as JavaScript or CSS text
+ * @param string $filter Name of filter to run
+ * @param string $data Text to filter, such as JavaScript or CSS text
* @return String: Filtered data, or a comment containing an error message
*/
protected function filter( $filter, $data ) {
@@ -210,7 +210,6 @@ class ResourceLoader {
$this->registerTestModules();
}
-
wfProfileOut( __METHOD__ );
}
@@ -218,7 +217,7 @@ class ResourceLoader {
* Registers a module with the ResourceLoader system.
*
* @param $name Mixed: Name of module as a string or List of name/object pairs as an array
- * @param $info array Module info array. For backwards compatibility with 1.17alpha,
+ * @param array $info Module info array. For backwards compatibility with 1.17alpha,
* this may also be a ResourceLoaderModule object. Optional when using
* multiple-registration calling style.
* @throws MWException: If a duplicate module registration is attempted
@@ -309,7 +308,8 @@ class ResourceLoader {
* '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
+ * @param array $properties source properties
+ * @throws MWException
*/
public function addSource( $id, $properties = null) {
// Allow multiple sources to be registered in one call
@@ -346,13 +346,13 @@ class ResourceLoader {
public function getModuleNames() {
return array_keys( $this->moduleInfos );
}
-
- /**
+
+ /**
* Get a list of test module names for one (or all) frameworks.
* If the given framework id is unknkown, or if the in-object variable is not an array,
* then it will return an empty array.
*
- * @param $framework String: Optional. Get only the test module names for one
+ * @param string $framework Optional. Get only the test module names for one
* particular framework.
* @return Array
*/
@@ -370,7 +370,7 @@ class ResourceLoader {
/**
* Get the ResourceLoaderModule object for a given module name.
*
- * @param $name String: Module name
+ * @param string $name Module name
* @return ResourceLoaderModule if module has been registered, null otherwise
*/
public function getModule( $name ) {
@@ -450,7 +450,7 @@ class ResourceLoader {
$this->hasErrors = true;
continue;
}
- $modules[$name] = $this->getModule( $name );
+ $modules[$name] = $module;
} else {
$missing[] = $name;
}
@@ -530,8 +530,8 @@ class ResourceLoader {
/**
* Send content type and last modified headers to the client.
* @param $context ResourceLoaderContext
- * @param $mtime string TS_MW timestamp to use for last-modified
- * @param $error bool Whether there are commented-out errors in the response
+ * @param string $mtime TS_MW timestamp to use for last-modified
+ * @param bool $error Whether there are commented-out errors in the response
* @return void
*/
protected function sendResponseHeaders( ResourceLoaderContext $context, $mtime, $errors ) {
@@ -540,12 +540,12 @@ class ResourceLoader {
// to propagate to clients quickly
// If there were errors, we also need a shorter expiry time so we can recover quickly
if ( is_null( $context->getVersion() ) || $errors ) {
- $maxage = $wgResourceLoaderMaxage['unversioned']['client'];
+ $maxage = $wgResourceLoaderMaxage['unversioned']['client'];
$smaxage = $wgResourceLoaderMaxage['unversioned']['server'];
// If a version was specified we can use a longer expiry time since changing
// version numbers causes cache misses
} else {
- $maxage = $wgResourceLoaderMaxage['versioned']['client'];
+ $maxage = $wgResourceLoaderMaxage['versioned']['client'];
$smaxage = $wgResourceLoaderMaxage['versioned']['server'];
}
if ( $context->getOnly() === 'styles' ) {
@@ -569,7 +569,7 @@ class ResourceLoader {
* If there's an If-Modified-Since header, respond with a 304 appropriately
* and clear out the output buffer. If the client cache is too old then do nothing.
* @param $context ResourceLoaderContext
- * @param $mtime string The TS_MW timestamp to check the header against
+ * @param string $mtime The TS_MW timestamp to check the header against
* @return bool True iff 304 header sent and output handled
*/
protected function tryRespondLastModified( ResourceLoaderContext $context, $mtime ) {
@@ -666,8 +666,8 @@ class ResourceLoader {
* Generates code for a response
*
* @param $context ResourceLoaderContext: Context in which to generate a response
- * @param $modules Array: List of module objects keyed by module name
- * @param $missing Array: List of unavailable modules (optional)
+ * @param array $modules List of module objects keyed by module name
+ * @param array $missing List of unavailable modules (optional)
* @return String: Response data
*/
public function makeModuleResponse( ResourceLoaderContext $context,
@@ -834,7 +834,7 @@ class ResourceLoader {
* Returns JS code to call to mw.loader.implement for a module with
* given properties.
*
- * @param $name string Module name
+ * @param string $name Module name
* @param $scripts Mixed: List of URLs to JavaScript files or String of JavaScript code
* @param $styles Mixed: Array of CSS strings keyed by media type, or an array of lists of URLs to
* CSS files keyed by media type
@@ -842,6 +842,7 @@ class ResourceLoader {
* associative array mapping message key to value, or a JSON-encoded message blob containing
* the same data, wrapped in an XmlJsCode object.
*
+ * @throws MWException
* @return string
*/
public static function makeLoaderImplementScript( $name, $scripts, $styles, $messages ) {
@@ -881,7 +882,7 @@ class ResourceLoader {
* Combines an associative array mapping media type to CSS into a
* single stylesheet with "@media" blocks.
*
- * @param $styles Array: Array keyed by media type containing (arrays of) CSS strings.
+ * @param array $stylePairs Array keyed by media type containing (arrays of) CSS strings.
*
* @return Array
*/
@@ -941,12 +942,12 @@ class ResourceLoader {
* which will have values corresponding to $name, $version, $dependencies
* and $group as supplied.
*
- * @param $name String: Module name
+ * @param string $name Module name
* @param $version Integer: Module version number as a timestamp
- * @param $dependencies Array: List of module names on which this module depends
- * @param $group String: Group which the module is in.
- * @param $source String: Source of the module, or 'local' if not foreign.
- * @param $script String: JavaScript code
+ * @param array $dependencies List of module names on which this module depends
+ * @param string $group Group which the module is in.
+ * @param string $source Source of the module, or 'local' if not foreign.
+ * @param string $script JavaScript code
*
* @return string
*/
@@ -974,11 +975,11 @@ class ResourceLoader {
* ) ):
* Registers modules with the given names and parameters.
*
- * @param $name String: Module name
+ * @param string $name Module name
* @param $version Integer: Module version number as a timestamp
- * @param $dependencies Array: List of module names on which this module depends
- * @param $group String: group which the module is in.
- * @param $source String: source of the module, or 'local' if not foreign
+ * @param array $dependencies List of module names on which this module depends
+ * @param string $group group which the module is in.
+ * @param string $source source of the module, or 'local' if not foreign
*
* @return string
*/
@@ -1004,8 +1005,8 @@ class ResourceLoader {
* - 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())
+ * @param string $id source ID
+ * @param array $properties source properties (see addSource())
*
* @return string
*/
@@ -1021,7 +1022,7 @@ class ResourceLoader {
* Returns JS code which runs given JS code if the client-side framework is
* present.
*
- * @param $script String: JavaScript code
+ * @param string $script JavaScript code
*
* @return string
*/
@@ -1033,7 +1034,7 @@ class ResourceLoader {
* Returns JS code which will set the MediaWiki configuration array to
* the given value.
*
- * @param $configuration Array: List of configuration values keyed by variable name
+ * @param array $configuration List of configuration values keyed by variable name
*
* @return string
*/
@@ -1046,7 +1047,7 @@ class ResourceLoader {
*
* For example, array( 'foo.bar', 'foo.baz', 'bar.baz', 'bar.quux' )
* becomes 'foo.bar,baz|bar.baz,quux'
- * @param $modules array of module names (strings)
+ * @param array $modules of module names (strings)
* @return string Packed query string
*/
public static function makePackedModulesString( $modules ) {
@@ -1084,16 +1085,16 @@ class ResourceLoader {
/**
* Build a load.php URL
- * @param $modules array of module names (strings)
- * @param $lang string Language code
- * @param $skin string Skin name
- * @param $user string|null User name. If null, the &user= parameter is omitted
- * @param $version string|null Versioning timestamp
- * @param $debug bool Whether the request should be in debug mode
- * @param $only string|null &only= parameter
- * @param $printable bool Printable mode
- * @param $handheld bool Handheld mode
- * @param $extraQuery array Extra query parameters to add
+ * @param array $modules of module names (strings)
+ * @param string $lang Language code
+ * @param string $skin Skin name
+ * @param string|null $user User name. If null, the &user= parameter is omitted
+ * @param string|null $version Versioning timestamp
+ * @param bool $debug Whether the request should be in debug mode
+ * @param string|null $only &only= parameter
+ * @param bool $printable Printable mode
+ * @param bool $handheld Handheld mode
+ * @param array $extraQuery Extra query parameters to add
* @return string URL to load.php. May be protocol-relative (if $wgLoadScript is procol-relative)
*/
public static function makeLoaderURL( $modules, $lang, $skin, $user = null, $version = null, $debug = false, $only = null,
@@ -1149,7 +1150,7 @@ class ResourceLoader {
* Module names may not contain pipes (|), commas (,) or exclamation marks (!) and can be
* at most 255 bytes.
*
- * @param $moduleName string Module name to check
+ * @param string $moduleName Module name to check
* @return bool Whether $moduleName is a valid module name
*/
public static function isValidModuleName( $moduleName ) {
diff --git a/includes/resourceloader/ResourceLoaderContext.php b/includes/resourceloader/ResourceLoaderContext.php
index 0e96c6c8..4588015f 100644
--- a/includes/resourceloader/ResourceLoaderContext.php
+++ b/includes/resourceloader/ResourceLoaderContext.php
@@ -58,14 +58,14 @@ class ResourceLoaderContext {
// Interpret request
// List of modules
$modules = $request->getVal( 'modules' );
- $this->modules = $modules ? self::expandModuleNames( $modules ) : array();
+ $this->modules = $modules ? self::expandModuleNames( $modules ) : array();
// Various parameters
- $this->skin = $request->getVal( 'skin' );
- $this->user = $request->getVal( 'user' );
- $this->debug = $request->getFuzzyBool( 'debug', $wgResourceLoaderDebug );
- $this->only = $request->getVal( 'only' );
- $this->version = $request->getVal( 'version' );
- $this->raw = $request->getFuzzyBool( 'raw' );
+ $this->skin = $request->getVal( 'skin' );
+ $this->user = $request->getVal( 'user' );
+ $this->debug = $request->getFuzzyBool( 'debug', $wgResourceLoaderDebug );
+ $this->only = $request->getVal( 'only' );
+ $this->version = $request->getVal( 'version' );
+ $this->raw = $request->getFuzzyBool( 'raw' );
$skinnames = Skin::getSkinNames();
// If no skin is specified, or we don't recognize the skin, use the default skin
@@ -78,7 +78,7 @@ class ResourceLoaderContext {
* 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',
* 'jquery.ui.baz', 'jquery.ui.quux' )
- * @param $modules String Packed module name list
+ * @param string $modules Packed module name list
* @return array of module names
*/
public static function expandModuleNames( $modules ) {
@@ -145,7 +145,7 @@ class ResourceLoaderContext {
public function getLanguage() {
if ( $this->language === null ) {
global $wgLang;
- $this->language = $this->request->getVal( 'lang' );
+ $this->language = $this->request->getVal( 'lang' );
if ( !$this->language ) {
$this->language = $wgLang->getCode();
}
diff --git a/includes/resourceloader/ResourceLoaderFileModule.php b/includes/resourceloader/ResourceLoaderFileModule.php
index 8b9b7277..cedb5dcc 100644
--- a/includes/resourceloader/ResourceLoaderFileModule.php
+++ b/includes/resourceloader/ResourceLoaderFileModule.php
@@ -113,6 +113,8 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
protected $debugRaw = true;
/** Boolean: Whether mw.loader.state() call should be omitted */
protected $raw = false;
+ protected $targets = array( 'desktop' );
+
/**
* Array: Cache for mtime
* @par Usage:
@@ -135,52 +137,53 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
/**
* Constructs a new module from an options array.
*
- * @param $options Array: List of options; if not given or empty, an empty module will be
+ * @param array $options List of options; if not given or empty, an empty module will be
* constructed
- * @param $localBasePath String: Base path to prepend to all local paths in $options. Defaults
+ * @param string $localBasePath Base path to prepend to all local paths in $options. Defaults
* to $IP
- * @param $remoteBasePath String: Base path to prepend to all remote paths in $options. Defaults
+ * @param string $remoteBasePath Base path to prepend to all remote paths in $options. Defaults
* to $wgScriptPath
*
* Below is a description for the $options array:
+ * @throws MWException
* @par Construction options:
* @code
- * array(
- * // Base path to prepend to all local paths in $options. Defaults to $IP
- * 'localBasePath' => [base path],
- * // Base path to prepend to all remote paths in $options. Defaults to $wgScriptPath
- * 'remoteBasePath' => [base path],
- * // Equivalent of remoteBasePath, but relative to $wgExtensionAssetsPath
- * 'remoteExtPath' => [base path],
- * // Scripts to always include
- * 'scripts' => [file path string or array of file path strings],
- * // Scripts to include in specific language contexts
- * 'languageScripts' => array(
- * [language code] => [file path string or array of file path strings],
- * ),
- * // Scripts to include in specific skin contexts
- * 'skinScripts' => array(
- * [skin name] => [file path string or array of file path strings],
- * ),
- * // Scripts to include in debug contexts
- * 'debugScripts' => [file path string or array of file path strings],
- * // Scripts to include in the startup module
- * 'loaderScripts' => [file path string or array of file path strings],
- * // Modules which must be loaded before this module
- * 'dependencies' => [modile name string or array of module name strings],
- * // Styles to always load
- * 'styles' => [file path string or array of file path strings],
- * // Styles to include in specific skin contexts
- * 'skinStyles' => array(
- * [skin name] => [file path string or array of file path strings],
- * ),
- * // Messages to always load
- * 'messages' => [array of message key strings],
- * // Group which this module should be loaded together with
- * 'group' => [group name string],
- * // Position on the page to load this module at
- * 'position' => ['bottom' (default) or 'top']
- * )
+ * array(
+ * // Base path to prepend to all local paths in $options. Defaults to $IP
+ * 'localBasePath' => [base path],
+ * // Base path to prepend to all remote paths in $options. Defaults to $wgScriptPath
+ * 'remoteBasePath' => [base path],
+ * // Equivalent of remoteBasePath, but relative to $wgExtensionAssetsPath
+ * 'remoteExtPath' => [base path],
+ * // Scripts to always include
+ * 'scripts' => [file path string or array of file path strings],
+ * // Scripts to include in specific language contexts
+ * 'languageScripts' => array(
+ * [language code] => [file path string or array of file path strings],
+ * ),
+ * // Scripts to include in specific skin contexts
+ * 'skinScripts' => array(
+ * [skin name] => [file path string or array of file path strings],
+ * ),
+ * // Scripts to include in debug contexts
+ * 'debugScripts' => [file path string or array of file path strings],
+ * // Scripts to include in the startup module
+ * 'loaderScripts' => [file path string or array of file path strings],
+ * // Modules which must be loaded before this module
+ * 'dependencies' => [module name string or array of module name strings],
+ * // Styles to always load
+ * 'styles' => [file path string or array of file path strings],
+ * // Styles to include in specific skin contexts
+ * 'skinStyles' => array(
+ * [skin name] => [file path string or array of file path strings],
+ * ),
+ * // Messages to always load
+ * 'messages' => [array of message key strings],
+ * // Group which this module should be loaded together with
+ * 'group' => [group name string],
+ * // Position on the page to load this module at
+ * 'position' => ['bottom' (default) or 'top']
+ * )
* @endcode
*/
public function __construct( $options = array(), $localBasePath = null,
@@ -231,6 +234,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
// Lists of strings
case 'dependencies':
case 'messages':
+ case 'targets':
$this->{$member} = (array) $option;
break;
// Single strings
@@ -437,9 +441,9 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
return $this->modifiedTime[$context->getHash()] = 1;
}
- wfProfileIn( __METHOD__.'-filemtime' );
+ wfProfileIn( __METHOD__ . '-filemtime' );
$filesMtime = max( array_map( array( __CLASS__, 'safeFilemtime' ), $files ) );
- wfProfileOut( __METHOD__.'-filemtime' );
+ wfProfileOut( __METHOD__ . '-filemtime' );
$this->modifiedTime[$context->getHash()] = max(
$filesMtime,
$this->getMsgBlobMtime( $context->getLanguage() ) );
@@ -469,9 +473,9 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
/**
* Collates file paths by option (where provided).
*
- * @param $list Array: List of file paths in any combination of index/path
+ * @param array $list List of file paths in any combination of index/path
* or path/options pairs
- * @param $option String: option name
+ * @param string $option option name
* @param $default Mixed: default value if the option isn't set
* @return Array: List of file paths, collated by $option
*/
@@ -499,9 +503,9 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
/**
* Gets a list of element that match a key, optionally using a fallback key.
*
- * @param $list Array: List of lists to select from
- * @param $key String: Key to look for in $map
- * @param $fallback String: Key to look for in $list if $key doesn't exist
+ * @param array $list List of lists to select from
+ * @param string $key Key to look for in $map
+ * @param string $fallback Key to look for in $list if $key doesn't exist
* @return Array: List of elements from $map which matched $key or $fallback,
* or an empty list in case of no match
*/
@@ -532,7 +536,8 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
if ( $context->getDebug() ) {
$files = array_merge( $files, $this->debugScripts );
}
- return $files;
+
+ return array_unique( $files );
}
/**
@@ -553,7 +558,8 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
/**
* Gets the contents of a list of JavaScript files.
*
- * @param $scripts Array: List of file paths to scripts to read, remap and concetenate
+ * @param array $scripts List of file paths to scripts to read, remap and concetenate
+ * @throws MWException
* @return String: Concatenated and remapped JavaScript data from $scripts
*/
protected function readScriptFiles( array $scripts ) {
@@ -565,7 +571,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
foreach ( array_unique( $scripts ) as $fileName ) {
$localPath = $this->getLocalPath( $fileName );
if ( !file_exists( $localPath ) ) {
- throw new MWException( __METHOD__.": script file not found: \"$localPath\"" );
+ throw new MWException( __METHOD__ . ": script file not found: \"$localPath\"" );
}
$contents = file_get_contents( $localPath );
if ( $wgResourceLoaderValidateStaticJS ) {
@@ -582,7 +588,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
/**
* Gets the contents of a list of CSS files.
*
- * @param $styles Array: List of media type/list of file paths pairs, to read, remap and
+ * @param array $styles List of media type/list of file paths pairs, to read, remap and
* concetenate
*
* @param $flip bool
@@ -613,7 +619,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
*
* This method can be used as a callback for array_map()
*
- * @param $path String: File path of style file to read
+ * @param string $path File path of style file to read
* @param $flip bool
*
* @return String: CSS data in script file
@@ -622,7 +628,9 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
protected function readStyleFile( $path, $flip ) {
$localPath = $this->getLocalPath( $path );
if ( !file_exists( $localPath ) ) {
- throw new MWException( __METHOD__.": style file not found: \"$localPath\"" );
+ $msg = __METHOD__ . ": style file not found: \"$localPath\"";
+ wfDebugLog( 'resourceloader', $msg );
+ throw new MWException( $msg );
}
$style = file_get_contents( $localPath );
if ( $flip ) {
@@ -646,23 +654,6 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
}
/**
- * Safe version of filemtime(), which doesn't throw a PHP warning if the file doesn't exist
- * but returns 1 instead.
- * @param $filename string File name
- * @return int UNIX timestamp, or 1 if the file doesn't exist
- */
- protected static function safeFilemtime( $filename ) {
- if ( file_exists( $filename ) ) {
- return filemtime( $filename );
- } else {
- // We only ever map this function on an array if we're gonna call max() after,
- // so return our standard minimum timestamps here. This is 1, not 0, because
- // wfTimestamp(0) == NOW
- return 1;
- }
- }
-
- /**
* Get whether CSS for this module should be flipped
* @param $context ResourceLoaderContext
* @return bool
@@ -670,4 +661,14 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
public function getFlip( $context ) {
return $context->getDirection() === 'rtl';
}
+
+ /**
+ * Get target(s) for the module, eg ['desktop'] or ['desktop', 'mobile']
+ *
+ * @return array of strings
+ */
+ public function getTargets() {
+ return $this->targets;
+ }
+
}
diff --git a/includes/resourceloader/ResourceLoaderLanguageDataModule.php b/includes/resourceloader/ResourceLoaderLanguageDataModule.php
index c916c4a5..0f8e54ce 100644
--- a/includes/resourceloader/ResourceLoaderLanguageDataModule.php
+++ b/includes/resourceloader/ResourceLoaderLanguageDataModule.php
@@ -28,6 +28,7 @@
class ResourceLoaderLanguageDataModule extends ResourceLoaderModule {
protected $language;
+ protected $targets = array( 'desktop', 'mobile' );
/**
* Get the grammar forms for the site content language.
*
@@ -47,24 +48,35 @@ class ResourceLoaderLanguageDataModule extends ResourceLoaderModule {
}
/**
+ * Get the digit groupin Pattern for the site content language.
+ *
+ * @return array
+ */
+ protected function getDigitGroupingPattern() {
+ return $this->language->digitGroupingPattern();
+ }
+
+ /**
* Get the digit transform table for the content language
- * Seperator transform table also required here to convert
- * the . and , sign to appropriate forms in content language.
*
* @return array
*/
protected function getDigitTransformTable() {
- $digitTransformTable = $this->language->digitTransformTable();
- $separatorTransformTable = $this->language->separatorTransformTable();
- if ( $digitTransformTable ) {
- array_merge( $digitTransformTable, (array)$separatorTransformTable );
- } else {
- return $separatorTransformTable;
- }
- return $digitTransformTable;
+ return $this->language->digitTransformTable();
}
/**
+ * Get seperator transform table required for converting
+ * the . and , sign to appropriate forms in site content language.
+ *
+ * @return array
+ */
+ protected function getSeparatorTransformTable() {
+ return $this->language->separatorTransformTable();
+ }
+
+
+ /**
* Get all the dynamic data for the content language to an array
*
* @return array
@@ -72,8 +84,10 @@ class ResourceLoaderLanguageDataModule extends ResourceLoaderModule {
protected function getData() {
return array(
'digitTransformTable' => $this->getDigitTransformTable(),
+ 'separatorTransformTable' => $this->getSeparatorTransformTable(),
'grammarForms' => $this->getSiteLangGrammarForms(),
'pluralRules' => $this->getPluralRules(),
+ 'digitGroupingPattern' => $this->getDigitGroupingPattern(),
);
}
diff --git a/includes/resourceloader/ResourceLoaderModule.php b/includes/resourceloader/ResourceLoaderModule.php
index 9c49c45f..03f3cc37 100644
--- a/includes/resourceloader/ResourceLoaderModule.php
+++ b/includes/resourceloader/ResourceLoaderModule.php
@@ -58,6 +58,7 @@ abstract class ResourceLoaderModule {
/* Protected Members */
protected $name = null;
+ protected $targets = array( 'desktop' );
// In-object cache for file dependencies
protected $fileDeps = array();
@@ -77,10 +78,10 @@ abstract class ResourceLoaderModule {
}
/**
- * Set this module's name. This is called by ResourceLodaer::register()
+ * Set this module's name. This is called by ResourceLoader::register()
* when registering the module. Other code should not call this.
*
- * @param $name String: Name
+ * @param string $name Name
*/
public function setName( $name ) {
$this->name = $name;
@@ -91,17 +92,17 @@ abstract class ResourceLoaderModule {
* with ResourceLoader::register()
*
* @return Int ResourceLoaderModule class constant, the subclass default
- * if not set manuall
+ * if not set manually
*/
public function getOrigin() {
return $this->origin;
}
/**
- * Set this module's origin. This is called by ResourceLodaer::register()
+ * Set this module's origin. This is called by ResourceLoader::register()
* when registering the module. Other code should not call this.
*
- * @param $origin Int origin
+ * @param int $origin origin
*/
public function setOrigin( $origin ) {
$this->origin = $origin;
@@ -290,10 +291,19 @@ abstract class ResourceLoaderModule {
}
/**
+ * Get target(s) for the module, eg ['desktop'] or ['desktop', 'mobile']
+ *
+ * @return array of strings
+ */
+ public function getTargets() {
+ return $this->targets;
+ }
+
+ /**
* Get the files this module depends on indirectly for a given skin.
* Currently these are only image files referenced by the module's CSS.
*
- * @param $skin String: Skin name
+ * @param string $skin Skin name
* @return Array: List of files
*/
public function getFileDependencies( $skin ) {
@@ -319,8 +329,8 @@ abstract class ResourceLoaderModule {
/**
* Set preloaded file dependency information. Used so we can load this
* information for all modules at once.
- * @param $skin String: Skin name
- * @param $deps Array: Array of file names
+ * @param string $skin Skin name
+ * @param array $deps Array of file names
*/
public function setFileDependencies( $skin, $deps ) {
$this->fileDeps[$skin] = $deps;
@@ -329,13 +339,14 @@ abstract class ResourceLoaderModule {
/**
* Get the last modification timestamp of the message blob for this
* module in a given language.
- * @param $lang String: Language code
+ * @param string $lang Language code
* @return Integer: UNIX timestamp, or 0 if the module doesn't have messages
*/
public function getMsgBlobMtime( $lang ) {
if ( !isset( $this->msgBlobMtime[$lang] ) ) {
- if ( !count( $this->getMessages() ) )
+ if ( !count( $this->getMessages() ) ) {
return 0;
+ }
$dbr = wfGetDB( DB_SLAVE );
$msgBlobMtime = $dbr->selectField( 'msg_resource', 'mr_timestamp', array(
@@ -356,7 +367,7 @@ abstract class ResourceLoaderModule {
/**
* Set a preloaded message blob last modification timestamp. Used so we
* can load this information for all modules at once.
- * @param $lang String: Language code
+ * @param string $lang Language code
* @param $mtime Integer: UNIX timestamp or 0 if there is no such blob
*/
public function setMsgBlobMtime( $lang, $mtime ) {
@@ -375,7 +386,7 @@ abstract class ResourceLoaderModule {
* NOTE: The mtime of the module's messages is NOT automatically included.
* If you want this to happen, you'll need to call getMsgBlobMtime()
* yourself and take its result into consideration.
- *
+ *
* @param $context ResourceLoaderContext: Context object
* @return Integer: UNIX timestamp
*/
@@ -397,7 +408,6 @@ abstract class ResourceLoaderModule {
return false;
}
-
/** @var JSParser lazy-initialized; use self::javaScriptParser() */
private static $jsParser;
private static $parseCacheVersion = 1;
@@ -426,10 +436,10 @@ abstract class ResourceLoaderModule {
try {
$parser->parse( $contents, $fileName, 1 );
$result = $contents;
- } catch (Exception $e) {
+ } catch ( Exception $e ) {
// We'll save this to cache to avoid having to validate broken JS over and over...
$err = $e->getMessage();
- $result = "throw new Error(" . Xml::encodeJsVar("JavaScript parse error: $err") . ");";
+ $result = "throw new Error(" . Xml::encodeJsVar( "JavaScript parse error: $err" ) . ");";
}
$cache->set( $key, $result );
@@ -449,4 +459,20 @@ abstract class ResourceLoaderModule {
return self::$jsParser;
}
+ /**
+ * Safe version of filemtime(), which doesn't throw a PHP warning if the file doesn't exist
+ * but returns 1 instead.
+ * @param string $filename File name
+ * @return int UNIX timestamp, or 1 if the file doesn't exist
+ */
+ protected static function safeFilemtime( $filename ) {
+ if ( file_exists( $filename ) ) {
+ return filemtime( $filename );
+ } else {
+ // We only ever map this function on an array if we're gonna call max() after,
+ // so return our standard minimum timestamps here. This is 1, not 0, because
+ // wfTimestamp(0) == NOW
+ return 1;
+ }
+ }
}
diff --git a/includes/resourceloader/ResourceLoaderNoscriptModule.php b/includes/resourceloader/ResourceLoaderNoscriptModule.php
index 8e81c8d9..bd026f3f 100644
--- a/includes/resourceloader/ResourceLoaderNoscriptModule.php
+++ b/includes/resourceloader/ResourceLoaderNoscriptModule.php
@@ -45,7 +45,7 @@ class ResourceLoaderNoscriptModule extends ResourceLoaderWikiModule {
/**
* Gets group name
- *
+ *
* @return String: Name of group
*/
public function getGroup() {
diff --git a/includes/resourceloader/ResourceLoaderSiteModule.php b/includes/resourceloader/ResourceLoaderSiteModule.php
index 03fe1fe5..1cc5c1a9 100644
--- a/includes/resourceloader/ResourceLoaderSiteModule.php
+++ b/includes/resourceloader/ResourceLoaderSiteModule.php
@@ -47,8 +47,8 @@ class ResourceLoaderSiteModule extends ResourceLoaderWikiModule {
'MediaWiki:Print.css' => array( 'type' => 'style', 'media' => 'print' ),
);
if ( $wgHandheldStyle ) {
- $pages['MediaWiki:Handheld.css'] = array(
- 'type' => 'style',
+ $pages['MediaWiki:Handheld.css'] = array(
+ 'type' => 'style',
'media' => 'handheld' );
}
return $pages;
@@ -58,7 +58,7 @@ class ResourceLoaderSiteModule extends ResourceLoaderWikiModule {
/**
* Gets group name
- *
+ *
* @return String: Name of group
*/
public function getGroup() {
diff --git a/includes/resourceloader/ResourceLoaderStartUpModule.php b/includes/resourceloader/ResourceLoaderStartUpModule.php
index 20ee83f9..32cf6b26 100644
--- a/includes/resourceloader/ResourceLoaderStartUpModule.php
+++ b/includes/resourceloader/ResourceLoaderStartUpModule.php
@@ -114,6 +114,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
$out = '';
$registrations = array();
$resourceLoader = $context->getResourceLoader();
+ $target = $context->getRequest()->getVal( 'target', 'desktop' );
// Register sources
$out .= ResourceLoader::makeLoaderSourcesScript( $resourceLoader->getSources() );
@@ -121,6 +122,10 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
// Register modules
foreach ( $resourceLoader->getModuleNames() as $name ) {
$module = $resourceLoader->getModule( $name );
+ $moduleTargets = $module->getTargets();
+ if ( !in_array( $target, $moduleTargets ) ) {
+ continue;
+ }
$deps = $module->getDependencies();
$group = $module->getGroup();
$source = $module->getSource();
@@ -130,33 +135,33 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
$version = wfTimestamp( TS_ISO_8601_BASIC,
$module->getModifiedTime( $context ) );
$out .= ResourceLoader::makeCustomLoaderScript( $name, $version, $deps, $group, $source, $loader );
+ continue;
}
+
// Automatically register module
+ // getModifiedTime() is supposed to return a UNIX timestamp, but it doesn't always
+ // seem to do that, and custom implementations might forget. Coerce it to TS_UNIX
+ $moduleMtime = wfTimestamp( TS_UNIX, $module->getModifiedTime( $context ) );
+ $mtime = max( $moduleMtime, wfTimestamp( TS_UNIX, $wgCacheEpoch ) );
+ // Modules without dependencies, a group or a foreign source pass two arguments (name, timestamp) to
+ // mw.loader.register()
+ if ( !count( $deps ) && $group === null && $source === 'local' ) {
+ $registrations[] = array( $name, $mtime );
+ }
+ // Modules with dependencies but no group or foreign source pass three arguments
+ // (name, timestamp, dependencies) to mw.loader.register()
+ elseif ( $group === null && $source === 'local' ) {
+ $registrations[] = array( $name, $mtime, $deps );
+ }
+ // Modules with a group but no foreign source pass four arguments (name, timestamp, dependencies, group)
+ // to mw.loader.register()
+ elseif ( $source === 'local' ) {
+ $registrations[] = array( $name, $mtime, $deps, $group );
+ }
+ // Modules with a foreign source pass five arguments (name, timestamp, dependencies, group, source)
+ // to mw.loader.register()
else {
- // getModifiedTime() is supposed to return a UNIX timestamp, but it doesn't always
- // seem to do that, and custom implementations might forget. Coerce it to TS_UNIX
- $moduleMtime = wfTimestamp( TS_UNIX, $module->getModifiedTime( $context ) );
- $mtime = max( $moduleMtime, wfTimestamp( TS_UNIX, $wgCacheEpoch ) );
- // Modules without dependencies, a group or a foreign source pass two arguments (name, timestamp) to
- // mw.loader.register()
- if ( !count( $deps ) && $group === null && $source === 'local' ) {
- $registrations[] = array( $name, $mtime );
- }
- // Modules with dependencies but no group or foreign source pass three arguments
- // (name, timestamp, dependencies) to mw.loader.register()
- elseif ( $group === null && $source === 'local' ) {
- $registrations[] = array( $name, $mtime, $deps );
- }
- // Modules with a group but no foreign source pass four arguments (name, timestamp, dependencies, group)
- // to mw.loader.register()
- elseif ( $source === 'local' ) {
- $registrations[] = array( $name, $mtime, $deps, $group );
- }
- // Modules with a foreign source pass five arguments (name, timestamp, dependencies, group, source)
- // to mw.loader.register()
- else {
- $registrations[] = array( $name, $mtime, $deps, $group, $source );
- }
+ $registrations[] = array( $name, $mtime, $deps, $group, $source );
}
}
$out .= ResourceLoader::makeLoaderRegisterScript( $registrations );
@@ -219,7 +224,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
"};\n";
// Conditional script injection
- $scriptTag = Html::linkedScript( $wgLoadScript . '?' . wfArrayToCGI( $query ) );
+ $scriptTag = Html::linkedScript( $wgLoadScript . '?' . wfArrayToCgi( $query ) );
$out .= "if ( isCompatible() ) {\n" .
"\t" . Xml::encodeJsCall( 'document.write', array( $scriptTag ) ) .
"}\n" .
diff --git a/includes/resourceloader/ResourceLoaderUserCSSPrefsModule.php b/includes/resourceloader/ResourceLoaderUserCSSPrefsModule.php
index 0e95d964..bdb240e0 100644
--- a/includes/resourceloader/ResourceLoaderUserCSSPrefsModule.php
+++ b/includes/resourceloader/ResourceLoaderUserCSSPrefsModule.php
@@ -48,7 +48,7 @@ class ResourceLoaderUserCSSPrefsModule extends ResourceLoaderModule {
global $wgUser;
return $this->modifiedTime[$hash] = wfTimestamp( TS_UNIX, $wgUser->getTouched() );
}
-
+
/**
* @param $context ResourceLoaderContext
* @return array
diff --git a/includes/resourceloader/ResourceLoaderUserTokensModule.php b/includes/resourceloader/ResourceLoaderUserTokensModule.php
index 62d096a6..6d787c50 100644
--- a/includes/resourceloader/ResourceLoaderUserTokensModule.php
+++ b/includes/resourceloader/ResourceLoaderUserTokensModule.php
@@ -43,7 +43,8 @@ class ResourceLoaderUserTokensModule extends ResourceLoaderModule {
return array(
'editToken' => $wgUser->getEditToken(),
- 'watchToken' => ApiQueryInfo::getWatchToken(null, null),
+ 'patrolToken' => ApiQueryRecentChanges::getPatrolToken( null, null ),
+ 'watchToken' => ApiQueryInfo::getWatchToken( null, null ),
);
}
diff --git a/includes/resourceloader/ResourceLoaderWikiModule.php b/includes/resourceloader/ResourceLoaderWikiModule.php
index ee8dd1e5..6c60d474 100644
--- a/includes/resourceloader/ResourceLoaderWikiModule.php
+++ b/includes/resourceloader/ResourceLoaderWikiModule.php
@@ -42,7 +42,20 @@ abstract class ResourceLoaderWikiModule extends ResourceLoaderModule {
/* Abstract Protected Methods */
/**
+ * Subclasses should return an associative array of resources in the module.
+ * Keys should be the title of a page in the MediaWiki or User namespace.
+ *
+ * Values should be a nested array of options. The supported keys are 'type' and
+ * (CSS only) 'media'.
+ *
+ * For scripts, 'type' should be 'script'.
+ *
+ * For stylesheets, 'type' should be 'style'.
+ * There is an optional media key, the value of which can be the
+ * medium ('screen', 'print', etc.) of the stylesheet.
+ *
* @param $context ResourceLoaderContext
+ * @return array
*/
abstract protected function getPages( ResourceLoaderContext $context );
@@ -75,7 +88,22 @@ abstract class ResourceLoaderWikiModule extends ResourceLoaderModule {
if ( !$revision ) {
return null;
}
- return $revision->getRawText();
+
+ $content = $revision->getContent( Revision::RAW );
+
+ if ( !$content ) {
+ wfDebug( __METHOD__ . "failed to load content of JS/CSS page!\n" );
+ return null;
+ }
+
+ $model = $content->getModel();
+
+ if ( $model !== CONTENT_MODEL_CSS && $model !== CONTENT_MODEL_JAVASCRIPT ) {
+ wfDebug( __METHOD__ . "bad content model $model for JS/CSS page!\n" );
+ return null;
+ }
+
+ return $content->getNativeData(); //NOTE: this is safe, we know it's JS or CSS
}
/* Methods */
@@ -98,7 +126,7 @@ abstract class ResourceLoaderWikiModule extends ResourceLoaderModule {
if ( strval( $script ) !== '' ) {
$script = $this->validateScriptFile( $titleText, $script );
if ( strpos( $titleText, '*/' ) === false ) {
- $scripts .= "/* $titleText */\n";
+ $scripts .= "/* $titleText */\n";
}
$scripts .= $script . "\n";
}
@@ -119,7 +147,7 @@ abstract class ResourceLoaderWikiModule extends ResourceLoaderModule {
continue;
}
$title = Title::newFromText( $titleText );
- if ( !$title || $title->isRedirect() ) {
+ if ( !$title || $title->isRedirect() ) {
continue;
}
$media = isset( $options['media'] ) ? $options['media'] : 'all';
@@ -135,7 +163,7 @@ abstract class ResourceLoaderWikiModule extends ResourceLoaderModule {
$styles[$media] = array();
}
if ( strpos( $titleText, '*/' ) === false ) {
- $style = "/* $titleText */\n" . $style;
+ $style = "/* $titleText */\n" . $style;
}
$styles[$media][] = $style;
}