// Safety check - this should never be called more than once
if ( !self::$initialized ) {
- // This needs to be first, because hooks might call ResourceLoader public interfaces which will call this
+ wfProfileIn( __METHOD__ );
+ // This needs to be first, because hooks might call ResourceLoader
+ // public interfaces which will call this
self::$initialized = true;
self::register( include( "$IP/resources/Resources.php" ) );
wfRunHooks( 'ResourceLoaderRegisterModules' );
+ wfProfileOut( __METHOD__ );
}
}
*
* @param $filter String: name of filter to run
* @param $data String: text to filter, such as JavaScript or CSS text
- * @param $file String: path to file being filtered, (optional: only required for CSS to resolve paths)
+ * @param $file String: path to file being filtered, (optional: only required
+ * for CSS to resolve paths)
* @return String: filtered data
*/
protected static function filter( $filter, $data ) {
global $wgMemc;
+ wfProfileIn( __METHOD__ );
// For empty or whitespace-only things, don't do any processing
if ( trim( $data ) === '' ) {
+ wfProfileOut( __METHOD__ );
return $data;
}
$cached = $wgMemc->get( $key );
if ( $cached !== false && $cached !== null ) {
+ wfProfileOut( __METHOD__ );
return $cached;
}
break;
default:
// Don't cache anything, just pass right through
+ wfProfileOut( __METHOD__ );
return $data;
}
} catch ( Exception $exception ) {
// Save to memcached
$wgMemc->set( $key, $result );
+ wfProfileOut( __METHOD__ );
return $result;
}
/**
* Registers a module with the ResourceLoader system.
*
- * Note that registering the same object under multiple names is not supported and may silently fail in all
- * kinds of interesting ways.
+ * Note that registering the same object under multiple names is not supported
+ * and may silently fail in all kinds of interesting ways.
*
* @param $name Mixed: string of name of module or array of name/object pairs
- * @param $object ResourceLoaderModule: module object (optional when using multiple-registration calling style)
- * @return Boolean: false if there were any errors, in which case one or more modules were not registered
+ * @param $object ResourceLoaderModule: module object (optional when using
+ * multiple-registration calling style)
+ * @return Boolean: false if there were any errors, in which case one or more
+ * modules were not registered
*
- * @todo We need much more clever error reporting, not just in detailing what happened, but in bringing errors to
- * the client in a way that they can easily see them if they want to, such as by using FireBug
+ * @todo We need much more clever error reporting, not just in detailing what
+ * happened, but in bringing errors to the client in a way that they can
+ * easily see them if they want to, such as by using FireBug
*/
public static function register( $name, ResourceLoaderModule $object = null ) {
-
+ wfProfileIn( __METHOD__ );
self::initialize();
// Allow multiple modules to be registered in one call
self::register( $key, $value );
}
+ wfProfileOut( __METHOD__ );
return;
}
// Attach module
self::$modules[$name] = $object;
$object->setName( $name );
+ wfProfileOut( __METHOD__ );
}
/**
}
/**
- * Gets registration code for all modules, except pre-registered ones listed in self::$preRegisteredModules
+ * Gets registration code for all modules, except pre-registered ones listed in
+ * self::$preRegisteredModules
*
* @param $context ResourceLoaderContext object
* @return String: JavaScript code for registering all modules with the client loader
*/
public static function getModuleRegistrations( ResourceLoaderContext $context ) {
-
+ wfProfileIn( __METHOD__ );
self::initialize();
$scripts = '';
// Support module loader scripts
if ( ( $loader = $module->getLoaderScript() ) !== false ) {
$deps = FormatJson::encode( $module->getDependencies() );
- $version = wfTimestamp( TS_ISO_8601, round( $module->getModifiedTime( $context ), -2 ) );
- $scripts .= "( function( name, version, dependencies ) { $loader } )( '$name', '$version', $deps );";
+ $version = wfTimestamp( TS_ISO_8601,
+ round( $module->getModifiedTime( $context ), -2 ) );
+ $scripts .= "( function( name, version, dependencies ) { $loader } )\n" .
+ "( '$name', '$version', $deps );\n";
}
// Automatically register module
else {
- // Modules without dependencies pass two arguments (name, timestamp) to mediaWiki.loader.register()
+ // Modules without dependencies pass two arguments (name, timestamp) to
+ // mediaWiki.loader.register()
if ( !count( $module->getDependencies() ) ) {
$registrations[] = array( $name, $module->getModifiedTime( $context ) );
}
- // Modules with dependencies pass three arguments (name, timestamp, dependencies) to mediaWiki.loader.register()
+ // Modules with dependencies pass three arguments (name, timestamp, dependencies)
+ // to mediaWiki.loader.register()
else {
- $registrations[] = array( $name, $module->getModifiedTime( $context ), $module->getDependencies() );
+ $registrations[] = array( $name, $module->getModifiedTime( $context ),
+ $module->getDependencies() );
}
}
}
- return $scripts . "mediaWiki.loader.register( " . FormatJson::encode( $registrations ) . " );";
+ $out = $scripts . "mediaWiki.loader.register( " . FormatJson::encode( $registrations ) . " );\n";
+ wfProfileOut( __METHOD__ );
+ return $out;
}
/**
- * Get the highest modification time of all modules, based on a given combination of language code,
- * skin name and debug mode flag.
+ * Get the highest modification time of all modules, based on a given
+ * combination of language code, skin name and debug mode flag.
*
* @param $context ResourceLoaderContext object
* @return Integer: UNIX timestamp
global $wgResourceLoaderVersionedClientMaxage, $wgResourceLoaderVersionedServerMaxage;
global $wgResourceLoaderUnversionedServerMaxage, $wgResourceLoaderUnversionedClientMaxage;
+ wfProfileIn( __METHOD__ );
self::initialize();
// Split requested modules into two groups, modules and missing
}
}
- // If a version wasn't specified we need a shorter expiry time for updates to propagate to clients quickly
+ // If a version wasn't specified we need a shorter expiry time for updates to
+ // propagate to clients quickly
if ( is_null( $context->getVersion() ) ) {
$maxage = $wgResourceLoaderUnversionedClientMaxage;
$smaxage = $wgResourceLoaderUnversionedServerMaxage;
}
- // If a version was specified we can use a longer expiry time since changing version numbers causes cache misses
+ // If a version was specified we can use a longer expiry time since changing
+ // version numbers causes cache misses
else {
$maxage = $wgResourceLoaderVersionedClientMaxage;
$smaxage = $wgResourceLoaderVersionedServerMaxage;
}
- // To send Last-Modified and support If-Modified-Since, we need to detect the last modified time
+ // To send Last-Modified and support If-Modified-Since, we need to detect
+ // the last modified time
+ wfProfileIn( __METHOD__.'-getModifiedTime' );
$mtime = 1;
foreach ( $modules as $name ) {
$mtime = max( $mtime, self::$modules[$name]->getModifiedTime( $context ) );
}
+ wfProfileOut( __METHOD__.'-getModifiedTime' );
header( 'Content-Type: ' . ( $context->getOnly() === 'styles' ? 'text/css' : 'text/javascript' ) );
header( 'Last-Modified: ' . wfTimestamp( TS_RFC2822, $mtime ) );
if ( $ims !== false && $mtime >= wfTimestamp( TS_UNIX, $ims ) ) {
header( 'HTTP/1.0 304 Not Modified' );
header( 'Status: 304 Not Modified' );
+ wfProfileOut( __METHOD__ );
return;
}
// Generate output
foreach ( $modules as $name ) {
+ wfProfileIn( __METHOD__ . '-' . $name );
// Scripts
$scripts = '';
if ( $context->shouldIncludeScripts() ) {
- $scripts .= self::$modules[$name]->getScript( $context );
+ $scripts .= self::$modules[$name]->getScript( $context ) . "\n";
}
// Styles
$styles = array();
if (
- $context->shouldIncludeStyles() && ( count( $styles = self::$modules[$name]->getStyles( $context ) ) )
+ $context->shouldIncludeStyles()
+ && ( count( $styles = self::$modules[$name]->getStyles( $context ) ) )
) {
foreach ( $styles as $media => $style ) {
if ( self::$modules[$name]->getFlip( $context ) ) {
}
echo "mediaWiki.loader.implement( '$name', function() {{$scripts}},\n$styles,\n$messages );\n";
}
+ wfProfileOut( __METHOD__ . '-' . $name );
}
// Update the status of script-only modules
echo self::filter( 'minify-js', ob_get_clean() );
}
}
+ wfProfileOut( __METHOD__ );
}
-}
\ No newline at end of file
+}
// Only store if modified
if ( $files !== $this->getFileDependencies( $context->getSkin() ) ) {
$encFiles = FormatJson::encode( $files );
- $dbw = wfGetDb( DB_MASTER );
+ $dbw = wfGetDB( DB_MASTER );
$dbw->replace( 'module_deps',
array( array( 'md_module', 'md_skin' ) ), array(
'md_module' => $this->getName(),
if ( isset( $this->modifiedTime[$context->getHash()] ) ) {
return $this->modifiedTime[$context->getHash()];
}
+ wfProfileIn( __METHOD__ );
// Sort of nasty way we can get a flat list of files depended on by all styles
$styles = array();
$this->loaders,
$this->getFileDependencies( $context->getSkin() )
);
+ wfProfileIn( __METHOD__.'-filemtime' );
$filesMtime = max( array_map( 'filemtime', array_map( array( __CLASS__, 'remapFilename' ), $files ) ) );
+ wfProfileOut( __METHOD__.'-filemtime' );
// Only get the message timestamp if there are messages in the module
$msgBlobMtime = 0;
if ( count( $this->messages ) ) {
// Get the mtime of the message blob
- // TODO: This timestamp is queried a lot and queried separately for each module. Maybe it should be put in memcached?
- $dbr = wfGetDb( DB_SLAVE );
+ // TODO: This timestamp is queried a lot and queried separately for each module.
+ // Maybe it should be put in memcached?
+ $dbr = wfGetDB( DB_SLAVE );
$msgBlobMtime = $dbr->selectField( 'msg_resource', 'mr_timestamp', array(
'mr_resource' => $this->getName(),
'mr_lang' => $context->getLanguage()
$msgBlobMtime = $msgBlobMtime ? wfTimestamp( TS_UNIX, $msgBlobMtime ) : 0;
}
$this->modifiedTime[$context->getHash()] = max( $filesMtime, $msgBlobMtime );
+ wfProfileOut( __METHOD__ );
return $this->modifiedTime[$context->getHash()];
}
$deps = $wgMemc->get( $key );
if ( !$deps ) {
- $dbr = wfGetDb( DB_SLAVE );
+ $dbr = wfGetDB( DB_SLAVE );
$deps = $dbr->selectField( 'module_deps', 'md_deps', array(
'md_module' => $this->getName(),
'md_skin' => $skin,
* @return String: concatenated contents of $files
*/
protected static function concatScripts( $files ) {
- return implode( "\n", array_map( 'file_get_contents', array_map( array( __CLASS__, 'remapFilename' ), array_unique( (array) $files ) ) ) );
+ return implode( "\n",
+ array_map(
+ 'file_get_contents',
+ array_map(
+ array( __CLASS__, 'remapFilename' ),
+ array_unique( (array) $files ) ) ) );
}
protected static function organizeFilesByOption( $files, $option, $default ) {
$styles = self::organizeFilesByOption( $styles, 'media', 'all' );
foreach ( $styles as $media => $files ) {
$styles[$media] =
- implode( "\n", array_map( array( __CLASS__, 'remapStyle' ), array_unique( (array) $files ) ) );
+ implode( "\n",
+ array_map(
+ array( __CLASS__, 'remapStyle' ),
+ array_unique( (array) $files ) ) );
}
return $styles;
}
public function getScript( ResourceLoaderContext $context ) {
$user = User::newFromName( $context->getUser() );
- $options = FormatJson::encode( $user instanceof User ? $user->getOptions() : User::getDefaultOptions() );
+ if ( $user instanceof User ) {
+ $options = FormatJson::encode( $user->getOptions() );
+ } else {
+ $options = FormatJson::encode( User::getDefaultOptions() );
+ }
return "mediaWiki.user.options.set( $options );";
}
/* Protected Methods */
protected function getConfig( $context ) {
- global $wgLoadScript, $wgScript, $wgStylePath, $wgScriptExtension, $wgArticlePath, $wgScriptPath, $wgServer,
- $wgContLang, $wgBreakFrames, $wgVariantArticlePath, $wgActionPaths, $wgUseAjax, $wgVersion,
- $wgEnableAPI, $wgEnableWriteAPI, $wgDBname, $wgEnableMWSuggest, $wgSitename, $wgFileExtensions;
+ global $wgLoadScript, $wgScript, $wgStylePath, $wgScriptExtension,
+ $wgArticlePath, $wgScriptPath, $wgServer, $wgContLang, $wgBreakFrames,
+ $wgVariantArticlePath, $wgActionPaths, $wgUseAjax, $wgVersion,
+ $wgEnableAPI, $wgEnableWriteAPI, $wgDBname, $wgEnableMWSuggest,
+ $wgSitename, $wgFileExtensions;
// Pre-process information
$separatorTransTable = $wgContLang->separatorTransformTable();
// Build configuration
$config = FormatJson::encode( $this->getConfig( $context ) );
// Add a well-known start-up function
- $scripts .= "window.startUp = function() { $registration mediaWiki.config.set( $config ); };";
+ $scripts .= <<<JAVASCRIPT
+window.startUp = function() {
+ $registration
+ mediaWiki.config.set( $config );
+};
+JAVASCRIPT;
// Build load query for jquery and mediawiki modules
$query = array(
'modules' => implode( '|', array( 'jquery', 'mediawiki' ) ),
// Build HTML code for loading jquery and mediawiki modules
$loadScript = Html::linkedScript( $wgLoadScript . '?' . wfArrayToCGI( $query ) );
// Add code to add jquery and mediawiki loading code; only if the current client is compatible
- $scripts .= "if ( isCompatible() ) { document.write( '$loadScript' ); }";
+ $scripts .= "if ( isCompatible() ) { document.write( " . FormatJson::encode( $loadScript ) . "); }\n";
// Delete the compatible function - it's not needed anymore
- $scripts .= "delete window['isCompatible'];";
+ $scripts .= "delete window['isCompatible'];\n";
}
return $scripts;