Passed
Push — trunk ( 6aa0cb...9bfd5f )
by SuperNova.WS
04:09
created

classSupernova::db_get_user_by_email()   C

Complexity

Conditions 11
Paths 11

Size

Total Lines 28
Code Lines 15

Duplication

Lines 10
Ratio 35.71 %

Code Coverage

Tests 0
CRAP Score 132

Importance

Changes 0
Metric Value
cc 11
eloc 15
nc 11
nop 4
dl 10
loc 28
ccs 0
cts 20
cp 0
crap 132
rs 5.2653
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
use Vector\Vector;
4
use Common\GlobalContainer;
5
6
/**
7
 * Class classSupernova
8
 *
9
 * Singleton
10
 */
11
class classSupernova {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
12
  /**
13
   * @var classSupernova $_sn
14
   */
15
  protected static $_sn;
16
17
  /**
18
   * @var GlobalContainer $gc
19
   */
20
  public static $gc;
21
22
  /**
23
   * Основная БД для доступа к данным
24
   *
25
   * @var db_mysql $db
26
   */
27
  public static $db;
28
  public static $db_name = '';
29
30
  /**
31
   * Настройки из файла конфигурации
32
   *
33
   * @var string
34
   */
35
  public static $cache_prefix = 'sn_';
36
  public static $sn_secret_word = '';
37
38
  /**
39
   * Конфигурация игры
40
   *
41
   * @var classConfig $config
42
   */
43
  public static $config;
44
45
46
  /**
47
   * Кэш игры
48
   *
49
   * @var classCache $cache
50
   */
51
  public static $cache;
52
53
  /**
54
   * @var classLocale $lang
55
   */
56
  public static $lang;
57
58
59
  /**
60
   * @var core_auth $auth
61
   */
62
  public static $auth = null;
63
64
65
  public static $db_in_transaction = false;
66
  public static $transaction_id = 0;
67
  public static $user = array();
68
  /**
69
   * @var userOptions
70
   */
71
  public static $user_options;
72
73
  /**
74
   * @var debug $debug
75
   */
76
  public static $debug = null;
77
78
79
  public static $options = array();
80
81
  /**
82
   * Is header already rendered?
83
   *
84
   * @var bool $headerRendered
85
   */
86
  public static $headerRendered = false;
87
88
  /*
89
  TODO Кэш:
90
  1. Всегда дешевле использовать процессор, чем локальную память
91
  2. Всегда дешевле использовать локальную память, чем общую память всех процессов
92
  3. Всегда дешевле использовать общую память всех процессов, чем обращаться к БД
93
94
  Кэш - многоуровневый: локальная память-общая память-БД
95
  БД может быть сверхкэширующей - см. HyperNova. Это реализуется на уровне СН-драйвера БД
96
  Предусмотреть вариант, когда уровни кэширования совпадают, например когда нет xcache и используется общая память
97
  */
98
  //public static $cache; // Объект-кэшер - либо встроенная память, либо мемкэш с блокировками - находится внутри $db!!!!
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% 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...
99
  //public static $db; // Объект-БД - либок кэшер с блокировками, либо БД
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% 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...
100
101
  // protected static $info = array(); // Кэш информации - инфо о юнитах, инфо о группах итд
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
102
103
  // TODO Автоматически заполнять эту таблицу. В случае кэша в памяти - делать show table при обращении к таблице
104
  public static $location_info = array(
105
    LOC_USER => array(
106
      P_TABLE_NAME => 'users',
107
      P_ID         => 'id',
108
      P_OWNER_INFO => array(),
109
    ),
110
111
    LOC_PLANET => array(
112
      P_TABLE_NAME => 'planets',
113
      P_ID         => 'id',
114
      P_OWNER_INFO => array(
115
        LOC_USER => array(
116
          P_LOCATION    => LOC_USER,
117
          P_OWNER_FIELD => 'id_owner',
118
        ),
119
      ),
120
    ),
121
122
    LOC_UNIT => array(
123
      P_TABLE_NAME => 'unit',
124
      P_ID         => 'unit_id',
125
      P_OWNER_INFO => array(
126
        LOC_USER => array(
127
          P_LOCATION    => LOC_USER,
128
          P_OWNER_FIELD => 'unit_player_id',
129
        ),
130
      ),
131
    ),
132
133
    LOC_QUE => array(
134
      P_TABLE_NAME => 'que',
135
      P_ID         => 'que_id',
136
      P_OWNER_INFO => array(
137
        array(
138
          P_LOCATION    => LOC_USER,
139
          P_OWNER_FIELD => 'que_player_id',
140
        ),
141
142
        array(
143
          P_LOCATION    => LOC_PLANET,
144
          P_OWNER_FIELD => 'que_planet_id_origin',
145
        ),
146
147
        array(
148
          P_LOCATION    => LOC_PLANET,
149
          P_OWNER_FIELD => 'que_planet_id',
150
        ),
151
      ),
152
    ),
153
154
    LOC_FLEET => array(
155
      P_TABLE_NAME => 'fleets',
156
      P_ID         => 'fleet_id',
157
      P_OWNER_INFO => array(
158
        array(
159
          P_LOCATION    => LOC_USER,
160
          P_OWNER_FIELD => 'fleet_owner',
161
        ),
162
163
        array(
164
          P_LOCATION    => LOC_USER,
165
          P_OWNER_FIELD => 'fleet_target_owner',
166
        ),
167
168
        array(
169
          P_LOCATION    => LOC_PLANET,
170
          P_OWNER_FIELD => 'fleet_start_planet_id',
171
        ),
172
173
        array(
174
          P_LOCATION    => LOC_PLANET,
175
          P_OWNER_FIELD => 'fleet_end_planet_id',
176
        ),
177
      ),
178
    ),
179
  );
180
181
  /**
182
   * @return classSupernova
183
   */
184
  public static function sn() {
185
    if (!isset(self::$_sn)) {
186
      self::$_sn = new self();
187
    }
188
189
    return self::$_sn;
190
  }
191
192
  public function __construct() {
193
194
  }
195
196
197
  public static function log_file($message, $spaces = 0) {
198
    if (self::$debug) {
199
      self::$debug->log_file($message, $spaces);
200
    }
201
  }
202
203
204
205
206
207
  // TODO Вынести в отдельный объект
208
209
  /**
210
   * Эта функция проверяет статус транзакции
211
   *
212
   * Это - низкоуровневая функция. В нормальном состоянии движка её сообщения никогда не будут видны
213
   *
214
   * @param null|true|false $status Должна ли быть запущена транзакция в момент проверки
215
   *   <p>null - транзакция НЕ должна быть запущена</p>
216
   *   <p>true - транзакция должна быть запущена - для совместимости с $for_update</p>
217
   *   <p>false - всё равно - для совместимости с $for_update</p>
218
   *
219
   * @return bool Текущий статус транзакции
220
   */
221
  public static function db_transaction_check($status = null) {
222
    $error_msg = false;
223
    if ($status && !static::$db_in_transaction) {
224
      $error_msg = 'No transaction started for current operation';
225
    } elseif ($status === null && static::$db_in_transaction) {
226
      $error_msg = 'Transaction is already started';
227
    }
228
229
    if ($error_msg) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $error_msg of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
230
      // TODO - Убрать позже
231
      print('<h1>СООБЩИТЕ ЭТО АДМИНУ: sn_db_transaction_check() - ' . $error_msg . '</h1>');
232
      $backtrace = debug_backtrace();
233
      array_shift($backtrace);
234
      pdump($backtrace);
235
      die($error_msg);
236
    }
237
238
    return static::$db_in_transaction;
239
  }
