Issues (2473)

Branch: master

Security Analysis    no vulnerabilities found

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

engine/lib/users.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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);
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
 *   Formerly this was the seconds parameter.
135
 *
136
 * @param int   $limit   Limit (deprecated usage, use $options)
137
 * @param int   $offset  Offset (deprecated usage, use $options)
138
 * @param bool  $count   Count (deprecated usage, use $options)
139
 *
140
 * @return \ElggUser[]|int
141
 */
142
function find_active_users($options = array(), $limit = 10, $offset = 0, $count = false) {
143
	return _elgg_services()->usersTable->findActive($options, $limit, $offset, $count);
144
}
145
146
/**
147
 * Generate and send a password request email to a given user's registered email address.
148
 *
149
 * @param int $user_guid User GUID
150
 *
151
 * @return bool
152
 */
153
function send_new_password_request($user_guid) {
154
	return _elgg_services()->passwords->sendNewPasswordRequest($user_guid);
155
}
156
157
/**
158
 * Low level function to reset a given user's password.
159
 *
160
 * This can only be called from execute_new_password_request().
161
 *
162
 * @param int    $user_guid The user.
163
 * @param string $password  Text (which will then be converted into a hash and stored)
164
 *
165
 * @return bool
166
 */
167
function force_user_password_reset($user_guid, $password) {
168
	return _elgg_services()->passwords->forcePasswordReset($user_guid, $password);
169
}
170
171
/**
172
 * Validate and change password for a user.
173
 *
174
 * @param int    $user_guid The user id
175
 * @param string $conf_code Confirmation code as sent in the request email.
176
 * @param string $password  Optional new password, if not randomly generated.
177
 *
178
 * @return bool True on success
179
 */
180
function execute_new_password_request($user_guid, $conf_code, $password = null) {
181
	return _elgg_services()->passwords->executeNewPasswordReset($user_guid, $conf_code, $password);
182
}
183
184
/**
185
 * Generate a random 12 character clear text password.
186
 *
187
 * @return string
188
 */
189
function generate_random_cleartext_password() {
190
	return _elgg_services()->crypto->getRandomString(12, \ElggCrypto::CHARS_PASSWORD);
191
}
192
193
194
195
/**
196
 * Simple function which ensures that a username contains only valid characters.
197
 *
198
 * This should only permit chars that are valid on the file system as well.
199
 *
200
 * @param string $username Username
201
 *
202
 * @return bool
203
 * @throws RegistrationException on invalid
204
 */
205
function validate_username($username) {
206
	global $CONFIG;
207
208
	// Basic, check length
209
	if (!isset($CONFIG->minusername)) {
210
		$CONFIG->minusername = 4;
211
	}
212
213
	if (strlen($username) < $CONFIG->minusername) {
214
		$msg = elgg_echo('registration:usernametooshort', array($CONFIG->minusername));
215
		throw new \RegistrationException($msg);
216
	}
217
218
	// username in the database has a limit of 128 characters
219
	if (strlen($username) > 128) {
220
		$msg = elgg_echo('registration:usernametoolong', array(128));
221
		throw new \RegistrationException($msg);
222
	}
223
224
	// Blacklist for bad characters (partially nicked from mediawiki)
225
	$blacklist = '/[' .
226
		'\x{0080}-\x{009f}' . // iso-8859-1 control chars
227
		'\x{00a0}' .          // non-breaking space
228
		'\x{2000}-\x{200f}' . // various whitespace
229
		'\x{2028}-\x{202f}' . // breaks and control chars
230
		'\x{3000}' .          // ideographic space
231
		'\x{e000}-\x{f8ff}' . // private use
232
		']/u';
233
234
	if (preg_match($blacklist, $username)) {
235
		// @todo error message needs work
236
		throw new \RegistrationException(elgg_echo('registration:invalidchars'));
237
	}
238
239
	// Belts and braces
240
	// @todo Tidy into main unicode
241
	$blacklist2 = '\'/\\"*& ?#%^(){}[]~?<>;|¬`@+=';
242
243
	$blacklist2 = elgg_trigger_plugin_hook('username:character_blacklist', 'user',
244
		array('blacklist' => $blacklist2), $blacklist2);
245
246
	for ($n = 0; $n < strlen($blacklist2); $n++) {
247
		if (strpos($username, $blacklist2[$n]) !== false) {
248
			$msg = elgg_echo('registration:invalidchars', array($blacklist2[$n], $blacklist2));
249
			$msg = htmlspecialchars($msg, ENT_QUOTES, 'UTF-8');
250
			throw new \RegistrationException($msg);
251
		}
252
	}
253
254
	$result = true;
255
	return elgg_trigger_plugin_hook('registeruser:validate:username', 'all',
256
		array('username' => $username), $result);
257
}
258
259
/**
260
 * Simple validation of a password.
261
 *
262
 * @param string $password Clear text password
263
 *
264
 * @return bool
265
 * @throws RegistrationException on invalid
266
 */
