Passed
Push — master ( c0a3a7...3b84a4 )
by Jeroen
58:51
created

engine/lib/user_settings.php (5 issues)

1
<?php
2
/**
3
 * Elgg user settings functions.
4
 * Functions for adding and manipulating options on the user settings panel.
5
 *
6
 * @package Elgg.Core
7
 * @subpackage Settings.User
8
 */
9
10
/**
11
 * Set a user's password
12
 * Returns null if no change is required
13
 * Returns true or false indicating success or failure if change was needed
14
 *
15
 * @return bool|void
16
 * @since 1.8.0
17
 * @access private
18
 */
19
function _elgg_set_user_password() {
20
	$current_password = get_input('current_password', null, false);
21
	$password = get_input('password', null, false);
22
	$password2 = get_input('password2', null, false);
23
	$user_guid = get_input('guid');
24
25
	if ($user_guid) {
26
		$user = get_user($user_guid);
0 ignored issues
show
It seems like $user_guid can also be of type string; however, parameter $guid of get_user() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

26
		$user = get_user(/** @scrutinizer ignore-type */ $user_guid);
Loading history...
27
	} else {
28
		$user = elgg_get_logged_in_user_entity();
29
	}
30
31
	if ($user && $password) {
32
		// let admin user change anyone's password without knowing it except his own.
33
		if (!elgg_is_admin_logged_in() || elgg_is_admin_logged_in() && $user->guid == elgg_get_logged_in_user_guid()) {
34
			$credentials = [
35
				'username' => $user->username,
36
				'password' => $current_password
37
			];
38
39
			try {
40
				pam_auth_userpass($credentials);
41
			} catch (LoginException $e) {
42
				register_error(elgg_echo('LoginException:ChangePasswordFailure'));
43
				return false;
44
			}
45
		}
46
47
		try {
48
			$result = validate_password($password);
49
		} catch (RegistrationException $e) {
50
			register_error($e->getMessage());
51
			return false;
52
		}
53
54
		if ($result) {
55
			if ($password == $password2) {
56
				$user->setPassword($password);
57
				_elgg_services()->persistentLogin->handlePasswordChange($user, elgg_get_logged_in_user_entity());
58
59
				if ($user->save()) {
60
					system_message(elgg_echo('user:password:success'));
61
					return true;
62
				} else {
63
					register_error(elgg_echo('user:password:fail'));
64
				}
65
			} else {
66
				register_error(elgg_echo('user:password:fail:notsame'));
67
			}
68
		} else {
69
			register_error(elgg_echo('user:password:fail:tooshort'));
70
		}
71
	} else {
72
		// no change
73
		return;
74
	}
75
76
	return false;
77
}
78
79
/**
80
 * Set a user's display name
81
 * Returns null if no change is required or input is not present in the form
82
 * Returns true or false indicating success or failure if change was needed
83
 *
84
 * @return bool|void
85
 * @since 1.8.0
86
 * @access private
87
 */
88
function _elgg_set_user_name() {
89
	$name = get_input('name');
90
	$user_guid = get_input('guid');
91
92
	if (!isset($name)) {
93
		return;
94
	}
95
96
	$name = strip_tags($name);
97
	if ($user_guid) {
98
		$user = get_user($user_guid);
0 ignored issues
show
It seems like $user_guid can also be of type string; however, parameter $guid of get_user() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

98
		$user = get_user(/** @scrutinizer ignore-type */ $user_guid);
Loading history...
99
	} else {
100
		$user = elgg_get_logged_in_user_entity();
101
	}
102
103
	if (elgg_strlen($name) > 50) {
104
		register_error(elgg_echo('user:name:fail'));
105
		return false;
106
	}
107
108
	if ($user && $user->canEdit() && $name) {
109
		if ($name != $user->name) {
110
			$user->name = $name;
111
			if ($user->save()) {
112
				system_message(elgg_echo('user:name:success'));
113
				return true;
114
			} else {
115
				register_error(elgg_echo('user:name:fail'));
116
			}
117
		} else {
118
			// no change
119
			return;
120
		}
121
	} else {
122
		register_error(elgg_echo('user:name:fail'));
123
	}
124
	return false;
125
}
126
127
/**
128
 * Set a user's username
129
 * Returns null if no change is required or input is not present in the form
130
 * Returns true or false indicating success or failure if change was needed
131
 *
132
 * @return bool|void
133
 *
134
 * @since 3.0
135
 *
136
 * @access private
137
 */
