Completed
Push — trunk ( 48600c...80fb95 )
by SuperNova.WS
04:23
created

Account::getMetamatterSum()   B

Complexity

Conditions 7
Paths 16

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
cc 7
eloc 8
nc 16
nop 2
dl 0
loc 15
ccs 0
cts 13
cp 0
crap 56
rs 8.2222
c 0
b 0
f 0
1
<?php
2
3
use \DBAL\DbQuery;
4
5
/**
6
 * User: Gorlum
7
 * Date: 24.08.2015
8
 * Time: 6:00
9
 */
10
class Account {
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...
11
  /**
12
   * @var int
13
   */
14
  public $account_id = 0;
15
  /**
16
   * @var string
17
   */
18
  public $account_name = '';
19
  /**
20
   * @var string
21
   */
22
  public $account_password = '';
23
  /**
24
   * @var string
25
   */
26
  public $account_salt = '';
27
  /**
28
   * @var string
29
   */
30
  public $account_email = '';
31
  /**
32
   * @var int
33
   */
34
  public $account_email_verified = 0;
35
  /**
36
   * @var string
37
   */
38
  public $account_register_time = '';
39
  /**
40
   * @var string
41
   */
42
  public $account_language = '';
43
44
  public $account_metamatter = 0;
45
  public $account_metamatter_total = 0;
46
47
  /**
48
   * @var int
49
   */
50
  public $is_exists = 0;
51
  /**
52
   * @var int
53
   */
54
  public $is_loaded = 0;
55
56
  /**
57
   * @var db_mysql
58
   */
59
  public $db;
60
61
  protected $sn_root_path = SN_ROOT_RELATIVE;
62
  protected $cookie_name = SN_COOKIE;
63
  protected $cookie_name_impersonate = SN_COOKIE_I;
64
65
  protected $table_check = array(
66
    'account' => 'account',
67
    'log_metamatter' => 'log_metamatter',
68
  );
69
70
  public function reset() {
71
    $this->account_id = 0;
72
    $this->account_name = '';
73
    $this->account_password = '';
74
    $this->account_salt = '';
75
    $this->account_email = '';
76
    $this->account_email_verified = 0;
77
    $this->account_register_time = '';
78
    $this->account_language = '';
79
80
    $this->is_exists = 0;
81
    $this->is_loaded = 0;
82
  }
83
  public function __construct($db = null) {
84
    $this->reset();
85
86
    $this->db = is_object($db) ? $db : SN::$db;
87
88
    $this->sn_root_path = SN_ROOT_RELATIVE;
89
    $this->cookie_name = SN_COOKIE;
90
    $this->cookie_name_impersonate = $this->cookie_name . AUTH_COOKIE_IMPERSONATE_SUFFIX;
91
    $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...
92
93
    $snTableNames = $this->db->schema()->getSnTables();
94
    foreach($this->table_check as $table_name) {
95
      if(empty($snTableNames[$table_name])) {
96
        die('Если вы видите это сообщение первый раз после обновления релиза - просто перегрузите страницу.<br />
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...
97
              В противном случае - сообщите Администрации сервера об ошибке.<br/>
98
              Не хватает таблицы для работы системы авторизации: ' . $table_name);
99
      }
100
    }
101
  }
102
103
  // OK 4.5
104
  public function password_check($password_unsafe) {
105
    return $this->password_encode($password_unsafe, $this->account_salt) == $this->account_password;
106
  }
107
108
  /**
109
   * Меняет пароль у аккаунта в БД
110
   *
111
   * @param      $old_password_unsafe
112
   * @param      $new_password_unsafe
113
   * @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...
114
   *
115
   * @return bool
116
   */
117
  // OK v4.6
118
  public function password_change($old_password_unsafe, $new_password_unsafe, $salt_unsafe = null) {
119
    if(!$this->password_check($old_password_unsafe)) {
120
      return false;
121
    }
122
123
    $salt_unsafe === null ? $salt_unsafe = $this->password_salt_generate() : false;
124
    $result = $this->db_set_password($new_password_unsafe, $salt_unsafe);
125
126
    return $result;
127
  }
128
129
130
  /**
131
   * Заполняет поля объекта значениями результата запроса
132
   *
133
   * @param array $row
134
   *
135
   * @return bool
136
   */
137
  // OK v4.5
138
  public function assign_from_db_row($row) {
139
    $this->reset();
140
    if(empty($row) || !is_array($row)) {
141
      return false;
142
    }
143
    $this->account_id = $row['account_id'];
144
    $this->account_name = $row['account_name'];
145
    $this->account_password = $row['account_password'];
146
    $this->account_salt = $row['account_salt'];
147
    $this->account_email = $row['account_email'];
148
    $this->account_email_verified = $row['account_email_verified'];
149
    $this->account_register_time = $row['account_register_time'];
150
    $this->account_language = $row['account_language'];
151
152
    $this->account_metamatter = $row['account_metamatter'];
153
    $this->account_metamatter_total = $row['account_metamatter_total'];
154
155
    $this->is_exists = 1;
156
    $this->is_loaded = 1;
157
158
    return true;
159
  }
160
161
  /**
162
   * Возвращает аккаунт по его ID
163
   *
164
   * @param $account_id_unsafe
165
   *
166
   * @return bool
167
   */
168
  // OK v4.5
169
  public function db_get_by_id($account_id_unsafe) {
170
    $this->reset();
171
172
    $account_id_safe = round(floatval($account_id_unsafe));
173
174
    $account_row = $this->db->doquery("SELECT * FROM {{account}} WHERE `account_id` = {$account_id_safe}", true);
175
    return $this->assign_from_db_row($account_row);
176
  }
177
  /**
178
   * Возвращает аккаунт по имени
179
   *
180
   * @param string $account_name_safe
181
   *
182
   * @return bool
183
   */
184
  // OK v4.5
185
  public function db_get_by_name($account_name_unsafe) {
186
    $this->reset();
187
188
    $account_name_safe = $this->db->db_escape($account_name_unsafe);
189
190
    $account_row = $this->db->doquery("SELECT * FROM {{account}} WHERE LOWER(`account_name`) = LOWER('{$account_name_safe}') FOR UPDATE", true);
191
    return $this->assign_from_db_row($account_row);
192
  }
193
  /**
194
   * Возвращает аккаунт по емейлу
195
   *
196
   * @param string $email_unsafe
197
   *
198
   * @return bool
199
   */
200
  // OK v4.5
201
  public function db_get_by_email($email_unsafe) {
202
    $this->reset();
203
204
    $email_safe = $this->db->db_escape($email_unsafe);
205
    if($email_safe) {
206
      $account_row = $this->db->doquery("SELECT * FROM {{account}} WHERE LOWER(`account_email`) = LOWER('{$email_safe}') FOR UPDATE;", true);
207
208
      return $this->assign_from_db_row($account_row);
209
    } else {
210
      return false;
211
    }
212
  }
213
  /**
214
   * Возвращает аккаунт по имени или аккаунту - проверка уникальных значений
215
   *
216
   * @param string $account_name_unsafe
217
   * @param string $email_unsafe
218
   *
219
   * @return bool
220
   *
221
   */
222
  // OK v4.5
223
  public function db_get_by_name_or_email($account_name_unsafe, $email_unsafe) {
224
    $this->reset();
225
226
    $account_name_safe = $this->db->db_escape($account_name_unsafe);
227
    $email_safe = $this->db->db_escape($email_unsafe);
228
229
    $account = $this->db->doquery("SELECT * FROM {{account}} WHERE LOWER(`account_name`) = LOWER('{$account_name_safe}') OR LOWER(`account_name`) = LOWER('{$email_safe}') OR LOWER(`account_email`) = LOWER('{$email_safe}') FOR UPDATE", true);
230
    return $this->assign_from_db_row($account);
231
  }
232
233
  /**
234
   * @param int|string $player_id_unsafe - player ID
235
   *
236
   * @return bool
237
   */
238
  public function dbGetByPlayerId($player_id_unsafe) {
239
    $translation = PlayerToAccountTranslate::db_translate_get_account_by_user_id($player_id_unsafe, core_auth::$main_provider->provider_id);
240
    if (empty($translation[$player_id_unsafe][core_auth::$main_provider->provider_id])) {
241
      return false;
242
    }
243
244
    $account_translation = reset($translation[$player_id_unsafe][core_auth::$main_provider->provider_id]);
245
    if (empty($account_translation['provider_account_id'])) {
246
      return false;
247
    }
248
249
    return $this->db_get_by_id($account_translation['provider_account_id']);
250
  }
251
252
253
  /**
254
   * Создает аккаунт
255
   *
256
   * @throws Exception
257
   */
258
  // OK v4.5
259
  public function db_create($account_name_unsafe, $password_raw, $email_unsafe, $language_unsafe = null, $salt_unsafe = null) {
260
    $this->reset();
261
262
    $account_name_safe = $this->db->db_escape($account_name_unsafe);
263
    $email_safe = $this->db->db_escape($email_unsafe);
264
    $language_safe = $this->db->db_escape($language_unsafe === null ? DEFAULT_LANG : $language_unsafe);
265
266
    $salt_unsafe === null ? $salt_unsafe = $this->password_salt_generate() : false;
267
    $password_salted_safe = $this->db->db_escape($this->password_encode($password_raw, $salt_unsafe));
268
    $salt_safe = $this->db->db_escape($salt_unsafe);
269
270
    $result = $this->db->doquery(
271
      "INSERT INTO {{account}} SET
272
        `account_name` = '{$account_name_safe}',
273
        `account_password` = '{$password_salted_safe}',
274
        `account_salt` = '{$salt_safe}',
275
        `account_email` = LOWER('{$email_safe}'),
276
        `account_language` = '{$language_safe}'"
277
    );
278
    if(!$result) {
279
      throw new Exception(REGISTER_ERROR_ACCOUNT_CREATE, ERR_ERROR);
280
    }
281
282
    if(!($account_id = $this->db->db_insert_id())) {
283
      throw new Exception(REGISTER_ERROR_ACCOUNT_CREATE, ERR_ERROR);
284
    }
285
286
    return $this->db_get_by_id($account_id);
287
  }
288
289
  /**
290
   * Физически меняет пароль аккаунта в БД
291
   *
292
   * @param string $password_unsafe
293
   * @param string $salt_unsafe
294
   *
295
   * @return bool
296
   */
297
  // OK v4.5
298
  public function db_set_password($password_unsafe, $salt_unsafe) {
299
    $password_encoded_unsafe = $this->password_encode($password_unsafe, $salt_unsafe);
300
    $password_encoded_safe = $this->db->db_escape($password_encoded_unsafe);
301
302
    $account_id_safe = $this->db->db_escape($this->account_id);
303
    $salt_safe = $this->db->db_escape($salt_unsafe);
304
305
    $result = $this->db->doquery(
306
      "UPDATE {{account}} SET
307
        `account_password` = '{$password_encoded_safe}',
308
        `account_salt` = '{$salt_safe}'
309
      WHERE `account_id` = '{$account_id_safe}'"
310
    ) ? true : false;
311
312
    if($result) {
313
      $result = $this->db_get_by_id($this->account_id);
314
    }
315
316
    return $result;
317
  }
318
319
320
321
  /**
322
   * Просаливает пароль
323
   *
324
   * @param $password
325
   * @param $salt
326
   *
327
   * @return string
328
   */
329
  // OK v4.5
330
  protected function password_encode($password, $salt) {
331
    return core_auth::password_encode($password, $salt);
332
  }
333
  /**
334
   * Генерирует соль
335
   *
336
   * @return string
337
   */
338
  // OK v4.5
339
  protected function password_salt_generate() {
340
    return core_auth::password_salt_generate();
341
  }
342
343
  /**
344
   * Вставляет запись об изменении количества ММ в лог ММ
345
   *
346
   * @param $comment
347
   * @param $change_type
348
   * @param $metamatter
349
   *
350
   * @return int|string
351
   */
352
  // OK 4.8
353
  protected function db_mm_log_insert($comment, $change_type, $metamatter, $user_id_unsafe) {
354
    $provider_id_safe = intval(core_auth::$main_provider->provider_id);
355
    //$account_id_safe = $this->db->db_escape($this->account_id);
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...
356
    $account_id_safe = intval($this->account_id);
357
    $account_name_safe = $this->db->db_escape($this->account_name);
358
359
    // $user_id_safe = $this->db->db_escape(core_auth::$user['id']);
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% 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...
360
    // $user_id_safe = intval(core_auth::$user['id']);
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...
361
    $user_id_safe = intval($user_id_unsafe);
362
    $username_safe = !empty(core_auth::$user['username']) ? $this->db->db_escape(core_auth::$user['username']) : '';
363
364
    $metamatter = round(floatval($metamatter));
365
366
    $comment_safe = $this->db->db_escape($comment);
367
368
    $server_name_safe = $this->db->db_escape(SN_ROOT_VIRTUAL);
369
    $page_url_safe = $this->db->db_escape($_SERVER['SCRIPT_NAME']);
370
371
    $this->db->doquery("INSERT INTO {{log_metamatter}} SET
372
        `provider_id` = {$provider_id_safe},
373
        `account_id` = {$account_id_safe},
374
        `account_name` = '{$account_name_safe}',
375
        `user_id` = {$user_id_safe},
376
        `username` = '{$username_safe}',
377
        `reason` = {$change_type},
378
        `amount` = {$metamatter},
379
        `comment` = '{$comment_safe}',
380
        `server_name` = '{$server_name_safe}',
381
        `page` = '{$page_url_safe}'
382
      ;");
383
    $result = $this->db->db_insert_id();
384
385
    return $result;
386
  }
387
388
  // OK 4.8
389
390
  /**
391
   * @param int               $change_type
392
   * @param float             $metamatter
393
   * @param string|array|bool $comment
394
   * @param bool              $already_changed
395
   *
396
   * @return array|bool|int|mysqli_result|null|string
397
   */
398
  public function metamatter_change($change_type, $metamatter, $comment = false, $already_changed = false) {
399
    global $debug, $mm_change_legit, $config, $sn_module;
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...
400
401
    if(!$this->is_exists || !($metamatter = round(floatval($metamatter)))) {
402
      $debug->error('Ошибка при попытке манипуляции с ММ');
403
      return false;
404
    }
405
406
    $account_id_safe = $this->db->db_escape($this->account_id);
407
408
    $mm_change_legit = true;
409
    // $sn_data_metamatter_db_name = pname_resource_name(RES_METAMATTER);
0 ignored issues
show
Unused Code Comprehensibility introduced by
40% 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...
410
    if($already_changed) {
411
      $metamatter_total_delta = 0;
412
      $result = -1;
413
    } else {
414
      $metamatter_total_delta = $metamatter > 0 ? $metamatter : 0;
415
416
      $result = $this->db->doquery(
417
        "UPDATE {{account}}
418
        SET
419
          `account_metamatter` = `account_metamatter` + '{$metamatter}'" .
420
          ($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}'" : '') .
421
        " WHERE `account_id` = {$account_id_safe}"
422
      );
423
      if(!$result) {
424
        $debug->error("Error adjusting Metamatter for player ID {$this->account_id} (Player Not Found?) with {$metamatter}. Reason: {$comment}", 'Metamatter Change', 402);
425
      }
426
      $result = SN::$db->db_affected_rows();
427
428
      $this->awardImmortal($metamatter, $config, $sn_module);
429
    }
430
431
    if(empty(core_auth::$user['id'])) {
432
      $user_list = PlayerToAccountTranslate::db_translate_get_users_from_account_list(core_auth::$main_provider->provider_id, $this->account_id);
433
      reset($user_list);
434
      $user_id_unsafe = key($user_list);
435
    } else {
436
      $user_id_unsafe = core_auth::$user['id'];
437
    }
438
    $user_id_safe = $this->db->db_escape($user_id_unsafe);
439
440
    if(!$result) {
441
      $debug->error("Error adjusting Metamatter for player ID {$this->account_id} (Player Not Found?) with {$metamatter}. Reason: {$comment}", 'Metamatter Change', 402);
442
    }
443
444
    if(!$already_changed) {
445
      $this->account_metamatter += $metamatter;
446
      $this->account_metamatter_total += $metamatter_total_delta;
447
    }
448
449
    if(is_array($comment)) {
450
      $comment = call_user_func_array('sprintf', $comment);
451
    }
452
453
    $result = $this->db_mm_log_insert($comment, $change_type, $metamatter, $user_id_unsafe);
454
455
    if($metamatter > 0 && !empty($user_id_safe)) {
456
      $old_referral = doquery("SELECT * FROM {{referrals}} WHERE `id` = {$user_id_safe} LIMIT 1 FOR UPDATE;", '', true);
457
      if($old_referral['id']) {
458
        $dark_matter_from_metamatter = $metamatter * AFFILIATE_MM_TO_REFERRAL_DM;
459
        doquery("UPDATE {{referrals}} SET dark_matter = dark_matter + '{$dark_matter_from_metamatter}' WHERE `id` = {$user_id_safe} LIMIT 1;");
460
        $new_referral = doquery("SELECT * FROM {{referrals}} WHERE `id` = {$user_id_safe} LIMIT 1;", '', true);
461
462
        $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);
463
        if($partner_bonus > 0 && $new_referral['dark_matter'] >= $config->rpg_bonus_minimum) {
464
          rpg_points_change($new_referral['id_partner'], RPG_REFERRAL_BOUGHT_MM, $partner_bonus, "Incoming MM From Referral ID {$user_id_safe}");
465
        }
466
      }
467
    }
468
469
    $mm_change_legit = false;
470
    return $result;
471
  }
472
473
  /**
474
   *
475
   * @return bool
476
   * @throws Exception
477
   */
478
  public function cookieSet($rememberMe = false, $domain = null) {
479
    if(!$this->is_exists) {
480
      throw new Exception(LOGIN_ERROR_NO_ACCOUNT_FOR_COOKIE_SET, ERR_ERROR);
481
    }
482
483
    $expire_time = $rememberMe ? SN_TIME_NOW + PERIOD_YEAR : 0;
484
485
    $password_encoded = $this->password_encode_for_cookie($this->account_password);
486
    $cookie = $this->account_id . AUTH_COOKIE_DELIMETER . $password_encoded . AUTH_COOKIE_DELIMETER . $rememberMe;
487
//    $this->flog("cookie_set() - Устанавливаем куку {$cookie}");
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% 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...
488
489
    return sn_setcookie($this->cookie_name, $cookie, $expire_time, $this->sn_root_path, $domain);
490
  }
491
492
  /**
493
   * Очищает куку аккаунта - совсем или восстанавливая куку текущего имперсонатора
494
   */
495
  // OK v4.1
496
  public function cookieClear($domain = null) {
497
    // Автоматически вообще-то - если установлена кука имперсонатора - то чистим обычную, а куку имперсонатора - копируем в неё
498
    if(!empty($_COOKIE[$this->cookie_name_impersonate])) {
499
      sn_setcookie($this->cookie_name, $_COOKIE[$this->cookie_name_impersonate], SN_TIME_NOW + PERIOD_YEAR, $this->sn_root_path, $domain);
500
      sn_setcookie($this->cookie_name_impersonate, '', SN_TIME_NOW - PERIOD_WEEK, $this->sn_root_path, $domain);
501
    } else {
502
      sn_setcookie($this->cookie_name, '', SN_TIME_NOW - PERIOD_WEEK, $this->sn_root_path, $domain);
503
    }
504
  }
505
506
  public function cookieLogin(&$rememberMe = false) {
507
    // Пытаемся войти по куке
508
    if(!empty($_COOKIE[$this->cookie_name])) {
509
      if(count(explode("/%/", $_COOKIE[$this->cookie_name])) < 4) {
510
        list($account_id_unsafe, $cookie_password_hash_salted, $user_remember_me) = explode(AUTH_COOKIE_DELIMETER, $_COOKIE[$this->cookie_name]);
511
      } else {
512
        list($account_id_unsafe, $user_name, $cookie_password_hash_salted, $user_remember_me) = explode("/%/", $_COOKIE[$this->cookie_name]);
513
      }
514
515
      if(
516
        $this->db_get_by_id($account_id_unsafe)
517
        && ($this->password_encode_for_cookie($this->account_password) == $cookie_password_hash_salted)
518
      ) {
519
        $rememberMe = intval($user_remember_me);
520
521
        return true;
522
      }
523
    }
524
525
    // Невалидная кука - чистим
526
    $this->cookieClear();
527
528
    return false;
529
  }
530
531
  protected function password_encode_for_cookie($password) {
532
    return md5("{$password}--" . $this->secret_word);
533
  }
534
535
  /**
536
   * @param int|float      $metamatter
537
   * @param classConfig    $config
538
   * @param player_award[] $sn_module
539
   */
540
  protected function awardImmortal($metamatter, $config, $sn_module) {
541
    if ($this->account_metamatter + $metamatter >= $config->player_metamatter_immortal && is_object($sn_module['player_award'])) {
542
      $account_translation = PlayerToAccountTranslate::db_translate_get_users_from_account_list(ACCOUNT_PROVIDER_LOCAL, $this->account_id);
543
      if (!empty($account_translation)) {
544
        reset($account_translation);
545
        $thisUserId = key($account_translation);
546
        if ($thisUserId) {
547
          $thisUser = ['id' => $thisUserId];
548
          if (!mrc_get_level($thisUser, [], UNIT_AWARD_MEMORY_IMMORTAL, true)) {
549
            $sn_module['player_award']->award($thisUserId, UNIT_AWARD_MEMORY, UNIT_AWARD_MEMORY_IMMORTAL);
550
          }
551
        }
552
      }
553
    }
554
  }
555
556
  /**
557
   * @param string|array $where
558
   * @param string|array $group
559
   *
560
   * @return bool|mysqli_result|null
561
   */
562
  public function getMetamatterSum($where = '', $group = '') {
563
    if(is_array($where) && !empty($where)) {
564
      $where = implode(' AND ', $where);
565
    }
566
    if(is_array($group) && !empty($group)) {
567
      $group = implode(',', $group);
568
    }
569
570
    $sql = "SELECT SUM(`amount`) as 'mm', reason, account_id, account_name, user_id, username
571
          FROM `{{log_metamatter}}`"
572
      . (!empty($where) ? ' WHERE ' . $where : '')
573
      . (!empty($group) ? ' GROUP BY ' . $group : '')
574
    ;
575
576
    return $this->db->doquery($sql);
577
  }
578
579
}
580