Skip to content

Commit 953b4eb

Browse files
author
Karpenko, Oleksandr
committed
MAGETWO-70571: There is no possibility to activate DEBUG logging in production mode
1 parent 20e58ef commit 953b4eb

File tree

8 files changed

+381
-13
lines changed

8 files changed

+381
-13
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Deploy\App\Mode;
7+
8+
/**
9+
* This class is responsible for providing configuration while switching application mode
10+
*/
11+
class ConfigProvider
12+
{
13+
/**
14+
* Configuration for combinations of $currentMode and $targetMode
15+
* For example:
16+
* [
17+
* 'developer' => [
18+
* 'production' => [
19+
* {{setting_path}} => {{setting_value}}
20+
* ]
21+
* ]
22+
* ]
23+
*
24+
* @var array
25+
*/
26+
private $config;
27+
28+
/**
29+
* @param array $config
30+
*/
31+
public function __construct(array $config = [])
32+
{
33+
$this->config = $config;
34+
}
35+
36+
/**
37+
* Provide configuration while switching from $currentMode to $targetMode
38+
* This method used in \Magento\Deploy\Model\Mode::setStoreMode
39+
*
40+
* For example: while switching from developer mode to production mode
41+
* need to turn off 'dev/debug/debug_logging' setting in this case method
42+
* will return array
43+
* [
44+
* {{setting_path}} => {{setting_value}}
45+
* ]
46+
*
47+
* @param string $currentMode
48+
* @param string $targetMode
49+
* @return array
50+
*/
51+
public function getConfigs($currentMode, $targetMode)
52+
{
53+
if (isset($this->config[$currentMode][$targetMode])) {
54+
return $this->config[$currentMode][$targetMode];
55+
}
56+
return [];
57+
}
58+
}

app/code/Magento/Deploy/Model/Mode.php

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
namespace Magento\Deploy\Model;
88

9+
use Magento\Deploy\App\Mode\ConfigProvider;
10+
use Magento\Framework\App\Config\ScopeConfigInterface;
911
use Magento\Framework\App\DeploymentConfig\Reader;
1012
use Magento\Framework\App\DeploymentConfig\Writer;
1113
use Magento\Framework\App\Filesystem\DirectoryList;
@@ -14,6 +16,8 @@
1416
use Magento\Framework\Config\File\ConfigFilePool;
1517
use Symfony\Component\Console\Input\InputInterface;
1618
use Symfony\Component\Console\Output\OutputInterface;
19+
use Magento\Config\Console\Command\ConfigSet\ProcessorFacadeFactory;
20+
use Magento\Config\Console\Command\EmulatedAdminhtmlAreaProcessor;
1721

1822
/**
1923
* A class to manage Magento modes
@@ -43,33 +47,66 @@ class Mode
4347
*/
4448
private $reader;
4549

50+
/**
51+
* @var MaintenanceMode
52+
*/
53+
private $maintenanceMode;
54+
4655
/**
4756
* @var Filesystem
4857
*/
4958
private $filesystem;
5059

60+
/**
61+
* @var ConfigProvider
62+
*/
63+
private $configProvider;
64+
65+
/**
66+
* The factory for processor facade.
67+
*
68+
* @var ProcessorFacadeFactory
69+
*/
70+
private $processorFacadeFactory;
71+
72+
/**
73+
* Emulator adminhtml area for CLI command.
74+
*
75+
* @var EmulatedAdminhtmlAreaProcessor
76+
*/
77+
private $emulatedAreaProcessor;
78+
5179
/**
5280
* @param InputInterface $input
5381
* @param OutputInterface $output
5482
* @param Writer $writer
5583
* @param Reader $reader
5684
* @param MaintenanceMode $maintenanceMode
5785
* @param Filesystem $filesystem
86+
* @param ConfigProvider $configProvider
87+
* @param ProcessorFacadeFactory $processorFacadeFactory
88+
* @param EmulatedAdminhtmlAreaProcessor $emulatedAreaProcessor
5889
*/
5990
public function __construct(
6091
InputInterface $input,
6192
OutputInterface $output,
6293
Writer $writer,
6394
Reader $reader,
6495
MaintenanceMode $maintenanceMode,
65-
Filesystem $filesystem
96+
Filesystem $filesystem,
97+
ConfigProvider $configProvider,
98+
ProcessorFacadeFactory $processorFacadeFactory,
99+
EmulatedAdminhtmlAreaProcessor $emulatedAreaProcessor
66100
) {
67101
$this->input = $input;
68102
$this->output = $output;
69103
$this->writer = $writer;
70104
$this->reader = $reader;
71105
$this->maintenanceMode = $maintenanceMode;
72106
$this->filesystem = $filesystem;
107+
$this->configProvider = $configProvider;
108+
$this->processorFacadeFactory = $processorFacadeFactory;
109+
$this->emulatedAreaProcessor = $emulatedAreaProcessor;
73110
}
74111

