Skip to content

Commit c38893e

Browse files
committed
MAGETWO-63382: CLI Improvements: Configuration management - Command config:show
1 parent 76ba425 commit c38893e

File tree

6 files changed

+275
-21
lines changed

6 files changed

+275
-21
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Config\Console\Command\ConfigShow;
7+
8+
use Magento\Framework\App\Config\ConfigSourceInterface;
9+
10+
/**
11+
* Configuration object used for ConfigShowCommand
12+
*/
13+
class ConfigSourceAggregated implements ConfigSourceInterface
14+
{
15+
/**
16+
* @var ConfigSourceInterface[]
17+
*/
18+
private $sources;
19+
20+
/**
21+
* @param array $sources
22+
*/
23+
public function __construct(array $sources = [])
24+
{
25+
$this->sources = $sources;
26+
}
27+
28+
/**
29+
* Retrieve aggregated configuration from all available sources.
30+
*
31+
* @param string $path
32+
* @return array
33+
*/
34+
public function get($path = '')
35+
{
36+
$this->sortSources();
37+
$data = [];
38+
foreach ($this->sources as $sourceConfig) {
39+
/** @var ConfigSourceInterface $source */
40+
$source = $sourceConfig['source'];
41+
$data = array_replace_recursive($data, $source->get($path));
42+
}
43+
return $data;
44+
}
45+
46+
/**
47+
* Sort given sources
48+
*
49+
* @return void
50+
*/
51+
private function sortSources()
52+
{
53+
uasort($this->sources, function ($firstItem, $secondItem) {
54+
return $firstItem['sortOrder'] > $secondItem['sortOrder'];
55+
});
56+
}
57+
}

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

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
*/
66
namespace Magento\Config\Console\Command;
77

8+
use Magento\Framework\App\Config\ConfigSourceInterface;
9+
use Magento\Framework\App\Config\MetadataProcessor;
810
use Magento\Framework\App\Config\ScopeConfigInterface;
11+
use Magento\Framework\App\Config\ScopePathResolver;
912
use Magento\Framework\Exception\LocalizedException;
1013
use Symfony\Component\Console\Command\Command;
1114
use Magento\Framework\App\Scope\ValidatorInterface;
@@ -34,21 +37,38 @@ class ConfigShowCommand extends Command
3437
private $scopeValidator;
3538

3639
/**
37-
* @var ScopeConfigInterface
40+
* @var ConfigSourceInterface
3841
*/
39-
private $appConfig;
42+
private $configSource;
43+
44+
/**
45+
* @var ScopePathResolver
46+
*/
47+
private $pathResolver;
48+
49+
/**
50+
* @var MetadataProcessor
51+
*/
52+
private $metadataProcessor;
4053

4154
/**
42-
* @param ScopeConfigInterface $appConfig
4355
* @param ValidatorInterface $scopeValidator
56+
* @param ConfigSourceInterface $configSource
57+
* @param ScopePathResolver $pathResolver
58+
* @param MetadataProcessor $metadataProcessor
59+
* @internal param ScopeConfigInterface $appConfig
4460
*/
4561
public function __construct(
46-
ScopeConfigInterface $appConfig,
47-
ValidatorInterface $scopeValidator
62+
ValidatorInterface $scopeValidator,
63+
ConfigSourceInterface $configSource,
64+
ScopePathResolver $pathResolver,
65+
MetadataProcessor $metadataProcessor
4866
) {
4967
parent::__construct();
5068
$this->scopeValidator = $scopeValidator;
51-
$this->appConfig = $appConfig;
69+
$this->configSource = $configSource;
70+
$this->pathResolver = $pathResolver;
71+
$this->metadataProcessor = $metadataProcessor;
5272
}
5373