138
function _elgg_set_user_username() {
139
	$username = get_input('username');
140
	$user_guid = get_input('guid');
141
142
	if (!isset($username)) {
143
		return;
144
	}
145
146
	if (!elgg_is_admin_logged_in()) {
147
		return;
148
	}
149
150
	$user = get_user($user_guid);
151
	if (empty($user)) {
152
		return;
153
	}
154
155
	if ($user->username === $username) {
156
		return;
157
	}
158
159
	// check if username is valid and does not exist
160
	try {
161
		if (validate_username($username)) {
162
			$found = false;
163
			// make sure we can check every user (even unvalidated)
164
			$hidden = access_show_hidden_entities(true);
165
			if (get_user_by_username($username)) {
166
				$found = true;
167
			}
168
			// restore access settings
169
			access_show_hidden_entities($hidden);
170
171
			if ($found) {
172
				register_error(elgg_echo('registration:userexists'));
173
				return false;
174
			}
175
		}
176
	} catch (Exception $e) {
177
		register_error($e->getMessage());
178
		return false;
179
	}
180
181
	$user->username = $username;
182
	if ($user->save()) {
183
		// correctly forward after after a username change
184
		elgg_register_plugin_hook_handler('forward', 'all', function() use ($username) {
185
			return "settings/user/$username";
186
		});
187
		system_message(elgg_echo('user:username:success'));
188
		return true;
189
	}
190
191
	register_error(elgg_echo('user:username:fail'));
192
	return false;
193
}
194
195
/**
196
 * Set a user's language
197
 * Returns null if no change is required or input is not present in the form
198
 * Returns true or false indicating success or failure if change was needed
199
 *
200
 * @return bool|void
201
 * @since 1.8.0
202
 * @access private
203
 */
204
function _elgg_set_user_language() {
205
	$language = get_input('language');
206
	$user_guid = get_input('guid');
207
208
	if (!isset($language)) {
209
		return;
210
	}
211
212
	if ($user_guid) {
213
		$user = get_user($user_guid);
0 ignored issues
show
It seems like $user_guid can also be of type string; however, parameter $guid of get_user() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

213
		$user = get_user(/** @scrutinizer ignore-type */ $user_guid);
Loading history...
214
	} else {
215
		$user = elgg_get_logged_in_user_entity();
216
	}
217
218
	if ($user && $language) {
219
		if (strcmp($language, $user->language) != 0) {
220
			$user->language = $language;
221
			if ($user->save()) {
222
				system_message(elgg_echo('user:language:success'));
223
				return true;
224
			} else {
225
				register_error(elgg_echo('user:language:fail'));
226
			}
227
		} else {
228
			// no change
229
			return;
230
		}
231
	} else {
232
		register_error(elgg_echo('user:language:fail'));
233
	}
234
	return false;
235
}
236
237
/**
238
 * Set a user's email address
239
 * Returns null if no change is required or input is not present in the form
240
 * Returns true or false indicating success or failure if change was needed
241
 *
242
 * @return bool|void
243
 * @since 1.8.0
244
 * @access private
245
 */