240
241
  public static function db_transaction_start($level = '') {
242
    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...
243
244
    static::db_transaction_check(null);
245
246
    $level ? doquery('SET TRANSACTION ISOLATION LEVEL ' . $level) : false;
247
248
    static::$transaction_id++;
249
    doquery('START TRANSACTION');
250
251
    if ($config->db_manual_lock_enabled) {
252
      $config->db_loadItem('var_db_manually_locked');
253
      $config->db_saveItem('var_db_manually_locked', SN_TIME_SQL);
254
    }
255
256
    static::$db_in_transaction = true;
257
    _SnCacheInternal::cache_locator_unset_all();
258
    _SnCacheInternal::cache_queries_unset_all();
259
260
    //print('<hr/>TRANSACTION START id' . static::$transaction_id . '<br />');
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% 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...
261
262
    return static::$transaction_id;
263
  }
264
265 View Code Duplication
  public static function db_transaction_commit() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
266
    static::db_transaction_check(true);
267
268
    _SnCacheInternal::cache_lock_unset_all();
269
    doquery('COMMIT');
270
271
    //print('<br/>TRANSACTION COMMIT id' . static::$transaction_id . '<hr />');
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% 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...
272
    static::$db_in_transaction = false;
273
274
    return static::$transaction_id++;
275
  }
276
277 View Code Duplication
  public static function db_transaction_rollback() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
