From 5af30a96c3aa8b8c96ff53a0387d492879cb7b98 Mon Sep 17 00:00:00 2001 From: Morgan Pichat Date: Fri, 2 Aug 2024 14:41:49 +0200 Subject: [PATCH] Add check requirements command --- README.md | 8 +- bin/console | 2 + classes/Commands/CheckRequirementsCommand.php | 156 ++++++++++++++++++ classes/Log/CliLogger.php | 2 + classes/Xml/ChecksumCompare.php | 12 +- 5 files changed, 173 insertions(+), 7 deletions(-) create mode 100644 classes/Commands/CheckRequirementsCommand.php diff --git a/README.md b/README.md index 2d39ecc8c..d99b8280a 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,13 @@ To use the Symfony Console, simply run the following command from the root direc $ php bin/console ``` -For instance, to start upgrading your store, you would use: +The requirements can be reviewed to confirm the shop is safe to update: + +``` +$ php bin/console update:check +``` + +The update process can be launched with: ``` $ php bin/console update:start --config-file-path=[/path/to/config.json] --chain diff --git a/bin/console b/bin/console index 17e67d459..a541cef4b 100755 --- a/bin/console +++ b/bin/console @@ -26,6 +26,7 @@ * @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0) */ +use PrestaShop\Module\AutoUpgrade\Commands\CheckRequirementsCommand; use PrestaShop\Module\AutoUpgrade\Commands\RestoreCommand; use PrestaShop\Module\AutoUpgrade\Commands\UpdateCommand; use Symfony\Component\Console\Application; @@ -44,6 +45,7 @@ $application = new Application(); $application->add(new UpdateCommand()); $application->add(new RestoreCommand()); +$application->add(new CheckRequirementsCommand()); try { $application->run(); diff --git a/classes/Commands/CheckRequirementsCommand.php b/classes/Commands/CheckRequirementsCommand.php new file mode 100644 index 000000000..f5746105f --- /dev/null +++ b/classes/Commands/CheckRequirementsCommand.php @@ -0,0 +1,156 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0) + */ + +namespace PrestaShop\Module\AutoUpgrade\Commands; + +use Exception; +use PrestaShop\Module\AutoUpgrade\Services\DistributionApiService; +use PrestaShop\Module\AutoUpgrade\Task\ExitCode; +use PrestaShop\Module\AutoUpgrade\UpgradeSelfCheck; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class CheckRequirementsCommand extends AbstractCommand +{ + /** @var string */ + protected static $defaultName = 'update:check'; + const MODULE_CONFIG_DIR = 'autoupgrade'; + /** @var UpgradeSelfCheck */ + private $upgradeSelfCheck; + /** @var OutputInterface */ + private $output; + /** @var int */ + private $exitCode; + + protected function configure(): void + { + $this + ->setDescription('Check all prerequisites for an update.') + ->setHelp('This command allows you to check the prerequisites necessary for the proper functioning of an update.') + ->addArgument('admin-dir', InputArgument::REQUIRED, 'The admin directory name.'); + } + + /** + * @throws Exception + */ + protected function execute(InputInterface $input, OutputInterface $output): ?int + { + $this->setupContainer($input, $output); + $this->output = $output; + + $moduleConfigPath = _PS_ADMIN_DIR_ . DIRECTORY_SEPARATOR . self::MODULE_CONFIG_DIR; + + $this->upgradeContainer->initPrestaShopAutoloader(); + $this->upgradeContainer->initPrestaShopCore(); + + $this->upgradeSelfCheck = new UpgradeSelfCheck( + $this->upgradeContainer->getUpgrader(), + $this->upgradeContainer->getPrestaShopConfiguration(), + $this->upgradeContainer->getTranslator(), + new DistributionApiService(), + $this->upgradeContainer->getChecksumCompare(), + _PS_ROOT_DIR_, + _PS_ADMIN_DIR_, + $moduleConfigPath, + $this->upgradeContainer->getState()->getOriginVersion() + ); + + $output->writeln('Result of prerequisite checks:'); + $this->exitCode = ExitCode::SUCCESS; + $this->processRequirementWarnings(); + $this->processRequirementErrors(); + + if ($this->exitCode === ExitCode::SUCCESS) { + $output->writeln(' All prerequisites meet the conditions for an update.'); + } + + return $this->exitCode; + } + + /** + * @throws Exception + */ + private function processRequirementErrors(): void + { + foreach ($this->upgradeSelfCheck->getErrors() as $error => $value) { + switch ($error) { + case UpgradeSelfCheck::NOT_LOADED_PHP_EXTENSIONS_LIST_NOT_EMPTY: + $notLoadedPhpExtensions = $this->upgradeSelfCheck->getNotLoadedPhpExtensions(); + $this->writeError($this->upgradeSelfCheck->getRequirementWording($error)); + foreach ($notLoadedPhpExtensions as $notLoadedPhpExtension) { + $this->output->writeln(' ' . $notLoadedPhpExtension); + } + break; + case UpgradeSelfCheck::NOT_EXIST_PHP_FUNCTIONS_LIST_NOT_EMPTY: + $notExistsPhpFunctions = $this->upgradeSelfCheck->getNotExistsPhpFunctions(); + $this->writeError($this->upgradeSelfCheck->getRequirementWording($error)); + foreach ($notExistsPhpFunctions as $notExistsPhpFunction) { + $this->output->writeln(' ' . $notExistsPhpFunction); + } + break; + case UpgradeSelfCheck::NOT_WRITING_DIRECTORY_LIST_NOT_EMPTY: + $notWritingDirectories = $this->upgradeSelfCheck->getNotWritingDirectories(); + $this->writeError($this->upgradeSelfCheck->getRequirementWording($error)); + foreach ($notWritingDirectories as $notWritingDirectory) { + $this->output->writeln(' ' . $notWritingDirectory); + } + break; + default: + $this->writeError($this->upgradeSelfCheck->getRequirementWording($error)); + } + } + } + + private function processRequirementWarnings(): void + { + foreach ($this->upgradeSelfCheck->getWarnings() as $warning => $value) { + switch ($warning) { + case UpgradeSelfCheck::TEMPERED_FILES_LIST_NOT_EMPTY: + $tamperedFiles = $this->upgradeSelfCheck->getTamperedFiles(); + $this->writeWarning($this->upgradeSelfCheck->getRequirementWording($warning)); + foreach ($tamperedFiles as $tamperedFile) { + $this->output->writeln(' ' . $tamperedFile); + } + break; + default: + $this->writeWarning($this->upgradeSelfCheck->getRequirementWording($warning)); + } + } + } + + private function writeWarning(string $message): void + { + $this->output->writeln(' ' . $message); + } + + private function writeError(string $message): void + { + $this->exitCode = ExitCode::FAIL; + $this->output->writeln(' ' . $message); + } +} diff --git a/classes/Log/CliLogger.php b/classes/Log/CliLogger.php index a6cc896b4..0f29c7142 100644 --- a/classes/Log/CliLogger.php +++ b/classes/Log/CliLogger.php @@ -60,9 +60,11 @@ class CliLogger extends Logger public function __construct(OutputInterface $output) { + $successStyle = new OutputFormatterStyle('green', null, []); $warningStyle = new OutputFormatterStyle('yellow', null, []); $errorStyle = new OutputFormatterStyle('red', null, []); $criticalStyle = new OutputFormatterStyle('red', null, ['bold']); + $output->getFormatter()->setStyle('success', $successStyle); $output->getFormatter()->setStyle('warning', $warningStyle); $output->getFormatter()->setStyle('error', $errorStyle); $output->getFormatter()->setStyle('critical', $criticalStyle); diff --git a/classes/Xml/ChecksumCompare.php b/classes/Xml/ChecksumCompare.php index 3781ca1e0..05dc748d7 100644 --- a/classes/Xml/ChecksumCompare.php +++ b/classes/Xml/ChecksumCompare.php @@ -168,15 +168,15 @@ protected function browseXmlAndCompare(SimpleXMLElement $node, array &$current_p $relative_path .= (string) $child['name']; // TODO: Drop use of constants and use args instead - $fullpath = _PS_ROOT_DIR_ . DIRECTORY_SEPARATOR . $relative_path; - $fullpath = str_replace('ps_root_dir', _PS_ROOT_DIR_, $fullpath); + $fullPath = _PS_ROOT_DIR_ . DIRECTORY_SEPARATOR . $relative_path; + $fullPath = str_replace('ps_root_dir', _PS_ROOT_DIR_, $fullPath); // replace default admin dir by current one - $fullpath = str_replace(_PS_ROOT_DIR_ . '/admin', _PS_ADMIN_DIR_, $fullpath); - $fullpath = str_replace(_PS_ROOT_DIR_ . DIRECTORY_SEPARATOR . 'admin', _PS_ADMIN_DIR_, $fullpath); - if (!file_exists($fullpath)) { + $fullPath = str_replace(_PS_ROOT_DIR_ . '/admin', _PS_ADMIN_DIR_, $fullPath); + $fullPath = str_replace(_PS_ROOT_DIR_ . DIRECTORY_SEPARATOR . 'admin', _PS_ADMIN_DIR_, $fullPath); + if (!file_exists($fullPath)) { // Not stored in a list as we do nothing with it. - } elseif (!$this->compareChecksum($fullpath, (string) $child) && substr(str_replace(DIRECTORY_SEPARATOR, '-', $relative_path), 0, 19) != 'modules/autoupgrade') { + } elseif (!$this->compareChecksum($fullPath, (string) $child) && substr(str_replace(DIRECTORY_SEPARATOR, '-', $relative_path), 0, 7) != 'modules') { $this->addChangedFile($relative_path); } // else, file is original (and ok)