Loading core/lib/Drupal/Core/Config/Command/ConfigCommandTrait.php 0 → 100644 +56 −0 Changes for core/lib/Drupal/Core/Config/Command/ConfigCommandTrait.php: 56 added lines, 0 removed lines. Original line number Diff line number Diff line <?php namespace Drupal\Core\Config\Command; use Drupal\Core\Config\StorageComparer; use Symfony\Component\Console\Style\SymfonyStyle; /** * Trait for methods used across config commands. */ trait ConfigCommandTrait { /** * Prints the change list of a storage comparer as a table. * * @param \Drupal\Core\Config\StorageComparer $comparer * The comparer holding the change list to render. * @param \Symfony\Component\Console\Style\SymfonyStyle $io * The input and output style. */ protected function renderTable(StorageComparer $comparer, SymfonyStyle $io): void { $translations = [ 'delete' => (string) $this->t('Delete'), 'update' => (string) $this->t('Update'), 'create' => (string) $this->t('Create'), 'rename' => (string) $this->t('Rename'), ]; $styles = [ 'delete' => 'fg=white;bg=red', 'update' => 'fg=black;bg=yellow', 'create' => 'fg=white;bg=green', 'rename' => 'fg=black;bg=cyan', ]; $header = [ (string) $this->t('Collection'), (string) $this->t('Config'), (string) $this->t('Operation'), ]; $rows = []; foreach ($comparer->getAllCollectionNames() as $collection) { foreach ($comparer->getChangelist(NULL, $collection) as $op => $names) { foreach ($names as $name) { $rows[] = [ $collection, $op !== 'rename' ? $name : str_replace('::', ' -> ', $name), \sprintf('<%s>%s</>', $styles[$op], $translations[$op]), ]; } } } $io->table($header, $rows); } } core/lib/Drupal/Core/Config/Command/ConfigExportCommand.php +1 −43 Changes for core/lib/Drupal/Core/Config/Command/ConfigExportCommand.php: 1 added line, 43 removed lines. Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ final class ConfigExportCommand extends Command { use StringTranslationTrait; use StorageCopyTrait; use ConfigCommandTrait; public function __construct( #[Autowire(service: 'config.storage.export')] Loading Loading @@ -87,47 +88,4 @@ public function __invoke( return self::SUCCESS; } /** * Prints the change list of a storage comparer as a table. * * @param \Drupal\Core\Config\StorageComparer $comparer * The comparer holding the change list to render. * @param \Symfony\Component\Console\Style\SymfonyStyle $io * The input and output style. */ protected function renderTable(StorageComparer $comparer, SymfonyStyle $io): void { $translations = [ 'delete' => (string) $this->t('Delete'), 'update' => (string) $this->t('Update'), 'create' => (string) $this->t('Create'), 'rename' => (string) $this->t('Rename'), ]; $styles = [ 'delete' => 'fg=white;bg=red', 'update' => 'fg=black;bg=yellow', 'create' => 'fg=white;bg=green', 'rename' => 'fg=black;bg=cyan', ]; $header = [ (string) $this->t('Collection'), (string) $this->t('Config'), (string) $this->t('Operation'), ]; $rows = []; foreach ($comparer->getAllCollectionNames() as $collection) { foreach ($comparer->getChangelist(NULL, $collection) as $op => $names) { foreach ($names as $name) { $rows[] = [ $collection, $op !== 'rename' ? $name : str_replace('::', ' -> ', $name), \sprintf('<%s>%s</>', $styles[$op], $translations[$op]), ]; } } } $io->table($header, $rows); } } core/lib/Drupal/Core/Config/Command/ConfigImportCommand.php 0 → 100644 +108 −0 Changes for core/lib/Drupal/Core/Config/Command/ConfigImportCommand.php: 108 added lines, 0 removed lines. Original line number Diff line number Diff line <?php namespace Drupal\Core\Config\Command; use Drupal\Core\Command\Exception\UserAbortException; use Drupal\Core\Config\ConfigImporterException; use Drupal\Core\Config\ConfigImporterFactory; use Drupal\Core\Config\ImportStorageTransformer; use Drupal\Core\Config\StorageComparer; use Drupal\Core\Config\StorageInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Attribute\Option; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\DependencyInjection\Attribute\Autowire; /** * Import configuration. * * @internal */ #[AsCommand( name: 'config:import', description: 'Import configuration', aliases: ['cim'], )] class ConfigImportCommand extends Command { use StringTranslationTrait; use ConfigCommandTrait; public function __construct( #[Autowire(service: 'config.storage')] private readonly StorageInterface $active, #[Autowire(service: 'config.storage.sync')] private readonly StorageInterface $sync, private readonly ImportStorageTransformer $transformer, private readonly ConfigImporterFactory $importerFactory, ) { parent::__construct(); } /** * Export the configuration. * * @param \Symfony\Component\Console\Style\SymfonyStyle $io * The symfony style. * @param bool $yes * The command option to skip the confirmation question. * * @return int * The command result. */ public function __invoke( SymfonyStyle $io, #[Option(description: 'Answer the confirmation question with yes.', shortcut: 'y')] bool $yes = FALSE, ): int { // Do the import storage transformation. $import = $this->transformer->transform($this->sync); $comparer = new StorageComparer($import, $this->active); $comparer->createChangelist(); if (!$comparer->hasChanges()) { $io->success((string) $this->t('There are no changes to import.')); return self::SUCCESS; } $this->renderTable($comparer, $io); if (!$yes && !$io->confirm((string) $this->t('Import the listed configuration changes?'))) { throw new UserAbortException('Cancelled'); } $importer = $this->importerFactory->get($comparer); if ($importer->alreadyImporting()) { $io->warning((string) $this->t('Another request may be synchronizing configuration already.')); return Command::FAILURE; } try { $importer->validate(); $importer->import(); } catch (ConfigImporterException $e) { $io->error($e->getMessage()); return Command::FAILURE; } $errors = $importer->getErrors(); if (empty($errors)) { $io->success((string) $this->t('The configuration was imported successfully.')); return Command::SUCCESS; } $io->error((string) $this->t('The configuration was imported with errors.')); foreach ($errors as $error) { $io->error((string) $error); } return Command::FAILURE; } } core/tests/Drupal/FunctionalTests/Core/Config/ConfigImportCommandTest.php 0 → 100644 +430 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
core/lib/Drupal/Core/Config/Command/ConfigCommandTrait.php 0 → 100644 +56 −0 Changes for core/lib/Drupal/Core/Config/Command/ConfigCommandTrait.php: 56 added lines, 0 removed lines. Original line number Diff line number Diff line <?php namespace Drupal\Core\Config\Command; use Drupal\Core\Config\StorageComparer; use Symfony\Component\Console\Style\SymfonyStyle; /** * Trait for methods used across config commands. */ trait ConfigCommandTrait { /** * Prints the change list of a storage comparer as a table. * * @param \Drupal\Core\Config\StorageComparer $comparer * The comparer holding the change list to render. * @param \Symfony\Component\Console\Style\SymfonyStyle $io * The input and output style. */ protected function renderTable(StorageComparer $comparer, SymfonyStyle $io): void { $translations = [ 'delete' => (string) $this->t('Delete'), 'update' => (string) $this->t('Update'), 'create' => (string) $this->t('Create'), 'rename' => (string) $this->t('Rename'), ]; $styles = [ 'delete' => 'fg=white;bg=red', 'update' => 'fg=black;bg=yellow', 'create' => 'fg=white;bg=green', 'rename' => 'fg=black;bg=cyan', ]; $header = [ (string) $this->t('Collection'), (string) $this->t('Config'), (string) $this->t('Operation'), ]; $rows = []; foreach ($comparer->getAllCollectionNames() as $collection) { foreach ($comparer->getChangelist(NULL, $collection) as $op => $names) { foreach ($names as $name) { $rows[] = [ $collection, $op !== 'rename' ? $name : str_replace('::', ' -> ', $name), \sprintf('<%s>%s</>', $styles[$op], $translations[$op]), ]; } } } $io->table($header, $rows); } }
core/lib/Drupal/Core/Config/Command/ConfigExportCommand.php +1 −43 Changes for core/lib/Drupal/Core/Config/Command/ConfigExportCommand.php: 1 added line, 43 removed lines. Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ final class ConfigExportCommand extends Command { use StringTranslationTrait; use StorageCopyTrait; use ConfigCommandTrait; public function __construct( #[Autowire(service: 'config.storage.export')] Loading Loading @@ -87,47 +88,4 @@ public function __invoke( return self::SUCCESS; } /** * Prints the change list of a storage comparer as a table. * * @param \Drupal\Core\Config\StorageComparer $comparer * The comparer holding the change list to render. * @param \Symfony\Component\Console\Style\SymfonyStyle $io * The input and output style. */ protected function renderTable(StorageComparer $comparer, SymfonyStyle $io): void { $translations = [ 'delete' => (string) $this->t('Delete'), 'update' => (string) $this->t('Update'), 'create' => (string) $this->t('Create'), 'rename' => (string) $this->t('Rename'), ]; $styles = [ 'delete' => 'fg=white;bg=red', 'update' => 'fg=black;bg=yellow', 'create' => 'fg=white;bg=green', 'rename' => 'fg=black;bg=cyan', ]; $header = [ (string) $this->t('Collection'), (string) $this->t('Config'), (string) $this->t('Operation'), ]; $rows = []; foreach ($comparer->getAllCollectionNames() as $collection) { foreach ($comparer->getChangelist(NULL, $collection) as $op => $names) { foreach ($names as $name) { $rows[] = [ $collection, $op !== 'rename' ? $name : str_replace('::', ' -> ', $name), \sprintf('<%s>%s</>', $styles[$op], $translations[$op]), ]; } } } $io->table($header, $rows); } }
core/lib/Drupal/Core/Config/Command/ConfigImportCommand.php 0 → 100644 +108 −0 Changes for core/lib/Drupal/Core/Config/Command/ConfigImportCommand.php: 108 added lines, 0 removed lines. Original line number Diff line number Diff line <?php namespace Drupal\Core\Config\Command; use Drupal\Core\Command\Exception\UserAbortException; use Drupal\Core\Config\ConfigImporterException; use Drupal\Core\Config\ConfigImporterFactory; use Drupal\Core\Config\ImportStorageTransformer; use Drupal\Core\Config\StorageComparer; use Drupal\Core\Config\StorageInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Attribute\Option; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\DependencyInjection\Attribute\Autowire; /** * Import configuration. * * @internal */ #[AsCommand( name: 'config:import', description: 'Import configuration', aliases: ['cim'], )] class ConfigImportCommand extends Command { use StringTranslationTrait; use ConfigCommandTrait; public function __construct( #[Autowire(service: 'config.storage')] private readonly StorageInterface $active, #[Autowire(service: 'config.storage.sync')] private readonly StorageInterface $sync, private readonly ImportStorageTransformer $transformer, private readonly ConfigImporterFactory $importerFactory, ) { parent::__construct(); } /** * Export the configuration. * * @param \Symfony\Component\Console\Style\SymfonyStyle $io * The symfony style. * @param bool $yes * The command option to skip the confirmation question. * * @return int * The command result. */ public function __invoke( SymfonyStyle $io, #[Option(description: 'Answer the confirmation question with yes.', shortcut: 'y')] bool $yes = FALSE, ): int { // Do the import storage transformation. $import = $this->transformer->transform($this->sync); $comparer = new StorageComparer($import, $this->active); $comparer->createChangelist(); if (!$comparer->hasChanges()) { $io->success((string) $this->t('There are no changes to import.')); return self::SUCCESS; } $this->renderTable($comparer, $io); if (!$yes && !$io->confirm((string) $this->t('Import the listed configuration changes?'))) { throw new UserAbortException('Cancelled'); } $importer = $this->importerFactory->get($comparer); if ($importer->alreadyImporting()) { $io->warning((string) $this->t('Another request may be synchronizing configuration already.')); return Command::FAILURE; } try { $importer->validate(); $importer->import(); } catch (ConfigImporterException $e) { $io->error($e->getMessage()); return Command::FAILURE; } $errors = $importer->getErrors(); if (empty($errors)) { $io->success((string) $this->t('The configuration was imported successfully.')); return Command::SUCCESS; } $io->error((string) $this->t('The configuration was imported with errors.')); foreach ($errors as $error) { $io->error((string) $error); } return Command::FAILURE; } }
core/tests/Drupal/FunctionalTests/Core/Config/ConfigImportCommandTest.php 0 → 100644 +430 −0 File added.Preview size limit exceeded, changes collapsed. Show changes