diff --git a/setup/src/Magento/Setup/Console/Command/ModuleConfigStatusCommand.php b/setup/src/Magento/Setup/Console/Command/ModuleConfigStatusCommand.php new file mode 100644 index 0000000000000..70dbf14728bd7 --- /dev/null +++ b/setup/src/Magento/Setup/Console/Command/ModuleConfigStatusCommand.php @@ -0,0 +1,109 @@ +configReader = $configReader; + $this->installerFactory = $installerFactory; + + parent::__construct(); + } + + /** + * @inheritdoc + */ + protected function configure() + { + $this + ->setName('module:config:status') + ->setDescription( + 'Checks the modules configuration in the \'app/etc/config.php\' file ' + . 'and reports if they are up to date or not' + ); + + parent::configure(); + } + + /** + * @inheritdoc + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + try { + // the config as currently in app/etc/config.php + $currentConfig = $this->configReader->load(ConfigFilePool::APP_CONFIG); + if (!array_key_exists(ConfigOptionsListConstants::KEY_MODULES, $currentConfig)) { + // phpcs:ignore Magento2.Exceptions.DirectThrow + throw new \Exception('Can\'t find the modules configuration in the \'app/etc/config.php\' file.'); + } + + $currentModuleConfig = $currentConfig[ConfigOptionsListConstants::KEY_MODULES]; + + $installer = $this->installerFactory->create(new ConsoleLogger($output)); + + // the module config as Magento calculated it + $correctModuleConfig = $installer->getModulesConfig(); + + if ($currentModuleConfig !== $correctModuleConfig) { + // phpcs:ignore Magento2.Exceptions.DirectThrow + throw new \Exception( + 'The modules configuration in the \'app/etc/config.php\' file is outdated. ' + . 'Run \'setup:upgrade\' to fix it.' + ); + } + + $output->writeln( + 'The modules configuration is up to date.' + ); + // phpcs:disable Magento2.Exceptions.ThrowCatch + } catch (\Exception $e) { + $output->writeln('' . $e->getMessage() . ''); + + return Cli::RETURN_FAILURE; + } + + return Cli::RETURN_SUCCESS; + } +} diff --git a/setup/src/Magento/Setup/Console/CommandList.php b/setup/src/Magento/Setup/Console/CommandList.php index 08befdca2221d..f0dad6f4a7452 100644 --- a/setup/src/Magento/Setup/Console/CommandList.php +++ b/setup/src/Magento/Setup/Console/CommandList.php @@ -66,6 +66,7 @@ protected function getCommandsClasses() \Magento\Setup\Console\Command\ModuleDisableCommand::class, \Magento\Setup\Console\Command\ModuleStatusCommand::class, \Magento\Setup\Console\Command\ModuleUninstallCommand::class, + \Magento\Setup\Console\Command\ModuleConfigStatusCommand::class, \Magento\Setup\Console\Command\MaintenanceAllowIpsCommand::class, \Magento\Setup\Console\Command\MaintenanceDisableCommand::class, \Magento\Setup\Console\Command\MaintenanceEnableCommand::class, @@ -91,6 +92,7 @@ public function getCommands() if (class_exists($class)) { $commands[] = $this->serviceManager->get($class); } else { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception('Class ' . $class . ' does not exist'); } } diff --git a/setup/src/Magento/Setup/Model/Installer.php b/setup/src/Magento/Setup/Model/Installer.php index d4ed261a9a945..f80a35937d5dc 100644 --- a/setup/src/Magento/Setup/Model/Installer.php +++ b/setup/src/Magento/Setup/Model/Installer.php @@ -1200,6 +1200,17 @@ public function updateModulesSequence($keepGeneratedFiles = false) $this->createModulesConfig([]); } + /** + * Get the modules config as Magento sees it + * + * @return array + * @throws \LogicException + */ + public function getModulesConfig() + { + return $this->createModulesConfig([], true); + } + /** * Uninstall Magento application * diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleConfigStatusCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleConfigStatusCommandTest.php new file mode 100644 index 0000000000000..16577ed2db738 --- /dev/null +++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/ModuleConfigStatusCommandTest.php @@ -0,0 +1,91 @@ +createMock(\Magento\Framework\App\DeploymentConfig\Reader::class); + $configReader->expects($this->once()) + ->method('load') + ->willReturn([ConfigOptionsListConstants::KEY_MODULES => $currentConfig]); + + $installer = $this->createMock(\Magento\Setup\Model\Installer::class); + $installer->expects($this->once()) + ->method('getModulesConfig') + ->willReturn($correctConfig); + + $installerFactory = $this->createMock(\Magento\Setup\Model\InstallerFactory::class); + $installerFactory->expects($this->once()) + ->method('create') + ->willReturn($installer); + + $command = new ModuleConfigStatusCommand($configReader, $installerFactory); + + $tester = new CommandTester($command); + $tester->execute([]); + + $this->assertEquals($expectedOutput, $tester->getDisplay()); + } + + public function executeDataProvider() + { + $successMessage = 'The modules configuration is up to date.' . PHP_EOL; + $failureMessage = 'The modules configuration in the \'app/etc/config.php\' ' + . 'file is outdated. Run \'setup:upgrade\' to fix it.' . PHP_EOL; + + return [ + [ + ['Magento_ModuleA' => 1, 'Magento_ModuleB' => 1], + ['Magento_ModuleA' => 1, 'Magento_ModuleB' => 1], + $successMessage, + ], + [ + ['Magento_ModuleA' => 0, 'Magento_ModuleB' => 1], + ['Magento_ModuleA' => 0, 'Magento_ModuleB' => 1], + $successMessage, + ], + [ + ['Magento_ModuleA' => 1, 'Magento_ModuleB' => 1], + ['Magento_ModuleB' => 1, 'Magento_ModuleA' => 1], + $failureMessage, + ], + [ + ['Magento_ModuleA' => 0, 'Magento_ModuleB' => 1], + ['Magento_ModuleB' => 1, 'Magento_ModuleA' => 0], + $failureMessage, + ], + [ + ['Magento_ModuleA' => 1], + ['Magento_ModuleB' => 1, 'Magento_ModuleA' => 1], + $failureMessage, + ], + [ + ['Magento_ModuleA' => 1, 'Magento_ModuleB' => 1], + ['Magento_ModuleB' => 1], + $failureMessage, + ], + ]; + } +}