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
|
|
|
* @return int last version of patches |
11
|
|
|
*/ |
12
|
|
|
function getPatchVersion() |
13
|
|
|
{ |
14
|
|
|
global $sqlPath; |
|
|
|
|
15
|
|
|
$lastVersion = 0; |
16
|
|
|
$d = dir($sqlPath); |
|
|
|
|
17
|
|
|
while (false !== ($entry = $d->read())) { |
18
|
|
|
if (preg_match('/^version\.(\d+)\.sql$/i', $entry, $a)) { |
|
|
|
|
19
|
|
|
if ((int) $a[1] > $lastVersion) { |
20
|
|
|
$lastVersion = (int) $a[1]; |
21
|
|
|
} |
22
|
|
|
} |
23
|
|
|
} |
24
|
|
|
$d->close(); |
25
|
|
|
|
26
|
|
|
return $lastVersion; |
27
|
|
|
} |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* Returns the whole SQL (enclosed in transaction) needed to update from |
31
|
|
|
* specified version to specified target version. |
32
|
|
|
* @param int $currentVersion the version currently found in database |
33
|
|
|
* @param int $targetVersion the target version to reach wich patches |
34
|
|
|
* @return string the SQL |
35
|
|
|
*/ |
36
|
|
|
function buildSQL($currentVersion, $targetVersion) |
37
|
|
|
{ |
38
|
|
|
global $sqlPath; |
|
|
|
|
39
|
|
|
|
40
|
|
|
if ($currentVersion > $targetVersion) { |
41
|
|
|
throw new Exception('Cannot downgrade versions. Target version must be higher than current version'); |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
$sql = "START TRANSACTION;\n"; |
45
|
|
|
|
46
|
|
|
$missingVersions = []; |
47
|
|
|
for ($v = $currentVersion + 1; $v <= $targetVersion; ++$v) { |
48
|
|
|
$file = $sqlPath . 'version.' . $v . '.sql'; |
49
|
|
|
if (is_file($file)) { |
50
|
|
|
$sql .= "\n-- -------- VERSION $v BEGINS ------------------------\n"; |
|
|
|
|
51
|
|
|
$sql .= file_get_contents($file); |
52
|
|
|
$sql .= "\n-- -------- VERSION $v ENDS --------------------------\n"; |
|
|
|
|
53
|
|
|
} else { |
54
|
|
|
$missingVersions[] = $v; |
55
|
|
|
} |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
$sql .= "\nCOMMIT;\n"; |
59
|
|
|
|
60
|
|
|
if (count($missingVersions)) { |
61
|
|
|
throw new Exception('Missing SQL file for versions: ' . implode(',', $missingVersions)); |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
return $sql; |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* Executes a batch of SQL commands. |
69
|
|
|
* (This is a workaround to Zend limitation to have only one command at once) |
70
|
|
|
* @param string $sql to be executed |
71
|
|
|
*/ |
72
|
|
|
function executeBatchSql($sql) |
73
|
|
|
{ |
74
|
|
|
$affectedRows = 0; |
75
|
|
|
$queries = preg_split("/;+(?=([^'|^\\\']*['|\\\'][^'|^\\\']*['|\\\'])*[^'|^\\\']*[^'|^\\\']$)/", $sql); |
76
|
|
|
foreach ($queries as $query) { |
77
|
|
|
if (strlen(trim($query)) > 0) { |
78
|
|
|
try { |
79
|
|
|
$result = Zend_Registry::get('db')->query($query); |
80
|
|
|
} catch (\Exception $exception) { |
81
|
|
|
echo 'FAILED QUERY: ' . $query . PHP_EOL; |
82
|
|
|
throw $exception; |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
$affectedRows += $result->rowCount(); |
86
|
|
|
} |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
echo "\n" . 'affected rows count: ' . $affectedRows . "\n"; |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* Do the actual update |
94
|
|
|
*/ |
95
|
|
|
function doUpdate() |
96
|
|
|
{ |
97
|
|
|
global $settingName; |
|
|
|
|
98
|
|
|
|
99
|
|
|
try { |
100
|
|
|
$currentVersion = (integer) \mQueue\Model\Setting::get($settingName, 0)->value; |
|
|
|
|
101
|
|
|
} catch (Exception $e) { |
102
|
|
|
if (strpos($e->getMessage(), 'SQLSTATE[42S02]') >= 0) { |
103
|
|
|
$currentVersion = -1; |
104
|
|
|
} else { |
105
|
|
|
die('Caught exception: ' . $e->getMessage() . "\n"); |
|
|
|
|
106
|
|
|
} |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
$targetVersion = getPatchVersion(); |
110
|
|
|
|
111
|
|
|
echo 'current version is: ' . $currentVersion . "\n"; |
112
|
|
|
echo 'target version is : ' . $targetVersion . "\n"; |
113
|
|
|
|
114
|
|
|
if ($currentVersion == $targetVersion) { |
115
|
|
|
echo "already up-to-date\n"; |
116
|
|
|
|
117
|
|
|
return; |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
$sql = buildSQL($currentVersion, $targetVersion); |
121
|
|
|
echo $sql; |
122
|
|
|
echo "\n_________________________________________________\n"; |
123
|
|
|
echo "updating...\n"; |
124
|
|
|
executeBatchSql($sql); |
125
|
|
|
\mQueue\Model\Setting::set($settingName, $targetVersion); |
126
|
|
|
|
127
|
|
|
echo "\nsuccessful update to version $targetVersion !\n"; |
|
|
|
|
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
doUpdate(); |
131
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.