Skip to content

Commit 13f39a4

Browse files
Merge branches 'MAGETWO-63084', 'MAGETWO-63381', 'MAGETWO-64223' and 'MAGETWO-64557' of https://github.com/magento-falcons/magento2ce into MAGETWO-65085
5 parents 84d382b + a300531 + 1f23587 + 2e79f7c + 136f6b1 commit 13f39a4

File tree

57 files changed

+3217
-255
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+3217
-255
lines changed

app/code/Magento/Backend/Block/System/Account/Edit/Form.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
*/
66
namespace Magento\Backend\Block\System\Account\Edit;
77

8+
use Magento\Framework\App\ObjectManager;
9+
use Magento\Framework\Locale\Deployed\OptionInterface;
10+
811
/**
912
* Adminhtml edit admin user account form
1013
*
@@ -29,6 +32,13 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic
2932
*/
3033
protected $_localeLists;
3134

35+
/**
36+
* Operates with deployed locales.
37+
*
38+
* @var OptionInterface
39+
*/
40+
private $deployedLocales;
41+
3242
/**
3343
* @param \Magento\Backend\Block\Template\Context $context
3444
* @param \Magento\Framework\Registry $registry
@@ -37,6 +47,7 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic
3747
* @param \Magento\Backend\Model\Auth\Session $authSession
3848
* @param \Magento\Framework\Locale\ListsInterface $localeLists
3949
* @param array $data
50+
* @param OptionInterface $deployedLocales Operates with deployed locales
4051
*/
4152
public function __construct(
4253
\Magento\Backend\Block\Template\Context $context,
@@ -45,11 +56,14 @@ public function __construct(
4556
\Magento\User\Model\UserFactory $userFactory,
4657
\Magento\Backend\Model\Auth\Session $authSession,
4758
\Magento\Framework\Locale\ListsInterface $localeLists,
48-
array $data = []
59+
array $data = [],
60+
OptionInterface $deployedLocales = null
4961
) {
5062
$this->_userFactory = $userFactory;
5163
$this->_authSession = $authSession;
5264
$this->_localeLists = $localeLists;
65+
$this->deployedLocales = $deployedLocales
66+
?: ObjectManager::getInstance()->get(OptionInterface::class);
5367
parent::__construct($context, $registry, $formFactory, $data);
5468
}
5569

@@ -121,7 +135,7 @@ protected function _prepareForm()
121135
'name' => 'interface_locale',
122136
'label' => __('Interface Locale'),
123137
'title' => __('Interface Locale'),
124-
'values' => $this->_localeLists->getTranslatedOptionLocales(),
138+
'values' => $this->deployedLocales->getTranslatedLocales(),
125139
'class' => 'select'
126140
]
127141
);

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);

app/code/Magento/Config/Console/Command/ConfigShow/ValueProcessor.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,20 @@
1212
use Magento\Config\Model\Config\Structure\Element\Field;
1313
use Magento\Framework\Config\ScopeInterface;
1414
use Magento\Framework\App\Area;
15+
use Magento\Config\Model\Config\Backend\Encrypted;
1516

1617
/**
1718
* Class processes values using backend model which declared in system.xml.
1819
*/
1920
class ValueProcessor
2021
{
22+
/**
23+
* Placeholder for the output of sensitive data.
24+
*
25+
* @const
26+
*/
27+
const SAFE_PLACEHOLDER = '******';
28+
2129
/**
2230
* System configuration structure factory.
2331
*
@@ -84,6 +92,8 @@ public function process($scope, $scopeCode, $value, $path)
8492
$backendModel->setValue($value);
8593
$backendModel->afterLoad();
8694

87-
return $backendModel->getValue();
95+
return ($backendModel instanceof Encrypted) && !empty($backendModel->getValue())
96+
? self::SAFE_PLACEHOLDER
97+
: $backendModel->getValue();
8898
}
8999
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
144144
try {
145145
$this->scope = $input->getOption(self::INPUT_OPTION_SCOPE);
146146
$this->scopeCode = $input->getOption(self::INPUT_OPTION_SCOPE_CODE);
147-
$this->inputPath = $input->getArgument(self::INPUT_ARGUMENT_PATH);
147+
$this->inputPath = trim($input->getArgument(self::INPUT_ARGUMENT_PATH), "/");
148148

149149
$this->scopeValidator->isValid($this->scope, $this->scopeCode);
150150
$configPath = $this->pathResolver->resolve($this->inputPath, $this->scope, $this->scopeCode);
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
}

0 commit comments

Comments
 (0)