Skip to content

Commit a6049d5

Browse files
fix issue with null config value
1 parent 3bff446 commit a6049d5

File tree

3 files changed

+146
-40
lines changed

3 files changed

+146
-40
lines changed

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

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
use Symfony\Component\Console\Input\InputInterface;
1717
use Symfony\Component\Console\Input\InputOption;
1818
use Symfony\Component\Console\Output\OutputInterface;
19+
use Magento\Framework\App\ObjectManager;
20+
use Magento\Config\Model\Config\PathValidatorFactory;
1921

2022
/**
2123
* Command provides possibility to show saved system configuration.
@@ -78,24 +80,42 @@ class ConfigShowCommand extends Command
7880
*/
7981
private $inputPath;
8082

83+
/**
84+
* @var PathValidatorFactory
85+
*/
86+
private $pathValidatorFactory;
87+
88+
/**
89+
* @var EmulatedAdminhtmlAreaProcessor
90+
*/
91+
private $emulatedAreaProcessor;
92+
8193
/**
8294
* @param ValidatorInterface $scopeValidator
8395
* @param ConfigSourceInterface $configSource
8496
* @param ConfigPathResolver $pathResolver
8597
* @param ValueProcessor $valueProcessor
98+
* @param PathValidatorFactory|null $pathValidatorFactory
99+
* @param EmulatedAdminhtmlAreaProcessor|null $emulatedAreaProcessor
86100
* @internal param ScopeConfigInterface $appConfig
87101
*/
88102
public function __construct(
89103
ValidatorInterface $scopeValidator,
90104
ConfigSourceInterface $configSource,
91105
ConfigPathResolver $pathResolver,
92-
ValueProcessor $valueProcessor
106+
ValueProcessor $valueProcessor,
107+
?PathValidatorFactory $pathValidatorFactory = null,
108+
?EmulatedAdminhtmlAreaProcessor $emulatedAreaProcessor = null
93109
) {
94110
parent::__construct();
95111
$this->scopeValidator = $scopeValidator;
96112
$this->configSource = $configSource;
97113
$this->pathResolver = $pathResolver;
98114
$this->valueProcessor = $valueProcessor;
115+
$this->pathValidatorFactory = $pathValidatorFactory
116+
?: ObjectManager::getInstance()->get(PathValidatorFactory::class);
117+
$this->emulatedAreaProcessor = $emulatedAreaProcessor
118+
?: ObjectManager::getInstance()->get(EmulatedAdminhtmlAreaProcessor::class);
99119
}
100120

