From 5a6583b93b9dd4c9c43ce1323fc5ec388ddeaafa Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Fri, 5 Apr 2024 13:19:43 +0300 Subject: [PATCH] migrations dev --- .../Console/Commands/MigrationVersionStep.php | 28 +------- .../Upgrades/Migration/AfterUpgradeRunner.php | 65 +++++++++++++++++++ .../Espo/Core/Upgrades/Migration/Runner.php | 44 ++++++++++--- .../Core/Upgrades/Migration/StepRunner.php | 22 ++++++- .../Core/Upgrades/Migration/StepsProvider.php | 20 +++++- 5 files changed, 142 insertions(+), 37 deletions(-) create mode 100644 application/Espo/Core/Upgrades/Migration/AfterUpgradeRunner.php diff --git a/application/Espo/Core/Console/Commands/MigrationVersionStep.php b/application/Espo/Core/Console/Commands/MigrationVersionStep.php index 860ed3805e..cced09d562 100644 --- a/application/Espo/Core/Console/Commands/MigrationVersionStep.php +++ b/application/Espo/Core/Console/Commands/MigrationVersionStep.php @@ -32,10 +32,7 @@ namespace Espo\Core\Console\Commands; use Espo\Core\Console\Command; use Espo\Core\Console\Command\Params; use Espo\Core\Console\IO; -use Espo\Core\DataManager; -use Espo\Core\Exceptions\Error; -use Espo\Core\InjectableFactory; -use Espo\Core\Upgrades\Migration; +use Espo\Core\Upgrades\Migration\AfterUpgradeRunner; use RuntimeException; /** @@ -44,8 +41,7 @@ use RuntimeException; class MigrationVersionStep implements Command { public function __construct( - private InjectableFactory $injectableFactory, - private DataManager $dataManager + private AfterUpgradeRunner $afterUpgradeRunner ) {} public function run(Params $params, IO $io): void @@ -56,25 +52,7 @@ class MigrationVersionStep implements Command throw new RuntimeException("No step parameter."); } - $dir = 'V' . str_replace('.', '_', $step); - - /** @var class-string $className */ - $className = "Espo\\Core\\Upgrades\\Migrations\\$dir\\AfterUpgrade"; - - if (!class_exists($className)) { - $io->writeLine("No after-upgrade script."); - } - - /** @var Migration\Script $script */ - $script = $this->injectableFactory->create($className); - $script->run(); - - try { - $this->dataManager->rebuild(); - } - catch (Error $e) { - throw new RuntimeException("Error while rebuild: " . $e->getMessage()); - } + $this->afterUpgradeRunner->run($step); $io->writeLine("Done."); } diff --git a/application/Espo/Core/Upgrades/Migration/AfterUpgradeRunner.php b/application/Espo/Core/Upgrades/Migration/AfterUpgradeRunner.php new file mode 100644 index 0000000000..1c30ed3707 --- /dev/null +++ b/application/Espo/Core/Upgrades/Migration/AfterUpgradeRunner.php @@ -0,0 +1,65 @@ +. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. + ************************************************************************/ + +namespace Espo\Core\Upgrades\Migration; + +use Espo\Core\DataManager; +use Espo\Core\Exceptions\Error; +use Espo\Core\InjectableFactory; +use RuntimeException; + +class AfterUpgradeRunner +{ + public function __construct( + private InjectableFactory $injectableFactory, + private DataManager $dataManager + ) {} + + public function run(string $step): void + { + $dir = 'V' . str_replace('.', '_', $step); + + $className = "Espo\\Core\\Upgrades\\Migrations\\$dir\\AfterUpgrade"; + + if (!class_exists($className)) { + throw new RuntimeException("No after-upgrade script $step."); + } + + /** @var Script $script */ + $script = $this->injectableFactory->create($className); + $script->run(); + + try { + $this->dataManager->rebuild(); + } + catch (Error $e) { + throw new RuntimeException("Error while rebuild: " . $e->getMessage()); + } + } +} diff --git a/application/Espo/Core/Upgrades/Migration/Runner.php b/application/Espo/Core/Upgrades/Migration/Runner.php index 9cb35f2c1c..50a1e4700e 100644 --- a/application/Espo/Core/Upgrades/Migration/Runner.php +++ b/application/Espo/Core/Upgrades/Migration/Runner.php @@ -30,6 +30,7 @@ namespace Espo\Core\Upgrades\Migration; use Espo\Core\Console\IO; +use Exception; use RuntimeException; class Runner @@ -45,27 +46,38 @@ class Runner $version = $this->versionDataProvider->getPreviousVersion(); $targetVersion = $this->versionDataProvider->getTargetVersion(); - $fullList = $this->stepsProvider->getAfterUpgrade(); - $steps = VersionUtil::extractSteps($version, $targetVersion, $fullList); + $fullPrepareSteps = $this->stepsProvider->getPrepare(); + $prepareSteps = VersionUtil::extractSteps($version, $targetVersion, $fullPrepareSteps); - if ($steps === []) { + if ($prepareSteps !== []) { + $io->write(" Running prepare migrations..."); + + foreach ($prepareSteps as $step) { + $this->runPrepareStep($io, $step); + } + } + + $fullAfterSteps = $this->stepsProvider->getAfterUpgrade(); + $afterSteps = VersionUtil::extractSteps($version, $targetVersion, $fullAfterSteps); + + if ($afterSteps === []) { $io->writeLine(" No migrations to run."); return; } - $io->write(" Running migrations..."); + $io->write(" Running after-upgrade migrations..."); - foreach ($steps as $step) { - $this->runVersionStep($io, $step); + foreach ($afterSteps as $step) { + $this->runAfterUpgradeStep($io, $step); } } - private function runVersionStep(IO $io, string $step): void + private function runAfterUpgradeStep(IO $io, string $step): void { $io->write(" $step..."); - $isSuccessful = $this->stepRunner->run($step); + $isSuccessful = $this->stepRunner->runAfterUpgrade($step); if ($isSuccessful) { $io->writeLine(" DONE"); @@ -77,4 +89,20 @@ class Runner throw new RuntimeException(); } + + private function runPrepareStep(IO $io, string $step): void + { + $io->write(" $step..."); + + try { + $this->stepRunner->runPrepare($step); + } + catch (Exception $e) { + $io->writeLine(" FAIL"); + + throw new RuntimeException($e->getMessage()); + } + + $io->writeLine(" DONE"); + } } diff --git a/application/Espo/Core/Upgrades/Migration/StepRunner.php b/application/Espo/Core/Upgrades/Migration/StepRunner.php index 851af6189c..ca16df1824 100644 --- a/application/Espo/Core/Upgrades/Migration/StepRunner.php +++ b/application/Espo/Core/Upgrades/Migration/StepRunner.php @@ -29,17 +29,20 @@ namespace Espo\Core\Upgrades\Migration; +use Espo\Core\InjectableFactory; use Espo\Core\Utils\Config; +use RuntimeException; use Symfony\Component\Process\PhpExecutableFinder; use Symfony\Component\Process\Process; class StepRunner { public function __construct( - private Config $config + private Config $config, + private InjectableFactory $injectableFactory ) {} - public function run(string $step): bool + public function runAfterUpgrade(string $step): bool { $phpExecutablePath = $this->getPhpExecutablePath(); @@ -52,6 +55,21 @@ class StepRunner return $process->isSuccessful(); } + public function runPrepare(string $step): void + { + $dir = 'V' . str_replace('.', '_', $step); + + $className = "Espo\\Core\\Upgrades\\Migrations\\$dir\\Prepare"; + + if (!class_exists($className)) { + throw new RuntimeException("No prepare script $step."); + } + + /** @var Script $script */ + $script = $this->injectableFactory->create($className); + $script->run(); + } + private function getPhpExecutablePath(): string { $phpExecutablePath = $this->config->get('phpExecutablePath'); diff --git a/application/Espo/Core/Upgrades/Migration/StepsProvider.php b/application/Espo/Core/Upgrades/Migration/StepsProvider.php index e0b2270dce..37e611e047 100644 --- a/application/Espo/Core/Upgrades/Migration/StepsProvider.php +++ b/application/Espo/Core/Upgrades/Migration/StepsProvider.php @@ -40,17 +40,33 @@ class StepsProvider private Manager $fileManager ) {} + /** + * @return string[] + */ + public function getPrepare(): array + { + return $this->get('Prepare'); + } + /** * @return string[] */ public function getAfterUpgrade(): array + { + return $this->get('AfterUpgrade'); + } + + /** + * @return string[] + */ + private function get(string $name): array { $list = $this->fileManager->getDirList($this->dir); - $list = array_filter($list, function ($item) { + $list = array_filter($list, function ($item) use ($name) { $dir = $this->dir . '/' . $item; - return $this->fileManager->isFile($dir . '/AfterUpgrade.php'); + return $this->fileManager->isFile("$dir/$name.php"); }); $list = array_values($list);