From 8af960e48469f6eec8aecf0ca2fc64f2b464472a Mon Sep 17 00:00:00 2001 From: jdlrobson Date: Thu, 14 Jul 2016 15:09:06 -0700 Subject: [PATCH] resourceloader: Implement 'deprecated' option for FileModule ResourceLoader modules can now carry a 'deprecated' option which can be a boolean or an object with message key. This message or a default deprecation message will be show whenever that module is used in production. Note: This will not work in debug mode for ResourceLoaderFile modules and this is deemed acceptable for the time being. We can revisit later. Bug: T137772 Change-Id: Ib9ebd2d39a59fd41d8537e06884699f77b03580c --- docs/extension.schema.json | 4 ++ docs/extension.schema.v1.json | 4 ++ .../ResourceLoaderFileModule.php | 5 ++- .../resourceloader/ResourceLoaderModule.php | 27 ++++++++++++++ .../ResourceLoaderFileModuleTest.php | 37 +++++++++++++++++++ 5 files changed, 76 insertions(+), 1 deletion(-) diff --git a/docs/extension.schema.json b/docs/extension.schema.json index 110e99d4e6..c01001421d 100644 --- a/docs/extension.schema.json +++ b/docs/extension.schema.json @@ -417,6 +417,10 @@ "type": "string", "description": "Group with which this module should be loaded" }, + "deprecated": { + "type": ["object", "boolean"], + "description": "Whether the module is deprecated and usage is discouraged. Either a boolean or an object with key message can be used to customise deprecation message." + }, "position": { "type": "string", "description": "Position on the page to load this module at", diff --git a/docs/extension.schema.v1.json b/docs/extension.schema.v1.json index 37235e93ab..d7078648aa 100644 --- a/docs/extension.schema.v1.json +++ b/docs/extension.schema.v1.json @@ -417,6 +417,10 @@ "type": "string", "description": "Group which this module should be loaded together with" }, + "deprecated": { + "type": ["object", "boolean"], + "description": "Whether the module is deprecated and usage is discouraged. Either a boolean or an object with key message can be used to customise deprecation message." + }, "position": { "type": "string", "description": "Position on the page to load this module at", diff --git a/includes/resourceloader/ResourceLoaderFileModule.php b/includes/resourceloader/ResourceLoaderFileModule.php index 6b755d7290..2816126036 100644 --- a/includes/resourceloader/ResourceLoaderFileModule.php +++ b/includes/resourceloader/ResourceLoaderFileModule.php @@ -255,6 +255,9 @@ class ResourceLoaderFileModule extends ResourceLoaderModule { $this->{$member}[$key] = (array)$value; } break; + case 'deprecated': + $this->deprecated = $option; + break; // Lists of strings case 'dependencies': case 'messages': @@ -352,7 +355,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule { */ public function getScript( ResourceLoaderContext $context ) { $files = $this->getScriptFiles( $context ); - return $this->readScriptFiles( $files ); + return $this->getDeprecationInformation() . $this->readScriptFiles( $files ); } /** diff --git a/includes/resourceloader/ResourceLoaderModule.php b/includes/resourceloader/ResourceLoaderModule.php index 59f9a6370c..48e7937104 100644 --- a/includes/resourceloader/ResourceLoaderModule.php +++ b/includes/resourceloader/ResourceLoaderModule.php @@ -82,6 +82,11 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface { */ protected $config; + /** + * @var array|bool + */ + protected $deprecated = false; + /** * @var LoggerInterface */ @@ -130,6 +135,28 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface { return $wgContLang->getDir() !== $context->getDirection(); } + /** + * Get JS representing deprecation information for the current module if available + * + * @return string JavaScript code + */ + protected function getDeprecationInformation() { + $deprecationInfo = $this->deprecated; + if ( $deprecationInfo ) { + $name = $this->getName(); + $warning = 'This page is using the deprecated ResourceLoader module "' . $name . '".'; + if ( !is_bool( $deprecationInfo ) && isset( $deprecationInfo['message'] ) ) { + $warning .= "\n" . $deprecationInfo['message']; + } + return Xml::encodeJsCall( + 'mw.log.warn', + [ $warning ] + ); + } else { + return ''; + } + } + /** * Get all JS for this module for a given language and skin. * Includes all relevant JS except loader scripts. diff --git a/tests/phpunit/includes/resourceloader/ResourceLoaderFileModuleTest.php b/tests/phpunit/includes/resourceloader/ResourceLoaderFileModuleTest.php index 2dec02b89f..e216ceda8a 100644 --- a/tests/phpunit/includes/resourceloader/ResourceLoaderFileModuleTest.php +++ b/tests/phpunit/includes/resourceloader/ResourceLoaderFileModuleTest.php @@ -27,6 +27,15 @@ class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase { return [ 'noTemplateModule' => [], + 'deprecatedModule' => $base + [ + 'deprecated' => true, + ], + 'deprecatedTomorrow' => $base + [ + 'deprecated' => [ + 'message' => 'Will be removed tomorrow.' + ], + ], + 'htmlTemplateModule' => $base + [ 'templates' => [ 'templates/template.html', @@ -96,6 +105,34 @@ class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase { $this->assertEquals( $rl->getDependencies(), $expected ); } + public static function providerDeprecatedModules() { + return [ + [ + 'deprecatedModule', + 'mw.log.warn("This page is using the deprecated ResourceLoader module \"deprecatedModule\".");', + ], + [ + 'deprecatedTomorrow', + 'mw.log.warn(' . + '"This page is using the deprecated ResourceLoader module \"deprecatedTomorrow\".\\n' . + "Will be removed tomorrow." . + '");' + ] + ]; + } + + /** + * @dataProvider providerDeprecatedModules + * @covers ResourceLoaderFileModule::getScripts + */ + public function testDeprecatedModules( $name, $expected ) { + $modules = self::getModules(); + $rl = new ResourceLoaderFileModule( $modules[$name] ); + $rl->setName( $name ); + $ctx = $this->getResourceLoaderContext( 'en', 'ltr' ); + $this->assertEquals( $rl->getScript( $ctx ), $expected ); + } + /** * @covers ResourceLoaderFileModule::getAllStyleFiles * @covers ResourceLoaderFileModule::getAllSkinStyleFiles -- 2.20.1