class DirectoryWithMetadataDiscovery

Same name in this branch
  1. 10 core/lib/Drupal/Core/Plugin/Discovery/DirectoryWithMetadataDiscovery.php \Drupal\Core\Plugin\Discovery\DirectoryWithMetadataDiscovery
Same name in other branches
  1. 11.x core/modules/sdc/src/Plugin/Discovery/DirectoryWithMetadataDiscovery.php \Drupal\sdc\Plugin\Discovery\DirectoryWithMetadataDiscovery
  2. 11.x core/lib/Drupal/Core/Plugin/Discovery/DirectoryWithMetadataDiscovery.php \Drupal\Core\Plugin\Discovery\DirectoryWithMetadataDiscovery

Does the actual finding of the directories with metadata files.

@internal

Hierarchy

Expanded class hierarchy of DirectoryWithMetadataDiscovery

File

core/modules/sdc/src/Plugin/Discovery/DirectoryWithMetadataDiscovery.php, line 13

Namespace

Drupal\sdc\Plugin\Discovery
View source
final class DirectoryWithMetadataDiscovery extends YamlDirectoryDiscovery {
    
    /**
     * 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 \Drupal\Core\File\FileSystemInterface $fileSystem
     *   The file system service.
     */
    public function __construct(array $directories, string $file_cache_key_suffix, FileSystemInterface $fileSystem) {
        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
     *   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 "my_component.component.yml".
        $regex = '/^([a-z0-9_-])+.component.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 component is overriding another one via "weight".
     * 2. Because the same component exists in different themes.
     */
    protected function getIdentifier($file, array $data) : string {
        $id = $this->fileSystem
            ->basename($file, '.component.yml');
        $provider_paths = array_flip($this->directories);
        $provider = $this->findProvider($file, $provider_paths);
        // We use the provider to dedupe components 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
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.