diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/widget/viewed/sidebar.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/widget/viewed/sidebar.phtml
index 456032ebcbc24..1c4ad3105a2b5 100644
--- a/app/code/Magento/Catalog/view/frontend/templates/product/widget/viewed/sidebar.phtml
+++ b/app/code/Magento/Catalog/view/frontend/templates/product/widget/viewed/sidebar.phtml
@@ -17,10 +17,8 @@
'listing' => [
'displayMode' => 'grid'
],
- 'column' => [
- 'image' => [
- 'imageCode' => 'recently_viewed_products_images_names_widget'
- ]
+ 'image' => [
+ 'imageCode' => 'recently_viewed_products_images_names_widget'
]
]
);
diff --git a/app/code/Magento/Deploy/App/Mode/ConfigProvider.php b/app/code/Magento/Deploy/App/Mode/ConfigProvider.php
new file mode 100644
index 0000000000000..142e3fe819438
--- /dev/null
+++ b/app/code/Magento/Deploy/App/Mode/ConfigProvider.php
@@ -0,0 +1,58 @@
+ [
+ * 'production' => [
+ * {{setting_path}} => {{setting_value}}
+ * ]
+ * ]
+ * ]
+ *
+ * @var array
+ */
+ private $config;
+
+ /**
+ * @param array $config
+ */
+ public function __construct(array $config = [])
+ {
+ $this->config = $config;
+ }
+
+ /**
+ * Provide configuration while switching from $currentMode to $targetMode
+ * This method used in \Magento\Deploy\Model\Mode::setStoreMode
+ *
+ * For example: while switching from developer mode to production mode
+ * need to turn off 'dev/debug/debug_logging' setting in this case method
+ * will return array
+ * [
+ * {{setting_path}} => {{setting_value}}
+ * ]
+ *
+ * @param string $currentMode
+ * @param string $targetMode
+ * @return array
+ */
+ public function getConfigs($currentMode, $targetMode)
+ {
+ if (isset($this->config[$currentMode][$targetMode])) {
+ return $this->config[$currentMode][$targetMode];
+ }
+ return [];
+ }
+}
diff --git a/app/code/Magento/Deploy/Model/Mode.php b/app/code/Magento/Deploy/Model/Mode.php
index 75de873f71e44..ba3e8652fd443 100644
--- a/app/code/Magento/Deploy/Model/Mode.php
+++ b/app/code/Magento/Deploy/Model/Mode.php
@@ -6,6 +6,8 @@
namespace Magento\Deploy\Model;
+use Magento\Deploy\App\Mode\ConfigProvider;
+use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\DeploymentConfig\Reader;
use Magento\Framework\App\DeploymentConfig\Writer;
use Magento\Framework\App\Filesystem\DirectoryList;
@@ -14,7 +16,10 @@
use Magento\Framework\Config\File\ConfigFilePool;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
+use Magento\Config\Console\Command\ConfigSet\ProcessorFacadeFactory;
+use Magento\Config\Console\Command\EmulatedAdminhtmlAreaProcessor;
use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\App\ObjectManager;
/**
* A class to manage Magento modes
@@ -44,11 +49,35 @@ class Mode
*/
private $reader;
+ /**
+ * @var MaintenanceMode
+ */
+ private $maintenanceMode;
+
/**
* @var Filesystem
*/
private $filesystem;
+ /**
+ * @var ConfigProvider
+ */
+ private $configProvider;
+
+ /**
+ * The factory for processor facade.
+ *
+ * @var ProcessorFacadeFactory
+ */
+ private $processorFacadeFactory;
+
+ /**
+ * Emulator adminhtml area for CLI command.
+ *
+ * @var EmulatedAdminhtmlAreaProcessor
+ */
+ private $emulatedAreaProcessor;
+
/**
* @param InputInterface $input
* @param OutputInterface $output
@@ -56,6 +85,9 @@ class Mode
* @param Reader $reader
* @param MaintenanceMode $maintenanceMode
* @param Filesystem $filesystem
+ * @param ConfigProvider $configProvider
+ * @param ProcessorFacadeFactory $processorFacadeFactory
+ * @param EmulatedAdminhtmlAreaProcessor $emulatedAreaProcessor
*/
public function __construct(
InputInterface $input,
@@ -63,7 +95,10 @@ public function __construct(
Writer $writer,
Reader $reader,
MaintenanceMode $maintenanceMode,
- Filesystem $filesystem
+ Filesystem $filesystem,
+ ConfigProvider $configProvider = null,
+ ProcessorFacadeFactory $processorFacadeFactory = null,
+ EmulatedAdminhtmlAreaProcessor $emulatedAreaProcessor = null
) {
$this->input = $input;
$this->output = $output;
@@ -71,6 +106,13 @@ public function __construct(
$this->reader = $reader;
$this->maintenanceMode = $maintenanceMode;
$this->filesystem = $filesystem;
+
+ $this->configProvider =
+ $configProvider ?: ObjectManager::getInstance()->get(ConfigProvider::class);
+ $this->processorFacadeFactory =
+ $processorFacadeFactory ?: ObjectManager::getInstance()->get(ProcessorFacadeFactory::class);
+ $this->emulatedAreaProcessor =
+ $emulatedAreaProcessor ?: ObjectManager::getInstance()->get(EmulatedAdminhtmlAreaProcessor::class);
}
/**
@@ -145,6 +187,7 @@ public function getMode()
*/
protected function setStoreMode($mode)
{
+ $this->saveAppConfigs($mode);
$data = [
ConfigFilePool::APP_ENV => [
State::PARAM_MODE => $mode
@@ -153,6 +196,29 @@ protected function setStoreMode($mode)
$this->writer->saveConfig($data);
}
+ /**
+ * Save application configs while switching mode
+ *
+ * @param string $mode
+ * @return void
+ */
+ private function saveAppConfigs($mode)
+ {
+ $configs = $this->configProvider->getConfigs($this->getMode(), $mode);
+ foreach ($configs as $path => $value) {
+ $this->emulatedAreaProcessor->process(function () use ($path, $value) {
+ $this->processorFacadeFactory->create()->process(
+ $path,
+ $value,
+ ScopeConfigInterface::SCOPE_TYPE_DEFAULT,
+ null,
+ true
+ );
+ });
+ $this->output->writeln('Config "' . $path . ' = ' . $value . '" has been saved.');
+ }
+ }
+
/**
* Enable maintenance mode
*
diff --git a/app/code/Magento/Deploy/Test/Unit/App/Mode/ConfigProviderTest.php b/app/code/Magento/Deploy/Test/Unit/App/Mode/ConfigProviderTest.php
new file mode 100644
index 0000000000000..ffb5c593f9e7e
--- /dev/null
+++ b/app/code/Magento/Deploy/Test/Unit/App/Mode/ConfigProviderTest.php
@@ -0,0 +1,27 @@
+ '{{setting_value}}'
+ ];
+ $configProvider = new ConfigProvider(
+ [
+ 'developer' => [
+ 'production' => $expectedValue
+ ]
+ ]
+ );
+ $this->assertEquals($expectedValue, $configProvider->getConfigs('developer', 'production'));
+ $this->assertEquals([], $configProvider->getConfigs('undefined', 'production'));
+ }
+}
diff --git a/app/code/Magento/Deploy/Test/Unit/Model/ModeTest.php b/app/code/Magento/Deploy/Test/Unit/Model/ModeTest.php
index 52ee9f1e65a7b..f80c6cb69f1a9 100644
--- a/app/code/Magento/Deploy/Test/Unit/Model/ModeTest.php
+++ b/app/code/Magento/Deploy/Test/Unit/Model/ModeTest.php
@@ -5,8 +5,13 @@
*/
namespace Magento\Deploy\Test\Unit\Model;
+use Magento\Config\Console\Command\ConfigSet\ProcessorFacadeFactory;
+use Magento\Config\Console\Command\ConfigSet\ProcessorFacade;
+use Magento\Config\Console\Command\EmulatedAdminhtmlAreaProcessor;
+use Magento\Deploy\App\Mode\ConfigProvider;
use Magento\Deploy\Model\Filesystem;
use Magento\Deploy\Model\Mode;
+use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\DeploymentConfig\Reader;
use Magento\Framework\App\DeploymentConfig\Writer;
use Magento\Framework\App\MaintenanceMode;
@@ -19,6 +24,7 @@
/**
* @inheritdoc
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class ModeTest extends \PHPUnit\Framework\TestCase
{
@@ -57,6 +63,26 @@ class ModeTest extends \PHPUnit\Framework\TestCase
*/
private $filesystemMock;
+ /**
+ * @var ConfigProvider|Mock
+ */
+ private $configProvider;
+
+ /**
+ * @var ProcessorFacadeFactory|Mock
+ */
+ private $processorFacadeFactory;
+
+ /**
+ * @var ProcessorFacade|Mock
+ */
+ private $processorFacade;
+
+ /**
+ * @var EmulatedAdminhtmlAreaProcessor|Mock
+ */
+ private $emulatedAreaProcessor;
+
protected function setUp()
{
$this->inputMock = $this->getMockBuilder(InputInterface::class)
@@ -75,6 +101,19 @@ protected function setUp()
$this->filesystemMock = $this->getMockBuilder(Filesystem::class)
->disableOriginalConstructor()
->getMock();
+ $this->configProvider = $this->getMockBuilder(ConfigProvider::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->processorFacadeFactory = $this->getMockBuilder(ProcessorFacadeFactory::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['create'])
+ ->getMockForAbstractClass();
+ $this->processorFacade = $this->getMockBuilder(ProcessorFacade::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->emulatedAreaProcessor = $this->getMockBuilder(EmulatedAdminhtmlAreaProcessor::class)
+ ->disableOriginalConstructor()
+ ->getMock();
$this->model = new Mode(
$this->inputMock,
@@ -82,7 +121,10 @@ protected function setUp()
$this->writerMock,
$this->readerMock,
$this->maintenanceMock,
- $this->filesystemMock
+ $this->filesystemMock,
+ $this->configProvider,
+ $this->processorFacadeFactory,
+ $this->emulatedAreaProcessor
);
}
@@ -112,6 +154,9 @@ public function testEnableProductionMode()
State::PARAM_MODE => State::MODE_DEVELOPER,
],
];
+ $this->configProvider->expects($this->any())
+ ->method('getConfigs')
+ ->willReturn([]);
$this->writerMock->expects($this->once())
->method("saveConfig")
->willReturnCallback(function ($data) use (&$dataStorage) {
@@ -145,6 +190,12 @@ public function testEnableDeveloperModeOnFail()
State::PARAM_MODE => State::MODE_DEVELOPER,
],
];
+ $this->readerMock->expects($this->any())
+ ->method('load')
+ ->willReturn([State::PARAM_MODE => State::MODE_DEVELOPER]);
+ $this->configProvider->expects($this->any())
+ ->method('getConfigs')
+ ->willReturn([]);
$this->writerMock->expects($this->exactly(2))
->method("saveConfig")
->withConsecutive(
@@ -165,4 +216,41 @@ public function testEnableDeveloperModeOnFail()
$this->model->enableProductionMode();
$this->assertEquals(State::MODE_PRODUCTION, $mode);
}
+
+ public function testEnableProductionModeMinimal()
+ {
+ $this->readerMock->expects($this->once())
+ ->method('load')
+ ->willReturn([State::PARAM_MODE => State::MODE_DEVELOPER]);
+ $this->configProvider->expects($this->once())
+ ->method('getConfigs')
+ ->with('developer', 'production')
+ ->willReturn([
+ 'dev/debug/debug_logging' => 0
+ ]);
+ $this->emulatedAreaProcessor->expects($this->once())
+ ->method('process')
+ ->willReturnCallback(function (\Closure $closure) {
+ return $closure->call($this->model);
+ });
+
+ $this->processorFacadeFactory->expects($this->once())
+ ->method('create')
+ ->willReturn($this->processorFacade);
+ $this->processorFacade
+ ->expects($this->once())
+ ->method('process')
+ ->with(
+ 'dev/debug/debug_logging',
+ 0,
+ ScopeConfigInterface::SCOPE_TYPE_DEFAULT,
+ null,
+ true
+ );
+ $this->outputMock->expects($this->once())
+ ->method('writeln')
+ ->with('Config "dev/debug/debug_logging = 0" has been saved.');
+
+ $this->model->enableProductionModeMinimal();
+ }
}
diff --git a/app/code/Magento/Deploy/etc/di.xml b/app/code/Magento/Deploy/etc/di.xml
index 52a2503a13678..e47fca3a6b946 100644
--- a/app/code/Magento/Deploy/etc/di.xml
+++ b/app/code/Magento/Deploy/etc/di.xml
@@ -70,4 +70,15 @@
+
+
+
+ -
+
-
+
- 0
+
+
+
+
+
diff --git a/app/code/Magento/Developer/Model/Logger/Handler/Debug.php b/app/code/Magento/Developer/Model/Logger/Handler/Debug.php
index ec5aff6891c11..9bfee42fa6a83 100644
--- a/app/code/Magento/Developer/Model/Logger/Handler/Debug.php
+++ b/app/code/Magento/Developer/Model/Logger/Handler/Debug.php
@@ -60,7 +60,6 @@ public function isHandling(array $record)
if ($this->deploymentConfig->isAvailable()) {
return
parent::isHandling($record)
- && $this->state->getMode() !== State::MODE_PRODUCTION
&& $this->scopeConfig->getValue('dev/debug/debug_logging', ScopeInterface::SCOPE_STORE);
}
diff --git a/app/code/Magento/Developer/Test/Unit/Model/Logger/Handler/DebugTest.php b/app/code/Magento/Developer/Test/Unit/Model/Logger/Handler/DebugTest.php
index 8b0136248fcf1..c116775d582bb 100644
--- a/app/code/Magento/Developer/Test/Unit/Model/Logger/Handler/DebugTest.php
+++ b/app/code/Magento/Developer/Test/Unit/Model/Logger/Handler/DebugTest.php
@@ -85,9 +85,8 @@ public function testHandle()
$this->deploymentConfigMock->expects($this->once())
->method('isAvailable')
->willReturn(true);
- $this->stateMock->expects($this->once())
- ->method('getMode')
- ->willReturn(State::MODE_DEVELOPER);
+ $this->stateMock->expects($this->never())
+ ->method('getMode');
$this->scopeConfigMock->expects($this->once())
->method('getValue')
->with('dev/debug/debug_logging', ScopeInterface::SCOPE_STORE, null)
@@ -101,10 +100,9 @@ public function testHandleDisabledByProduction()
$this->deploymentConfigMock->expects($this->once())
->method('isAvailable')
->willReturn(true);
- $this->stateMock->expects($this->once())
- ->method('getMode')
- ->willReturn(State::MODE_PRODUCTION);
- $this->scopeConfigMock->expects($this->never())
+ $this->stateMock->expects($this->never())
+ ->method('getMode');
+ $this->scopeConfigMock->expects($this->once())
->method('getValue');
$this->assertFalse($this->model->isHandling(['formatted' => false, 'level' => Logger::DEBUG]));
@@ -115,9 +113,8 @@ public function testHandleDisabledByConfig()
$this->deploymentConfigMock->expects($this->once())
->method('isAvailable')
->willReturn(true);
- $this->stateMock->expects($this->once())
- ->method('getMode')
- ->willReturn(State::MODE_DEVELOPER);
+ $this->stateMock->expects($this->never())
+ ->method('getMode');
$this->scopeConfigMock->expects($this->once())
->method('getValue')
->with('dev/debug/debug_logging', ScopeInterface::SCOPE_STORE, null)
diff --git a/dev/tests/integration/testsuite/Magento/Developer/Model/Logger/Handler/DebugTest.php b/dev/tests/integration/testsuite/Magento/Developer/Model/Logger/Handler/DebugTest.php
new file mode 100644
index 0000000000000..71e61162d29c9
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Developer/Model/Logger/Handler/DebugTest.php
@@ -0,0 +1,166 @@
+create(Filesystem::class);
+ $this->etcDirectory = $filesystem->getDirectoryWrite(DirectoryList::CONFIG);
+ $this->etcDirectory->copyFile('env.php', 'env.base.php');
+
+ $this->inputMock = $this->getMockBuilder(InputInterface::class)
+ ->getMockForAbstractClass();
+ $this->outputMock = $this->getMockBuilder(OutputInterface::class)
+ ->getMockForAbstractClass();
+ $this->logger = Bootstrap::getObjectManager()->get(Monolog::class);
+ $this->mode = Bootstrap::getObjectManager()->create(
+ Mode::class,
+ [
+ 'input' => $this->inputMock,
+ 'output' => $this->outputMock
+ ]
+ );
+ $this->configSetCommand = Bootstrap::getObjectManager()->create(ConfigSetCommand::class);
+ $this->appConfig = Bootstrap::getObjectManager()->create(Config::class);
+
+ // Preconditions
+ $this->mode->enableDeveloperMode();
+ $this->enableDebugging();
+ if (file_exists($this->getDebuggerLogPath())) {
+ unlink($this->getDebuggerLogPath());
+ }
+ }
+
+ public function tearDown()
+ {
+ $this->etcDirectory->delete('env.php');
+ $this->etcDirectory->renameFile('env.base.php', 'env.php');
+ }
+
+ private function enableDebugging()
+ {
+ $this->inputMock = $this->getMockBuilder(InputInterface::class)
+ ->getMockForAbstractClass();
+ $this->outputMock = $this->getMockBuilder(OutputInterface::class)
+ ->getMockForAbstractClass();
+ $this->inputMock->expects($this->exactly(2))
+ ->method('getArgument')
+ ->withConsecutive([ConfigSetCommand::ARG_PATH], [ConfigSetCommand::ARG_VALUE])
+ ->willReturnOnConsecutiveCalls('dev/debug/debug_logging', 1);
+ $this->inputMock->expects($this->exactly(3))
+ ->method('getOption')
+ ->withConsecutive(
+ [ConfigSetCommand::OPTION_SCOPE],
+ [ConfigSetCommand::OPTION_SCOPE_CODE],
+ [ConfigSetCommand::OPTION_LOCK]
+ )
+ ->willReturnOnConsecutiveCalls(
+ ScopeConfigInterface::SCOPE_TYPE_DEFAULT,
+ null,
+ true
+ );
+ $this->outputMock->expects($this->once())
+ ->method('writeln')
+ ->with('Value was saved and locked.');
+ $this->assertFalse((bool)$this->configSetCommand->run($this->inputMock, $this->outputMock));
+ }
+
+ public function testDebugInProductionMode()
+ {
+ $message = 'test message';
+
+ $this->mode->enableProductionModeMinimal();
+ $this->logger->debug($message);
+ $this->assertFileNotExists($this->getDebuggerLogPath());
+ $this->assertFalse((bool)$this->appConfig->getValue('dev/debug/debug_logging'));
+
+ $this->enableDebugging();
+ $this->logger->debug($message);
+
+ $this->assertFileExists($this->getDebuggerLogPath());
+ $this->assertContains($message, file_get_contents($this->getDebuggerLogPath()));
+ }
+
+ /**
+ * @return bool|string
+ */
+ private function getDebuggerLogPath()
+ {
+ foreach ($this->logger->getHandlers() as $handler) {
+ if ($handler instanceof Debug) {
+ return $handler->getUrl();
+ }
+ }
+ return false;
+ }
+}