5474
/**
@@ -92,11 +112,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
92112
{
93113
$scope = $input->getOption(self::INPUT_OPTION_SCOPE);
94114
$scopeCode = $input->getOption(self::INPUT_OPTION_SCOPE_CODE);
95-
$configPath = $input->getArgument(self::INPUT_ARGUMENT_PATH);
115+
$inputPath = $input->getArgument(self::INPUT_ARGUMENT_PATH);
96116

97117
try {
98118
$this->scopeValidator->isValid($scope, $scopeCode);
99-
$configValue = $this->appConfig->getValue($configPath, $scope, $scopeCode);
119+
$configPath = $this->pathResolver->resolve($inputPath, $scope, $scopeCode);
120+
$configValue = $this->configSource->get($configPath);
100121
} catch (LocalizedException $e) {
101122
$output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
102123
return Cli::RETURN_FAILURE;
@@ -105,12 +126,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
105126
if ($configValue === null) {
106127
$output->writeln(sprintf(
107128
'<error>%s</error>',
108-
__('Configuration for path: "%1" doesn\'t exist', $configPath)->render()
129+
__('Configuration for path: "%1" doesn\'t exist', $inputPath)->render()
109130
));
110131
return Cli::RETURN_FAILURE;
111132
}
112133

113-
$this->outputResult($output, $configValue, $configPath);
134+
$this->outputResult($output, $configValue, $inputPath);
114135
return Cli::RETURN_SUCCESS;
115136
}
116137

@@ -127,7 +148,8 @@ private function outputResult(OutputInterface $output, $configValue, $configPath
127148
{
128149
$margin = str_repeat(" ", max($level - 1, 0) * 2);
129150
if (is_string($configValue)) {
130-
$output->writeln(sprintf("%s%s - %s", $margin, $configPath, $configValue));
151+
$value = $this->metadataProcessor->processValue($configValue, $configPath);
152+
$output->writeln(sprintf("%s%s - %s", $margin, $configPath, $value));
131153
} else if (is_array($configValue)) {
132154
if ($level > 0) {
133155
$output->writeln(sprintf("%s%s:", $margin, $configPath ?: 'config'));

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

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66
namespace Magento\Config\Test\Unit\Console\Command;
77

88
use Magento\Config\Console\Command\ConfigShowCommand;
9+
use Magento\Framework\App\Config\ConfigSourceInterface;
910
use Magento\Framework\Console\Cli;
1011
use Magento\Framework\Exception\LocalizedException;
1112
use PHPUnit_Framework_MockObject_MockObject as MockObject;
12-
use Magento\Framework\App\Config\ScopeConfigInterface;
1313
use Magento\Framework\App\Scope\ValidatorInterface;
1414
use Symfony\Component\Console\Tester\CommandTester;
15+
use Magento\Framework\App\Config\MetadataProcessor;
16+
use Magento\Framework\App\Config\ScopePathResolver;
1517

1618
class ConfigShowCommandTest extends \PHPUnit_Framework_TestCase
1719
{
@@ -21,9 +23,19 @@ class ConfigShowCommandTest extends \PHPUnit_Framework_TestCase
2123
private $scopeValidatorMock;
2224

2325
/**
24-
* @var ScopeConfigInterface|MockObject
26+
* @var ConfigSourceInterface|MockObject
2527
*/
26-
private $appConfigMock;
28+
private $configSourceMock;
29+
30+
/**
31+
* @var MetadataProcessor|MockObject
32+
*/
33+
private $metadataProcessorMock;
34+
35+
/**
36+
* @var ScopePathResolver|MockObject
37+
*/
38+
private $pathResolverMock;
2739

