/**
* Register a module with the ResourceLoader system.
*
- * @param mixed $name Name of module as a string or List of name/object pairs as an array
- * @param array|null $info Module info array. For backwards compatibility with 1.17alpha,
- * this may also be a ResourceLoaderModule object. Optional when using
- * multiple-registration calling style.
+ * @param string|array[] $name Module name as a string or, array of module info arrays
+ * keyed by name.
+ * @param array|null $info Module info array. When using the first parameter to register
+ * multiple modules at once, this parameter is optional.
* @throws MWException If a duplicate module registration is attempted
* @throws MWException If a module name contains illegal characters (pipes or commas)
- * @throws MWException If something other than a ResourceLoaderModule is being registered
+ * @throws InvalidArgumentException If the module info is not an array
*/
public function register( $name, $info = null ) {
$moduleSkinStyles = $this->config->get( 'ResourceModuleSkinStyles' );
);
}
- // Check $name for validity
+ // Check validity
if ( !self::isValidModuleName( $name ) ) {
throw new MWException( "ResourceLoader module name '$name' is invalid, "
. "see ResourceLoader::isValidModuleName()" );
}
-
- // Attach module
- if ( $info instanceof ResourceLoaderModule ) {
- $this->moduleInfos[$name] = [ 'object' => $info ];
- $info->setName( $name );
- $this->modules[$name] = $info;
- } elseif ( is_array( $info ) ) {
- // New calling convention
- $this->moduleInfos[$name] = $info;
- } else {
- throw new MWException(
- 'ResourceLoader module info type error for module \'' . $name .
- '\': expected ResourceLoaderModule or array (got: ' . gettype( $info ) . ')'
+ if ( !is_array( $info ) ) {
+ throw new InvalidArgumentException(
+ 'Invalid module info for "' . $name . '": expected array, got ' . gettype( $info )
);
}
- // Last-minute changes
+ // Attach module
+ $this->moduleInfos[$name] = $info;
+ // Last-minute changes
// Apply custom skin-defined styles to existing modules.
if ( $this->isFileModule( $name ) ) {
foreach ( $moduleSkinStyles as $skinName => $skinStyles ) {
// No such module
return null;
}
- // Construct the requested object
+ // Construct the requested module object
$info = $this->moduleInfos[$name];
- /** @var ResourceLoaderModule $object */
- if ( isset( $info['object'] ) ) {
- // Object given in info array
- $object = $info['object'];
- } elseif ( isset( $info['factory'] ) ) {
+ if ( isset( $info['factory'] ) ) {
+ /** @var ResourceLoaderModule $object */
$object = call_user_func( $info['factory'], $info );
- $object->setConfig( $this->getConfig() );
- $object->setLogger( $this->logger );
} else {
$class = $info['class'] ?? ResourceLoaderFileModule::class;
/** @var ResourceLoaderModule $object */
$object = new $class( $info );
- $object->setConfig( $this->getConfig() );
- $object->setLogger( $this->logger );
}
+ $object->setConfig( $this->getConfig() );
+ $object->setLogger( $this->logger );
$object->setName( $name );
$this->modules[$name] = $object;
}
return false;
}
$info = $this->moduleInfos[$name];
- if ( isset( $info['object'] ) ) {
- return false;
- }
return !isset( $info['factory'] ) && (
// The implied default for 'class' is ResourceLoaderFileModule
!isset( $info['class'] ) ||
* @return string JavaScript code
*/
public static function makeMessageSetScript( $messages ) {
- return Xml::encodeJsCall(
- 'mw.messages.set',
- [ (object)$messages ],
- self::inDebugMode()
- );
+ return 'mw.messages.set('
+ . self::encodeJsonForScript( (object)$messages )
+ . ');';
}
/**
if ( !is_array( $states ) ) {
$states = [ $states => $state ];
}
- return Xml::encodeJsCall(
- 'mw.loader.state',
- [ $states ],
- self::inDebugMode()
- );
+ return 'mw.loader.state('
+ . self::encodeJsonForScript( $states )
+ . ');';
}
private static function isEmptyObject( stdClass $obj ) {
array_walk( $modules, [ self::class, 'trimArray' ] );
- return Xml::encodeJsCall(
- 'mw.loader.register',
- [ $modules ],
- self::inDebugMode()
- );
+ return 'mw.loader.register('
+ . self::encodeJsonForScript( $modules )
+ . ');';
}
/**
if ( !is_array( $sources ) ) {
$sources = [ $sources => $loadUrl ];
}
- return Xml::encodeJsCall(
- 'mw.loader.addSource',
- [ $sources ],
- self::inDebugMode()
- );
+ return 'mw.loader.addSource('
+ . self::encodeJsonForScript( $sources )
+ . ');';
}
/**
*/
public function testRegisterInvalidType() {
$resourceLoader = new EmptyResourceLoader();
- $this->setExpectedException( MWException::class, 'ResourceLoader module info type error' );
+ $this->setExpectedException( InvalidArgumentException::class, 'Invalid module info' );
$resourceLoader->register( 'test', new stdClass() );
}
*/
public function testMakeLoaderRegisterScript() {
$this->assertEquals(
- 'mw.loader.register( [
+ 'mw.loader.register([
[
"test.name",
"1234567"
]
- ] );',
+ ]);',
ResourceLoader::makeLoaderRegisterScript( [
[ 'test.name', '1234567' ],
] ),
);
$this->assertEquals(
- 'mw.loader.register( [
+ 'mw.loader.register([
[
"test.foo",
"100"
null,
"return true;"
]
- ] );',
+ ]);',
ResourceLoader::makeLoaderRegisterScript( [
[ 'test.foo', '100' , [], null, null ],
[ 'test.bar', '200', [ 'test.unknown' ], null ],
*/
public function testMakeLoaderSourcesScript() {
$this->assertEquals(
- 'mw.loader.addSource( {
+ 'mw.loader.addSource({
"local": "/w/load.php"
- } );',
+ });',
ResourceLoader::makeLoaderSourcesScript( 'local', '/w/load.php' )
);
$this->assertEquals(
- 'mw.loader.addSource( {
+ 'mw.loader.addSource({
"local": "/w/load.php"
- } );',
+ });',
ResourceLoader::makeLoaderSourcesScript( [ 'local' => '/w/load.php' ] )
);
$this->assertEquals(
- 'mw.loader.addSource( {
+ 'mw.loader.addSource({
"local": "/w/load.php",
"example": "https://example.org/w/load.php"
- } );',
+ });',
ResourceLoader::makeLoaderSourcesScript( [
'local' => '/w/load.php',
'example' => 'https://example.org/w/load.php'
] )
);
$this->assertEquals(
- 'mw.loader.addSource( [] );',
+ 'mw.loader.addSource([]);',
ResourceLoader::makeLoaderSourcesScript( [] )
);
}
'modules' => [
'foo' => 'foo()',
],
- 'expected' => "foo()\n" . 'mw.loader.state( {
+ 'expected' => "foo()\n" . 'mw.loader.state({
"foo": "ready"
- } );',
+ });',
'minified' => "foo()\n" . 'mw.loader.state({"foo":"ready"});',
'message' => 'Script without semi-colon',
],
'foo' => 'foo()',
'bar' => 'bar()',
],
- 'expected' => "foo()\nbar()\n" . 'mw.loader.state( {
+ 'expected' => "foo()\nbar()\n" . 'mw.loader.state({
"foo": "ready",
"bar": "ready"
- } );',
+ });',
'minified' => "foo()\nbar()\n" . 'mw.loader.state({"foo":"ready","bar":"ready"});',
'message' => 'Two scripts without semi-colon',
],
'modules' => [
'foo' => "foo()\n// bar();"
],
- 'expected' => "foo()\n// bar();\n" . 'mw.loader.state( {
+ 'expected' => "foo()\n// bar();\n" . 'mw.loader.state({
"foo": "ready"
- } );',
+ });',
'minified' => "foo()\n" . 'mw.loader.state({"foo":"ready"});',
'message' => 'Script with semi-colon in comment (T162719)',
],
$this->assertCount( 1, $errors );
$this->assertRegExp( '/Ferry not found/', $errors[0] );
$this->assertEquals(
- "foo();\nbar();\n" . 'mw.loader.state( {
+ "foo();\nbar();\n" . 'mw.loader.state({
"ferry": "error",
"foo": "ready",
"bar": "ready"
- } );',
+ });',
$response
);
}