config_preview_deploy-1.0.0-alpha3/src/ConfigFilter.php
src/ConfigFilter.php
<?php
declare(strict_types=1);
namespace Drupal\config_preview_deploy;
use Drupal\config_ignore\EventSubscriber\ConfigIgnoreEventSubscriber;
use Drupal\Core\Config\MemoryStorage;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\Config\StorageTransformEvent;
use Drupal\Core\Config\Checkpoint\CheckpointStorage;
use Drupal\Core\Extension\ModuleHandlerInterface;
/**
* Service for filtering configurations based on config_ignore patterns.
*
* @todo Solve this better by working out a solution with config_ignore at
* https://www.drupal.org/project/config_ignore/issues/3534690
*/
class ConfigFilter {
/**
* The config factory.
*/
protected ConfigFactoryInterface $configFactory;
/**
* The module handler.
*/
protected ModuleHandlerInterface $moduleHandler;
/**
* Constructs a ConfigFilter object.
*/
public function __construct(
ConfigFactoryInterface $configFactory,
ModuleHandlerInterface $moduleHandler,
) {
$this->configFactory = $configFactory;
$this->moduleHandler = $moduleHandler;
}
/**
* Gets a transformed storage with config_ignore patterns applied.
*
* @param \Drupal\Core\Config\StorageInterface $sourceStorage
* The source storage to copy and transform.
* @param \Drupal\Core\Config\Checkpoint\CheckpointStorage $checkpointStorage
* The checkpoint storage instance. The caller is responsible for setting
* the appropriate checkpoint to read from before calling this method.
*
* @return \Drupal\Core\Config\StorageInterface
* A new memory storage with transformations applied, or the original
* source storage if filtering is not available.
*/
public function getFilteredStorage(StorageInterface $sourceStorage, CheckpointStorage $checkpointStorage): StorageInterface {
// Check if filtering is available first to avoid unnecessary copying.
if (!$this->isAvailable()) {
return $sourceStorage;
}
// Copy source storage to memory storage for transformation.
$memoryStorage = new MemoryStorage();
foreach ($sourceStorage->listAll() as $name) {
$data = $sourceStorage->read($name);
if ($data !== FALSE) {
$memoryStorage->write($name, $data);
}
}
// Apply filtering.
$this->applyFilter($memoryStorage, $checkpointStorage);
return $memoryStorage;
}
/**
* Applies config filtering transformations to a storage.
*
* @param \Drupal\Core\Config\StorageInterface $storage
* The storage to transform.
* @param \Drupal\Core\Config\StorageInterface $checkpointStorage
* The checkpoint storage to use for restoring ignored values.
*
* @return bool
* TRUE if transformations were applied, FALSE otherwise.
*/
protected function applyFilter(StorageInterface $storage, StorageInterface $checkpointStorage): bool {
// Check if we should apply filtering.
if (!$this->isAvailable()) {
return FALSE;
}
// Create a config_ignore event subscriber.
// IMPORTANT: We pass checkpoint storage as the sync storage.
// This ensures that ignored configs get their checkpoint values restored,
// effectively removing them from the diff.
// We pass the memory storage as the active storage parameter since that's
// what config_ignore will compare against when determining what to ignore.
$configIgnoreSubscriber = new ConfigIgnoreEventSubscriber(
$this->configFactory,
$this->moduleHandler,
// Pass the memory storage being transformed, not the real active storage.
$storage,
// Use checkpoint storage to restore ignored values.
$checkpointStorage
);
// Create and handle the event.
$event = new StorageTransformEvent($storage);
$configIgnoreSubscriber->onExportTransform($event);
return TRUE;
}
/**
* Checks if config filtering is available.
*
* @return bool
* TRUE if config_ignore is available and configured.
*/
public function isAvailable(): bool {
// Check if config_ignore module exists.
if (!$this->moduleHandler->moduleExists('config_ignore')) {
return FALSE;
}
// Check if ConfigIgnoreEventSubscriber class is available.
if (!class_exists('\Drupal\config_ignore\EventSubscriber\ConfigIgnoreEventSubscriber')) {
return FALSE;
}
// Check if config_ignore has any patterns configured.
$config = $this->configFactory->get('config_ignore.settings');
$patterns = $config->get('ignored_config_entities') ?: [];
return !empty($patterns);
}
}
