Completed
Push — master ( cf7e49...23b00d )
by Steve
60:56 queued 51:28
created

users.php ➔ _elgg_user_topbar_menu()   B

Complexity

Conditions 4
Paths 5

Size

Total Lines 65
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 47
nc 5
nop 4
dl 0
loc 65
rs 8.8507
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Elgg users
4
 * Functions to manage multiple or single users in an Elgg install
5
 *
6
 * @package Elgg.Core
7
 * @subpackage DataModel.User
8
 */
9
10
/**
11
 * Return the user specific details of a user by a row.
12
 *
13
 * @param int $guid The \ElggUser guid
14
 *
15
 * @return mixed
16
 * @access private
17
 */
18
function get_user_entity_as_row($guid) {
19
	return _elgg_services()->usersTable->getRow($guid);
20
}
21
22
/**
23
 * Disables all of a user's entities
24
 *
25
 * @param int $owner_guid The owner GUID
26
 *
27
 * @return bool Depending on success
28
 */
29
function disable_user_entities($owner_guid) {
30
	return _elgg_services()->usersTable->disableEntities($owner_guid);
0 ignored issues
show
Deprecated Code introduced by
The method Elgg\Database\UsersTable::disableEntities() has been deprecated with message: 2.3

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
31
}
32
33
/**
34
 * Ban a user
35
 *
36
 * @param int    $user_guid The user guid
37
 * @param string $reason    A reason
38
 *
39
 * @return bool
40
 */
41
function ban_user($user_guid, $reason = "") {
42
	return _elgg_services()->usersTable->ban($user_guid, $reason);
43
}
44
45
/**
46
 * Unban a user.
47
 *
48
 * @param int $user_guid Unban a user.
49
 *
50
 * @return bool
51
 */
52
function unban_user($user_guid) {
53
	return _elgg_services()->usersTable->unban($user_guid);
54
}
55
56
/**
57
 * Makes user $guid an admin.
58
 *
59
 * @param int $user_guid User guid
60
 *
61
 * @return bool
62
 */
63
function make_user_admin($user_guid) {
64
	return _elgg_services()->usersTable->makeAdmin($user_guid);
65
}
66
67
/**
68
 * Removes user $guid's admin flag.
69
 *
70
 * @param int $user_guid User GUID
71
 *
72
 * @return bool
73
 */
74
function remove_user_admin($user_guid) {
75
	return _elgg_services()->usersTable->removeAdmin($user_guid);
76
}
77
78
/**
79
 * Get a user object from a GUID.
80
 *
81
 * This function returns an \ElggUser from a given GUID.
82
 *
83
 * @param int $guid The GUID
84
 *
85
 * @return \ElggUser|false
86
 */
87
function get_user($guid) {
88
	return _elgg_services()->entityTable->get($guid, 'user');
89
}
90
91
/**
92
 * Get user by username
93
 *
94
 * @param string $username The user's username
95
 *
96
 * @return \ElggUser|false Depending on success
97
 */
98
function get_user_by_username($username) {
99
	return _elgg_services()->usersTable->getByUsername($username);
100
}
101
102
/**
103
 * Get user by persistent login password
104
 *
105
 * @param string $hash Hash of the persistent login password
106
 *
107
 * @return \ElggUser
108
 */
109
function get_user_by_code($hash) {
110
	return _elgg_services()->persistentLogin->getUserFromHash($hash);
111
}
112
113
/**
114
 * Get an array of users from an email address
115
 *
116
 * @param string $email Email address.
117
 *
118
 * @return array
119
 */
120
function get_user_by_email($email) {
121
	return _elgg_services()->usersTable->getByEmail($email);
122
}
123
124
/**
125
 * Return users (or the number of them) who have been active within a recent period.
126
 *
127
 * @param array $options Array of options with keys:
128
 *
129
 *   seconds (int)  => Length of period (default 600 = 10min)
130
 *   limit   (int)  => Limit (default from settings)
131
 *   offset  (int)  => Offset (default 0)
132
 *   count   (bool) => Return a count instead of users? (default false)
133
 *
134
 * @return \ElggUser[]|int
135
 */
136
function find_active_users(array $options = []) {
137
	return _elgg_services()->usersTable->findActive($options);
138
}
139
140
/**
141
 * Generate and send a password request email to a given user's registered email address.
142
 *
143
 * @param int $user_guid User GUID
144
 *
145
 * @return bool
146
 */
