Skip to content

Commit e1aad10

Browse files
Merge branch 'MAGETWO-64223' of https://github.com/magento-falcons/magento2ce into MAGETWO-65308
2 parents 84d382b + 2e79f7c commit e1aad10

File tree

9 files changed

+551
-207
lines changed

9 files changed

+551
-207
lines changed

app/code/Magento/Config/Console/Command/ConfigSetCommand.php

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
namespace Magento\Config\Console\Command;
77

88
use Magento\Config\Console\Command\ConfigSet\ConfigSetProcessorFactory;
9+
use Magento\Config\Model\Config\PathValidatorFactory;
910
use Magento\Framework\App\Area;
1011
use Magento\Framework\App\Config\ScopeConfigInterface;
1112
use Magento\Framework\App\Scope\ValidatorInterface;
@@ -33,33 +34,49 @@ class ConfigSetCommand extends Command
3334
/**#@-*/
3435

3536
/**
37+
* The factory for config:set processors.
38+
*
3639
* @var ConfigSetProcessorFactory
3740
*/
3841
private $configSetProcessorFactory;
3942

4043
/**
44+
* Scope validator.
45+
*
4146
* @var ValidatorInterface
4247
*/
4348
private $validator;
4449

4550
/**
51+
* Scope manager.
52+
*
4653
* @var ScopeInterface
4754
*/
4855
private $scope;
4956

5057
/**
51-
* @param ConfigSetProcessorFactory $configSetProcessorFactory
52-
* @param ValidatorInterface $validator
53-
* @param ScopeInterface $scope
58+
* The factory for path validator.
59+
*
60+
* @var PathValidatorFactory
61+
*/
62+
private $pathValidatorFactory;
63+
64+
/**
65+
* @param ConfigSetProcessorFactory $configSetProcessorFactory The factory for config:set processors
66+
* @param ValidatorInterface $validator Scope validator
67+
* @param ScopeInterface $scope Scope manager
68+
* @param PathValidatorFactory $pathValidatorFactory The factory for path validator
5469
*/
5570
public function __construct(
5671
ConfigSetProcessorFactory $configSetProcessorFactory,
5772
ValidatorInterface $validator,
58-
ScopeInterface $scope
73+
ScopeInterface $scope,
74+
PathValidatorFactory $pathValidatorFactory
5975
) {
6076
$this->configSetProcessorFactory = $configSetProcessorFactory;
6177
$this->validator = $validator;
6278
$this->scope = $scope;
79+
$this->pathValidatorFactory = $pathValidatorFactory;
6380

6481
parent::__construct();
6582
}
@@ -118,6 +135,14 @@ protected function execute(InputInterface $input, OutputInterface $output)
118135
// Emulating adminhtml scope to be able to read configs.
119136
$this->scope->setCurrentScope(Area::AREA_ADMINHTML);
120137

138+
/**
139+
* Validates the entered config path.
140+
* Requires emulated area.
141+
*/
142+
$this->pathValidatorFactory->create()->validate(
143+
$input->getArgument(ConfigSetCommand::ARG_PATH)
144+
);
145+
121146
$processor = $input->getOption(static::OPTION_LOCK)
122147
? $this->configSetProcessorFactory->create(ConfigSetProcessorFactory::TYPE_LOCK)
123148
: $this->configSetProcessorFactory->create(ConfigSetProcessorFactory::TYPE_DEFAULT);
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Config\Model\Config;
7+
8+
use Magento\Framework\Exception\ValidatorException;
9+
10+
/**
11+
* Validates the config path by config structure schema.
12+
*/
13+
class PathValidator
14+
{
15+
/**
16+
* The config structure.
17+
*
18+
* @var Structure
19+
*/
20+
private $structure;
21+
22+
/**
23+
* @param Structure $structure The config structure
24+
*/
25+
public function __construct(Structure $structure)
26+
{
27+
$this->structure = $structure;
28+
}
29+
30+
/**
31+
* Validates the config path by config structure schema.
32+
*
33+
* @param string $path The config path
34+
* @return bool The result of validation
35+
* @throws ValidatorException If provided path is not valid
36+
*/
37+
public function validate($path)
38+
{
39+
$allPaths = $this->structure->getFieldPaths();
40+
41+
if (!array_key_exists($path, $allPaths)) {
42+
throw new ValidatorException(__('The "%1" path does not exist', $path));
43+
}
44+
45+
return true;
46+
}
47+
}