101121
/**
@@ -146,17 +166,17 @@ protected function execute(InputInterface $input, OutputInterface $output)
146166
$this->scopeCode = $input->getOption(self::INPUT_OPTION_SCOPE_CODE);
147167
$this->inputPath = trim($input->getArgument(self::INPUT_ARGUMENT_PATH), '/');
148168

149-
$this->scopeValidator->isValid($this->scope, $this->scopeCode);
150-
$configPath = $this->pathResolver->resolve($this->inputPath, $this->scope, $this->scopeCode);
151-
$configValue = $this->configSource->get($configPath);
169+
$configValue = $this->emulatedAreaProcessor->process(function () {
170+
$this->scopeValidator->isValid($this->scope, $this->scopeCode);
171+
if ($this->inputPath) {
172+
$pathValidator = $this->pathValidatorFactory->create();
173+
$pathValidator->validate($this->inputPath);
174+
}
152175

153-
if ($configValue === null) {
154-
$output->writeln(sprintf(
155-
'<error>%s</error>',
156-
__('Configuration for path: "%1" doesn\'t exist', $this->inputPath)->render()
157-
));
158-
return Cli::RETURN_FAILURE;
159-
}
176+
$configPath = $this->pathResolver->resolve($this->inputPath, $this->scope, $this->scopeCode);
177+
178+
return $this->configSource->get($configPath);
179+
});
160180

161181
$this->outputResult($output, $configValue, $this->inputPath);
162182
return Cli::RETURN_SUCCESS;

app/code/Magento/Config/Test/Unit/App/Config/Source/RuntimeConfigSourceTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ public function configDataProvider(): array
262262
return [
263263
'config value 0' => ['default/test/option', ['test' => ['option' => 0]], '0'],
264264
'config value blank' => ['default/test/option', ['test' => ['option' => '']], ''],
265+
'config value null' => ['default/test/option', ['test' => ['option' => null]], ''],
265266
];
266267
}
267268
}

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

Lines changed: 114 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,41 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
67
declare(strict_types=1);
78

89
namespace Magento\Config\Test\Unit\Console\Command;
910

1011
use Magento\Config\Console\Command\ConfigShow\ValueProcessor;
1112
use Magento\Config\Console\Command\ConfigShowCommand;
13+
use Magento\Config\Console\Command\EmulatedAdminhtmlAreaProcessor;
1214
use Magento\Framework\App\Config\ConfigPathResolver;
1315
use Magento\Framework\App\Config\ConfigSourceInterface;
1416
use Magento\Framework\App\Scope\ValidatorInterface;
1517
use Magento\Framework\Console\Cli;
1618
use Magento\Framework\Exception\LocalizedException;
19+
use Magento\Config\Model\Config\PathValidatorFactory;
20+
use Magento\Config\Model\Config\PathValidator;
21+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
1722
use PHPUnit\Framework\MockObject\MockObject;
1823
use PHPUnit\Framework\TestCase;
1924
use Symfony\Component\Console\Tester\CommandTester;
2025

26+
/**
27+
* Test for \Magento\Config\Console\Command\ConfigShowCommand.
28+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
29+
*/
2130
class ConfigShowCommandTest extends TestCase
2231
{
32+
private const CONFIG_PATH = 'some/config/path';
33+
private const SCOPE = 'some/config/path';
34+
private const SCOPE_CODE = 'someScopeCode';
35+
36+
/**
37+
* @var ConfigShowCommand
38+
*/
39+
private $model;
40+
2341
/**
2442
* @var ValidatorInterface|MockObject
2543
*/
@@ -41,12 +59,22 @@ class ConfigShowCommandTest extends TestCase
4159
private $pathResolverMock;
4260

4361
/**
44-
* @var ConfigShowCommand
62+
* @var EmulatedAdminhtmlAreaProcessor|MockObject
63+
*/
64+
private $emulatedAreProcessorMock;
65+
66+
/**
67+
* @var PathValidator|MockObject
4568
*/
46-
private $command;
69+
private $pathValidatorMock;
4770

71+
/**
72+
* @inheritdoc
73+
*/
4874
protected function setUp(): void
4975
{
76+
$objectManager = new ObjectManager($this);
77+
5078
$this->valueProcessorMock = $this->getMockBuilder(ValueProcessor::class)
5179
->disableOriginalConstructor()
5280
->getMock();
@@ -57,40 +85,69 @@ protected function setUp(): void
5785
->getMockForAbstractClass();
5886
$this->configSourceMock = $this->getMockBuilder(ConfigSourceInterface::class)
5987
->getMockForAbstractClass();
88+
$this->pathValidatorMock = $this->getMockBuilder(PathValidator::class)
89+
->disableOriginalConstructor()
90+
->getMock();
91+
$pathValidatorFactoryMock = $this->getMockBuilder(PathValidatorFactory::class)
92+
->disableOriginalConstructor()
93+
->getMock();
94+
$pathValidatorFactoryMock->expects($this->atMost(1))
95+
->method('create')
96+
->willReturn($this->pathValidatorMock);
6097

61-
$this->command = new ConfigShowCommand(
62-
$this->scopeValidatorMock,
63-
$this->configSourceMock,
64-
$this->pathResolverMock,
65-
$this->valueProcessorMock
98+
$this->emulatedAreProcessorMock = $this->getMockBuilder(EmulatedAdminhtmlAreaProcessor::class)
99+
->disableOriginalConstructor()
100+
->getMock();
101+
102+
$this->model = $objectManager->getObject(
103+
ConfigShowCommand::class,
104+
[
105+
'scopeValidator' => $this->scopeValidatorMock,
106+
'configSource' => $this->configSourceMock,
107+
'pathResolver' => $this->pathResolverMock,
108+
'valueProcessor' => $this->valueProcessorMock,
109+
'pathValidatorFactory' => $pathValidatorFactoryMock,
110+
'emulatedAreaProcessor' => $this->emulatedAreProcessorMock,
111+
]
66112
);
67113
}
68114

69-
public function testExecute()
115+
/**
116+
* Test get config value
117+
*
118+
* @return void
119+
*/
120+
public function testExecute(): void
70121
{
71-
$configPath = 'some/config/path';
72122
$resolvedConfigPath = 'someScope/someScopeCode/some/config/path';
73-
$scope = 'someScope';
74-
$scopeCode = 'someScopeCode';
75123

76124
$this->scopeValidatorMock->expects($this->once())
77125
->method('isValid')
78-
->with($scope, $scopeCode)
126+
->with(self::SCOPE, self::SCOPE_CODE)
79127
->willReturn(true);
80128
$this->pathResolverMock->expects($this->once())
81129
->method('resolve')
82-
->with($configPath, $scope, $scopeCode)
130+
->with(self::CONFIG_PATH, self::SCOPE, self::SCOPE_CODE)
83131
->willReturn($resolvedConfigPath);
84132
$this->configSourceMock->expects($this->once())
85133
->method('get')
86134
->with($resolvedConfigPath)
87135
->willReturn('someValue');
88136
$this->valueProcessorMock->expects($this->once())
89137
->method('process')
90-
->with($scope, $scopeCode, 'someValue', $configPath)
138+
->with(self::SCOPE, self::SCOPE_CODE, 'someValue', self::CONFIG_PATH)
91139
->willReturn('someProcessedValue');
92-
93-
$tester = $this->getConfigShowCommandTester($configPath, $scope, $scopeCode);
140+
$this->emulatedAreProcessorMock->expects($this->once())
141+
->method('process')
142+
->willReturnCallback(function ($function) {
143+
return $function();
144+
});
145+
146+
$tester = $this->getConfigShowCommandTester(
147+
self::CONFIG_PATH,
148+
self::SCOPE,
149+
self::SCOPE_CODE
150+
);
94151

95152
$this->assertEquals(
96153
Cli::RETURN_SUCCESS,
@@ -102,18 +159,28 @@ public function testExecute()
102159
);
103160
}
104161

105-
public function testNotValidScopeOrScopeCode()
162+
/**
163+
* Test not valid scope or scope code
164+
*
165+
* @return void
166+
*/
167+
public function testNotValidScopeOrScopeCode(): void
106168
{
107-
$configPath = 'some/config/path';
108-
$scope = 'someScope';
109-
$scopeCode = 'someScopeCode';
110-
111169
$this->scopeValidatorMock->expects($this->once())
112170
->method('isValid')
113-
->with($scope, $scopeCode)
171+
->with(self::SCOPE, self::SCOPE_CODE)
114172
->willThrowException(new LocalizedException(__('error message')));
115-
116-
$tester = $this->getConfigShowCommandTester($configPath, $scope, $scopeCode);
173+
$this->emulatedAreProcessorMock->expects($this->once())
174+
->method('process')
175+
->willReturnCallback(function ($function) {
176+
return $function();
177+
});
178+
179+
$tester = $this->getConfigShowCommandTester(
180+
self::CONFIG_PATH,
181+
self::SCOPE,
182+
self::SCOPE_CODE
183+
);
117184

118185
$this->assertEquals(
119186
Cli::RETURN_FAILURE,
@@ -125,17 +192,35 @@ public function testNotValidScopeOrScopeCode()
125192
);
126193
}
127194

128-
public function testConfigPathNotExist()
195+
/**
196+
* Test get config value for not existed path.
197+
*
198+
* @return void
199+
*/
200+
public function testConfigPathNotExist(): void
129201
{
130-
$configPath = 'some/path';
131-
$tester = $this->getConfigShowCommandTester($configPath);
202+
$exception = new LocalizedException(
203+
__('The "%1" path doesn\'t exist. Verify and try again.', self::CONFIG_PATH)
204+
);
205+
206+
$this->pathValidatorMock->expects($this->once())
207+
->method('validate')
208+
->with(self::CONFIG_PATH)
209+
->willThrowException($exception);
210+
$this->emulatedAreProcessorMock->expects($this->once())
211+
->method('process')
212+
->willReturnCallback(function ($function) {
213+
return $function();
214+
});
215+
216+
$tester = $this->getConfigShowCommandTester(self::CONFIG_PATH);
132217

133218
$this->assertEquals(
134219
Cli::RETURN_FAILURE,
135220
$tester->getStatusCode()
136221
);
137222
$this->assertStringContainsString(
138-
__('Configuration for path: "%1" doesn\'t exist', $configPath)->render(),
223+
__('The "%1" path doesn\'t exist. Verify and try again.', self::CONFIG_PATH)->render(),
139224
$tester->getDisplay()
140225
);
141226
}
@@ -159,7 +244,7 @@ private function getConfigShowCommandTester($configPath, $scope = null, $scopeCo
159244
$arguments['--' . ConfigShowCommand::INPUT_OPTION_SCOPE_CODE] = $scopeCode;
160245
}
161246

162-
$tester = new CommandTester($this->command);
247+
$tester = new CommandTester($this->model);
163248
$tester->execute($arguments);
164249

165250
return $tester;

0 commit comments

Comments
 (0)