147
function send_new_password_request($user_guid) {
148
	return _elgg_services()->passwords->sendNewPasswordRequest($user_guid);
149
}
150
151
/**
152
 * Low level function to reset a given user's password.
153
 *
154
 * This can only be called from execute_new_password_request().
155
 *
156
 * @param int    $user_guid The user.
157
 * @param string $password  Text (which will then be converted into a hash and stored)
158
 *
159
 * @return bool
160
 */
161
function force_user_password_reset($user_guid, $password) {
162
	return _elgg_services()->passwords->forcePasswordReset($user_guid, $password);
163
}
164
165
/**
166
 * Validate and change password for a user.
167
 *
168
 * @param int    $user_guid The user id
169
 * @param string $conf_code Confirmation code as sent in the request email.
170
 * @param string $password  Optional new password, if not randomly generated.
171
 *
172
 * @return bool True on success
173
 */
174
function execute_new_password_request($user_guid, $conf_code, $password = null) {
175
	return _elgg_services()->passwords->executeNewPasswordReset($user_guid, $conf_code, $password);
176
}
177
178
/**
179
 * Generate a random 12 character clear text password.
180
 *
181
 * @return string
182
 */
183
function generate_random_cleartext_password() {
184
	return _elgg_services()->crypto->getRandomString(12, \ElggCrypto::CHARS_PASSWORD);
185
}
186
187
188
189
/**
190
 * Simple function which ensures that a username contains only valid characters.
191
 *
192
 * This should only permit chars that are valid on the file system as well.
193
 *
194
 * @param string $username Username
195
 *
196
 * @return bool
197
 * @throws RegistrationException on invalid
198
 */
199
function validate_username($username) {
200
	global $CONFIG;
201
202
	// Basic, check length
203
	if (!isset($CONFIG->minusername)) {
204
		$CONFIG->minusername = 4;
205
	}
206
207
	if (strlen($username) < $CONFIG->minusername) {
208
		$msg = elgg_echo('registration:usernametooshort', [$CONFIG->minusername]);
209
		throw new \RegistrationException($msg);
210
	}
211
212
	// username in the database has a limit of 128 characters
213
	if (strlen($username) > 128) {
214
		$msg = elgg_echo('registration:usernametoolong', [128]);
215
		throw new \RegistrationException($msg);
216
	}
217
218
	// Blacklist for bad characters (partially nicked from mediawiki)
219
	$blacklist = '/[' .
220
		'\x{0080}-\x{009f}' . // iso-8859-1 control chars
221
		'\x{00a0}' .          // non-breaking space
222
		'\x{2000}-\x{200f}' . // various whitespace
223
		'\x{2028}-\x{202f}' . // breaks and control chars
224
		'\x{3000}' .          // ideographic space
225
		'\x{e000}-\x{f8ff}' . // private use
226
		']/u';
227
228
	if (preg_match($blacklist, $username)) {
229
		// @todo error message needs work
230
		throw new \RegistrationException(elgg_echo('registration:invalidchars'));
231
	}
232
233
	// Belts and braces
234
	// @todo Tidy into main unicode
235
	$blacklist2 = '\'/\\"*& ?#%^(){}[]~?<>;|¬`@+=';
236
237
	$blacklist2 = elgg_trigger_plugin_hook('username:character_blacklist', 'user',
238
		['blacklist' => $blacklist2], $blacklist2);
239
240
	for ($n = 0; $n < strlen($blacklist2); $n++) {
241
		if (strpos($username, $blacklist2[$n]) !== false) {
242
			$msg = elgg_echo('registration:invalidchars', [$blacklist2[$n], $blacklist2]);
243
			$msg = htmlspecialchars($msg, ENT_QUOTES, 'UTF-8');
244
			throw new \RegistrationException($msg);
245
		}
246
	}
247
248
	$result = true;
249
	return elgg_trigger_plugin_hook('registeruser:validate:username', 'all',
250
		['username' => $username], $result);
251
}
252
253
/**
254
 * Simple validation of a password.
255
 *
256
 * @param string $password Clear text password
257
 *
258
 * @return bool
259
 * @throws RegistrationException on invalid
260
 */
261
function validate_password($password) {
262
	global $CONFIG;
263
264
	if (!isset($CONFIG->min_password_length)) {
265
		$CONFIG->min_password_length = 6;
266
	}
267
268
	if (strlen($password) < $CONFIG->min_password_length) {
269
		$msg = elgg_echo('registration:passwordtooshort', [$CONFIG->min_password_length]);
270
		throw new \RegistrationException($msg);
271
	}
272
273
	$result = true;
274
	return elgg_trigger_plugin_hook('registeruser:validate:password', 'all',
275
		['password' => $password], $result);
276
}
277
278
/**
279
 * Simple validation of a email.
280
 *
281
 * @param string $address Email address
282
 *
283
 * @throws RegistrationException on invalid
284
 * @return bool
285
 */
