View source
<?php
namespace Drupal\config_split;
use Drupal\config_filter\Config\FilteredStorage;
use Drupal\config_filter\Config\FilteredStorageInterface;
use Drupal\config_filter\ConfigFilterManagerInterface;
use Drupal\config_filter\ConfigFilterStorageFactory;
use Drupal\config_split\Config\GhostStorage;
use Drupal\Core\Config\ConfigImporter;
use Drupal\Core\Config\ConfigImporterException;
use Drupal\Core\Config\ConfigManagerInterface;
use Drupal\Core\Config\FileStorageFactory;
use Drupal\Core\Config\StorageComparer;
use Drupal\Core\Config\StorageCopyTrait;
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\Config\TypedConfigManagerInterface;
use Drupal\Core\Extension\ModuleExtensionList;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Extension\ModuleInstallerInterface;
use Drupal\Core\Extension\ThemeHandlerInterface;
use Drupal\Core\Lock\LockBackendInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class ConfigSplitCliService {
use StorageCopyTrait;
const NO_CHANGES = 'no_changes';
const ALREADY_IMPORTING = 'already_importing';
const COMPLETE = 'complete';
protected $configFilterManager;
protected $storageFactory;
protected $configManager;
protected $activeStorage;
protected $syncStorage;
protected $eventDispatcher;
protected $lock;
protected $configTyped;
protected $moduleHandler;
protected $moduleInstaller;
protected $themeHandler;
protected $stringTranslation;
protected $moduleExtensionList;
protected $errors;
public function __construct(ConfigFilterManagerInterface $config_filter_manager, ConfigFilterStorageFactory $storageFactory, ConfigManagerInterface $config_manager, StorageInterface $active_storage, StorageInterface $sync_storage, EventDispatcherInterface $event_dispatcher, LockBackendInterface $lock, TypedConfigManagerInterface $config_typed, ModuleHandlerInterface $module_handler, ModuleInstallerInterface $module_installer, ThemeHandlerInterface $theme_handler, TranslationInterface $string_translation, ModuleExtensionList $moduleExtensionList) {
$this->configFilterManager = $config_filter_manager;
$this->storageFactory = $storageFactory;
$this->configManager = $config_manager;
$this->activeStorage = $active_storage;
$this->syncStorage = $sync_storage;
$this->eventDispatcher = $event_dispatcher;
$this->lock = $lock;
$this->configTyped = $config_typed;
$this->moduleHandler = $module_handler;
$this->moduleInstaller = $module_installer;
$this->themeHandler = $theme_handler;
$this->stringTranslation = $string_translation;
$this->moduleExtensionList = $moduleExtensionList;
$this->errors = [];
}
public function ioExport($split, $io, callable $t, $confirmed = FALSE) {
if (!$split) {
$io
->warning('Please consider using `drush config:export` instead for exporting all config.');
$message = $t('Do a normal (including filters) config export?');
$storage = $this->syncStorage;
if (!$storage instanceof FilteredStorageInterface) {
throw new \RuntimeException('Only exporting splits is supported when not using Config Filter 8.x-1.x');
}
}
else {
$config_name = $this
->getSplitName($split);
$plugin_id = $this
->getPluginIdFromConfigName($config_name);
$filter = $this->configFilterManager
->getFilterInstance($plugin_id);
$storage = $this->storageFactory
->getFilteredStorage(FileStorageFactory::getSync(), [
'config.storage.sync',
], [
$plugin_id,
]);
$storage = new FilteredStorage(new GhostStorage($storage), [
$filter,
]);
$message = $t('The following directories will be purged and used for exporting configuration:');
$message .= "\n";
$message .= $this
->getDestination($config_name);
$message .= "\n";
$message .= $t('Export the configuration?');
}
if ($confirmed || $io
->confirm($message)) {
$this
->export($storage);
$io
->success($t("Configuration successfully exported."));
}
}
public function ioImport($split, $io, callable $t, $confirmed = FALSE) {
if (!$split) {
$io
->text('Please consider using `drush config:import` instead for importing all config.');
$message = $t('Do a normal (including filters) config import?');
$storage = $this->syncStorage;
if (!$storage instanceof FilteredStorageInterface) {
throw new \RuntimeException('Only importing splits is supported when not using Config Filter 8.x-1.x');
}
}
else {
$config_name = $this
->getSplitName($split);
$filter = $this->configFilterManager
->getFilterInstance($this
->getPluginIdFromConfigName($config_name));
$storage = new FilteredStorage($this->activeStorage, [
$filter,
]);
$message = $t('The following directory will be used to merge config into the active storage:');
$message .= "\n";
$message .= $this
->getDestination($config_name);
$message .= "\n";
$message .= $t('Import the configuration?');
}
try {
if ($confirmed || $io
->confirm($message)) {
$status = $this
->import($storage);
switch ($status) {
case ConfigSplitCliService::COMPLETE:
$io
->success($t("Configuration successfully imported."));
break;
case ConfigSplitCliService::NO_CHANGES:
$io
->text($t("There are no changes to import."));
break;
case ConfigSplitCliService::ALREADY_IMPORTING:
$io
->error($t("Another request may be synchronizing configuration already."));
break;
default:
$io
->error($t("Something unexpected happened"));
break;
}
}
} catch (ConfigImporterException $e) {
$io
->error($t('There have been errors importing: @errors', [
'@errors' => strip_tags(implode("\n", $this
->getErrors())),
]));
}
}
public function export(StorageInterface $storage, StorageInterface $active = NULL) {
if (!isset($active)) {
$active = $this->activeStorage;
}
static::replaceStorageContents($active, $storage);
}
public function import(StorageInterface $storage) {
$comparer = new StorageComparer($storage, $this->activeStorage);
if (!$comparer
->createChangelist()
->hasChanges()) {
return static::NO_CHANGES;
}
$importer = new ConfigImporter($comparer, $this->eventDispatcher, $this->configManager, $this->lock, $this->configTyped, $this->moduleHandler, $this->moduleInstaller, $this->themeHandler, $this->stringTranslation, $this->moduleExtensionList);
if ($importer
->alreadyImporting()) {
return static::ALREADY_IMPORTING;
}
try {
$importer
->import();
} catch (ConfigImporterException $e) {
$this->errors = $importer
->getErrors();
throw $e;
}
return static::COMPLETE;
}
public function getErrors() {
return $this->errors;
}
protected function getPluginIdFromConfigName($name) {
return 'config_split:' . str_replace('config_split.config_split.', '', $name);
}
protected function getSplitName($name) {
if (strpos($name, 'config_split.config_split.') !== 0) {
$name = 'config_split.config_split.' . $name;
}
if (!in_array($name, $this->activeStorage
->listAll('config_split.config_split.'))) {
$names = [];
foreach ($this->activeStorage
->listAll('config_split.config_split.') as $split_name) {
$names[] = $split_name;
}
$names = implode(', ', $names);
throw new \InvalidArgumentException('The following split is not available: ' . $name . PHP_EOL . 'Available names: ' . $names);
}
return $name;
}
protected function getDestination($config_name) {
$destination = $this->configManager
->getConfigFactory()
->get($config_name)
->get('folder');
if ($destination == '') {
$destination = 'dedicated database table.';
}
return $destination;
}
}