From c34dc29cb96a1872a154cb027c223708c7738527 Mon Sep 17 00:00:00 2001 From: Vlad Podorozhnyi Date: Tue, 19 Mar 2024 14:27:47 +0100 Subject: [PATCH] Allow to KEEP configs unchanged on the environemnt. So base config will not override configs that are already set on environment. --- Model/Processor/ImportProcessor.php | 66 +++++++++++++------ .../Model/Processor/ImportProcessorTest.php | 16 ++++- 2 files changed, 61 insertions(+), 21 deletions(-) diff --git a/Model/Processor/ImportProcessor.php b/Model/Processor/ImportProcessor.php index 470b643..fe6ff6c 100644 --- a/Model/Processor/ImportProcessor.php +++ b/Model/Processor/ImportProcessor.php @@ -19,6 +19,8 @@ class ImportProcessor extends AbstractProcessor implements ImportProcessorInterface { private const DELETE_CONFIG_FLAG = '!!DELETE'; + private const KEEP_CONFIG_FLAG = '!!KEEP'; + /** * @var WriterInterface */ @@ -92,39 +94,63 @@ public function process() $this->getOutput()->writeln('Maybe this is expected behaviour, because you passed the --allow-empty-directories option.'); } + $configs = $this->collectConfigs($files); + + foreach ($configs as $configPath => $configValue) { + foreach ($configValue as $scopeType => $scopeValue) { + foreach ($scopeValue as $scopeId => $value) { + + if ($value === self::DELETE_CONFIG_FLAG) { + $this->configWriter->delete($configPath, $scopeType, $scopeId); + $this->getOutput()->writeln(sprintf('[%s] [%s] %s => %s', $scopeType, $scopeId, $configPath, 'DELETED')); + continue; + } + + if ($value === self::KEEP_CONFIG_FLAG) { + $this->getOutput()->writeln(sprintf('[%s] [%s] %s => %s', $scopeType, $scopeId, $configPath, 'KEPT')); + continue; + } + + $this->configWriter->save($configPath, $value, $scopeType, $scopeId); + $this->getOutput()->writeln(sprintf('[%s] [%s] %s => %s', $scopeType, $scopeId, $configPath, $value)); + } + } + } + } + + /** + * @param array $files + * @return array + */ + private function collectConfigs(array $files): array + { + $buffer = []; + foreach ($files as $file) { $valuesSet = 0; $configurations = $this->getConfigurationsFromFile($file); + foreach ($configurations as $configPath => $configValues) { - $scopeConfigValues = $this->transformConfigToScopeConfig($configPath, $configValues); - foreach ($scopeConfigValues as $scopeConfigValue) { - if ($scopeConfigValue['value'] === self::DELETE_CONFIG_FLAG) { - $this->configWriter->delete( - $configPath, - $scopeConfigValue['scope'], - $this->scopeConverter->convert($scopeConfigValue['scope_id'], $scopeConfigValue['scope']) - ); - $this->getOutput()->writeln(sprintf('%s => %s', $configPath, 'DELETED')); - $valuesSet++; + if (!isset($buffer[$configPath])) { + $buffer[$configPath] = []; + } - continue; - } + $scopeConfigValues = $this->transformConfigToScopeConfig($configPath, $configValues); - $this->configWriter->save( - $configPath, - $scopeConfigValue['value'], - $scopeConfigValue['scope'], - $this->scopeConverter->convert($scopeConfigValue['scope_id'], $scopeConfigValue['scope']) - ); + foreach ($scopeConfigValues as $scopeConfigValue) { - $this->getOutput()->writeln(sprintf('%s => %s', $configPath, $scopeConfigValue['value'])); + $scopeType = $scopeConfigValue['scope']; + $scopeId = $this->scopeConverter->convert($scopeConfigValue['scope_id'], $scopeConfigValue['scope']); + $buffer[$configPath][$scopeType][$scopeId] = $scopeConfigValue['value']; $valuesSet++; } } - $this->getOutput()->writeln(sprintf('Processed: %s with %s value(s).', $file, $valuesSet)); + $this->getOutput()->writeln(sprintf('Configs collected: %s with %s value(s).', $file, $valuesSet)); } + + return $buffer; } /** diff --git a/Test/Unit/Model/Processor/ImportProcessorTest.php b/Test/Unit/Model/Processor/ImportProcessorTest.php index e1be178..c54362a 100644 --- a/Test/Unit/Model/Processor/ImportProcessorTest.php +++ b/Test/Unit/Model/Processor/ImportProcessorTest.php @@ -14,6 +14,7 @@ use Semaio\ConfigImportExport\Model\File\Reader\YamlReader; use Semaio\ConfigImportExport\Model\Processor\ImportProcessor; use Semaio\ConfigImportExport\Model\Validator\ScopeValidatorInterface; +use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; class ImportProcessorTest extends TestCase @@ -67,6 +68,9 @@ public function processWithoutFiles(): void $this->expectException(InvalidArgumentException::class); $processor = new ImportProcessor($this->configWriterMock, $this->scopeValidatorMock, $this->scopeConverterMock, []); + $inputMock = $this->getMockBuilder(InputInterface::class)->getMock(); + $inputMock->method('getOption')->with('allow-empty-directories')->willReturn(false); + $processor->setInput($inputMock); $processor->setFinder($finderMock); $processor->process(); } @@ -126,6 +130,16 @@ public function process(): void 0 => '!!DELETE', ], ], + 'test/config/custom_field_to_be_keeped' => [ + 'default' => [ + 0 => 'VALUE_THAT_SHOULD_NOT_BE_PROCESSED', + ], + ], + 'test/config/custom_field_to_be_keeped' => [ + 'default' => [ + 0 => '!!KEEP', + ], + ], ]; $readerMock = $this->getMockBuilder(YamlReader::class) @@ -133,7 +147,7 @@ public function process(): void ->getMock(); $readerMock->expects($this->once())->method('parse')->willReturn($parseResult); - $this->scopeValidatorMock->expects($this->exactly(2))->method('validate')->willReturn(true); + $this->scopeValidatorMock->expects($this->exactly(3))->method('validate')->willReturn(true); $this->configWriterMock->expects($this->once())->method('save'); $this->configWriterMock->expects($this->once())->method('delete');