267
function validate_password($password) {
268
	global $CONFIG;
269
270
	if (!isset($CONFIG->min_password_length)) {
271
		$CONFIG->min_password_length = 6;
272
	}
273
274
	if (strlen($password) < $CONFIG->min_password_length) {
275
		$msg = elgg_echo('registration:passwordtooshort', array($CONFIG->min_password_length));
276
		throw new \RegistrationException($msg);
277
	}
278
279
	$result = true;
280
	return elgg_trigger_plugin_hook('registeruser:validate:password', 'all',
281
		array('password' => $password), $result);
282
}
283
284
/**
285
 * Simple validation of a email.
286
 *
287
 * @param string $address Email address
288
 *
289
 * @throws RegistrationException on invalid
290
 * @return bool
291
 */
292
function validate_email_address($address) {
293
	if (!is_email_address($address)) {
294
		throw new \RegistrationException(elgg_echo('registration:notemail'));
295
	}
296
297
	// Got here, so lets try a hook (defaulting to ok)
298
	$result = true;
299
	return elgg_trigger_plugin_hook('registeruser:validate:email', 'all',
300
		array('email' => $address), $result);
301
}
302
303
/**
304
 * Registers a user, returning false if the username already exists
305
 *
306
 * @param string $username              The username of the new user
307
 * @param string $password              The password
308
 * @param string $name                  The user's display name
309
 * @param string $email                 The user's email address
310
 * @param bool   $allow_multiple_emails Allow the same email address to be
311
 *                                      registered multiple times?
312
 *
313
 * @return int|false The new user's GUID; false on failure
314
 * @throws RegistrationException
315
 */
316
function register_user($username, $password, $name, $email, $allow_multiple_emails = false) {
317
	return _elgg_services()->usersTable->register($username, $password, $name, $email, $allow_multiple_emails);
318
}
319
320
/**
321
 * Generates a unique invite code for a user
322
 *
323
 * @param string $username The username of the user sending the invitation
324
 *
325
 * @return string Invite code
326
 * @see elgg_validate_invite_code
327
 */
328
function generate_invite_code($username) {
329
	return _elgg_services()->usersTable->generateInviteCode($username);
330
}
331
332
/**
333
 * Validate a user's invite code
334
 *
335
 * @param string $username The username
336
 * @param string $code     The invite code
337
 *
338
 * @return bool
339
 * @see generate_invite_code
340
 * @since 1.10
341
 */
342
function elgg_validate_invite_code($username, $code) {
343
	return _elgg_services()->usersTable->validateInviteCode($username, $code);
344
}
345
346
/**
347
 * Set the validation status for a user.
348
 *
349
 * @param int    $user_guid The user's GUID
350
 * @param bool   $status    Validated (true) or unvalidated (false)
351
 * @param string $method    Optional method to say how a user was validated
352
 * @return bool
353
 * @since 1.8.0
354
 */
355
function elgg_set_user_validation_status($user_guid, $status, $method = '') {
356
	return _elgg_services()->usersTable->setValidationStatus($user_guid, $status, $method);
357
}
358
359
/**
360
 * Gets the validation status of a user.
361
 *
362
 * @param int $user_guid The user's GUID
363
 * @return bool|null Null means status was not set for this user.
364
 * @since 1.8.0
365
 */
366
function elgg_get_user_validation_status($user_guid) {
367
	return _elgg_services()->usersTable->getValidationStatus($user_guid);
368
}
369
370
/**
371
 * Page handler for account related pages
372
 *
373
 * @param array  $page_elements Page elements
374
 * @param string $handler The handler string
375
 *
376
 * @return bool
377
 * @access private
378
 */
379
function elgg_user_account_page_handler($page_elements, $handler) {
380
381
	$base_dir = elgg_get_root_path() . 'pages/account';
382
	switch ($handler) {
383
		case 'login':
384
			require_once("$base_dir/login.php");
385
			break;
386
		case 'forgotpassword':
387
			require_once("$base_dir/forgotten_password.php");
388
			break;
389
		case 'changepassword':
390
			require_once("$base_dir/change_password.php");
391
			break;
392
		case 'register':
393
			require_once("$base_dir/register.php");
394
			break;
395
		default:
396
			return false;
397
	}
398
	return true;
399
}
400
401
/**
402
 * Sets the last action time of the given user to right now.
403
 *
404
 * @param int $user_guid The user GUID
405
 *
406
 * @return void
407
 */
