Issues (1369)

classes/Account.php (10 issues)

1
<?php
2
3
use DBAL\db_mysql;
4
use \DBAL\DbQuery;
0 ignored issues
show
The type \DBAL\DbQuery was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
5
6
/**
7
 * User: Gorlum
8
 * Date: 24.08.2015
9
 * Time: 6:00
10
 */
11
class Account {
12
  /**
13
   * @var int
14
   */
15
  public $account_id = 0;
16
  /**
17
   * @var string
18
   */
19
  public $account_name = '';
20
  /**
21
   * @var string
22
   */
23
  public $account_password = '';
24
  /**
25
   * @var string
26
   */
27
  public $account_salt = '';
28
  /**
29
   * @var string
30
   */
31
  public $account_email = '';
32
  /**
33
   * @var int
34
   */
35
  public $account_email_verified = 0;
36
  /**
37
   * @var string
38
   */
39
  public $account_register_time = '';
40
  /**
41
   * @var string
42
   */
43
  public $account_language = '';
44
45
  public $account_metamatter = 0;
46
  public $account_metamatter_total = 0;
47
48
  /**
49
   * @var int
50
   */
51
  public $is_exists = 0;
52
  /**
53
   * @var int
54
   */
55
  public $is_loaded = 0;
56
57
  /**
58
   * @var db_mysql
59
   */
60
  public $db;
61
62
  protected $sn_root_path = SN_ROOT_RELATIVE;
63
  protected $cookie_name = SN_COOKIE;
64
  protected $cookie_name_impersonate = SN_COOKIE_I;
65
66
  protected $table_check = array(
67
    'account' => 'account',
68
    'log_metamatter' => 'log_metamatter',
69
  );
70
71
  public function reset() {
72
    $this->account_id = 0;
73
    $this->account_name = '';
74
    $this->account_password = '';
75
    $this->account_salt = '';
76
    $this->account_email = '';
77
    $this->account_email_verified = 0;
78
    $this->account_register_time = '';
79
    $this->account_language = '';
80
81
    $this->is_exists = 0;
82
    $this->is_loaded = 0;
83
  }
84
  public function __construct($db = null) {
85
    $this->reset();
86
87
    $this->db = is_object($db) ? $db : SN::$db;
88
89
    $this->sn_root_path = SN_ROOT_RELATIVE;
90
    $this->cookie_name = SN_COOKIE;
91
    $this->cookie_name_impersonate = $this->cookie_name . AUTH_COOKIE_IMPERSONATE_SUFFIX;
92
    $this->secret_word = SN::$sn_secret_word;
0 ignored issues
show
Bug Best Practice introduced by
The property secret_word does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
93
94
    $snTableNames = $this->db->schema()->getSnTables();
95
    foreach($this->table_check as $table_name) {
96
      if(empty($snTableNames[$table_name])) {
97
        die('Если вы видите это сообщение первый раз после обновления релиза - просто перегрузите страницу.<br />
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...
98
              В противном случае - сообщите Администрации сервера об ошибке.<br/>
99
              Не хватает таблицы для работы системы авторизации: ' . $table_name);
100
      }
101
    }
102
  }
103
104
  // OK 4.5
105
  public function password_check($password_unsafe) {
106
    return $this->password_encode($password_unsafe, $this->account_salt) == $this->account_password;
107
  }
108
109
  /**
110
   * Меняет пароль у аккаунта в БД
111
   *
112
   * @param      $old_password_unsafe
113
   * @param      $new_password_unsafe
114
   * @param null $salt_unsafe
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $salt_unsafe is correct as it would always require null to be passed?
Loading history...
115
   *
116
   * @return bool
117
   */
118
  // OK v4.6
119
  public function password_change($old_password_unsafe, $new_password_unsafe, $salt_unsafe = null) {
120
    if(!$this->password_check($old_password_unsafe)) {
121
      return false;
122
    }
123
124
    $salt_unsafe === null ? $salt_unsafe = $this->password_salt_generate() : false;
0 ignored issues
show
The condition $salt_unsafe === null is always true.
Loading history...
125
    $result = $this->db_set_password($new_password_unsafe, $salt_unsafe);
126
127
    return $result;
128
  }
129
130
131
  /**
132
   * Заполняет поля объекта значениями результата запроса
133
   *
134
   * @param array $row
135
   *
136
   * @return bool
137
   */
138
  // OK v4.5
139
  public function assign_from_db_row($row) {
140
    $this->reset();
141
    if(empty($row) || !is_array($row)) {
142
      return false;
143
    }
144
    $this->account_id = $row['account_id'];
145
    $this->account_name = $row['account_name'];
146
    $this->account_password = $row['account_password'];
147
    $this->account_salt = $row['account_salt'];
148
    $this->account_email = $row['account_email'];
149
    $this->account_email_verified = $row['account_email_verified'];
150
    $this->account_register_time = $row['account_register_time'];
151
    $this->account_language = $row['account_language'];
152
153
    $this->account_metamatter = $row['account_metamatter'];
154
    $this->account_metamatter_total = $row['account_metamatter_total'];
155
156
    $this->is_exists = 1;
157
    $this->is_loaded = 1;
158
159
    return true;
160
  }
161
162
  /**
163
   * Возвращает аккаунт по его ID
164
   *
165
   * @param $account_id_unsafe
166
   *
167
   * @return bool
168
   */
169
  // OK v4.5
170
  public function db_get_by_id($account_id_unsafe) {
171
    $this->reset();
172
173
    $account_id_safe = round(floatval($account_id_unsafe));
174
175
    $account_row = $this->db->doQueryAndFetch("SELECT * FROM `{{account}}` WHERE `account_id` = {$account_id_safe}");
176
    return $this->assign_from_db_row($account_row);
177
  }
178
  /**
179
   * Возвращает аккаунт по имени
180
   *
181
   * @param string $account_name_safe
182
   *
183
   * @return bool
184
   */
185
  // OK v4.5
186
  public function db_get_by_name($account_name_unsafe) {
187
    $this->reset();
188
189
    $account_name_safe = $this->db->db_escape($account_name_unsafe);
190
191
    $account_row = $this->db->doQueryAndFetch("SELECT * FROM `{{account}}` WHERE LOWER(`account_name`) = LOWER('{$account_name_safe}') FOR UPDATE");
192
    return $this->assign_from_db_row($account_row);
193
  }
194
  /**
195
   * Возвращает аккаунт по емейлу
196
   *
197
   * @param string $email_unsafe
198
   *
199
   * @return bool
200
   */
201
  // OK v4.5
202
  public function db_get_by_email($email_unsafe) {
203
    $this->reset();
204
205
    $email_safe = $this->db->db_escape($email_unsafe);
206
    if($email_safe) {
207
      $account_row = $this->db->doQueryAndFetch("SELECT * FROM `{{account}}` WHERE LOWER(`account_email`) = LOWER('{$email_safe}') FOR UPDATE;");
208
209
      return $this->assign_from_db_row($account_row);
210
    } else {
211
      return false;
212
    }
213
  }
214
  /**
215
   * Возвращает аккаунт по имени или аккаунту - проверка уникальных значений
216
   *
217
   * @param string $account_name_unsafe
218
   * @param string $email_unsafe
219
   *
220
   * @return bool
221
   *
222
   */
223
  // OK v4.5
224
  public function db_get_by_name_or_email($account_name_unsafe, $email_unsafe) {
225
    $this->reset();
226
227
    $account_name_safe = $this->db->db_escape($account_name_unsafe);
228
    $email_safe = $this->db->db_escape($email_unsafe);
229
230
    $account = $this->db->doQueryAndFetch(
231
      "SELECT * FROM `{{account}}` 
232
      WHERE 
233
        LOWER(`account_name`) = LOWER('{$account_name_safe}') 
234
        OR LOWER(`account_name`) = LOWER('{$email_safe}') 
235
        OR LOWER(`account_email`) = LOWER('{$email_safe}') 
236
        FOR UPDATE"
237
    );
238
    return $this->assign_from_db_row($account);
239
  }
240
241
  /**
242
   * @param int|string $player_id_unsafe - player ID
243
   *
244
   * @return bool
245
   */
246
  public function dbGetByPlayerId($player_id_unsafe) {
247
    $translation = PlayerToAccountTranslate::db_translate_get_account_by_user_id($player_id_unsafe, core_auth::$main_provider->provider_id);
248
    if (empty($translation[$player_id_unsafe][core_auth::$main_provider->provider_id])) {
249
      return false;
250
    }
251
252
    $account_translation = reset($translation[$player_id_unsafe][core_auth::$main_provider->provider_id]);
253
    if (empty($account_translation['provider_account_id'])) {
254
      return false;
255
    }
256
257
    return $this->db_get_by_id($account_translation['provider_account_id']);
258
  }
259
260
261
  /**
262
   * Создает аккаунт
263
   *
264
   * @throws Exception
265
   */
266
  // OK v4.5
267
  public function db_create($account_name_unsafe, $password_raw, $email_unsafe, $language_unsafe = null, $salt_unsafe = null) {
268
    $this->reset();
269
270
    $account_name_safe = $this->db->db_escape($account_name_unsafe);
271
    $email_safe = $this->db->db_escape($email_unsafe);
272
    $language_safe = $this->db->db_escape($language_unsafe === null ? DEFAULT_LANG : $language_unsafe);
273
274
    $salt_unsafe === null ? $salt_unsafe = $this->password_salt_generate() : false;
275
    $password_salted_safe = $this->db->db_escape($this->password_encode($password_raw, $salt_unsafe));
276
    $salt_safe = $this->db->db_escape($salt_unsafe);
277
278
    $result = $this->db->doquery(
279
      "INSERT INTO `{{account}}` SET
280
        `account_name` = '{$account_name_safe}',
281
        `account_password` = '{$password_salted_safe}',
282
        `account_salt` = '{$salt_safe}',
283
        `account_email` = LOWER('{$email_safe}'),
284
        `account_language` = '{$language_safe}'"
285
    );
286
    if(!$result) {
287
      throw new Exception(REGISTER_ERROR_ACCOUNT_CREATE, ERR_ERROR);
288
    }
289
290
    if(!($account_id = $this->db->db_insert_id())) {
291
      throw new Exception(REGISTER_ERROR_ACCOUNT_CREATE, ERR_ERROR);
292
    }
293
294
    return $this->db_get_by_id($account_id);
295
  }
296
297
  /**
298
   * Физически меняет пароль аккаунта в БД
299
   *
300
   * @param string $password_unsafe
301
   * @param string $salt_unsafe
302
   *
303
   * @return bool
304
   */
305
  // OK v4.5
306
  public function db_set_password($password_unsafe, $salt_unsafe) {
307
    $password_encoded_unsafe = $this->password_encode($password_unsafe, $salt_unsafe);
308
    $password_encoded_safe = $this->db->db_escape($password_encoded_unsafe);
309
310
    $account_id_safe = $this->db->db_escape($this->account_id);
311
    $salt_safe = $this->db->db_escape($salt_unsafe);
312
313
    $result = $this->db->doquery(
314
      "UPDATE `{{account}}` SET
315
        `account_password` = '{$password_encoded_safe}',
316
        `account_salt` = '{$salt_safe}'
317
      WHERE `account_id` = '{$account_id_safe}'"
318
    ) ? true : false;
319
320
    if($result) {
321
      $result = $this->db_get_by_id($this->account_id);
322
    }
323
324
    return $result;
325
  }
326
327
328
329
  /**
330
   * Просаливает пароль
331
   *
332
   * @param $password
333
   * @param $salt
334
   *
335
   * @return string
336
   */
337
  // OK v4.5
338
  protected function password_encode($password, $salt) {
339
    return core_auth::password_encode($password, $salt);
340
  }
341
  /**
342
   * Генерирует соль
343
   *
344
   * @return string
345
   */
346
  // OK v4.5
347
  protected function password_salt_generate() {
348
    return core_auth::password_salt_generate();
349
  }
350
351
  /**
352
   * Вставляет запись об изменении количества ММ в лог ММ
353
   *
354
   * @param $comment
355
   * @param $change_type
356
   * @param $metamatter
357
   *
358
   * @return int|string
359
   */
360
  // OK 4.8
361
  protected function db_mm_log_insert($comment, $change_type, $metamatter, $user_id_unsafe) {
362
    $provider_id_safe = intval(core_auth::$main_provider->provider_id);
363
    //$account_id_safe = $this->db->db_escape($this->account_id);
364
    $account_id_safe = intval($this->account_id);
365
    $account_name_safe = $this->db->db_escape($this->account_name);
366
367
    // $user_id_safe = $this->db->db_escape(core_auth::$user['id']);
368
    // $user_id_safe = intval(core_auth::$user['id']);
369
    $user_id_safe = intval($user_id_unsafe);
370
    $username_safe = !empty(core_auth::$user['username']) ? $this->db->db_escape(core_auth::$user['username']) : '';
371
372
    $metamatter = round(floatval($metamatter));
373
374
    $comment_safe = $this->db->db_escape($comment);
375
376
    $server_name_safe = $this->db->db_escape(SN_ROOT_VIRTUAL);
377
    $page_url_safe = $this->db->db_escape($_SERVER['SCRIPT_NAME']);
378
379
    $this->db->doquery(
380
      "INSERT INTO `{{log_metamatter}}` 
381
      SET
382
        `provider_id` = {$provider_id_safe},
383
        `account_id` = {$account_id_safe},
384
        `account_name` = '{$account_name_safe}',
385
        `user_id` = {$user_id_safe},
386
        `username` = '{$username_safe}',
387
        `reason` = {$change_type},
388
        `amount` = {$metamatter},
389
        `comment` = '{$comment_safe}',
390
        `server_name` = '{$server_name_safe}',
391
        `page` = '{$page_url_safe}'
392
      ;"
393
    );
394
    $result = $this->db->db_insert_id();
395
396
    return $result;
397
  }
398
399
  // OK 4.8
400
401
  /**
402
   * @param int               $change_type
403
   * @param float             $metamatter
404
   * @param string|array|bool $comment
405
   * @param bool              $already_changed
406
   *
407
   * @return array|bool|int|mysqli_result|null|string
408
   */
409
  public function metamatter_change($change_type, $metamatter, $comment = false, $already_changed = false) {
410
    global $debug, $mm_change_legit, $config;
411
412
    if(!$this->is_exists || !($metamatter = round(floatval($metamatter)))) {
413
      $debug->error('Ошибка при попытке манипуляции с ММ');
414
      return false;
415
    }
416
417
    $account_id_safe = $this->db->db_escape($this->account_id);
418
419
    $mm_change_legit = true;
420
    // $sn_data_metamatter_db_name = pname_resource_name(RES_METAMATTER);
421
    if($already_changed) {
422
      $metamatter_total_delta = 0;
423
      $result = -1;
424
    } else {
425
      $metamatter_total_delta = $metamatter > 0 ? $metamatter : 0;
426
427
      $result = $this->db->doquery(
428
        "UPDATE `{{account}}`
429
        SET
430
          `account_metamatter` = `account_metamatter` + '{$metamatter}'" .
431
          ($metamatter_total_delta ? ", `account_immortal` = IF(`account_metamatter_total` + '{$metamatter_total_delta}' >= {$config->player_metamatter_immortal} AND `account_immortal` IS NULL, NOW(), `account_immortal`), `account_metamatter_total` = `account_metamatter_total` + '{$metamatter_total_delta}'" : '') .
432
        " WHERE `account_id` = {$account_id_safe}"
433
      );
434
      if(!$result) {
435
        $debug->error("Error adjusting Metamatter for player ID {$this->account_id} (Player Not Found?) with {$metamatter}. Reason: {$comment}", 'Metamatter Change', 402);
436
      }
437
      $result = SN::$db->db_affected_rows();
438
439
      $this->awardImmortal($metamatter, $config);
440
    }
441
442
    if(empty(core_auth::$user['id'])) {
443
      $user_list = PlayerToAccountTranslate::db_translate_get_users_from_account_list(core_auth::$main_provider->provider_id, $this->account_id);
444
      reset($user_list);
445
      $user_id_unsafe = key($user_list);
446
    } else {
447
      $user_id_unsafe = core_auth::$user['id'];
448
    }
449
    $user_id_safe = $this->db->db_escape($user_id_unsafe);
450
451
    if(!$result) {
452
      $debug->error("Error adjusting Metamatter for player ID {$this->account_id} (Player Not Found?) with {$metamatter}. Reason: {$comment}", 'Metamatter Change', 402);
453
    }
454
455
    if(!$already_changed) {
456
      $this->account_metamatter += $metamatter;
457
      $this->account_metamatter_total += $metamatter_total_delta;
458
    }
459
460
    if(is_array($comment)) {
461
      $comment = call_user_func_array('sprintf', $comment);
462
    }
463
464
    $result = $this->db_mm_log_insert($comment, $change_type, $metamatter, $user_id_unsafe);
465
466
    if($metamatter > 0 && !empty($user_id_safe)) {
467
      $old_referral = doquery("SELECT * FROM `{{referrals}}` WHERE `id` = {$user_id_safe} LIMIT 1 FOR UPDATE;", '', true);
0 ignored issues
show
Deprecated Code introduced by
The function doquery() 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
      $old_referral = /** @scrutinizer ignore-deprecated */ doquery("SELECT * FROM `{{referrals}}` WHERE `id` = {$user_id_safe} LIMIT 1 FOR UPDATE;", '', true);
Loading history...
468
      if($old_referral['id']) {
469
        $dark_matter_from_metamatter = $metamatter * AFFILIATE_MM_TO_REFERRAL_DM;
470
        doquery("UPDATE `{{referrals}}` SET dark_matter = dark_matter + '{$dark_matter_from_metamatter}' WHERE `id` = {$user_id_safe} LIMIT 1;");
0 ignored issues
show
Deprecated Code introduced by
The function doquery() 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

470
        /** @scrutinizer ignore-deprecated */ doquery("UPDATE `{{referrals}}` SET dark_matter = dark_matter + '{$dark_matter_from_metamatter}' WHERE `id` = {$user_id_safe} LIMIT 1;");
Loading history...
471
        $new_referral = doquery("SELECT * FROM `{{referrals}}` WHERE `id` = {$user_id_safe} LIMIT 1;", '', true);
0 ignored issues
show
Deprecated Code introduced by
The function doquery() 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

471
        $new_referral = /** @scrutinizer ignore-deprecated */ doquery("SELECT * FROM `{{referrals}}` WHERE `id` = {$user_id_safe} LIMIT 1;", '', true);
Loading history...
472
473
        $partner_bonus = floor($new_referral['dark_matter'] / $config->rpg_bonus_divisor) - ($old_referral['dark_matter'] >= $config->rpg_bonus_minimum ? floor($old_referral['dark_matter'] / $config->rpg_bonus_divisor) : 0);
474
        if($partner_bonus > 0 && $new_referral['dark_matter'] >= $config->rpg_bonus_minimum) {
475
          rpg_points_change($new_referral['id_partner'], RPG_REFERRAL_BOUGHT_MM, $partner_bonus, "Incoming MM From Referral ID {$user_id_safe}");
0 ignored issues
show
'Incoming MM From Referral ID '.$user_id_safe of type string is incompatible with the type boolean expected by parameter $comment of rpg_points_change(). ( Ignorable by Annotation )

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

475
          rpg_points_change($new_referral['id_partner'], RPG_REFERRAL_BOUGHT_MM, $partner_bonus, /** @scrutinizer ignore-type */ "Incoming MM From Referral ID {$user_id_safe}");
Loading history...
476
        }
477
      }
478
    }
479
480
    $mm_change_legit = false;
481
    return $result;
482
  }
483
484
  /**
485
   *
486
   * @return bool
487
   * @throws Exception
488
   */
489
  public function cookieSet($rememberMe = false, $domain = null) {
490
    if(!$this->is_exists) {
491
      throw new Exception(LOGIN_ERROR_NO_ACCOUNT_FOR_COOKIE_SET, ERR_ERROR);
492
    }
493
494
    $expire_time = $rememberMe ? SN_TIME_NOW + PERIOD_YEAR : 0;
495
496
    $password_encoded = $this->password_encode_for_cookie($this->account_password);
497
    $cookie = $this->account_id . AUTH_COOKIE_DELIMETER . $password_encoded . AUTH_COOKIE_DELIMETER . $rememberMe;
498
//    $this->flog("cookie_set() - Устанавливаем куку {$cookie}");
499
500
    return sn_setcookie($this->cookie_name, $cookie, $expire_time, $this->sn_root_path, $domain);
501
  }
502
503
  /**
504
   * Очищает куку аккаунта - совсем или восстанавливая куку текущего имперсонатора
505
   */
506
  // OK v4.1
507
  public function cookieClear($domain = null) {
508
    // Автоматически вообще-то - если установлена кука имперсонатора - то чистим обычную, а куку имперсонатора - копируем в неё
509
    if(!empty($_COOKIE[$this->cookie_name_impersonate])) {
510
      sn_setcookie($this->cookie_name, $_COOKIE[$this->cookie_name_impersonate], SN_TIME_NOW + PERIOD_YEAR, $this->sn_root_path, $domain);
511
      sn_setcookie($this->cookie_name_impersonate, '', SN_TIME_NOW - PERIOD_WEEK, $this->sn_root_path, $domain);
512
    } else {
513
      sn_setcookie($this->cookie_name, '', SN_TIME_NOW - PERIOD_WEEK, $this->sn_root_path, $domain);
514
    }
515
  }
516
517
  public function cookieLogin(&$rememberMe = false) {
518
    // Пытаемся войти по куке
519
    if(!empty($_COOKIE[$this->cookie_name])) {
520
      if(count(explode("/%/", $_COOKIE[$this->cookie_name])) < 4) {
521
        list($account_id_unsafe, $cookie_password_hash_salted, $user_remember_me) = explode(AUTH_COOKIE_DELIMETER, $_COOKIE[$this->cookie_name]);
522
      } else {
523
        list($account_id_unsafe, $user_name, $cookie_password_hash_salted, $user_remember_me) = explode("/%/", $_COOKIE[$this->cookie_name]);
524
      }
525
526
      if(
527
        $this->db_get_by_id($account_id_unsafe)
528
        && ($this->password_encode_for_cookie($this->account_password) == $cookie_password_hash_salted)
529
      ) {
530
        $rememberMe = intval($user_remember_me);
531
532
        return true;
533
      }
534
    }
535
536
    // Невалидная кука - чистим
537
    $this->cookieClear();
538
539
    return false;
540
  }
541
542
  protected function password_encode_for_cookie($password) {
543
    return md5("{$password}--" . $this->secret_word);
544
  }
545
546
  /**
547
   * @param int|float   $metamatter
548
   * @param classConfig $config
549
   */
550
  protected function awardImmortal($metamatter, $config) {
551
    if(!is_object($awardModule = moduleAward())) {
552
      return;
553
    }
554
    if ($this->account_metamatter + $metamatter >= $config->player_metamatter_immortal ) {
555
      $account_translation = PlayerToAccountTranslate::db_translate_get_users_from_account_list(ACCOUNT_PROVIDER_LOCAL, $this->account_id);
556
      if (!empty($account_translation)) {
557
        reset($account_translation);
558
        $thisUserId = key($account_translation);
559
        if ($thisUserId) {
560
          $thisUser = ['id' => $thisUserId];
561
          if (!mrc_get_level($thisUser, [], UNIT_AWARD_MEMORY_IMMORTAL, true)) {
562
            $awardModule->award($thisUserId, UNIT_AWARD_MEMORY, UNIT_AWARD_MEMORY_IMMORTAL);
0 ignored issues
show
The method award() does not exist on Modules\sn_module. ( Ignorable by Annotation )

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

562
            $awardModule->/** @scrutinizer ignore-call */ 
563
                          award($thisUserId, UNIT_AWARD_MEMORY, UNIT_AWARD_MEMORY_IMMORTAL);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
563
          }
564
        }
565
      }
566
    }
567
  }
568
569
  /**
570
   * @param string|array $where
571
   * @param string|array $group
572
   *
573
   * @return bool|mysqli_result|null
574
   */
575
  public function getMetamatterSum($where = '', $group = '') {
576
    if(is_array($where) && !empty($where)) {
577
      $where = implode(' AND ', $where);
578
    }
579
    if(is_array($group) && !empty($group)) {
580
      $group = implode(',', $group);
581
    }
582
583
    $sql = "SELECT SUM(`amount`) as 'mm', reason, account_id, account_name, user_id, username
584
          FROM `{{log_metamatter}}`"
585
      . (!empty($where) ? ' WHERE ' . $where : '')
586
      . (!empty($group) ? ' GROUP BY ' . $group : '')
587
    ;
588
589
    return $this->db->doquery($sql);
590
  }
591
592
}
593