Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
72.92% covered (warning)
72.92%
35 / 48
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
SetupRunner
72.92% covered (warning)
72.92%
35 / 48
50.00% covered (danger)
50.00%
1 / 2
10.61
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
1
 execute
64.86% covered (warning)
64.86%
24 / 37
0.00% covered (danger)
0.00%
0 / 1
10.78
1<?php
2
3declare(strict_types=1);
4
5namespace PeServer\App\Models\Setup;
6
7use PeServer\App\Models\AppConfiguration;
8use PeServer\App\Models\Setup\Versions\SetupVersion_0000;
9use PeServer\App\Models\Setup\Versions\SetupVersion_0001;
10use PeServer\App\Models\Setup\Versions\SetupVersion_0002;
11use PeServer\App\Models\Setup\Versions\SetupVersion_0003;
12use PeServer\App\Models\Setup\Versions\SetupVersion_0004;
13use PeServer\App\Models\Setup\Versions\SetupVersion_0005;
14use PeServer\App\Models\Setup\Versions\SetupVersion_0006;
15use PeServer\App\Models\Setup\Versions\SetupVersionBase;
16use PeServer\App\Models\Setup\Versions\SetupVersionLast;
17use PeServer\Core\Collection\Arr;
18use PeServer\Core\Database\DatabaseUtility;
19use PeServer\Core\Database\IDatabaseConnection;
20use PeServer\Core\Database\IDatabaseContext;
21use PeServer\Core\IO\File;
22use PeServer\Core\Log\ILogger;
23use PeServer\Core\Log\ILoggerFactory;
24use PeServer\Core\Text;
25
26class SetupRunner
27{
28    #region variable
29
30    /**
31     * @var class-string<SetupVersionBase>[]
32     */
33    private array $versions;
34
35    private ILogger $logger;
36
37    #endregion
38
39    public function __construct(
40        private IDatabaseConnection $defaultConnection,
41        private AppConfiguration $appConfig,
42        private ILoggerFactory $loggerFactory
43    ) {
44        $this->logger = $loggerFactory->createLogger($this);
45
46        /** @var class-string<SetupVersionBase>[] */
47        $versions = [
48            SetupVersion_0000::class,
49            SetupVersion_0001::class,
50            SetupVersion_0002::class,
51            SetupVersion_0003::class,
52            SetupVersion_0004::class,
53            SetupVersion_0005::class,
54            SetupVersion_0006::class,
55        ];
56        // 定義ミス対応としてバージョン間並べ替え(ミスるな)
57        $this->versions = Arr::sortCallbackByValue($versions, fn ($a, $b) => SetupVersionBase::getVersion($a) <=> SetupVersionBase::getVersion($b));
58    }
59
60    #region function
61
62    public function execute(): void
63    {
64        $dbVersion = -1;
65        // SQLite を使うのは決定事項である!
66        $connectionSetting = $this->defaultConnection->getConnectionSetting();
67
68        if (!DatabaseUtility::isSqliteMemoryMode($connectionSetting)) {
69            $filePath = DatabaseUtility::getSqliteFilePath($connectionSetting);
70
71            if (File::exists($filePath)) {
72                $this->logger->info('DBあり: {0}', $filePath);
73
74                $context = $this->defaultConnection->open();
75                $checkCount = $context->selectSingleCount("select COUNT(*) from sqlite_master where sqlite_master.type='table' and sqlite_master.name='database_version'");
76                if (0 < $checkCount) {
77                    $row = $context->queryFirstOrNull("select version from database_version");
78                    if ($row !== null) {
79                        $dbVersion = (int)$row->fields['version'];
80                        ;
81                    }
82                }
83            }
84        }
85
86        $this->logger->info('DBバージョン: {0}', $dbVersion);
87
88        $newVersion = 0;
89        $context = $this->defaultConnection->open();
90        $context->execute('PRAGMA foreign_keys = OFF;');
91
92        $context->transaction(function (IDatabaseContext $context) use ($dbVersion, &$newVersion) {
93            // ええねん、SQLite しか使わん
94            $ioArg = new IOSetupArgument();
95            $dbArg = new DatabaseSetupArgument($context);
96
97            foreach ($this->versions as $version) {
98                $ver = SetupVersionBase::getVersion($version);
99                if ($ver <= $dbVersion) {
100                    $this->logger->info('無視バージョン: {0}', $ver);
101                    continue;
102                }
103
104                $this->logger->info('VERSION: {0}', $version);
105
106                /** @var SetupVersionBase */
107                $setupVersion = new $version($this->appConfig, $this->loggerFactory);
108                $setupVersion->migrate($ioArg, $dbArg);
109                $newVersion = $ver;
110            }
111
112            if ($dbVersion <= $newVersion) {
113                $setupLastVersion = new SetupVersionLast($dbVersion, $newVersion, $this->appConfig, $this->loggerFactory);
114                $setupLastVersion->migrate($ioArg, $dbArg);
115                $this->logger->info('DBバージョン更新: {0}', $newVersion);
116                return true;
117            }
118
119            $this->logger->info('DBバージョン未更新: {0}', $dbVersion);
120            return false;
121        });
122
123        $context->execute('PRAGMA foreign_keys = ON;');
124    }
125
126    #endregion
127}