408
function set_last_action($user_guid) {
409
	_elgg_services()->usersTable->setLastAction($user_guid);
410
}
411
412
/**
413
 * Sets the last logon time of the given user to right now.
414
 *
415
 * @param int $user_guid The user GUID
416
 *
417
 * @return void
418
 */
419
function set_last_login($user_guid) {
420
	_elgg_services()->usersTable->setLastLogin($user_guid);
421
}
422
423
/**
424
 * Creates a relationship between this site and the user.
425
 *
426
 * @param string   $event       create
427
 * @param string   $object_type user
428
 * @param \ElggUser $object      User object
429
 *
430
 * @return void
431
 * @access private
432
 */
433
function user_create_hook_add_site_relationship($event, $object_type, $object) {
434
	add_entity_relationship($object->getGUID(), 'member_of_site', elgg_get_site_entity()->guid);
435
}
436
437
/**
438
 * Serves the user's avatar
439
 *
440
 * @param string $hook
441
 * @param string $entity_type
442
 * @param string $returnvalue
443
 * @param array  $params
444
 * @return string
445
 * @access private
446
 */
447
function user_avatar_hook($hook, $entity_type, $returnvalue, $params) {
448
	$user = $params['entity'];
449
	$size = $params['size'];
450
451
	if (isset($user->icontime)) {
452
		return "avatar/view/$user->username/$size/$user->icontime";
453
	} else {
454
		return "_graphics/icons/user/default{$size}.gif";
455
	}
456
}
457
458
/**
459
 * Setup the default user hover menu
460
 * @access private
461
 */
462
function elgg_user_hover_menu($hook, $type, $return, $params) {
463
	$user = elgg_extract('entity', $params);
464
	/* @var \ElggUser $user */
465
466
	if (!$user instanceof \ElggUser) {
467
		return;
468
	}
469
470
	if (!elgg_is_logged_in()) {
471
		return;
472
	}
473
	
474
	if (elgg_get_logged_in_user_guid() == $user->guid) {
475
		$url = "profile/$user->username/edit";
476
		$item = new \ElggMenuItem('profile:edit', elgg_echo('profile:edit'), $url);
477
		$item->setSection('action');
478
		$return[] = $item;
479
480
		$url = "avatar/edit/$user->username";
481
		$item = new \ElggMenuItem('avatar:edit', elgg_echo('avatar:edit'), $url);
482
		$item->setSection('action');
483
		$return[] = $item;
484
	}
485
486
	// prevent admins from banning or deleting themselves
487
	if (elgg_get_logged_in_user_guid() == $user->guid) {
488
		return $return;
489
	}
490
491
	if (elgg_is_admin_logged_in()) {
492
		$actions = array();
493
		if (!$user->isBanned()) {
494
			$actions[] = 'ban';
495
		} else {
496
			$actions[] = 'unban';
497
		}
498
		$actions[] = 'delete';
499
		$actions[] = 'resetpassword';
500
		if (!$user->isAdmin()) {
501
			$actions[] = 'makeadmin';
502
		} else {
503
			$actions[] = 'removeadmin';
504
		}
505
506
		foreach ($actions as $action) {
507
			$url = "action/admin/user/$action?guid={$user->guid}";
508
			$url = elgg_add_action_tokens_to_url($url);
509
			$item = new \ElggMenuItem($action, elgg_echo($action), $url);
510
			$item->setSection('admin');
511
			$item->setConfirmText(true);
0 ignored issues
show
true is of type boolean, but the function expects a string.

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...
512
513
			$return[] = $item;
514
		}
515
516
		$url = "profile/$user->username/edit";
517
		$item = new \ElggMenuItem('profile:edit', elgg_echo('profile:edit'), $url);
518
		$item->setSection('admin');
519
		$return[] = $item;
520
		
521
		$url = "avatar/edit/$user->username";
522
		$item = new \ElggMenuItem('avatar:edit', elgg_echo('avatar:edit'), $url);
523
		$item->setSection('admin');
524
		$return[] = $item;
525
		
526
		$url = "settings/user/$user->username";
527
		$item = new \ElggMenuItem('settings:edit', elgg_echo('settings:edit'), $url);
528
		$item->setSection('admin');
529
		$return[] = $item;
530
531
		$url = "activity/owner/$user->username";
532
		$item = new \ElggMenuItem('activity:owner', elgg_echo('activity:owner'), $url);
533
		$item->setSection('action');
534
		$return[] = $item;
535
	}
536
537
	return $return;
538
}
539
540
/**
541
 * Setup the menu shown with an entity
542
 *
543
 * @param string $hook
544
 * @param string $type
545
 * @param array $return
546
 * @param array $params
547
 * @return array
548
 *
549
 * @access private
550
 */
