1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* A user entity |
4
|
|
|
* |
5
|
|
|
* @property string $name The display name that the user will be known by in the network |
6
|
|
|
* @property string $username The short, reference name for the user in the network |
7
|
|
|
* @property string $email The email address to which Elgg will send email notifications |
8
|
|
|
* @property string $language The language preference of the user (ISO 639-1 formatted) |
9
|
|
|
* @property string $banned 'yes' if the user is banned from the network, 'no' otherwise |
10
|
|
|
* @property string $admin 'yes' if the user is an administrator of the network, 'no' otherwise |
11
|
|
|
* @property-read string $password_hash The hashed password of the user |
12
|
|
|
* @property-read int $prev_last_action A UNIX timestamp of the previous last action |
13
|
|
|
* @property-read int $last_login A UNIX timestamp of the last login |
14
|
|
|
* @property-read int $prev_last_login A UNIX timestamp of the previous login |
15
|
|
|
*/ |
16
|
|
|
class ElggUser extends \ElggEntity |
17
|
|
|
implements Friendable { |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* {@inheritdoc} |
21
|
|
|
*/ |
22
|
504 |
|
public function getType() { |
23
|
504 |
|
return 'user'; |
24
|
|
|
} |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* Get user language or default to site language |
28
|
|
|
* |
29
|
|
|
* @param string $fallback If this is provided, it will be returned if the user doesn't have a language set. |
30
|
|
|
* If null, the site language will be returned. |
31
|
|
|
* |
32
|
|
|
* @return string |
33
|
|
|
*/ |
34
|
|
|
public function getLanguage($fallback = null) { |
35
|
|
|
if (!empty($this->language)) { |
36
|
|
|
return $this->language; |
37
|
|
|
} |
38
|
|
|
if ($fallback !== null) { |
39
|
|
|
return $fallback; |
40
|
|
|
} |
41
|
|
|
return elgg_get_config('language'); |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* {@inheritdoc} |
46
|
|
|
*/ |
47
|
286 |
|
public function __set($name, $value) { |
48
|
|
|
switch ($name) { |
49
|
286 |
|
case 'salt': |
50
|
286 |
|
case 'password': |
51
|
|
|
_elgg_services()->logger->error("User entities no longer contain {$name}"); |
52
|
|
|
return; |
53
|
286 |
|
case 'password_hash': |
54
|
|
|
_elgg_services()->logger->error("password_hash is a readonly attribute."); |
55
|
|
|
return; |
56
|
286 |
|
case 'email': |
57
|
275 |
|
if (!validate_email_address($value)) { |
58
|
|
|
throw new \InvalidParameterException("Email is not a valid email address"); |
59
|
|
|
} |
60
|
275 |
|
break; |
61
|
286 |
|
case 'username': |
62
|
286 |
|
if (!validate_username($value)) { |
63
|
|
|
throw new \InvalidParameterException("Username is not a valid username"); |
64
|
|
|
} |
65
|
286 |
|
$existing_user = get_user_by_username($value); |
66
|
286 |
|
if ($existing_user && ($existing_user->guid !== $this->guid)) { |
67
|
|
|
throw new \InvalidParameterException("{$name} is supposed to be unique for ElggUser"); |
68
|
|
|
} |
69
|
286 |
|
break; |
70
|
|
|
} |
71
|
|
|
|
72
|
286 |
|
parent::__set($name, $value); |
73
|
286 |
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* {@inheritdoc} |
77
|
|
|
*/ |
78
|
3 |
|
public function getURL() { |
79
|
|
|
|
80
|
3 |
|
$result = parent::getURL(); |
81
|
3 |
|
if ($result !== '') { |
82
|
|
|
return $result; |
83
|
|
|
} |
84
|
|
|
|
85
|
3 |
|
return elgg_normalize_url("user/view/{$this->guid}"); |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* Ban this user. |
90
|
|
|
* |
91
|
|
|
* @param string $reason Optional reason |
92
|
|
|
* |
93
|
|
|
* @return bool |
94
|
|
|
*/ |
95
|
62 |
View Code Duplication |
public function ban($reason = '') { |
|
|
|
|
96
|
|
|
|
97
|
62 |
|
if (!$this->canEdit()) { |
98
|
|
|
return false; |
99
|
|
|
} |
100
|
|
|
|
101
|
62 |
|
if (!elgg_trigger_event('ban', 'user', $this)) { |
|
|
|
|
102
|
|
|
return false; |
103
|
|
|
} |
104
|
|
|
|
105
|
62 |
|
$this->ban_reason = $reason; |
|
|
|
|
106
|
62 |
|
$this->banned = 'yes'; |
107
|
|
|
|
108
|
62 |
|
_elgg_invalidate_cache_for_entity($this->guid); |
109
|
62 |
|
_elgg_invalidate_memcache_for_entity($this->guid); |
110
|
|
|
|
111
|
62 |
|
return true; |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* Unban this user. |
116
|
|
|
* |
117
|
|
|
* @return bool |
118
|
|
|
*/ |
119
|
1 |
View Code Duplication |
public function unban() { |
|
|
|
|
120
|
|
|
|
121
|
1 |
|
if (!$this->canEdit()) { |
122
|
|
|
return false; |
123
|
|
|
} |
124
|
|
|
|
125
|
1 |
|
if (!elgg_trigger_event('unban', 'user', $this)) { |
|
|
|
|
126
|
|
|
return false; |
127
|
|
|
} |
128
|
|
|
|
129
|
1 |
|
unset($this->ban_reason); |
130
|
1 |
|
$this->banned = 'yes'; |
131
|
|
|
|
132
|
1 |
|
_elgg_invalidate_cache_for_entity($this->guid); |
133
|
1 |
|
_elgg_invalidate_memcache_for_entity($this->guid); |
134
|
|
|
|
135
|
1 |
|
return true; |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* Is this user banned or not? |
140
|
|
|
* |
141
|
|
|
* @return bool |
142
|
|
|
*/ |
143
|
20 |
|
public function isBanned() { |
144
|
20 |
|
return $this->banned == 'yes'; |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* Is this user admin? |
149
|
|
|
* |
150
|
|
|
* @return bool |
151
|
|
|
*/ |
152
|
450 |
|
public function isAdmin() { |
153
|
450 |
|
$ia = elgg_set_ignore_access(true); |
154
|
450 |
|
$is_admin = ($this->admin == 'yes'); |
155
|
450 |
|
elgg_set_ignore_access($ia); |
156
|
|
|
|
157
|
450 |
|
return $is_admin; |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
/** |
161
|
|
|
* Make the user an admin |
162
|
|
|
* |
163
|
|
|
* @return bool |
164
|
|
|
*/ |
165
|
4 |
View Code Duplication |
public function makeAdmin() { |
|
|
|
|
166
|
|
|
|
167
|
4 |
|
if ($this->isAdmin()) { |
168
|
|
|
return true; |
169
|
|
|
} |
170
|
|
|
|
171
|
4 |
|
if (!elgg_trigger_event('make_admin', 'user', $this)) { |
|
|
|
|
172
|
|
|
return false; |
173
|
|
|
} |
174
|
|
|
|
175
|
4 |
|
$this->admin = 'yes'; |
176
|
|
|
|
177
|
4 |
|
_elgg_invalidate_cache_for_entity($this->guid); |
178
|
4 |
|
_elgg_invalidate_memcache_for_entity($this->guid); |
179
|
|
|
|
180
|
4 |
|
return true; |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* Remove the admin flag for user |
185
|
|
|
* |
186
|
|
|
* @return bool |
187
|
|
|
*/ |
188
|
2 |
View Code Duplication |
public function removeAdmin() { |
|
|
|
|
189
|
|
|
|
190
|
2 |
|
if (!$this->isAdmin()) { |
191
|
1 |
|
return true; |
192
|
|
|
} |
193
|
|
|
|
194
|
1 |
|
if (!elgg_trigger_event('remove_admin', 'user', $this)) { |
|
|
|
|
195
|
|
|
return false; |
196
|
|
|
} |
197
|
|
|
|
198
|
1 |
|
$this->admin = 'no'; |
199
|
|
|
|
200
|
1 |
|
_elgg_invalidate_cache_for_entity($this->guid); |
201
|
1 |
|
_elgg_invalidate_memcache_for_entity($this->guid); |
202
|
|
|
|
203
|
1 |
|
return true; |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
/** |
207
|
|
|
* Sets the last logon time of the user to right now. |
208
|
|
|
* |
209
|
|
|
* @return void |
210
|
|
|
*/ |
211
|
|
|
public function setLastLogin() { |
212
|
|
|
|
213
|
|
|
$time = $this->getCurrentTime()->getTimestamp(); |
214
|
|
|
|
215
|
|
|
if ($this->last_login == $time) { |
216
|
|
|
// no change required |
217
|
|
|
return; |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
// these writes actually work, we just type hint read-only. |
221
|
|
|
$this->prev_last_login = $user->last_login; |
|
|
|
|
222
|
|
|
$this->last_login = $time; |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
/** |
226
|
|
|
* Sets the last action time of the given user to right now. |
227
|
|
|
* |
228
|
|
|
* @see _elgg_session_boot The session boot calls this at the beginning of every request |
229
|
|
|
* |
230
|
|
|
* @return void |
231
|
|
|
*/ |
232
|
|
|
public function setLastAction() { |
233
|
|
|
|
234
|
|
|
$time = $this->getCurrentTime()->getTimestamp(); |
235
|
|
|
|
236
|
|
|
if ($this->last_action == $time) { |
237
|
|
|
// no change required |
238
|
|
|
return; |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
// these writes actually work, we just type hint read-only. |
242
|
|
|
$this->prev_last_action = $this->last_action; |
243
|
|
|
$this->last_action = $time; |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
/** |
247
|
|
|
* Gets the validation status of a user. |
248
|
|
|
* |
249
|
|
|
* @return bool|null Null means status was not set for this user. |
250
|
|
|
*/ |
251
|
|
|
public function isValidated() { |
252
|
|
|
if (!isset($this->validated)) { |
253
|
|
|
return null; |
254
|
|
|
} |
255
|
|
|
return (bool) $this->validated; |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
/** |
259
|
|
|
* Set the validation status for a user. |
260
|
|
|
* |
261
|
|
|
* @param bool $status Validated (true) or unvalidated (false) |
262
|
|
|
* @param string $method Optional method to say how a user was validated |
263
|
|
|
* @return void |
264
|
|
|
*/ |
265
|
63 |
|
public function setValidationStatus($status, $method = '') { |
266
|
|
|
|
267
|
63 |
|
$this->validated = $status; |
|
|
|
|
268
|
63 |
|
$this->validated_method = $method; |
|
|
|
|
269
|
|
|
|
270
|
63 |
|
if ((bool) $status) { |
271
|
44 |
|
elgg_trigger_after_event('validate', 'user', $this); |
|
|
|
|
272
|
|
|
} else { |
273
|
26 |
|
elgg_trigger_after_event('invalidate', 'user', $this); |
|
|
|
|
274
|
|
|
} |
275
|
63 |
|
} |
276
|
|
|
|
277
|
|
|
/** |
278
|
|
|
* Adds a user as a friend |
279
|
|
|
* |
280
|
|
|
* @param int $friend_guid The GUID of the user to add |
281
|
|
|
* @param bool $create_river_item Create the river item announcing this friendship |
282
|
|
|
* |
283
|
|
|
* @return bool |
284
|
|
|
*/ |
285
|
1 |
|
public function addFriend($friend_guid, $create_river_item = false) { |
286
|
1 |
|
if (!get_user($friend_guid)) { |
287
|
|
|
return false; |
288
|
|
|
} |
289
|
|
|
|
290
|
1 |
|
if (!add_entity_relationship($this->guid, "friend", $friend_guid)) { |
291
|
|
|
return false; |
292
|
|
|
} |
293
|
|
|
|
294
|
1 |
|
if ($create_river_item) { |
295
|
|
|
elgg_create_river_item([ |
296
|
|
|
'view' => 'river/relationship/friend/create', |
297
|
|
|
'action_type' => 'friend', |
298
|
|
|
'subject_guid' => $this->guid, |
299
|
|
|
'object_guid' => $friend_guid, |
300
|
|
|
]); |
301
|
|
|
} |
302
|
|
|
|
303
|
1 |
|
return true; |
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
/** |
307
|
|
|
* Removes a user as a friend |
308
|
|
|
* |
309
|
|
|
* @param int $friend_guid The GUID of the user to remove |
310
|
|
|
* @return bool |
311
|
|
|
*/ |
312
|
|
|
public function removeFriend($friend_guid) { |
313
|
|
|
return $this->removeRelationship($friend_guid, 'friend'); |
314
|
|
|
} |
315
|
|
|
|
316
|
|
|
/** |
317
|
|
|
* Determines whether or not this user is a friend of the currently logged in user |
318
|
|
|
* |
319
|
|
|
* @return bool |
320
|
|
|
*/ |
321
|
|
|
public function isFriend() { |
322
|
|
|
return $this->isFriendOf(_elgg_services()->session->getLoggedInUserGuid()); |
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
/** |
326
|
|
|
* Determines whether this user is friends with another user |
327
|
|
|
* |
328
|
|
|
* @param int $user_guid The GUID of the user to check against |
329
|
|
|
* |
330
|
|
|
* @return bool |
331
|
|
|
*/ |
332
|
|
|
public function isFriendsWith($user_guid) { |
333
|
|
|
return (bool) check_entity_relationship($this->guid, "friend", $user_guid); |
334
|
|
|
} |
335
|
|
|
|
336
|
|
|
/** |
337
|
|
|
* Determines whether or not this user is another user's friend |
338
|
|
|
* |
339
|
|
|
* @param int $user_guid The GUID of the user to check against |
340
|
|
|
* |
341
|
|
|
* @return bool |
342
|
|
|
*/ |
343
|
|
|
public function isFriendOf($user_guid) { |
344
|
|
|
return (bool) check_entity_relationship($user_guid, "friend", $this->guid); |
345
|
|
|
} |
346
|
|
|
|
347
|
|
|
/** |
348
|
|
|
* {@inheritdoc} |
349
|
|
|
*/ |
350
|
|
View Code Duplication |
public function getFriends(array $options = []) { |
|
|
|
|
351
|
|
|
$options['relationship'] = 'friend'; |
352
|
|
|
$options['relationship_guid'] = $this->getGUID(); |
353
|
|
|
$options['type'] = 'user'; |
354
|
|
|
|
355
|
|
|
return elgg_get_entities_from_relationship($options); |
|
|
|
|
356
|
|
|
} |
357
|
|
|
|
358
|
|
|
/** |
359
|
|
|
* {@inheritdoc} |
360
|
|
|
*/ |
361
|
|
View Code Duplication |
public function getFriendsOf(array $options = []) { |
|
|
|
|
362
|
|
|
$options['relationship'] = 'friend'; |
363
|
|
|
$options['relationship_guid'] = $this->getGUID(); |
364
|
|
|
$options['inverse_relationship'] = true; |
365
|
|
|
$options['type'] = 'user'; |
366
|
|
|
|
367
|
|
|
return elgg_get_entities_from_relationship($options); |
|
|
|
|
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
/** |
371
|
|
|
* Gets the user's groups |
372
|
|
|
* |
373
|
|
|
* @param array $options Options array. |
374
|
|
|
* |
375
|
|
|
* @return array|false Array of \ElggGroup, or false, depending on success |
376
|
|
|
*/ |
377
|
|
|
public function getGroups(array $options = []) { |
378
|
|
|
$options['type'] = 'group'; |
379
|
|
|
$options['relationship'] = 'member'; |
380
|
|
|
$options['relationship_guid'] = $this->guid; |
381
|
|
|
|
382
|
|
|
return elgg_get_entities_from_relationship($options); |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
/** |
386
|
|
|
* {@inheritdoc} |
387
|
|
|
*/ |
388
|
|
|
public function getObjects(array $options = []) { |
389
|
|
|
$options['type'] = 'object'; |
390
|
|
|
$options['owner_guid'] = $this->getGUID(); |
391
|
|
|
|
392
|
|
|
return elgg_get_entities($options); |
|
|
|
|
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
/** |
396
|
|
|
* {@inheritdoc} |
397
|
|
|
*/ |
398
|
|
View Code Duplication |
public function getFriendsObjects(array $options = []) { |
|
|
|
|
399
|
|
|
$options['type'] = 'object'; |
400
|
|
|
$options['relationship'] = 'friend'; |
401
|
|
|
$options['relationship_guid'] = $this->getGUID(); |
402
|
|
|
$options['relationship_join_on'] = 'container_guid'; |
403
|
|
|
|
404
|
|
|
return elgg_get_entities_from_relationship($options); |
|
|
|
|
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
/** |
408
|
|
|
* Get a user's owner GUID |
409
|
|
|
* |
410
|
|
|
* Returns it's own GUID if the user is not owned. |
411
|
|
|
* |
412
|
|
|
* @return int |
413
|
|
|
*/ |
414
|
|
|
public function getOwnerGUID() { |
415
|
|
|
if ($this->owner_guid == 0) { |
416
|
|
|
return $this->guid; |
417
|
|
|
} |
418
|
|
|
|
419
|
|
|
return $this->owner_guid; |
420
|
|
|
} |
421
|
|
|
|
422
|
|
|
/** |
423
|
|
|
* {@inheritdoc} |
424
|
|
|
*/ |
425
|
|
|
protected function prepareObject($object) { |
426
|
|
|
$object = parent::prepareObject($object); |
427
|
|
|
$object->name = $this->getDisplayName(); |
428
|
|
|
$object->username = $this->username; |
429
|
|
|
$object->language = $this->language; |
430
|
|
|
unset($object->read_access); |
431
|
|
|
return $object; |
432
|
|
|
} |
433
|
|
|
|
434
|
|
|
/** |
435
|
|
|
* Can a user comment on this user? |
436
|
|
|
* |
437
|
|
|
* @see \ElggEntity::canComment() |
438
|
|
|
* |
439
|
|
|
* @param int $user_guid User guid (default is logged in user) |
440
|
|
|
* @param bool $default Default permission |
441
|
|
|
* @return bool |
442
|
|
|
* @since 1.8.0 |
443
|
|
|
*/ |
444
|
1 |
|
public function canComment($user_guid = 0, $default = null) { |
445
|
1 |
|
$result = parent::canComment($user_guid, $default); |
446
|
1 |
|
if ($result !== null) { |
447
|
|
|
return $result; |
448
|
|
|
} |
449
|
1 |
|
return false; |
450
|
|
|
} |
451
|
|
|
|
452
|
|
|
/** |
453
|
|
|
* Set the necessary metadata to store a hash of the user's password. |
454
|
|
|
* |
455
|
|
|
* @param string $password The password to be hashed |
456
|
|
|
* @return void |
457
|
|
|
* @since 1.10.0 |
458
|
|
|
*/ |
459
|
63 |
|
public function setPassword($password) { |
460
|
63 |
|
$this->setMetadata('password_hash', _elgg_services()->passwords->generateHash($password)); |
461
|
63 |
|
} |
462
|
|
|
|
463
|
|
|
/** |
464
|
|
|
* Enable or disable a notification delivery method |
465
|
|
|
* |
466
|
|
|
* @param string $method Method name |
467
|
|
|
* @param bool $enabled Enabled or disabled |
468
|
|
|
* @return bool |
469
|
|
|
*/ |
470
|
64 |
|
public function setNotificationSetting($method, $enabled = true) { |
471
|
64 |
|
$this->{"notification:method:$method"} = (int) $enabled; |
472
|
64 |
|
return (bool) $this->save(); |
473
|
|
|
} |
474
|
|
|
|
475
|
|
|
/** |
476
|
|
|
* Returns users's notification settings |
477
|
|
|
* <code> |
478
|
|
|
* [ |
479
|
|
|
* 'email' => true, // enabled |
480
|
|
|
* 'ajax' => false, // disabled |
481
|
|
|
* ] |
482
|
|
|
* </code> |
483
|
|
|
* |
484
|
|
|
* @return array |
485
|
|
|
*/ |
486
|
19 |
|
public function getNotificationSettings() { |
487
|
|
|
|
488
|
19 |
|
$settings = []; |
489
|
|
|
|
490
|
19 |
|
$methods = _elgg_services()->notifications->getMethods(); |
491
|
19 |
|
foreach ($methods as $method) { |
492
|
19 |
|
$settings[$method] = (bool) $this->{"notification:method:$method"}; |
493
|
|
|
} |
494
|
|
|
|
495
|
19 |
|
return $settings; |
496
|
|
|
|
497
|
|
|
} |
498
|
|
|
} |
499
|
|
|
|
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.