246
function _elgg_set_user_email() {
247
	$email = get_input('email');
248
	$user_guid = get_input('guid');
249
250
	if (!isset($email)) {
251
		return;
252
	}
253
254
	if ($user_guid) {
255
		$user = get_user($user_guid);
0 ignored issues
show
It seems like $user_guid can also be of type string; however, parameter $guid of get_user() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

255
		$user = get_user(/** @scrutinizer ignore-type */ $user_guid);
Loading history...
256
	} else {
257
		$user = elgg_get_logged_in_user_entity();
258
	}
259
260
	if (!is_email_address($email)) {
261
		register_error(elgg_echo('email:save:fail'));
262
		return false;
263
	}
264
265
	if (!($user instanceof ElggUser)) {
266
		register_error(elgg_echo('email:save:fail'));
267
		return false;
268
	}
269
270
	if (strcmp($email, $user->email) === 0) {
271
		// no change
272
		return;
273
	}
274
275
	if (_elgg_config()->security_email_require_password && ($user->getGUID() === elgg_get_logged_in_user_guid())) {
276
		// validate password
277
		$pwd = get_input('email_password');
278
		$auth = elgg_authenticate($user->username, $pwd);
279
		if ($auth !== true) {
280
			register_error(elgg_echo('email:save:fail:password'));
281
			return false;
282
		}
283
	}
284
285
	if (!get_user_by_email($email)) {
286
		$user->email = $email;
287
		if ($user->save()) {
288
			system_message(elgg_echo('email:save:success'));
289
			return true;
290
		} else {
291
			register_error(elgg_echo('email:save:fail'));
292
		}
293
	} else {
294
		register_error(elgg_echo('registration:dupeemail'));
295
	}
296
297
	return false;
298
}
299
300
/**
301
 * Set a user's default access level
302
 * Returns null if no change is required or input is not present in the form
303
 * Returns true or false indicating success or failure if change was needed
304
 *
305
 * @return bool|void
306
 * @since 1.8.0
307
 * @access private
308
 */
309
function _elgg_set_user_default_access() {
310
311
	if (!_elgg_config()->allow_user_default_access) {
312
		return;
313
	}
314
315
	$default_access = get_input('default_access');
316
	$user_guid = get_input('guid');
317
318
	if ($user_guid) {
319
		$user = get_user($user_guid);
0 ignored issues
show
It seems like $user_guid can also be of type string; however, parameter $guid of get_user() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

319
		$user = get_user(/** @scrutinizer ignore-type */ $user_guid);
Loading history...
320
	} else {
321
		$user = elgg_get_logged_in_user_entity();
322
	}
323
324
	if ($user) {
325
		$current_default_access = $user->getPrivateSetting('elgg_default_access');
326
		if ($default_access !== $current_default_access) {
327
			if ($user->setPrivateSetting('elgg_default_access', $default_access)) {
328
				system_message(elgg_echo('user:default_access:success'));
329
				return true;
330
			} else {
331
				register_error(elgg_echo('user:default_access:failure'));
332
			}
333
		} else {
334
			// no change
335
			return;
336
		}
337
	} else {
338
		register_error(elgg_echo('user:default_access:failure'));
339
	}
340
341
	return false;
342
}
343
344
/**
345
 * Register menu items for the user settings page menu
346
 *
347
 * @param string         $hook   'register'
348
 * @param string         $type   'menu:page'
349
 * @param ElggMenuItem[] $return current return value
350
 * @param array          $params supplied params
351
 *
352
 * @return void|ElggMenuItem[]
353
 *
354
 * @access private
355
 * @since 3.0
356
 */