286
function validate_email_address($address) {
287
	if (!is_email_address($address)) {
288
		throw new \RegistrationException(elgg_echo('registration:notemail'));
289
	}
290
291
	// Got here, so lets try a hook (defaulting to ok)
292
	$result = true;
293
	return elgg_trigger_plugin_hook('registeruser:validate:email', 'all',
294
		['email' => $address], $result);
295
}
296
297
/**
298
 * Registers a user, returning false if the username already exists
299
 *
300
 * @param string $username              The username of the new user
301
 * @param string $password              The password
302
 * @param string $name                  The user's display name
303
 * @param string $email                 The user's email address
304
 * @param bool   $allow_multiple_emails Allow the same email address to be
305
 *                                      registered multiple times?
306
 *
307
 * @return int|false The new user's GUID; false on failure
308
 * @throws RegistrationException
309
 */
310
function register_user($username, $password, $name, $email, $allow_multiple_emails = false) {
311
	return _elgg_services()->usersTable->register($username, $password, $name, $email, $allow_multiple_emails);
312
}
313
314
/**
315
 * Generates a unique invite code for a user
316
 *
317
 * @param string $username The username of the user sending the invitation
318
 *
319
 * @return string Invite code
320
 * @see elgg_validate_invite_code
321
 */
322
function generate_invite_code($username) {
323
	return _elgg_services()->usersTable->generateInviteCode($username);
324
}
325
326
/**
327
 * Validate a user's invite code
328
 *
329
 * @param string $username The username
330
 * @param string $code     The invite code
331
 *
332
 * @return bool
333
 * @see generate_invite_code
334
 * @since 1.10
335
 */
336
function elgg_validate_invite_code($username, $code) {
337
	return _elgg_services()->usersTable->validateInviteCode($username, $code);
338
}
339
340
/**
341
 * Set the validation status for a user.
342
 *
343
 * @param int    $user_guid The user's GUID
344
 * @param bool   $status    Validated (true) or unvalidated (false)
345
 * @param string $method    Optional method to say how a user was validated
346
 * @return bool
347
 * @since 1.8.0
348
 */
349
function elgg_set_user_validation_status($user_guid, $status, $method = '') {
350
	return _elgg_services()->usersTable->setValidationStatus($user_guid, $status, $method);
351
}
352
353
/**
354
 * Gets the validation status of a user.
355
 *
356
 * @param int $user_guid The user's GUID
357
 * @return bool|null Null means status was not set for this user.
358
 * @since 1.8.0
359
 */
360
function elgg_get_user_validation_status($user_guid) {
361
	return _elgg_services()->usersTable->getValidationStatus($user_guid);
362
}
363
364
/**
365
 * Page handler for account related pages
366
 *
367
 * @param array  $page_elements Page elements
368
 * @param string $handler The handler string
369
 *
370
 * @return bool
371
 * @access private
372
 */
373
function elgg_user_account_page_handler($page_elements, $handler) {
0 ignored issues
show
Unused Code introduced by
The parameter $page_elements is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
374
375
	switch ($handler) {
376
		case 'login':
377
			echo elgg_view_resource("account/login");
378
			break;
379
		case 'forgotpassword':
380
			echo elgg_view_resource("account/forgotten_password");
381
			break;
382
		case 'changepassword':
383
			echo elgg_view_resource("account/change_password");
384
			break;
385
		case 'register':
386
			echo elgg_view_resource("account/register");
387
			break;
388
		default:
389
			return false;
390
	}
391
392
	return true;
393
}
394
395
/**
396
 * Returns site's registration URL
397
 * Triggers a 'registration_url', 'site' plugin hook that can be used by
398
 * plugins to alter the default registration URL and append query elements, such as
399
 * an invitation code and inviting user's guid
400
 *
401
 * @param array  $query    An array of query elements
402
 * @param string $fragment Fragment identifier
403
 * @return string
404
 */
405
function elgg_get_registration_url(array $query = [], $fragment = '') {
406
	$url = elgg_normalize_url('register');
407
	$url = elgg_http_add_url_query_elements($url, $query) . $fragment;
408
	return elgg_trigger_plugin_hook('registration_url', 'site', $query, $url);
409
}
410
411
/**
412
 * Returns site's login URL
413
 * Triggers a 'login_url', 'site' plugin hook that can be used by
414
 * plugins to alter the default login URL
415
 *
416
 * @param array  $query    An array of query elements
417
 * @param string $fragment Fragment identifier (e.g. #login-dropdown-box)
418
 * @return string
419
 */