278
    // static::db_transaction_check(true); // TODO - вообще-то тут тоже надо проверять есть ли транзакция
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% 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...
279
    _SnCacheInternal::cache_lock_unset_all();
280
    doquery('ROLLBACK');
281
282
    //print('<br/>TRANSACTION ROLLBACK id' . static::$transaction_id . '<hr />');
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% 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...
283
    static::$db_in_transaction = false;
284
    static::$transaction_id++;
285
286
    return static::$transaction_id;
287
  }
288
289
  /**
290
   * Блокирует указанные таблицу/список таблиц
291
   *
292
   * @param string|array $tables Таблица/список таблиц для блокировки. Названия таблиц - без префиксов
293
   * <p>string - название таблицы для блокировки</p>
294
   * <p>array - массив, где ключ - имя таблицы, а значение - условия блокировки элементов</p>
295
   */
296
  public static function db_lock_tables($tables) {
297
    $tables = is_array($tables) ? $tables : array($tables => '');
298
    foreach ($tables as $table_name => $condition) {
299
      self::$db->doquery("SELECT 1 FROM {{{$table_name}}}" . ($condition ? ' WHERE ' . $condition : ''));
300
    }
301
  }
302
303
  public static function db_query_select($query, $fetch = false, $skip_lock = false) {
304
    $select = strpos(strtoupper($query), 'SELECT') !== false;
305
306
    $query .= $select && $fetch ? ' LIMIT 1' : '';
307
    $query .= $select && !$skip_lock && static::db_transaction_check(false) ? ' FOR UPDATE' : '';
308
309
    $result = self::$db->doquery($query, $fetch);
310
311
    return $result;
312
  }
313
314
  public static function db_query_update($query) {
315
    return self::$db->doquery($query, false);
316
  }
317
318
  public static function db_query_delete($query) {
319
    return self::$db->doquery($query, false);
320
  }
321
322
  public static function db_query_insert($query) {
323
    return self::$db->doquery($query, false);
324
  }
325
326
  /**
327
   * Возвращает информацию о записи по её ID
328
   *
329
   * @param int       $location_type
330
   * @param int|array $record_id_unsafe
331
   *    <p>int - ID записи</p>
332
   *    <p>array - запись пользователя с установленным полем P_ID</p>
333
   * @param bool      $for_update @deprecated
334
   * @param string    $fields @deprecated список полей или '*'/'' для всех полей
335
   * @param bool      $skip_lock Указывает на то, что не нужно блокировать запись //TODO и не нужно сохранять в кэше
336
   *
337
   * @return array|false
338
   *    <p>false - Нет записи с указанным ID</p>
339
   *    <p>array - запись</p>
340
   */
341
  public static function db_get_record_by_id($location_type, $record_id_unsafe, $for_update = false, $fields = '*', $skip_lock = false) {
0 ignored issues
show
Unused Code introduced by
The parameter $for_update is not used and could be removed. ( Ignorable by Annotation )

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

341
  public static function db_get_record_by_id($location_type, $record_id_unsafe, /** @scrutinizer ignore-unused */ $for_update = false, $fields = '*', $skip_lock = false) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $fields is not used and could be removed. ( Ignorable by Annotation )

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

341
  public static function db_get_record_by_id($location_type, $record_id_unsafe, $for_update = false, /** @scrutinizer ignore-unused */ $fields = '*', $skip_lock = false) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $skip_lock is not used and could be removed. ( Ignorable by Annotation )

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

341
  public static function db_get_record_by_id($location_type, $record_id_unsafe, $for_update = false, $fields = '*', /** @scrutinizer ignore-unused */ $skip_lock = false) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
342
    $id_field = static::$location_info[$location_type][P_ID];
343
    $record_id_safe = idval(is_array($record_id_unsafe) && isset($record_id_unsafe[$id_field]) ? $record_id_unsafe[$id_field] : $record_id_unsafe);
344
345
    return static::db_get_record_list($location_type, "`{$id_field}` = {$record_id_safe}", true, false);
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::db_get_re...apsedNode, true, false) returns the type boolean which is incompatible with the documented return type false|array.
Loading history...
346
  }