app/code/Magento/Config/Model/Config/Structure.php

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@
33
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
namespace Magento\Config\Model\Config;
67

78
/**
8-
* System configuration structure
9+
* System configuration structure.
910
*/
10-
namespace Magento\Config\Model\Config;
11-
1211
class Structure implements \Magento\Config\Model\Config\Structure\SearchInterface
1312
{
1413
/**
@@ -251,4 +250,57 @@ protected function _getGroupFieldPathsByAttribute(array $fields, $parentPath, $a
251250
}
252251
return $result;
253252
}
253+
254+
/**
255+
* Collects config field paths recursively from config schema.
256+
* Returns an array map of fields specification.
257+
*
258+
* ```php
259+
* [
260+
* 'test_config/test_config/test_config' => [
261+
* 'test_structure/test_structure/test_structure'
262+
* ]
263+
* ```
264+
*
265+
* @return array An array of config path to config structure path map
266+
*/
267+
public function getFieldPaths()
268+
{
269+
$sections = !empty($this->_data['sections']) ? $this->_data['sections'] : [];
270+
271+
return $this->getFieldsRecursively($sections);
272+
}
273+
274+
/**
275+
* Iteration that collects config field paths recursively from config schema.
276+
*
277+
* @param array $elements The elements to be parsed
278+
* @return array An array of config path to config structure path map
279+
*/
280+
private function getFieldsRecursively(array $elements = [])
281+
{
282+
$result = [];
283+
284+
foreach ($elements as $element) {
285+
if (isset($element['children'])) {
286+
$result = array_replace_recursive(
287+
$result,
288+
$this->getFieldsRecursively($element['children'])
289+
);
290+
} else {
291+
if ($element['_elementType'] === 'field' && isset($element['label'])) {
292+
$structurePath = (isset($element['path']) ? $element['path'] . '/' : '') . $element['id'];
293+
$configPath = isset($element['config_path']) ? $element['config_path'] : $structurePath;
294+
295+
if (!isset($result[$configPath])) {
296+
$result[$configPath] = [];
297+
}
298+
299+
$result[$configPath][] = $structurePath;
300+
}
301+
}
302+
}
303+
304+
return $result;
305+
}
254306
}

app/code/Magento/Config/Test/Unit/Console/Command/ConfigSetCommandTest.php

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@
88
use Magento\Config\Console\Command\ConfigSet\ConfigSetProcessorFactory;
99
use Magento\Config\Console\Command\ConfigSet\ConfigSetProcessorInterface;
1010
use Magento\Config\Console\Command\ConfigSetCommand;
11+
use Magento\Config\Model\Config\PathValidator;
12+
use Magento\Config\Model\Config\PathValidatorFactory;
1113
use Magento\Framework\App\Scope\ValidatorInterface;
1214
use Magento\Framework\Config\ScopeInterface;
1315
use Magento\Framework\Console\Cli;
1416
use Magento\Framework\Exception\LocalizedException;
17+
use Magento\Framework\Exception\ValidatorException;
1518
use PHPUnit_Framework_MockObject_MockObject as Mock;
1619
use Symfony\Component\Console\Tester\CommandTester;
1720

@@ -48,6 +51,16 @@ class ConfigSetCommandTest extends \PHPUnit_Framework_TestCase
4851
*/
4952
private $scopeMock;
5053

