1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @package CleverStyle CMS |
4
|
|
|
* @author Nazar Mokrynskyi <[email protected]> |
5
|
|
|
* @copyright Copyright (c) 2011-2016, Nazar Mokrynskyi |
6
|
|
|
* @license MIT License, see license.txt |
7
|
|
|
*/ |
8
|
|
|
namespace cs\User; |
9
|
|
|
use |
10
|
|
|
cs\Config, |
11
|
|
|
cs\Event, |
12
|
|
|
cs\Language, |
13
|
|
|
cs\Session, |
14
|
|
|
cs\User, |
15
|
|
|
h; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Trait that contains all methods from <i>>cs\User</i> for working with user data |
19
|
|
|
* |
20
|
|
|
* @property \cs\Cache\Prefix $cache |
21
|
|
|
* @property int $id |
22
|
|
|
* |
23
|
|
|
* @method \cs\DB\_Abstract db() |
24
|
|
|
* @method \cs\DB\_Abstract db_prime() |
25
|
|
|
* @method false|int[] get_groups(false|int $user) |
26
|
|
|
*/ |
27
|
|
|
trait Data { |
28
|
|
|
/** |
29
|
|
|
* Copy of columns list of users table for internal needs without Cache usage |
30
|
|
|
* @var array |
31
|
|
|
*/ |
32
|
|
|
protected $users_columns = []; |
33
|
|
|
/** |
34
|
|
|
* Local cache of users data |
35
|
|
|
* @var array |
36
|
|
|
*/ |
37
|
|
|
protected $data = []; |
38
|
|
|
/** |
39
|
|
|
* Changed users data, at the finish, data in db must be replaced by this data |
40
|
|
|
* @var array |
41
|
|
|
*/ |
42
|
|
|
protected $data_set = []; |
43
|
|
|
/** |
44
|
|
|
* Whether to use memory cache (locally, inside object, may require a lot of memory if working with many users together) |
45
|
|
|
* @var bool |
46
|
|
|
*/ |
47
|
|
|
protected $memory_cache = true; |
48
|
|
|
protected function initialize_data () { |
49
|
|
|
$this->users_columns = $this->cache->get( |
50
|
|
|
'columns', |
51
|
|
|
function () { |
52
|
|
|
return $this->db()->columns('[prefix]users'); |
53
|
|
|
} |
54
|
|
|
); |
55
|
|
|
} |
56
|
|
|
/** |
57
|
|
|
* Get data item of specified user |
58
|
|
|
* |
59
|
|
|
* @param string|string[] $item |
60
|
|
|
* @param false|int $user If not specified - current user assumed |
61
|
|
|
* |
62
|
|
|
* @return false|int|mixed[]|string|Properties If <i>$item</i> is integer - cs\User\Properties object will be returned |
|
|
|
|
63
|
|
|
*/ |
64
|
|
|
function get ($item, $user = false) { |
65
|
|
|
if (is_scalar($item) && ctype_digit((string)$item)) { |
66
|
|
|
return new Properties($item); |
67
|
|
|
} |
68
|
|
|
return $this->get_internal($item, $user); |
69
|
|
|
} |
70
|
|
|
/** |
71
|
|
|
* Get data item of specified user |
72
|
|
|
* |
73
|
|
|
* @todo Refactor this to select all or nothing; this selection of only necessary stuff is tricky and should be simplified |
74
|
|
|
* |
75
|
|
|
* @param string|string[] $item |
76
|
|
|
* @param false|int $user If not specified - current user assumed |
77
|
|
|
* |
78
|
|
|
* @return false|int|string|mixed[] |
|
|
|
|
79
|
|
|
*/ |
80
|
|
|
protected function get_internal ($item, $user = false) { |
81
|
|
|
$user = (int)$user ?: $this->id; |
82
|
|
|
if (!$user) { |
83
|
|
|
return false; |
84
|
|
|
} |
85
|
|
|
/** @noinspection NestedTernaryOperatorInspection */ |
86
|
|
|
$data = isset($this->data[$user]) ? $this->data[$user] : ($this->cache->$user ?: ['id' => $user]); |
87
|
|
|
/** |
88
|
|
|
* If get an array of values |
89
|
|
|
*/ |
90
|
|
|
if (is_array($item)) { |
91
|
|
|
$result = $new_items = []; |
92
|
|
|
/** |
93
|
|
|
* Trying to get value from the local cache, or make up an array of missing values |
94
|
|
|
*/ |
95
|
|
|
foreach ($item as $i) { |
96
|
|
|
if (in_array($i, $this->users_columns)) { |
97
|
|
|
if (isset($data[$i])) { |
98
|
|
|
$result[$i] = $data[$i]; |
99
|
|
|
} else { |
100
|
|
|
$new_items[] = $i; |
101
|
|
|
} |
102
|
|
|
} |
103
|
|
|
} |
104
|
|
|
if (!$new_items) { |
105
|
|
|
return $result; |
106
|
|
|
} |
107
|
|
|
/** |
108
|
|
|
* If there are missing values - get them from the database |
109
|
|
|
*/ |
110
|
|
|
$new_items = '`'.implode('`, `', $new_items).'`'; |
111
|
|
|
$res = $this->db()->qf( |
112
|
|
|
"SELECT $new_items |
113
|
|
|
FROM `[prefix]users` |
114
|
|
|
WHERE `id` = '$user' |
115
|
|
|
LIMIT 1" |
116
|
|
|
); |
117
|
|
|
unset($new_items); |
118
|
|
|
if (is_array($res)) { |
119
|
|
|
$data = array_merge($res, $data ?: []); |
120
|
|
|
$this->cache->$user = $data; |
121
|
|
|
if ($this->memory_cache) { |
122
|
|
|
$this->data[$user] = $data; |
123
|
|
|
} |
124
|
|
|
$result = array_merge($result, $res); |
125
|
|
|
/** |
126
|
|
|
* Sorting the resulting array in the same manner as the input array |
127
|
|
|
*/ |
128
|
|
|
$res = []; |
129
|
|
|
foreach ($item as $i) { |
130
|
|
|
$res[$i] = &$result[$i]; |
131
|
|
|
} |
132
|
|
|
return $res; |
133
|
|
|
} else { |
134
|
|
|
return false; |
135
|
|
|
} |
136
|
|
|
} |
137
|
|
|
/** |
138
|
|
|
* If get one value |
139
|
|
|
*/ |
140
|
|
|
return $this->get_internal_one_item($item, $user, $data); |
141
|
|
|
} |
142
|
|
|
/** |
143
|
|
|
* @param string $item |
144
|
|
|
* @param int $user |
145
|
|
|
* @param mixed[] $data |
146
|
|
|
* |
147
|
|
|
* @return false|int|string |
148
|
|
|
*/ |
149
|
|
|
protected function get_internal_one_item ($item, $user, &$data) { |
150
|
|
|
if (!in_array($item, $this->users_columns)) { |
151
|
|
|
return false; |
152
|
|
|
} |
153
|
|
|
/** |
154
|
|
|
* If data in local cache - return them |
155
|
|
|
*/ |
156
|
|
|
if (isset($data[$item])) { |
157
|
|
|
return $data[$item]; |
158
|
|
|
} |
159
|
|
|
$data_from_db = $this->db()->qfs( |
160
|
|
|
"SELECT `$item` |
161
|
|
|
FROM `[prefix]users` |
162
|
|
|
WHERE `id` = '$user' |
163
|
|
|
LIMIT 1" |
164
|
|
|
); |
165
|
|
|
if ($data_from_db !== false) { |
166
|
|
|
$data[$item] = $data_from_db; |
167
|
|
|
$this->cache->$user = $data; |
168
|
|
|
if ($this->memory_cache) { |
169
|
|
|
$this->data[$user] = $data; |
170
|
|
|
} |
171
|
|
|
return $data_from_db; |
172
|
|
|
} |
173
|
|
|
return false; |
174
|
|
|
} |
175
|
|
|
/** |
176
|
|
|
* Set data item of specified user |
177
|
|
|
* |
178
|
|
|
* @param array|string $item Item-value array may be specified for setting several items at once |
179
|
|
|
* @param int|null|string $value |
180
|
|
|
* @param false|int $user If not specified - current user assumed |
181
|
|
|
* |
182
|
|
|
* @return bool |
183
|
|
|
*/ |
184
|
|
|
function set ($item, $value = null, $user = false) { |
185
|
|
|
$result = $this->set_internal($item, $value, $user); |
186
|
|
|
$this->persist_data(); |
187
|
|
|
return $result; |
188
|
|
|
} |
189
|
|
|
/** |
190
|
|
|
* Set data item of specified user |
191
|
|
|
* |
192
|
|
|
* @param array|string $item Item-value array may be specified for setting several items at once |
193
|
|
|
* @param int|null|string $value |
194
|
|
|
* @param false|int $user If not specified - current user assumed |
195
|
|
|
* |
196
|
|
|
* @return bool |
197
|
|
|
*/ |
198
|
|
|
protected function set_internal ($item, $value = null, $user = false) { |
199
|
|
|
$user = (int)$user ?: $this->id; |
200
|
|
|
if (!$user) { |
201
|
|
|
return false; |
202
|
|
|
} |
203
|
|
|
if (is_array($item)) { |
204
|
|
|
$result = true; |
205
|
|
|
foreach ($item as $i => $v) { |
206
|
|
|
$result = $result && $this->set($i, $v, $user); |
207
|
|
|
} |
208
|
|
|
return $result; |
209
|
|
|
} |
210
|
|
|
if (!$this->set_internal_allowed($user, $item, $value)) { |
211
|
|
|
return false; |
212
|
|
|
} |
213
|
|
|
if ($item === 'language') { |
214
|
|
|
$value = $value ? Language::instance()->get('clanguage', $value) : ''; |
215
|
|
|
} elseif ($item === 'timezone') { |
216
|
|
|
$value = in_array($value, get_timezones_list(), true) ? $value : ''; |
217
|
|
|
} elseif ($item == 'avatar') { |
218
|
|
|
if ( |
219
|
|
|
strpos($value, 'http://') !== 0 && |
220
|
|
|
strpos($value, 'https://') !== 0 |
221
|
|
|
) { |
222
|
|
|
$value = ''; |
223
|
|
|
} else { |
224
|
|
|
$old_value = $this->get($item, $user); |
225
|
|
|
if ($value !== $old_value) { |
226
|
|
|
$Event = Event::instance(); |
227
|
|
|
$Event->fire( |
228
|
|
|
'System/upload_files/del_tag', |
229
|
|
|
[ |
230
|
|
|
'url' => $old_value, |
231
|
|
|
'tag' => "users/$user/avatar" |
232
|
|
|
] |
233
|
|
|
); |
234
|
|
|
$Event->fire( |
235
|
|
|
'System/upload_files/add_tag', |
236
|
|
|
[ |
237
|
|
|
'url' => $value, |
238
|
|
|
'tag' => "users/$user/avatar" |
239
|
|
|
] |
240
|
|
|
); |
241
|
|
|
} |
242
|
|
|
} |
243
|
|
|
} |
244
|
|
|
$this->data_set[$user][$item] = $value; |
245
|
|
|
if (in_array($item, ['login', 'email'], true)) { |
246
|
|
|
$old_value = $this->get($item.'_hash', $user); |
247
|
|
|
$this->data_set[$user][$item.'_hash'] = hash('sha224', $value); |
248
|
|
|
unset($this->cache->$old_value); |
249
|
|
|
} elseif ($item === 'password_hash' || ($item === 'status' && $value == 0)) { |
250
|
|
|
Session::instance()->del_all($user); |
251
|
|
|
} |
252
|
|
|
return true; |
253
|
|
|
} |
254
|
|
|
/** |
255
|
|
|
* Check whether setting specified item to specified value for specified user is allowed |
256
|
|
|
* |
257
|
|
|
* @param int $user |
258
|
|
|
* @param string $item |
259
|
|
|
* @param string $value |
260
|
|
|
* |
261
|
|
|
* @return bool |
262
|
|
|
*/ |
263
|
|
|
protected function set_internal_allowed ($user, $item, $value) { |
264
|
|
|
if ( |
265
|
|
|
$user === User::GUEST_ID || |
266
|
|
|
$item === 'id' || |
267
|
|
|
!in_array($item, $this->users_columns, true) |
268
|
|
|
) { |
269
|
|
|
return false; |
270
|
|
|
} |
271
|
|
|
if (in_array($item, ['login', 'email'], true)) { |
272
|
|
|
$value = mb_strtolower($value); |
273
|
|
|
if ( |
274
|
|
|
$item === 'email' && |
275
|
|
|
!filter_var($value, FILTER_VALIDATE_EMAIL) && |
276
|
|
|
!in_array(User::BOT_GROUP_ID, $this->get_groups($user)) |
277
|
|
|
) { |
278
|
|
|
return false; |
279
|
|
|
} |
280
|
|
|
if ($value === $this->get($item, $user)) { |
281
|
|
|
return true; |
282
|
|
|
} |
283
|
|
|
return !$this->get_id(hash('sha224', $value)); |
284
|
|
|
} |
285
|
|
|
return true; |
286
|
|
|
} |
287
|
|
|
/** |
288
|
|
|
* Getting additional data item(s) of specified user |
289
|
|
|
* |
290
|
|
|
* @param string|string[] $item |
291
|
|
|
* @param false|int $user If not specified - current user assumed |
292
|
|
|
* |
293
|
|
|
* @return false|string|mixed[] |
294
|
|
|
*/ |
295
|
|
|
function get_data ($item, $user = false) { |
296
|
|
|
$user = (int)$user ?: $this->id; |
297
|
|
|
if (!$user || !$item || $user == User::GUEST_ID) { |
298
|
|
|
return false; |
299
|
|
|
} |
300
|
|
|
$Cache = $this->cache; |
301
|
|
|
$data = $Cache->{"data/$user"} ?: []; |
302
|
|
|
if (is_array($item)) { |
303
|
|
|
$result = []; |
304
|
|
|
$absent = []; |
305
|
|
|
foreach ($item as $i) { |
306
|
|
|
if (isset($data[$i])) { |
307
|
|
|
$result[$i] = $data[$i]; |
308
|
|
|
} else { |
309
|
|
|
$absent[] = $i; |
310
|
|
|
} |
311
|
|
|
} |
312
|
|
|
if ($absent) { |
313
|
|
|
$absent = implode( |
314
|
|
|
',', |
315
|
|
|
$this->db()->s($absent) |
316
|
|
|
); |
317
|
|
|
$absent = array_column( |
318
|
|
|
$this->db()->qfa( |
319
|
|
|
[ |
320
|
|
|
"SELECT `item`, `value` |
321
|
|
|
FROM `[prefix]users_data` |
322
|
|
|
WHERE |
323
|
|
|
`id` = '$user' AND |
324
|
|
|
`item` IN($absent)" |
325
|
|
|
] |
326
|
|
|
), |
327
|
|
|
'value', |
328
|
|
|
'item' |
329
|
|
|
); |
330
|
|
|
foreach ($absent as &$a) { |
331
|
|
|
$a = _json_decode($a); |
332
|
|
|
if ($a === null) { |
333
|
|
|
$a = false; |
334
|
|
|
} |
335
|
|
|
} |
336
|
|
|
unset($a); |
337
|
|
|
$result += $absent; |
338
|
|
|
$data += $absent; |
339
|
|
|
$Cache->{"data/$user"} = $data; |
340
|
|
|
} |
341
|
|
|
return $result; |
342
|
|
|
} |
343
|
|
|
if ($data === false || !isset($data[$item])) { |
344
|
|
|
if (!is_array($data)) { |
345
|
|
|
$data = []; |
346
|
|
|
} |
347
|
|
|
$data[$item] = _json_decode( |
348
|
|
|
$this->db()->qfs( |
349
|
|
|
[ |
350
|
|
|
"SELECT `value` |
351
|
|
|
FROM `[prefix]users_data` |
352
|
|
|
WHERE |
353
|
|
|
`id` = '$user' AND |
354
|
|
|
`item` = '%s'", |
355
|
|
|
$item |
356
|
|
|
] |
357
|
|
|
) |
358
|
|
|
); |
359
|
|
|
if ($data[$item] === null) { |
360
|
|
|
$data[$item] = false; |
361
|
|
|
} |
362
|
|
|
$Cache->{"data/$user"} = $data; |
363
|
|
|
} |
364
|
|
|
return $data[$item]; |
365
|
|
|
} |
366
|
|
|
/** |
367
|
|
|
* Setting additional data item(s) of specified user |
368
|
|
|
* |
369
|
|
|
* @param array|string $item Item-value array may be specified for setting several items at once |
370
|
|
|
* @param mixed|null $value |
371
|
|
|
* @param false|int $user If not specified - current user assumed |
372
|
|
|
* |
373
|
|
|
* @return bool |
374
|
|
|
*/ |
375
|
|
|
function set_data ($item, $value = null, $user = false) { |
376
|
|
|
$user = (int)$user ?: $this->id; |
377
|
|
|
if (!$user || !$item || $user == User::GUEST_ID) { |
378
|
|
|
return false; |
379
|
|
|
} |
380
|
|
|
if (is_array($item)) { |
381
|
|
|
$params = []; |
382
|
|
|
foreach ($item as $i => $v) { |
383
|
|
|
$params[] = [ |
384
|
|
|
$i, |
385
|
|
|
_json_encode($v) |
386
|
|
|
]; |
387
|
|
|
} |
388
|
|
|
unset($i, $v); |
389
|
|
|
$result = $this->db_prime()->insert( |
390
|
|
|
"REPLACE INTO `[prefix]users_data` |
391
|
|
|
( |
392
|
|
|
`id`, |
393
|
|
|
`item`, |
394
|
|
|
`value` |
395
|
|
|
) VALUES ( |
396
|
|
|
$user, |
397
|
|
|
'%s', |
398
|
|
|
'%s' |
399
|
|
|
)", |
400
|
|
|
$params |
401
|
|
|
); |
402
|
|
|
} else { |
403
|
|
|
$result = $this->db_prime()->q( |
404
|
|
|
"REPLACE INTO `[prefix]users_data` |
405
|
|
|
( |
406
|
|
|
`id`, |
407
|
|
|
`item`, |
408
|
|
|
`value` |
409
|
|
|
) VALUES ( |
410
|
|
|
'$user', |
411
|
|
|
'%s', |
412
|
|
|
'%s' |
413
|
|
|
)", |
414
|
|
|
$item, |
415
|
|
|
_json_encode($value) |
416
|
|
|
); |
417
|
|
|
} |
418
|
|
|
unset($this->cache->{"data/$user"}); |
419
|
|
|
return (bool)$result; |
420
|
|
|
} |
421
|
|
|
/** |
422
|
|
|
* Deletion of additional data item(s) of specified user |
423
|
|
|
* |
424
|
|
|
* @param string|string[] $item |
425
|
|
|
* @param false|int $user If not specified - current user assumed |
426
|
|
|
* |
427
|
|
|
* @return bool |
428
|
|
|
*/ |
429
|
|
|
function del_data ($item, $user = false) { |
430
|
|
|
$user = (int)$user ?: $this->id; |
431
|
|
|
if (!$user || !$item || $user == User::GUEST_ID) { |
432
|
|
|
return false; |
433
|
|
|
} |
434
|
|
|
$item = implode( |
435
|
|
|
',', |
436
|
|
|
$this->db_prime()->s((array)$item) |
437
|
|
|
); |
438
|
|
|
$result = $this->db_prime()->q( |
439
|
|
|
"DELETE FROM `[prefix]users_data` |
440
|
|
|
WHERE |
441
|
|
|
`id` = '$user' AND |
442
|
|
|
`item` IN($item)" |
443
|
|
|
); |
444
|
|
|
unset($this->cache->{"data/$user"}); |
445
|
|
|
return (bool)$result; |
446
|
|
|
} |
447
|
|
|
/** |
448
|
|
|
* Get user id by login or email hash (sha224) (hash from lowercase string) |
449
|
|
|
* |
450
|
|
|
* @param string $login_hash Login or email hash |
451
|
|
|
* |
452
|
|
|
* @return false|int User id if found and not guest, otherwise - boolean <i>false</i> |
453
|
|
|
*/ |
454
|
|
|
function get_id ($login_hash) { |
455
|
|
|
if (!preg_match('/^[0-9a-z]{56}$/', $login_hash)) { |
456
|
|
|
return false; |
457
|
|
|
} |
458
|
|
|
$id = $this->cache->get( |
459
|
|
|
$login_hash, |
460
|
|
|
function () use ($login_hash) { |
461
|
|
|
return $this->db()->qfs( |
462
|
|
|
[ |
463
|
|
|
"SELECT `id` |
464
|
|
|
FROM `[prefix]users` |
465
|
|
|
WHERE |
466
|
|
|
`login_hash` = '%s' OR |
467
|
|
|
`email_hash` = '%s' |
468
|
|
|
LIMIT 1", |
469
|
|
|
$login_hash, |
470
|
|
|
$login_hash |
471
|
|
|
] |
472
|
|
|
) ?: false; |
473
|
|
|
} |
474
|
|
|
); |
475
|
|
|
return $id && $id != User::GUEST_ID ? $id : false; |
476
|
|
|
} |
477
|
|
|
/** |
478
|
|
|
* Get user avatar, if no one present - uses Gravatar |
479
|
|
|
* |
480
|
|
|
* @param int|null $size Avatar size, if not specified or resizing is not possible - original image is used |
481
|
|
|
* @param false|int $user If not specified - current user assumed |
482
|
|
|
* |
483
|
|
|
* @return string |
484
|
|
|
*/ |
485
|
|
|
function avatar ($size = null, $user = false) { |
486
|
|
|
$user = (int)$user ?: $this->id; |
487
|
|
|
$avatar = $this->get('avatar', $user); |
488
|
|
|
$Config = Config::instance(); |
489
|
|
|
if (!$avatar && $this->id != User::GUEST_ID && $Config->core['gravatar_support']) { |
490
|
|
|
$email_hash = md5($this->get('email', $user)); |
491
|
|
|
$default_avatar = urlencode($Config->core_url().'/includes/img/guest.svg'); |
492
|
|
|
$avatar = "https://www.gravatar.com/avatar/$email_hash?d=mm&s=$size&d=$default_avatar"; |
493
|
|
|
} |
494
|
|
|
if (!$avatar) { |
495
|
|
|
$avatar = '/includes/img/guest.svg'; |
496
|
|
|
} |
497
|
|
|
return h::prepare_url($avatar, true); |
498
|
|
|
} |
499
|
|
|
/** |
500
|
|
|
* Get user name or login or email, depending on existing information |
501
|
|
|
* |
502
|
|
|
* @param false|int $user If not specified - current user assumed |
503
|
|
|
* |
504
|
|
|
* @return string |
505
|
|
|
*/ |
506
|
|
|
function username ($user = false) { |
507
|
|
|
$user = (int)$user ?: $this->id; |
508
|
|
|
if ($user === User::GUEST_ID) { |
509
|
|
|
return Language::instance()->system_profile_guest; |
510
|
|
|
} |
511
|
|
|
$username = $this->get('username', $user); |
512
|
|
|
if (!$username) { |
513
|
|
|
$username = $this->get('login', $user); |
514
|
|
|
} |
515
|
|
|
if (!$username) { |
516
|
|
|
$username = $this->get('email', $user); |
517
|
|
|
} |
518
|
|
|
return $username; |
519
|
|
|
} |
520
|
|
|
/** |
521
|
|
|
* Disable memory cache |
522
|
|
|
* |
523
|
|
|
* Memory cache stores users data inside User class in order to get data faster next time. |
524
|
|
|
* But in case of working with large amount of users this cache can be too large. Disabling will cause some performance drop, but save a lot of RAM. |
525
|
|
|
*/ |
526
|
|
|
function disable_memory_cache () { |
527
|
|
|
$this->memory_cache = false; |
528
|
|
|
} |
529
|
|
|
/** |
530
|
|
|
* Returns array of users columns, available for getting of data |
531
|
|
|
* |
532
|
|
|
* @return array |
533
|
|
|
*/ |
534
|
|
|
function get_users_columns () { |
535
|
|
|
return $this->users_columns; |
536
|
|
|
} |
537
|
|
|
/** |
538
|
|
|
* Saving changes of cache and users data |
539
|
|
|
*/ |
540
|
|
|
protected function persist_data () { |
541
|
|
|
foreach ($this->data_set as $user => $data_set) { |
542
|
|
|
$update = []; |
543
|
|
|
foreach ($data_set as $item => $value) { |
544
|
|
|
if ($item != 'id' && in_array($item, $this->users_columns)) { |
545
|
|
|
$value = xap($value, false); |
546
|
|
|
if (isset($this->data[$user])) { |
547
|
|
|
$this->data[$user][$item] = $value; |
548
|
|
|
} |
549
|
|
|
$update[] = "`$item` = ".$this->db_prime()->s($value); |
550
|
|
|
} |
551
|
|
|
} |
552
|
|
|
if (isset($this->data[$user])) { |
553
|
|
|
$this->cache->$user = $this->data[$user]; |
554
|
|
|
} |
555
|
|
|
if (!$update) { |
556
|
|
|
$update = implode(', ', $update); |
557
|
|
|
$this->db_prime()->q( |
558
|
|
|
"UPDATE `[prefix]users` |
559
|
|
|
SET $update |
560
|
|
|
WHERE `id` = '$user'" |
561
|
|
|
); |
562
|
|
|
} |
563
|
|
|
} |
564
|
|
|
$this->data_set = []; |
565
|
|
|
} |
566
|
|
|
} |
567
|
|
|
|
This check compares the return type specified in the
@return
annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.If the return type contains the type array, this check recommends the use of a more specific type like
String[]
orarray<String>
.