Completed
Push — trunk ( e6cc80...a060bf )
by SuperNova.WS
05:00
created

updPatchApply()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
c 0
b 0
f 0
nc 3
nop 3
dl 0
loc 6
rs 9.4285
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 13 and the first side effect is on line 4.

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.

Loading history...
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;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
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());
0 ignored issues
show
Best Practice introduced by
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...
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
27
28
  return $result;
29
}
30
31
function upd_check_key($key, $default_value, $condition = false) {
32
  global $config, $sys_log_disabled;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
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;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
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;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
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;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
64
65
  if ($sys_log_disabled) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
66
//    print("{$message}<br />");
0 ignored issues
show
Unused Code Comprehensibility introduced by
84% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
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;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
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;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
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;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
125
126
  if (!$condition) {
127
    return;
128
  }
129
130
  upd_add_more_time();
131
  $alters_print = is_array($alters) ? dump($alters) : $alters;
0 ignored issues
show
introduced by
The condition is_array($alters) can never be false.
Loading history...
132
  upd_log_message("Altering table '{$table}' with alterations {$alters_print}");
133
134
  if (!is_array($alters)) {
0 ignored issues
show
introduced by
The condition ! is_array($alters) can never be true.
Loading history...
135
    $alters = array($alters);
136
  }
137
138
  $alters = implode(',', $alters);
139
  // foreach($alters as $table_name => )
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
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}");
0 ignored issues
show
Best Practice introduced by
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...
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;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
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;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
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));
0 ignored issues
show
Best Practice introduced by
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...
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;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.
Loading history...
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(
0 ignored issues
show
Bug introduced by
upd_do_query(EncapsedNod...e ? ' FOR UPDATE' : '') cannot be passed to db_fetch() as the parameter $query expects a reference. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

198
  return db_fetch(/** @scrutinizer ignore-type */ upd_do_query(
Loading history...
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}" : '') .
0 ignored issues
show
Unused Code introduced by
The assignment to $user_id is dead and can be removed.
Loading history...
204
    ($unit_snid = intval($unit_snid) ? " AND `unit_snid` = {$unit_snid}" : '') .
0 ignored issues
show
Unused Code introduced by
The assignment to $unit_snid is dead and can be removed.
Loading history...
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');
0 ignored issues
show
Best Practice introduced by
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...
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] пустой');
0 ignored issues
show
Best Practice introduced by
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...
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);
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

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