54+
/**
55+
* @var PathValidatorFactory|Mock
56+
*/
57+
private $pathValidatorFactoryMock;
58+
59+
/**
60+
* @var PathValidator|Mock
61+
*/
62+
private $pathValidator;
63+
5164
/**
5265
* @inheritdoc
5366
*/
@@ -63,11 +76,23 @@ protected function setUp()
6376
->getMockForAbstractClass();
6477
$this->scopeMock = $this->getMockBuilder(ScopeInterface::class)
6578
->getMockForAbstractClass();
79+
$this->pathValidatorFactoryMock = $this->getMockBuilder(PathValidatorFactory::class)
80+
->disableOriginalConstructor()
81+
->setMethods(['create'])
82+
->getMock();
83+
$this->pathValidator = $this->getMockBuilder(PathValidator::class)
84+
->disableOriginalConstructor()
85+
->getMock();
86+
87+
$this->pathValidatorFactoryMock->expects($this->any())
88+
->method('create')
89+
->willReturn($this->pathValidator);
6690

6791
$this->command = new ConfigSetCommand(
6892
$this->configSetProcessorFactoryMock,
6993
$this->validatorMock,
70-
$this->scopeMock
94+
$this->scopeMock,
95+
$this->pathValidatorFactoryMock
7196
);
7297
}
7398

@@ -120,4 +145,28 @@ public function testExecuteNotValidScope()
120145

121146
$this->assertSame(Cli::RETURN_FAILURE, $tester->getStatusCode());
122147
}
148+
149+
public function testExecuteWithException()
150+
{
151+
$this->validatorMock->expects($this->once())
152+
->method('isValid')
153+
->willReturn(true);
154+
$this->pathValidator->expects($this->once())
155+
->method('validate')
156+
->willThrowException(new ValidatorException(__('The "test/test/test" path does not exists')));
157+
$this->configSetProcessorFactoryMock->expects($this->never())
158+
->method('create');
159+
160+
$tester = new CommandTester($this->command);
161+
$tester->execute([
162+
ConfigSetCommand::ARG_PATH => 'test/test/test',
163+
ConfigSetCommand::ARG_VALUE => 'value'
164+
]);
165+
166+
$this->assertContains(
167+
__('The "test/test/test" path does not exists')->render(),
168+
$tester->getDisplay()
169+
);
170+
$this->assertSame(Cli::RETURN_FAILURE, $tester->getStatusCode());
171+
}
123172
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Config\Test\Unit\Model\Config;
7+
8+
use Magento\Config\Model\Config\PathValidator;
9+
use Magento\Config\Model\Config\Structure;
10+
use PHPUnit_Framework_MockObject_MockObject as Mock;
11+
12+
/**
13+
* Test class for PathValidator.
14+
*
15+
* @see PathValidator
16+
*/
17+
class PathValidatorTest extends \PHPUnit_Framework_TestCase
18+
{
19+
/**
20+
* @var PathValidator
21+
*/
22+
private $model;
23+
24+
/**
25+
* @var Structure|Mock
26+
*/
27+
private $structureMock;
28+
29+
/**
30+
* @inheritdoc
31+
*/
32+
protected function setUp()
33+
{
34+
$this->structureMock = $this->getMockBuilder(Structure::class)
35+
->disableOriginalConstructor()
36+
->getMock();
37+
38+
$this->model = new PathValidator(
39+
$this->structureMock
40+
);
41+
}
42+
43+
public function testValidate()
44+
{
45+
$this->structureMock->expects($this->once())
46+
->method('getFieldPaths')
47+
->willReturn([
48+
'test/test/test' => [
49+
'test/test/test'
50+
]
51+
]);
52+
53+
$this->assertTrue($this->model->validate('test/test/test'));
54+
}
55+
56+
/**
57+
* @expectedException \Magento\Framework\Exception\ValidatorException
58+
* @expectedExceptionMessage The "test/test/test" path does not exist
59+
*/
60+
public function testValidateWithException()
61+
{
62+
$this->structureMock->expects($this->once())
63+
->method('getFieldPaths')
64+
->willReturn([]);
65+
66+
$this->assertTrue($this->model->validate('test/test/test'));
67+
}
68+
}

0 commit comments

Comments
 (0)