551
function elgg_users_setup_entity_menu($hook, $type, $return, $params) {
552
	if (elgg_in_context('widgets')) {
553
		return $return;
554
	}
555
556
	$entity = $params['entity'];
557
	if (!elgg_instanceof($entity, 'user')) {
558
		return $return;
559
	}
560
	/* @var \ElggUser $entity */
561
562
	if ($entity->isBanned()) {
563
		$banned = elgg_echo('banned');
564
		$options = array(
565
			'name' => 'banned',
566
			'text' => "<span>$banned</span>",
567
			'href' => false,
568
			'priority' => 0,
569
		);
570
		$return = array(\ElggMenuItem::factory($options));
571
	} else {
572
		$return = array();
573
		$location = $entity->location;
574
		if (is_string($location) && $location !== '') {
575
			$location = htmlspecialchars($location, ENT_QUOTES, 'UTF-8', false);
576
			$options = array(
577
				'name' => 'location',
578
				'text' => "<span>$location</span>",
579
				'href' => false,
580
				'priority' => 150,
581
			);
582
			$return[] = \ElggMenuItem::factory($options);
583
		}
584
	}
585
586
	return $return;
587
}
588
589
/**
590
 * This function loads a set of default fields into the profile, then triggers a hook letting other plugins to edit
591
 * add and delete fields.
592
 *
593
 * Note: This is a secondary system:init call and is run at a super low priority to guarantee that it is called after all
594
 * other plugins have initialised.
595
 * @access private
596
 */
597
function elgg_profile_fields_setup() {
598
	global $CONFIG;
599
600
	$profile_defaults = array (
601
		'description' => 'longtext',
602
		'briefdescription' => 'text',
603
		'location' => 'location',
604
		'interests' => 'tags',
605
		'skills' => 'tags',
606
		'contactemail' => 'email',
607
		'phone' => 'text',
608
		'mobile' => 'text',
609
		'website' => 'url',
610
		'twitter' => 'text',
611
	);
612
613
	$loaded_defaults = array();
614
	$fieldlist = elgg_get_config('profile_custom_fields');
615
	if ($fieldlist || $fieldlist === '0') {
616
		$fieldlistarray = explode(',', $fieldlist);
617
		foreach ($fieldlistarray as $listitem) {
618
			if ($translation = elgg_get_config("admin_defined_profile_{$listitem}")) {
619
				$type = elgg_get_config("admin_defined_profile_type_{$listitem}");
620
				$loaded_defaults["admin_defined_profile_{$listitem}"] = $type;
621
				add_translation(get_current_language(), array("profile:admin_defined_profile_{$listitem}" => $translation));
622
			}
623
		}
624
	}
625
626
	if (count($loaded_defaults)) {
627
		$CONFIG->profile_using_custom = true;
628
		$profile_defaults = $loaded_defaults;
629
	}
630
631
	$CONFIG->profile_fields = elgg_trigger_plugin_hook('profile:fields', 'profile', null, $profile_defaults);
632
633
	// register any tag metadata names
634
	foreach ($CONFIG->profile_fields as $name => $type) {
635
		if ($type == 'tags' || $type == 'location' || $type == 'tag') {
636
			elgg_register_tag_metadata_name($name);
637
			// register a tag name translation
638
			add_translation(get_current_language(), array("tag_names:$name" => elgg_echo("profile:$name")));
639
		}
640
	}
641
}
642
643
/**
644
 * Avatar page handler
645
 *
646
 * /avatar/edit/<username>
647
 * /avatar/view/<username>/<size>/<icontime>
648
 *
649
 * @param array $page
650
 * @return bool
651
 * @access private
652
 */
653
function elgg_avatar_page_handler($page) {
654
	global $CONFIG;
655
656
	$user = get_user_by_username($page[1]);
657
	if ($user) {
658
		elgg_set_page_owner_guid($user->getGUID());
659
	}
660
661
	if ($page[0] == 'edit') {
662
		require_once("{$CONFIG->path}pages/avatar/edit.php");
663
		return true;
664
	} else {
665
		set_input('size', $page[2]);
666
		require_once("{$CONFIG->path}pages/avatar/view.php");
667
		return true;
668
	}
669
	return false;
0 ignored issues
show
return false; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
670
}
671
672
/**
673
 * Profile page handler
674
 *
675
 * @param array $page
676
 * @return bool
677
 * @access private
678
 */