420
function elgg_get_login_url(array $query = [], $fragment = '') {
421
	$url = elgg_normalize_url('login');
422
	$url = elgg_http_add_url_query_elements($url, $query) . $fragment;
423
	return elgg_trigger_plugin_hook('login_url', 'site', $query, $url);
424
}
425
426
/**
427
 * Sets the last action time of the given user to right now.
428
 *
429
 * @param int $user_guid The user GUID
430
 * @return void
431
 */
432
function set_last_action($user_guid) {
433
	$user = get_user($user_guid);
434
	if (!$user) {
435
		return;
436
	}
437
	_elgg_services()->usersTable->setLastAction($user);
0 ignored issues
show
Documentation introduced by
$user is of type object<ElggEntity>|object<stdClass>, but the function expects a object<ElggUser>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
438
}
439
440
/**
441
 * Sets the last logon time of the given user to right now.
442
 *
443
 * @param int $user_guid The user GUID
444
 * @return void
445
 */
446
function set_last_login($user_guid) {
447
	$user = get_user($user_guid);
448
	if (!$user) {
449
		return;
450
	}
451
	_elgg_services()->usersTable->setLastLogin($user);
0 ignored issues
show
Documentation introduced by
$user is of type object<ElggEntity>|object<stdClass>, but the function expects a object<ElggUser>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
452
}
453
454
/**
455
 * Set user avatar URL
456
 * Replaces user avatar URL with a public URL when walled garden is disabled
457
 *
458
 * @param string $hook   "entity:icon:url"
459
 * @param string $type   "user"
460
 * @param string $return Icon URL
461
 * @param array  $params Hook params
462
 * @return string
463
 * @access private
464
 */
465
function user_avatar_hook($hook, $type, $return, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $return is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
466
	$user = elgg_extract('entity', $params);
467
	$size = elgg_extract('size', $params, 'medium');
468
469
	if (!$user instanceof ElggUser) {
470
		return;
471
	}
472
473
	if (elgg_get_config('walled_garden')) {
474
		return;
475
	}
476
477
	if (!$user->hasIcon($size, 'icon')) {
478
		return;
479
	}
480
	
481
	$icon = $user->getIcon($size, 'icon');
482
	return elgg_get_inline_url($icon, false);
483
}
484
485
/**
486
 * Setup the default user hover menu
487
 * @access private
488
 */
489
function elgg_user_hover_menu($hook, $type, $return, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
490
	$user = elgg_extract('entity', $params);
491
	/* @var \ElggUser $user */
492
493
	if (!$user instanceof \ElggUser) {
494
		return;
495
	}
496
497
	if (!elgg_is_logged_in()) {
498
		return;
499
	}
500
	
501
	if ($user->canEdit()) {
502
		$return[] = ElggMenuItem::factory([
503
			'name' => 'profile:edit',
504
			'text' => elgg_echo('profile:edit'),
505
			'icon' => 'address-card',
506
			'href' => "profile/$user->username/edit",
507
			'section' => (elgg_get_logged_in_user_guid() == $user->guid)? 'action' : 'admin',
508
		]);
509
510
		$return[] = ElggMenuItem::factory([
511
			'name' => 'avatar:edit',
512
			'text' => elgg_echo('avatar:edit'),
513
			'icon' => 'image',
514
			'href' => "avatar/edit/$user->username",
515
			'section' => (elgg_get_logged_in_user_guid() == $user->guid)? 'action' : 'admin',
516
		]);
517
	}
518
519
	// prevent admins from banning or deleting themselves
520
	if (elgg_get_logged_in_user_guid() == $user->guid) {
521
		return $return;
522
	}
523
524
	if (!elgg_is_admin_logged_in()) {
525
		return $return;
526
	}
527
	
528
	// following items are admin only
529 View Code Duplication
	if (!$user->isBanned()) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
530
		$return[] = ElggMenuItem::factory([
531
			'name' => 'ban',
532
			'text' => elgg_echo('ban'),
533
			'icon' => 'ban',
534
			'href' => "action/admin/user/ban?guid={$user->guid}",
535
			'confirm' => true,
536
			'section' => 'admin',
537
		]);
538
	} else {
539
		$return[] = ElggMenuItem::factory([
540
			'name' => 'unban',
541
			'text' => elgg_echo('unban'),
542
			'icon' => 'ban',
543
			'href' => "action/admin/user/unban?guid={$user->guid}",
544
			'confirm' => true,
545
			'section' => 'admin',
546
		]);
547
	}
