Issues (98)

bin/update_database.php (1 issue)

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
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
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