1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace DBStatic; |
4
|
|
|
|
5
|
|
|
use classSupernova; |
6
|
|
|
use DbEmptyIterator; |
7
|
|
|
use DbMysqliResultIterator; |
8
|
|
|
use DbResultIterator; |
9
|
|
|
use mysqli_result; |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* Class DBStatic\DBStaticUser |
13
|
|
|
*/ |
14
|
|
|
class DBStaticUser { |
15
|
|
|
// public static $_table = 'users'; |
|
|
|
|
16
|
|
|
// public static $_idField = 'id'; |
17
|
|
|
|
18
|
|
|
// TODO - это вообще-то надо хранить в конфигурации |
19
|
|
|
/** |
20
|
|
|
* @return string |
21
|
|
|
*/ |
22
|
|
View Code Duplication |
public static function getLastRegisteredUserName() { |
|
|
|
|
23
|
|
|
$query = |
24
|
|
|
"SELECT `username` |
25
|
|
|
FROM `{{users}}` |
26
|
|
|
WHERE |
27
|
|
|
`user_as_ally` IS NULL |
28
|
|
|
AND |
29
|
|
|
`user_bot` = " . USER_BOT_PLAYER . " |
30
|
|
|
ORDER BY `id` DESC |
31
|
|
|
LIMIT 1" |
32
|
|
|
; |
33
|
|
|
$result = classSupernova::$db->doSelectFetchValue($query); |
34
|
|
|
|
35
|
|
|
// $query = |
|
|
|
|
36
|
|
|
// static::buildDBQ() |
37
|
|
|
// ->field('username') |
38
|
|
|
// ->where('`user_as_ally` IS NULL') |
39
|
|
|
// ->orderBy(array('`id` DESC')); |
40
|
|
|
// $result = (string)$query->selectValue(); |
41
|
|
|
|
42
|
|
|
return $result; |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @return DbResultIterator |
47
|
|
|
*/ |
48
|
|
View Code Duplication |
public static function db_player_list_export_blitz_info() { |
|
|
|
|
49
|
|
|
$query = |
50
|
|
|
"SELECT `id`, `username`, `total_rank`, `total_points`, `onlinetime` |
51
|
|
|
FROM `{{users}}` |
52
|
|
|
WHERE |
53
|
|
|
`user_as_ally` IS NULL |
54
|
|
|
AND |
55
|
|
|
`user_bot` = " . USER_BOT_PLAYER . " |
56
|
|
|
ORDER BY `id`"; |
57
|
|
|
$result = classSupernova::$db->doSelectIterator($query); |
58
|
|
|
|
59
|
|
|
|
60
|
|
|
// $result = static::buildDBQ() |
|
|
|
|
61
|
|
|
// ->fields(array('id', 'username', 'total_rank', 'total_points', 'onlinetime',)) |
62
|
|
|
// ->where('`user_as_ally` IS NULL') |
63
|
|
|
// ->orderBy(array('`id`')) |
64
|
|
|
// ->selectIterator(); |
65
|
|
|
|
66
|
|
|
return $result; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* @return DbResultIterator |
71
|
|
|
*/ |
72
|
|
View Code Duplication |
public static function db_user_list_non_bots() { |
|
|
|
|
73
|
|
|
$query = "SELECT `id` FROM `{{users}}` WHERE `user_as_ally` IS NULL AND `user_bot` = " . USER_BOT_PLAYER . " FOR UPDATE;"; |
74
|
|
|
$result = classSupernova::$db->doSelectIterator($query); |
75
|
|
|
|
76
|
|
|
// $query = |
|
|
|
|
77
|
|
|
// static::buildDBQ() |
78
|
|
|
// ->field('id') |
79
|
|
|
// ->where("`user_as_ally` IS NULL") |
80
|
|
|
// ->where("`user_bot` = " . USER_BOT_PLAYER) |
81
|
|
|
// ->setForUpdate(); |
82
|
|
|
// $result = $query->selectIterator(); |
83
|
|
|
|
84
|
|
|
return $result; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
public static function db_user_lock_with_target_owner_and_acs($user, $planet = array()) { |
88
|
|
|
$query = |
89
|
|
|
"SELECT 1 |
90
|
|
|
FROM `{{users}}` |
91
|
|
|
WHERE `id` = " . idval($user['id']) . |
92
|
|
|
(!empty($planet['id_owner']) ? ' OR `id` = ' . idval($planet['id_owner']) : '') . |
93
|
|
|
" FOR UPDATE"; |
94
|
|
|
|
95
|
|
|
classSupernova::$db->doSelect($query); |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* @param bool $online |
100
|
|
|
* |
101
|
|
|
* @return int |
102
|
|
|
*/ |
103
|
|
|
public static function db_user_count($online = false) { |
104
|
|
|
return intval(classSupernova::$db->doSelectFetchValue( |
105
|
|
|
"SELECT COUNT(`id`) AS `user_count` |
106
|
|
|
FROM `{{users}}` |
107
|
|
|
WHERE |
108
|
|
|
`user_as_ally` IS NULL" . |
109
|
|
|
($online ? ' AND `onlinetime` > ' . (SN_TIME_NOW - classSupernova::$config->game_users_online_timeout) : '') |
110
|
|
|
)); |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
public static function db_user_list_admin_sorted($sort, $online = false) { |
114
|
|
|
$query = "SELECT |
115
|
|
|
u.*, COUNT(r.id) AS referral_count, SUM(r.dark_matter) AS referral_dm |
116
|
|
|
FROM |
117
|
|
|
{{users}} as u |
118
|
|
|
LEFT JOIN |
119
|
|
|
{{referrals}} as r on r.id_partner = u.id |
120
|
|
|
WHERE " . |
121
|
|
|
($online ? "`onlinetime` >= " . intval(SN_TIME_NOW - classSupernova::$config->game_users_online_timeout) : 'user_as_ally IS NULL') . |
122
|
|
|
" GROUP BY u.id |
123
|
|
|
ORDER BY user_as_ally, {$sort} ASC"; |
124
|
|
|
$result = classSupernova::$db->doSelectIterator($query); |
125
|
|
|
|
126
|
|
|
// $query = static::buildDBQ() |
|
|
|
|
127
|
|
|
// ->setAlias('u') |
128
|
|
|
// ->field('u.*') |
129
|
|
|
// ->fieldCount('r.id', 'referral_count') |
130
|
|
|
// ->fieldSingleFunction('sum', 'r.dark_matter', 'referral_dm') |
131
|
|
|
// ->join('LEFT JOIN {{referrals}} as r on r.id_partner = u.id') |
132
|
|
|
// ->where($online ? "`onlinetime` >= " . intval(SN_TIME_NOW - classSupernova::$config->game_users_online_timeout) : 'user_as_ally IS NULL') |
133
|
|
|
// ->groupBy('u.id') |
134
|
|
|
// ->orderBy("user_as_ally, {$sort} ASC"); |
135
|
|
|
// |
136
|
|
|
// $result = $query->selectIterator(); |
137
|
|
|
|
138
|
|
|
return $result; |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
public static function db_user_list_to_celebrate($config_user_birthday_range) { |
142
|
|
|
$query = "SELECT |
143
|
|
|
`id`, `username`, `user_birthday`, `user_birthday_celebrated`, |
144
|
|
|
CONCAT(YEAR(CURRENT_DATE), DATE_FORMAT(`user_birthday`, '-%m-%d')) AS `current_birthday`, |
145
|
|
|
DATEDIFF(CURRENT_DATE, CONCAT(YEAR(CURRENT_DATE), DATE_FORMAT(`user_birthday`, '-%m-%d'))) AS `days_after_birthday` |
146
|
|
|
FROM |
147
|
|
|
`{{users}}` |
148
|
|
|
WHERE |
149
|
|
|
`user_birthday` IS NOT NULL |
150
|
|
|
AND `user_as_ally` IS NULL |
151
|
|
|
AND (`user_birthday_celebrated` IS NULL OR DATE_ADD(`user_birthday_celebrated`, INTERVAL 1 YEAR) < CURRENT_DATE) |
152
|
|
|
HAVING |
153
|
|
|
`days_after_birthday` >= 0 AND `days_after_birthday` < {$config_user_birthday_range} FOR UPDATE"; |
154
|
|
|
|
155
|
|
|
$result = classSupernova::$db->doSelectIterator($query); |
156
|
|
|
|
157
|
|
|
return $result; |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
/** |
161
|
|
|
* @return DbEmptyIterator|DbMysqliResultIterator |
162
|
|
|
*/ |
163
|
|
|
public static function db_user_list_admin_multiaccounts() { |
164
|
|
|
$query = "SELECT COUNT(*) AS `ip_count`, `user_lastip` |
165
|
|
|
FROM `{{users}}` |
166
|
|
|
WHERE `user_as_ally` IS NULL |
167
|
|
|
GROUP BY `user_lastip` |
168
|
|
|
HAVING COUNT(*) > 1"; |
169
|
|
|
|
170
|
|
|
return classSupernova::$db->doSelectIterator($query); |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
public static function db_player_list_blitz_delete_players() { |
174
|
|
|
classSupernova::$db->doDeleteDanger( |
|
|
|
|
175
|
|
|
TABLE_USERS, |
176
|
|
|
array(), |
177
|
|
|
array( |
178
|
|
|
"`username` LIKE 'Игрок%'" |
179
|
|
|
) |
180
|
|
|
); |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* @deprecated - NEVER change DM amount directly w/o logging! |
185
|
|
|
*/ |
186
|
|
|
public static function db_player_list_blitz_set_50k_dm() { |
187
|
|
|
classSupernova::$db->doUpdateTableSet( |
188
|
|
|
TABLE_USERS, |
189
|
|
|
array( |
190
|
|
|
'dark_matter' => 50000, |
191
|
|
|
'dark_matter_total' => 50000, |
192
|
|
|
) |
193
|
|
|
); |
194
|
|
|
|
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* Выбирает записи игроков по списку их ID |
200
|
|
|
* |
201
|
|
|
* @param $user_id_list |
202
|
|
|
* |
203
|
|
|
* @return array |
204
|
|
|
*/ |
205
|
|
|
public static function db_user_list_by_id($user_id_list) { |
206
|
|
|
!is_array($user_id_list) ? $user_id_list = array($user_id_list) : false; |
207
|
|
|
|
208
|
|
|
$user_list = array(); |
209
|
|
|
foreach ($user_id_list as $user_id_unsafe) { |
210
|
|
|
$user = DBStaticUser::db_user_by_id($user_id_unsafe); |
211
|
|
|
!empty($user) ? $user_list[$user_id_unsafe] = $user : false; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
return $user_list; |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
|
218
|
|
|
public static function db_user_by_username($username_unsafe, $for_update = false, $fields = '*', $player = null, $like = false) { |
|
|
|
|
219
|
|
|
// TODO Проверить, кстати - а везде ли нужно выбирать юзеров или где-то все-таки ищутся Альянсы ? |
220
|
|
|
if (!($username_unsafe = trim($username_unsafe))) { |
221
|
|
|
return false; |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
$user = null; |
225
|
|
|
if (classSupernova::$gc->snCache->isArrayLocation(LOC_USER)) { |
|
|
|
|
226
|
|
|
foreach (classSupernova::$gc->snCache->getData(LOC_USER) as $user_id => $user_data) { |
|
|
|
|
227
|
|
|
if (is_array($user_data) && isset($user_data['username'])) { |
228
|
|
|
// проверяем поле |
229
|
|
|
// TODO Возможно есть смысл всегда искать по strtolower - но может игрок захочет переименоваться с другим регистром? Проверить! |
230
|
|
|
if ((!$like && $user_data['username'] == $username_unsafe) || ($like && strtolower($user_data['username']) == strtolower($username_unsafe))) { |
231
|
|
|
// $user_as_ally = intval($user_data['user_as_ally']); |
|
|
|
|
232
|
|
|
$user_as_ally = idval($user_data['user_as_ally']); |
233
|
|
|
if ($player === null || ($player === true && !$user_as_ally) || ($player === false && $user_as_ally)) { |
234
|
|
|
$user = $user_data; |
235
|
|
|
break; |
236
|
|
|
} |
237
|
|
|
} |
238
|
|
|
} |
239
|
|
|
} |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
if ($user === null) { |
243
|
|
|
// Вытаскиваем запись |
244
|
|
|
$username_safe = db_escape($like ? strtolower($username_unsafe) : $username_unsafe); // тут на самом деле strtolower() лишняя, но пусть будет |
245
|
|
|
|
246
|
|
|
$user = classSupernova::$db->doSelectFetch( |
247
|
|
|
"SELECT * FROM {{users}} WHERE `username` " . ($like ? 'LIKE' : '=') . " '{$username_safe}'" |
248
|
|
|
. " FOR UPDATE" |
249
|
|
|
); |
250
|
|
|
classSupernova::$gc->snCache->cache_set(LOC_USER, $user); // В кэш-юзер так же заполнять индексы |
|
|
|
|
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
return $user; |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
public static function db_user_list($user_filter = '', $for_update = false, $fields = '*') { |
|
|
|
|
257
|
|
|
return classSupernova::$gc->cacheOperator->db_get_record_list(LOC_USER, $user_filter); |
|
|
|
|
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
/** |
261
|
|
|
* @param $user_id |
262
|
|
|
* @param array $set |
263
|
|
|
* |
264
|
|
|
* @return array|bool|mysqli_result|null |
265
|
|
|
*/ |
266
|
|
|
public static function db_user_set_by_id($user_id, $set) { |
267
|
|
|
return classSupernova::$gc->cacheOperator->db_upd_record_by_id(LOC_USER, $user_id, $set, array()); |
|
|
|
|
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
/** |
271
|
|
|
* @param $user_id |
272
|
|
|
* @param array $set |
|
|
|
|
273
|
|
|
* @param array $adjust |
274
|
|
|
* |
275
|
|
|
* @return array|bool|mysqli_result|null |
276
|
|
|
*/ |
277
|
|
|
public static function db_user_adjust_by_id($user_id, $adjust) { |
278
|
|
|
return classSupernova::$gc->cacheOperator->db_upd_record_by_id(LOC_USER, $user_id, array(), $adjust); |
|
|
|
|
279
|
|
|
} |
280
|
|
|
|
281
|
|
|
/** |
282
|
|
|
* Возвращает информацию о пользователе по его ID |
283
|
|
|
* |
284
|
|
|
* @param int|array $user_id_unsafe |
285
|
|
|
* <p>int - ID пользователя</p> |
286
|
|
|
* <p>array - запись пользователя с установленным полем ['id']</p> |
287
|
|
|
* @param bool $for_update @deprecated |
288
|
|
|
* @param string $fields @deprecated список полей или '*'/'' для всех полей |
289
|
|
|
* @param null $player |
290
|
|
|
* @param bool|null $player Признак выбора записи пользователь типа "игрок" |
291
|
|
|
* <p>null - Можно выбрать запись любого типа</p> |
292
|
|
|
* <p>true - Выбирается только запись типа "игрок"</p> |
293
|
|
|
* <p>false - Выбирается только запись типа "альянс"</p> |
294
|
|
|
* |
295
|
|
|
* @return array|false |
296
|
|
|
* <p>false - Нет записи с указанным ID и $player</p> |
297
|
|
|
* <p>array - запись типа $user</p> |
298
|
|
|
*/ |
299
|
|
|
public static function db_user_by_id($user_id_unsafe, $for_update = false, $fields = '*', $player = null) { |
300
|
|
|
$user = classSupernova::$gc->cacheOperator->db_get_record_by_id(LOC_USER, $user_id_unsafe, $for_update, $fields); |
|
|
|
|
301
|
|
|
|
302
|
|
|
return (is_array($user) && |
303
|
|
|
( |
304
|
|
|
$player === null |
305
|
|
|
|| |
306
|
|
|
($player === true && !$user['user_as_ally']) |
307
|
|
|
|| |
308
|
|
|
($player === false && $user['user_as_ally']) |
309
|
|
|
)) ? $user : false; |
310
|
|
|
} |
311
|
|
|
|
312
|
|
|
|
313
|
|
|
/** |
314
|
|
|
* @param $ally_id |
315
|
|
|
* @param $ally_rank_id |
316
|
|
|
* @param array $set |
317
|
|
|
* @param array $adjust |
318
|
|
|
*/ |
319
|
|
|
public static function db_user_list_set_by_ally_and_rank($ally_id, $ally_rank_id, $set, $adjust) { |
320
|
|
|
classSupernova::$gc->cacheOperator->db_upd_record_list_DANGER( |
|
|
|
|
321
|
|
|
LOC_USER, |
322
|
|
|
$set, |
323
|
|
|
$adjust, |
324
|
|
|
array( |
325
|
|
|
'ally_id' => $ally_id, |
326
|
|
|
), |
327
|
|
|
array( |
328
|
|
|
// TODO - DANGER !!! |
329
|
|
|
"`ally_rank_id` >= {$ally_rank_id}" |
330
|
|
|
) |
331
|
|
|
); |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
/** |
335
|
|
|
* @param array $playerArray |
336
|
|
|
*/ |
337
|
|
|
public static function renderNameAndCoordinates($playerArray) { |
338
|
|
|
return "{$playerArray['username']} " . uni_render_coordinates($playerArray); |
339
|
|
|
} |
340
|
|
|
|
341
|
|
|
/** |
342
|
|
|
* @param mixed $user |
343
|
|
|
*/ |
344
|
|
|
public static function validateUserRecord($user) { |
345
|
|
|
if (!is_array($user)) { |
346
|
|
|
// TODO - remove later |
347
|
|
|
print('<h1>СООБЩИТЕ ЭТО АДМИНУ: sn_db_unit_changeset_prepare() - USER is not ARRAY</h1>'); |
348
|
|
|
pdump(debug_backtrace()); |
349
|
|
|
die('USER is not ARRAY'); |
350
|
|
|
} |
351
|
|
|
if (!isset($user['id']) || !$user['id']) { |
352
|
|
|
// TODO - remove later |
353
|
|
|
print('<h1>СООБЩИТЕ ЭТО АДМИНУ: sn_db_unit_changeset_prepare() - USER[id] пустой</h1>'); |
354
|
|
|
pdump($user); |
355
|
|
|
pdump(debug_backtrace()); |
356
|
|
|
die('USER[id] пустой'); |
357
|
|
|
} |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
/** |
361
|
|
|
* @param array $playerRowFieldChanges - array of $resourceId => $amount |
362
|
|
|
* @param int $userId |
363
|
|
|
* |
364
|
|
|
* // TODO - DEDUPLICATE |
365
|
|
|
* @see DBStaticPlanet::db_planet_update_resources |
366
|
|
|
*/ |
367
|
|
View Code Duplication |
public static function db_user_update_resources($playerRowFieldChanges, $userId) { |
|
|
|
|
368
|
|
|
$fields = array(); |
369
|
|
|
foreach ($playerRowFieldChanges as $resourceId => $value) { |
370
|
|
|
$fields[pname_resource_name($resourceId)] = $value; |
371
|
|
|
} |
372
|
|
|
if (!empty($fields)) { |
373
|
|
|
classSupernova::$gc->db->doUpdateRowAdjust( |
|
|
|
|
374
|
|
|
TABLE_USERS, |
375
|
|
|
array(), |
376
|
|
|
$fields, |
377
|
|
|
array( |
378
|
|
|
'id' => $userId |
379
|
|
|
) |
380
|
|
|
); |
381
|
|
|
} |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
public static function lockAllRecords() { |
385
|
|
|
classSupernova::$db->doSelect("SELECT 1 FROM `{{users}}` FOR UPDATE"); |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
} |
389
|
|
|
|
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.