diff --git a/core/lib/Drupal/Core/StreamWrapper/StreamWrapperManager.php b/core/lib/Drupal/Core/StreamWrapper/StreamWrapperManager.php index ddd4799..9ff525b 100644 --- a/core/lib/Drupal/Core/StreamWrapper/StreamWrapperManager.php +++ b/core/lib/Drupal/Core/StreamWrapper/StreamWrapperManager.php @@ -23,6 +23,10 @@ class StreamWrapperManager extends ContainerAware { /** * Contains stream wrapper info. * + * An associative array where keys are scheme names and values are themselves + * associative arrays with the keys class, type and (optionally) service_id, + * and string values. + * * @var array */ protected $info = array(); @@ -30,16 +34,20 @@ class StreamWrapperManager extends ContainerAware { /** * Contains collected stream wrappers. * - * @var array - */ - protected $wrappers = array(); - - /** - * Contains tagged stream-wrapper services. + * Keyed by filter, each value is itself an associative array keyed by scheme. + * Each of those values is an array representing a stream wrapper, with the + * following keys and values: + * - class: stream wrapper class name + * - type: a bitmask corresponding to the type constants in + * StreamWrapperInterface + * - service_id: name of service + * + * The array on key StreamWrapperInterface::ALL contains representations of + * all schemes and corresponding wrappers. * * @var array */ - protected $services = array(); + protected $wrappers = array(); /** * The module handler. @@ -231,8 +239,8 @@ public function getClass($scheme) { * A stream wrapper object, or false if the scheme is not available. */ protected function getWrapper($scheme, $uri) { - if (isset($this->services[$scheme])) { - $instance = $this->container->get($this->services[$scheme]); + if (isset($this->info[$scheme]['service_id'])) { + $instance = $this->container->get($this->info[$scheme]['service_id']); $instance->setUri($uri); return $instance; } @@ -249,13 +257,15 @@ protected function getWrapper($scheme, $uri) { * The service id. * @param string $class * The stream wrapper class. + * @param string $scheme + * The scheme for which the wrapper should be registered. */ public function addStreamWrapper($service_id, $class, $scheme) { - $info = array(); - $info['class'] = $class; - $info['type'] = $class::getType(); - $this->services[$scheme] = $service_id; - $this->info[$scheme] = $info; + $this->info[$scheme] = array( + 'class' => $class, + 'type' => $class::getType(), + 'service_id' => $service_id, + ); } /** @@ -265,7 +275,6 @@ public function addStreamWrapper($service_id, $class, $scheme) { */ public function register() { $this->moduleHandler->alter('stream_wrappers', $this->info); - $this->services = array_intersect_key($this->services, $this->info); foreach ($this->info as $scheme => $info) { $this->registerWrapper($scheme, $info['class'], $info['type']); @@ -278,8 +287,14 @@ public function register() { * Internal use only. */ public function unregister() { - foreach (array_keys($this->wrappers[StreamWrapperInterface::ALL]) as $scheme) { - stream_wrapper_unregister($scheme); + // Normally, there are definitely wrappers set for the ALL filter. However, + // in some cases involving many container rebuilds (e.g. WebTestBase), + // $this->wrappers may be empty although wrappers are still registered + // globally. Thus an isset() check is needed before iterating. + if (isset($this->wrappers[StreamWrapperInterface::ALL])) { + foreach (array_keys($this->wrappers[StreamWrapperInterface::ALL]) as $scheme) { + stream_wrapper_unregister($scheme); + } } }