347
348
  public static function db_get_record_list($location_type, $filter = '', $fetch = false, $no_return = false) {
349
    $query_cache = &_SnCacheInternal::$queries[$location_type][$filter];
350
351
    if (!isset($query_cache) || $query_cache === null) {
352
      $location_info = &static::$location_info[$location_type];
353
      $id_field = $location_info[P_ID];
354
      $query_cache = array();
355
356
      if (static::db_transaction_check(false)) {
357
        // Проходим по всем родителям данной записи
358
        foreach ($location_info[P_OWNER_INFO] as $owner_data) {
359
          $owner_location_type = $owner_data[P_LOCATION];
360
          $parent_id_list = array();
361
          // Выбираем родителей данного типа и соответствующие ИД текущего типа
362
          $query = static::db_query_select(
363
            "SELECT
364
              distinct({{{$location_info[P_TABLE_NAME]}}}.{$owner_data[P_OWNER_FIELD]}) AS parent_id
365
            FROM {{{$location_info[P_TABLE_NAME]}}}" .
366
            ($filter ? ' WHERE ' . $filter : '') .
367
            ($fetch ? ' LIMIT 1' : ''),
368
            false,
369
            true
370
          );
371
372
          while ($row = db_fetch($query)) {
373
            // Исключаем из списка родительских ИД уже заблокированные записи
374
            if (!_SnCacheInternal::cache_lock_get($owner_location_type, $row['parent_id'])) {
375
              $parent_id_list[$row['parent_id']] = $row['parent_id'];
376
            }
377
          }
378
379
          // Если все-таки какие-то записи еще не заблокированы - вынимаем текущие версии из базы
380
          if ($indexes_str = implode(',', $parent_id_list)) {
381
            $parent_id_field = static::$location_info[$owner_location_type][P_ID];
382
            static::db_get_record_list($owner_location_type,
383
              $parent_id_field . (count($parent_id_list) > 1 ? " IN ({$indexes_str})" : " = {$indexes_str}"), $fetch, true);
384
          }
385
        }
386
      }
387
388
      $query = static::db_query_select(
389
        "SELECT * FROM {{{$location_info[P_TABLE_NAME]}}}" . (($filter = trim($filter)) ? " WHERE {$filter}" : '')
390
      );
391
      while ($row = db_fetch($query)) {
392
        _SnCacheInternal::cache_set($location_type, $row[$id_field], $row);
393
        $query_cache[$row[$id_field]] = &_SnCacheInternal::$data[$location_type][$row[$id_field]];
394
      }
395
    }
396
397
    if ($no_return) {
398
      return true;
399
    } else {
400
      $result = false;
401
      if (is_array($query_cache)) {
402
        foreach ($query_cache as $key => $value) {
403
          $result[$key] = $value;
404
          if ($fetch) {
405
            break;
406
          }
407
        }
408
      }
409
410
      return $fetch ? (is_array($result) ? reset($result) : false) : $result;
411
    }
412
  }
413
414
  public static function db_upd_record_by_id($location_type, $record_id, $set) {
415
    if (!($record_id = idval($record_id)) || !($set = trim($set))) {
416
      return false;
417
    }
418
419
    $location_info = &static::$location_info[$location_type];
420
    $id_field = $location_info[P_ID];
421
    $table_name = $location_info[P_TABLE_NAME];
422
    if ($result = static::db_query_update("UPDATE {{{$table_name}}} SET {$set} WHERE `{$id_field}` = {$record_id}")) // TODO Как-то вернуть может быть LIMIT 1 ?
423
    {
424 View Code Duplication
      if (static::$db->db_affected_rows()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
425
        // Обновляем данные только если ряд был затронут
426
        // TODO - переделать под работу со структурированными $set
427
428
        // Тут именно так, а не cache_unset - что бы в кэшах автоматически обновилась запись. Будет нужно на будущее
429
        _SnCacheInternal::$data[$location_type][$record_id] = null;
430
        // Вытаскиваем обновленную запись
431
        static::db_get_record_by_id($location_type, $record_id);
0 ignored issues
show
Bug introduced by
It seems like $record_id can also be of type double; however, parameter $record_id_unsafe of classSupernova::db_get_record_by_id() does only seem to accept integer|array, maybe add an additional type check? ( Ignorable by Annotation )

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

431
        static::db_get_record_by_id($location_type, /** @scrutinizer ignore-type */ $record_id);
Loading history...
Deprecated Code introduced by
The function classSupernova::db_get_record_by_id() has been deprecated. ( Ignorable by Annotation )

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

431
        /** @scrutinizer ignore-deprecated */ static::db_get_record_by_id($location_type, $record_id);
Loading history...
432
        _SnCacheInternal::cache_clear($location_type, false); // Мягкий сброс - только $queries
433
      }
434
    }
435
436
    return $result;
437
  }