679
function elgg_profile_page_handler($page) {
680
	global $CONFIG;
681
682
	$user = get_user_by_username($page[0]);
683
	elgg_set_page_owner_guid($user->guid);
684
685
	if ($page[1] == 'edit') {
686
		require_once("{$CONFIG->path}pages/profile/edit.php");
687
		return true;
688
	}
689
	return false;
690
}
691
692
/**
693
 * Sets up user-related menu items
694
 *
695
 * @return void
696
 * @access private
697
 */
698
function users_pagesetup() {
699
700
	$owner = elgg_get_page_owner_entity();
701
	$viewer = elgg_get_logged_in_user_entity();
702
703
/*	if ($owner) {
704
		elgg_register_menu_item('page', array(
705
			'name' => 'edit_avatar',
706
			'href' => "avatar/edit/{$owner->username}",
707
			'text' => elgg_echo('avatar:edit'),
708
			'section' => '1_profile',
709
			'contexts' => array('settings'),
710
		));
711
712
		elgg_register_menu_item('page', array(
713
			'name' => 'edit_profile',
714
			'href' => "profile/{$owner->username}/edit",
715
			'text' => elgg_echo('profile:edit'),
716
			'section' => '1_profile',
717
			'contexts' => array('settings'),
718
		));
719
	}
720
*/
721
	// topbar
722
	if ($viewer) {
723
		elgg_register_menu_item('topbar', array(
724
			'name' => 'usersettings',
725
			'href' => "settings/user/{$viewer->username}",
726
			'text' => elgg_view_icon('settings') . elgg_echo('settings'),
727
			'priority' => 500,
728
			'section' => 'alt',
729
		));
730
731
		elgg_register_menu_item('topbar', array(
732
			'name' => 'logout',
733
			'href' => "action/logout",
734
			'text' => elgg_echo('logout'),
735
			'is_action' => true,
736
			'priority' => 1000,
737
			'section' => 'alt',
738
		));
739
	}
740
}
741
742
/**
743
 * Users initialisation function, which establishes the page handler
744
 *
745
 * @return void
746
 * @access private
747
 */
748
function users_init() {
749
750
	elgg_register_page_handler('register', 'elgg_user_account_page_handler');
751
	elgg_register_page_handler('forgotpassword', 'elgg_user_account_page_handler');
752
	elgg_register_page_handler('changepassword', 'elgg_user_account_page_handler');
753
	elgg_register_page_handler('login', 'elgg_user_account_page_handler');
754
	elgg_register_page_handler('avatar', 'elgg_avatar_page_handler');
755
	elgg_register_page_handler('profile', 'elgg_profile_page_handler');
756
757
	elgg_register_plugin_hook_handler('register', 'menu:user_hover', 'elgg_user_hover_menu');
758
759
	elgg_register_action('register', '', 'public');
760
	elgg_register_action('useradd', '', 'admin');
761
	elgg_register_action('avatar/upload');
762
	elgg_register_action('avatar/crop');
763
	elgg_register_action('avatar/remove');
764
	elgg_register_action('profile/edit');
765
766
	elgg_register_plugin_hook_handler('entity:icon:url', 'user', 'user_avatar_hook');
767
768
	elgg_register_action('user/changepassword', '', 'public');
769
	elgg_register_action('user/requestnewpassword', '', 'public');
770
771
	// Register the user type
772
	elgg_register_entity_type('user', '');
773
774
	elgg_register_plugin_hook_handler('register', 'menu:entity', 'elgg_users_setup_entity_menu', 501);
775
776
	elgg_register_event_handler('create', 'user', 'user_create_hook_add_site_relationship');
777
}
778
779
/**
780
 * Runs unit tests for \ElggUser
781
 *
782
 * @param string $hook   unit_test
783
 * @param string $type   system
784
 * @param mixed  $value  Array of tests
785
 * @param mixed  $params Params
786
 *
787
 * @return array
788
 * @access private
789
 */
790
function users_test($hook, $type, $value, $params) {
791
	global $CONFIG;
792
	$value[] = "{$CONFIG->path}engine/tests/ElggUserTest.php";
793
	return $value;
794
}
795
796
return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {
797
	$events->registerHandler('init', 'system', 'users_init', 0);
798
	$events->registerHandler('init', 'system', 'elgg_profile_fields_setup', 10000); // Ensure this runs after other plugins
799
	$events->registerHandler('pagesetup', 'system', 'users_pagesetup', 0);
800
	$hooks->registerHandler('unit_test', 'system', 'users_test');
801
};
802