/
githubmirror
/
magento2
Обзор
Документация
Войти
/
githubmirror
/
magento2
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
2.4-develop
setup/src/Magento/Setup/Console/Command/UpgradeCommand.php
299 строк
11 KB
Darshan Modi
Revert "AC-17283: RabbitMQ 4.3 compatibility"
12 июн 2026, 10:38
12 июн 2026, 10:38
ea41d1f
Код
Авторство
О чём код?
<?php /** * Copyright 2015 Adobe * All Rights Reserved. */ namespace Magento\Setup\Console\Command; use Magento\Amqp\Setup\ConnectionValidator; use Magento\Deploy\Console\Command\App\ConfigImportCommand; use Magento\Framework\App\DeploymentConfig; use Magento\Framework\App\ObjectManager; use Magento\Framework\App\State as AppState; use Magento\Framework\Config\CacheInterface; use Magento\Framework\Console\Cli; use Magento\Framework\Exception\RuntimeException; use Magento\Framework\Setup\ConsoleLogger; use Magento\Framework\Setup\Declaration\Schema\DryRunLogger; use Magento\Framework\Setup\Declaration\Schema\OperationsExecutor; use Magento\Setup\Model\DbInitStatementsCleanup; use Magento\Setup\Model\InstallerFactory; use Magento\Setup\Model\SearchConfigFactory; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * Command for updating installed application after the code base has changed. * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class UpgradeCommand extends AbstractSetupCommand { /** * Option to skip deletion of generated/code directory. */ public const INPUT_KEY_KEEP_GENERATED = 'keep-generated'; public const NAME = 'setup:upgrade'; /** * Installer service factory. * * @var InstallerFactory */ private $installerFactory; /** * @var DeploymentConfig */ private $deploymentConfig; /** * @var AppState */ private $appState; /** * @var SearchConfigFactory */ private $searchConfigFactory; /** * @var CacheInterface */ private $cache; /** * @var DbInitStatementsCleanup */ private $dbInitStatementsCleanup; /** * @param InstallerFactory $installerFactory * @param SearchConfigFactory $searchConfigFactory * @param DeploymentConfig $deploymentConfig * @param AppState|null $appState * @param CacheInterface|null $cache * @param DbInitStatementsCleanup|null $dbInitStatementsCleanup */ public function __construct( InstallerFactory $installerFactory, SearchConfigFactory $searchConfigFactory, ?DeploymentConfig $deploymentConfig = null, ?AppState $appState = null, ?CacheInterface $cache = null, ?DbInitStatementsCleanup $dbInitStatementsCleanup = null ) { $this->installerFactory = $installerFactory; $this->searchConfigFactory = $searchConfigFactory; $this->deploymentConfig = $deploymentConfig ?: ObjectManager::getInstance()->get(DeploymentConfig::class); $this->appState = $appState ?: ObjectManager::getInstance()->get(AppState::class); $this->cache = $cache ?: ObjectManager::getInstance()->get(CacheInterface::class); $this->dbInitStatementsCleanup = $dbInitStatementsCleanup ?: ObjectManager::getInstance()->get(DbInitStatementsCleanup::class); parent::__construct(); } /** * @inheritdoc */ protected function configure() { $options = [ new InputOption( self::INPUT_KEY_KEEP_GENERATED, null, InputOption::VALUE_NONE, 'Prevents generated files from being deleted. ' . PHP_EOL . 'We discourage using this option except when deploying to production. ' . PHP_EOL . 'Consult your system integrator or administrator for more information.' ), new InputOption( InstallCommand::CONVERT_OLD_SCRIPTS_KEY, null, InputOption::VALUE_OPTIONAL, 'Allows to convert old scripts (InstallSchema, UpgradeSchema) to db_schema.xml format', false ), new InputOption( OperationsExecutor::KEY_SAFE_MODE, null, InputOption::VALUE_OPTIONAL, 'Safe installation of Magento with dumps on destructive operations, like column removal' ), new InputOption( OperationsExecutor::KEY_DATA_RESTORE, null, InputOption::VALUE_OPTIONAL, 'Restore removed data from dumps' ), new InputOption( DryRunLogger::INPUT_KEY_DRY_RUN_MODE, null, InputOption::VALUE_OPTIONAL, 'Magento Installation will be run in dry-run mode', false ) ]; $this->setName(self::NAME) ->setDescription('Upgrades the Magento application, DB data, and schema') ->setDefinition($options); parent::configure(); } /** * @inheritdoc */ protected function execute(InputInterface $input, OutputInterface $output): int { try { $request = $input->getOptions(); $keepGenerated = $input->getOption(self::INPUT_KEY_KEEP_GENERATED); // Clean up deprecated 'SET NAMES utf8;' from database connections $output->writeln('<info>Cleaning up deprecated SET NAMES utf8 from database connections...</info>'); $this->dbInitStatementsCleanup->execute(); $this->deploymentConfig->resetData(); $installer = $this->installerFactory->create(new ConsoleLogger($output)); $installer->updateModulesSequence($keepGenerated); $searchConfig = $this->searchConfigFactory->create(); $this->cache->clean(); $searchConfig->validateSearchEngine(); $amqpVersionError = $this->validateAmqpVersion(); if ($amqpVersionError !== null) { $output->writeln('<error>' . $amqpVersionError . '</error>'); return Cli::RETURN_FAILURE; } $installer->installSchema($request); $installer->removeUnusedTriggers(); $installer->installDataFixtures($request, true); if ($this->deploymentConfig->isAvailable()) { $importConfigCommand = $this->getApplication()->find(ConfigImportCommand::COMMAND_NAME); $arrayInput = new ArrayInput([]); $arrayInput->setInteractive($input->isInteractive()); $result = $importConfigCommand->run($arrayInput, $output); if ($result === Cli::RETURN_FAILURE) { throw new RuntimeException( __('%1 failed. See previous output.', ConfigImportCommand::COMMAND_NAME) ); } } if (!$keepGenerated && $this->appState->getMode() === AppState::MODE_PRODUCTION) { $output->writeln( '<info>Please re-run Magento compile command. Use the command "setup:di:compile"</info>' ); } $output->writeln( "<info>Media files stored outside of 'Media Gallery Allowed' folders" . " will not be available to the media gallery.</info>" ); $output->writeln( '<info>Please refer to Developer Guide for more details.</info>' ); // Add standardized success message for deployment script parsing $output->writeln('<info>Upgrade completed successfully.</info>'); } catch (\Exception $e) { $output->writeln('<error>' . $e->getMessage() . '</error>'); // Add standardized failure message for deployment script parsing $output->writeln('<error>Upgrade failed: ' . $e->getMessage() . '</error>'); return Cli::RETURN_FAILURE; } return Cli::RETURN_SUCCESS; } /** * Validate RabbitMQ version from deployment configuration. * * Reads AMQP settings from env.php and checks the running RabbitMQ server * version against the minimum requirement. Skips validation if AMQP is * not configured or if the server version cannot be determined. * * ConnectionValidator is resolved lazily via ObjectManager at execution time * (after updateModulesSequence) to ensure the proper DI context is available, * since the setup bootstrap may reset generated files and caches. * * @return string|null Error message if validation fails, null if validation passes */ private function validateAmqpVersion(): ?string { $defaultConnection = $this->deploymentConfig->get('queue/default_connection'); if ($defaultConnection && $defaultConnection !== 'amqp') { return null; } $amqpConfig = $this->deploymentConfig->get('queue/amqp'); if (empty($amqpConfig['host'])) { return null; } try { /** @var ConnectionValidator $connectionValidator */ $connectionValidator = ObjectManager::getInstance()->get(ConnectionValidator::class); } catch (\Exception) { return null; } $version = $this->detectServerVersion($connectionValidator, $amqpConfig); if ($version !== null && version_compare($version, ConnectionValidator::MINIMUM_RABBITMQ_VERSION, '<') ) { return sprintf( 'RabbitMQ version "%s" detected. Magento requires RabbitMQ version %s or later. ' . 'Please upgrade RabbitMQ and rerun setup.', $version, ConnectionValidator::MINIMUM_RABBITMQ_VERSION ); } return null; } /** * Retrieve RabbitMQ server version. * * @param ConnectionValidator $connectionValidator * @param array $amqpConfig * @return string|null */ private function detectServerVersion(ConnectionValidator $connectionValidator, array $amqpConfig): ?string { $isSsl = ($amqpConfig['ssl'] ?? '') !== '' && $amqpConfig['ssl'] !== 'false'; return $connectionValidator->getServerVersion( $amqpConfig['host'], $amqpConfig['port'] ?? '5672', $amqpConfig['user'] ?? '', $amqpConfig['password'] ?? '', $amqpConfig['virtualhost'] ?? '/', (bool)$isSsl, $this->getSslOptions($amqpConfig) ); } /** * Parse SSL options from configuration. * * @param array $amqpConfig * @return array|null */ private function getSslOptions(array $amqpConfig): ?array { $sslOptions = $amqpConfig['ssl_options'] ?? null; if (is_string($sslOptions)) { return json_decode($sslOptions, true); } return is_array($sslOptions) ? $sslOptions : null; } }