2840
/**
2941
* @var ConfigShowCommand
@@ -32,27 +44,48 @@ class ConfigShowCommandTest extends \PHPUnit_Framework_TestCase
3244

3345
protected function setUp()
3446
{
35-
$this->appConfigMock = $this->getMockBuilder(ScopeConfigInterface::class)
36-
->getMockForAbstractClass();
47+
$this->metadataProcessorMock = $this->getMockBuilder(MetadataProcessor::class)
48+
->disableOriginalConstructor()
49+
->getMock();
50+
$this->pathResolverMock = $this->getMockBuilder(ScopePathResolver::class)
51+
->disableOriginalConstructor()
52+
->getMock();
3753
$this->scopeValidatorMock = $this->getMockBuilder(ValidatorInterface::class)
3854
->getMockForAbstractClass();
55+
$this->configSourceMock = $this->getMockBuilder(ConfigSourceInterface::class)
56+
->getMockForAbstractClass();
3957

4058
$this->command = new ConfigShowCommand(
41-
$this->appConfigMock,
42-
$this->scopeValidatorMock
59+
$this->scopeValidatorMock,
60+
$this->configSourceMock,
61+
$this->pathResolverMock,
62+
$this->metadataProcessorMock
4363
);
4464
}
4565

4666
public function testExecute()
4767
{
4868
$configPath = 'some/config/path';
69+
$resolvedConfigPath = 'someScope/someScopeCode/some/config/path';
4970
$scope = 'someScope';
5071
$scopeCode = 'someScopeCode';
5172

52-
$this->appConfigMock->expects($this->once())
53-
->method('getValue')
73+
$this->scopeValidatorMock->expects($this->once())
74+
->method('isValid')
75+
->with($scope, $scopeCode)
76+
->willReturn(true);
77+
$this->pathResolverMock->expects($this->once())
78+
->method('resolve')
5479
->with($configPath, $scope, $scopeCode)
80+
->willReturn($resolvedConfigPath);
81+
$this->configSourceMock->expects($this->once())
82+
->method('get')
83+
->with($resolvedConfigPath)
5584
->willReturn('someValue');
85+
$this->metadataProcessorMock->expects($this->once())
86+
->method('processValue')
87+
->with('someValue')
88+
->willReturn('someProcessedValue');
5689

5790
$tester = $this->getConfigShowCommandTester($configPath, $scope, $scopeCode);
5891

@@ -61,7 +94,7 @@ public function testExecute()
6194
$tester->getStatusCode()
6295
);
6396
$this->assertContains(
64-
'someValue',
97+
'someProcessedValue',
6598
$tester->getDisplay()
6699
);
67100
}

app/code/Magento/Config/etc/di.xml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,25 @@
190190
<argument name="placeholder" xsi:type="object">Magento\Config\Model\Placeholder\Environment</argument>
191191
</arguments>
192192
</type>
193+
<virtualType name="configShowSourceAggregated" type="Magento\Config\Console\Command\ConfigShow\ConfigSourceAggregated">
194+
<arguments>
195+
<argument name="sources" xsi:type="array">
196+
<item name="dynamic" xsi:type="array">
197+
<item name="source" xsi:type="object">Magento\Config\App\Config\Source\RuntimeConfigSource</item>
198+
<item name="sortOrder" xsi:type="string">100</item>
199+
</item>
200+
<item name="initial" xsi:type="array">
201+
<item name="source" xsi:type="object">systemConfigInitialDataProvider</item>
202+
<item name="sortOrder" xsi:type="string">1000</item>
203+
</item>
204+
</argument>
205+
</arguments>
206+
</virtualType>
207+
<type name="Magento\Config\Console\Command\ConfigShowCommand">
208+
<arguments>
209+
<argument name="configSource" xsi:type="object">configShowSourceAggregated</argument>
210+
</arguments>
211+
</type>
193212
<type name="Magento\Framework\Console\CommandListInterface">
194213
<arguments>
195214
<argument name="commands" xsi:type="array">

lib/internal/Magento/Framework/App/Config/MetadataProcessor.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,49 @@ public function process(array $data)
8888
}
8989
return $data;
9090
}
91+
92+
/**
93+
* Processes value into correct form.
94+
* Example: decrypt a value.
95+
*
96+
* @param string|int $value The value to process
97+
* @param string $path The path of the value
98+
* @return string The processed value
99+
*/
100+
public function processValue($value, $path)
101+
{
102+
if (isset($this->_metadata[$path])) {
103+
/** @var \Magento\Framework\App\Config\Data\ProcessorInterface $processor */
104+
$processor = $this->_processorFactory->get($this->_metadata[$path]['backendModel']);
105+
106+
return $processor->processValue($value);
107+
}
108+
109+
return $value;
110+
}
111+
112+
/**
113+
* Prepares value for saving.
114+
* Example: encrypt a value.
115+
*
116+
* @param string|int $value The value to prepare
117+
* @param string $path The path of the value
118+
* @return string The prepared value
119+
*/
120+
public function prepareValue($value, $path)
121+
{
122+
if (isset($this->_metadata[$path])) {
123+
/** @var \Magento\Framework\App\Config\Data\ProcessorInterface $processor */
124+
$processor = $this->_processorFactory->get($this->_metadata[$path]['backendModel']);
125+
126+
if ($processor instanceof \Magento\Framework\App\Config\Value) {
127+
$processor->setValue($value);
128+
$processor->beforeSave();
129+
130+
return $processor->getValue();
131+
}
132+
}
133+
134+
return $value;
135+
}
91136
}

0 commit comments

Comments
 (0)