438
439
  public static function db_upd_record_list($location_type, $condition, $set) {
440
    if (!($set = trim($set))) {
441
      return false;
442
    }
443
444
    $condition = trim($condition);
445
    $table_name = static::$location_info[$location_type][P_TABLE_NAME];
446
447
    if ($result = static::db_query_update("UPDATE {{{$table_name}}} SET " . $set . ($condition ? ' WHERE ' . $condition : ''))) {
448
449
      if (static::$db->db_affected_rows()) { // Обновляем данные только если ряд был затронут
450
        // Поскольку нам неизвестно, что и как обновилось - сбрасываем кэш этого типа полностью
451
        // TODO - когда будет структурированный $condition и $set - перепаковывать данные
452
        _SnCacheInternal::cache_clear($location_type, true);
453
      }
454
    }
455
456
    return $result;
457
  }
458
459
  public static function db_ins_record($location_type, $set) {
460
    $set = trim($set);
461
    $table_name = static::$location_info[$location_type][P_TABLE_NAME];
462
    if ($result = static::db_query_insert("INSERT INTO `{{{$table_name}}}` SET {$set}")) {
463 View Code Duplication
      if (static::$db->db_affected_rows()) // Обновляем данные только если ряд был затронут
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
464
      {
465
        $record_id = db_insert_id();
466
        // Вытаскиваем запись целиком, потому что в $set могли быть "данные по умолчанию"
467
        $result = static::db_get_record_by_id($location_type, $record_id);
0 ignored issues
show
Deprecated Code introduced by
The function classSupernova::db_get_record_by_id() has been deprecated. ( Ignorable by Annotation )

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

467
        $result = /** @scrutinizer ignore-deprecated */ static::db_get_record_by_id($location_type, $record_id);
Loading history...
Bug introduced by
It seems like $record_id can also be of type string; however, parameter $record_id_unsafe of classSupernova::db_get_record_by_id() does only seem to accept integer|array, maybe add an additional type check? ( Ignorable by Annotation )

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

467
        $result = static::db_get_record_by_id($location_type, /** @scrutinizer ignore-type */ $record_id);
Loading history...
468
        // Очищаем второстепенные кэши - потому что вставленная запись могла повлиять на результаты запросов или локация или еще чего
469
        // TODO - когда будет поддержка изменения индексов и локаций - можно будет вызывать её
470
        _SnCacheInternal::cache_clear($location_type, false); // Мягкий сброс - только $queries
471
      }
472
    }
473
474
    return $result;
475
  }
476
477
  public static function db_del_record_by_id($location_type, $safe_record_id) {
478
    if (!($safe_record_id = idval($safe_record_id))) {
479
      return false;
480
    }
481
482
    $location_info = &static::$location_info[$location_type];
483
    $id_field = $location_info[P_ID];
484
    $table_name = $location_info[P_TABLE_NAME];
485
    if ($result = static::db_query_delete("DELETE FROM `{{{$table_name}}}` WHERE `{$id_field}` = {$safe_record_id}")) {
486
      if (static::$db->db_affected_rows()) // Обновляем данные только если ряд был затронут
487
      {
488
        _SnCacheInternal::cache_unset($location_type, $safe_record_id);
489
      }
490
    }
491
492
    return $result;
493
  }
494
495
  public static function db_del_record_list($location_type, $condition) {
496
    if (!($condition = trim($condition))) {
497
      return false;
498
    }
499
500
    $table_name = static::$location_info[$location_type][P_TABLE_NAME];
501
502
    if ($result = static::db_query_delete("DELETE FROM `{{{$table_name}}}` WHERE {$condition}")) {
503
      if (static::$db->db_affected_rows()) // Обновляем данные только если ряд был затронут
504
      {
505
        // Обнуление кэша, потому что непонятно, что поменялось
506
        _SnCacheInternal::cache_clear($location_type);
507
      }
508
    }
509
510
    return $result;
511
  }
512
513
514
515
  // Работа с пользователями
516
517
  /**
518
   * Возвращает информацию о пользователе по его ID
519
   *
520
   * @param int|array $user_id_unsafe
521
   *    <p>int - ID пользователя</p>
522
   *    <p>array - запись пользователя с установленным полем ['id']</p>
523
   * @param bool      $for_update @deprecated
524
   * @param string    $fields @deprecated список полей или '*'/'' для всех полей
525
   * @param null      $player
526
   * @param bool|null $player Признак выбора записи пользователь типа "игрок"
527
   *    <p>null - Можно выбрать запись любого типа</p>
528
   *    <p>true - Выбирается только запись типа "игрок"</p>
529
   *    <p>false - Выбирается только запись типа "альянс"</p>
530
   *
531
   * @return array|false
532
   *    <p>false - Нет записи с указанным ID и $player</p>
533
   *    <p>array - запись типа $user</p>
534
   */
