diff --git a/app/code/Magento/Catalog/Block/Product/ListProduct.php b/app/code/Magento/Catalog/Block/Product/ListProduct.php
index db592353da44a..33488ee1c93c4 100644
--- a/app/code/Magento/Catalog/Block/Product/ListProduct.php
+++ b/app/code/Magento/Catalog/Block/Product/ListProduct.php
@@ -334,13 +334,21 @@ public function prepareSortableFieldsByCategory($category)
public function getIdentities()
{
$identities = [];
- foreach ($this->_getProductCollection() as $item) {
- $identities = array_merge($identities, $item->getIdentities());
- }
+
$category = $this->getLayer()->getCurrentCategory();
if ($category) {
$identities[] = Product::CACHE_PRODUCT_CATEGORY_TAG . '_' . $category->getId();
}
+
+ //Check if category page shows only static block (No products)
+ if ($category->getData('display_mode') == Category::DM_PAGE) {
+ return $identities;
+ }
+
+ foreach ($this->_getProductCollection() as $item) {
+ $identities = array_merge($identities, $item->getIdentities());
+ }
+
return $identities;
}
diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Product/ListProductTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Product/ListProductTest.php
index b42357db89041..fe07f69e8046f 100644
--- a/app/code/Magento/Catalog/Test/Unit/Block/Product/ListProductTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Block/Product/ListProductTest.php
@@ -192,7 +192,7 @@ public function testGetIdentities()
->will($this->returnValue($this->toolbarMock));
$this->assertEquals(
- [$productTag, $categoryTag],
+ [$categoryTag, $productTag],
$this->block->getIdentities()
);
$this->assertEquals(
diff --git a/app/code/Magento/Customer/Model/Plugin/CustomerFlushFormKey.php b/app/code/Magento/Customer/Model/Plugin/CustomerFlushFormKey.php
new file mode 100644
index 0000000000000..b7b462b3cc317
--- /dev/null
+++ b/app/code/Magento/Customer/Model/Plugin/CustomerFlushFormKey.php
@@ -0,0 +1,53 @@
+session = $session;
+ $this->dataFormKey = $dataFormKey;
+ }
+
+ /**
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ * @param FlushFormKey $subject
+ * @param callable $proceed
+ * @param $args
+ */
+ public function aroundExecute(FlushFormKey $subject, callable $proceed, ...$args)
+ {
+ $currentFormKey = $this->dataFormKey->getFormKey();
+ $proceed(...$args);
+ $beforeParams = $this->session->getBeforeRequestParams();
+ if ($beforeParams['form_key'] == $currentFormKey) {
+ $beforeParams['form_key'] = $this->dataFormKey->getFormKey();
+ $this->session->setBeforeRequestParams($beforeParams);
+ }
+ }
+}
diff --git a/app/code/Magento/Customer/Test/Unit/Model/Plugin/CustomerFlushFormKeyTest.php b/app/code/Magento/Customer/Test/Unit/Model/Plugin/CustomerFlushFormKeyTest.php
new file mode 100644
index 0000000000000..1b30fb5c60e9c
--- /dev/null
+++ b/app/code/Magento/Customer/Test/Unit/Model/Plugin/CustomerFlushFormKeyTest.php
@@ -0,0 +1,105 @@
+cookieFormKey = $this->getMockBuilder(CookieFormKey::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ /** @var DataFormKey | MockObject */
+ $this->dataFormKey = $this->getMockBuilder(DataFormKey::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ /** @var Session | MockObject */
+ $this->customerSession = $this->getMockBuilder(Session::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getBeforeRequestParams', 'setBeforeRequestParams'])
+ ->getMock();
+ }
+
+ /**
+ * @dataProvider aroundFlushFormKeyProvider
+ * @param $beforeFormKey
+ * @param $currentFormKey
+ * @param $getFormKeyTimes
+ * @param $setBeforeParamsTimes
+ */
+ public function testAroundFlushFormKey(
+ $beforeFormKey,
+ $currentFormKey,
+ $getFormKeyTimes,
+ $setBeforeParamsTimes
+ ) {
+ $observerDto = new Observer();
+ $observer = new FlushFormKey($this->cookieFormKey, $this->dataFormKey);
+ $plugin = new CustomerFlushFormKey($this->customerSession, $this->dataFormKey);
+
+ $beforeParams['form_key'] = $beforeFormKey;
+
+ $this->dataFormKey->expects($this->exactly($getFormKeyTimes))
+ ->method('getFormKey')
+ ->willReturn($currentFormKey);
+
+ $this->customerSession->expects($this->once())
+ ->method('getBeforeRequestParams')
+ ->willReturn($beforeParams);
+
+ $this->customerSession->expects($this->exactly($setBeforeParamsTimes))
+ ->method('setBeforeRequestParams')
+ ->with($beforeParams);
+
+ $proceed = function ($observerDto) use ($observer) {
+ return $observer->execute($observerDto);
+ };
+
+ $plugin->aroundExecute($observer, $proceed, $observerDto);
+ }
+
+ /**
+ * Data provider for testAroundFlushFormKey
+ *
+ * @return array
+ */
+ public function aroundFlushFormKeyProvider()
+ {
+ return [
+ ['form_key_value', 'form_key_value', 2, 1],
+ ['form_old_key_value', 'form_key_value', 1, 0],
+ [null, 'form_key_value', 1, 0]
+ ];
+ }
+}
diff --git a/app/code/Magento/Customer/etc/di.xml b/app/code/Magento/Customer/etc/di.xml
index 6eea4e1582a97..40ef730120783 100644
--- a/app/code/Magento/Customer/etc/di.xml
+++ b/app/code/Magento/Customer/etc/di.xml
@@ -323,6 +323,9 @@
+
+
+
Magento\Customer\Model\Cache\Type\Notification
diff --git a/app/code/Magento/Deploy/Model/Mode.php b/app/code/Magento/Deploy/Model/Mode.php
index c20a459561d76..3810ef0953124 100644
--- a/app/code/Magento/Deploy/Model/Mode.php
+++ b/app/code/Magento/Deploy/Model/Mode.php
@@ -8,6 +8,7 @@
use Magento\Deploy\App\Mode\ConfigProvider;
use Magento\Framework\App\Config\ScopeConfigInterface;
+use Magento\Framework\App\Console\MaintenanceModeEnabler;
use Magento\Framework\App\DeploymentConfig\Reader;
use Magento\Framework\App\DeploymentConfig\Writer;
use Magento\Framework\App\Filesystem\DirectoryList;
@@ -49,11 +50,6 @@ class Mode
*/
private $reader;
- /**
- * @var MaintenanceMode
- */
- private $maintenanceMode;
-
/**
* @var Filesystem
*/
@@ -78,16 +74,24 @@ class Mode
*/
private $emulatedAreaProcessor;
+ /**
+ * @var MaintenanceModeEnabler
+ */
+ private $maintenanceModeEnabler;
+
/**
* @param InputInterface $input
* @param OutputInterface $output
* @param Writer $writer
* @param Reader $reader
- * @param MaintenanceMode $maintenanceMode
+ * @param MaintenanceMode $maintenanceMode deprecated, use $maintenanceModeEnabler instead
* @param Filesystem $filesystem
* @param ConfigProvider $configProvider
* @param ProcessorFacadeFactory $processorFacadeFactory
* @param EmulatedAdminhtmlAreaProcessor $emulatedAreaProcessor
+ * @param MaintenanceModeEnabler $maintenanceModeEnabler
+ *
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function __construct(
InputInterface $input,
@@ -98,13 +102,13 @@ public function __construct(
Filesystem $filesystem,
ConfigProvider $configProvider = null,
ProcessorFacadeFactory $processorFacadeFactory = null,
- EmulatedAdminhtmlAreaProcessor $emulatedAreaProcessor = null
+ EmulatedAdminhtmlAreaProcessor $emulatedAreaProcessor = null,
+ MaintenanceModeEnabler $maintenanceModeEnabler = null
) {
$this->input = $input;
$this->output = $output;
$this->writer = $writer;
$this->reader = $reader;
- $this->maintenanceMode = $maintenanceMode;
$this->filesystem = $filesystem;
$this->configProvider =
@@ -113,6 +117,8 @@ public function __construct(
$processorFacadeFactory ?: ObjectManager::getInstance()->get(ProcessorFacadeFactory::class);
$this->emulatedAreaProcessor =
$emulatedAreaProcessor ?: ObjectManager::getInstance()->get(EmulatedAdminhtmlAreaProcessor::class);
+ $this->maintenanceModeEnabler =
+ $maintenanceModeEnabler ?: ObjectManager::getInstance()->get(MaintenanceModeEnabler::class);
}
/**
@@ -123,19 +129,23 @@ public function __construct(
*/
public function enableProductionMode()
{
- $this->enableMaintenanceMode($this->output);
- $previousMode = $this->getMode();
- try {
- // We have to turn on production mode before generation.
- // We need this to enable generation of the "min" files.
- $this->setStoreMode(State::MODE_PRODUCTION);
- $this->filesystem->regenerateStatic($this->output);
- } catch (LocalizedException $e) {
- // We have to return store mode to previous state in case of error.
- $this->setStoreMode($previousMode);
- throw $e;
- }
- $this->disableMaintenanceMode($this->output);
+ $this->maintenanceModeEnabler->executeInMaintenanceMode(
+ function () {
+ $previousMode = $this->getMode();
+ try {
+ // We have to turn on production mode before generation.
+ // We need this to enable generation of the "min" files.
+ $this->setStoreMode(State::MODE_PRODUCTION);
+ $this->filesystem->regenerateStatic($this->output);
+ } catch (LocalizedException $e) {
+ // We have to return store mode to previous state in case of error.
+ $this->setStoreMode($previousMode);
+ throw $e;
+ }
+ },
+ $this->output,
+ false
+ );
}
/**
@@ -218,28 +228,4 @@ private function saveAppConfigs($mode)
$this->output->writeln('Config "' . $path . ' = ' . $item['value'] . '" has been saved.');
}
}
-
- /**
- * Enable maintenance mode
- *
- * @param OutputInterface $output
- * @return void
- */
- protected function enableMaintenanceMode(OutputInterface $output)
- {
- $this->maintenanceMode->set(true);
- $output->writeln('Enabled maintenance mode');
- }
-
- /**
- * Disable maintenance mode
- *
- * @param OutputInterface $output
- * @return void
- */
- protected function disableMaintenanceMode(OutputInterface $output)
- {
- $this->maintenanceMode->set(false);
- $output->writeln('Disabled maintenance mode');
- }
}
diff --git a/app/code/Magento/Deploy/Test/Unit/Model/ModeTest.php b/app/code/Magento/Deploy/Test/Unit/Model/ModeTest.php
index 3db2023e12f40..25625eaa5e267 100644
--- a/app/code/Magento/Deploy/Test/Unit/Model/ModeTest.php
+++ b/app/code/Magento/Deploy/Test/Unit/Model/ModeTest.php
@@ -12,6 +12,7 @@
use Magento\Deploy\Model\Filesystem;
use Magento\Deploy\Model\Mode;
use Magento\Framework\App\Config\ScopeConfigInterface;
+use Magento\Framework\App\Console\MaintenanceModeEnabler;
use Magento\Framework\App\DeploymentConfig\Reader;
use Magento\Framework\App\DeploymentConfig\Writer;
use Magento\Framework\App\MaintenanceMode;
@@ -124,7 +125,8 @@ protected function setUp()
$this->filesystemMock,
$this->configProvider,
$this->processorFacadeFactory,
- $this->emulatedAreaProcessor
+ $this->emulatedAreaProcessor,
+ new MaintenanceModeEnabler($this->maintenanceMock)
);
}
diff --git a/app/code/Magento/Theme/Console/Command/ThemeUninstallCommand.php b/app/code/Magento/Theme/Console/Command/ThemeUninstallCommand.php
index 4c8d6bca52edc..540fd962a4f2e 100644
--- a/app/code/Magento/Theme/Console/Command/ThemeUninstallCommand.php
+++ b/app/code/Magento/Theme/Console/Command/ThemeUninstallCommand.php
@@ -6,9 +6,10 @@
namespace Magento\Theme\Console\Command;
-use Magento\Framework\App\Area;
use Magento\Framework\App\Cache;
use Magento\Framework\App\MaintenanceMode;
+use Magento\Framework\App\Console\MaintenanceModeEnabler;
+use Magento\Framework\App\ObjectManager;
use Magento\Framework\App\State\CleanupFiles;
use Magento\Framework\Composer\ComposerInformation;
use Magento\Framework\Composer\DependencyChecker;
@@ -39,13 +40,6 @@ class ThemeUninstallCommand extends Command
const INPUT_KEY_THEMES = 'theme';
const INPUT_KEY_CLEAR_STATIC_CONTENT = 'clear-static-content';
- /**
- * Maintenance Mode
- *
- * @var MaintenanceMode
- */
- private $maintenanceMode;
-
/**
* Composer general dependency checker
*
@@ -116,13 +110,18 @@ class ThemeUninstallCommand extends Command
*/
private $themeDependencyChecker;
+ /**
+ * @var MaintenanceModeEnabler
+ */
+ private $maintenanceModeEnabler;
+
/**
* Constructor
*
* @param Cache $cache
* @param CleanupFiles $cleanupFiles
* @param ComposerInformation $composer
- * @param MaintenanceMode $maintenanceMode
+ * @param MaintenanceMode $maintenanceMode deprecated, use $maintenanceModeEnabler instead
* @param DependencyChecker $dependencyChecker
* @param Collection $themeCollection
* @param BackupRollbackFactory $backupRollbackFactory
@@ -130,6 +129,9 @@ class ThemeUninstallCommand extends Command
* @param ThemePackageInfo $themePackageInfo
* @param ThemeUninstaller $themeUninstaller
* @param ThemeDependencyChecker $themeDependencyChecker
+ * @param MaintenanceModeEnabler $maintenanceModeEnabler
+ *
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function __construct(
Cache $cache,
@@ -142,12 +144,12 @@ public function __construct(
ThemeValidator $themeValidator,
ThemePackageInfo $themePackageInfo,
ThemeUninstaller $themeUninstaller,
- ThemeDependencyChecker $themeDependencyChecker
+ ThemeDependencyChecker $themeDependencyChecker,
+ MaintenanceModeEnabler $maintenanceModeEnabler = null
) {
$this->cache = $cache;
$this->cleanupFiles = $cleanupFiles;
$this->composer = $composer;
- $this->maintenanceMode = $maintenanceMode;
$this->dependencyChecker = $dependencyChecker;
$this->themeCollection = $themeCollection;
$this->backupRollbackFactory = $backupRollbackFactory;
@@ -155,6 +157,8 @@ public function __construct(
$this->themePackageInfo = $themePackageInfo;
$this->themeUninstaller = $themeUninstaller;
$this->themeDependencyChecker = $themeDependencyChecker;
+ $this->maintenanceModeEnabler =
+ $maintenanceModeEnabler ?: ObjectManager::getInstance()->get(MaintenanceModeEnabler::class);
parent::__construct();
}
@@ -214,27 +218,32 @@ protected function execute(InputInterface $input, OutputInterface $output)
return \Magento\Framework\Console\Cli::RETURN_FAILURE;
}
- try {
- $output->writeln('Enabling maintenance mode');
- $this->maintenanceMode->set(true);
- if ($input->getOption(self::INPUT_KEY_BACKUP_CODE)) {
- $time = time();
- $codeBackup = $this->backupRollbackFactory->create($output);
- $codeBackup->codeBackup($time);
- }
-
- $this->themeUninstaller->uninstallRegistry($output, $themePaths);
- $this->themeUninstaller->uninstallCode($output, $themePaths);
+ $result = $this->maintenanceModeEnabler->executeInMaintenanceMode(
+ function () use ($input, $output, $themePaths) {
+ try {
+ if ($input->getOption(self::INPUT_KEY_BACKUP_CODE)) {
+ $time = time();
+ $codeBackup = $this->backupRollbackFactory->create($output);
+ $codeBackup->codeBackup($time);
+ }
+
+ $this->themeUninstaller->uninstallRegistry($output, $themePaths);
+ $this->themeUninstaller->uninstallCode($output, $themePaths);
+
+ $this->cleanup($input, $output);
+ return \Magento\Framework\Console\Cli::RETURN_SUCCESS;
+ } catch (\Exception $e) {
+ $output->writeln('' . $e->getMessage() . '');
+ $output->writeln('Please disable maintenance mode after you resolved above issues');
+ // we must have an exit code higher than zero to indicate something was wrong
+ return \Magento\Framework\Console\Cli::RETURN_FAILURE;
+ }
+ },
+ $output,
+ true
+ );
- $this->cleanup($input, $output);
- $output->writeln('Disabling maintenance mode');
- $this->maintenanceMode->set(false);
- } catch (\Exception $e) {
- $output->writeln('' . $e->getMessage() . '');
- $output->writeln('Please disable maintenance mode after you resolved above issues');
- // we must have an exit code higher than zero to indicate something was wrong
- return \Magento\Framework\Console\Cli::RETURN_FAILURE;
- }
+ return $result;
}
/**
diff --git a/app/code/Magento/Theme/Test/Unit/Console/Command/ThemeUninstallCommandTest.php b/app/code/Magento/Theme/Test/Unit/Console/Command/ThemeUninstallCommandTest.php
index abd4c91a7e1b7..2ae889e69bb12 100644
--- a/app/code/Magento/Theme/Test/Unit/Console/Command/ThemeUninstallCommandTest.php
+++ b/app/code/Magento/Theme/Test/Unit/Console/Command/ThemeUninstallCommandTest.php
@@ -6,6 +6,7 @@
namespace Magento\Theme\Test\Unit\Console\Command;
+use Magento\Framework\App\Console\MaintenanceModeEnabler;
use Magento\Theme\Console\Command\ThemeUninstallCommand;
use Magento\Theme\Model\Theme\themePackageInfo;
use Magento\Theme\Model\Theme\ThemeUninstaller;
@@ -19,7 +20,7 @@
class ThemeUninstallCommandTest extends \PHPUnit\Framework\TestCase
{
/**
- * @var \Magento\Framework\App\MaintenanceMode|\PHPUnit_Framework_MockObject_MockObject
+ * @var \Magento\Framework\App\Console\MaintenanceMode|\PHPUnit_Framework_MockObject_MockObject
*/
private $maintenanceMode;
@@ -107,7 +108,8 @@ protected function setUp()
$this->themeValidator,
$this->themePackageInfo,
$this->themeUninstaller,
- $this->themeDependencyChecker
+ $this->themeDependencyChecker,
+ new MaintenanceModeEnabler($this->maintenanceMode)
);
$this->tester = new CommandTester($this->command);
}
diff --git a/app/code/Magento/Variable/Block/System/Variable/Edit.php b/app/code/Magento/Variable/Block/System/Variable/Edit.php
index be68814ea27e2..ea119b88fa795 100644
--- a/app/code/Magento/Variable/Block/System/Variable/Edit.php
+++ b/app/code/Magento/Variable/Block/System/Variable/Edit.php
@@ -90,11 +90,7 @@ protected function _preparelayout()
*/
public function getFormHtml()
{
- $formHtml = parent::getFormHtml();
- if (!$this->_storeManager->isSingleStoreMode() && $this->getVariable()->getId()) {
- $formHtml = $formHtml;
- }
- return $formHtml;
+ return parent::getFormHtml();
}
/**
diff --git a/lib/internal/Magento/Framework/App/Console/MaintenanceModeEnabler.php b/lib/internal/Magento/Framework/App/Console/MaintenanceModeEnabler.php
new file mode 100644
index 0000000000000..6f834d50c51f7
--- /dev/null
+++ b/lib/internal/Magento/Framework/App/Console/MaintenanceModeEnabler.php
@@ -0,0 +1,96 @@
+maintenanceMode = $maintenanceMode;
+ }
+
+ /**
+ * Enable maintenance mode
+ *
+ * @param OutputInterface $output
+ * @return void
+ */
+ private function enableMaintenanceMode(OutputInterface $output)
+ {
+ if ($this->maintenanceMode->isOn()) {
+ $this->skipDisableMaintenanceMode = true;
+ $output->writeln('Maintenance mode already enabled');
+ return;
+ }
+
+ $this->maintenanceMode->set(true);
+ $this->skipDisableMaintenanceMode = false;
+ $output->writeln('Enabling maintenance mode');
+ }
+
+ /**
+ * Disable maintenance mode
+ *
+ * @param OutputInterface $output
+ * @return void
+ */
+ private function disableMaintenanceMode(OutputInterface $output)
+ {
+ if ($this->skipDisableMaintenanceMode) {
+ $output->writeln('Skipped disabling maintenance mode');
+ return;
+ }
+
+ $this->maintenanceMode->set(false);
+ $output->writeln('Disabling maintenance mode');
+ }
+
+ /**
+ * Run task in maintenance mode
+ *
+ * @param callable $task
+ * @param OutputInterface $output
+ * @param bool $holdMaintenanceOnFailure
+ * @return mixed
+ * @throws \Throwable if error occurred
+ */
+ public function executeInMaintenanceMode(callable $task, OutputInterface $output, bool $holdMaintenanceOnFailure)
+ {
+ $this->enableMaintenanceMode($output);
+
+ try {
+ $result = call_user_func($task);
+ } catch (\Throwable $e) {
+ if (!$holdMaintenanceOnFailure) {
+ $this->disableMaintenanceMode($output);
+ }
+ throw $e;
+ }
+
+ $this->disableMaintenanceMode($output);
+ return $result;
+ }
+}
diff --git a/lib/internal/Magento/Framework/App/Test/Unit/Console/MaintenanceModeEnablerTest.php b/lib/internal/Magento/Framework/App/Test/Unit/Console/MaintenanceModeEnablerTest.php
new file mode 100644
index 0000000000000..ebd47c0dc8936
--- /dev/null
+++ b/lib/internal/Magento/Framework/App/Test/Unit/Console/MaintenanceModeEnablerTest.php
@@ -0,0 +1,122 @@
+createMaintenanceMode($maintenanceModeEnabledInitially);
+ $enabler = new MaintenanceModeEnabler($maintenanceMode);
+ $successTask = function () {
+ // do nothing
+ };
+
+ $enabler->executeInMaintenanceMode(
+ $successTask,
+ $this->createOutput(),
+ true
+ );
+
+ $this->assertEquals(
+ $maintenanceModeEnabledInitially,
+ $maintenanceMode->isOn(),
+ 'Initial state is not restored'
+ );
+ }
+
+ /**
+ * @dataProvider initialAppStateProvider
+ */
+ public function testFailedTaskWithMaintenanceModeOnFailure(bool $maintenanceModeEnabledInitially)
+ {
+ $maintenanceMode = $this->createMaintenanceMode($maintenanceModeEnabledInitially);
+ $enabler = new MaintenanceModeEnabler($maintenanceMode);
+ $failedTask = function () {
+ throw new \Exception('Woops!');
+ };
+
+ try {
+ $enabler->executeInMaintenanceMode(
+ $failedTask,
+ $this->createOutput(),
+ true
+ );
+ } catch (\Exception $e) {
+ $this->assertEquals(
+ true,
+ $maintenanceMode->isOn(),
+ 'Maintenance mode is not active after failure'
+ );
+ }
+ }
+
+ /**
+ * @dataProvider initialAppStateProvider
+ */
+ public function testFailedTaskWithRestoredModeOnFailure(bool $maintenanceModeEnabledInitially)
+ {
+ $maintenanceMode = $this->createMaintenanceMode($maintenanceModeEnabledInitially);
+ $enabler = new MaintenanceModeEnabler($maintenanceMode);
+ $failedTask = function () {
+ throw new \Exception('Woops!');
+ };
+
+ try {
+ $enabler->executeInMaintenanceMode(
+ $failedTask,
+ $this->createOutput(),
+ false
+ );
+ } catch (\Exception $e) {
+ $this->assertEquals(
+ $maintenanceModeEnabledInitially,
+ $maintenanceMode->isOn(),
+ 'Initial state is not restored'
+ );
+ }
+ }
+
+ public function initialAppStateProvider()
+ {
+ return [
+ 'Maintenance mode disabled initially' => [false],
+ 'Maintenance mode enabled initially' => [true],
+ ];
+ }
+
+ private function createMaintenanceMode(bool $isOn): MaintenanceMode
+ {
+ $maintenanceMode = $this->getMockBuilder(MaintenanceMode::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $maintenanceMode->method('isOn')->willReturnCallback(function () use (&$isOn) {
+ return $isOn;
+ });
+ $maintenanceMode->method('set')->willReturnCallback(function ($newValue) use (&$isOn) {
+ $isOn = (bool)$newValue;
+ return true;
+ });
+
+ return $maintenanceMode;
+ }
+
+ private function createOutput(): OutputInterface
+ {
+ $output = $this->getMockBuilder(OutputInterface::class)
+ ->getMockForAbstractClass();
+ return $output;
+ }
+}
diff --git a/lib/web/mage/menu.js b/lib/web/mage/menu.js
index 05d3217414883..6ad60333d2e1b 100644
--- a/lib/web/mage/menu.js
+++ b/lib/web/mage/menu.js
@@ -21,6 +21,7 @@ define([
expanded: false,
showDelay: 42,
hideDelay: 300,
+ delay: 300,
mediaBreakpoint: '(max-width: 768px)'
},
@@ -30,6 +31,8 @@ define([
_create: function () {
var self = this;
+ this.delay = this.options.delay;
+
this._super();
$(window).on('resize', function () {
self.element.find('.submenu-reverse').removeClass('submenu-reverse');
@@ -583,7 +586,7 @@ define([
html.removeClass('nav-open');
setTimeout(function () {
html.removeClass('nav-before-open');
- }, 300);
+ }, this.options.hideDelay);
}
},
diff --git a/setup/src/Magento/Setup/Console/Command/BackupCommand.php b/setup/src/Magento/Setup/Console/Command/BackupCommand.php
index a6ec091cc50b0..0c65d3db1f7ba 100644
--- a/setup/src/Magento/Setup/Console/Command/BackupCommand.php
+++ b/setup/src/Magento/Setup/Console/Command/BackupCommand.php
@@ -5,6 +5,7 @@
*/
namespace Magento\Setup\Console\Command;
+use Magento\Framework\App\Console\MaintenanceModeEnabler;
use Magento\Framework\App\DeploymentConfig;
use Magento\Framework\App\MaintenanceMode;
use Magento\Framework\Backup\Factory;
@@ -36,13 +37,6 @@ class BackupCommand extends AbstractSetupCommand
*/
private $objectManager;
- /**
- * Handler for maintenance mode
- *
- * @var MaintenanceMode
- */
- private $maintenanceMode;
-
/**
* Factory for BackupRollback
*
@@ -58,28 +52,31 @@ class BackupCommand extends AbstractSetupCommand
private $deploymentConfig;
/**
- * The initial maintenance mode state
- * @var bool
+ * @var MaintenanceModeEnabler
*/
- private $maintenanceModeInitialState;
+ private $maintenanceModeEnabler;
/**
* Constructor
*
* @param ObjectManagerProvider $objectManagerProvider
- * @param MaintenanceMode $maintenanceMode
+ * @param MaintenanceMode $maintenanceMode deprecated, use $maintenanceModeEnabler instead
* @param DeploymentConfig $deploymentConfig
+ * @param MaintenanceModeEnabler $maintenanceModeEnabler
+ *
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function __construct(
ObjectManagerProvider $objectManagerProvider,
MaintenanceMode $maintenanceMode,
- DeploymentConfig $deploymentConfig
+ DeploymentConfig $deploymentConfig,
+ MaintenanceModeEnabler $maintenanceModeEnabler = null
) {
$this->objectManager = $objectManagerProvider->get();
- $this->maintenanceMode = $maintenanceMode;
$this->backupRollbackFactory = $this->objectManager->get(\Magento\Framework\Setup\BackupRollbackFactory::class);
$this->deploymentConfig = $deploymentConfig;
- $this->maintenanceModeInitialState = $this->maintenanceMode->isOn();
+ $this->maintenanceModeEnabler =
+ $maintenanceModeEnabler ?: $this->objectManager->get(MaintenanceModeEnabler::class);
parent::__construct();
}
@@ -126,41 +123,40 @@ protected function execute(InputInterface $input, OutputInterface $output)
// We need exit code higher than 0 here as an indication
return \Magento\Framework\Console\Cli::RETURN_FAILURE;
}
- $returnValue = \Magento\Framework\Console\Cli::RETURN_SUCCESS;
- try {
- $inputOptionProvided = false;
- $output->writeln('Enabling maintenance mode');
- $this->maintenanceMode->set(true);
- $time = time();
- $backupHandler = $this->backupRollbackFactory->create($output);
- if ($input->getOption(self::INPUT_KEY_CODE)) {
- $backupHandler->codeBackup($time);
- $inputOptionProvided = true;
- }
- if ($input->getOption(self::INPUT_KEY_MEDIA)) {
- $backupHandler->codeBackup($time, Factory::TYPE_MEDIA);
- $inputOptionProvided = true;
- }
- if ($input->getOption(self::INPUT_KEY_DB)) {
- $this->setAreaCode();
- $backupHandler->dbBackup($time);
- $inputOptionProvided = true;
- }
- if (!$inputOptionProvided) {
- throw new \InvalidArgumentException(
- 'Not enough information provided to take backup.'
- );
- }
- } catch (\Exception $e) {
- $output->writeln('' . $e->getMessage() . '');
- $returnValue = \Magento\Framework\Console\Cli::RETURN_FAILURE;
- } finally {
- // Only disable maintenace mode if it wasn't turned on before
- if (!$this->maintenanceModeInitialState) {
- $output->writeln('Disabling maintenance mode');
- $this->maintenanceMode->set(false);
- }
- }
+
+ $returnValue = $this->maintenanceModeEnabler->executeInMaintenanceMode(
+ function () use ($input, $output) {
+ try {
+ $inputOptionProvided = false;
+ $time = time();
+ $backupHandler = $this->backupRollbackFactory->create($output);
+ if ($input->getOption(self::INPUT_KEY_CODE)) {
+ $backupHandler->codeBackup($time);
+ $inputOptionProvided = true;
+ }
+ if ($input->getOption(self::INPUT_KEY_MEDIA)) {
+ $backupHandler->codeBackup($time, Factory::TYPE_MEDIA);
+ $inputOptionProvided = true;
+ }
+ if ($input->getOption(self::INPUT_KEY_DB)) {
+ $this->setAreaCode();
+ $backupHandler->dbBackup($time);
+ $inputOptionProvided = true;
+ }
+ if (!$inputOptionProvided) {
+ throw new \InvalidArgumentException(
+ 'Not enough information provided to take backup.'
+ );
+ }
+ return \Magento\Framework\Console\Cli::RETURN_SUCCESS;
+ } catch (\Exception $e) {
+ $output->writeln('' . $e->getMessage() . '');
+ return \Magento\Framework\Console\Cli::RETURN_FAILURE;
+ }
+ },
+ $output,
+ false
+ );
return $returnValue;
}
diff --git a/setup/src/Magento/Setup/Console/Command/ModuleUninstallCommand.php b/setup/src/Magento/Setup/Console/Command/ModuleUninstallCommand.php
index 4e25cf60a56d3..9740efa1a7457 100644
--- a/setup/src/Magento/Setup/Console/Command/ModuleUninstallCommand.php
+++ b/setup/src/Magento/Setup/Console/Command/ModuleUninstallCommand.php
@@ -5,6 +5,7 @@
*/
namespace Magento\Setup\Console\Command;
+use Magento\Framework\App\Console\MaintenanceModeEnabler;
use Magento\Framework\App\DeploymentConfig;
use Magento\Framework\App\MaintenanceMode;
use Magento\Framework\Backup\Factory;
@@ -38,13 +39,6 @@ class ModuleUninstallCommand extends AbstractModuleCommand
const INPUT_KEY_BACKUP_MEDIA = 'backup-media';
const INPUT_KEY_BACKUP_DB = 'backup-db';
- /**
- * Maintenance mode
- *
- * @var MaintenanceMode
- */
- private $maintenanceMode;
-
/**
* Deployment Configuration
*
@@ -108,17 +102,25 @@ class ModuleUninstallCommand extends AbstractModuleCommand
*/
private $moduleRegistryUninstaller;
+ /**
+ * @var MaintenanceModeEnabler
+ */
+ private $maintenanceModeEnabler;
+
/**
* Constructor
*
* @param ComposerInformation $composer
* @param DeploymentConfig $deploymentConfig
* @param FullModuleList $fullModuleList
- * @param MaintenanceMode $maintenanceMode
+ * @param MaintenanceMode $maintenanceMode deprecated, use $maintenanceModeEnabler instead
* @param ObjectManagerProvider $objectManagerProvider
* @param UninstallCollector $collector
* @param ModuleUninstaller $moduleUninstaller
* @param ModuleRegistryUninstaller $moduleRegistryUninstaller
+ * @param MaintenanceModeEnabler $maintenanceModeEnabler
+ *
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function __construct(
ComposerInformation $composer,
@@ -128,12 +130,12 @@ public function __construct(
ObjectManagerProvider $objectManagerProvider,
UninstallCollector $collector,
ModuleUninstaller $moduleUninstaller,
- ModuleRegistryUninstaller $moduleRegistryUninstaller
+ ModuleRegistryUninstaller $moduleRegistryUninstaller,
+ MaintenanceModeEnabler $maintenanceModeEnabler = null
) {
parent::__construct($objectManagerProvider);
$this->composer = $composer;
$this->deploymentConfig = $deploymentConfig;
- $this->maintenanceMode = $maintenanceMode;
$this->fullModuleList = $fullModuleList;
$this->packageInfo = $this->objectManager->get(\Magento\Framework\Module\PackageInfoFactory::class)->create();
$this->collector = $collector;
@@ -141,6 +143,8 @@ public function __construct(
$this->backupRollbackFactory = $this->objectManager->get(\Magento\Framework\Setup\BackupRollbackFactory::class);
$this->moduleUninstaller = $moduleUninstaller;
$this->moduleRegistryUninstaller = $moduleRegistryUninstaller;
+ $this->maintenanceModeEnabler =
+ $maintenanceModeEnabler ?: $this->objectManager->get(MaintenanceModeEnabler::class);
}
/**
@@ -227,41 +231,47 @@ protected function execute(InputInterface $input, OutputInterface $output)
if (!$helper->ask($input, $output, $question) && $input->isInteractive()) {
return \Magento\Framework\Console\Cli::RETURN_FAILURE;
}
- try {
- $output->writeln('Enabling maintenance mode');
- $this->maintenanceMode->set(true);
- $this->takeBackup($input, $output);
- $dbBackupOption = $input->getOption(self::INPUT_KEY_BACKUP_DB);
- if ($input->getOption(self::INPUT_KEY_REMOVE_DATA)) {
- $this->removeData($modules, $output, $dbBackupOption);
- } else {
- if (!empty($this->collector->collectUninstall())) {
- $question = new ConfirmationQuestion(
- 'You are about to remove a module(s) that might have database data. '
- . 'Do you want to remove the data from database?[y/N]',
- false
- );
- if ($helper->ask($input, $output, $question) || !$input->isInteractive()) {
+
+ $result = $this->maintenanceModeEnabler->executeInMaintenanceMode(
+ function () use ($input, $output, $modules, $helper) {
+ try {
+ $this->takeBackup($input, $output);
+ $dbBackupOption = $input->getOption(self::INPUT_KEY_BACKUP_DB);
+ if ($input->getOption(self::INPUT_KEY_REMOVE_DATA)) {
$this->removeData($modules, $output, $dbBackupOption);
+ } else {
+ if (!empty($this->collector->collectUninstall())) {
+ $question = new ConfirmationQuestion(
+ 'You are about to remove a module(s) that might have database data. '
+ . 'Do you want to remove the data from database?[y/N]',
+ false
+ );
+ if ($helper->ask($input, $output, $question) || !$input->isInteractive()) {
+ $this->removeData($modules, $output, $dbBackupOption);
+ }
+ } else {
+ $output->writeln(
+ 'You are about to remove a module(s) that might have database data. '
+ . 'Remove the database data manually after uninstalling, if desired.'
+ );
+ }
}
- } else {
- $output->writeln(
- 'You are about to remove a module(s) that might have database data. '
- . 'Remove the database data manually after uninstalling, if desired.'
- );
+ $this->moduleRegistryUninstaller->removeModulesFromDb($output, $modules);
+ $this->moduleRegistryUninstaller->removeModulesFromDeploymentConfig($output, $modules);
+ $this->moduleUninstaller->uninstallCode($output, $modules);
+ $this->cleanup($input, $output);
+ return \Magento\Framework\Console\Cli::RETURN_SUCCESS;
+ } catch (\Exception $e) {
+ $output->writeln('' . $e->getMessage() . '');
+ $output->writeln('Please disable maintenance mode after you resolved above issues');
+ return \Magento\Framework\Console\Cli::RETURN_FAILURE;
}
- }
- $this->moduleRegistryUninstaller->removeModulesFromDb($output, $modules);
- $this->moduleRegistryUninstaller->removeModulesFromDeploymentConfig($output, $modules);
- $this->moduleUninstaller->uninstallCode($output, $modules);
- $this->cleanup($input, $output);
- $output->writeln('Disabling maintenance mode');
- $this->maintenanceMode->set(false);
- } catch (\Exception $e) {
- $output->writeln('' . $e->getMessage() . '');
- $output->writeln('Please disable maintenance mode after you resolved above issues');
- return \Magento\Framework\Console\Cli::RETURN_FAILURE;
- }
+ },
+ $output,
+ true
+ );
+
+ return $result;
}
/**
diff --git a/setup/src/Magento/Setup/Console/Command/RollbackCommand.php b/setup/src/Magento/Setup/Console/Command/RollbackCommand.php
index 2d728e22fa140..d67e7f0a53796 100644
--- a/setup/src/Magento/Setup/Console/Command/RollbackCommand.php
+++ b/setup/src/Magento/Setup/Console/Command/RollbackCommand.php
@@ -5,6 +5,7 @@
*/
namespace Magento\Setup\Console\Command;
+use Magento\Framework\App\Console\MaintenanceModeEnabler;
use Magento\Framework\App\DeploymentConfig;
use Magento\Framework\App\MaintenanceMode;
use Magento\Framework\Backup\Factory;
@@ -37,11 +38,6 @@ class RollbackCommand extends AbstractSetupCommand
*/
private $objectManager;
- /**
- * @var MaintenanceMode
- */
- private $maintenanceMode;
-
/**
* @var BackupRollbackFactory
*/
@@ -54,22 +50,33 @@ class RollbackCommand extends AbstractSetupCommand
*/
private $deploymentConfig;
+ /**
+ * @var MaintenanceModeEnabler
+ */
+ private $maintenanceModeEnabler;
+
/**
* Constructor
*
* @param ObjectManagerProvider $objectManagerProvider
- * @param MaintenanceMode $maintenanceMode
+ * @param MaintenanceMode $maintenanceMode deprecated, use $maintenanceModeEnabler instead
* @param DeploymentConfig $deploymentConfig
+ * @param MaintenanceModeEnabler $maintenanceModeEnabler
+ *
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function __construct(
ObjectManagerProvider $objectManagerProvider,
MaintenanceMode $maintenanceMode,
- DeploymentConfig $deploymentConfig
+ DeploymentConfig $deploymentConfig,
+ MaintenanceModeEnabler $maintenanceModeEnabler = null
) {
$this->objectManager = $objectManagerProvider->get();
- $this->maintenanceMode = $maintenanceMode;
+ $this->maintenanceModeEnabler = $maintenanceMode;
$this->backupRollbackFactory = $this->objectManager->get(\Magento\Framework\Setup\BackupRollbackFactory::class);
$this->deploymentConfig = $deploymentConfig;
+ $this->maintenanceModeEnabler =
+ $maintenanceModeEnabler ?: $this->objectManager->get(MaintenanceModeEnabler::class);
parent::__construct();
}
@@ -115,28 +122,32 @@ protected function execute(InputInterface $input, OutputInterface $output)
// we must have an exit code higher than zero to indicate something was wrong
return \Magento\Framework\Console\Cli::RETURN_FAILURE;
}
- $returnValue = \Magento\Framework\Console\Cli::RETURN_SUCCESS;
- try {
- $output->writeln('Enabling maintenance mode');
- $this->maintenanceMode->set(true);
- $helper = $this->getHelper('question');
- $question = new ConfirmationQuestion(
- 'You are about to remove current code and/or database tables. Are you sure?[y/N]',
- false
- );
- if (!$helper->ask($input, $output, $question) && $input->isInteractive()) {
- return \Magento\Framework\Console\Cli::RETURN_FAILURE;
- }
- $this->doRollback($input, $output);
- $output->writeln('Please set file permission of bin/magento to executable');
- } catch (\Exception $e) {
- $output->writeln('' . $e->getMessage() . '');
- // we must have an exit code higher than zero to indicate something was wrong
- $returnValue = \Magento\Framework\Console\Cli::RETURN_FAILURE;
- } finally {
- $output->writeln('Disabling maintenance mode');
- $this->maintenanceMode->set(false);
- }
+
+ $returnValue = $this->maintenanceModeEnabler->executeInMaintenanceMode(
+ function () use ($input, $output, &$returnValue) {
+ try {
+ $helper = $this->getHelper('question');
+ $question = new ConfirmationQuestion(
+ 'You are about to remove current code and/or database tables. Are you sure?[y/N]',
+ false
+ );
+ if (!$helper->ask($input, $output, $question) && $input->isInteractive()) {
+ return \Magento\Framework\Console\Cli::RETURN_FAILURE;
+ }
+ $this->doRollback($input, $output);
+ $output->writeln('Please set file permission of bin/magento to executable');
+
+ return \Magento\Framework\Console\Cli::RETURN_SUCCESS;
+ } catch (\Exception $e) {
+ $output->writeln('' . $e->getMessage() . '');
+ // we must have an exit code higher than zero to indicate something was wrong
+ return \Magento\Framework\Console\Cli::RETURN_FAILURE;
+ }
+ },
+ $output,
+ false
+ );
+
return $returnValue;
}
diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/BackupCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/BackupCommandTest.php
index b44dcb123632e..e8179cff4a94e 100644
--- a/setup/src/Magento/Setup/Test/Unit/Console/Command/BackupCommandTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/BackupCommandTest.php
@@ -5,6 +5,7 @@
*/
namespace Magento\Setup\Test\Unit\Console\Command;
+use Magento\Framework\App\Console\MaintenanceModeEnabler;
use Magento\Setup\Console\Command\BackupCommand;
use Symfony\Component\Console\Tester\CommandTester;
@@ -73,7 +74,8 @@ public function setUp()
$command = new BackupCommand(
$objectManagerProvider,
$maintenanceMode,
- $this->deploymentConfig
+ $this->deploymentConfig,
+ new MaintenanceModeEnabler($maintenanceMode)
);
$this->tester = new CommandTester($command);
}
diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleUninstallCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleUninstallCommandTest.php
index affff69d83544..b6674c9aac986 100644
--- a/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleUninstallCommandTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleUninstallCommandTest.php
@@ -5,6 +5,7 @@
*/
namespace Magento\Setup\Test\Unit\Console\Command;
+use Magento\Framework\App\Console\MaintenanceModeEnabler;
use Magento\Setup\Console\Command\ModuleUninstallCommand;
use Magento\Setup\Model\ModuleUninstaller;
use Symfony\Component\Console\Tester\CommandTester;
@@ -158,7 +159,8 @@ public function setUp()
$objectManagerProvider,
$this->uninstallCollector,
$this->moduleUninstaller,
- $this->moduleRegistryUninstaller
+ $this->moduleRegistryUninstaller,
+ new MaintenanceModeEnabler($this->maintenanceMode)
);
$this->question = $this->createMock(\Symfony\Component\Console\Helper\QuestionHelper::class);
$this->question
diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/RollbackCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/RollbackCommandTest.php
index 6c2e22a9a202c..9ced38c316636 100644
--- a/setup/src/Magento/Setup/Test/Unit/Console/Command/RollbackCommandTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/RollbackCommandTest.php
@@ -5,9 +5,13 @@
*/
namespace Magento\Setup\Test\Unit\Console\Command;
+use Magento\Framework\App\Console\MaintenanceModeEnabler;
use Magento\Setup\Console\Command\RollbackCommand;
use Symfony\Component\Console\Tester\CommandTester;
+/**
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
class RollbackCommandTest extends \PHPUnit\Framework\TestCase
{
/**
@@ -96,7 +100,8 @@ public function setUp()
$this->command = new RollbackCommand(
$objectManagerProvider,
$maintenanceMode,
- $this->deploymentConfig
+ $this->deploymentConfig,
+ new MaintenanceModeEnabler($maintenanceMode)
);
$this->command->setHelperSet($this->helperSet);
$this->tester = new CommandTester($this->command);