Skip to content

Commit

Permalink
Merge pull request #911 from magento-falcons/MAGETWO-65701
Browse files Browse the repository at this point in the history
Bugs
- MAGETWO-65308 CLI command config:set fails on configurations which requires session
- MAGETWO-62560 Catalog Module UpgradeData to 2.1.3 breaks when cost attribute is deleted #7804 - for 2.2.0
Task
- MAGETWO-65208 Store checksum for every section of configuration file & change behavior on read-only FS & add sorting of importers
  • Loading branch information
VladimirZaets authored Mar 15, 2017
2 parents aa93ea8 + 85a3ef6 commit b14d70e
Show file tree
Hide file tree
Showing 30 changed files with 886 additions and 444 deletions.
15 changes: 8 additions & 7 deletions app/code/Magento/Catalog/Setup/UpgradeData.php
Original file line number Diff line number Diff line change
Expand Up @@ -401,13 +401,14 @@ private function changePriceAttributeDefaultScope($categorySetup)
$entityTypeId = $categorySetup->getEntityTypeId(\Magento\Catalog\Model\Product::ENTITY);
foreach (['price', 'cost', 'special_price'] as $attributeCode) {
$attribute = $categorySetup->getAttribute($entityTypeId, $attributeCode);
$categorySetup->updateAttribute(
$entityTypeId,
$attribute['attribute_id'],
'is_global',
\Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL
);

if (isset($attribute['attribute_id'])) {
$categorySetup->updateAttribute(
$entityTypeId,
$attribute['attribute_id'],
'is_global',
\Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL
);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php
/**
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Config\Console\Command\ConfigSet;

use Magento\Config\Console\Command\ConfigSetCommand;
use Magento\Framework\App\Scope\ValidatorInterface;
use Magento\Config\Model\Config\PathValidator;
use Magento\Framework\Exception\ConfigurationMismatchException;
use Magento\Framework\Exception\CouldNotSaveException;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\ValidatorException;

/**
* Processor facade for config:set command.
*
* @see ConfigSetCommand
*/
class ProcessorFacade
{
/**
* The scope validator.
*
* @var ValidatorInterface
*/
private $scopeValidator;

/**
* The path validator.
*
* @var PathValidator
*/
private $pathValidator;

/**
* The factory for config:set processors.
*
* @var ConfigSetProcessorFactory
*/
private $configSetProcessorFactory;

/**
* @param ValidatorInterface $scopeValidator The scope validator
* @param PathValidator $pathValidator The path validator
* @param ConfigSetProcessorFactory $configSetProcessorFactory The factory for config:set processors
*/
public function __construct(
ValidatorInterface $scopeValidator,
PathValidator $pathValidator,
ConfigSetProcessorFactory $configSetProcessorFactory
) {
$this->scopeValidator = $scopeValidator;
$this->pathValidator = $pathValidator;
$this->configSetProcessorFactory = $configSetProcessorFactory;
}

/**
* 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 LocalizedException If scope validation failed
* @throws ValidatorException If path validation failed
* @throws CouldNotSaveException If processing failed
* @throws ConfigurationMismatchException If processor can not be instantiated
*/
public function process($path, $value, $scope, $scopeCode, $lock)
{
$this->scopeValidator->isValid($scope, $scopeCode);
$this->pathValidator->validate($path);

$processor = $lock
? $this->configSetProcessorFactory->create(ConfigSetProcessorFactory::TYPE_LOCK)
: $this->configSetProcessorFactory->create(ConfigSetProcessorFactory::TYPE_DEFAULT);
$message = $lock
? 'Value was saved and locked.'
: 'Value was saved.';

// The processing flow depends on --lock option.
$processor->process($path, $value, $scope, $scopeCode);

return $message;
}
}
91 changes: 31 additions & 60 deletions app/code/Magento/Config/Console/Command/ConfigSetCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,17 @@
*/
namespace Magento\Config\Console\Command;

use Magento\Config\Console\Command\ConfigSet\ConfigSetProcessorFactory;
use Magento\Config\Model\Config\PathValidatorFactory;
use Magento\Framework\App\Area;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\Scope\ValidatorInterface;
use Magento\Framework\App\State;
use Magento\Framework\Config\ScopeInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Console\Cli;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Magento\Config\Console\Command\ConfigSet\ProcessorFacadeFactory;

/**
* Command provides possibility to change system configuration.
Expand All @@ -34,49 +33,39 @@ class ConfigSetCommand extends Command
/**#@-*/

/**
* The factory for config:set processors.
* Scope manager.
*
* @var ConfigSetProcessorFactory
* @var ScopeInterface
*/
private $configSetProcessorFactory;
private $scope;

/**
* Scope validator.
* Application state.
*
* @var ValidatorInterface
* @var State
*/
private $validator;
private $state;

/**
* Scope manager.
* The processor facade factory
*
* @var ScopeInterface
* @var ProcessorFacadeFactory
*/
private $scope;
private $processorFacadeFactory;

/**
* The factory for path validator.
*
* @var PathValidatorFactory
*/
private $pathValidatorFactory;

/**
* @param ConfigSetProcessorFactory $configSetProcessorFactory The factory for config:set processors
* @param ValidatorInterface $validator Scope validator
* @param ScopeInterface $scope Scope manager
* @param PathValidatorFactory $pathValidatorFactory The factory for path validator
* @param State $state Application state
* @param ProcessorFacadeFactory $processorFacadeFactory The processor facade factory
*/
public function __construct(
ConfigSetProcessorFactory $configSetProcessorFactory,
ValidatorInterface $validator,
ScopeInterface $scope,
PathValidatorFactory $pathValidatorFactory
State $state,
ProcessorFacadeFactory $processorFacadeFactory
) {
$this->configSetProcessorFactory = $configSetProcessorFactory;
$this->validator = $validator;
$this->scope = $scope;
$this->pathValidatorFactory = $pathValidatorFactory;
$this->state = $state;
$this->processorFacadeFactory = $processorFacadeFactory;

parent::__construct();
}
Expand Down Expand Up @@ -127,38 +116,20 @@ protected function configure()
protected function execute(InputInterface $input, OutputInterface $output)
{
try {
$this->validator->isValid(
$input->getOption(static::OPTION_SCOPE),
$input->getOption(static::OPTION_SCOPE_CODE)
);

// Emulating adminhtml scope to be able to read configs.
$this->scope->setCurrentScope(Area::AREA_ADMINHTML);

/**
* Validates the entered config path.
* Requires emulated area.
*/
$this->pathValidatorFactory->create()->validate(
$input->getArgument(ConfigSetCommand::ARG_PATH)
);

$processor = $input->getOption(static::OPTION_LOCK)
? $this->configSetProcessorFactory->create(ConfigSetProcessorFactory::TYPE_LOCK)
: $this->configSetProcessorFactory->create(ConfigSetProcessorFactory::TYPE_DEFAULT);
$message = $input->getOption(static::OPTION_LOCK)
? 'Value was saved and locked.'
: 'Value was saved.';

// The processing flow depends on --lock option.
$processor->process(
$input->getArgument(ConfigSetCommand::ARG_PATH),
$input->getArgument(ConfigSetCommand::ARG_VALUE),
$input->getOption(ConfigSetCommand::OPTION_SCOPE),
$input->getOption(ConfigSetCommand::OPTION_SCOPE_CODE)
);

$output->writeln('<info>' . $message . '</info>');
$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('<info>' . $message . '</info>');
});

return Cli::RETURN_SUCCESS;
} catch (\Exception $exception) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php
/**
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Config\Test\Unit\Console\Command\ConfigSet;

use Magento\Config\Console\Command\ConfigSet\ConfigSetProcessorFactory;
use Magento\Config\Console\Command\ConfigSet\ConfigSetProcessorInterface;
use Magento\Config\Console\Command\ConfigSet\ProcessorFacade;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\Scope\ValidatorInterface;
use Magento\Config\Model\Config\PathValidator;
use PHPUnit_Framework_MockObject_MockObject as Mock;

/**
* Test for ProcessorFacade.
*
* @see ProcessorFacade
*/
class ProcessorFacadeTest extends \PHPUnit_Framework_TestCase
{
/**
* @var ProcessorFacade
*/
private $model;

/**
* @var ValidatorInterface|Mock
*/
private $scopeValidatorMock;

/**
* @var PathValidator|Mock
*/
private $pathValidatorMock;

/**
* @var ConfigSetProcessorFactory|Mock
*/
private $configSetProcessorFactoryMock;

/**
* @var ConfigSetProcessorInterface|Mock
*/
private $processorMock;

/**
* @inheritdoc
*/
protected function setUp()
{
$this->scopeValidatorMock = $this->getMockBuilder(ValidatorInterface::class)
->getMockForAbstractClass();
$this->pathValidatorMock = $this->getMockBuilder(PathValidator::class)
->disableOriginalConstructor()
->getMock();
$this->configSetProcessorFactoryMock = $this->getMockBuilder(ConfigSetProcessorFactory::class)
->disableOriginalConstructor()
->getMock();
$this->processorMock = $this->getMockBuilder(ConfigSetProcessorInterface::class)
->getMockForAbstractClass();

$this->configSetProcessorFactoryMock->expects($this->any())
->method('create')
->willReturn($this->processorMock);

$this->model = new ProcessorFacade(
$this->scopeValidatorMock,
$this->pathValidatorMock,
$this->configSetProcessorFactoryMock
);
}

public function testProcess()
{
$this->scopeValidatorMock->expects($this->once())
->method('isValid')
->willReturn(true);
$this->configSetProcessorFactoryMock->expects($this->once())
->method('create')
->with(ConfigSetProcessorFactory::TYPE_DEFAULT)
->willReturn($this->processorMock);
$this->processorMock->expects($this->once())
->method('process')
->with('test/test/test', 'test', ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null);

$this->assertSame(
'Value was saved.',
$this->model->process('test/test/test', 'test', ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null, false)
);
}

public function testExecuteLock()
{
$this->scopeValidatorMock->expects($this->once())
->method('isValid')
->willReturn(true);
$this->configSetProcessorFactoryMock->expects($this->once())
->method('create')
->with(ConfigSetProcessorFactory::TYPE_LOCK)
->willReturn($this->processorMock);
$this->processorMock->expects($this->once())
->method('process')
->with('test/test/test', 'test', ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null);

$this->assertSame(
'Value was saved and locked.',
$this->model->process('test/test/test', 'test', ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null, true)
);
}
}
Loading

0 comments on commit b14d70e

Please sign in to comment.