/** @var bool */
protected static $debugMode = null;
- /** @var array Module name/ResourceLoaderModule object pairs */
+ /**
+ * Module name/ResourceLoaderModule object pairs
+ * @var array
+ */
protected $modules = array();
- /** @var array Associative array mapping module name to info associative array */
+ /**
+ * Associative array mapping module name to info associative array
+ * @var array
+ */
protected $moduleInfos = array();
/** @var Config $config */
private $config;
/**
- * @var 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', .. ), .. )
+ * 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', .. ), .. )
+ * @var array
*/
protected $testModuleNames = array();
- /** @var array E.g. array( 'source-id' => 'http://.../load.php' ) */
+ /**
+ * E.g. array( 'source-id' => 'http://.../load.php' )
+ * @var array
+ */
protected $sources = array();
/** @var bool */
foreach ( array_keys( $modulesWithoutMessages ) as $name ) {
$module = $this->getModule( $name );
if ( $module ) {
- $module->setMsgBlobMtime( $lang, 0 );
+ $module->setMsgBlobMtime( $lang, 1 );
}
}
}
// Generate a response
$response = $this->makeModuleResponse( $context, $modules, $missing );
- // Prepend comments indicating exceptions
- $response = $errors . $response;
-
// Capture any PHP warnings from the output buffer and append them to the
- // response in a comment if we're in debug mode.
+ // error list if we're in debug mode.
if ( $context->getDebug() && strlen( $warnings = ob_get_contents() ) ) {
- $response = self::makeComment( $warnings ) . $response;
+ $errors .= self::makeComment( $warnings );
$this->hasErrors = true;
}
+ if ( $context->getImageObj() && !$response ) {
+ $errors .= self::makeComment( "Image generation failed." );
+ $this->hasErrors = true;
+ }
+
+ if ( $this->hasErrors ) {
+ if ( $context->getImageObj() ) {
+ // Bail, we can't show both the error messages and the response when it's not CSS or JS.
+ // sendResponseHeaders() will handle this sensibly.
+ $response = $errors;
+ } else {
+ // Prepend comments indicating exceptions
+ $response = $errors . $response;
+ }
+ }
+
// Save response to file cache unless there are errors
- if ( isset( $fileCache ) && !$errors && !count( $missing ) ) {
- // Cache single modules...and other requests if there are enough hits
+ if ( isset( $fileCache ) && !$this->hasErrors && !count( $missing ) ) {
+ // Cache single modules and images...and other requests if there are enough hits
if ( ResourceFileCache::useFileCache( $context ) ) {
if ( $fileCache->isCacheWorthy() ) {
$fileCache->saveText( $response );
$maxage = $rlMaxage['versioned']['client'];
$smaxage = $rlMaxage['versioned']['server'];
}
- if ( $context->getOnly() === 'styles' ) {
+ if ( $context->getImageObj() ) {
+ if ( $errors ) {
+ header( 'Content-Type: text/plain; charset=utf-8' );
+ } else {
+ $context->getImageObj()->sendResponseHeaders( $context );
+ }
+ } elseif ( $context->getOnly() === 'styles' ) {
header( 'Content-Type: text/css; charset=utf-8' );
header( 'Access-Control-Allow-Origin: *' );
} else {
wfProfileIn( __METHOD__ );
+ $image = $context->getImageObj();
+ if ( $image ) {
+ $data = $image->getImageData( $context );
+ wfProfileOut( __METHOD__ );
+ return $data;
+ }
+
// Pre-fetch blobs
if ( $context->shouldIncludeMessages() ) {
try {
case 'messages':
$out .= self::makeMessageSetScript( new XmlJsCode( $messagesBlob ) );
break;
+ case 'templates':
+ $out .= Xml::encodeJsCall(
+ 'mw.templates.set',
+ array( $name, (object)$module->getTemplates() ),
+ ResourceLoader::inDebugMode()
+ );
+ break;
default:
$out .= self::makeLoaderImplementScript(
$name,
$scripts,
$styles,
- new XmlJsCode( $messagesBlob )
+ new XmlJsCode( $messagesBlob ),
+ $module->getTemplates()
);
break;
}
* @param mixed $messages List of messages associated with this module. May either be an
* associative array mapping message key to value, or a JSON-encoded message blob containing
* the same data, wrapped in an XmlJsCode object.
+ * @param array $templates Keys are name of templates and values are the source of
+ * the template.
* @throws MWException
* @return string
*/
- public static function makeLoaderImplementScript( $name, $scripts, $styles, $messages ) {
+ public static function makeLoaderImplementScript( $name, $scripts, $styles,
+ $messages, $templates
+ ) {
if ( is_string( $scripts ) ) {
$scripts = new XmlJsCode( "function ( $, jQuery ) {\n{$scripts}\n}" );
} elseif ( !is_array( $scripts ) ) {
throw new MWException( 'Invalid scripts error. Array of URLs or string of code expected.' );
}
+
return Xml::encodeJsCall(
'mw.loader.implement',
array(
// PHP/json_encode() consider empty arrays to be numerical arrays and
// output javascript "[]" instead of "{}". This fixes that.
(object)$styles,
- (object)$messages
+ (object)$messages,
+ (object)$templates,
),
ResourceLoader::inDebugMode()
);
);
}
+ /**
+ * Remove empty values from the end of an array.
+ *
+ * Values considered empty:
+ *
+ * - null
+ * - empty array
+ *
+ * @param Array $array
+ */
+ private static function trimArray( Array &$array ) {
+ $i = count( $array );
+ while ( $i-- ) {
+ if ( $array[$i] === null || $array[$i] === array() ) {
+ unset( $array[$i] );
+ } else {
+ break;
+ }
+ }
+ }
+
/**
* Returns JS code which calls mw.loader.register with the given
* parameters. Has three calling conventions:
$dependencies = null, $group = null, $source = null, $skip = null
) {
if ( is_array( $name ) ) {
+ // Build module name index
+ $index = array();
+ foreach ( $name as $i => &$module ) {
+ $index[$module[0]] = $i;
+ }
+
+ // Transform dependency names into indexes when possible, they will be resolved by
+ // mw.loader.register on the other end
+ foreach ( $name as &$module ) {
+ if ( isset( $module[2] ) ) {
+ foreach ( $module[2] as &$dependency ) {
+ if ( isset( $index[$dependency] ) ) {
+ $dependency = $index[$dependency];
+ }
+ }
+ }
+ }
+
+ array_walk( $name, array( 'self', 'trimArray' ) );
+
return Xml::encodeJsCall(
'mw.loader.register',
array( $name ),
ResourceLoader::inDebugMode()
);
} else {
- $version = (int)$version > 1 ? (int)$version : 1;
+ $registration = array( $name, $version, $dependencies, $group, $source, $skip );
+ self::trimArray( $registration );
return Xml::encodeJsCall(
'mw.loader.register',
- array( $name, $version, $dependencies, $group, $source, $skip ),
+ $registration,
ResourceLoader::inDebugMode()
);
}
// When called from the installer, it is possible that a required PHP extension
// is missing (at least for now; see bug 47564). If this is the case, throw an
// exception (caught by the installer) to prevent a fatal error later on.
+ if ( !class_exists( 'lessc' ) ) {
+ throw new MWException( 'MediaWiki requires the lessphp compiler' );
+ }
if ( !function_exists( 'ctype_digit' ) ) {
throw new MWException( 'lessc requires the Ctype extension' );
}