diff --git a/app/code/Magento/Analytics/Cron/SignUp.php b/app/code/Magento/Analytics/Cron/SignUp.php index 8b0b797177234..c17b9b8c381c3 100644 --- a/app/code/Magento/Analytics/Cron/SignUp.php +++ b/app/code/Magento/Analytics/Cron/SignUp.php @@ -7,7 +7,7 @@ use Magento\Analytics\Model\Config\Backend\Enabled\SubscriptionHandler; use Magento\Analytics\Model\Connector; -use Magento\Analytics\Model\FlagManager; +use Magento\Framework\FlagManager; use Magento\Framework\App\Config\ReinitableConfigInterface; use Magento\Framework\App\Config\Storage\WriterInterface; diff --git a/app/code/Magento/Analytics/Cron/Update.php b/app/code/Magento/Analytics/Cron/Update.php index c3c5ede3d4020..36e6c3e59e5c7 100644 --- a/app/code/Magento/Analytics/Cron/Update.php +++ b/app/code/Magento/Analytics/Cron/Update.php @@ -6,8 +6,8 @@ namespace Magento\Analytics\Cron; use Magento\Analytics\Model\Connector; -use Magento\Analytics\Model\FlagManager; use Magento\Analytics\Model\Plugin\BaseUrlConfigPlugin; +use Magento\Framework\FlagManager; use Magento\Framework\App\Config\ReinitableConfigInterface; use Magento\Framework\App\Config\Storage\WriterInterface; diff --git a/app/code/Magento/Analytics/Model/Config/Backend/Enabled/SubscriptionHandler.php b/app/code/Magento/Analytics/Model/Config/Backend/Enabled/SubscriptionHandler.php index fb9b6ecede0d5..71f2100a5cebc 100644 --- a/app/code/Magento/Analytics/Model/Config/Backend/Enabled/SubscriptionHandler.php +++ b/app/code/Magento/Analytics/Model/Config/Backend/Enabled/SubscriptionHandler.php @@ -7,8 +7,8 @@ use Magento\Analytics\Model\AnalyticsToken; use Magento\Analytics\Model\Config\Backend\CollectionTime; -use Magento\Analytics\Model\FlagManager; use Magento\Analytics\Model\NotificationTime; +use Magento\Framework\FlagManager; use Magento\Framework\App\Config\Storage\WriterInterface; /** diff --git a/app/code/Magento/Analytics/Model/Connector/UpdateCommand.php b/app/code/Magento/Analytics/Model/Connector/UpdateCommand.php index a4560c43904b9..185b2c1ebe606 100644 --- a/app/code/Magento/Analytics/Model/Connector/UpdateCommand.php +++ b/app/code/Magento/Analytics/Model/Connector/UpdateCommand.php @@ -6,9 +6,9 @@ namespace Magento\Analytics\Model\Connector; use Magento\Analytics\Model\AnalyticsToken; -use Magento\Analytics\Model\FlagManager; use Magento\Analytics\Model\Plugin\BaseUrlConfigPlugin; use Magento\Config\Model\Config; +use Magento\Framework\FlagManager; use Magento\Framework\HTTP\ZendClient; use Magento\Store\Model\Store; use Psr\Log\LoggerInterface; diff --git a/app/code/Magento/Analytics/Model/FileInfoManager.php b/app/code/Magento/Analytics/Model/FileInfoManager.php index c8ca204acd83b..e37700e665420 100644 --- a/app/code/Magento/Analytics/Model/FileInfoManager.php +++ b/app/code/Magento/Analytics/Model/FileInfoManager.php @@ -6,6 +6,7 @@ namespace Magento\Analytics\Model; use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\FlagManager; /** * Manage saving and loading FileInfo object. diff --git a/app/code/Magento/Analytics/Model/NotificationTime.php b/app/code/Magento/Analytics/Model/NotificationTime.php index 06be68e709f03..47b9f35cc77b9 100644 --- a/app/code/Magento/Analytics/Model/NotificationTime.php +++ b/app/code/Magento/Analytics/Model/NotificationTime.php @@ -3,9 +3,10 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Analytics\Model; +use Magento\Framework\FlagManager; + /** * Class NotificationTime * diff --git a/app/code/Magento/Analytics/Model/Plugin/BaseUrlConfigPlugin.php b/app/code/Magento/Analytics/Model/Plugin/BaseUrlConfigPlugin.php index d7bfcafc013e5..705c627798aa9 100644 --- a/app/code/Magento/Analytics/Model/Plugin/BaseUrlConfigPlugin.php +++ b/app/code/Magento/Analytics/Model/Plugin/BaseUrlConfigPlugin.php @@ -5,8 +5,8 @@ */ namespace Magento\Analytics\Model\Plugin; -use Magento\Analytics\Model\FlagManager; use Magento\Analytics\Model\SubscriptionStatusProvider; +use Magento\Framework\FlagManager; use Magento\Framework\App\Config\Storage\WriterInterface; /** diff --git a/app/code/Magento/Analytics/Model/SubscriptionStatusProvider.php b/app/code/Magento/Analytics/Model/SubscriptionStatusProvider.php index da1bc856ce0a5..fc363231cf4d5 100644 --- a/app/code/Magento/Analytics/Model/SubscriptionStatusProvider.php +++ b/app/code/Magento/Analytics/Model/SubscriptionStatusProvider.php @@ -7,6 +7,7 @@ use Magento\Analytics\Model\Config\Backend\Enabled\SubscriptionHandler; use Magento\Config\App\Config\Type\System; +use Magento\Framework\FlagManager; /** * Provider of subscription status. diff --git a/app/code/Magento/Analytics/Test/Unit/Cron/SignUpTest.php b/app/code/Magento/Analytics/Test/Unit/Cron/SignUpTest.php index 38a9dc59216db..c8ab5a6f4649e 100644 --- a/app/code/Magento/Analytics/Test/Unit/Cron/SignUpTest.php +++ b/app/code/Magento/Analytics/Test/Unit/Cron/SignUpTest.php @@ -8,9 +8,9 @@ use Magento\Analytics\Cron\SignUp; use Magento\Analytics\Model\Config\Backend\Enabled\SubscriptionHandler; use Magento\Analytics\Model\Connector; -use Magento\Analytics\Model\FlagManager; use Magento\Framework\App\Config\ReinitableConfigInterface; use Magento\Framework\App\Config\Storage\WriterInterface; +use Magento\Framework\FlagManager; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) diff --git a/app/code/Magento/Analytics/Test/Unit/Cron/UpdateTest.php b/app/code/Magento/Analytics/Test/Unit/Cron/UpdateTest.php index 23d1df343cdf8..9a5355de62a5c 100644 --- a/app/code/Magento/Analytics/Test/Unit/Cron/UpdateTest.php +++ b/app/code/Magento/Analytics/Test/Unit/Cron/UpdateTest.php @@ -7,10 +7,10 @@ use Magento\Analytics\Cron\Update; use Magento\Analytics\Model\Connector; -use Magento\Analytics\Model\FlagManager; use Magento\Analytics\Model\Plugin\BaseUrlConfigPlugin; use Magento\Framework\App\Config\ReinitableConfigInterface; use Magento\Framework\App\Config\Storage\WriterInterface; +use Magento\Framework\FlagManager; /** * Class Update diff --git a/app/code/Magento/Analytics/Test/Unit/Model/Config/Backend/Enabled/SubscriptionHandlerTest.php b/app/code/Magento/Analytics/Test/Unit/Model/Config/Backend/Enabled/SubscriptionHandlerTest.php index 646babebfe54a..d01101bf5cc3b 100644 --- a/app/code/Magento/Analytics/Test/Unit/Model/Config/Backend/Enabled/SubscriptionHandlerTest.php +++ b/app/code/Magento/Analytics/Test/Unit/Model/Config/Backend/Enabled/SubscriptionHandlerTest.php @@ -9,9 +9,9 @@ use Magento\Analytics\Model\AnalyticsToken; use Magento\Analytics\Model\Config\Backend\CollectionTime; use Magento\Analytics\Model\Config\Backend\Enabled\SubscriptionHandler; -use Magento\Analytics\Model\FlagManager; use Magento\Analytics\Model\NotificationTime; use Magento\Framework\App\Config\Storage\WriterInterface; +use Magento\Framework\FlagManager; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; /** diff --git a/app/code/Magento/Analytics/Test/Unit/Model/Connector/UpdateCommandTest.php b/app/code/Magento/Analytics/Test/Unit/Model/Connector/UpdateCommandTest.php index e51952aa23022..c9cb6b8b0f712 100644 --- a/app/code/Magento/Analytics/Test/Unit/Model/Connector/UpdateCommandTest.php +++ b/app/code/Magento/Analytics/Test/Unit/Model/Connector/UpdateCommandTest.php @@ -8,9 +8,9 @@ use Magento\Analytics\Model\AnalyticsToken; use Magento\Analytics\Model\Connector\Http\ClientInterface; use Magento\Analytics\Model\Connector\UpdateCommand; -use Magento\Analytics\Model\FlagManager; use Magento\Analytics\Model\Plugin\BaseUrlConfigPlugin; use Magento\Config\Model\Config; +use Magento\Framework\FlagManager; use Magento\Framework\HTTP\ZendClient; use Psr\Log\LoggerInterface; diff --git a/app/code/Magento/Analytics/Test/Unit/Model/FileInfoManagerTest.php b/app/code/Magento/Analytics/Test/Unit/Model/FileInfoManagerTest.php index 6e60d8b9678fb..c8c07ae8240c3 100644 --- a/app/code/Magento/Analytics/Test/Unit/Model/FileInfoManagerTest.php +++ b/app/code/Magento/Analytics/Test/Unit/Model/FileInfoManagerTest.php @@ -8,7 +8,7 @@ use Magento\Analytics\Model\FileInfo; use Magento\Analytics\Model\FileInfoFactory; use Magento\Analytics\Model\FileInfoManager; -use Magento\Analytics\Model\FlagManager; +use Magento\Framework\FlagManager; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; /** diff --git a/app/code/Magento/Analytics/Test/Unit/Model/NotificationTimeTest.php b/app/code/Magento/Analytics/Test/Unit/Model/NotificationTimeTest.php index 61e11a86d8662..c2a947362d1db 100644 --- a/app/code/Magento/Analytics/Test/Unit/Model/NotificationTimeTest.php +++ b/app/code/Magento/Analytics/Test/Unit/Model/NotificationTimeTest.php @@ -6,7 +6,7 @@ namespace Magento\Analytics\Test\Unit\Model; -use Magento\Analytics\Model\FlagManager; +use Magento\Framework\FlagManager; use Magento\Analytics\Model\NotificationTime; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; diff --git a/app/code/Magento/Analytics/Test/Unit/Model/Plugin/BaseUrlConfigPluginTest.php b/app/code/Magento/Analytics/Test/Unit/Model/Plugin/BaseUrlConfigPluginTest.php index 85b2ced0705f3..caf81b77fbdf9 100644 --- a/app/code/Magento/Analytics/Test/Unit/Model/Plugin/BaseUrlConfigPluginTest.php +++ b/app/code/Magento/Analytics/Test/Unit/Model/Plugin/BaseUrlConfigPluginTest.php @@ -5,10 +5,10 @@ */ namespace Magento\Analytics\Test\Unit\Model\Plugin; -use Magento\Analytics\Model\FlagManager; use Magento\Analytics\Model\Plugin\BaseUrlConfigPlugin; use Magento\Analytics\Model\SubscriptionStatusProvider; use Magento\Config\Model\Config\Backend\Baseurl; +use Magento\Framework\FlagManager; use Magento\Framework\App\Config\Storage\WriterInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; use Magento\Store\Model\Store; diff --git a/app/code/Magento/Analytics/Test/Unit/Model/SubscriptionStatusProviderTest.php b/app/code/Magento/Analytics/Test/Unit/Model/SubscriptionStatusProviderTest.php index eb4403ad7d4d1..9e4defe195b32 100644 --- a/app/code/Magento/Analytics/Test/Unit/Model/SubscriptionStatusProviderTest.php +++ b/app/code/Magento/Analytics/Test/Unit/Model/SubscriptionStatusProviderTest.php @@ -7,9 +7,9 @@ use Magento\Analytics\Model\AnalyticsToken; use Magento\Analytics\Model\Config\Backend\Enabled\SubscriptionHandler; -use Magento\Analytics\Model\FlagManager; use Magento\Analytics\Model\SubscriptionStatusProvider; use Magento\Config\App\Config\Type\System; +use Magento\Framework\FlagManager; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; /** diff --git a/app/code/Magento/Config/App/Config/Source/InitialSnapshotConfigSource.php b/app/code/Magento/Config/App/Config/Source/InitialSnapshotConfigSource.php new file mode 100644 index 0000000000000..d1658a4badf37 --- /dev/null +++ b/app/code/Magento/Config/App/Config/Source/InitialSnapshotConfigSource.php @@ -0,0 +1,57 @@ +flagManager = $flagManager; + $this->dataObjectFactory = $dataObjectFactory; + } + + /** + * Retrieves previously imported configuration. + * Snapshots are stored in flags. + * + * {@inheritdoc} + */ + public function get($path = '') + { + $flagData = (array)($this->flagManager->getFlagData('system_config_snapshot') ?: []); + + $data = $this->dataObjectFactory->create( + ['data' => $flagData] + ); + + return $data->getData($path) ?: []; + } +} diff --git a/app/code/Magento/Config/App/Config/Type/System.php b/app/code/Magento/Config/App/Config/Type/System.php index 04ec7ee856776..c8712eb1f4420 100644 --- a/app/code/Magento/Config/App/Config/Type/System.php +++ b/app/code/Magento/Config/App/Config/Type/System.php @@ -57,6 +57,13 @@ class System implements ConfigTypeInterface */ private $serializer; + /** + * The type of config. + * + * @var string + */ + private $configType; + /** * @param \Magento\Framework\App\Config\ConfigSourceInterface $source * @param \Magento\Framework\App\Config\Spi\PostProcessorInterface $postProcessor @@ -65,6 +72,7 @@ class System implements ConfigTypeInterface * @param \Magento\Framework\Serialize\SerializerInterface $serializer * @param \Magento\Framework\App\Config\Spi\PreProcessorInterface $preProcessor * @param int $cachingNestedLevel + * @param string $configType */ public function __construct( \Magento\Framework\App\Config\ConfigSourceInterface $source, @@ -73,7 +81,8 @@ public function __construct( \Magento\Framework\Cache\FrontendInterface $cache, \Magento\Framework\Serialize\SerializerInterface $serializer, \Magento\Framework\App\Config\Spi\PreProcessorInterface $preProcessor, - $cachingNestedLevel = 1 + $cachingNestedLevel = 1, + $configType = self::CONFIG_TYPE ) { $this->source = $source; $this->postProcessor = $postProcessor; @@ -82,6 +91,7 @@ public function __construct( $this->cachingNestedLevel = $cachingNestedLevel; $this->fallback = $fallback; $this->serializer = $serializer; + $this->configType = $configType; } /** @@ -93,7 +103,7 @@ public function get($path = '') $path = ''; } if (!$this->data) { - $data = $this->cache->load(self::CONFIG_TYPE); + $data = $this->cache->load($this->configType); if (!$data) { $data = $this->preProcessor->process($this->source->get()); $this->data = new DataObject($data); @@ -104,7 +114,7 @@ public function get($path = '') $this->data = new DataObject($data); $this->cache->save( $this->serializer->serialize($this->data->getData()), - self::CONFIG_TYPE, + $this->configType, [self::CACHE_TAG] ); } else { diff --git a/app/code/Magento/Config/Console/Command/ConfigSet/EmulatedProcessorFacade.php b/app/code/Magento/Config/Console/Command/ConfigSet/EmulatedProcessorFacade.php new file mode 100644 index 0000000000000..cb5ba6f09a5e1 --- /dev/null +++ b/app/code/Magento/Config/Console/Command/ConfigSet/EmulatedProcessorFacade.php @@ -0,0 +1,95 @@ +scope = $scope; + $this->state = $state; + $this->processorFacadeFactory = $processorFacadeFactory; + } + + /** + * Processes config:set command. + * + * @param string $path The configuration path in format group/section/field_name + * @param string $value The configuration value + * @param string $scope The configuration scope (default, website, or store) + * @param string $scopeCode The scope code + * @param boolean $lock The lock flag + * @return string Processor response message + * @throws RuntimeException If exception was catch + */ + public function process($path, $value, $scope, $scopeCode, $lock) + { + $currentScope = $this->scope->getCurrentScope(); + + try { + // Emulating adminhtml scope to be able to read configs. + return $this->state->emulateAreaCode(Area::AREA_ADMINHTML, function () use ( + $path, + $value, + $scope, + $scopeCode, + $lock + ) { + $this->scope->setCurrentScope(Area::AREA_ADMINHTML); + + return $this->processorFacadeFactory->create()->process( + $path, + $value, + $scope, + $scopeCode, + $lock + ); + }); + } catch (LocalizedException $exception) { + throw new RuntimeException(__('%1', $exception->getMessage()), $exception); + } finally { + $this->scope->setCurrentScope($currentScope); + } + } +} diff --git a/app/code/Magento/Config/Console/Command/ConfigSet/LockProcessor.php b/app/code/Magento/Config/Console/Command/ConfigSet/LockProcessor.php index 0a9da86aecf32..3b09bd55b8b45 100644 --- a/app/code/Magento/Config/Console/Command/ConfigSet/LockProcessor.php +++ b/app/code/Magento/Config/Console/Command/ConfigSet/LockProcessor.php @@ -6,10 +6,8 @@ namespace Magento\Config\Console\Command\ConfigSet; use Magento\Config\App\Config\Type\System; -use Magento\Config\Model\Config\Structure; +use Magento\Config\Model\PreparedValueFactory; use Magento\Framework\App\Config\ConfigPathResolver; -use Magento\Framework\App\Config\Value; -use Magento\Framework\App\Config\ValueFactory; use Magento\Framework\App\DeploymentConfig; use Magento\Framework\Config\File\ConfigFilePool; use Magento\Framework\Exception\CouldNotSaveException; @@ -24,11 +22,11 @@ class LockProcessor implements ConfigSetProcessorInterface { /** - * The deployment configuration reader. + * The factory for prepared value. * - * @var DeploymentConfig + * @var PreparedValueFactory */ - private $deploymentConfig; + private $preparedValueFactory; /** * The deployment configuration writer. @@ -52,42 +50,21 @@ class LockProcessor implements ConfigSetProcessorInterface private $configPathResolver; /** - * The manager for system configuration structure. - * - * @var Structure - */ - private $configStructure; - - /** - * The factory for configuration value objects. - * - * @see Value - * @var ValueFactory - */ - private $configValueFactory; - - /** - * @param DeploymentConfig $deploymentConfig The deployment configuration reader + * @param PreparedValueFactory $preparedValueFactory The factory for prepared value * @param DeploymentConfig\Writer $writer The deployment configuration writer * @param ArrayManager $arrayManager An array manager for different manipulations with arrays * @param ConfigPathResolver $configPathResolver The resolver for configuration paths according to source type - * @param Structure $configStructure The manager for system configuration structure - * @param ValueFactory $configValueFactory The factory for configuration value objects */ public function __construct( - DeploymentConfig $deploymentConfig, + PreparedValueFactory $preparedValueFactory, DeploymentConfig\Writer $writer, ArrayManager $arrayManager, - ConfigPathResolver $configPathResolver, - Structure $configStructure, - ValueFactory $configValueFactory + ConfigPathResolver $configPathResolver ) { - $this->deploymentConfig = $deploymentConfig; + $this->preparedValueFactory = $preparedValueFactory; $this->deploymentConfigWriter = $writer; $this->arrayManager = $arrayManager; $this->configPathResolver = $configPathResolver; - $this->configStructure = $configStructure; - $this->configValueFactory = $configValueFactory; } /** @@ -100,19 +77,7 @@ public function process($path, $value, $scope, $scopeCode) { try { $configPath = $this->configPathResolver->resolve($path, $scope, $scopeCode, System::CONFIG_TYPE); - /** @var Structure\Element\Field $field */ - $field = $this->deploymentConfig->isAvailable() - ? $this->configStructure->getElement($path) - : null; - /** @var Value $backendModel */ - $backendModel = $field && $field->hasBackendModel() - ? $field->getBackendModel() - : $this->configValueFactory->create(); - - $backendModel->setPath($path); - $backendModel->setScope($scope); - $backendModel->setScopeId($scopeCode); - $backendModel->setValue($value); + $backendModel = $this->preparedValueFactory->create($path, $value, $scope, $scopeCode); /** * Temporary solution until Magento introduce unified interface diff --git a/app/code/Magento/Config/Console/Command/ConfigSetCommand.php b/app/code/Magento/Config/Console/Command/ConfigSetCommand.php index 54759be8943d6..3629cde113d2e 100644 --- a/app/code/Magento/Config/Console/Command/ConfigSetCommand.php +++ b/app/code/Magento/Config/Console/Command/ConfigSetCommand.php @@ -5,11 +5,12 @@ */ namespace Magento\Config\Console\Command; -use Magento\Config\Console\Command\ConfigSet\ProcessorFacadeFactory; -use Magento\Framework\App\Area; +use Magento\Config\App\Config\Type\System; +use Magento\Config\Console\Command\ConfigSet\EmulatedProcessorFacade; +use Magento\Deploy\Model\DeploymentConfig\ChangeDetector; +use Magento\Deploy\Model\DeploymentConfig\Hash; +use Magento\Deploy\Model\DeploymentConfig\Validator; use Magento\Framework\App\Config\ScopeConfigInterface; -use Magento\Framework\App\State; -use Magento\Framework\Config\ScopeInterface; use Magento\Framework\Console\Cli; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; @@ -33,39 +34,39 @@ class ConfigSetCommand extends Command /**#@-*/ /** - * Scope manager. + * The emulated processor facade. * - * @var ScopeInterface + * @var EmulatedProcessorFacade */ - private $scope; + private $emulatedProcessorFacade; /** - * Application state. + * The config change detector. * - * @var State + * @var ChangeDetector */ - private $state; + private $changeDetector; /** - * The processor facade factory + * The hash manager. * - * @var ProcessorFacadeFactory + * @var Hash */ - private $processorFacadeFactory; + private $hash; /** - * @param ScopeInterface $scope Scope manager - * @param State $state Application state - * @param ProcessorFacadeFactory $processorFacadeFactory The processor facade factory + * @param EmulatedProcessorFacade $emulatedProcessorFacade The emulated processor facade + * @param ChangeDetector $changeDetector The config change detector + * @param Hash $hash The hash manager */ public function __construct( - ScopeInterface $scope, - State $state, - ProcessorFacadeFactory $processorFacadeFactory + EmulatedProcessorFacade $emulatedProcessorFacade, + ChangeDetector $changeDetector, + Hash $hash ) { - $this->scope = $scope; - $this->state = $state; - $this->processorFacadeFactory = $processorFacadeFactory; + $this->emulatedProcessorFacade = $emulatedProcessorFacade; + $this->changeDetector = $changeDetector; + $this->hash = $hash; parent::__construct(); } @@ -115,24 +116,29 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { + if ($this->changeDetector->hasChanges(System::CONFIG_TYPE)) { + $output->writeln( + '' + . 'This command is unavailable right now. ' + . 'To continue working with it please run app:config:import or setup:upgrade command before.' + . '' + ); + + return Cli::RETURN_FAILURE; + } + try { - $areaScope = $this->scope->getCurrentScope(); - // Emulating adminhtml scope to be able to read configs. - $this->state->emulateAreaCode(Area::AREA_ADMINHTML, function () use ($input, $output) { - $this->scope->setCurrentScope(Area::AREA_ADMINHTML); - - $message = $this->processorFacadeFactory->create()->process( - $input->getArgument(static::ARG_PATH), - $input->getArgument(static::ARG_VALUE), - $input->getOption(static::OPTION_SCOPE), - $input->getOption(static::OPTION_SCOPE_CODE), - $input->getOption(static::OPTION_LOCK) - ); - - $output->writeln('' . $message . ''); - }); - - $this->scope->setCurrentScope($areaScope); + $message = $this->emulatedProcessorFacade->process( + $input->getArgument(static::ARG_PATH), + $input->getArgument(static::ARG_VALUE), + $input->getOption(static::OPTION_SCOPE), + $input->getOption(static::OPTION_SCOPE_CODE), + $input->getOption(static::OPTION_LOCK) + ); + + $this->hash->regenerate(System::CONFIG_TYPE); + + $output->writeln('' . $message . ''); return Cli::RETURN_SUCCESS; } catch (\Exception $exception) { diff --git a/app/code/Magento/Config/Model/Config/BackendFactory.php b/app/code/Magento/Config/Model/Config/BackendFactory.php index 21e97fec9f88d..235b4e309c8ee 100644 --- a/app/code/Magento/Config/Model/Config/BackendFactory.php +++ b/app/code/Magento/Config/Model/Config/BackendFactory.php @@ -26,12 +26,13 @@ public function __construct(\Magento\Framework\ObjectManagerInterface $objectman * Create backend model by name * * @param string $modelName + * @param array $arguments The object arguments * @return \Magento\Framework\App\Config\ValueInterface * @throws \InvalidArgumentException */ - public function create($modelName) + public function create($modelName, array $arguments = []) { - $model = $this->_objectManager->create($modelName); + $model = $this->_objectManager->create($modelName, $arguments); if (!$model instanceof \Magento\Framework\App\Config\ValueInterface) { throw new \InvalidArgumentException('Invalid config field backend model: ' . $modelName); } diff --git a/app/code/Magento/Config/Model/Config/Importer.php b/app/code/Magento/Config/Model/Config/Importer.php index 573f0e646f14d..7c3e4450e3469 100644 --- a/app/code/Magento/Config/Model/Config/Importer.php +++ b/app/code/Magento/Config/Model/Config/Importer.php @@ -212,7 +212,6 @@ private function invokeSave(array $scopeData, $scope, $scopeCode = null) $backendModel = $this->valueFactory->create($path, $value, $scope, $scopeCode); if ($backendModel instanceof Config\Value) { - $backendModel->setData('force_changed_value', true); $backendModel->beforeSave(); $backendModel->afterSave(); } diff --git a/app/code/Magento/Config/Model/PreparedValueFactory.php b/app/code/Magento/Config/Model/PreparedValueFactory.php index 20484f3532c36..14555096336c6 100644 --- a/app/code/Magento/Config/Model/PreparedValueFactory.php +++ b/app/code/Magento/Config/Model/PreparedValueFactory.php @@ -5,11 +5,12 @@ */ namespace Magento\Config\Model; +use Magento\Config\Model\Config\BackendFactory; use Magento\Config\Model\Config\Structure; use Magento\Config\Model\Config\StructureFactory; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\Config\ValueInterface; use Magento\Framework\App\Config\Value; -use Magento\Framework\App\Config\ValueFactory; use Magento\Framework\App\ScopeInterface; use Magento\Framework\App\ScopeResolverPool; use Magento\Framework\Exception\RuntimeException; @@ -39,23 +40,33 @@ class PreparedValueFactory * The factory for configuration value objects. * * @see ValueInterface - * @var ValueFactory + * @var BackendFactory */ private $valueFactory; + /** + * The scope configuration. + * + * @var ScopeConfigInterface + */ + private $config; + /** * @param ScopeResolverPool $scopeResolverPool The scope resolver pool * @param StructureFactory $structureFactory The manager for system configuration structure - * @param ValueFactory $valueFactory The factory for configuration value objects + * @param BackendFactory $valueFactory The factory for configuration value objects + * @param ScopeConfigInterface $config The scope configuration */ public function __construct( ScopeResolverPool $scopeResolverPool, StructureFactory $structureFactory, - ValueFactory $valueFactory + BackendFactory $valueFactory, + ScopeConfigInterface $config ) { $this->scopeResolverPool = $scopeResolverPool; $this->structureFactory = $structureFactory; $this->valueFactory = $valueFactory; + $this->config = $config; } /** @@ -77,10 +88,15 @@ public function create($path, $value, $scope, $scopeCode = null) $structure = $this->structureFactory->create(); /** @var Structure\ElementInterface $field */ $field = $structure->getElement($path); + /** @var string $backendModelName */ + $backendModelName = $field instanceof Structure\Element\Field && $field->hasBackendModel() + ? $field->getData()['backend_model'] + : ValueInterface::class; /** @var ValueInterface $backendModel */ - $backendModel = $field instanceof Structure\Element\Field && $field->hasBackendModel() - ? $field->getBackendModel() - : $this->valueFactory->create(); + $backendModel = $this->valueFactory->create( + $backendModelName, + ['config' => $this->config] + ); if ($backendModel instanceof Value) { $scopeId = 0; diff --git a/app/code/Magento/Config/Test/Unit/App/Config/Source/InitialSnapshotConfigSourceTest.php b/app/code/Magento/Config/Test/Unit/App/Config/Source/InitialSnapshotConfigSourceTest.php new file mode 100644 index 0000000000000..67b0f3d034d11 --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/App/Config/Source/InitialSnapshotConfigSourceTest.php @@ -0,0 +1,84 @@ +flagManagerMock = $this->getMockBuilder(FlagManager::class) + ->disableOriginalConstructor() + ->getMock(); + $this->dataObjectFactoryMock = $this->getMockBuilder(DataObjectFactory::class) + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + $this->dataObjectMock = $this->getMockBuilder(DataObject::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->dataObjectFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($this->dataObjectMock); + + $this->model = new InitialSnapshotConfigSource( + $this->flagManagerMock, + $this->dataObjectFactoryMock + ); + } + + public function testGet() + { + $this->flagManagerMock->expects($this->exactly(2)) + ->method('getFlagData') + ->with('system_config_snapshot') + ->willReturnOnConsecutiveCalls( + ['some' => 'data'], + 'data' + ); + $this->dataObjectMock->expects($this->exactly(2)) + ->method('getData') + ->willReturnOnConsecutiveCalls( + ['some' => 'data'], + 'data' + ); + + $this->assertSame(['some' => 'data'], $this->model->get()); + $this->assertSame('data', $this->model->get('some/path')); + } +} diff --git a/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/EmulatedProcessorFacadeTest.php b/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/EmulatedProcessorFacadeTest.php new file mode 100644 index 0000000000000..07c119cda8742 --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/EmulatedProcessorFacadeTest.php @@ -0,0 +1,74 @@ +scopeMock = $this->getMockBuilder(ScopeInterface::class) + ->getMockForAbstractClass(); + $this->stateMock = $this->getMockBuilder(State::class) + ->disableOriginalConstructor() + ->getMock(); + $this->processorFacadeFactory = $this->getMockBuilder(ProcessorFacadeFactory::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->model = new EmulatedProcessorFacade( + $this->scopeMock, + $this->stateMock, + $this->processorFacadeFactory + ); + } + + public function testProcess() + { + $this->scopeMock->expects($this->once()) + ->method('getCurrentScope') + ->willReturn('currentScope'); + $this->scopeMock->expects($this->once()) + ->method('setCurrentScope') + ->with('currentScope'); + $this->stateMock->expects($this->once()) + ->method('emulateAreaCode'); + + $this->model->process( + 'test/test/test', + 'value', + ScopeConfigInterface::SCOPE_TYPE_DEFAULT, + null, + false + ); + } +} diff --git a/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/LockProcessorTest.php b/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/LockProcessorTest.php index 8686de88b19e1..e37214411ff51 100644 --- a/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/LockProcessorTest.php +++ b/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/LockProcessorTest.php @@ -6,12 +6,10 @@ namespace Magento\Config\Test\Unit\Console\Command\ConfigSet; use Magento\Config\Console\Command\ConfigSet\LockProcessor; -use Magento\Config\Model\Config\Structure; -use Magento\Config\Model\Config\Structure\Element\Field; +use Magento\Config\Model\PreparedValueFactory; use Magento\Framework\App\Config\ConfigPathResolver; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\Config\Value; -use Magento\Framework\App\Config\ValueFactory; use Magento\Framework\App\DeploymentConfig; use Magento\Framework\Config\File\ConfigFilePool; use Magento\Framework\Exception\FileSystemException; @@ -33,9 +31,9 @@ class LockProcessorTest extends \PHPUnit_Framework_TestCase private $model; /** - * @var DeploymentConfig + * @var PreparedValueFactory|Mock */ - private $deploymentConfigMock; + private $preparedValueFactory; /** * @var DeploymentConfig\Writer|Mock @@ -52,32 +50,17 @@ class LockProcessorTest extends \PHPUnit_Framework_TestCase */ private $configPathResolver; - /** - * @var Structure|Mock - */ - private $structureMock; - /** * @var Value|Mock */ private $valueMock; - /** - * @var ValueFactory|Mock - */ - private $valueFactoryMock; - - /** - * @var Field|Mock - */ - private $fieldMock; - /** * @inheritdoc */ protected function setUp() { - $this->deploymentConfigMock = $this->getMockBuilder(DeploymentConfig::class) + $this->preparedValueFactory = $this->getMockBuilder(PreparedValueFactory::class) ->disableOriginalConstructor() ->getMock(); $this->deploymentConfigWriterMock = $this->getMockBuilder(DeploymentConfig\Writer::class) @@ -89,37 +72,16 @@ protected function setUp() $this->configPathResolver = $this->getMockBuilder(ConfigPathResolver::class) ->disableOriginalConstructor() ->getMock(); - $this->structureMock = $this->getMockBuilder(Structure::class) - ->disableOriginalConstructor() - ->getMock(); - $this->valueFactoryMock = $this->getMockBuilder(ValueFactory::class) - ->disableOriginalConstructor() - ->getMock(); - $this->fieldMock = $this->getMockBuilder(Field::class) - ->disableOriginalConstructor() - ->getMock(); $this->valueMock = $this->getMockBuilder(Value::class) ->setMethods(['validateBeforeSave', 'beforeSave', 'setValue', 'getValue', 'afterSave']) ->disableOriginalConstructor() ->getMock(); - $this->structureMock->expects($this->any()) - ->method('getElement') - ->willReturn($this->fieldMock); - $this->deploymentConfigMock->expects($this->any()) - ->method('isAvailable') - ->willReturn(true); - $this->valueFactoryMock->expects($this->any()) - ->method('create') - ->willReturn($this->valueMock); - $this->model = new LockProcessor( - $this->deploymentConfigMock, + $this->preparedValueFactory, $this->deploymentConfigWriterMock, $this->arrayManagerMock, - $this->configPathResolver, - $this->structureMock, - $this->valueFactoryMock + $this->configPathResolver ); } @@ -134,11 +96,9 @@ protected function setUp() */ public function testProcess($path, $value, $scope, $scopeCode) { - $this->fieldMock->expects($this->once()) - ->method('hasBackendModel') - ->willReturn(true); - $this->fieldMock->expects($this->once()) - ->method('getBackendModel') + $this->preparedValueFactory->expects($this->once()) + ->method('create') + ->with($path, $value, $scope, $scopeCode) ->willReturn($this->valueMock); $this->configPathResolver->expects($this->once()) ->method('resolve') @@ -200,58 +160,6 @@ public function processDataProvider() ]; } - public function testProcessBackendModelNotExists() - { - $path = 'test/test/test'; - $value = 'value'; - - $this->fieldMock->expects($this->once()) - ->method('hasBackendModel') - ->willReturn(false); - $this->fieldMock->expects($this->never()) - ->method('getBackendModel'); - $this->configPathResolver->expects($this->once()) - ->method('resolve') - ->willReturn('system/default/test/test/test'); - $this->arrayManagerMock->expects($this->once()) - ->method('set') - ->with('system/default/test/test/test', [], $value) - ->willReturn([ - 'system' => [ - 'default' => [ - 'test' => [ - 'test' => [ - 'test' => $value - ] - ] - ] - ] - ]); - $this->valueMock->expects($this->once()) - ->method('getValue') - ->willReturn($value); - $this->deploymentConfigWriterMock->expects($this->once()) - ->method('saveConfig') - ->with( - [ - ConfigFilePool::APP_ENV => [ - 'system' => [ - 'default' => [ - 'test' => [ - 'test' => [ - 'test' => $value - ] - ] - ] - ] - ] - ], - false - ); - - $this->model->process($path, $value, ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null); - } - /** * @expectedException \Magento\Framework\Exception\LocalizedException * @expectedExceptionMessage Filesystem is not writable. @@ -261,11 +169,8 @@ public function testProcessNotReadableFs() $path = 'test/test/test'; $value = 'value'; - $this->fieldMock->expects($this->once()) - ->method('hasBackendModel') - ->willReturn(true); - $this->fieldMock->expects($this->once()) - ->method('getBackendModel') + $this->preparedValueFactory->expects($this->once()) + ->method('create') ->willReturn($this->valueMock); $this->valueMock->expects($this->once()) ->method('getValue') @@ -293,15 +198,12 @@ public function testCustomException() $path = 'test/test/test'; $value = 'value'; - $this->fieldMock->expects($this->once()) - ->method('hasBackendModel') - ->willReturn(true); - $this->fieldMock->expects($this->once()) - ->method('getBackendModel') - ->willReturn($this->valueMock); $this->configPathResolver->expects($this->once()) ->method('resolve') ->willReturn('system/default/test/test/test'); + $this->preparedValueFactory->expects($this->once()) + ->method('create') + ->willReturn($this->valueMock); $this->arrayManagerMock->expects($this->never()) ->method('set'); $this->valueMock->expects($this->never()) diff --git a/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSetCommandTest.php b/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSetCommandTest.php index bd62068d672c3..c0cbb210e457a 100644 --- a/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSetCommandTest.php +++ b/app/code/Magento/Config/Test/Unit/Console/Command/ConfigSetCommandTest.php @@ -5,11 +5,12 @@ */ namespace Magento\Config\Test\Unit\Console\Command; -use Magento\Config\Console\Command\ConfigSet\ProcessorFacade; -use Magento\Config\Console\Command\ConfigSet\ProcessorFacadeFactory; +use Magento\Config\App\Config\Type\System; +use Magento\Config\Console\Command\ConfigSet\EmulatedProcessorFacade; use Magento\Config\Console\Command\ConfigSetCommand; -use Magento\Framework\App\State; -use Magento\Framework\Config\ScopeInterface; +use Magento\Deploy\Model\DeploymentConfig\ChangeDetector; +use Magento\Deploy\Model\DeploymentConfig\Hash; +use Magento\Deploy\Model\DeploymentConfig\Validator; use Magento\Framework\Console\Cli; use Magento\Framework\Exception\ValidatorException; use PHPUnit_Framework_MockObject_MockObject as Mock; @@ -28,60 +29,96 @@ class ConfigSetCommandTest extends \PHPUnit_Framework_TestCase private $command; /** - * @var ScopeInterface|Mock + * @var EmulatedProcessorFacade|Mock */ - private $scopeMock; + private $emulatedProcessorFacadeMock; /** - * @var State|Mock + * @var ChangeDetector|Mock */ - private $stateMock; + private $changeDetectorMock; /** - * @var ProcessorFacadeFactory|Mock + * @var Hash|Mock */ - private $processorFacadeFactoryMock; - - /** - * @var ProcessorFacade|Mock - */ - private $processorFacadeMock; + private $hashMock; /** * @inheritdoc */ protected function setUp() { - $this->scopeMock = $this->getMockBuilder(ScopeInterface::class) - ->getMockForAbstractClass(); - $this->stateMock = $this->getMockBuilder(State::class) + $this->emulatedProcessorFacadeMock = $this->getMockBuilder(EmulatedProcessorFacade::class) ->disableOriginalConstructor() ->getMock(); - $this->processorFacadeFactoryMock = $this->getMockBuilder(ProcessorFacadeFactory::class) + $this->changeDetectorMock = $this->getMockBuilder(ChangeDetector::class) ->disableOriginalConstructor() ->getMock(); - $this->processorFacadeMock = $this->getMockBuilder(ProcessorFacade::class) + $this->hashMock = $this->getMockBuilder(Hash::class) ->disableOriginalConstructor() ->getMock(); - $this->processorFacadeFactoryMock->expects($this->any()) - ->method('create') - ->willReturn($this->processorFacadeMock); - $this->command = new ConfigSetCommand( - $this->scopeMock, - $this->stateMock, - $this->processorFacadeFactoryMock + $this->emulatedProcessorFacadeMock, + $this->changeDetectorMock, + $this->hashMock ); } + public function testExecute() + { + $this->changeDetectorMock->expects($this->once()) + ->method('hasChanges') + ->willReturn(false); + $this->emulatedProcessorFacadeMock->expects($this->once()) + ->method('process') + ->willReturn('Some message'); + $this->hashMock->expects($this->once()) + ->method('regenerate') + ->with(System::CONFIG_TYPE); + + $tester = new CommandTester($this->command); + $tester->execute([ + ConfigSetCommand::ARG_PATH => 'test/test/test', + ConfigSetCommand::ARG_VALUE => 'value' + ]); + + $this->assertContains( + __('Some message')->render(), + $tester->getDisplay() + ); + $this->assertSame(Cli::RETURN_SUCCESS, $tester->getStatusCode()); + } + + public function testExecuteNeedsRegeneration() + { + $this->changeDetectorMock->expects($this->once()) + ->method('hasChanges') + ->willReturn(true); + $this->emulatedProcessorFacadeMock->expects($this->never()) + ->method('process'); + + $tester = new CommandTester($this->command); + $tester->execute([ + ConfigSetCommand::ARG_PATH => 'test/test/test', + ConfigSetCommand::ARG_VALUE => 'value' + ]); + + $this->assertContains( + __('This command is unavailable right now.')->render(), + $tester->getDisplay() + ); + $this->assertSame(Cli::RETURN_FAILURE, $tester->getStatusCode()); + } + public function testExecuteWithException() { - $this->stateMock->expects($this->once()) - ->method('emulateAreaCode') + $this->changeDetectorMock->expects($this->once()) + ->method('hasChanges') + ->willReturn(false); + $this->emulatedProcessorFacadeMock->expects($this->once()) + ->method('process') ->willThrowException(new ValidatorException(__('The "test/test/test" path does not exists'))); - $this->processorFacadeFactoryMock->expects($this->never()) - ->method('create'); $tester = new CommandTester($this->command); $tester->execute([ diff --git a/app/code/Magento/Config/Test/Unit/Model/Config/ImporterTest.php b/app/code/Magento/Config/Test/Unit/Model/Config/ImporterTest.php index 01fed0f916fb5..9ece6ba21226a 100644 --- a/app/code/Magento/Config/Test/Unit/Model/Config/ImporterTest.php +++ b/app/code/Magento/Config/Test/Unit/Model/Config/ImporterTest.php @@ -204,9 +204,6 @@ public function testInvokeSaveAll() 'websites' => ['base' => ['web' => ['unsecure' => ['base_url' => 'http://magento2.local/']]]], ]; - $this->valueMock->expects($this->exactly(2)) - ->method('setData') - ->with('force_changed_value', true); $this->valueMock->expects($this->exactly(2)) ->method('beforeSave'); $this->valueMock->expects($this->exactly(2)) diff --git a/app/code/Magento/Config/Test/Unit/Model/PreparedValueFactoryTest.php b/app/code/Magento/Config/Test/Unit/Model/PreparedValueFactoryTest.php index 2b3b870396da5..743ec0d991b32 100644 --- a/app/code/Magento/Config/Test/Unit/Model/PreparedValueFactoryTest.php +++ b/app/code/Magento/Config/Test/Unit/Model/PreparedValueFactoryTest.php @@ -5,8 +5,9 @@ */ namespace Magento\Config\Test\Unit\Model; +use Magento\Config\Model\Config\BackendFactory; use Magento\Config\Model\PreparedValueFactory; -use Magento\Framework\App\Config\ValueFactory; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Config\Model\Config\StructureFactory; use Magento\Framework\App\Config\Value; use Magento\Config\Model\Config\Structure; @@ -27,7 +28,7 @@ class PreparedValueFactoryTest extends \PHPUnit_Framework_TestCase private $structureFactoryMock; /** - * @var ValueFactory|Mock + * @var BackendFactory|Mock */ private $valueFactoryMock; @@ -46,6 +47,11 @@ class PreparedValueFactoryTest extends \PHPUnit_Framework_TestCase */ private $fieldMock; + /** + * @var ScopeConfigInterface|Mock + */ + private $configMock; + /** * @var ScopeResolverPool|Mock */ @@ -75,7 +81,7 @@ protected function setUp() ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); - $this->valueFactoryMock = $this->getMockBuilder(ValueFactory::class) + $this->valueFactoryMock = $this->getMockBuilder(BackendFactory::class) ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); @@ -89,6 +95,8 @@ protected function setUp() ->disableOriginalConstructor() ->setMethods(['setPath', 'setScope', 'setScopeId', 'setValue']) ->getMock(); + $this->configMock = $this->getMockBuilder(ScopeConfigInterface::class) + ->getMockForAbstractClass(); $this->scopeResolverPoolMock = $this->getMockBuilder(ScopeResolverPool::class) ->disableOriginalConstructor() ->getMock(); @@ -101,7 +109,8 @@ protected function setUp() $this->preparedValueFactory = new PreparedValueFactory( $this->scopeResolverPoolMock, $this->structureFactoryMock, - $this->valueFactoryMock + $this->valueFactoryMock, + $this->configMock ); } @@ -143,10 +152,7 @@ public function testCreate( $this->fieldMock->expects($this->once()) ->method('hasBackendModel') ->willReturn(true); - $this->fieldMock->expects($this->once()) - ->method('getBackendModel') - ->willReturn($this->valueMock); - $this->valueFactoryMock->expects($this->never()) + $this->valueFactoryMock->expects($this->once()) ->method('create') ->willReturn($this->valueMock); $this->valueMock->expects($this->once()) diff --git a/app/code/Magento/Config/composer.json b/app/code/Magento/Config/composer.json index 735618945ba35..c140b5cc187ac 100644 --- a/app/code/Magento/Config/composer.json +++ b/app/code/Magento/Config/composer.json @@ -9,9 +9,7 @@ "magento/module-email": "100.2.*", "magento/module-directory": "100.2.*", "magento/module-backend": "100.2.*", - "magento/module-media-storage": "100.2.*" - }, - "suggest": { + "magento/module-media-storage": "100.2.*", "magento/module-deploy": "100.2.*" }, "type": "magento2-module", diff --git a/app/code/Magento/Config/etc/di.xml b/app/code/Magento/Config/etc/di.xml index 728bb1334ebff..1abc5e35f578f 100644 --- a/app/code/Magento/Config/etc/di.xml +++ b/app/code/Magento/Config/etc/di.xml @@ -86,6 +86,29 @@ Magento\Framework\Serialize\Serializer\Serialize + + + systemConfigSnapshotSourceAggregated + system_snapshot + + + + + + systemSnapshot + + + + + + configSnapshot + + + + + snapshotValueFactory + + modulesDataProvider @@ -141,6 +164,16 @@ + + + + + Magento\Config\App\Config\Source\InitialSnapshotConfigSource + 1000 + + + + Magento\Framework\App\DeploymentConfig\Reader diff --git a/app/code/Magento/Deploy/Console/Command/App/SensitiveConfigSet/SensitiveConfigSetFacade.php b/app/code/Magento/Deploy/Console/Command/App/SensitiveConfigSet/SensitiveConfigSetFacade.php new file mode 100644 index 0000000000000..319b358c4ccc6 --- /dev/null +++ b/app/code/Magento/Deploy/Console/Command/App/SensitiveConfigSet/SensitiveConfigSetFacade.php @@ -0,0 +1,136 @@ +commentParser = $commentParser; + $this->configFilePool = $configFilePool; + $this->configWriter = $configWriter; + $this->scopeValidator = $scopeValidator; + $this->collectorFactory = $collectorFactory; + } + + /** + * Processes the sensitive:config:set command. + * + * @param InputInterface $input The input manager + * @param OutputInterface $output The output manager + * @return void + * @throws RuntimeException If data can not be processed + */ + public function process(InputInterface $input, OutputInterface $output) + { + $scope = $input->getOption(SensitiveConfigSetCommand::INPUT_OPTION_SCOPE); + $scopeCode = $input->getOption(SensitiveConfigSetCommand::INPUT_OPTION_SCOPE_CODE); + $isInteractive = $input->getOption(SensitiveConfigSetCommand::INPUT_OPTION_INTERACTIVE); + + $this->scopeValidator->isValid($scope, $scopeCode); + $configPaths = $this->getConfigPaths(); + $collector = $this->collectorFactory->create( + $isInteractive ? CollectorFactory::TYPE_INTERACTIVE : CollectorFactory::TYPE_SIMPLE + ); + $values = $collector->getValues($input, $output, $configPaths); + + $this->configWriter->save($values, $scope, $scopeCode); + + $output->writeln(sprintf( + 'Configuration value%s saved in app/etc/%s', + $isInteractive ? 's' : '', + $this->configFilePool->getPath(ConfigFilePool::APP_ENV) + )); + } + + /** + * Get sensitive configuration paths. + * + * @return array + * @throws LocalizedException if configuration file not exists or sensitive configuration is empty + */ + private function getConfigPaths() + { + $configFilePath = $this->configFilePool->getPath(ConfigFilePool::APP_CONFIG); + try { + $configPaths = $this->commentParser->execute($configFilePath); + } catch (FileSystemException $e) { + throw new RuntimeException(__( + 'File app/etc/%1 can\'t be read. Please check if it exists and has read permissions.', + [ + $configFilePath + ] + )); + } + + if (empty($configPaths)) { + throw new RuntimeException(__('There are no sensitive configurations to fill')); + } + + return $configPaths; + } +} diff --git a/app/code/Magento/Deploy/Console/Command/App/SensitiveConfigSetCommand.php b/app/code/Magento/Deploy/Console/Command/App/SensitiveConfigSetCommand.php index 9b30fa95ddac8..30b2117b48864 100644 --- a/app/code/Magento/Deploy/Console/Command/App/SensitiveConfigSetCommand.php +++ b/app/code/Magento/Deploy/Console/Command/App/SensitiveConfigSetCommand.php @@ -5,15 +5,13 @@ */ namespace Magento\Deploy\Console\Command\App; -use Magento\Deploy\Console\Command\App\SensitiveConfigSet\CollectorFactory; -use Magento\Deploy\Model\ConfigWriter; -use Magento\Framework\App\Config\CommentParserInterface; +use Magento\Config\App\Config\Type\System; +use Magento\Deploy\Console\Command\App\SensitiveConfigSet\SensitiveConfigSetFacade; +use Magento\Deploy\Model\DeploymentConfig\ChangeDetector; +use Magento\Deploy\Model\DeploymentConfig\Hash; +use Magento\Deploy\Model\DeploymentConfig\Validator; use Magento\Framework\App\Config\ScopeConfigInterface; -use Magento\Framework\App\Scope\ValidatorInterface; -use Magento\Framework\Config\File\ConfigFilePool; use Magento\Framework\Console\Cli; -use Magento\Framework\Exception\FileSystemException; -use Magento\Framework\Exception\LocalizedException; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -22,8 +20,6 @@ /** * Command for set sensitive variable through deploy process - * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class SensitiveConfigSetCommand extends Command { @@ -53,52 +49,41 @@ class SensitiveConfigSetCommand extends Command const INPUT_ARGUMENT_VALUE = 'value'; /** - * @var CommentParserInterface - */ - private $commentParser; - - /** - * @var ConfigFilePool - */ - private $configFilePool; - - /** - * @var ConfigWriter + * The config change detector. + * + * @var ChangeDetector */ - private $configWriter; + private $changeDetector; /** - * @var ValidatorInterface + * The hash manager. + * + * @var Hash */ - private $scopeValidator; + private $hash; /** - * @var CollectorFactory + * The facade for command. + * + * @var SensitiveConfigSetFacade */ - private $collectorFactory; + private $facade; /** - * SensitiveConfigSetCommand constructor - * - * @param ConfigFilePool $configFilePool - * @param CommentParserInterface $commentParser - * @param ConfigWriter $configWriter - * @param ValidatorInterface $scopeValidator - * @param CollectorFactory $collectorFactory + * @param SensitiveConfigSetFacade $facade The processor facade + * @param ChangeDetector $changeDetector The config change detector + * @param Hash $hash The hash manager */ public function __construct( - ConfigFilePool $configFilePool, - CommentParserInterface $commentParser, - ConfigWriter $configWriter, - ValidatorInterface $scopeValidator, - CollectorFactory $collectorFactory + SensitiveConfigSetFacade $facade, + ChangeDetector $changeDetector, + Hash $hash ) { + $this->facade = $facade; + $this->changeDetector = $changeDetector; + $this->hash = $hash; + parent::__construct(); - $this->commentParser = $commentParser; - $this->configFilePool = $configFilePool; - $this->configWriter = $configWriter; - $this->scopeValidator = $scopeValidator; - $this->collectorFactory = $collectorFactory; } /** @@ -146,68 +131,28 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $scope = $input->getOption(self::INPUT_OPTION_SCOPE); - $scopeCode = $input->getOption(self::INPUT_OPTION_SCOPE_CODE); - - try { - $this->scopeValidator->isValid($scope, $scopeCode); - $configPaths = $this->getConfigPaths(); - $isInteractive = $input->getOption(self::INPUT_OPTION_INTERACTIVE); - $collector = $this->collectorFactory->create( - $isInteractive ? CollectorFactory::TYPE_INTERACTIVE : CollectorFactory::TYPE_SIMPLE + if ($this->changeDetector->hasChanges(System::CONFIG_TYPE)) { + $output->writeln( + '' + . 'This command is unavailable right now. ' + . 'To continue working with it please run app:config:import or setup:upgrade command before.' + . '' ); - $values = $collector->getValues($input, $output, $configPaths); - $this->configWriter->save($values, $scope, $scopeCode); - } catch (LocalizedException $e) { - $output->writeln(sprintf('%s', $e->getMessage())); + return Cli::RETURN_FAILURE; } - $this->writeSuccessMessage($output, $isInteractive); - - return Cli::RETURN_SUCCESS; - } - - /** - * Writes success message - * - * @param OutputInterface $output - * @param boolean $isInteractive - * @return void - */ - private function writeSuccessMessage(OutputInterface $output, $isInteractive) - { - $output->writeln(sprintf( - 'Configuration value%s saved in app/etc/%s', - $isInteractive ? 's' : '', - $this->configFilePool->getPath(ConfigFilePool::APP_ENV) - )); - } - - /** - * Get sensitive configuration paths - * - * @return array - * @throws LocalizedException if configuration file not exists or sensitive configuration is empty - */ - private function getConfigPaths() - { - $configFilePath = $this->configFilePool->getPath(ConfigFilePool::APP_CONFIG); try { - $configPaths = $this->commentParser->execute($configFilePath); - } catch (FileSystemException $e) { - throw new LocalizedException(__( - 'File app/etc/%1 can\'t be read. Please check if it exists and has read permissions.', - [ - $configFilePath - ] - )); - } + $this->facade->process($input, $output); + $this->hash->regenerate(System::CONFIG_TYPE); - if (empty($configPaths)) { - throw new LocalizedException(__('There are no sensitive configurations to fill')); - } + return Cli::RETURN_SUCCESS; + } catch (\Exception $e) { + $output->writeln( + sprintf('%s', $e->getMessage()) + ); - return $configPaths; + return Cli::RETURN_FAILURE; + } } } diff --git a/app/code/Magento/Deploy/Test/Unit/Console/Command/App/SensitiveConfigSet/SensitiveConfigSetFacadeTest.php b/app/code/Magento/Deploy/Test/Unit/Console/Command/App/SensitiveConfigSet/SensitiveConfigSetFacadeTest.php new file mode 100644 index 0000000000000..d4c5d96689a8b --- /dev/null +++ b/app/code/Magento/Deploy/Test/Unit/Console/Command/App/SensitiveConfigSet/SensitiveConfigSetFacadeTest.php @@ -0,0 +1,276 @@ +configFilePoolMock = $this->getMockBuilder(ConfigFilePool::class) + ->disableOriginalConstructor() + ->getMock(); + $this->commentParserMock = $this->getMockBuilder(CommentParserInterface::class) + ->getMockForAbstractClass(); + $this->configWriterMock = $this->getMockBuilder(ConfigWriter::class) + ->disableOriginalConstructor() + ->getMock(); + $this->scopeValidatorMock = $this->getMockBuilder(ValidatorInterface::class) + ->getMockForAbstractClass(); + $this->collectorFactoryMock = $this->getMockBuilder(CollectorFactory::class) + ->disableOriginalConstructor() + ->getMock(); + $this->inputMock = $this->getMockBuilder(InputInterface::class) + ->getMockForAbstractClass(); + $this->outputMock = $this->getMockBuilder(OutputInterface::class) + ->getMockForAbstractClass(); + + $this->command = new SensitiveConfigSetFacade( + $this->configFilePoolMock, + $this->commentParserMock, + $this->configWriterMock, + $this->scopeValidatorMock, + $this->collectorFactoryMock + ); + } + + /** + * @expectedExceptionMessage File app/etc/config.php can't be read. + * @expectedException \Magento\Framework\Exception\RuntimeException + */ + public function testConfigFileNotExist() + { + $this->inputMock->expects($this->any()) + ->method('getOption') + ->with() + ->willReturnMap([ + [SensitiveConfigSetCommand::INPUT_OPTION_SCOPE, 'default'], + ]); + $this->configFilePoolMock->expects($this->once()) + ->method('getPath') + ->with(ConfigFilePool::APP_CONFIG) + ->willReturn('config.php'); + $this->scopeValidatorMock->expects($this->once()) + ->method('isValid') + ->with('default', '') + ->willReturn(true); + $this->commentParserMock->expects($this->any()) + ->method('execute') + ->willThrowException(new FileSystemException(new Phrase('some message'))); + + $this->command->process( + $this->inputMock, + $this->outputMock + ); + } + + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Some exception + */ + public function testWriterException() + { + $exceptionMessage = 'Some exception'; + $this->inputMock->expects($this->any()) + ->method('getOption') + ->with() + ->willReturnMap([ + [SensitiveConfigSetCommand::INPUT_OPTION_SCOPE, 'default'], + ]); + $this->scopeValidatorMock->expects($this->once()) + ->method('isValid') + ->with('default', '') + ->willReturn(true); + $this->commentParserMock->expects($this->once()) + ->method('execute') + ->willReturn([ + 'some/config/path1', + 'some/config/path2' + ]); + $collectorMock = $this->getMockBuilder(CollectorInterface::class) + ->getMockForAbstractClass(); + $collectorMock->expects($this->once()) + ->method('getValues') + ->willReturn(['some/config/pathNotExist' => 'value']); + $this->collectorFactoryMock->expects($this->once()) + ->method('create') + ->with(CollectorFactory::TYPE_SIMPLE) + ->willReturn($collectorMock); + $this->configWriterMock->expects($this->once()) + ->method('save') + ->willThrowException(new LocalizedException(__($exceptionMessage))); + + $this->command->process( + $this->inputMock, + $this->outputMock + ); + } + + /** + * @expectedException \Magento\Framework\Exception\RuntimeException + * @expectedExceptionMessage There are no sensitive configurations to fill + */ + public function testEmptyConfigPaths() + { + $this->inputMock->expects($this->any()) + ->method('getOption') + ->with() + ->willReturnMap([ + [SensitiveConfigSetCommand::INPUT_OPTION_SCOPE, 'default'], + ]); + $this->scopeValidatorMock->expects($this->once()) + ->method('isValid') + ->with('default', '') + ->willReturn(true); + $this->commentParserMock->expects($this->once()) + ->method('execute') + ->willReturn([]); + + $this->command->process( + $this->inputMock, + $this->outputMock + ); + } + + public function testExecute() + { + $collectedValues = ['some/config/path1' => 'value']; + $this->inputMock->expects($this->any()) + ->method('getOption') + ->with() + ->willReturnMap([ + [SensitiveConfigSetCommand::INPUT_OPTION_SCOPE, 'default'], + ]); + $this->scopeValidatorMock->expects($this->once()) + ->method('isValid') + ->with('default', '') + ->willReturn(true); + $this->commentParserMock->expects($this->once()) + ->method('execute') + ->willReturn([ + 'some/config/path1', + 'some/config/path2' + ]); + $collectorMock = $this->getMockBuilder(CollectorInterface::class) + ->getMockForAbstractClass(); + $collectorMock->expects($this->once()) + ->method('getValues') + ->willReturn($collectedValues); + $this->collectorFactoryMock->expects($this->once()) + ->method('create') + ->with(CollectorFactory::TYPE_SIMPLE) + ->willReturn($collectorMock); + $this->configWriterMock->expects($this->once()) + ->method('save') + ->with($collectedValues, ScopeConfigInterface::SCOPE_TYPE_DEFAULT, ''); + + $this->command->process( + $this->inputMock, + $this->outputMock + ); + } + + public function testExecuteInteractive() + { + $collectedValues = ['some/config/path1' => 'value']; + $this->inputMock->expects($this->any()) + ->method('getOption') + ->with() + ->willReturnMap([ + [SensitiveConfigSetCommand::INPUT_OPTION_SCOPE, 'default'], + [SensitiveConfigSetCommand::INPUT_OPTION_INTERACTIVE, true], + ]); + $this->scopeValidatorMock->expects($this->once()) + ->method('isValid') + ->with('default', '') + ->willReturn(true); + $this->commentParserMock->expects($this->once()) + ->method('execute') + ->willReturn([ + 'some/config/path1', + 'some/config/path2', + 'some/config/path3' + ]); + $collectorMock = $this->getMockBuilder(CollectorInterface::class) + ->getMockForAbstractClass(); + $collectorMock->expects($this->once()) + ->method('getValues') + ->willReturn($collectedValues); + $this->collectorFactoryMock->expects($this->once()) + ->method('create') + ->with(CollectorFactory::TYPE_INTERACTIVE) + ->willReturn($collectorMock); + $this->configWriterMock->expects($this->once()) + ->method('save') + ->with($collectedValues, ScopeConfigInterface::SCOPE_TYPE_DEFAULT, ''); + + $this->command->process( + $this->inputMock, + $this->outputMock + ); + } +} diff --git a/app/code/Magento/Deploy/Test/Unit/Console/Command/App/SensitiveConfigSetCommandTest.php b/app/code/Magento/Deploy/Test/Unit/Console/Command/App/SensitiveConfigSetCommandTest.php index 779cb5f0fd500..a227d130ef38a 100644 --- a/app/code/Magento/Deploy/Test/Unit/Console/Command/App/SensitiveConfigSetCommandTest.php +++ b/app/code/Magento/Deploy/Test/Unit/Console/Command/App/SensitiveConfigSetCommandTest.php @@ -5,18 +5,13 @@ */ namespace Magento\Deploy\Test\Unit\Console\Command\App; -use Magento\Deploy\Console\Command\App\SensitiveConfigSet\CollectorFactory; -use Magento\Deploy\Console\Command\App\SensitiveConfigSet\CollectorInterface; +use Magento\Config\App\Config\Type\System; +use Magento\Deploy\Console\Command\App\SensitiveConfigSet\SensitiveConfigSetFacade; use Magento\Deploy\Console\Command\App\SensitiveConfigSetCommand; -use Magento\Deploy\Model\ConfigWriter; -use Magento\Framework\App\Config\CommentParserInterface; -use Magento\Framework\App\Config\ScopeConfigInterface; -use Magento\Framework\App\Scope\ValidatorInterface; -use Magento\Framework\Config\File\ConfigFilePool; +use Magento\Deploy\Model\DeploymentConfig\ChangeDetector; +use Magento\Deploy\Model\DeploymentConfig\Hash; +use Magento\Deploy\Model\DeploymentConfig\Validator; use Magento\Framework\Console\Cli; -use Magento\Framework\Exception\FileSystemException; -use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\Phrase; use PHPUnit_Framework_MockObject_MockObject as MockObject; use Symfony\Component\Console\Tester\CommandTester; @@ -26,237 +21,108 @@ class SensitiveConfigSetCommandTest extends \PHPUnit_Framework_TestCase { /** - * @var ConfigFilePool|MockObject + * @var SensitiveConfigSetFacade|MockObject */ - private $configFilePoolMock; + private $facadeMock; /** - * @var CommentParserInterface|MockObject + * @var ChangeDetector|MockObject */ - private $commentParserMock; + private $changeDetectorMock; /** - * @var ConfigWriter|MockObject + * @var Hash|MockObject */ - private $configWriterMock; - - /** - * @var ValidatorInterface|MockObject - */ - private $scopeValidatorMock; - - /** - * @var CollectorFactory|MockObject - */ - private $collectorFactoryMock; + private $hashMock; /** * @var SensitiveConfigSetCommand */ - private $command; + private $model; /** * @inheritdoc */ public function setUp() { - $this->configFilePoolMock = $this->getMockBuilder(ConfigFilePool::class) + $this->facadeMock = $this->getMockBuilder(SensitiveConfigSetFacade::class) ->disableOriginalConstructor() ->getMock(); - $this->commentParserMock = $this->getMockBuilder(CommentParserInterface::class) - ->getMockForAbstractClass(); - $this->configWriterMock = $this->getMockBuilder(ConfigWriter::class) + $this->changeDetectorMock = $this->getMockBuilder(ChangeDetector::class) ->disableOriginalConstructor() ->getMock(); - $this->scopeValidatorMock = $this->getMockBuilder(ValidatorInterface::class) - ->getMockForAbstractClass(); - $this->collectorFactoryMock = $this->getMockBuilder(CollectorFactory::class) + $this->hashMock = $this->getMockBuilder(Hash::class) ->disableOriginalConstructor() ->getMock(); - $this->command = new SensitiveConfigSetCommand( - $this->configFilePoolMock, - $this->commentParserMock, - $this->configWriterMock, - $this->scopeValidatorMock, - $this->collectorFactoryMock - ); - } - - public function testConfigFileNotExist() - { - $this->configFilePoolMock->expects($this->once()) - ->method('getPath') - ->with(ConfigFilePool::APP_CONFIG) - ->willReturn('config.php'); - $this->scopeValidatorMock->expects($this->once()) - ->method('isValid') - ->with('default', '') - ->willReturn(true); - $this->commentParserMock->expects($this->any()) - ->method('execute') - ->willThrowException(new FileSystemException(new Phrase('some message'))); - - $tester = new CommandTester($this->command); - $tester->execute([ - 'path' => 'some/path', - 'value' => 'some value' - ]); - - $this->assertEquals( - Cli::RETURN_FAILURE, - $tester->getStatusCode() - ); - $this->assertContains( - 'File app/etc/config.php can\'t be read. ' - . 'Please check if it exists and has read permissions.', - $tester->getDisplay() + $this->model = new SensitiveConfigSetCommand( + $this->facadeMock, + $this->changeDetectorMock, + $this->hashMock ); } - public function testWriterException() + public function testExecute() { - $exceptionMessage = 'exception'; - $this->scopeValidatorMock->expects($this->once()) - ->method('isValid') - ->with('default', '') - ->willReturn(true); - $this->commentParserMock->expects($this->once()) - ->method('execute') - ->willReturn([ - 'some/config/path1', - 'some/config/path2' - ]); - $collectorMock = $this->getMockBuilder(CollectorInterface::class) - ->getMockForAbstractClass(); - $collectorMock->expects($this->once()) - ->method('getValues') - ->willReturn(['some/config/pathNotExist' => 'value']); - $this->collectorFactoryMock->expects($this->once()) - ->method('create') - ->with(CollectorFactory::TYPE_SIMPLE) - ->willReturn($collectorMock); - $this->configWriterMock->expects($this->once()) - ->method('save') - ->willThrowException(new LocalizedException(__($exceptionMessage))); - - $tester = new CommandTester($this->command); - $tester->execute([ - 'path' => 'some/config/pathNotExist', - 'value' => 'some value' - ]); + $this->changeDetectorMock->expects($this->once()) + ->method('hasChanges') + ->willReturn(false); + $this->facadeMock->expects($this->once()) + ->method('process'); + $this->hashMock->expects($this->once()) + ->method('regenerate') + ->with(System::CONFIG_TYPE); + + $tester = new CommandTester($this->model); + $tester->execute([]); $this->assertEquals( - Cli::RETURN_FAILURE, + Cli::RETURN_SUCCESS, $tester->getStatusCode() ); - $this->assertContains( - $exceptionMessage, - $tester->getDisplay() - ); } - public function testEmptyConfigPaths() + public function testExecuteNeedsRegeneration() { - $this->scopeValidatorMock->expects($this->once()) - ->method('isValid') - ->with('default', '') + $this->changeDetectorMock->expects($this->once()) + ->method('hasChanges') ->willReturn(true); - $this->commentParserMock->expects($this->once()) - ->method('execute') - ->willReturn([]); + $this->facadeMock->expects($this->never()) + ->method('process'); + $this->hashMock->expects($this->never()) + ->method('regenerate'); - $tester = new CommandTester($this->command); - $tester->execute([ - 'path' => 'some/config/pathNotExist', - 'value' => 'some value' - ]); + $tester = new CommandTester($this->model); + $tester->execute([]); $this->assertEquals( Cli::RETURN_FAILURE, $tester->getStatusCode() ); $this->assertContains( - 'There are no sensitive configurations to fill', + 'This command is unavailable right now.', $tester->getDisplay() ); } - public function testExecute() + public function testExecuteWithException() { - $collectedValues = ['some/config/path1' => 'value']; - $this->scopeValidatorMock->expects($this->once()) - ->method('isValid') - ->with('default', '') - ->willReturn(true); - $this->commentParserMock->expects($this->once()) - ->method('execute') - ->willReturn([ - 'some/config/path1', - 'some/config/path2' - ]); - $collectorMock = $this->getMockBuilder(CollectorInterface::class) - ->getMockForAbstractClass(); - $collectorMock->expects($this->once()) - ->method('getValues') - ->willReturn($collectedValues); - $this->collectorFactoryMock->expects($this->once()) - ->method('create') - ->with(CollectorFactory::TYPE_SIMPLE) - ->willReturn($collectorMock); - $this->configWriterMock->expects($this->once()) - ->method('save') - ->with($collectedValues, ScopeConfigInterface::SCOPE_TYPE_DEFAULT, ''); - - $tester = new CommandTester($this->command); + $this->changeDetectorMock->expects($this->once()) + ->method('hasChanges') + ->willReturn(false); + $this->facadeMock->expects($this->once()) + ->method('process') + ->willThrowException(new \Exception('Some exception')); + + $tester = new CommandTester($this->model); $tester->execute([]); $this->assertEquals( - Cli::RETURN_SUCCESS, - $tester->getStatusCode() - ); - $this->assertContains( - 'Configuration value saved in', - $tester->getDisplay() - ); - } - - public function testExecuteInteractive() - { - $collectedValues = ['some/config/path1' => 'value']; - $this->scopeValidatorMock->expects($this->once()) - ->method('isValid') - ->with('default', '') - ->willReturn(true); - $this->commentParserMock->expects($this->once()) - ->method('execute') - ->willReturn([ - 'some/config/path1', - 'some/config/path2', - 'some/config/path3' - ]); - $collectorMock = $this->getMockBuilder(CollectorInterface::class) - ->getMockForAbstractClass(); - $collectorMock->expects($this->once()) - ->method('getValues') - ->willReturn($collectedValues); - $this->collectorFactoryMock->expects($this->once()) - ->method('create') - ->with(CollectorFactory::TYPE_INTERACTIVE) - ->willReturn($collectorMock); - $this->configWriterMock->expects($this->once()) - ->method('save') - ->with($collectedValues, ScopeConfigInterface::SCOPE_TYPE_DEFAULT, ''); - - $tester = new CommandTester($this->command); - $tester->execute(['--interactive' => true]); - - $this->assertEquals( - Cli::RETURN_SUCCESS, + Cli::RETURN_FAILURE, $tester->getStatusCode() ); $this->assertContains( - 'Configuration values saved in', + 'Some exception', $tester->getDisplay() ); } diff --git a/dev/tests/integration/testsuite/Magento/Deploy/Console/Command/App/SensitiveConfigSetCommandTest.php b/dev/tests/integration/testsuite/Magento/Deploy/Console/Command/App/SensitiveConfigSetCommandTest.php index abd35fd478c0d..40212c5e11563 100644 --- a/dev/tests/integration/testsuite/Magento/Deploy/Console/Command/App/SensitiveConfigSetCommandTest.php +++ b/dev/tests/integration/testsuite/Magento/Deploy/Console/Command/App/SensitiveConfigSetCommandTest.php @@ -7,6 +7,7 @@ use Magento\Deploy\Console\Command\App\SensitiveConfigSet\CollectorFactory; use Magento\Deploy\Console\Command\App\SensitiveConfigSet\InteractiveCollector; +use Magento\Deploy\Console\Command\App\SensitiveConfigSet\SensitiveConfigSetFacade; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\DeploymentConfig\FileReader; use Magento\Framework\App\DeploymentConfig\Writer; @@ -210,7 +211,12 @@ public function testExecuteInteractive($scope, $scopeCode, callable $assertCallb $command = $this->objectManager->create( SensitiveConfigSetCommand::class, [ - 'collectorFactory' => $collectorFactoryMock + 'facade' => $this->objectManager->create( + SensitiveConfigSetFacade::class, + [ + 'collectorFactory' => $collectorFactoryMock + ] + ) ] ); $command->run($inputMock, $outputMock); diff --git a/dev/tests/integration/testsuite/Magento/Deploy/_files/config.php b/dev/tests/integration/testsuite/Magento/Deploy/_files/config.php index 03476ae2e2c3a..8aa7d8fd617af 100644 --- a/dev/tests/integration/testsuite/Magento/Deploy/_files/config.php +++ b/dev/tests/integration/testsuite/Magento/Deploy/_files/config.php @@ -15,12 +15,7 @@ * CONFIG__DEFAULT__SOME__CONFIG__PATH_TWO for some/config/path_two * CONFIG__DEFAULT__SOME__CONFIG__PATH_THREE for some/config/path_three */ - 'system' => [ - 'default' => [ - 'web' => [], - 'general' => [] - ] - ], + 'system' => [], 'integrationTestImporter' => [ 'someGroup' => [ 'someField' => 'testValue', diff --git a/lib/internal/Magento/Framework/App/Config/Value.php b/lib/internal/Magento/Framework/App/Config/Value.php index 7e2ed867e91e6..2f83205fc1cf0 100644 --- a/lib/internal/Magento/Framework/App/Config/Value.php +++ b/lib/internal/Magento/Framework/App/Config/Value.php @@ -78,10 +78,6 @@ public function __construct( */ public function isValueChanged() { - if ($this->getData('force_changed_value')) { - return true; - } - return $this->getValue() != $this->getOldValue(); } diff --git a/app/code/Magento/Analytics/Model/FlagManager.php b/lib/internal/Magento/Framework/FlagManager.php similarity index 50% rename from app/code/Magento/Analytics/Model/FlagManager.php rename to lib/internal/Magento/Framework/FlagManager.php index 13390c3921b0c..05c2c1156a1d2 100644 --- a/app/code/Magento/Analytics/Model/FlagManager.php +++ b/lib/internal/Magento/Framework/FlagManager.php @@ -3,11 +3,9 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Analytics\Model; +namespace Magento\Framework; -use Magento\Framework\FlagFactory; use Magento\Framework\Flag\FlagResource; -use Magento\Framework\Flag; /** * Service that allows to handle a flag object as a scalar value. @@ -15,19 +13,24 @@ class FlagManager { /** + * The factory of flags. + * * @var FlagFactory + * @see Flag */ private $flagFactory; /** + * The flag resource. + * * @var FlagResource */ private $flagResource; /** - * FlagManager constructor. - * @param FlagFactory $flagFactory - * @param FlagResource $flagResource + * + * @param FlagFactory $flagFactory The factory of flags + * @param FlagResource $flagResource The flag resource */ public function __construct( FlagFactory $flagFactory, @@ -38,56 +41,65 @@ public function __construct( } /** - * Return raw data from flag - * @param string $flagCode + * Retrieves raw data from the flag. + * + * @param string $code The code of flag * @return mixed */ - public function getFlagData($flagCode) + public function getFlagData($code) { - return $this->getFlagObject($flagCode)->getFlagData(); + return $this->getFlagObject($code)->getFlagData(); } /** - * Save flag by code - * @param string $flagCode - * @param mixed $value + * Saves the flag value by code. + * + * @param string $code The code of flag + * @param mixed $value The value of flag * @return bool */ - public function saveFlag($flagCode, $value) + public function saveFlag($code, $value) { - $flag = $this->getFlagObject($flagCode); + $flag = $this->getFlagObject($code); $flag->setFlagData($value); $this->flagResource->save($flag); + return true; } /** - * Delete flag by code + * Deletes the flag by code. * - * @param string $flagCode + * @param string $code The code of flag * @return bool */ - public function deleteFlag($flagCode) + public function deleteFlag($code) { - $flag = $this->getFlagObject($flagCode); + $flag = $this->getFlagObject($code); + if ($flag->getId()) { $this->flagResource->delete($flag); } + return true; } /** * Returns flag object * - * @param string $flagCode + * @param string $code * @return Flag */ - private function getFlagObject($flagCode) + private function getFlagObject($code) { /** @var Flag $flag */ - $flag = $this->flagFactory - ->create(['data' => ['flag_code' => $flagCode]]); - $this->flagResource->load($flag, $flagCode, 'flag_code'); + $flag = $this->flagFactory->create(['data' => ['flag_code' => $code]]); + $this->flagResource->load( + $flag, + $code, + 'flag_code' + ); + return $flag; } } diff --git a/app/code/Magento/Analytics/Test/Unit/Model/FlagManagerTest.php b/lib/internal/Magento/Framework/Test/Unit/FlagManagerTest.php similarity index 78% rename from app/code/Magento/Analytics/Test/Unit/Model/FlagManagerTest.php rename to lib/internal/Magento/Framework/Test/Unit/FlagManagerTest.php index 7143d398c9dc4..1aaabbbf78b2e 100644 --- a/app/code/Magento/Analytics/Test/Unit/Model/FlagManagerTest.php +++ b/lib/internal/Magento/Framework/Test/Unit/FlagManagerTest.php @@ -3,12 +3,13 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Analytics\Test\Unit\Model; +namespace Magento\Framework\Test\Unit; -use Magento\Analytics\Model\FlagManager; use Magento\Framework\FlagFactory; use Magento\Framework\Flag\FlagResource; use Magento\Framework\Flag; +use Magento\Framework\FlagManager; +use PHPUnit_Framework_MockObject_MockObject as Mock; /** * Class FlagManagerTest @@ -16,36 +17,40 @@ class FlagManagerTest extends \PHPUnit_Framework_TestCase { /** - * @var FlagFactory|\PHPUnit_Framework_MockObject_MockObject + * @var FlagFactory|Mock */ private $flagFactoryMock; /** - * @var FlagManager + * @var Flag|Mock */ - private $flagManager; + private $flagMock; /** - * @var Flag|\PHPUnit_Framework_MockObject_MockObject + * @var FlagResource|Mock */ - private $flagMock; + private $flagResourceMock; /** - * @var FlagResource|\PHPUnit_Framework_MockObject_MockObject + * @var FlagManager */ - private $flagResourceMock; + private $flagManager; + /** + * @inheritdoc + */ protected function setUp() { - $this->flagFactoryMock = $this->getMockBuilder(FlagFactory::class) + $this->flagFactoryMock = $this->getMockBuilder(FlagFactory::class) ->disableOriginalConstructor() ->getMock(); - $this->flagResourceMock = $this->getMockBuilder(FlagResource::class) + $this->flagResourceMock = $this->getMockBuilder(FlagResource::class) ->disableOriginalConstructor() ->getMock(); - $this->flagMock = $this->getMockBuilder(Flag::class) + $this->flagMock = $this->getMockBuilder(Flag::class) ->disableOriginalConstructor() ->getMock(); + $this->flagManager = new FlagManager( $this->flagFactoryMock, $this->flagResourceMock @@ -54,17 +59,18 @@ protected function setUp() public function testGetFlagData() { - $flagCode = "flag"; + $flagCode = 'flag'; $this->setupFlagObject($flagCode); $this->flagMock->expects($this->once()) ->method('getFlagData') ->willReturn(10); + $this->assertEquals($this->flagManager->getFlagData($flagCode), 10); } public function testSaveFlag() { - $flagCode = "flag"; + $flagCode = 'flag'; $this->setupFlagObject($flagCode); $this->flagMock->expects($this->once()) ->method('setFlagData') @@ -72,7 +78,10 @@ public function testSaveFlag() $this->flagResourceMock->expects($this->once()) ->method('save') ->with($this->flagMock); - $this->assertTrue($this->flagManager->saveFlag($flagCode, 10)); + + $this->assertTrue( + $this->flagManager->saveFlag($flagCode, 10) + ); } /** @@ -82,19 +91,25 @@ public function testSaveFlag() */ public function testDeleteFlag($isFlagExist) { - $flagCode = "flag"; + $flagCode = 'flag'; + $this->setupFlagObject($flagCode); + $this->flagMock ->expects($this->once()) ->method('getId') ->willReturn($isFlagExist); + if ($isFlagExist) { $this->flagResourceMock ->expects($this->once()) ->method('delete') ->with($this->flagMock); } - $this->assertTrue($this->flagManager->deleteFlag($flagCode)); + + $this->assertTrue( + $this->flagManager->deleteFlag($flagCode) + ); } private function setupFlagObject($flagCode)