548
	
549
	$return[] = ElggMenuItem::factory([
550
		'name' => 'delete',
551
		'text' => elgg_echo('delete'),
552
		'icon' => 'delete',
553
		'href' => "action/admin/user/delete?guid={$user->guid}",
554
		'confirm' => true,
555
		'section' => 'admin',
556
	]);
557
	
558
	$return[] = ElggMenuItem::factory([
559
		'name' => 'resetpassword',
560
		'text' => elgg_echo('resetpassword'),
561
		'icon' => 'refresh',
562
		'href' => "action/admin/user/resetpassword?guid={$user->guid}",
563
		'confirm' => true,
564
		'section' => 'admin',
565
	]);
566
	
567 View Code Duplication
	if (!$user->isAdmin()) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
568
		$return[] = ElggMenuItem::factory([
569
			'name' => 'makeadmin',
570
			'text' => elgg_echo('makeadmin'),
571
			'icon' => 'level-up',
572
			'href' => "action/admin/user/makeadmin?guid={$user->guid}",
573
			'confirm' => true,
574
			'section' => 'admin',
575
		]);
576
	} else {
577
		$return[] = ElggMenuItem::factory([
578
			'name' => 'removeadmin',
579
			'text' => elgg_echo('removeadmin'),
580
			'icon' => 'level-down',
581
			'href' => "action/admin/user/removeadmin?guid={$user->guid}",
582
			'confirm' => true,
583
			'section' => 'admin',
584
		]);
585
	}
586
	
587
	$return[] = ElggMenuItem::factory([
588
		'name' => 'settings:edit',
589
		'text' => elgg_echo('settings:edit'),
590
		'icon' => 'cogs',
591
		'href' => "settings/user/$user->username",
592
		'section' => 'admin',
593
	]);
594
595
	return $return;
596
}
597
598
/**
599
 * Setup the menu shown with an entity
600
 *
601
 * @param string $hook
602
 * @param string $type
603
 * @param array $return
604
 * @param array $params
605
 * @return array
606
 *
607
 * @access private
608
 */
609
function elgg_users_setup_entity_menu($hook, $type, $return, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
610
	if (elgg_in_context('widgets')) {
611
		return $return;
612
	}
613
614
	$entity = $params['entity'];
615
	if (!elgg_instanceof($entity, 'user')) {
616
		return $return;
617
	}
618
	/* @var \ElggUser $entity */
619
620
	if ($entity->isBanned()) {
621
		$banned = elgg_echo('banned');
622
		$options = [
623
			'name' => 'banned',
624
			'text' => "<span>$banned</span>",
625
			'href' => false,
626
			'priority' => 0,
627
		];
628
		$return = [\ElggMenuItem::factory($options)];
629
	} else {
630
		$return = [];
631
		$location = $entity->location;
632
		if (is_string($location) && $location !== '') {
633
			$location = htmlspecialchars($location, ENT_QUOTES, 'UTF-8', false);
634
			$options = [
635
				'name' => 'location',
636
				'text' => "<span>$location</span>",
637
				'href' => false,
638
				'priority' => 150,
639
			];
640
			$return[] = \ElggMenuItem::factory($options);
641
		}
642
	}
643
644
	return $return;
645
}
646
647
/**
648
 * This function loads a set of default fields into the profile, then triggers a hook letting other plugins to edit
649
 * add and delete fields.
650
 *
651
 * Note: This is a secondary system:init call and is run at a super low priority to guarantee that it is called after all
652
 * other plugins have initialised.
653
 * @access private
654
 */
