You are here

class StreamWrapperManager in Drupal 10

Same name and namespace in other branches
  1. 8 core/lib/Drupal/Core/StreamWrapper/StreamWrapperManager.php \Drupal\Core\StreamWrapper\StreamWrapperManager
  2. 9 core/lib/Drupal/Core/StreamWrapper/StreamWrapperManager.php \Drupal\Core\StreamWrapper\StreamWrapperManager

Provides a StreamWrapper manager.

Hierarchy

  • class \Drupal\Core\StreamWrapper\StreamWrapperManager implements \Symfony\Component\DependencyInjection\ContainerAwareInterface, \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface uses \Symfony\Component\DependencyInjection\ContainerAwareTrait

Expanded class hierarchy of StreamWrapperManager

See also

\Drupal\Core\StreamWrapper\StreamWrapperInterface

19 files declare their use of StreamWrapperManager
config.module in core/modules/config/config.module
Allows site administrators to modify configuration.
CssOptimizer.php in core/lib/Drupal/Core/Asset/CssOptimizer.php
file.api.php in core/lib/Drupal/Core/File/file.api.php
Hooks related to the File management system.
FileCopy.php in core/modules/migrate/src/Plugin/migrate/process/FileCopy.php
FileSystem.php in core/lib/Drupal/Core/File/FileSystem.php

... See full list

1 string reference to 'StreamWrapperManager'
core.services.yml in core/core.services.yml
core/core.services.yml
1 service uses StreamWrapperManager
stream_wrapper_manager in core/core.services.yml
Drupal\Core\StreamWrapper\StreamWrapperManager

File

core/lib/Drupal/Core/StreamWrapper/StreamWrapperManager.php, line 13

Namespace

Drupal\Core\StreamWrapper
View source
class StreamWrapperManager implements ContainerAwareInterface, StreamWrapperManagerInterface {
  use ContainerAwareTrait;

