From a68c44f486b3c3bca3d2ea81211bf1cfe19b56a8 Mon Sep 17 00:00:00 2001 From: Nathaniel Catchpole Date: Tue, 22 Nov 2016 11:11:46 +0000 Subject: [PATCH] Issue #2808063 by vaplas, martin107, Chi, Wim Leers, catch, dawehner, alexpott: LibraryDiscoveryParser::buildByExtension() doesn't validate that extensions exist --- core/core.services.yml | 2 +- .../Core/Asset/LibraryDiscoveryParser.php | 18 ++++++++- .../Ajax/AjaxTest.php | 2 +- .../Core/Asset/LibraryDiscoveryParserTest.php | 38 ++++++++++++++++++- 4 files changed, 55 insertions(+), 5 deletions(-) diff --git a/core/core.services.yml b/core/core.services.yml index 5c42b23e055..aed2de90142 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -1543,7 +1543,7 @@ services: - { name: needs_destruction } library.discovery.parser: class: Drupal\Core\Asset\LibraryDiscoveryParser - arguments: ['@app.root', '@module_handler', '@theme.manager'] + arguments: ['@app.root', '@module_handler', '@theme.manager', '@theme_handler'] library.dependency_resolver: class: Drupal\Core\Asset\LibraryDependencyResolver arguments: ['@library.discovery'] diff --git a/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php b/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php index 799ee07f91f..34e395159e7 100644 --- a/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php +++ b/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php @@ -11,6 +11,7 @@ use Drupal\Core\Serialization\Yaml; use Drupal\Core\Theme\ThemeManagerInterface; use Drupal\Component\Serialization\Exception\InvalidDataTypeException; use Drupal\Component\Utility\NestedArray; +use Drupal\Core\Extension\ThemeHandlerInterface; /** * Parses library files to get extension data. @@ -31,6 +32,13 @@ class LibraryDiscoveryParser { */ protected $themeManager; + /** + * The theme handler. + * + * @var \Drupal\Core\Extension\ThemeHandlerInterface + */ + protected $themeHandler; + /** * The app root. * @@ -47,11 +55,14 @@ class LibraryDiscoveryParser { * The module handler. * @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager * The theme manager. + * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler + * The theme handler. */ - public function __construct($root, ModuleHandlerInterface $module_handler, ThemeManagerInterface $theme_manager) { + public function __construct($root, ModuleHandlerInterface $module_handler, ThemeManagerInterface $theme_manager, ThemeHandlerInterface $theme_handler) { $this->root = $root; $this->moduleHandler = $module_handler; $this->themeManager = $theme_manager; + $this->themeHandler = $theme_handler; } /** @@ -63,6 +74,8 @@ class LibraryDiscoveryParser { * @return array * All library definitions of the passed extension. * + * @throws \AssertionError + * When the extension (theme, module, library) is not available. * @throws \Drupal\Core\Asset\Exception\IncompleteLibraryDefinitionException * Thrown when a library has no js/css/setting. * @throws \UnexpectedValueException @@ -79,9 +92,10 @@ class LibraryDiscoveryParser { if ($this->moduleHandler->moduleExists($extension)) { $extension_type = 'module'; } - else { + elseif ($this->themeHandler->themeExists($extension)) { $extension_type = 'theme'; } + assert(isset($extension_type), sprintf('The extension "%s" is not available.', $extension)); $path = $this->drupalGetPath($extension_type, $extension); } diff --git a/core/tests/Drupal/FunctionalJavascriptTests/Ajax/AjaxTest.php b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/AjaxTest.php index e05940537c4..7339db855dc 100644 --- a/core/tests/Drupal/FunctionalJavascriptTests/Ajax/AjaxTest.php +++ b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/AjaxTest.php @@ -53,7 +53,7 @@ class AjaxTest extends JavascriptTestBase { $session = $this->getSession(); // Insert a fake library into the already loaded library settings. - $fake_library = 'fakeLibrary/fakeLibrary'; + $fake_library = 'core/fakeLibrary'; $session->evaluateScript("drupalSettings.ajaxPageState.libraries = drupalSettings.ajaxPageState.libraries + ',$fake_library';"); $libraries = $session->evaluateScript('drupalSettings.ajaxPageState.libraries'); diff --git a/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php b/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php index 121aebc953b..b46e29dc478 100644 --- a/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php +++ b/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php @@ -44,6 +44,13 @@ class LibraryDiscoveryParserTest extends UnitTestCase { */ protected $themeManager; + /** + * The mocked theme handler. + * + * @var \Drupal\Core\Extension\ThemeHandlerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $themeHandler; + /** * The mocked lock backend. * @@ -59,6 +66,8 @@ class LibraryDiscoveryParserTest extends UnitTestCase { $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface'); $this->themeManager = $this->getMock('Drupal\Core\Theme\ThemeManagerInterface'); + $this->themeHandler = $this->getMock('Drupal\Core\Extension\ThemeHandlerInterface'); + $mock_active_theme = $this->getMockBuilder('Drupal\Core\Theme\ActiveTheme') ->disableOriginalConstructor() ->getMock(); @@ -68,7 +77,7 @@ class LibraryDiscoveryParserTest extends UnitTestCase { $this->themeManager->expects($this->any()) ->method('getActiveTheme') ->willReturn($mock_active_theme); - $this->libraryDiscoveryParser = new TestLibraryDiscoveryParser($this->root, $this->moduleHandler, $this->themeManager); + $this->libraryDiscoveryParser = new TestLibraryDiscoveryParser($this->root, $this->moduleHandler, $this->themeManager, $this->themeHandler); } /** @@ -109,6 +118,11 @@ class LibraryDiscoveryParserTest extends UnitTestCase { ->with('example_theme') ->will($this->returnValue(FALSE)); + $this->themeHandler->expects($this->atLeastOnce()) + ->method('themeExists') + ->with('example_theme') + ->will($this->returnValue(TRUE)); + $path = __DIR__ . '/library_test_files'; $path = substr($path, strlen($this->root) + 1); $this->libraryDiscoveryParser->setPaths('theme', 'example_theme', $path); @@ -160,6 +174,28 @@ class LibraryDiscoveryParserTest extends UnitTestCase { $this->libraryDiscoveryParser->buildByExtension('invalid_file'); } + /** + * Tests that an exception is thrown when the extension is not a valid + * module, theme or library. + * + * @covers ::buildByExtension + */ + public function testMissingExtension() { + $this->moduleHandler->expects($this->atLeastOnce()) + ->method('moduleExists') + ->with('missing_extension') + ->will($this->returnValue(FALSE)); + + $this->themeHandler->expects($this->atLeastOnce()) + ->method('themeExists') + ->with('missing_extension') + ->will($this->returnValue(FALSE)); + + assert_options(ASSERT_ACTIVE, 1); + $this->setExpectedException('\AssertionError', 'The extension "missing_extension" is not available.'); + $this->libraryDiscoveryParser->buildByExtension('missing_extension'); + } + /** * Tests that an exception is thrown when no CSS/JS/setting is specified. *