655
function elgg_profile_fields_setup() {
656
	global $CONFIG;
657
658
	$profile_defaults =  [
659
		'description' => 'longtext',
660
		'briefdescription' => 'text',
661
		'location' => 'location',
662
		'interests' => 'tags',
663
		'skills' => 'tags',
664
		'contactemail' => 'email',
665
		'phone' => 'text',
666
		'mobile' => 'text',
667
		'website' => 'url',
668
		'twitter' => 'text',
669
	];
670
671
	$loaded_defaults = [];
672
	$fieldlist = elgg_get_config('profile_custom_fields');
673
	if ($fieldlist || $fieldlist === '0') {
674
		$fieldlistarray = explode(',', $fieldlist);
675
		foreach ($fieldlistarray as $listitem) {
676
			if ($translation = elgg_get_config("admin_defined_profile_{$listitem}")) {
677
				$type = elgg_get_config("admin_defined_profile_type_{$listitem}");
678
				$loaded_defaults["admin_defined_profile_{$listitem}"] = $type;
679
				add_translation(get_current_language(), ["profile:admin_defined_profile_{$listitem}" => $translation]);
680
			}
681
		}
682
	}
683
684
	if (count($loaded_defaults)) {
685
		$CONFIG->profile_using_custom = true;
686
		$profile_defaults = $loaded_defaults;
687
	}
688
689
	$CONFIG->profile_fields = elgg_trigger_plugin_hook('profile:fields', 'profile', null, $profile_defaults);
690
691
	// register any tag metadata names
692
	foreach ($CONFIG->profile_fields as $name => $type) {
693
		if ($type == 'tags' || $type == 'location' || $type == 'tag') {
694
			elgg_register_tag_metadata_name($name);
695
			// register a tag name translation
696
			add_translation(get_current_language(), ["tag_names:$name" => elgg_echo("profile:$name")]);
697
		}
698
	}
699
}
700
701
/**
702
 * Avatar page handler
703
 *
704
 * /avatar/edit/<username>
705
 *
706
 * @param array $page
707
 * @return bool
708
 * @access private
709
 */
710 View Code Duplication
function elgg_avatar_page_handler($page) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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.

Loading history...
711
	$user = get_user_by_username(elgg_extract(1, $page));
712
	if ($user) {
713
		elgg_set_page_owner_guid($user->getGUID());
714
	}
715
716
	if ($page[0] == 'edit') {
717
		echo elgg_view_resource("avatar/edit");
718
		return true;
719
	}
720
}
721
722
/**
723
 * Profile page handler
724
 *
725
 * @param array $page
726
 * @return bool
727
 * @access private
728
 */
729 View Code Duplication
function elgg_profile_page_handler($page) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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.

Loading history...
730
	$user = get_user_by_username($page[0]);
731
	elgg_set_page_owner_guid($user->guid);
732
733
	if ($page[1] == 'edit') {
734
		echo elgg_view_resource("profile/edit");
735
		return true;
736
	}
737
	return false;
738
}
739
740
/**
741
 * Register menu items for the page menu
742
 *
743
 * @param string $hook
744
 * @param string $type
745
 * @param array  $return
746
 * @param array  $params
747
 *
748
 * @return array
749
 *
750
 * @access private
751
 *
752
 * @since 3.0
753
 */
754
function _elgg_user_page_menu($hook, $type, $return, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $params is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
755
	
756
	$owner = elgg_get_page_owner_entity();
757
	if (!$owner) {
758
		return;
759
	}
760
761
	$return[] = \ElggMenuItem::factory([
762
		'name' => 'edit_avatar',
763
		'href' => "avatar/edit/{$owner->username}",
764
		'text' => elgg_echo('avatar:edit'),
765
		'section' => '1_profile',
766
		'contexts' => ['settings'],
767
	]);
768
	
769
	$return[] = \ElggMenuItem::factory([
770
		'name' => 'edit_profile',
771
		'href' => "profile/{$owner->username}/edit",
772
		'text' => elgg_echo('profile:edit'),
773
		'section' => '1_profile',
774
		'contexts' => ['settings'],
775
	]);
776
	
777
	return $return;
778
}
779
780
/**
781
 * Register menu items for the topbar menu
782
 *
783
 * @param string $hook
784
 * @param string $type
785
 * @param array  $return
786
 * @param array  $params
787
 *
788
 * @return array
789
 *
790
 * @access private
791
 *
792
 * @since 3.0
793
 */
