decoupled_config-8.x-1.0-alpha1/src/DecoupledConfigYamlDiscovery.php
src/DecoupledConfigYamlDiscovery.php
<?php
namespace Drupal\decoupled_config;
use Drupal\Component\Discovery\DiscoverableInterface;
use Drupal\Component\FileCache\FileCacheFactory;
use Drupal\Component\Serialization\Yaml;
use Drupal\decoupled_config\Helper\DecoupledConfigArrayHelper;
/**
* Class DecoupledConfigYamlDiscovery.
*
* @package Drupal\decoupled_config
*/
class DecoupledConfigYamlDiscovery implements DiscoverableInterface {
/**
* Directory to scan the files.
*/
const DISCOVERY_DIR = 'decoupled_config';
/**
* An array of directories to scan, keyed by the provider but without discovery dir.
*
* @var array
*/
protected $originalDirectories = [];
/**
* An array of directories to scan, keyed by the provider.
*
* @var array
*/
protected $directories = [];
/**
* Constructs a DecoupledConfigYamlDiscovery object.
*
* @param array $directories
* An array of directories to scan, keyed by the provider.
*/
public function __construct(array $directories) {
$this->originalDirectories = $directories;
$this->addSuffixesToDirectories($directories, [static::DISCOVERY_DIR]);
$this->directories = $directories;
}
/**
* Add suffix to directories.
*
* @param $directories
* @param array $suffixes
*/
protected function addSuffixesToDirectories(array &$directories, array $suffixes): void {
$directories = DecoupledConfigArrayHelper::wrapItems($directories, [], $suffixes, '/');
}
/**
* Find all yaml files grouped by module and get their content.
*
* Differences with \Drupal\Component\Discovery\YamlDiscovery::findFiles():
* - Array item key is filename without extensions.
* - This method find all yaml files even yaml files without $provider and
* $name in the file name.
*
* Example:
* @code
* $all[
* 'provider (e.g. module_name)' => [
* 'filename (without extensions)' => 'file parsed content',
* ],
* ];
* @endcode
*
* @return array
*
* @see \Drupal\Component\Discovery\YamlDiscovery::findAll()
*/
public function findAll(): array {
$all = [];
$files_grouped = $this->findFiles();
foreach ($files_grouped as $module => $files) {
$provider_by_files[$module] = array_flip($files);
}
$file_cache = FileCacheFactory::get('yaml_discovery:' . static::DISCOVERY_DIR);
foreach ($files_grouped as $module => $files) {
// Try to load from the file cache first.
foreach ($file_cache->getMultiple($files) as $file => $data) {
if (!empty($provider_by_files[$module][$file])) {
$all[$module][$provider_by_files[$module][$file]] = $data;
unset($provider_by_files[$module][$file]);
}
}
}
// If there are files left that were not returned from the cache, load and
// parse them now. This list was flipped above and is keyed by filename.
if (!empty($provider_by_files)) {
foreach ($provider_by_files as $module => $files) {
foreach ($files as $file => $provider) {
$all[$module][$provider] = $this->decode($file);
$file_cache->set($file, $all[$module][$provider]);
}
}
}
return $all;
}
/**
* Decode a YAML file.
*
* @param string $file
* Yaml file path.
*
* @return array
*/
protected function decode($file) {
return Yaml::decode(file_get_contents($file)) ?: [];
}
/**
* Find all yaml files grouped by module.
*
* Differences with \Drupal\Component\Discovery\YamlDiscovery::findFiles():
* - Array item key is filename without extensions.
* - This method find all yaml files even yaml files without $provider and
* $name in the file name.
*
* Example:
* @code
* $files[
* 'provider (e.g. module_name)' => [
* 'filename (without extensions)' => 'absolute file path with extensions',
* ],
* ];
* @endcode
*
* @return array
*
* @see \Drupal\Component\Discovery\YamlDiscovery::findFiles()
*/
protected function findFiles(): array {
$files = [];
foreach ($this->directories as $provider => $directory) {
$extension = ".yml";
if (is_dir($directory)) {
$decoupled_config_files = \Drupal::service('file_system')->scanDirectory($directory, '/' . preg_quote($extension) . '$/');
}
if (!empty($decoupled_config_files)) {
foreach ($decoupled_config_files as $file_path => $value) {
$filename = pathinfo($file_path, PATHINFO_FILENAME);
$files[$provider][$filename] = $file_path;
}
}
}
return $files;
}
}
