From 08aa4418c30cfc18ccc69a0f0f9cb9e17be6c196 Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Mon, 12 Aug 2013 09:28:15 +0200 Subject: Update to MediaWiki 1.21.1 --- includes/resourceloader/ResourceLoader.php | 93 +++++++------- includes/resourceloader/ResourceLoaderContext.php | 18 +-- .../resourceloader/ResourceLoaderFileModule.php | 139 +++++++++++---------- .../ResourceLoaderLanguageDataModule.php | 34 +++-- includes/resourceloader/ResourceLoaderModule.php | 56 ++++++--- .../ResourceLoaderNoscriptModule.php | 2 +- .../resourceloader/ResourceLoaderSiteModule.php | 6 +- .../resourceloader/ResourceLoaderStartUpModule.php | 55 ++++---- .../ResourceLoaderUserCSSPrefsModule.php | 2 +- .../ResourceLoaderUserTokensModule.php | 3 +- .../resourceloader/ResourceLoaderWikiModule.php | 36 +++++- 11 files changed, 260 insertions(+), 184 deletions(-) (limited to 'includes/resourceloader') 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 ) { @@ -645,23 +653,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 @@ -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. * @@ -46,24 +47,35 @@ class ResourceLoaderLanguageDataModule extends ResourceLoaderModule { return $this->language->getPluralRules(); } + /** + * 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 * @@ -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; @@ -289,11 +290,20 @@ abstract class ResourceLoaderModule { return array(); } + /** + * 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; } -- cgit v1.2.2