794
function _elgg_user_topbar_menu($hook, $type, $return, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $params is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
795
	
796
	$viewer = elgg_get_logged_in_user_entity();
797
	if (!$viewer) {
798
		return;
799
	}
800
801
	$toggle = elgg_view_icon('chevron-down', ['class' => 'elgg-state-closed']);
802
	$toggle .= elgg_view_icon('chevron-up', ['class' => 'elgg-state-opened']);
803
804
	// If JS fails here, allow easy access to place where they can upgrade/flush caches
805
	$href = elgg_is_admin_logged_in() ? elgg_get_login_url() : '#';
806
807
	$return[] = \ElggMenuItem::factory([
808
		'name' => 'account',
809
		'text' => elgg_echo('account') . $toggle,
810
		'href' => $href,
811
		'priority' => 800,
812
		'section' => 'alt',
813
		'child_menu' => [
814
			'display' => 'dropdown',
815
			'class' => 'elgg-topbar-child-menu',
816
			'data-position' => json_encode([
817
				'at' => 'right+10px bottom',
818
				'my' => 'right top',
819
				'collision' => 'fit fit',
820
			]),
821
		],
822
	]);
823
	
824
	$return[] = \ElggMenuItem::factory([
825
		'name' => 'usersettings',
826
		'parent_name' => 'account',
827
		'href' => "settings/user/{$viewer->username}",
828
		'text' => elgg_echo('settings'),
829
		'icon' => 'cogs',
830
		'priority' => 300,
831
		'section' => 'alt',
832
	]);
833
	
834
	if ($viewer->isAdmin()) {
835
		$return[] = \ElggMenuItem::factory([
836
			'name' => 'administration',
837
			'parent_name' => 'account',
838
			'href' => 'admin',
839
			'text' => elgg_echo('admin'),
840
			'icon' => 'tasks',
841
			'priority' => 800,
842
			'section' => 'alt',
843
		]);
844
	}
845
	
846
	$return[] = \ElggMenuItem::factory([
847
		'name' => 'logout',
848
		'parent_name' => 'account',
849
		'href' => 'action/logout',
850
		'text' => elgg_echo('logout'),
851
		'icon' => 'sign-out',
852
		'is_action' => true,
853
		'priority' => 900,
854
		'section' => 'alt',
855
	]);
856
	
857
	return $return;
858
}
859
860
/**
861
 * Set user icon file
862
 *
863
 * @param string    $hook   "entity:icon:file"
864
 * @param string    $type   "user"
865
 * @param \ElggIcon $icon   Icon file
866
 * @param array     $params Hook params
867
 * @return \ElggIcon
868
 */
869
function _elgg_user_set_icon_file($hook, $type, $icon, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
870
871
	$entity = elgg_extract('entity', $params);
872
	$size = elgg_extract('size', $params, 'medium');
873
874
	$icon->owner_guid = $entity->guid;
875
	$icon->setFilename("profile/{$entity->guid}{$size}.jpg");
876
	
877
	return $icon;
878
}
879
880
/**
881
 * Add the user to the subscribers when (un)banning the account
882
 *
883
 * @param string $hook         'get'
884
 * @param string $type         'subscribers'
885
 * @param array  $return_value current subscribers
886
 * @param arary  $params       supplied params
887
 *
888
 * @return void|array
889
 */
890
function _elgg_user_get_subscriber_unban_action($hook, $type, $return_value, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
891
	
892
	if (!elgg_get_config('security_notify_user_ban')) {
893
		return;
894
	}
895
	
896
	$event = elgg_extract('event', $params);
897
	if (!($event instanceof \Elgg\Notifications\Event)) {
898
		return;
899
	}
900
	
901
	if ($event->getAction() !== 'unban') {
902
		return;
903
	}
904
	
905
	$user = $event->getObject();
906
	if (!($user instanceof \ElggUser)) {
907
		return;
908
	}
909
	
910
	$return_value[$user->getGUID()] = ['email'];
911
	
912
	return $return_value;
913
}
914
915
/**
916
 * Send a notification to the user that the account was banned
917
 *
918
 * Note: this can't be handled by the delayed notification system as it won't send notifications to banned users
919
 *
920
 * @param string    $event 'ban'
921
 * @param string    $type  'user'
922
 * @param \ElggUser $user  the user being banned
923
 *
924
 * @return void
925
 */
926
function _elgg_user_ban_notification($event, $type, $user) {
0 ignored issues
show
Unused Code introduced by
The parameter $event is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
927
	
928
	if (!elgg_get_config('security_notify_user_ban')) {
929
		return;
930
	}
931
	
932
	if (!($user instanceof \ElggUser)) {
933
		return;
934
	}
935
	
936
	$site = elgg_get_site_entity();
937
	
938
	$subject = elgg_echo('user:notification:ban:subject', [$site->name], $language);
0 ignored issues
show
Bug introduced by
The variable $language does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
939
	$body = elgg_echo('user:notification:ban:body', [
940
		$recipient->name,
0 ignored issues
show
Bug introduced by
The variable $recipient does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
941
		$site->name,
942
		$site->getURL(),
943
	], $language);
944
	
945
	$params = [
946
		'action' => 'ban',
947
		'object' => $user,
948
	];
949
	
950
	notify_user($user->getGUID(), $site->getGUID(), $subject, $body, $params, ['email']);
951
}
952
953
/**
954
 * Prepare the notification content for the user being unbanned
955
 *
956
 * @param string                           $hook         'prepare'
957
 * @param string                           $type         'notification:unban:user:'
958
 * @param \Elgg\Notifications\Notification $return_value current notification content
959
 * @param array                            $params       supplied params
960
 *
961
 * @return void|\Elgg\Notifications\Notification
962
 */
