Skip to content

Commit 3f75fac

Browse files
Merge pull request #889 from magento-falcons/MAGETWO-65085
Task - MAGETWO-65085 [PR] Delivery of deployment improvements Story - MAGETWO-63084 Sync config file with DB: Validation - MAGETWO-62736 Rename config.local.php file, use env.php file as configs storage - MAGETWO-63381 CLI Improvements: Configuration management - Hide sensitive values from config:show command - MAGETWO-64223 CLI Improvements: Configuration management - Add validations to config:set command - MAGETWO-63095 User can change the Interface Locale only to locales that are already deployed.
2 parents a6b6599 + 54cbf40 commit 3f75fac

File tree

79 files changed

+3991
-601
lines changed

Some content is hidden

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

79 files changed

+3991
-601
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\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->getTranslatedOptionLocales(),
125139
'class' => 'select'
126140
]
127141
);

app/code/Magento/Config/Console/Command/ConfigSet/LockProcessor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ public function process($path, $value, $scope, $scopeCode)
122122
$backendModel->beforeSave();
123123

124124
$this->deploymentConfigWriter->saveConfig(
125-
[ConfigFilePool::APP_CONFIG => $this->arrayManager->set($configPath, [], $backendModel->getValue())],
125+
[ConfigFilePool::APP_ENV => $this->arrayManager->set($configPath, [], $backendModel->getValue())],
126126
false
127127
);
128128

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: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,18 @@
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 SAFE_PLACEHOLDER = '******';
26+
2127
/**
2228
* System configuration structure factory.
2329
*
@@ -55,7 +61,7 @@ public function __construct(
5561
}
5662

5763
/**
58-
* Processes value using backend model.
64+
* Processes value to display using backend model.
5965
*
6066
* @param string $scope The scope of configuration. E.g. 'default', 'website' or 'store'
6167
* @param string $scopeCode The scope code of configuration
@@ -78,6 +84,11 @@ public function process($scope, $scopeCode, $value, $path)
7884
$backendModel = $field && $field->hasBackendModel()
7985
? $field->getBackendModel()
8086
: $this->configValueFactory->create();
87+
88+
if ($backendModel instanceof Encrypted) {
89+
return $value ? self::SAFE_PLACEHOLDER : null;
90+
}
91+
8192
$backendModel->setPath($path);
8293
$backendModel->setScope($scope);
8394
$backendModel->setScopeId($scopeCode);

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+
* Checks whether the config path present in configuration structure.
32+
*
33+
* @param string $path The config path
34+
* @return true 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: 78 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,80 @@ protected function _getGroupFieldPathsByAttribute(array $fields, $parentPath, $a
251250
}
252251
return $result;
253252
}
253+
254+
/**
255+
* Collects config paths and their structure paths from configuration files.
256+
* Returns the map of config paths and their structure paths.
257+
*
258+
* All paths are declared in module's system.xml.
259+
*
260+
* ```xml
261+
* <section id="section_id">
262+
* <group id="group_id" ...>
263+
* <field id="field_one_id" ...>
264+
* <label>Field One</label>
265+
* ...
266+
* </field>
267+
* <field id="field_two_id" ...>
268+
* <label>Field Two</label>
269+
* <config_path>section/group/field</config_path>
270+
* ...
271+
* </field>
272+
* </group>
273+
* </section>
274+
* ```
275+
* If <config_path> node does not exist, then config path duplicates structure path.
276+
* The result of this example will be:
277+
*
278+
* ```php
279+
* [
280+
* 'section_id/group_id/field_one_id' => [
281+
* 'section_id/group_id/field_one_id'
282+
* ],
283+
* 'section/group/field' => [
284+
* 'section_id/group_id/field_two_id'
285+
* ]
286+
*```
287+
*
288+
* @return array An array of config path to config structure path map
289+
*/
290+
public function getFieldPaths()
291+
{
292+
$sections = !empty($this->_data['sections']) ? $this->_data['sections'] : [];
293+
294+
return $this->getFieldsRecursively($sections);
295+
}
296+
297+
/**
298+
* Iteration that collects config field paths recursively from config files.
299+
*
300+
* @param array $elements The elements to be parsed
301+
* @return array An array of config path to config structure path map
302+
*/
303+
private function getFieldsRecursively(array $elements = [])
304+
{
305+
$result = [];
306+
307+
foreach ($elements as $element) {
308+
if (isset($element['children'])) {
309+
$result = array_replace_recursive(
310+
$result,
311+
$this->getFieldsRecursively($element['children'])
312+
);
313+
} else {
314+
if ($element['_elementType'] === 'field' && isset($element['label'])) {
315+
$structurePath = (isset($element['path']) ? $element['path'] . '/' : '') . $element['id'];
316+
$configPath = isset($element['config_path']) ? $element['config_path'] : $structurePath;
317+
318+
if (!isset($result[$configPath])) {
319+
$result[$configPath] = [];
320+
}
321+
322+
$result[$configPath][] = $structurePath;
323+
}
324+
}
325+
}
326+
327+
return $result;
328+
}
254329
}

app/code/Magento/Config/Test/Unit/Console/Command/ConfigSet/LockProcessorTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ public function testProcess($path, $value, $scope, $scopeCode)
164164
->method('saveConfig')
165165
->with(
166166
[
167-
ConfigFilePool::APP_CONFIG => [
167+
ConfigFilePool::APP_ENV => [
168168
'system' => [
169169
'default' => [
170170
'test' => [
@@ -234,7 +234,7 @@ public function testProcessBackendModelNotExists()
234234
->method('saveConfig')
235235
->with(
236236
[
237-
ConfigFilePool::APP_CONFIG => [
237+
ConfigFilePool::APP_ENV => [
238238
'system' => [
239239
'default' => [
240240
'test' => [

0 commit comments

Comments
 (0)