75112
/**
@@ -134,6 +171,7 @@ public function getMode()
134171
*/
135172
protected function setStoreMode($mode)
136173
{
174+
$this->saveAppConfigs($mode);
137175
$data = [
138176
ConfigFilePool::APP_ENV => [
139177
State::PARAM_MODE => $mode
@@ -142,6 +180,29 @@ protected function setStoreMode($mode)
142180
$this->writer->saveConfig($data);
143181
}
144182

183+
/**
184+
* Save application configs while switching mode
185+
*
186+
* @param string $mode
187+
* @return void
188+
*/
189+
private function saveAppConfigs($mode)
190+
{
191+
$configs = $this->configProvider->getConfigs($this->getMode(), $mode);
192+
foreach ($configs as $path => $value) {
193+
$this->emulatedAreaProcessor->process(function () use ($path, $value) {
194+
$this->processorFacadeFactory->create()->process(
195+
$path,
196+
$value,
197+
ScopeConfigInterface::SCOPE_TYPE_DEFAULT,
198+
null,
199+
true
200+
);
201+
});
202+
$this->output->writeln('Config "' . $path . ' = ' . $value . '" has been saved.');
203+
}
204+
}
205+
145206
/**
146207
* Enable maintenance mode
147208
*
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Deploy\Test\Unit\App\Mode;
7+
8+
use Magento\Deploy\App\Mode\ConfigProvider;
9+
10+
class ConfigProviderTest extends \PHPUnit_Framework_TestCase
11+
{
12+
public function testGetConfigs()
13+
{
14+
$expectedValue = [
15+
'{{setting_path}}' => '{{setting_value}}'
16+
];
17+
$configProvider = new ConfigProvider(
18+
[
19+
'developer' => [
20+
'production' => $expectedValue
21+
]
22+
]
23+
);
24+
$this->assertEquals($expectedValue, $configProvider->getConfigs('developer', 'production'));
25+
$this->assertEquals([], $configProvider->getConfigs('undefined', 'production'));
26+
}
27+
}

app/code/Magento/Deploy/Test/Unit/Model/ModeTest.php

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@
55
*/
66
namespace Magento\Deploy\Test\Unit\Model;
77

8+
use Magento\Config\Console\Command\ConfigSet\ProcessorFacadeFactory;
9+
use Magento\Config\Console\Command\ConfigSet\ProcessorFacade;
10+
use Magento\Config\Console\Command\EmulatedAdminhtmlAreaProcessor;
11+
use Magento\Deploy\App\Mode\ConfigProvider;
812
use Magento\Deploy\Model\Filesystem;
913
use Magento\Deploy\Model\Mode;
14+
use Magento\Framework\App\Config\ScopeConfigInterface;
1015
use Magento\Framework\App\DeploymentConfig\Reader;
1116
use Magento\Framework\App\DeploymentConfig\Writer;
1217
use Magento\Framework\App\MaintenanceMode;
@@ -17,6 +22,7 @@
1722

1823
/**
1924
* @inheritdoc
25+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2026
*/
2127
class ModeTest extends \PHPUnit_Framework_TestCase
2228
{
@@ -55,6 +61,26 @@ class ModeTest extends \PHPUnit_Framework_TestCase
5561
*/
5662
private $filesystemMock;
5763

64+
/**
65+
* @var ConfigProvider|Mock
66+
*/
67+
private $configProvider;
68+
69+
/**
70+
* @var ProcessorFacadeFactory|Mock
71+
*/
72+
private $processorFacadeFactory;
73+
74+
/**
75+
* @var ProcessorFacade|Mock
76+
*/
77+
private $processorFacade;
78+
79+
/**
80+
* @var EmulatedAdminhtmlAreaProcessor|Mock
81+
*/
82+
private $emulatedAreaProcessor;
83+
5884
protected function setUp()
5985
{
6086
$this->inputMock = $this->getMockBuilder(InputInterface::class)
@@ -73,14 +99,30 @@ protected function setUp()
7399
$this->filesystemMock = $this->getMockBuilder(Filesystem::class)
74100
->disableOriginalConstructor()
75101
->getMock();
102+
$this->configProvider = $this->getMockBuilder(ConfigProvider::class)
103+
->disableOriginalConstructor()
104+
->getMock();
105+
$this->processorFacadeFactory = $this->getMockBuilder(ProcessorFacadeFactory::class)
106+
->disableOriginalConstructor()
107+
->setMethods(['create'])
108+
->getMockForAbstractClass();
109+
$this->processorFacade = $this->getMockBuilder(ProcessorFacade::class)
110+
->disableOriginalConstructor()
111+
->getMock();
112+
$this->emulatedAreaProcessor = $this->getMockBuilder(EmulatedAdminhtmlAreaProcessor::class)
113+
->disableOriginalConstructor()
114+
->getMock();
76115

77116
$this->model = new Mode(
78117
$this->inputMock,
79118
$this->outputMock,
80119
$this->writerMock,
81120
$this->readerMock,
82121
$this->maintenanceMock,
83-
$this->filesystemMock
122+
$this->filesystemMock,
123+
$this->configProvider,
124+
$this->processorFacadeFactory,
125+
$this->emulatedAreaProcessor
84126
);
85127
}
86128

@@ -96,4 +138,41 @@ public function testGetMode()
96138
$this->assertSame(null, $this->model->getMode());
97139
$this->assertSame(State::MODE_DEVELOPER, $this->model->getMode());
98140
}
141+
142+
public function testEnableProductionModeMinimal()
143+
{
144+
$this->readerMock->expects($this->once())
145+
->method('load')
146+
->willReturn([State::PARAM_MODE => State::MODE_DEVELOPER]);
147+
$this->configProvider->expects($this->once())
148+
->method('getConfigs')
149+
->with('developer', 'production')
150+
->willReturn([
151+
'dev/debug/debug_logging' => 0
152+
]);
153+
$this->emulatedAreaProcessor->expects($this->once())
154+
->method('process')
155+
->willReturnCallback(function (\Closure $closure) {
156+
return $closure->call($this->model);
157+
});
158+
159+
$this->processorFacadeFactory->expects($this->once())
160+
->method('create')
161+
->willReturn($this->processorFacade);
162+
$this->processorFacade
163+
->expects($this->once())
164+
->method('process')
165+
->with(
166+
'dev/debug/debug_logging',
167+
0,
168+
ScopeConfigInterface::SCOPE_TYPE_DEFAULT,
169+
null,
170+
true
171+
);
172+
$this->outputMock->expects($this->once())
173+
->method('writeln')
174+
->with('Config "dev/debug/debug_logging = 0" has been saved.');
175+
176+
$this->model->enableProductionModeMinimal();
177+
}
99178
}

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,15 @@
7070
</argument>
7171
</arguments>
7272
</type>
73+
<type name="Magento\Deploy\App\Mode\ConfigProvider">
74+
<arguments>
75+
<argument name="config" xsi:type="array">
76+
<item name="developer" xsi:type="array">
77+
<item name="production" xsi:type="array">
78+
<item name="dev/debug/debug_logging" xsi:type="string">0</item>
79+
</item>
80+
</item>
81+
</argument>
82+
</arguments>
83+
</type>
7384
</config>

app/code/Magento/Developer/Model/Logger/Handler/Debug.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ public function isHandling(array $record)
6060
if ($this->deploymentConfig->isAvailable()) {
6161
return
6262
parent::isHandling($record)
63-
&& $this->state->getMode() !== State::MODE_PRODUCTION
6463
&& $this->scopeConfig->getValue('dev/debug/debug_logging', ScopeInterface::SCOPE_STORE);
6564
}
6665

app/code/Magento/Developer/Test/Unit/Model/Logger/Handler/DebugTest.php

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,8 @@ public function testHandle()
8585
$this->deploymentConfigMock->expects($this->once())
8686
->method('isAvailable')
8787
->willReturn(true);
88-
$this->stateMock->expects($this->once())
89-
->method('getMode')
90-
->willReturn(State::MODE_DEVELOPER);
88+
$this->stateMock->expects($this->never())
89+
->method('getMode');
9190
$this->scopeConfigMock->expects($this->once())
9291
->method('getValue')
9392
->with('dev/debug/debug_logging', ScopeInterface::SCOPE_STORE, null)
@@ -101,10 +100,9 @@ public function testHandleDisabledByProduction()
101100
$this->deploymentConfigMock->expects($this->once())
102101
->method('isAvailable')
103102
->willReturn(true);
104-
$this->stateMock->expects($this->once())
105-
->method('getMode')
106-
->willReturn(State::MODE_PRODUCTION);
107-
$this->scopeConfigMock->expects($this->never())
103+
$this->stateMock->expects($this->never())
104+
->method('getMode');
105+
$this->scopeConfigMock->expects($this->once())
108106
->method('getValue');
109107

110108
$this->assertFalse($this->model->isHandling(['formatted' => false, 'level' => Logger::DEBUG]));
@@ -115,9 +113,8 @@ public function testHandleDisabledByConfig()
115113
$this->deploymentConfigMock->expects($this->once())
116114
->method('isAvailable')
117115
->willReturn(true);
118-
$this->stateMock->expects($this->once())
119-
->method('getMode')
120-
->willReturn(State::MODE_DEVELOPER);
116+
$this->stateMock->expects($this->never())
117+
->method('getMode');
121118
$this->scopeConfigMock->expects($this->once())
122119
->method('getValue')
123120
->with('dev/debug/debug_logging', ScopeInterface::SCOPE_STORE, null)

0 commit comments

Comments
 (0)