1
|
|
|
<?php |
|
|
|
|
2
|
|
|
|
3
|
|
|
if (!defined('IN_UPDATE')) { |
4
|
|
|
die('Trying to call update helpers externally!'); |
5
|
|
|
} |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* @param string $query |
9
|
|
|
* @param bool $no_log |
10
|
|
|
* |
11
|
|
|
* @return bool|mysqli_result |
12
|
|
|
*/ |
13
|
|
|
function upd_do_query($query, $no_log = false) { |
14
|
|
|
global $update_tables; |
|
|
|
|
15
|
|
|
|
16
|
|
|
upd_add_more_time(); |
17
|
|
|
if (!$no_log) { |
18
|
|
|
upd_log_message("Performing query '{$query}'"); |
19
|
|
|
} |
20
|
|
|
|
21
|
|
|
if (strpos($query, '{{') !== false) { |
22
|
|
|
foreach ($update_tables as $tableName => $cork) { |
23
|
|
|
$query = str_replace("{{{$tableName}}}", classSupernova::$db->db_prefix . $tableName, $query); |
24
|
|
|
} |
25
|
|
|
} |
26
|
|
|
$result = classSupernova::$db->db_sql_query($query) or die('Query error for ' . $query . ': ' . db_error()); |
|
|
|
|
27
|
|
|
|
28
|
|
|
return $result; |
29
|
|
|
} |
30
|
|
|
|
31
|
|
|
function upd_check_key($key, $default_value, $condition = false) { |
32
|
|
|
global $config, $sys_log_disabled; |
|
|
|
|
33
|
|
|
|
34
|
|
|
$config->db_loadItem($key); |
35
|
|
|
if ($condition || !isset($config->$key)) { |
36
|
|
|
upd_add_more_time(); |
37
|
|
|
if (!$sys_log_disabled) { |
38
|
|
|
upd_log_message("Updating config key '{$key}' with value '{$default_value}'"); |
39
|
|
|
} |
40
|
|
|
$config->db_saveItem($key, $default_value); |
41
|
|
|
} else { |
42
|
|
|
$config->db_saveItem($key); |
43
|
|
|
} |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
function upd_log_version_update() { |
47
|
|
|
global $new_version; |
|
|
|
|
48
|
|
|
|
49
|
|
|
doquery('START TRANSACTION;'); |
50
|
|
|
upd_add_more_time(); |
51
|
|
|
upd_log_message("Detected outdated version {$new_version}. Upgrading..."); |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
function upd_add_more_time($time = 0) { |
55
|
|
|
global $config, $sys_log_disabled; |
|
|
|
|
56
|
|
|
|
57
|
|
|
$time = $time ? $time : ($config->upd_lock_time ? $config->upd_lock_time : 30); |
58
|
|
|
!$sys_log_disabled ? $config->db_saveItem('var_db_update_end', SN_TIME_NOW + $time) : false; |
59
|
|
|
set_time_limit($time); |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
function upd_log_message($message) { |
63
|
|
|
global $sys_log_disabled, $upd_log, $debug; |
|
|
|
|
64
|
|
|
|
65
|
|
|
if ($sys_log_disabled) { |
|
|
|
|
66
|
|
|
// print("{$message}<br />"); |
|
|
|
|
67
|
|
|
} else { |
68
|
|
|
$upd_log .= "{$message}\r\n"; |
69
|
|
|
$debug->warning($message, 'Database Update', 103); |
70
|
|
|
} |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
function upd_unset_table_info($table_name) { |
74
|
|
|
global $update_tables, $update_indexes, $update_foreigns; |
|
|
|
|
75
|
|
|
|
76
|
|
|
if (isset($update_tables[$table_name])) { |
77
|
|
|
unset($update_tables[$table_name]); |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
if (isset($update_indexes[$table_name])) { |
81
|
|
|
unset($update_indexes[$table_name]); |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
if (isset($update_foreigns[$table_name])) { |
85
|
|
|
unset($update_foreigns[$table_name]); |
86
|
|
|
} |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
function upd_load_table_info($prefix_table_name, $prefixed = true) { |
90
|
|
|
global $config, $update_tables, $update_indexes, $update_indexes_full, $update_foreigns; |
|
|
|
|
91
|
|
|
|
92
|
|
|
$tableName = $prefixed ? str_replace($config->db_prefix, '', $prefix_table_name) : $prefix_table_name; |
93
|
|
|
$prefix_table_name = $prefixed ? $prefix_table_name : $config->db_prefix . $prefix_table_name; |
94
|
|
|
|
95
|
|
|
upd_unset_table_info($tableName); |
96
|
|
|
|
97
|
|
|
$q1 = upd_do_query("SHOW FULL COLUMNS FROM {$prefix_table_name};", true); |
98
|
|
|
while ($r1 = db_fetch($q1)) { |
99
|
|
|
$update_tables[$tableName][$r1['Field']] = $r1; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
$q1 = upd_do_query("SHOW INDEX FROM {$prefix_table_name};", true); |
103
|
|
|
while ($r1 = db_fetch($q1)) { |
104
|
|
|
$update_indexes[$tableName][$r1['Key_name']] .= "{$r1['Column_name']},"; |
105
|
|
|
$update_indexes_full[$tableName][$r1['Key_name']][$r1['Column_name']] = $r1; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
$q1 = upd_do_query("SELECT * FROM `information_schema`.`KEY_COLUMN_USAGE` WHERE `TABLE_SCHEMA` = '" . db_escape(classSupernova::$db_name) . "' AND TABLE_NAME = '{$prefix_table_name}' AND REFERENCED_TABLE_NAME is not null;", true); |
109
|
|
|
while ($r1 = db_fetch($q1)) { |
110
|
|
|
$table_referenced = str_replace($config->db_prefix, '', $r1['REFERENCED_TABLE_NAME']); |
111
|
|
|
|
112
|
|
|
$update_foreigns[$tableName][$r1['CONSTRAINT_NAME']] .= "{$r1['COLUMN_NAME']},{$table_referenced},{$r1['REFERENCED_COLUMN_NAME']};"; |
113
|
|
|
} |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* @param string $table |
118
|
|
|
* @param string[] $alters |
119
|
|
|
* @param bool $condition |
120
|
|
|
* |
121
|
|
|
* @return bool|mysqli_result|void |
122
|
|
|
*/ |
123
|
|
|
function upd_alter_table($table, $alters, $condition = true) { |
124
|
|
|
global $config, $update_tables; |
|
|
|
|
125
|
|
|
|
126
|
|
|
if (!$condition) { |
127
|
|
|
return; |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
upd_add_more_time(); |
131
|
|
|
$alters_print = is_array($alters) ? dump($alters) : $alters; |
|
|
|
|
132
|
|
|
upd_log_message("Altering table '{$table}' with alterations {$alters_print}"); |
133
|
|
|
|
134
|
|
|
if (!is_array($alters)) { |
|
|
|
|
135
|
|
|
$alters = array($alters); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
$alters = implode(',', $alters); |
139
|
|
|
// foreach($alters as $table_name => ) |
|
|
|
|
140
|
|
|
$qry = "ALTER TABLE {$config->db_prefix}{$table} {$alters};"; |
141
|
|
|
|
142
|
|
|
$result = upd_do_query($qry); |
143
|
|
|
$error = db_error(); |
144
|
|
|
if ($error) { |
145
|
|
|
die("Altering error for table `{$table}`: {$error}<br />{$alters_print}"); |
|
|
|
|
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
upd_load_table_info($table, false); |
149
|
|
|
|
150
|
|
|
return $result; |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
function upd_drop_table($table_name) { |
154
|
|
|
global $config; |
|
|
|
|
155
|
|
|
|
156
|
|
|
classSupernova::$db->db_sql_query("DROP TABLE IF EXISTS {$config->db_prefix}{$table_name};"); |
157
|
|
|
|
158
|
|
|
upd_unset_table_info($table_name); |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* @param string $table_name |
163
|
|
|
* @param string|array $declaration |
164
|
|
|
* @param string $tableOptions |
165
|
|
|
* |
166
|
|
|
* @return bool|mysqli_result |
167
|
|
|
*/ |
168
|
|
|
function upd_create_table($table_name, $declaration, $tableOptions = '') { |
169
|
|
|
global $config, $update_tables; |
|
|
|
|
170
|
|
|
|
171
|
|
|
if (!$update_tables[$table_name]) { |
172
|
|
|
upd_do_query('set foreign_key_checks = 0;', true); |
173
|
|
|
if (is_array($declaration)) { |
174
|
|
|
$declaration = implode(',', $declaration); |
175
|
|
|
} |
176
|
|
|
$declaration = trim($declaration); |
177
|
|
|
if (substr($declaration, 0, 1) != '(') { |
178
|
|
|
$declaration = "($declaration)"; |
179
|
|
|
} |
180
|
|
|
$tableOptions = trim($tableOptions); |
181
|
|
|
if (!empty($tableOptions)) { |
182
|
|
|
$declaration .= $tableOptions; |
183
|
|
|
} |
184
|
|
|
$result = upd_do_query("CREATE TABLE IF NOT EXISTS `{$config->db_prefix}{$table_name}` {$declaration}"); |
185
|
|
|
$error = db_error(); |
186
|
|
|
if ($error) { |
187
|
|
|
die("Creating error for table `{$table_name}`: {$error}<br />" . dump($declaration)); |
|
|
|
|
188
|
|
|
} |
189
|
|
|
upd_do_query('set foreign_key_checks = 1;', true); |
190
|
|
|
upd_load_table_info($table_name, false); |
191
|
|
|
classSupernova::$db->schema()->clear(); |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
return $result; |
|
|
|
|
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
function upd_db_unit_by_location($user_id = 0, $location_type, $location_id, $unit_snid = 0, $for_update = false, $fields = '*') { |
198
|
|
|
return db_fetch(upd_do_query( |
|
|
|
|
199
|
|
|
"SELECT {$fields} |
200
|
|
|
FROM {{unit}} |
201
|
|
|
WHERE |
202
|
|
|
`unit_location_type` = {$location_type} AND `unit_location_id` = {$location_id} AND " . DBStaticUnit::db_unit_time_restrictions() . |
203
|
|
|
($user_id = intval($user_id) ? " AND `unit_player_id` = {$user_id}" : '') . |
|
|
|
|
204
|
|
|
($unit_snid = intval($unit_snid) ? " AND `unit_snid` = {$unit_snid}" : '') . |
|
|
|
|
205
|
|
|
" LIMIT 1" . |
206
|
|
|
($for_update ? ' FOR UPDATE' : '') |
207
|
|
|
)); |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
|
211
|
|
|
function upd_db_unit_changeset_prepare($unit_id, $unit_value, $user, $planet_id = null) { |
212
|
|
|
if (!is_array($user)) { |
213
|
|
|
// TODO - remove later |
214
|
|
|
print('<h1>СООБЩИТЕ ЭТО АДМИНУ: upd_db_unit_changeset_prepare() - USER is not ARRAY</h1>'); |
215
|
|
|
pdump(debug_backtrace()); |
216
|
|
|
die('USER is not ARRAY'); |
|
|
|
|
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
if (!isset($user['id']) || !$user['id']) { |
220
|
|
|
// TODO - remove later |
221
|
|
|
print('<h1>СООБЩИТЕ ЭТО АДМИНУ: upd_db_unit_changeset_prepare() - USER[id] пустой</h1>'); |
222
|
|
|
pdump($user); |
223
|
|
|
pdump(debug_backtrace()); |
224
|
|
|
die('USER[id] пустой'); |
|
|
|
|
225
|
|
|
} |
226
|
|
|
$planet_id = is_array($planet_id) && isset($planet_id['id']) ? $planet_id['id'] : $planet_id; |
227
|
|
|
|
228
|
|
|
$unit_location = get_unit_param($unit_id, 'location'); // sys_get_unit_location($user, array(), $unit_id); |
|
|
|
|
229
|
|
|
$location_id = $unit_location == LOC_USER ? $user['id'] : $planet_id; |
230
|
|
|
$location_id = $location_id ? $location_id : 'NULL'; |
231
|
|
|
|
232
|
|
|
$db_changeset = array(); |
233
|
|
|
$temp = upd_db_unit_by_location($user['id'], $unit_location, $location_id, $unit_id, true, 'unit_id'); |
234
|
|
|
if ($temp['unit_id']) { |
235
|
|
|
// update |
236
|
|
|
$db_changeset = array( |
237
|
|
|
'action' => SQL_OP_UPDATE, |
238
|
|
|
'where' => array( |
239
|
|
|
"`unit_id` = {$temp['unit_id']}", |
240
|
|
|
), |
241
|
|
|
'fields' => array( |
242
|
|
|
'unit_level' => array( |
243
|
|
|
'delta' => $unit_value |
244
|
|
|
), |
245
|
|
|
), |
246
|
|
|
); |
247
|
|
|
} else { |
248
|
|
|
// insert |
249
|
|
|
$db_changeset = array( |
250
|
|
|
'action' => SQL_OP_INSERT, |
251
|
|
|
'fields' => array( |
252
|
|
|
'unit_player_id' => array( |
253
|
|
|
'set' => $user['id'], |
254
|
|
|
), |
255
|
|
|
'unit_location_type' => array( |
256
|
|
|
'set' => $unit_location, |
257
|
|
|
), |
258
|
|
|
'unit_location_id' => array( |
259
|
|
|
'set' => $unit_location == LOC_USER ? $user['id'] : $planet_id, |
260
|
|
|
), |
261
|
|
|
'unit_type' => array( |
262
|
|
|
'set' => get_unit_param($unit_id, P_UNIT_TYPE), |
263
|
|
|
), |
264
|
|
|
'unit_snid' => array( |
265
|
|
|
'set' => $unit_id, |
266
|
|
|
), |
267
|
|
|
'unit_level' => array( |
268
|
|
|
'set' => $unit_value, |
269
|
|
|
), |
270
|
|
|
), |
271
|
|
|
); |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
return $db_changeset; |
275
|
|
|
} |
276
|
|
|
|
277
|
|
|
|
278
|
|
|
function upd_db_changeset_apply($db_changeset) { |
279
|
|
|
if (!is_array($db_changeset) || empty($db_changeset)) { |
280
|
|
|
return; |
281
|
|
|
} |
282
|
|
|
|
283
|
|
|
foreach ($db_changeset as $table_name => $table_data) { |
284
|
|
|
foreach ($table_data as $record_id => $conditions) { |
285
|
|
|
$where = ''; |
286
|
|
|
if (!empty($conditions['where'])) { |
287
|
|
|
$where = 'WHERE ' . implode(' AND ', $conditions['where']); |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
$fields = array(); |
291
|
|
|
if ($conditions['fields']) { |
292
|
|
|
foreach ($conditions['fields'] as $field_name => $field_data) { |
293
|
|
|
$condition = "`{$field_name}` = "; |
294
|
|
|
$value = ''; |
295
|
|
|
if ($field_data['delta']) { |
296
|
|
|
$value = "`{$field_name}`" . ($field_data['delta'] >= 0 ? '+' : '') . $field_data['delta']; |
297
|
|
|
} elseif ($field_data['set']) { |
298
|
|
|
$value = (is_string($field_data['set']) ? "'{$field_data['set']}'" : $field_data['set']); |
299
|
|
|
} |
300
|
|
|
if ($value) { |
301
|
|
|
$fields[] = $condition . $value; |
302
|
|
|
} |
303
|
|
|
} |
304
|
|
|
} |
305
|
|
|
$fields = implode(',', $fields); |
306
|
|
|
|
307
|
|
|
switch ($conditions['action']) { |
308
|
|
|
case SQL_OP_DELETE: |
309
|
|
|
upd_do_query("DELETE FROM {{{$table_name}}} {$where}"); |
310
|
|
|
break; |
311
|
|
|
|
312
|
|
|
case SQL_OP_UPDATE: |
313
|
|
|
if ($fields) { |
314
|
|
|
upd_do_query("UPDATE {{{$table_name}}} SET {$fields} {$where}"); |
315
|
|
|
} |
316
|
|
|
break; |
317
|
|
|
|
318
|
|
|
case SQL_OP_INSERT: |
319
|
|
|
if ($fields) { |
320
|
|
|
upd_do_query("INSERT INTO {{{$table_name}}} SET {$fields}"); |
321
|
|
|
} |
322
|
|
|
break; |
323
|
|
|
|
324
|
|
|
case SQL_OP_REPLACE: |
325
|
|
|
if ($fields) { |
326
|
|
|
upd_do_query("REPLACE INTO {{{$table_name}}} SET {$fields}"); |
327
|
|
|
} |
328
|
|
|
break; |
329
|
|
|
|
330
|
|
|
} |
331
|
|
|
} |
332
|
|
|
} |
333
|
|
|
} |
334
|
|
|
|
335
|
|
|
/** |
336
|
|
|
* @param int $id |
337
|
|
|
*/ |
338
|
|
|
function updPatchExists($id) { |
339
|
|
|
$q = upd_do_query("SELECT 1 FROM {{server_patches}} WHERE `id` = " . intval($id), true); |
340
|
|
|
|
341
|
|
|
return !empty(db_fetch($q)); |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
/** |
345
|
|
|
* @param int $id |
346
|
|
|
*/ |
347
|
|
|
function updPatchRegister($id) { |
348
|
|
|
upd_do_query("INSERT INTO {{server_patches}} SET `id` = " . intval($id)); |
349
|
|
|
} |
350
|
|
|
|
351
|
|
|
/** |
352
|
|
|
* @param int $patchId |
353
|
|
|
* @param callable $callable |
354
|
|
|
* @param bool $preCheck - [PATCH_REGISTER|PATCH_PRE_CHECK] |
355
|
|
|
*/ |
356
|
|
|
function updPatchApply($patchId, $callable, $preCheck = PATCH_REGISTER) { |
357
|
|
|
if (!updPatchExists($patchId)) { |
358
|
|
|
$callable(); |
359
|
|
|
|
360
|
|
|
if (!$preCheck) { |
361
|
|
|
updPatchRegister($patchId); |
362
|
|
|
} |
363
|
|
|
} |
364
|
|
|
} |
365
|
|
|
|
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.