. */ namespace SP\Domain\Upgrade\Services; use SP\Core\Application; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; use SP\Domain\Common\Services\Service; use SP\Domain\Config\Ports\ConfigDataInterface; use SP\Domain\Providers\FileLogHandlerProvider; use SP\Domain\Upgrade\Ports\UpgradeService; use SP\Infrastructure\File\FileException; use SP\Util\VersionUtil; use function SP\__u; use function SP\logger; /** * Class UpgradeBase */ abstract class UpgradeBase extends Service implements UpgradeService { protected ?ConfigDataInterface $configData = null; public function __construct(Application $application, FileLogHandlerProvider $fileLogHandler) { parent::__construct($application); $this->eventDispatcher->attach($fileLogHandler); } /** * @inheritDoc */ final public static function needsUpgrade(string $version): bool { return !empty($version) && VersionUtil::checkVersion($version, static::getUpgrades()); } abstract protected static function getUpgrades(): array; /** * @inheritDoc * @throws UpgradeException * @throws FileException */ final public function upgrade(string $version, ConfigDataInterface $configData): void { $this->configData = $configData; $class = get_class(); $this->eventDispatcher->notify( sprintf('upgrade.%s.start', $class), new Event( $this, EventMessage::factory()->addDescription(__u('Update'))->addDetail('type', $class) ) ); $upgradeVersions = array_filter( static::getUpgrades(), static fn(string $appVersion) => VersionUtil::checkVersion($version, $appVersion) ); foreach ($upgradeVersions as $upgradeVersion) { if ($this->applyUpgrade($upgradeVersion) === false) { throw UpgradeException::critical( __u('Error while applying the update'), __u('Please, check the event log for more details') ); } logger('Upgrade: ' . $upgradeVersion); $this->commitVersion($upgradeVersion); $this->config->save($configData, false); } $this->eventDispatcher->notify( sprintf('upgrade.%s.end', $class), new Event( $this, EventMessage::factory()->addDescription(__u('Update'))->addDetail('type', $class) ) ); } abstract protected function applyUpgrade(string $version): bool; abstract protected function commitVersion(string $version): void; }