963
function _elgg_user_prepare_unban_notification($hook, $type, $return_value, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
964
	
965
	if (!($return_value instanceof \Elgg\Notifications\Notification)) {
966
		return;
967
	}
968
	
969
	$recipient = elgg_extract('recipient', $params);
970
	$object = elgg_extract('object', $params);
971
	$language = elgg_extract('language', $params);
972
	
973
	if (!($recipient instanceof ElggUser) || !($object instanceof ElggUser)) {
974
		return;
975
	}
976
	
977
	if ($recipient->getGUID() !== $object->getGUID()) {
978
		return;
979
	}
980
	
981
	$site = elgg_get_site_entity();
982
	
983
	$return_value->subject = elgg_echo('user:notification:unban:subject', [$site->name], $language);
984
	$return_value->body = elgg_echo('user:notification:unban:body', [
985
		$recipient->name,
986
		$site->name,
987
		$site->getURL(),
988
	], $language);
989
990
	$return_value->url = $recipient->getURL();
991
	
992
	return $return_value;
993
}
994
995
/**
996
 * Users initialisation function, which establishes the page handler
997
 *
998
 * @return void
999
 * @access private
1000
 */
1001 View Code Duplication
function users_init() {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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.

Loading history...
1002
1003
	elgg_register_page_handler('register', 'elgg_user_account_page_handler');
1004
	elgg_register_page_handler('forgotpassword', 'elgg_user_account_page_handler');
1005
	elgg_register_page_handler('changepassword', 'elgg_user_account_page_handler');
1006
	elgg_register_page_handler('login', 'elgg_user_account_page_handler');
1007
	elgg_register_page_handler('avatar', 'elgg_avatar_page_handler');
1008
	elgg_register_page_handler('profile', 'elgg_profile_page_handler');
1009
1010
	elgg_register_plugin_hook_handler('register', 'menu:user_hover', 'elgg_user_hover_menu');
1011
	elgg_register_plugin_hook_handler('register', 'menu:page', '_elgg_user_page_menu');
1012
	elgg_register_plugin_hook_handler('register', 'menu:topbar', '_elgg_user_topbar_menu');
1013
1014
	elgg_register_action('login', '', 'public');
1015
	elgg_register_action('logout');
1016
	elgg_register_action('register', '', 'public');
1017
	elgg_register_action('useradd', '', 'admin');
1018
	elgg_register_action('avatar/upload');
1019
	elgg_register_action('avatar/crop');
1020
	elgg_register_action('avatar/remove');
1021
	elgg_register_action('profile/edit');
1022
1023
	elgg_register_plugin_hook_handler('entity:icon:url', 'user', 'user_avatar_hook');
1024
1025
	elgg_register_action('user/changepassword', '', 'public');
1026
	elgg_register_action('user/requestnewpassword', '', 'public');
1027
1028
	// Register the user type
1029
	elgg_register_entity_type('user', '');
1030
1031
	elgg_register_plugin_hook_handler('register', 'menu:entity', 'elgg_users_setup_entity_menu', 501);
1032
1033
	elgg_register_plugin_hook_handler('entity:icon:file', 'user', '_elgg_user_set_icon_file');
1034
	
1035
	elgg_register_notification_event('user', '', ['unban']);
1036
	elgg_register_plugin_hook_handler('get', 'subscriptions', '_elgg_user_get_subscriber_ban_action');
1037
	elgg_register_event_handler('ban', 'user', '_elgg_user_ban_notification');
1038
	elgg_register_plugin_hook_handler('prepare', 'notification:unban:user:', '_elgg_user_prepare_unban_notification');
1039
	
1040
}
1041
1042
/**
1043
 * Runs unit tests for \ElggUser
1044
 *
1045
 * @param string $hook   unit_test
1046
 * @param string $type   system
1047
 * @param mixed  $value  Array of tests
1048
 * @param mixed  $params Params
1049
 *
1050
 * @return array
1051
 * @access private
1052
 */
1053
function users_test($hook, $type, $value, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $params is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1054
	global $CONFIG;
1055
	$value[] = "{$CONFIG->path}engine/tests/ElggUserTest.php";
1056
	return $value;
1057
}
1058
1059
return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {
1060
	$events->registerHandler('init', 'system', 'users_init', 0);
1061
	$events->registerHandler('init', 'system', 'elgg_profile_fields_setup', 10000); // Ensure this runs after other plugins
1062
	$hooks->registerHandler('unit_test', 'system', 'users_test');
1063
};
1064