class DirectoryWithMetadataDiscovery

Same name and namespace in other branches
  1. 11.x core/lib/Drupal/Core/Plugin/Discovery/DirectoryWithMetadataDiscovery.php \Drupal\Core\Plugin\Discovery\DirectoryWithMetadataDiscovery
  2. 10 core/lib/Drupal/Core/Plugin/Discovery/DirectoryWithMetadataDiscovery.php \Drupal\Core\Plugin\Discovery\DirectoryWithMetadataDiscovery

Does the actual finding of the directories with metadata files.

Hierarchy

Expanded class hierarchy of DirectoryWithMetadataDiscovery

File

core/lib/Drupal/Core/Plugin/Discovery/DirectoryWithMetadataDiscovery.php, line 12

Namespace

Drupal\Core\Plugin\Discovery
View source
class DirectoryWithMetadataDiscovery extends YamlDirectoryDiscovery {
  use DeprecatedServicePropertyTrait;
  
  /**
   * Allowed characters of plugin ID.
   *
   * This discovery has the particularity of searching for plugin IDs in
   * filenames.
   */
  const PLUGIN_ID_REGEX = '([a-z0-9._-])+';
  
  /**
   * The deprecated properties.
   *
   * @see https://www.drupal.org/node/3530869
   */
  protected array $deprecatedProperties = [
    'fileSystem' => FileSystemInterface::class,
  ];
  
  /**
   * Constructs a DirectoryWithMetadataDiscovery object.
   *
   * @param array $directories
   *   An array of directories to scan, keyed by the provider. The value can
   *   either be a string or an array of strings. The string values should be
   *   the path of a directory to scan.
   * @param string $file_cache_key_suffix
   *   The file cache key suffix. This should be unique for each type of
   *   discovery.
   * @param string $file_name_suffix
   *   The file name suffix that identifies a plugin metadata file, without the
   *   leading dot or trailing .yml extension. For example, passing 'component'
   *   will match files of the form 'my-plugin.component.yml'.
   */
  public function __construct(array $directories, string $file_cache_key_suffix, protected string $file_name_suffix) {
    parent::__construct($directories, $file_cache_key_suffix);
  }
  
  /**
   * Gets an iterator to loop over the files in the provided directory.
   *
   * This method exists so that it is easy to replace this functionality in a
   * class that extends this one. For example, it could be used to make the scan
   * recursive.
   *
   * @param string $directory
   *   The directory to scan.
   *
   * @return \RecursiveIteratorIterator<\SplFileInfo>
   *   A \RecursiveIteratorIterator object or array where the values are
   *   \SplFileInfo objects.
   */
  protected function getDirectoryIterator($directory) : \RecursiveIteratorIterator {
    // Use FilesystemIterator to not iterate over the . and .. directories.
    $flags = \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS;
    $directory_iterator = new \RecursiveDirectoryIterator($directory, $flags);
    // Detect files of the form "my_plugin.{$file_name_suffix}.yml".
    $regex = '/^' . static::PLUGIN_ID_REGEX . '\\.' . preg_quote($this->file_name_suffix, '/') . '\\.yml$/i';
    $filter = new RegexRecursiveFilterIterator($directory_iterator, $regex);
    return new \RecursiveIteratorIterator($filter, \RecursiveIteratorIterator::LEAVES_ONLY, $flags);
  }
  
  /**
   * {@inheritdoc}
   *
   * The IDs can collide in two different scenarios:
   *
   * 1. Because one plugin is overriding another one via "weight".
   * 2. Because the same plugin exists in different themes.
   */
  protected function getIdentifier($file, array $data) : string {
    $id = basename($file, '.' . $this->file_name_suffix . '.yml');
    $provider_paths = array_flip($this->directories);
    $provider = $this->findProvider($file, $provider_paths);
    // We use the provider to dedupe plugins because it does not make sense
    // for a single provider to fork itself.
    return sprintf('%s:%s', $provider, $id);
  }
  
  /**
   * Finds the provider of the discovered file.
   *
   * The approach here is suboptimal because the provider is actually set in
   * the plugin definition after the getIdentifier is called. So we either do
   * this, or we forego the base class.
   *
   * @param string $file
   *   The discovered file.
   * @param array $provider_paths
   *   The associative array of the path to the provider.
   *
   * @return string
   *   The provider
   */
  private function findProvider(string $file, array $provider_paths) : string {
    $parts = explode(DIRECTORY_SEPARATOR, $file);
    array_pop($parts);
    if (empty($parts)) {
      return '';
    }
    $provider = $provider_paths[implode(DIRECTORY_SEPARATOR, $parts)] ?? '';
    return empty($provider) ? $this->findProvider(implode(DIRECTORY_SEPARATOR, $parts), $provider_paths) : $provider;
  }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title
DeprecatedServicePropertyTrait::__get public function Allows to access deprecated/removed properties.
DirectoryWithMetadataDiscovery::$deprecatedProperties protected property The deprecated properties.
DirectoryWithMetadataDiscovery::findProvider private function Finds the provider of the discovered file.
DirectoryWithMetadataDiscovery::getDirectoryIterator protected function Gets an iterator to loop over the files in the provided directory. Overrides YamlDirectoryDiscovery::getDirectoryIterator
DirectoryWithMetadataDiscovery::getIdentifier protected function The IDs can collide in two different scenarios: Overrides YamlDirectoryDiscovery::getIdentifier
DirectoryWithMetadataDiscovery::__construct public function Constructs a DirectoryWithMetadataDiscovery object. Overrides YamlDirectoryDiscovery::__construct
YamlDirectoryDiscovery::$directories protected property An array of directories to scan, keyed by the provider.
YamlDirectoryDiscovery::$fileCacheKeySuffix protected property The suffix for the file cache key.
YamlDirectoryDiscovery::$idKey protected property The key contained in the discovered data that identifies it.
YamlDirectoryDiscovery::FILE_KEY constant Defines the key in the discovered data where the file path is stored.
YamlDirectoryDiscovery::findAll public function Overrides DiscoverableInterface::findAll
YamlDirectoryDiscovery::findFiles protected function Returns an array of providers keyed by file path.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.