diff --git a/core/lib/Drupal/Core/StreamWrapper/LocalStream.php b/core/lib/Drupal/Core/StreamWrapper/LocalStream.php index dbc7fcb..99a2b1e 100644 --- a/core/lib/Drupal/Core/StreamWrapper/LocalStream.php +++ b/core/lib/Drupal/Core/StreamWrapper/LocalStream.php @@ -81,6 +81,9 @@ function getUri() { * @return string|bool * Returns a string representing a location suitable for writing of a file, * or FALSE if unable to write to the file such as with read-only streams. + * + * @throws \InvalidArgumentException + * If a malformed $uri parameter is passed in. */ protected function getTarget($uri = NULL) { if (!isset($uri)) { @@ -90,14 +93,11 @@ protected function getTarget($uri = NULL) { $uri_parts = explode('://', $uri, 2); if (count($uri_parts) === 1) { // The delimiter ('://') was not found in $uri, malformed $uri passed. - throw new \InvalidArgumentException('Malformed $uri parameter passed: %s', $uri); + throw new \InvalidArgumentException(sprintf('Malformed uri parameter passed: %s', $uri)); } - else { - list(, $target) = $uri_parts; - // Remove erroneous leading or trailing, forward-slashes and backslashes. - return trim($target, '\/'); - } + // Remove erroneous leading or trailing forward-slashes and backslashes. + return trim($uri_parts[1], '\/'); } /** @@ -308,14 +308,14 @@ public function stream_close() { * @param int $cast_as * Can be STREAM_CAST_FOR_SELECT or STREAM_CAST_AS_STREAM. * - * @return resource|false + * @return resource|FALSE * The underlying stream resource or FALSE if stream_select() is not * supported. * * @see http://php.net/manual/streamwrapper.stream-cast.php */ public function stream_cast($cast_as) { - return false; + return FALSE; } /** diff --git a/core/lib/Drupal/Core/StreamWrapper/ModuleStream.php b/core/lib/Drupal/Core/StreamWrapper/ModuleStream.php index 9021ae3..efd81a0 100644 --- a/core/lib/Drupal/Core/StreamWrapper/ModuleStream.php +++ b/core/lib/Drupal/Core/StreamWrapper/ModuleStream.php @@ -8,27 +8,22 @@ namespace Drupal\Core\StreamWrapper; /** - * Defines a read-only Drupal stream wrapper base class for modules. - * - * This class extends the complete stream wrapper implementation in LocalStream. - * URIs such as "module://system" are expanded to a normal filesystem path - * such as "modules/system" and then PHP filesystem functions are - * invoked. + * Defines the read-only module:// stream wrapper for module files. */ class ModuleStream extends SystemStream { /** - * Get the module name of the current URI. - * - * @param string $uri - * Optional URI. - * - * @return string - * The extension name. + * {@inheritdoc} */ public function getOwnerName($uri = NULL) { $name = parent::getOwnerName($uri); - return \Drupal::moduleHandler()->moduleExists($name) ? $name : FALSE; + if (\Drupal::moduleHandler()->moduleExists($name)) { + return $name; + } + else { + // The module does not exist or is disabled. + throw new \InvalidArgumentException(sprintf('Module %s does not exist or is disabled', $name)); + } } /** diff --git a/core/lib/Drupal/Core/StreamWrapper/ProfileStream.php b/core/lib/Drupal/Core/StreamWrapper/ProfileStream.php index bf2cdfc..0e1fd62 100644 --- a/core/lib/Drupal/Core/StreamWrapper/ProfileStream.php +++ b/core/lib/Drupal/Core/StreamWrapper/ProfileStream.php @@ -8,14 +8,7 @@ namespace Drupal\Core\StreamWrapper; /** - * Defines a read-only Drupal stream wrapper base class for profiles. - * - * This class extends the complete stream wrapper implementation in LocalStream. - * URIs such as "profile://standard" are expanded to a normal filesystem path - * such as "profiles/standard" and then PHP filesystem functions are invoked. - * - * Specifying "profile://current" will return a stream for the currently - * installed profile. + * Defines the read-only profile:// stream wrapper for profiles. */ class ProfileStream extends SystemStream { @@ -24,13 +17,16 @@ class ProfileStream extends SystemStream { */ public function getOwnerName($uri = NULL) { $name = parent::getOwnerName($uri); - $current = drupal_get_profile(); - switch ($name) { - case 'current': - case $current: - return $current; - default: - return !is_null(drupal_get_filename('profile', $name)) ? $name : FALSE; + if ($name == 'current') { + $name = drupal_get_profile(); + } + + if (!is_null(drupal_get_filename('profile', $name))) { + return $name; + } + else { + // The profile does not exist. + throw new \InvalidArgumentException(sprintf('Profile %s does not exist', $name)); } } diff --git a/core/lib/Drupal/Core/StreamWrapper/SystemStream.php b/core/lib/Drupal/Core/StreamWrapper/SystemStream.php index 57e3d60..5d53458 100644 --- a/core/lib/Drupal/Core/StreamWrapper/SystemStream.php +++ b/core/lib/Drupal/Core/StreamWrapper/SystemStream.php @@ -25,6 +25,8 @@ * * @return string * The extension name. + * + * @throws \InvalidArgumentException */ public function getOwnerName($uri = NULL) { if (!isset($uri)) { @@ -36,12 +38,10 @@ public function getOwnerName($uri = NULL) { // The delimiter ('://') was not found in $uri, malformed $uri passed. throw new \InvalidArgumentException(sprintf('Malformed uri parameter passed: %s', $uri)); } - else { - list($scheme, $target) = $uri_parts; - } + // Remove the trailing filename from the path. - $length = strpos($target, '/'); - return ($length === FALSE) ? $target : substr($target, 0, $length); + $length = strpos($uri_parts[1], '/'); + return ($length === FALSE) ? $uri_parts[1] : substr($uri_parts[1], 0, $length); } /** @@ -49,7 +49,12 @@ public function getOwnerName($uri = NULL) { */ public function getTarget($uri = NULL) { $target = $this->extractTarget($uri); - return file_exists($this->getDirectoryPath($uri) . '/' . $target) ? $target : NULL; + if (file_exists($this->getDirectoryPath($uri) . '/' . $target)) { + return $target; + } + else { + throw new \InvalidArgumentException(sprintf('Target %s does not exist', $uri)); + } } /** @@ -58,28 +63,38 @@ public function getTarget($uri = NULL) { * @param string $uri * Optional URI. * - * @return bool|string + * @return string * A path to the local target. + * + * @throws \InvalidArgumentException */ protected function extractTarget($uri = NULL) { // If the owner doesn't exist at all, we don't extract anything. - if ($this->getOwnerName($uri) === FALSE) { - return FALSE; + if ($this->getOwnerName($uri)) { + $target = parent::getTarget($uri); + // Remove the preceding owner name including slash from the path. + $start = strpos($target, '/'); + return ($start === FALSE) ? '' : substr($target, $start + 1); } - $target = parent::getTarget($uri); - // Remove the preceding owner name including slash from the path. - $start = strpos($target, '/'); - $target = ($start === FALSE) ? '' : substr($target, $start + 1); - return $target; } /** - * {@inheritdoc} + * Returns a web accessible URL for the resource. + * + * This function should return a URL that can be embedded in a web page + * and accessed from a browser. For example, the external URL of + * "youtube://xIpLd0WQKCY" might be + * "http://www.youtube.com/watch?v=xIpLd0WQKCY". + * + * @return string + * Returns a string containing a web accessible URL for the resource. + * + * @throws \InvalidArgumentException */ public function getExternalUrl($uri = NULL) { $dir = $this->getDirectoryPath($uri); if (empty($dir)) { - return FALSE; + throw new \InvalidArgumentException(sprintf('Extension directory for %s does not exist.', $uri)); } $target = $this->extractTarget($uri); diff --git a/core/lib/Drupal/Core/StreamWrapper/ThemeStream.php b/core/lib/Drupal/Core/StreamWrapper/ThemeStream.php index e59efd0..b7aa3ab 100644 --- a/core/lib/Drupal/Core/StreamWrapper/ThemeStream.php +++ b/core/lib/Drupal/Core/StreamWrapper/ThemeStream.php @@ -8,15 +8,7 @@ namespace Drupal\Core\StreamWrapper; /** - * Defines a read-only Drupal stream wrapper base class for themes. - * - * This class extends the complete stream wrapper implementation in LocalStream. - * URIs such as "theme://bartik" are expanded to a normal filesystem path - * such as "themes/bartik" and then PHP filesystem functions are invoked. - * - * Specifying "theme://current" returns a stream for the current theme, - * "theme://default" returns a stream for the default theme, and "theme://admin" - * returns a stream for the admin theme. + * Defines the read-only theme:// stream wrapper for theme files. */ class ThemeStream extends SystemStream { @@ -37,7 +29,13 @@ public function getOwnerName($uri = NULL) { break; } // Return name only for enabled themes. - return array_key_exists($name, \Drupal::service('theme_handler')->listInfo()) ? $name : FALSE; + if (array_key_exists($name, \Drupal::service('theme_handler')->listInfo())) { + return $name; + } + else { + // The theme does not exist or is disabled. + throw new \InvalidArgumentException(sprintf('Theme %s does not exist or is disabled', $name)); + } } /** diff --git a/core/modules/system/src/Tests/File/SystemStreamUnitTest.php b/core/modules/system/src/Tests/File/SystemStreamUnitTest.php index 691f309..e1de808 100644 --- a/core/modules/system/src/Tests/File/SystemStreamUnitTest.php +++ b/core/modules/system/src/Tests/File/SystemStreamUnitTest.php @@ -7,6 +7,7 @@ namespace Drupal\system\Tests\File; +use Drupal\Component\Utility\String; use Drupal\Core\Site\Settings; use Drupal\simpletest\KernelTestBase; @@ -78,10 +79,10 @@ public function testInvalidStreamUriException() { foreach ($bad_uris as $bad_uri) { try { $instance->getOwnerName($bad_uri); - $this->fail(format_string('Invalid uri %uri not detected.', array('%uri' => $bad_uri))); + $this->fail(String::format('Invalid uri %uri not detected.', array('%uri' => $bad_uri))); } catch (\InvalidArgumentException $e) { - $this->pass(format_string('Throw exception on invalid uri %uri supplied.', array('%uri' => $bad_uri))); + $this->pass(String::format('Throw exception on invalid uri %uri supplied.', array('%uri' => $bad_uri))); } } } @@ -91,102 +92,170 @@ public function testInvalidStreamUriException() { */ public function testModuleStream() { // Generate a module stream wrapper instance. - $uri1 = 'module://system'; - $uri2 = 'module://system/css/system.admin.css'; - $uri3 = 'module://file_test/file_test.dummy.inc'; - $uri4 = 'module://file_test/includes/file_test.dummy.inc'; - $uri5 = 'module://ckeditor/ckeditor.info.yml'; - $uri6 = 'module://foo_bar/foo.bar.js'; - /** @var \Drupal\Core\StreamWrapper\ModuleStream $instance */ $instance = file_stream_wrapper_get_instance_by_scheme('module'); // getOwnerName() - $this->assertEqual($instance->getOwnerName($uri1), 'system', 'Extract module name from a partial URI.'); - $this->assertEqual($instance->getOwnerName($uri2), 'system', 'Extract module name for a resource located in a subdirectory.'); - $this->assertEqual($instance->getOwnerName($uri3), 'file_test', 'Extract module name for a module located in a subdirectory.'); - $this->assertEqual($instance->getOwnerName($uri4), 'file_test', 'Extract module name even for a non-existing resource, as long as the module exists.'); - $this->assertFalse($instance->getOwnerName($uri5), "Fail returning a disabled module's name."); - $this->assertFalse($instance->getOwnerName($uri6), "Fail returning a non-existing module's name."); + $data = $this->providerModuleStream('getOwnerName'); + $this->runTestOnInstanceMethod($instance, 'getOwnerName', $data); // getTarget() - $this->assertEqual($instance->getTarget($uri1), '', 'Return empty target from a partial URI.'); - $this->assertEqual($instance->getTarget($uri2), 'css/system.admin.css', 'Extract target for a resource located in a subdirectory.'); - $this->assertEqual($instance->getTarget($uri3), 'file_test.dummy.inc', 'Extract target for a module in a non-standard location.'); - $this->assertFalse($instance->getTarget($uri4), 'Fail returning a target for a non-existing resource.'); - $this->assertFalse($instance->getTarget($uri5), "Fail returning a target within a disabled module."); - $this->assertFalse($instance->getTarget($uri6), "Fail returning a target within a non-existing module."); + $data = $this->providerModuleStream('getTarget'); + $this->runTestOnInstanceMethod($instance, 'getTarget', $data); // getDirectoryPath() - $this->assertEqual($instance->getDirectoryPath($uri1), 'core/modules/system', "Lookup module's directory path for a partial URI."); - $this->assertEqual($instance->getDirectoryPath($uri2), 'core/modules/system', "Lookup module's directory path for a resource located in a subdirectory."); - $this->assertEqual($instance->getDirectoryPath($uri3), 'core/modules/file/tests/file_test', "Lookup module's directory path for a module located in a subdirectory."); - $this->assertEqual($instance->getDirectoryPath($uri4), 'core/modules/file/tests/file_test', "Lookup module's directory path even for a non-existing resource, as long as the module exists."); - $this->assertFalse($instance->getDirectoryPath($uri5), "Fail returning a disabled module's directory path"); - $this->assertFalse($instance->getDirectoryPath($uri6), "Fail returning a non-existing module's directory path."); + $data = $this->providerModuleStream('getDirectoryPath'); + $this->runTestOnInstanceMethod($instance, 'getDirectoryPath', $data); // getExternalUrl() - $base_url = \Drupal::request()->getUri(); - $this->assertEqual($instance->getExternalUrl($uri1), $base_url . 'core/modules/system', "Return the external url for the module directory path."); - $this->assertEqual($instance->getExternalUrl($uri2), $base_url . 'core/modules/system/css/system.admin.css', "Return the external url of a resource located in a subdirectory."); - $this->assertEqual($instance->getExternalUrl($uri3), $base_url . 'core/modules/file/tests/file_test/file_test.dummy.inc', "Return the external url of an include file located in a subdirectory."); - $this->assertEqual($instance->getExternalUrl($uri4), $base_url . 'core/modules/file/tests/file_test/includes/file_test.dummy.inc', "Return the external url even for a non-existing resource, as long as the module exists."); - $this->assertFalse($instance->getExternalUrl($uri5), "Fail returning the external uri for resources in a disabled module."); - $this->assertFalse($instance->getExternalUrl($uri6), "Fail returning the external uri for resources in a non-existing module."); + $data = $this->providerModuleStream('getExternalUrl'); + $this->runTestOnInstanceMethod($instance, 'getExternalUrl', $data); + } + + /** + * Provides test data for testModuleStream() + */ + protected function providerModuleStream($method) { + $uris = array( + 'module://system', + 'module://system/css/system.admin.css', + 'module://file_test/file_test.dummy.inc', + 'module://file_test/includes/file_test.dummy.inc', + 'module://ckeditor/ckeditor.info.yml', + 'module://foo_bar/foo.bar.js', + ); + + switch ($method) { + case 'getOwnerName': + return array_combine($uris, array( + array('system', 'Extract module name from a partial URI.'), + array('system', 'Extract module name for a resource located in a subdirectory.'), + array('file_test', 'Extract module name for a module located in a subdirectory.'), + array('file_test', 'Extract module name even for a non-existing resource, as long as the module exists.'), + array(new \InvalidArgumentException(), 'Fail returning a disabled module\'s name.'), + array(new \InvalidArgumentException(), 'Fail returning a non-existing module\'s name.'), + )); + + case 'getTarget': + return array_combine($uris, array( + array('', 'Return empty target from a partial URI.'), + array('css/system.admin.css', 'Extract target for a resource located in a subdirectory.'), + array('file_test.dummy.inc', 'Extract target for a module in a non-standard location.'), + array(new \InvalidArgumentException(), 'Fail extracting a target for a non-existing resource.'), + array(new \InvalidArgumentException(), 'Fail extracting a target within a disabled module.'), + array(new \InvalidArgumentException(), 'Fail extracting a target within a non-existing module.'), + )); + + case 'getDirectoryPath': + return array_combine($uris, array( + array('core/modules/system', "Lookup module's directory path for a partial URI."), + array('core/modules/system', "Lookup module's directory path for a resource located in a subdirectory."), + array('core/modules/file/tests/file_test', "Lookup module's directory path for a module located in a subdirectory."), + array('core/modules/file/tests/file_test', "Lookup module's directory path even for a non-existing resource, as long as the module exists."), + array(new \InvalidArgumentException(), "Fail lookup of a disabled module's directory path"), + array(new \InvalidArgumentException(), "Fail lookup of a non-existing module's directory path."), + )); + + case 'getExternalUrl': + $base_url = \Drupal::request()->getUri(); + return array_combine($uris, array( + array($base_url . 'core/modules/system', "Return the external url for the module directory path."), + array($base_url . 'core/modules/system/css/system.admin.css', "Return the external url of a resource located in a subdirectory."), + array($base_url . 'core/modules/file/tests/file_test/file_test.dummy.inc', "Return the external url of an include file located in a subdirectory."), + array($base_url . 'core/modules/file/tests/file_test/includes/file_test.dummy.inc', "Return the external url even for a non-existing resource, as long as the module exists."), + array(new \InvalidArgumentException(), "Fail returning the external uri for resources in a disabled module."), + array(new \InvalidArgumentException(), "Fail returning the external uri for resources in a non-existing module."), + )); + } } /** * Test the Profile stream wrapper functions. */ public function testProfileStream() { - $uri1 = 'profile://minimal'; - $uri2 = 'profile://minimal/config/install/block.block.stark_login.yml'; - $uri3 = 'profile://minimal/config/install/node.type.article.yml'; - $uri4 = 'profile://foo_bar/'; - $uri5 = 'profile://current'; - $uri6 = 'profile://current/standard.info.yml'; - + // Generate a profile stream wrapper instance. /** @var \Drupal\Core\StreamWrapper\ProfileStream $instance */ $instance = file_stream_wrapper_get_instance_by_scheme('profile'); // getOwnerName() - $this->assertEqual($instance->getOwnerName($uri1), 'minimal', "Extract profile's name from a partial URI."); - $this->assertEqual($instance->getOwnerName($uri2), 'minimal', "Extract profile's name for a resource located in a subdirectory."); - $this->assertEqual($instance->getOwnerName($uri3), 'minimal', "Extract profile's name even for a non-existing resource, as long as the profile exists."); - $this->assertFalse($instance->getOwnerName($uri4), "Fail returning a non-existing profile's name."); - $this->assertEqual($instance->getOwnerName($uri5), 'standard', format_string('Lookup real name of %current for a partial URI.', array('%current' => 'profile://current'))); - $this->assertEqual($instance->getOwnerName($uri6), 'standard', format_string('Lookup real name of %current for a resource.', array('%current' => 'profile://current'))); + $data = $this->providerProfileStream('getOwnerName'); + $this->runTestOnInstanceMethod($instance, 'getOwnerName', $data); // getTarget() - $this->assertEqual($instance->getTarget($uri1), '', 'Return empty target for a partial URI giving only the profile.'); - $this->assertEqual($instance->getTarget($uri2), 'config/install/block.block.stark_login.yml', 'Extract target for a resource located in a subdirectory.'); - $this->assertFalse($instance->getTarget($uri3), 'Fail returning a target for a non-existing resource.'); - $this->assertFalse($instance->getTarget($uri4), 'Fail returning a target within a non-existing profile.'); - $this->assertEqual($instance->getTarget($uri5), '', format_string('Return empty target for a partial URI giving only %current.', array('%current' => 'profile://current'))); - $this->assertEqual($instance->getTarget($uri6), 'standard.info.yml', format_string("Extract target from a resource within %current.", array('%current' => 'profile://current'))); + $data = $this->providerProfileStream('getTarget'); + $this->runTestOnInstanceMethod($instance, 'getTarget', $data); // getDirectoryPath() - $this->assertEqual($instance->getDirectoryPath($uri1), 'core/profiles/minimal', "Lookup profile's directory path for a partial URI."); - $this->assertEqual($instance->getDirectoryPath($uri2), 'core/profiles/minimal', "Lookup profile's directory path for a resource located in a subdirectory."); - $this->assertEqual($instance->getDirectoryPath($uri3), 'core/profiles/minimal', "Lookup profile's directory path even for a non-existing resource, as long as the profile exists."); - $this->assertFalse($instance->getDirectoryPath($uri4), "Fail returning a non-existing profile's directory path."); - $this->assertEqual($instance->getDirectoryPath($uri5), 'core/profiles/standard', format_string('Lookup real directory path of %current for a partial URI.', array('%current' => 'profile://current'))); - $this->assertEqual($instance->getDirectoryPath($uri6), 'core/profiles/standard', format_string('Lookup real directory path of %current for a resource.', array('%current' => 'profile://current'))); + $data = $this->providerProfileStream('getDirectoryPath'); + $this->runTestOnInstanceMethod($instance, 'getDirectoryPath', $data); // getExternalUrl() - $base_url = \Drupal::request()->getUri(); - $this->assertEqual($instance->getExternalUrl($uri1), $base_url . 'core/profiles/minimal', "Return the external url for the profile directory path."); - $this->assertEqual($instance->getExternalUrl($uri2), $base_url . 'core/profiles/minimal/config/install/block.block.stark_login.yml', "Return the external url of a file located in a subdirectory."); - $this->assertEqual($instance->getExternalUrl($uri3), $base_url . 'core/profiles/minimal/config/install/node.type.article.yml', "Return the external url of a non-existing file located in a subdirectory."); - $this->assertFalse($instance->getExternalUrl($uri4), "Fail returning the external uri for a disabled profile."); - $this->assertEqual($instance->getExternalUrl($uri5), $base_url . 'core/profiles/standard', format_string('Lookup the external url of %current for a partial URI.', array('%current' => 'profile://current'))); - $this->assertEqual($instance->getExternalUrl($uri6), $base_url . 'core/profiles/standard/standard.info.yml', format_string('Lookup the external url of %current for a resource.', array('%current' => 'profile://current'))); + $data = $this->providerProfileStream('getExternalUrl'); + $this->runTestOnInstanceMethod($instance, 'getExternalUrl', $data); + } + + /** + * Provides test data for testProfileStream() + */ + protected function providerProfileStream($method) { + $uris = array( + 'profile://minimal', + 'profile://minimal/config/install/block.block.stark_login.yml', + 'profile://minimal/config/install/node.type.article.yml', + 'profile://foo_bar/', + 'profile://current', + 'profile://current/standard.info.yml', + ); + + switch ($method) { + case 'getOwnerName': + return array_combine($uris, array( + array('minimal', "Extract profile's name from a partial URI."), + array('minimal', "Extract profile's name for a resource located in a subdirectory."), + array('minimal', "Extract profile's name even for a non-existing resource, as long as the profile exists."), + array(new \InvalidArgumentException(), "Fail returning a non-existing profile's name."), + array('standard', String::format('Lookup real name of %current for a partial URI.', array('%current' => 'profile://current'))), + array('standard', String::format('Lookup real name of %current for a resource.', array('%current' => 'profile://current'))), + )); + + case 'getTarget': + return array_combine($uris, array( + array('', 'Return empty target for a partial URI giving only the profile.'), + array('config/install/block.block.stark_login.yml', 'Extract target for a resource located in a subdirectory.'), + array(new \InvalidArgumentException(), 'Fail returning a target for a non-existing resource.'), + array(new \InvalidArgumentException(), 'Fail returning a target within a non-existing profile.'), + array('', String::format('Return empty target for a partial URI giving only %current.', array('%current' => 'profile://current'))), + array('standard.info.yml', String::format("Extract target from a resource within %current.", array('%current' => 'profile://current'))), + )); + + case 'getDirectoryPath': + return array_combine($uris, array( + array('core/profiles/minimal', "Lookup profile's directory path for a partial URI."), + array('core/profiles/minimal', "Lookup profile's directory path for a resource located in a subdirectory."), + array('core/profiles/minimal', "Lookup profile's directory path even for a non-existing resource, as long as the profile exists."), + array(new \InvalidArgumentException(), "Fail returning a non-existing profile's directory path."), + array('core/profiles/standard', String::format('Lookup real directory path of %current for a partial URI.', array('%current' => 'profile://current'))), + array('core/profiles/standard', String::format('Lookup real directory path of %current for a resource.', array('%current' => 'profile://current'))), + )); + + case 'getExternalUrl': + $base_url = \Drupal::request()->getUri(); + return array_combine($uris, array( + array($base_url . 'core/profiles/minimal', "Return the external url for the profile directory path."), + array($base_url . 'core/profiles/minimal/config/install/block.block.stark_login.yml', "Return the external url of a file located in a subdirectory."), + array($base_url . 'core/profiles/minimal/config/install/node.type.article.yml', "Return the external url of a non-existing file located in a subdirectory."), + array(new \InvalidArgumentException(), "Fail returning the external uri for a disabled profile."), + array($base_url . 'core/profiles/standard', String::format('Lookup the external url of %current for a partial URI.', array('%current' => 'profile://current'))), + array($base_url . 'core/profiles/standard/standard.info.yml', String::format('Lookup the external url of %current for a resource.', array('%current' => 'profile://current'))), + )); + } } /** * Test the Theme stream wrapper functions. */ public function testThemeStream() { + // Generate a theme stream wrapper instance. /** @var \Drupal\Core\Extension\ThemeHandler $theme_handler */ $theme_handler = \Drupal::service('theme_handler'); @@ -197,82 +266,147 @@ public function testThemeStream() { $system_theme = \Drupal::config('system.theme'); $this->assertNull($system_theme->get('admin'), 'No admin theme was set.'); $system_theme->set('admin', 'seven')->save(); - $this->assertEqual($system_theme->get('admin'), 'seven', format_string('Make %seven the admin theme.', array('%seven' => 'Seven'))); + $this->assertEqual($system_theme->get('admin'), 'seven', String::format('Make %seven the admin theme.', array('%seven' => 'Seven'))); // Set default theme to Bartik. $theme_handler->setDefault('bartik'); - $this->assertEqual($theme_handler->getDefault(), 'bartik', format_string('Make %bartik the default theme.', array('%bartik' => 'Bartik'))); + $this->assertEqual($theme_handler->getDefault(), 'bartik', String::format('Make %bartik the default theme.', array('%bartik' => 'Bartik'))); // Disable Stark theme. $theme_handler->disable(array('stark')); - $uri1 = 'theme://seven'; - $uri2 = 'theme://seven/style.css'; - $uri3 = 'theme://bartik/color/preview.js'; - $uri4 = 'theme://fifteen/screenshot.png'; - $uri5 = 'theme://current'; - $uri6 = 'theme://current/logo.png'; - $uri7 = 'theme://default'; - $uri8 = 'theme://default/bartik.info.yml'; - $uri9 = 'theme://admin'; - $uri10 = 'theme://admin/fake.info.yml'; - $uri11 = 'theme://stark/stark.info.yml'; - /** @var \Drupal\Core\StreamWrapper\ThemeStream $instance */ $instance = file_stream_wrapper_get_instance_by_scheme('theme'); // getOwnerName() - $this->assertEqual($instance->getOwnerName($uri1), 'seven', "Extract theme's name from a partial URI."); - $this->assertEqual($instance->getOwnerName($uri2), 'seven', "Extract theme's name from a full URI."); - $this->assertEqual($instance->getOwnerName($uri3), 'bartik', "Extract theme's name from a full URI with subdirectory."); - $this->assertFalse($instance->getOwnerName($uri4), "Fail returning a non-existing theme's name."); - $this->assertEqual($instance->getOwnerName($uri5), 'bartik', format_string('Lookup real name of %current for a partial URI.', array('%current' => 'theme://current')) . $instance->getOwnerName($uri5)); - $this->assertEqual($instance->getOwnerName($uri6), 'bartik', format_string('Lookup real name of %current for a resource.', array('%current' => 'theme://current')) . $instance->getOwnerName($uri6)); - $this->assertEqual($instance->getOwnerName($uri7), 'bartik', format_string('Lookup real name of %default for a partial URI.', array('%default' => 'theme://default'))); - $this->assertEqual($instance->getOwnerName($uri8), 'bartik', format_string('Lookup real name of %default for a resource.', array('%default' => 'theme://default'))); - $this->assertEqual($instance->getOwnerName($uri9), 'seven', format_string('Lookup real name of %admin for a partial URI.', array('%admin' => 'theme://admin'))); - $this->assertEqual($instance->getOwnerName($uri10), 'seven', format_string('Lookup real name of %admin even for a non-existing resource.', array('%admin' => 'theme://admin'))); - $this->assertFalse($instance->getOwnerName($uri11), "Fail returning a disabled theme's name."); + $data = $this->providerThemeStream('getOwnerName'); + $this->runTestOnInstanceMethod($instance, 'getOwnerName', $data); // getTarget() - $this->assertEqual($instance->getTarget($uri1), '', 'Return empty target for a partial URI giving only the theme.'); - $this->assertFalse($instance->getTarget($uri2), 'Fail returning a target for a non-existent resource.'); - $this->assertEqual($instance->getTarget($uri3), 'color/preview.js', 'Extract target for a resource located in a subdirectory.'); - $this->assertFalse($instance->getTarget($uri4), 'Fail returning a target within a non-existing theme.'); - $this->assertEqual($instance->getTarget($uri5), '', format_string('Return empty target for a partial URI giving only %current.', array('%current' => 'theme://current'))); - $this->assertEqual($instance->getTarget($uri6), 'logo.png', format_string("Extract target from a resource within %current.", array('%current' => 'theme://current'))); - $this->assertEqual($instance->getTarget($uri7), '', format_string('Return empty target for a partial URI giving only %default.', array('%default' => 'theme://default'))); - $this->assertEqual($instance->getTarget($uri8), 'bartik.info.yml', format_string("Extract target from a resource located in a subdirectory of %default.", array('%default' => 'theme://default')) . $instance->getTarget($uri8)); - $this->assertEqual($instance->getTarget($uri9), '', format_string('Return empty target for a partial URI giving only %admin.', array('%admin' => 'theme://admin'))); - $this->assertFalse($instance->getTarget($uri10), format_string("Fail returning target for a non-existing resource within %admin.", array('%admin' => 'theme://admin'))); - $this->assertFalse($instance->getTarget($uri11), "Fail returning a target for a disabled theme."); + $data = $this->providerThemeStream('getTarget'); + $this->runTestOnInstanceMethod($instance, 'getTarget', $data); // getDirectoryPath() - $this->assertEqual($instance->getDirectoryPath($uri1), 'core/themes/seven', "Lookup theme's directory path for a partial URI."); - $this->assertEqual($instance->getDirectoryPath($uri2), 'core/themes/seven', "Lookup theme's directory path for a resource located in a subdirectory."); - $this->assertEqual($instance->getDirectoryPath($uri3), 'core/themes/bartik', "Lookup theme's directory path for a resource."); - $this->assertFalse($instance->getDirectoryPath($uri4), "Fail returning a non-existing theme's directory path."); - $this->assertEqual($instance->getDirectoryPath($uri5), 'core/themes/bartik', format_string('Lookup real directory path of %current for a partial URI.', array('%current' => 'theme://current'))); - $this->assertEqual($instance->getDirectoryPath($uri6), 'core/themes/bartik', format_string('Lookup real directory path of %current for a resource.', array('%current' => 'theme://current'))); - $this->assertEqual($instance->getDirectoryPath($uri7), 'core/themes/bartik', format_string('Lookup real directory path of %default for a partial URI.', array('%default' => 'theme://default'))); - $this->assertEqual($instance->getDirectoryPath($uri8), 'core/themes/bartik', format_string('Lookup real directory path of %default for a resource.', array('%default' => 'theme://default'))); - $this->assertEqual($instance->getDirectoryPath($uri9), 'core/themes/seven', format_string('Lookup real directory path of %admin for a partial URI.', array('%admin' => 'theme://admin'))); - $this->assertEqual($instance->getDirectoryPath($uri10), 'core/themes/seven', format_string('Lookup real directory path of %admin for a resource.', array('%admin' => 'theme://admin'))); - $this->assertFalse($instance->getDirectoryPath($uri11), "Fail returning a disabled theme's directory path."); + $data = $this->providerThemeStream('getDirectoryPath'); + $this->runTestOnInstanceMethod($instance, 'getDirectoryPath', $data); // getExternalUrl() - $base_url = \Drupal::request()->getUri(); - $this->assertEqual($instance->getExternalUrl($uri1), $base_url . 'core/themes/seven', "Lookup theme's external url for a partial URI."); - $this->assertEqual($instance->getExternalUrl($uri2), $base_url . 'core/themes/seven/style.css', "Lookup theme's external url for a resource located in a subdirectory."); - $this->assertEqual($instance->getExternalUrl($uri3), $base_url . 'core/themes/bartik/color/preview.js', "Lookup theme's external url for a resource."); - $this->assertFalse($instance->getExternalUrl($uri4), "Fail returning a non-existing theme's external url."); - $this->assertEqual($instance->getExternalUrl($uri5), $base_url . 'core/themes/bartik', format_string('Lookup real external url of %current for a partial URI.', array('%current' => 'theme://current'))); - $this->assertEqual($instance->getExternalUrl($uri6), $base_url . 'core/themes/bartik/logo.png', format_string('Lookup external url of %current for a resource.', array('%current' => 'theme://current'))); - $this->assertEqual($instance->getExternalUrl($uri7), $base_url . 'core/themes/bartik', format_string('Lookup external url of %default for a partial URI.', array('%default' => 'theme://default'))); - $this->assertEqual($instance->getExternalUrl($uri8), $base_url . 'core/themes/bartik/bartik.info.yml', format_string('Lookup external url of %default for a resource.', array('%default' => 'theme://default'))); - $this->assertEqual($instance->getExternalUrl($uri9), $base_url . 'core/themes/seven', format_string('Lookup external url of %admin for a partial URI.', array('%admin' => 'theme://admin'))); - $this->assertEqual($instance->getExternalUrl($uri10), $base_url . 'core/themes/seven/fake.info.yml', format_string('Lookup external url of %admin for a resource.', array('%admin' => 'theme://admin'))); - $this->assertFalse($instance->getExternalUrl($uri11), "Fail returning a disabled theme's external url."); + $data = $this->providerThemeStream('getExternalUrl'); + $this->runTestOnInstanceMethod($instance, 'getExternalUrl', $data); + } + /** + * Provides test data for testThemeStream() + */ + protected function providerThemeStream($method) { + $uris = array( + 'theme://seven', + 'theme://seven/style.css', + 'theme://bartik/color/preview.js', + 'theme://fifteen/screenshot.png', + 'theme://current', + 'theme://current/logo.png', + 'theme://default', + 'theme://default/bartik.info.yml', + 'theme://admin', + 'theme://admin/fake.info.yml', + 'theme://stark/stark.info.yml', + ); + + switch ($method) { + case 'getOwnerName': + return array_combine($uris, array( + array('seven', "Extract theme's name from a partial URI."), + array('seven', "Extract theme's name from a full URI."), + array('bartik', "Extract theme's name from a full URI with subdirectory."), + array(new \InvalidArgumentException(), "Fail returning a non-existing theme's name."), + array('bartik', String::format('Lookup real name of %current for a partial URI.', array('%current' => 'theme://current'))), + array('bartik', String::format('Lookup real name of %current for a resource.', array('%current' => 'theme://current'))), + array('bartik', String::format('Lookup real name of %default for a partial URI.', array('%default' => 'theme://default'))), + array('bartik', String::format('Lookup real name of %default for a resource.', array('%default' => 'theme://default'))), + array('seven', String::format('Lookup real name of %admin for a partial URI.', array('%admin' => 'theme://admin'))), + array('seven', String::format('Lookup real name of %admin even for a non-existing resource.', array('%admin' => 'theme://admin'))), + array(new \InvalidArgumentException(), "Fail returning a disabled theme's name."), + )); + + case 'getTarget': + return array_combine($uris, array( + array('', 'Return empty target for a partial URI giving only the theme.'), + array(new \InvalidArgumentException(), 'Fail returning a target for a non-existent resource.'), + array('color/preview.js', 'Extract target for a resource located in a subdirectory.'), + array(new \InvalidArgumentException(), 'Fail returning a target within a non-existing theme.'), + array('', String::format('Return empty target for a partial URI giving only %current.', array('%current' => 'theme://current'))), + array('logo.png', String::format("Extract target from a resource within %current.", array('%current' => 'theme://current'))), + array('', String::format('Return empty target for a partial URI giving only %default.', array('%default' => 'theme://default'))), + array('bartik.info.yml', String::format("Extract target from a resource located in a subdirectory of %default.", array('%default' => 'theme://default'))), + array('', String::format('Return empty target for a partial URI giving only %admin.', array('%admin' => 'theme://admin'))), + array(new \InvalidArgumentException(), String::format("Fail returning target for a non-existing resource within %admin.", array('%admin' => 'theme://admin'))), + array(new \InvalidArgumentException(), "Fail returning a target for a disabled theme."), + )); + + case 'getDirectoryPath': + return array_combine($uris, array( + array('core/themes/seven', "Lookup theme's directory path for a partial URI."), + array('core/themes/seven', "Lookup theme's directory path for a resource located in a subdirectory."), + array('core/themes/bartik', "Lookup theme's directory path for a resource."), + array(new \InvalidArgumentException(), "Fail returning a non-existing theme's directory path."), + array('core/themes/bartik', String::format('Lookup real directory path of %current for a partial URI.', array('%current' => 'theme://current'))), + array('core/themes/bartik', String::format('Lookup real directory path of %current for a resource.', array('%current' => 'theme://current'))), + array('core/themes/bartik', String::format('Lookup real directory path of %default for a partial URI.', array('%default' => 'theme://default'))), + array('core/themes/bartik', String::format('Lookup real directory path of %default for a resource.', array('%default' => 'theme://default'))), + array('core/themes/seven', String::format('Lookup real directory path of %admin for a partial URI.', array('%admin' => 'theme://admin'))), + array('core/themes/seven', String::format('Lookup real directory path of %admin for a resource.', array('%admin' => 'theme://admin'))), + array(new \InvalidArgumentException(), "Fail returning a disabled theme's directory path."), + )); + + case 'getExternalUrl': + $base_url = \Drupal::request()->getUri(); + return array_combine($uris, array( + array($base_url . 'core/themes/seven', "Lookup theme's external url for a partial URI."), + array($base_url . 'core/themes/seven/style.css', "Lookup theme's external url for a resource located in a subdirectory."), + array($base_url . 'core/themes/bartik/color/preview.js', "Lookup theme's external url for a resource."), + array(new \InvalidArgumentException(), "Fail returning a non-existing theme's external url."), + array($base_url . 'core/themes/bartik', String::format('Lookup real external url of %current for a partial URI.', array('%current' => 'theme://current'))), + array($base_url . 'core/themes/bartik/logo.png', String::format('Lookup external url of %current for a resource.', array('%current' => 'theme://current'))), + array($base_url . 'core/themes/bartik', String::format('Lookup external url of %default for a partial URI.', array('%default' => 'theme://default'))), + array($base_url . 'core/themes/bartik/bartik.info.yml', String::format('Lookup external url of %default for a resource.', array('%default' => 'theme://default'))), + array($base_url . 'core/themes/seven', String::format('Lookup external url of %admin for a partial URI.', array('%admin' => 'theme://admin'))), + array($base_url . 'core/themes/seven/fake.info.yml', String::format('Lookup external url of %admin for a resource.', array('%admin' => 'theme://admin'))), + array(new \InvalidArgumentException(), "Fail returning a disabled theme's external url."), + )); + } + } + + + /** + * Helper method to run specific tests on each StreamWrapper method. + * + * @param \Drupal\Core\StreamWrapper\SystemStream $instance + * The stream wrapper instance to carry out the test on. + * @param string $method + * The SystemStream method to be tested. + * @param array $data + * An array of data to be used for the test, containing the following info: + * - The expected result. + * - The test result message. + */ + private function runTestOnInstanceMethod($instance, $method, array $data) { + foreach ($data as $uri => $info) { + if ($info[0] instanceof \Exception) { + try { + $instance->$method($uri); + $this->fail($info[1]); + } + catch (\Exception $e) { + if (get_class($e) == get_class($info[0])) { + $this->pass($info[1]); + } + } + } + else { + $this->assertEqual($instance->$method($uri), $info[0], $info[1]); + } + } } + }