1 | <?php |
||
2 | |||
3 | require_once __DIR__ . '/../public/index.php'; |
||
4 | |||
5 | $settingName = 'databaseVersion'; // This is the setting name used in the database to store the version information |
||
6 | $sqlPath = __DIR__ . '/sql/'; // This is the path where all SQL patches resides |
||
7 | |||
8 | /** |
||
9 | * Returns the last version available in SQL file |
||
10 | * |
||
11 | * @return int last version of patches |
||
12 | */ |
||
13 | function getPatchVersion() |
||
14 | { |
||
15 | global $sqlPath; |
||
16 | $lastVersion = 0; |
||
17 | $d = dir($sqlPath); |
||
18 | while (false !== ($entry = $d->read())) { |
||
19 | if (preg_match('/^version\.(\d+)\.sql$/i', $entry, $a)) { |
||
20 | if ((int) $a[1] > $lastVersion) { |
||
21 | $lastVersion = (int) $a[1]; |
||
22 | } |
||
23 | } |
||
24 | } |
||
25 | $d->close(); |
||
26 | |||
27 | return $lastVersion; |
||
28 | } |
||
29 | |||
30 | /** |
||
31 | * Returns the whole SQL (enclosed in transaction) needed to update from |
||
32 | * specified version to specified target version. |
||
33 | * |
||
34 | * @param int $currentVersion the version currently found in database |
||
35 | * @param int $targetVersion the target version to reach wich patches |
||
36 | * |
||
37 | * @return string the SQL |
||
38 | */ |
||
39 | function buildSQL($currentVersion, $targetVersion) |
||
40 | { |
||
41 | global $sqlPath; |
||
42 | |||
43 | if ($currentVersion > $targetVersion) { |
||
44 | throw new Exception('Cannot downgrade versions. Target version must be higher than current version'); |
||
45 | } |
||
46 | |||
47 | $sql = "START TRANSACTION;\n"; |
||
48 | |||
49 | $missingVersions = []; |
||
50 | for ($v = $currentVersion + 1; $v <= $targetVersion; ++$v) { |
||
51 | $file = $sqlPath . 'version.' . $v . '.sql'; |
||
52 | if (is_file($file)) { |
||
53 | $sql .= "\n-- -------- VERSION $v BEGINS ------------------------\n"; |
||
54 | $sql .= file_get_contents($file); |
||
55 | $sql .= "\n-- -------- VERSION $v ENDS --------------------------\n"; |
||
56 | } else { |
||
57 | $missingVersions[] = $v; |
||
58 | } |
||
59 | } |
||
60 | |||
61 | $sql .= "\nCOMMIT;\n"; |
||
62 | |||
63 | if (count($missingVersions)) { |
||
64 | throw new Exception('Missing SQL file for versions: ' . implode(',', $missingVersions)); |
||
65 | } |
||
66 | |||
67 | return $sql; |
||
68 | } |
||
69 | |||
70 | /** |
||
71 | * Executes a batch of SQL commands. |
||
72 | * (This is a workaround to Zend limitation to have only one command at once) |
||
73 | * |
||
74 | * @param string $sql to be executed |
||
75 | */ |
||
76 | function executeBatchSql($sql): void |
||
77 | { |
||
78 | $affectedRows = 0; |
||
79 | $queries = preg_split("/;+(?=([^'|^\\\']*['|\\\'][^'|^\\\']*['|\\\'])*[^'|^\\\']*[^'|^\\\']$)/", $sql); |
||
80 | foreach ($queries as $query) { |
||
81 | if (mb_strlen(trim($query)) > 0) { |
||
82 | try { |
||
83 | $result = Zend_Registry::get('db')->query($query); |
||
84 | } catch (\Exception $exception) { |
||
85 | echo 'FAILED QUERY: ' . $query . PHP_EOL; |
||
86 | |||
87 | throw $exception; |
||
88 | } |
||
89 | |||
90 | $affectedRows += $result->rowCount(); |
||
91 | } |
||
92 | } |
||
93 | |||
94 | echo "\n" . 'affected rows count: ' . $affectedRows . "\n"; |
||
95 | } |
||
96 | |||
97 | /** |
||
98 | * Do the actual update |
||
99 | */ |
||
100 | function doUpdate(): void |
||
101 | { |
||
102 | global $settingName; |
||
103 | |||
104 | try { |
||
105 | $currentVersion = (int) \mQueue\Model\Setting::get($settingName, 0)->value; |
||
106 | } catch (Exception $e) { |
||
107 | if (mb_strpos($e->getMessage(), 'SQLSTATE[42S02]') >= 0) { |
||
108 | $currentVersion = -1; |
||
109 | } else { |
||
110 | die('Caught exception: ' . $e->getMessage() . "\n"); |
||
0 ignored issues
–
show
|
|||
111 | } |
||
112 | } |
||
113 | |||
114 | $targetVersion = getPatchVersion(); |
||
115 | |||
116 | echo 'current version is: ' . $currentVersion . "\n"; |
||
117 | echo 'target version is : ' . $targetVersion . "\n"; |
||
118 | |||
119 | if ($currentVersion == $targetVersion) { |
||
120 | echo "already up-to-date\n"; |
||
121 | |||
122 | return; |
||
123 | } |
||
124 | |||
125 | $sql = buildSQL($currentVersion, $targetVersion); |
||
126 | echo $sql; |
||
127 | echo "\n_________________________________________________\n"; |
||
128 | echo "updating...\n"; |
||
129 | executeBatchSql($sql); |
||
130 | \mQueue\Model\Setting::set($settingName, $targetVersion); |
||
131 | |||
132 | echo "\nsuccessful update to version $targetVersion !\n"; |
||
133 | } |
||
134 | |||
135 | doUpdate(); |
||
136 |
In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.