535
  public static function db_get_user_by_id($user_id_unsafe, $for_update = false, $fields = '*', $player = null) {
536
    $user = static::db_get_record_by_id(LOC_USER, $user_id_unsafe, $for_update, $fields);
0 ignored issues
show
Deprecated Code introduced by
The function classSupernova::db_get_record_by_id() has been deprecated. ( Ignorable by Annotation )

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

536
    $user = /** @scrutinizer ignore-deprecated */ static::db_get_record_by_id(LOC_USER, $user_id_unsafe, $for_update, $fields);
Loading history...
537
538
    return (is_array($user) &&
539
      (
540
        $player === null
541
        ||
542
        ($player === true && !$user['user_as_ally'])
543
        ||
544
        ($player === false && $user['user_as_ally'])
545
      )) ? $user : false;
546
  }
547
548
  /**
549
   * @param        $where_safe
550
   * @param bool   $for_update
551
   * @param string $fields
552
   *
553
   * @return array|null
554
   */
555
  public static function db_get_user_by_where($where_safe, $for_update = false, $fields = '*') {
0 ignored issues
show
Unused Code introduced by
The parameter $for_update is not used and could be removed. ( Ignorable by Annotation )

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

555
  public static function db_get_user_by_where($where_safe, /** @scrutinizer ignore-unused */ $for_update = false, $fields = '*') {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $fields is not used and could be removed. ( Ignorable by Annotation )

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

555
  public static function db_get_user_by_where($where_safe, $for_update = false, /** @scrutinizer ignore-unused */ $fields = '*') {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
556
    $user = null;
557
558
    if (!empty($where_safe)) {
559
      // Вытаскиваем запись
560
      $user = static::db_query_select(
561
        "SELECT * FROM {{users}} WHERE {$where_safe}",
562
        true
563
      );
564
565
      _SnCacheInternal::cache_set(LOC_USER, $user['id'], $user); // В кэш-юзер так же заполнять индексы
566
    }
567
568
    return $user;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $user also could return the type boolean|mysqli_result which is incompatible with the documented return type null|array.
Loading history...
569
  }
570
571
572
  /**
573
   * @param string $username_unsafe
574
   * @param null   $player
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $player is correct as it would always require null to be passed?
Loading history...
575
   * @param bool   $like
576
   *
577
   * @return array|null
578
   */
579
  public static function db_get_user_by_username($username_unsafe, $player = null, $like = false) {
0 ignored issues
show
Unused Code introduced by
The parameter $player is not used and could be removed. ( Ignorable by Annotation )

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

579
  public static function db_get_user_by_username($username_unsafe, /** @scrutinizer ignore-unused */ $player = null, $like = false) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
580
    if (!($username_unsafe = trim($username_unsafe))) {
581
      return null;
582
    }
583
584
    $username_safe = db_escape($like ? strtolower($username_unsafe) : $username_unsafe); // тут на самом деле strtolower() лишняя, но пусть будет
585
586
    $user = static::db_get_user_by_where("`username` " . ($like ? 'LIKE' : '=') . " '{$username_safe}'");
587
588
    return $user;
589
  }
590
591
  public static function db_unit_time_restrictions($date = SN_TIME_NOW) {
592
    $date = is_numeric($date) ? "FROM_UNIXTIME({$date})" : "'{$date}'";
593
594
    return
595
      "(unit_time_start IS NULL OR unit_time_start <= {$date}) AND
596
    (unit_time_finish IS NULL OR unit_time_finish = '1970-01-01 03:00:00' OR unit_time_finish >= {$date})";
597
  }
598
599
  public static function db_get_unit_by_id($unit_db_id, $for_update = false, $fields = '*') {
600
    // TODO запихивать в $data[LOC_LOCATION][$location_type][$location_id]
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% 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...
601
    $unit = static::db_get_record_by_id(LOC_UNIT, $unit_db_id, $for_update, $fields);
0 ignored issues
show
Bug introduced by
LOC_UNIT of type string is incompatible with the type integer expected by parameter $location_type of classSupernova::db_get_record_by_id(). ( Ignorable by Annotation )

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

601
    $unit = static::db_get_record_by_id(/** @scrutinizer ignore-type */ LOC_UNIT, $unit_db_id, $for_update, $fields);
Loading history...
Deprecated Code introduced by
The function classSupernova::db_get_record_by_id() has been deprecated. ( Ignorable by Annotation )

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

601
    $unit = /** @scrutinizer ignore-deprecated */ static::db_get_record_by_id(LOC_UNIT, $unit_db_id, $for_update, $fields);
Loading history...
602
    if (is_array($unit)) {
603
      _SnCacheInternal::unit_linkLocatorToData($unit, $unit_db_id);
604
    }
605
606
    return $unit;
607
  }
608
609
  /**
610
   * @param int $user_id
611
   * @param     $location_type
612
   * @param     $location_id
613
   *
614
   * @return array|false
615
   */
616
  public static function db_get_unit_list_by_location($user_id = 0, $location_type, $location_id) {
0 ignored issues
show
Unused Code introduced by
The parameter $user_id is not used and could be removed. ( Ignorable by Annotation )

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

616
  public static function db_get_unit_list_by_location(/** @scrutinizer ignore-unused */ $user_id = 0, $location_type, $location_id) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
617
    if (!($location_type = idval($location_type)) || !($location_id = idval($location_id))) {
618
      return false;
619
    }
620
621
    if (!_SnCacheInternal::unit_locatorIsSet($location_type, $location_id)) {
622
      $got_data = static::db_get_record_list(LOC_UNIT, "unit_location_type = {$location_type} AND unit_location_id = {$location_id} AND " . static::db_unit_time_restrictions());
623
      if (is_array($got_data)) {
624
        foreach ($got_data as $unit_db_id => $unitRow) {
625
          _SnCacheInternal::unit_linkLocatorToData($unitRow, $unit_db_id);
626
        }
627
      }
628
    }
629
630
    return _SnCacheInternal::unit_locatorGetAllFromLocation($location_type, $location_id);
631
  }
632
633
  public static function db_get_unit_by_location($user_id = 0, $location_type, $location_id, $unit_snid = 0, $for_update = false, $fields = '*') {
0 ignored issues
show
Unused Code introduced by
The parameter $fields is not used and could be removed. ( Ignorable by Annotation )

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

633
  public static function db_get_unit_by_location($user_id = 0, $location_type, $location_id, $unit_snid = 0, $for_update = false, /** @scrutinizer ignore-unused */ $fields = '*') {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $for_update is not used and could be removed. ( Ignorable by Annotation )

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

633
  public static function db_get_unit_by_location($user_id = 0, $location_type, $location_id, $unit_snid = 0, /** @scrutinizer ignore-unused */ $for_update = false, $fields = '*') {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
634
    static::db_get_unit_list_by_location($user_id, $location_type, $location_id);
635
636
    return
637
      !$unit_snid
638
        ? _SnCacheInternal::unit_locatorGetAllFromLocation($location_type, $location_id)
639
        : _SnCacheInternal::unit_locatorGetUnitFromLocation($location_type, $location_id, $unit_snid);
640
  }
641
642
643
  /*
644
   * С $for_update === true эта функция должна вызываться только из транзакции! Все соответствующие записи в users и planets должны быть уже блокированы!
645
   *
646
   * $que_type
647
   *   !$que_type - все очереди
648
   *   QUE_XXXXXX - конкретная очередь по планете
649
   * $user_id - ID пользователя
650
   * $planet_id
651
   *   $que_type == QUE_RESEARCH - игнорируется
652
   *   null - обработка очередей планет не производится
653
   *   false/0 - обрабатываются очереди всех планет по $user_id
654
   *   (integer) - обрабатываются локальные очереди для планеты. Нужно, например, в обработчике флотов
655
   *   иначе - $que_type для указанной планеты
656
   * $for_update - true == нужно блокировать записи
657
   *
658
   * TODO Работа при !$user_id
659
   * TODO Переформатировать вывод данных, что бы можно было возвращать данные по всем планетам и юзерам в одном запросе: добавить подмассивы 'que', 'planets', 'players'
660
   *
661
   */
662
  public static function db_que_list_by_type_location($user_id, $planet_id = null, $que_type = false, $for_update = false) {
0 ignored issues
show
Unused Code introduced by
The parameter $for_update is not used and could be removed. ( Ignorable by Annotation )

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

662
  public static function db_que_list_by_type_location($user_id, $planet_id = null, $que_type = false, /** @scrutinizer ignore-unused */ $for_update = false) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
663
    if (!$user_id) {
664
      pdump(debug_backtrace());
665
      die('No user_id for que_get_que()');
666
    }
667
668
    $ques = array();
669
670
    $query = array();
671
672
    if ($user_id = idval($user_id)) {
673
      $query[] = "`que_player_id` = {$user_id}";
674
    }
675
676
    if ($que_type == QUE_RESEARCH || $planet_id === null) {
677
      $query[] = "`que_planet_id` IS NULL";
678
    } elseif ($planet_id) {
679
      $query[] = "(`que_planet_id` = {$planet_id}" . ($que_type ? '' : ' OR que_planet_id IS NULL') . ")";
680
    }
681
    if ($que_type) {
682
      $query[] = "`que_type` = {$que_type}";
683
    }
684
685
    $ques['items'] = static::db_get_record_list(LOC_QUE, implode(' AND ', $query));
686
687
    return que_recalculate($ques);
688
  }
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
  // que_process не всегда должна работать в режиме прямой работы с БД !! Она может работать и в режиме эмуляции
767
  // !!!!!!!! После que_get брать не [0] элемент, а first() - тогда можно в индекс элемента засовывать que_id из таблицы
768
769
770
  // TODO - это вообще-то надо хранить в конфигурации
771
  public static function db_get_user_player_username_last_registered() {
772
    $user = static::db_query_select(
773
      'SELECT * FROM `{{users}}` WHERE `user_as_ally` IS NULL ORDER BY `id` DESC',
774
      true
775
    );
776
    _SnCacheInternal::cache_set(LOC_USER, $user['id'], $user);
777
778
    return isset($user['username']) ? $user['username'] : '';
779
  }
780
781
  // Это для поиска по кэшу
782
  protected static function db_get_record_by_field($location_type) {
0 ignored issues
show
Unused Code introduced by
The parameter $location_type is not used and could be removed. ( Ignorable by Annotation )

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

782
  protected static function db_get_record_by_field(/** @scrutinizer ignore-unused */ $location_type) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
783
  }
784
785
  // Для модулей - регистрация юнитов
786
  public static function unit_register() {
787
788
  }
789
790
791
  public static function loadFileSettings() {
792
    $dbsettings = array();
793
794
    require(SN_ROOT_PHYSICAL . "config" . DOT_PHP_EX);
795
    //self::$db_prefix = $dbsettings['prefix'];
0 ignored issues
show
Unused Code Comprehensibility introduced by
73% 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...
796
    self::$cache_prefix = !empty($dbsettings['cache_prefix']) ? $dbsettings['cache_prefix'] : $dbsettings['prefix'];
797
    self::$db_name = $dbsettings['name'];
798
    self::$sn_secret_word = $dbsettings['secretword'];
799
800
    self::services();
801
802
    unset($dbsettings);
803
  }
804
805
  public static function init_global_objects() {
806
    global $sn_cache, $config, $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...
807
808
    $debug = self::$debug = self::$gc->debug;
809
    self::$db = self::$gc->db;
810
    self::$db->sn_db_connect();
811
812
    self::$user_options = new userOptions(0);
813
814
    // Initializing global 'cache' object
815
    $sn_cache = static::$cache = self::$gc->cache;
816
    $tables = classSupernova::$db->schema()->getSnTables();
817
    empty($tables) && die('DB error - cannot find any table. Halting...');
818
819
    // Initializing global "config" object
820
    $config = static::$config = self::$gc->config;
821
822
    // Initializing statics
823
    Vector::_staticInit(static::$config);
824
  }
825
826
  /**
827
   * @param int    $newStatus
828
   * @param string $newMessage
829
   *
830
   * @return int
831
   */
832
  public static function gameDisable($newStatus = GAME_DISABLE_REASON, $newMessage = '') {
0 ignored issues
show
Unused Code introduced by
The parameter $newMessage is not used and could be removed. ( Ignorable by Annotation )

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

832
  public static function gameDisable($newStatus = GAME_DISABLE_REASON, /** @scrutinizer ignore-unused */ $newMessage = '') {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
833
    $old_server_status = intval(self::$config->db_loadItem('game_disable'));
834
    self::$config->db_saveItem('game_disable', $newStatus);
835
836
    return $old_server_status;
837
  }
838
839
  public static function gameEnable() {
840
    self::$config->db_saveItem('game_disable', GAME_DISABLE_NONE);
841
  }
842
843
  /**
844
   * Is game disabled?
845
   *
846
   * @return bool
847
   */
848
  public static function gameIsDisabled() {
849
    return self::$config->game_disable != GAME_DISABLE_NONE;
850
  }
851
852
853
  /**
854
   * @return GlobalContainer
855
   */
856
  public static function services() {
857
    if (empty(self::$gc)) {
858
      self::$gc = new GlobalContainer(array(
859
        'cachePrefix' => self::$cache_prefix,
860
      ));
861
    }
862
863
    return self::$gc;
864
  }
865
866
}
867