  /**
   * 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 = [];

  /**
   * Contains collected stream wrappers.
   *
   * 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 $wrappers = [];

  /**
   * {@inheritdoc}
   */
  public function getWrappers($filter = StreamWrapperInterface::ALL) {
    if (isset($this->wrappers[$filter])) {
      return $this->wrappers[$filter];
    }
    elseif (isset($this->wrappers[StreamWrapperInterface::ALL])) {
      $this->wrappers[$filter] = [];
      foreach ($this->wrappers[StreamWrapperInterface::ALL] as $scheme => $info) {

        // Bit-wise filter.
        if (($info['type'] & $filter) == $filter) {
          $this->wrappers[$filter][$scheme] = $info;
        }
      }
      return $this->wrappers[$filter];
    }
    else {
      return [];
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getNames($filter = StreamWrapperInterface::ALL) {
    $names = [];
    foreach (array_keys($this
      ->getWrappers($filter)) as $scheme) {
      $names[$scheme] = $this
        ->getViaScheme($scheme)
        ->getName();
    }
    return $names;
  }

  /**
   * {@inheritdoc}
   */
  public function getDescriptions($filter = StreamWrapperInterface::ALL) {
    $descriptions = [];
    foreach (array_keys($this
      ->getWrappers($filter)) as $scheme) {
      $descriptions[$scheme] = $this
        ->getViaScheme($scheme)
        ->getDescription();
    }
    return $descriptions;
  }

  /**
   * {@inheritdoc}
   */
  public function getViaScheme($scheme) {
    return $this
      ->getWrapper($scheme, $scheme . '://');
  }

  /**
   * {@inheritdoc}
   */
  public function getViaUri($uri) {
    $scheme = static::getScheme($uri);
    return $this
      ->getWrapper($scheme, $uri);
  }

  /**
   * {@inheritdoc}
   */
  public function getClass($scheme) {
    if (isset($this->info[$scheme])) {
      return $this->info[$scheme]['class'];
    }
    return FALSE;
  }

  /**
   * Returns a stream wrapper instance.
   *
   * @param string $scheme
   *   The scheme of the desired stream wrapper.
   * @param string $uri
   *   The URI of the stream.
   *
   * @return \Drupal\Core\StreamWrapper\StreamWrapperInterface|bool
   *   A stream wrapper object, or false if the scheme is not available.
   */
  protected function getWrapper($scheme, $uri) {
    if (isset($this->info[$scheme]['service_id'])) {
      $instance = $this->container
        ->get($this->info[$scheme]['service_id']);
      $instance
        ->setUri($uri);
      return $instance;
    }
    return FALSE;
  }

  /**
   * Adds a stream wrapper.
   *
   * Internal use only.
   *
   * @param string $service_id
   *   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) {
    $this->info[$scheme] = [
      'class' => $class,
      'type' => $class::getType(),
      'service_id' => $service_id,
    ];
  }

  /**
   * Registers the tagged stream wrappers.
   *
   * Internal use only.
   */
  public function register() {
    foreach ($this->info as $scheme => $info) {
      $this
        ->registerWrapper($scheme, $info['class'], $info['type']);
    }
  }

  /**
   * Unregisters the tagged stream wrappers.
   *
   * Internal use only.
   */
  public function unregister() {

    // Normally, there are definitely wrappers set for the ALL filter. However,
    // in some cases involving many container rebuilds (e.g. BrowserTestBase),
    // $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);
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function registerWrapper($scheme, $class, $type) {
    if (in_array($scheme, stream_get_wrappers(), TRUE)) {
      stream_wrapper_unregister($scheme);
    }
    if (($type & StreamWrapperInterface::LOCAL) == StreamWrapperInterface::LOCAL) {
      stream_wrapper_register($scheme, $class);
    }
    else {
      stream_wrapper_register($scheme, $class, STREAM_IS_URL);
    }

    // Pre-populate the static cache with the filters most typically used.
    $info = [
      'type' => $type,
      'class' => $class,
    ];
    $this->wrappers[StreamWrapperInterface::ALL][$scheme] = $info;
    if (($type & StreamWrapperInterface::WRITE_VISIBLE) == StreamWrapperInterface::WRITE_VISIBLE) {
      $this->wrappers[StreamWrapperInterface::WRITE_VISIBLE][$scheme] = $info;
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function getTarget($uri) {

    // Remove the scheme from the URI and remove erroneous leading or trailing,
    // forward-slashes and backslashes.
    $target = trim(preg_replace('/^[\\w\\-]+:\\/\\/|^data:/', '', $uri), '\\/');

    // If nothing was replaced, the URI doesn't have a valid scheme.
    return $target !== $uri ? $target : FALSE;
  }

  /**
   * Normalizes a URI by making it syntactically correct.
   *
   * A stream is referenced as "scheme://target".
   *
   * The following actions are taken:
   * - Remove trailing slashes from target
   * - Trim erroneous leading slashes from target. e.g. ":///" becomes "://".
   *
   * @param string $uri
   *   String reference containing the URI to normalize.
   *
   * @return string
   *   The normalized URI.
   */
  public function normalizeUri($uri) {
    $scheme = $this
      ->getScheme($uri);
    if ($this
      ->isValidScheme($scheme)) {
      $target = $this
        ->getTarget($uri);
      if ($target !== FALSE) {
        $uri = $scheme . '://' . $target;
      }
    }
    return $uri;
  }

  /**
   * {@inheritdoc}
   */
  public static function getScheme($uri) {
    if (preg_match('/^([\\w\\-]+):\\/\\/|^(data):/', $uri, $matches)) {

      // The scheme will always be the last element in the matches array.
      return array_pop($matches);
    }
    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function isValidScheme($scheme) {
    if (!$scheme) {
      return FALSE;
    }
    return class_exists($this
      ->getClass($scheme));
  }

  /**
   * {@inheritdoc}
   */
  public function isValidUri($uri) {

    // Assert that the URI has an allowed scheme. Bare paths are not allowed.
    return $this
      ->isValidScheme($this
      ->getScheme($uri));
  }

}

Members