357
function _elgg_user_settings_menu_register($hook, $type, $return, $params) {
358 1
	$user = elgg_get_page_owner_entity();
359 1
	if (!$user) {
360
		return;
361
	}
362
363 1
	if (!elgg_in_context('settings')) {
364 1
		return;
365
	}
366
367
	$return[] = \ElggMenuItem::factory([
368
		'name' => '1_account',
369
		'text' => elgg_echo('usersettings:user:opt:linktext'),
370
		'href' => "settings/user/{$user->username}",
371
		'section' => 'configure',
372
	]);
373
374
	$return[] = \ElggMenuItem::factory([
375
		'name' => '1_plugins',
376
		'text' => elgg_echo('usersettings:plugins:opt:linktext'),
377
		'href' => '#',
378
		'section' => 'configure',
379
	]);
380
381
	$return[] = \ElggMenuItem::factory([
382
		'name' => '1_statistics',
383
		'text' => elgg_echo('usersettings:statistics:opt:linktext'),
384
		'href' => "settings/statistics/{$user->username}",
385
		'section' => 'configure',
386
	]);
387
388
	// register plugin user settings menu items
389
	$active_plugins = elgg_get_plugins();
390
391
	foreach ($active_plugins as $plugin) {
392
		$plugin_id = $plugin->getID();
393
		if (!elgg_view_exists("usersettings/$plugin_id/edit") && !elgg_view_exists("plugins/$plugin_id/usersettings")) {
394
			continue;
395
		}
396
397
		if (elgg_language_key_exists($plugin_id . ':usersettings:title')) {
398
			$title = elgg_echo($plugin_id . ':usersettings:title');
399
		} else {
400
			$title = $plugin->getDisplayName();
401
		}
402
403
		$return[] = \ElggMenuItem::factory([
404
			'name' => $plugin_id,
405
			'text' => $title,
406
			'href' => "settings/plugins/{$user->username}/$plugin_id",
407
			'parent_name' => '1_plugins',
408
			'section' => 'configure',
409
		]);
410
	}
411
412
	return $return;
413
}
414
415
/**
416
 * Prepares the page menu to strip out empty plugins menu item for user settings
417
 *
418
 * @param string $hook   prepare
419
 * @param string $type   menu:page
420
 * @param array  $value  array of menu items
421
 * @param array  $params menu related parameters
422
 *
423
 * @return array
424
 * @access private
425
 */
426
function _elgg_user_settings_menu_prepare($hook, $type, $value, $params) {
427 2
	if (empty($value)) {
428 1
		return $value;
429
	}
430
431 1
	if (!elgg_in_context("settings")) {
432 1
		return $value;
433
	}
434
435
	$configure = elgg_extract("configure", $value);
436
	if (empty($configure)) {
437
		return $value;
438
	}
439
440
	foreach ($configure as $index => $menu_item) {
441
		if (!($menu_item instanceof ElggMenuItem)) {
442
			continue;
443
		}
444
445
		if ($menu_item->getName() == "1_plugins") {
446
			if (!$menu_item->getChildren()) {
447
				// no need for this menu item if it has no children
448
				unset($value["configure"][$index]);
449
			}
450
		}
451
	}
452
453
	return $value;
454
}
455
456
/**
457
 * Initialize the user settings library
458
 *
459
 * @return void
460
 * @access private
461
 */
462
function _elgg_user_settings_init() {
463
464 31
	elgg_register_plugin_hook_handler('register', 'menu:page', '_elgg_user_settings_menu_register');
465 31
	elgg_register_plugin_hook_handler('prepare', 'menu:page', '_elgg_user_settings_menu_prepare');
466
467 31
	elgg_register_plugin_hook_handler('usersettings:save', 'user', '_elgg_set_user_language');
468 31
	elgg_register_plugin_hook_handler('usersettings:save', 'user', '_elgg_set_user_password');
469 31
	elgg_register_plugin_hook_handler('usersettings:save', 'user', '_elgg_set_user_default_access');
470 31
	elgg_register_plugin_hook_handler('usersettings:save', 'user', '_elgg_set_user_name');
471 31
	elgg_register_plugin_hook_handler('usersettings:save', 'user', '_elgg_set_user_username');
472 31
	elgg_register_plugin_hook_handler('usersettings:save', 'user', '_elgg_set_user_email');
473
474 31
	elgg_register_action("usersettings/save");
475
476
	// extend the account settings form
477 31
	elgg_extend_view('forms/account/settings', 'core/settings/account/username', 100);
478 31
	elgg_extend_view('forms/account/settings', 'core/settings/account/name', 100);
479 31
	elgg_extend_view('forms/account/settings', 'core/settings/account/password', 100);
480 31
	elgg_extend_view('forms/account/settings', 'core/settings/account/email', 100);
481 31
	elgg_extend_view('forms/account/settings', 'core/settings/account/language', 100);
482 31
	elgg_extend_view('forms/account/settings', 'core/settings/account/default_access', 100);
483 31
}
484
485
/**
486
 * @see \Elgg\Application::loadCore Do not do work here. Just register for events.
487
 */
488
return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {
489 18
	$events->registerHandler('init', 'system', '_elgg_user_settings_init');
490
};
491