diff --git a/core/core.services.yml b/core/core.services.yml index da2d413..793df76 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -456,6 +456,9 @@ services: plugin.manager.condition: class: Drupal\Core\Condition\ConditionManager arguments: ['@container.namespaces', '@cache.cache', '@language_manager', '@module_handler'] + plugin.manager.stream_wrapper: + class: Drupal\Core\StreamWrapper\StreamWrapperManager + arguments: ['@container.namespaces', '@module_handler'] kernel_destruct_subscriber: class: Drupal\Core\EventSubscriber\KernelDestructionSubscriber tags: diff --git a/core/includes/file.inc b/core/includes/file.inc index 58644ff..5d7af0d 100644 --- a/core/includes/file.inc +++ b/core/includes/file.inc @@ -5,6 +5,7 @@ * API for handling file uploads and server file management. */ +use Drupal\Component\Plugin\Exception\PluginException; use Drupal\Core\StreamWrapper\LocalStream; use Drupal\Component\PhpStorage\MTimeProtectedFastFileStorage; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; @@ -140,37 +141,8 @@ /** * Provides Drupal stream wrapper registry. * - * A stream wrapper is an abstraction of a file system that allows Drupal to - * use the same set of methods to access both local files and remote resources. * - * Provide a facility for managing and querying user-defined stream wrappers - * in PHP. PHP's internal stream_get_wrappers() doesn't return the class - * registered to handle a stream, which we need to be able to find the handler - * for class instantiation. - * - * If a module registers a scheme that is already registered with PHP, the - * existing scheme will be unregistered and replaced with the specified class. - * - * A stream is referenced as "scheme://target". - * - * The optional $filter parameter can be used to retrieve only the stream - * wrappers that are appropriate for particular usage. For example, this returns - * only stream wrappers that use local file storage: - * @code - * $local_stream_wrappers = file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL); - * @endcode - * - * The $filter parameter can only filter to types containing a particular flag. - * In some cases, you may want to filter to types that do not contain a - * particular flag. For example, you may want to retrieve all stream wrappers - * that are not writable, or all stream wrappers that are not local. PHP's - * array_diff_key() function can be used to help with this. For example, this - * returns only stream wrappers that do not use local file storage: - * @code - * $remote_stream_wrappers = array_diff_key(file_get_stream_wrappers(STREAM_WRAPPERS_ALL), file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL)); - * @endcode - * - * @param $filter + * @param int $filter * (Optional) Filters out all types except those with an on bit for each on * bit in $filter. For example, if $filter is STREAM_WRAPPERS_WRITE_VISIBLE, * which is equal to (STREAM_WRAPPERS_READ | STREAM_WRAPPERS_WRITE | @@ -178,7 +150,7 @@ * bits set are returned. Defaults to STREAM_WRAPPERS_ALL, which returns all * registered stream wrappers. * - * @return + * @return array * An array keyed by scheme, with values containing an array of information * about the stream wrapper, as returned by hook_stream_wrappers(). If $filter * is omitted or set to STREAM_WRAPPERS_ALL, the entire Drupal stream wrapper @@ -187,78 +159,33 @@ * * @see hook_stream_wrappers() * @see hook_stream_wrappers_alter() + * @see \Drupal\Core\StreamWrapper\StreamWrapperManager */ function file_get_stream_wrappers($filter = STREAM_WRAPPERS_ALL) { - $wrappers_storage = &drupal_static(__FUNCTION__); - - if (!isset($wrappers_storage)) { - $wrappers = module_invoke_all('stream_wrappers'); - foreach ($wrappers as $scheme => $info) { - // Add defaults. - $wrappers[$scheme] += array('type' => STREAM_WRAPPERS_NORMAL); - } - drupal_alter('stream_wrappers', $wrappers); - $existing = stream_get_wrappers(); - foreach ($wrappers as $scheme => $info) { - // We only register classes that implement our interface. - if (in_array('Drupal\Core\StreamWrapper\StreamWrapperInterface', class_implements($info['class']), TRUE)) { - // Record whether we are overriding an existing scheme. - if (in_array($scheme, $existing, TRUE)) { - $wrappers[$scheme]['override'] = TRUE; - stream_wrapper_unregister($scheme); - } - else { - $wrappers[$scheme]['override'] = FALSE; - } - if (($info['type'] & STREAM_WRAPPERS_LOCAL) == STREAM_WRAPPERS_LOCAL) { - stream_wrapper_register($scheme, $info['class']); - } - else { - stream_wrapper_register($scheme, $info['class'], STREAM_IS_URL); - } - } - // Pre-populate the static cache with the filters most typically used. - $wrappers_storage[STREAM_WRAPPERS_ALL][$scheme] = $wrappers[$scheme]; - if (($info['type'] & STREAM_WRAPPERS_WRITE_VISIBLE) == STREAM_WRAPPERS_WRITE_VISIBLE) { - $wrappers_storage[STREAM_WRAPPERS_WRITE_VISIBLE][$scheme] = $wrappers[$scheme]; - } - } - } - - if (!isset($wrappers_storage[$filter])) { - $wrappers_storage[$filter] = array(); - foreach ($wrappers_storage[STREAM_WRAPPERS_ALL] as $scheme => $info) { - // Bit-wise filter. - if (($info['type'] & $filter) == $filter) { - $wrappers_storage[$filter][$scheme] = $info; - } - } - } - - return $wrappers_storage[$filter]; + return Drupal::service('plugin.manager.stream_wrapper')->getWrappers($filter); } /** * Returns the stream wrapper class name for a given scheme. * - * @param $scheme + * @param string $scheme * Stream scheme. * - * @return + * @return string|bool * Return string if a scheme has a registered handler, or FALSE. */ function file_stream_wrapper_get_class($scheme) { - $wrappers = file_get_stream_wrappers(); - return empty($wrappers[$scheme]) ? FALSE : $wrappers[$scheme]['class']; + $wrapper = Drupal::service('plugin.manager.stream_wrapper')->getDefinition($scheme); + return !empty($wrapper) ? $wrapper['class'] : FALSE; } /** * Returns the scheme of a URI (e.g. a stream). * - * @param $uri + * @param string $uri * A stream, referenced as "scheme://target". * - * @return + * @return string|bool * A string containing the name of the scheme, or FALSE if none. For example, * the URI "public://example.txt" would return "public". * @@ -276,10 +203,10 @@ function file_uri_scheme($uri) { * and that it is callable. This is useful if you want to confirm a valid * scheme without creating a new instance of the registered handler. * - * @param $scheme + * @param string $scheme * A URI scheme, a stream is referenced as "scheme://target". * - * @return + * @return bool * Returns TRUE if the string is the name of a validated stream, * or FALSE if the scheme does not have a registered handler. */ @@ -291,10 +218,10 @@ function file_stream_wrapper_valid_scheme($scheme) { /** * Returns the part of a URI after the schema. * - * @param $uri + * @param string $uri * A stream, referenced as "scheme://target". * - * @return + * @return string|bool * A string containing the target (path), or FALSE if none. * For example, the URI "public://sample/test.txt" would return * "sample/test.txt". @@ -311,7 +238,7 @@ function file_uri_target($uri) { /** * Gets the default file stream implementation. * - * @return + * @return string * 'public', 'private' or any other file scheme defined as the default. */ function file_default_scheme() { @@ -327,10 +254,10 @@ function file_default_scheme() { * - Remove trailing slashes from target * - Trim erroneous leading slashes from target. e.g. ":///" becomes "://". * - * @param $uri + * @param string $uri * String reference containing the URI to normalize. * - * @return + * @return string * The normalized URI. */ function file_stream_wrapper_uri_normalize($uri) { @@ -353,25 +280,17 @@ function file_stream_wrapper_uri_normalize($uri) { * The scheme determines the stream wrapper class that should be * used by consulting the stream wrapper registry. * - * @param $uri + * @param string $uri * A stream, referenced as "scheme://target". * - * @return + * @return \Drupal\Core\StreamWrapper\StreamWrapperInterface|bool * Returns a new stream wrapper object appropriate for the given URI or FALSE * if no registered handler could be found. For example, a URI of * "private://example.txt" would return a new private stream wrapper object * (Drupal\Core\StreamWrapper\PrivateStream). */ function file_stream_wrapper_get_instance_by_uri($uri) { - if ($scheme = file_uri_scheme($uri)) { - $class = file_stream_wrapper_get_class($scheme); - if (class_exists($class)) { - $instance = new $class(); - $instance->setUri($uri); - return $instance; - } - } - return FALSE; + return Drupal::service('plugin.manager.stream_wrapper')->getInstance(array('uri' => $uri)); } /** @@ -385,25 +304,17 @@ function file_stream_wrapper_get_instance_by_uri($uri) { * Note: the instance URI will be initialized to "scheme://" so that you can * make the customary method calls as if you had retrieved an instance by URI. * - * @param $scheme + * @param string $scheme * If the stream was "public://target", "public" would be the scheme. * - * @return + * @return \Drupal\Core\StreamWrapper\StreamWrapperInterface|bool * Returns a new stream wrapper object appropriate for the given $scheme. * For example, for the public scheme a stream wrapper object * (Drupal\Core\StreamWrapper\PublicStream). * FALSE is returned if no registered handler could be found. */ function file_stream_wrapper_get_instance_by_scheme($scheme) { - $class = file_stream_wrapper_get_class($scheme); - if (class_exists($class)) { - $instance = new $class(); - $instance->setUri($scheme . '://'); - return $instance; - } - else { - return FALSE; - } + return Drupal::service('plugin.manager.stream_wrapper')->getInstance(array('scheme' => $scheme)); } /** diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index eefe926..2ada884 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -410,6 +410,12 @@ function install_begin_request(&$install_state) { $container ->register('module_handler', 'Drupal\Core\Extension\ModuleHandler'); + // Register the stream wrapper manager with an empty set of namespaces. + $container + ->register('plugin.manager.stream_wrapper', 'Drupal\Core\StreamWrapper\StreamWrapperManager') + ->addArgument(new ArrayObject()) + ->addArgument(new Reference('module_handler')); + // Register the Guzzle HTTP client for fetching translation files from a // remote translation server such as localization.drupal.org. $container->register('http_default_client', 'Guzzle\Http\Client') diff --git a/core/lib/Drupal/Core/Annotation/StreamWrapper.php b/core/lib/Drupal/Core/Annotation/StreamWrapper.php new file mode 100644 index 0000000..f72a6a6 --- /dev/null +++ b/core/lib/Drupal/Core/Annotation/StreamWrapper.php @@ -0,0 +1,68 @@ +alterInfo($module_handler, 'stream_wrappers'); + } + + /** + * Provides Drupal stream wrapper registry. + * + * A stream wrapper is an abstraction of a file system that allows Drupal to + * use the same set of methods to access both local files and remote resources. + * + * Provide a facility for managing and querying user-defined stream wrappers + * in PHP. PHP's internal stream_get_wrappers() doesn't return the class + * registered to handle a stream, which we need to be able to find the handler + * for class instantiation. + * + * If a module registers a scheme that is already registered with PHP, the + * existing scheme will be unregistered and replaced with the specified class. + * + * A stream is referenced as "scheme://target". + * + * The optional $filter parameter can be used to retrieve only the stream + * wrappers that are appropriate for particular usage. For example, this returns + * only stream wrappers that use local file storage: + * + * @code + * $local_stream_wrappers = file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL); + * @endcode + * + * The $filter parameter can only filter to types containing a particular flag. + * In some cases, you may want to filter to types that do not contain a + * particular flag. For example, you may want to retrieve all stream wrappers + * that are not writable, or all stream wrappers that are not local. PHP's + * array_diff_key() function can be used to help with this. For example, this + * returns only stream wrappers that do not use local file storage: + * @code + * $remote_stream_wrappers = array_diff_key(file_get_stream_wrappers(STREAM_WRAPPERS_ALL), file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL)); + * @endcode + * + * @param int $filter + * (Optional) Filters out all types except those with an on bit for each on + * bit in $filter. For example, if $filter is STREAM_WRAPPERS_WRITE_VISIBLE, + * which is equal to (STREAM_WRAPPERS_READ | STREAM_WRAPPERS_WRITE | + * STREAM_WRAPPERS_VISIBLE), then only stream wrappers with all three of these + * bits set are returned. Defaults to STREAM_WRAPPERS_ALL, which returns all + * registered stream wrappers. + * + * @return array + * An array keyed by scheme, with values containing an array of information + * about the stream wrapper, as returned by hook_stream_wrappers(). If $filter + * is omitted or set to STREAM_WRAPPERS_ALL, the entire Drupal stream wrapper + * registry is returned. Otherwise only the stream wrappers whose 'type' + * bitmask has an on bit for each bit specified in $filter are returned. + */ + public function getWrappers($filter = STREAM_WRAPPERS_ALL) { + if (!$this->wrappers) { + $wrappers = $this->getDefinitions(); + foreach ($wrappers as $scheme => $info) { + // Pre-populate the static cache with the filters most typically used. + $this->wrappers[STREAM_WRAPPERS_ALL][$scheme] = $info; + if (($info['type'] & STREAM_WRAPPERS_WRITE_VISIBLE) == STREAM_WRAPPERS_WRITE_VISIBLE) { + $this->wrappers[STREAM_WRAPPERS_WRITE_VISIBLE][$scheme] = $info; + } + } + } + + if (!isset($this->wrappers[$filter])) { + $this->wrappers[$filter] = array(); + foreach ($this->wrappers[STREAM_WRAPPERS_ALL] as $scheme => $info) { + // Bit-wise filter. + if (($info['type'] & $filter) == $filter) { + $this->wrappers[$filter][$scheme] = $info; + } + } + } + + return $this->wrappers[$filter]; + } + + /** + * {@inheritdoc} + */ + public function processDefinition(&$definition, $plugin_id) { + parent::processDefinition($definition, $plugin_id); + + // Record whether we are overriding an existing scheme. + if (in_array($plugin_id, stream_get_wrappers(), TRUE)) { + $definition['override'] = TRUE; + stream_wrapper_unregister($plugin_id); + } + else { + $definition['override'] = FALSE; + } + + if (($definition['type'] & STREAM_WRAPPERS_LOCAL) == STREAM_WRAPPERS_LOCAL) { + stream_wrapper_register($plugin_id, $definition['class']); + } + else { + stream_wrapper_register($plugin_id, $definition['class'], STREAM_IS_URL); + } + } + + /** + * {@inheritdoc} + */ + public function getInstance(array $options) { + if (isset($options['scheme'])) { + $scheme = $options['scheme']; + $uri = $scheme . '://'; + } + elseif (isset($options['uri'])) { + $uri = $options['uri']; + $scheme = file_uri_scheme($uri); + } + else { + return FALSE; + } + + // Attempt to instantiate a stream wrapper. + try { + $instance = $this->createInstance($scheme); + $instance->setUri($uri); + return $instance; + } + catch (PluginException $e) { + return FALSE; + } + } + +} diff --git a/core/modules/file/tests/file_test/file_test.module b/core/modules/file/tests/file_test/file_test.module index b6b88dc..1b77063 100644 --- a/core/modules/file/tests/file_test/file_test.module +++ b/core/modules/file/tests/file_test/file_test.module @@ -14,29 +14,6 @@ const FILE_URL_TEST_CDN_2 = 'http://cdn2.example.com'; /** - * Implements hook_stream_wrappers(). - */ -function file_test_stream_wrappers() { - return array( - 'dummy' => array( - 'name' => t('Dummy files'), - 'class' => 'Drupal\file_test\DummyStreamWrapper', - 'description' => t('Dummy wrapper for simpletest.'), - ), - 'dummy-remote' => array( - 'name' => t('Dummy files (remote)'), - 'class' => 'Drupal\file_test\DummyRemoteStreamWrapper', - 'description' => t('Dummy wrapper for simpletest (remote).'), - ), - 'dummy-readonly' => array( - 'name' => t('Dummy files (readonly)'), - 'class' => 'Drupal\file_test\DummyReadOnlyStreamWrapper', - 'description' => t('Dummy wrapper for simpletest (readonly).'), - ), - ); -} - -/** * Reset/initialize the history of calls to the file_* hooks. * * @see file_test_get_calls() diff --git a/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyRemoteStreamWrapper.php b/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyRemoteStreamWrapper.php deleted file mode 100644 index 2741196..0000000 --- a/core/modules/file/tests/file_test/lib/Drupal/file_test/DummyRemoteStreamWrapper.php +++ /dev/null @@ -1,23 +0,0 @@ -getWrappers(STREAM_WRAPPERS_WRITE_VISIBLE); foreach ($wrappers as $wrapper => $wrapper_data) { file_unmanaged_delete_recursive($wrapper . '://styles/' . $this->id()); } diff --git a/core/modules/locale/lib/Drupal/locale/TranslationsStream.php b/core/modules/locale/lib/Drupal/locale/Plugin/StreamWrapper/TranslationsStream.php similarity index 70% rename from core/modules/locale/lib/Drupal/locale/TranslationsStream.php rename to core/modules/locale/lib/Drupal/locale/Plugin/StreamWrapper/TranslationsStream.php index 34ef38e..15c2cbf 100644 --- a/core/modules/locale/lib/Drupal/locale/TranslationsStream.php +++ b/core/modules/locale/lib/Drupal/locale/Plugin/StreamWrapper/TranslationsStream.php @@ -5,14 +5,23 @@ * Definition of Drupal\locale\TranslationStream. */ -namespace Drupal\locale; +namespace Drupal\locale\Plugin\StreamWrapper; use Drupal\Core\StreamWrapper\LocalStream; +use Drupal\Core\Annotation\StreamWrapper; +use Drupal\Core\Annotation\Translation; /** * Defines a Drupal translations (translations://) stream wrapper class. * * Provides support for storing translation files. + * + * @StreamWrapper( + * id = "translations", + * name = @Translation("Translation files"), + * description = @Translation("Translation files"), + * type = STREAM_WRAPPERS_LOCAL_HIDDEN + * ) */ class TranslationsStream extends LocalStream { diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index 8d6ff20..c849d06 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -261,21 +261,6 @@ function locale_theme() { } /** - * Implements hook_stream_wrappers(). - */ -function locale_stream_wrappers() { - $wrappers = array( - 'translations' => array( - 'name' => t('Translation files'), - 'class' => 'Drupal\locale\TranslationsStream', - 'description' => t('Translation files'), - 'type' => STREAM_WRAPPERS_LOCAL_HIDDEN, - ), - ); - return $wrappers; -} - -/** * Implements hook_language_insert(). */ function locale_language_insert($language) { diff --git a/core/modules/system/lib/Drupal/system/Form/FileSystemForm.php b/core/modules/system/lib/Drupal/system/Form/FileSystemForm.php index 3a4aa18..2771392 100644 --- a/core/modules/system/lib/Drupal/system/Form/FileSystemForm.php +++ b/core/modules/system/lib/Drupal/system/Form/FileSystemForm.php @@ -7,7 +7,12 @@ namespace Drupal\system\Form; +use Drupal\Component\Utility\String; +use Drupal\Core\Config\ConfigFactory; +use Drupal\Core\Config\Context\ContextInterface; +use Drupal\Core\StreamWrapper\StreamWrapperManager; use Drupal\system\SystemConfigFormBase; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Configure file system settings for this site. @@ -15,6 +20,40 @@ class FileSystemForm extends SystemConfigFormBase { /** + * The stream wrapper manager. + * + * @var \Drupal\Core\StreamWrapper\StreamWrapperManager + */ + protected $streamWrapperManager; + + /** + * Constructs a FileSystemForm object. + * + * @param \Drupal\Core\Config\ConfigFactory $config_factory + * The factory for configuration objects. + * @param \Drupal\Core\Config\Context\ContextInterface $context + * The configuration context to use. + * @param \Drupal\Core\StreamWrapper\StreamWrapperManager $stream_wrapper_manager + * The stream wrapper manager. + */ + public function __construct(ConfigFactory $config_factory, ContextInterface $context, StreamWrapperManager $stream_wrapper_manager) { + parent::__construct($config_factory, $context); + + $this->streamWrapperManager = $stream_wrapper_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('config.factory'), + $container->get('config.context.free'), + $container->get('plugin.manager.stream_wrapper') + ); + } + + /** * {@inheritdoc} */ public function getFormID() { @@ -54,9 +93,9 @@ public function buildForm(array $form, array &$form_state) { ); // Any visible, writeable wrapper can potentially be used for the files // directory, including a remote file system that integrates with a CDN. - foreach (file_get_stream_wrappers(STREAM_WRAPPERS_WRITE_VISIBLE) as $scheme => $info) { - $options[$scheme] = check_plain($info['description']); - } + $options = array_map(function ($wrapper) { + return String::checkPlain($wrapper['description']); + }, $this->streamWrapperManager->getWrappers(STREAM_WRAPPERS_WRITE_VISIBLE)); if (!empty($options)) { $form['file_default_scheme'] = array( diff --git a/core/modules/system/lib/Drupal/system/Tests/File/StreamWrapperTest.php b/core/modules/system/lib/Drupal/system/Tests/File/StreamWrapperTest.php index c17dcb7..cf0174b 100644 --- a/core/modules/system/lib/Drupal/system/Tests/File/StreamWrapperTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/File/StreamWrapperTest.php @@ -22,7 +22,7 @@ class StreamWrapperTest extends WebTestBase { public static $modules = array('file_test'); protected $scheme = 'dummy'; - protected $classname = 'Drupal\file_test\DummyStreamWrapper'; + protected $classname = 'Drupal\file_test\Plugin\StreamWrapper\DummyStreamWrapper'; public static function getInfo() { return array( @@ -49,7 +49,7 @@ function testGetClassName() { // Check the dummy scheme. $this->assertEqual($this->classname, file_stream_wrapper_get_class($this->scheme), 'Got correct class name for dummy scheme.'); // Check core's scheme. - $this->assertEqual('Drupal\Core\StreamWrapper\PublicStream', file_stream_wrapper_get_class('public'), 'Got correct class name for public scheme.'); + $this->assertEqual('Drupal\Core\StreamWrapper\Plugin\StreamWrapper\PublicStream', file_stream_wrapper_get_class('public'), 'Got correct class name for public scheme.'); } /** @@ -60,7 +60,7 @@ function testGetInstanceByScheme() { $this->assertEqual($this->classname, get_class($instance), 'Got correct class type for dummy scheme.'); $instance = file_stream_wrapper_get_instance_by_scheme('public'); - $this->assertEqual('Drupal\Core\StreamWrapper\PublicStream', get_class($instance), 'Got correct class type for public scheme.'); + $this->assertEqual('Drupal\Core\StreamWrapper\Plugin\StreamWrapper\PublicStream', get_class($instance), 'Got correct class type for public scheme.'); } /** @@ -73,7 +73,7 @@ function testUriFunctions() { $this->assertEqual($this->classname, get_class($instance), 'Got correct class type for dummy URI.'); $instance = file_stream_wrapper_get_instance_by_uri('public://foo'); - $this->assertEqual('Drupal\Core\StreamWrapper\PublicStream', get_class($instance), 'Got correct class type for public URI.'); + $this->assertEqual('Drupal\Core\StreamWrapper\Plugin\StreamWrapper\PublicStream', get_class($instance), 'Got correct class type for public URI.'); // Test file_uri_target(). $this->assertEqual(file_uri_target('public://foo/bar.txt'), 'foo/bar.txt', 'Got a valid stream target from public://foo/bar.txt.'); diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php index 1e1bae3..78417af 100644 --- a/core/modules/system/system.api.php +++ b/core/modules/system/system.api.php @@ -2042,80 +2042,10 @@ function hook_modules_uninstalled($modules) { } /** - * Registers PHP stream wrapper implementations associated with a module. - * - * Provide a facility for managing and querying user-defined stream wrappers - * in PHP. PHP's internal stream_get_wrappers() doesn't return the class - * registered to handle a stream, which we need to be able to find the handler - * for class instantiation. - * - * If a module registers a scheme that is already registered with PHP, it will - * be unregistered and replaced with the specified class. - * - * @return - * A nested array, keyed first by scheme name ("public" for "public://"), - * then keyed by the following values: - * - 'name' A short string to name the wrapper. - * - 'class' A string specifying the PHP class that implements the - * Drupal\Core\StreamWrapper\StreamWrapperInterface interface. - * - 'description' A string with a short description of what the wrapper does. - * - 'type' (Optional) A bitmask of flags indicating what type of streams this - * wrapper will access - local or remote, readable and/or writeable, etc. - * Many shortcut constants are defined in file.inc. Defaults to - * STREAM_WRAPPERS_NORMAL which includes all of these bit flags: - * - STREAM_WRAPPERS_READ - * - STREAM_WRAPPERS_WRITE - * - STREAM_WRAPPERS_VISIBLE - * - * @see file_get_stream_wrappers() - * @see hook_stream_wrappers_alter() - * @see system_stream_wrappers() - */ -function hook_stream_wrappers() { - return array( - 'public' => array( - 'name' => t('Public files'), - 'class' => 'Drupal\Core\StreamWrapper\PublicStream', - 'description' => t('Public local files served by the webserver.'), - 'type' => STREAM_WRAPPERS_LOCAL_NORMAL, - ), - 'private' => array( - 'name' => t('Private files'), - 'class' => 'Drupal\Core\StreamWrapper\PrivateStream', - 'description' => t('Private local files served by Drupal.'), - 'type' => STREAM_WRAPPERS_LOCAL_NORMAL, - ), - 'temp' => array( - 'name' => t('Temporary files'), - 'class' => 'Drupal\Core\StreamWrapper\TemporaryStream', - 'description' => t('Temporary local files for upload and previews.'), - 'type' => STREAM_WRAPPERS_LOCAL_HIDDEN, - ), - 'cdn' => array( - 'name' => t('Content delivery network files'), - // @todo: Fix the name of this class when we decide on module PSR-0 usage. - 'class' => 'MyModuleCDNStream', - 'description' => t('Files served by a content delivery network.'), - // 'type' can be omitted to use the default of STREAM_WRAPPERS_NORMAL - ), - 'youtube' => array( - 'name' => t('YouTube video'), - // @todo: Fix the name of this class when we decide on module PSR-0 usage. - 'class' => 'MyModuleYouTubeStream', - 'description' => t('Video streamed from YouTube.'), - // A module implementing YouTube integration may decide to support using - // the YouTube API for uploading video, but here, we assume that this - // particular module only supports playing YouTube video. - 'type' => STREAM_WRAPPERS_READ_VISIBLE, - ), - ); -} - -/** * Alters the list of PHP stream wrapper implementations. * * @see file_get_stream_wrappers() - * @see hook_stream_wrappers() + * @see \Drupal\Core\StreamWrapper\StreamWrapperManager */ function hook_stream_wrappers_alter(&$wrappers) { // Change the name of private files to reflect the performance. diff --git a/core/modules/system/system.module b/core/modules/system/system.module index a6a7786..73f0512 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -2125,35 +2125,13 @@ function system_library_info() { } /** - * Implements hook_stream_wrappers(). + * Implements hook_stream_wrappers_alter(). */ -function system_stream_wrappers() { - $wrappers = array( - 'public' => array( - 'name' => t('Public files'), - 'class' => 'Drupal\Core\StreamWrapper\PublicStream', - 'description' => t('Public local files served by the webserver.'), - 'type' => STREAM_WRAPPERS_LOCAL_NORMAL, - ), - 'temporary' => array( - 'name' => t('Temporary files'), - 'class' => 'Drupal\Core\StreamWrapper\TemporaryStream', - 'description' => t('Temporary local files for upload and previews.'), - 'type' => STREAM_WRAPPERS_LOCAL_HIDDEN, - ), - ); - +function system_stream_wrappers_alter(&$wrappers) { // Only register the private file stream wrapper if a file path has been set. - if (config('system.file')->get('path.private')) { - $wrappers['private'] = array( - 'name' => t('Private files'), - 'class' => 'Drupal\Core\StreamWrapper\PrivateStream', - 'description' => t('Private local files served by Drupal.'), - 'type' => STREAM_WRAPPERS_LOCAL_NORMAL, - ); + if (!config('system.file')->get('path.private')) { + unset($wrappers['private']); } - - return $wrappers; } /**