From 977b9adeff10f465295863dbb79e7100bdcbcd49 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Fri, 5 Apr 2024 12:17:00 +0300 Subject: [PATCH] migrations dev --- .../Espo/Core/Upgrades/Actions/Base.php | 7 ++- .../Core/Upgrades/Actions/Upgrade/Install.php | 51 ++++++++++++++++++- .../Espo/Core/Upgrades/Migration/Runner.php | 3 +- .../{StepsExtractor.php => VersionUtil.php} | 21 +++++--- .../Upgrades/Migration/StepsExtractorTest.php | 34 ++++--------- 5 files changed, 79 insertions(+), 37 deletions(-) rename application/Espo/Core/Upgrades/Migration/{StepsExtractor.php => VersionUtil.php} (86%) diff --git a/application/Espo/Core/Upgrades/Actions/Base.php b/application/Espo/Core/Upgrades/Actions/Base.php index c289a35775..e0ed69d056 100644 --- a/application/Espo/Core/Upgrades/Actions/Base.php +++ b/application/Espo/Core/Upgrades/Actions/Base.php @@ -131,7 +131,7 @@ abstract class Base return $this->getContainer()->getByClass(FileManager::class); } - private function getConfig(): Config + protected function getConfig(): Config { return $this->getContainer()->getByClass(Config::class); } @@ -141,6 +141,11 @@ abstract class Base return $this->getContainer()->getByClass(EntityManager::class); } + protected function getInjectableFactory(): InjectableFactory + { + return $this->getContainer()->getByClass(InjectableFactory::class); + } + protected function createConfigWriter(): ConfigWriter { $injectableFactory = $this->getContainer()->getByClass(InjectableFactory::class); diff --git a/application/Espo/Core/Upgrades/Actions/Upgrade/Install.php b/application/Espo/Core/Upgrades/Actions/Upgrade/Install.php index e38c5063fc..49a0a3d28e 100644 --- a/application/Espo/Core/Upgrades/Actions/Upgrade/Install.php +++ b/application/Espo/Core/Upgrades/Actions/Upgrade/Install.php @@ -30,6 +30,9 @@ namespace Espo\Core\Upgrades\Actions\Upgrade; use Espo\Core\Exceptions\Error; +use Espo\Core\Upgrades\Migration\Script; +use Espo\Core\Upgrades\Migration\VersionUtil; +use RuntimeException; class Install extends \Espo\Core\Upgrades\Actions\Base\Install { @@ -49,6 +52,7 @@ class Install extends \Espo\Core\Upgrades\Actions\Base\Install public function stepAfterUpgradeScript(array $data): void { $this->stepAfterInstallScript($data); + $this->runMigrationAfterInstallScript(); } /** @@ -82,9 +86,54 @@ class Install extends \Espo\Core\Upgrades\Actions\Base\Install $version = $this->getManifest()['version']; if (!$version) { - throw new Error("No 'version' in manifest."); + throw new RuntimeException("No 'version' in manifest."); } return $version; } + + /** + * @throws Error + */ + private function runMigrationAfterInstallScript(): void + { + $targetVersion = $this->getTargetVersion(); + $version = $this->getConfig()->get('version'); + + if (!$version || !is_string($version)) { + throw new RuntimeException("No or bad 'version' in config."); + } + + $script = $this->getMigrationAfterInstallScript($version, $targetVersion); + + if (!$script) { + return; + } + + $script->run(); + } + + private function getMigrationAfterInstallScript(string $version, string $targetVersion): ?Script + { + $isPatch = VersionUtil::isPatch($version, $targetVersion); + $a = VersionUtil::split($targetVersion); + + $dir = $isPatch ? + 'V' . $a[0] . '_' . $a[1] . '_' . $a[2] : + 'V' . $a[0] . '_' . $a[1]; + + $className = "Espo\\Core\\Upgrades\\Migrations\\$dir\\AfterUpgrade"; + + if (!class_exists($className)) { + return null; + } + + $script = $this->getInjectableFactory()->create($className); + + if (!$script instanceof Script) { + throw new RuntimeException("$className does not implement Script interface."); + } + + return $script; + } } diff --git a/application/Espo/Core/Upgrades/Migration/Runner.php b/application/Espo/Core/Upgrades/Migration/Runner.php index 1b017f6bf5..9cb35f2c1c 100644 --- a/application/Espo/Core/Upgrades/Migration/Runner.php +++ b/application/Espo/Core/Upgrades/Migration/Runner.php @@ -35,7 +35,6 @@ use RuntimeException; class Runner { public function __construct( - private StepsExtractor $stepsExtractor, private StepsProvider $stepsProvider, private VersionDataProvider $versionDataProvider, private StepRunner $stepRunner @@ -47,7 +46,7 @@ class Runner $targetVersion = $this->versionDataProvider->getTargetVersion(); $fullList = $this->stepsProvider->getAfterUpgrade(); - $steps = $this->stepsExtractor->extract($version, $targetVersion, $fullList); + $steps = VersionUtil::extractSteps($version, $targetVersion, $fullList); if ($steps === []) { $io->writeLine(" No migrations to run."); diff --git a/application/Espo/Core/Upgrades/Migration/StepsExtractor.php b/application/Espo/Core/Upgrades/Migration/VersionUtil.php similarity index 86% rename from application/Espo/Core/Upgrades/Migration/StepsExtractor.php rename to application/Espo/Core/Upgrades/Migration/VersionUtil.php index 94a3737f6c..7e5a6623ff 100644 --- a/application/Espo/Core/Upgrades/Migration/StepsExtractor.php +++ b/application/Espo/Core/Upgrades/Migration/VersionUtil.php @@ -32,20 +32,17 @@ namespace Espo\Core\Upgrades\Migration; use RuntimeException; use const SORT_STRING; -class StepsExtractor +class VersionUtil { /** * @param string[] $fullList * @return string[] */ - public function extract(string $from, string $to, array $fullList): array + public static function extractSteps(string $from, string $to, array $fullList): array { sort($fullList, SORT_STRING); - $aFrom = self::split($from); - $aTo = self::split($to); - - $isHotfix = $aFrom[0] === $aTo[0] && $aFrom[1] === $aTo[1]; + $isPatch = self::isPatch($from, $to); $list = []; @@ -62,7 +59,7 @@ class StepsExtractor continue; } - if (!$isHotfix && $a[2] !== null) { + if (!$isPatch && $a[2] !== null) { continue; } @@ -75,7 +72,7 @@ class StepsExtractor /** * @return array{string, string, ?string} */ - private static function split(string $version): array + public static function split(string $version): array { $array = explode('.', $version, 3); @@ -90,4 +87,12 @@ class StepsExtractor /** @var array{string, string, string} */ return $array; } + + public static function isPatch(string $from, string $to): bool + { + $aFrom = self::split($from); + $aTo = self::split($to); + + return $aFrom[0] === $aTo[0] && $aFrom[1] === $aTo[1]; + } } diff --git a/tests/unit/Espo/Core/Upgrades/Migration/StepsExtractorTest.php b/tests/unit/Espo/Core/Upgrades/Migration/StepsExtractorTest.php index 45c3399f9b..7153213754 100644 --- a/tests/unit/Espo/Core/Upgrades/Migration/StepsExtractorTest.php +++ b/tests/unit/Espo/Core/Upgrades/Migration/StepsExtractorTest.php @@ -29,16 +29,14 @@ namespace tests\unit\Espo\Core\Upgrades\Migration; -use Espo\Core\Upgrades\Migration\StepsExtractor; +use Espo\Core\Upgrades\Migration\VersionUtil; use PHPUnit\Framework\TestCase; class StepsExtractorTest extends TestCase { public function testGet1(): void { - $extractor = new StepsExtractor(); - - $list = $extractor->extract('8.0.0', '8.3.0', [ + $list = VersionUtil::extractSteps('8.0.0', '8.3.0', [ '7.0', '7.5', '8.0', @@ -56,9 +54,7 @@ class StepsExtractorTest extends TestCase public function testGet2(): void { - $extractor = new StepsExtractor(); - - $list = $extractor->extract('8.0.0', '8.3.1', [ + $list = VersionUtil::extractSteps('8.0.0', '8.3.1', [ '7.0', '7.5', '8.0', @@ -76,9 +72,7 @@ class StepsExtractorTest extends TestCase public function testGet3(): void { - $extractor = new StepsExtractor(); - - $list = $extractor->extract('8.0.0', '8.3.5', [ + $list = VersionUtil::extractSteps('8.0.0', '8.3.5', [ '7.0', '7.5', '8.0', @@ -96,9 +90,7 @@ class StepsExtractorTest extends TestCase public function testGet4(): void { - $extractor = new StepsExtractor(); - - $list = $extractor->extract('8.2.0', '8.3.5', [ + $list = VersionUtil::extractSteps('8.2.0', '8.3.5', [ '7.0', '7.5', '8.0', @@ -115,9 +107,7 @@ class StepsExtractorTest extends TestCase public function testGet5(): void { - $extractor = new StepsExtractor(); - - $list = $extractor->extract('8.0.4', '8.3.5', [ + $list = VersionUtil::extractSteps('8.0.4', '8.3.5', [ '7.0', '7.5', '8.0', @@ -135,9 +125,7 @@ class StepsExtractorTest extends TestCase public function testGetMajor1(): void { - $extractor = new StepsExtractor(); - - $list = $extractor->extract('7.5.4', '8.3.5', array_reverse([ + $list = VersionUtil::extractSteps('7.5.4', '8.3.5', array_reverse([ '7.0', '7.5', '7.5.1', @@ -160,9 +148,7 @@ class StepsExtractorTest extends TestCase public function testGetPatch1(): void { - $extractor = new StepsExtractor(); - - $list = $extractor->extract('8.3.0', '8.3.5', [ + $list = VersionUtil::extractSteps('8.3.0', '8.3.5', [ '7.0', '7.5', '8.0', @@ -181,9 +167,7 @@ class StepsExtractorTest extends TestCase public function testGetPatch2(): void { - $extractor = new StepsExtractor(); - - $list = $extractor->extract('8.3.0', '8.3.5', [ + $list = VersionUtil::extractSteps('8.3.0', '8.3.5', [ '7.0', '7.5', '8.0',