Completed
Pull Request — development (#2528)
by Thorsten
15:29
created

ProfileOptions_Controller::action_account()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 82
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 32
nc 4
nop 0
dl 0
loc 82
rs 8.7769
ccs 0
cts 71
cp 0
crap 12
c 1
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
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 29 and the first side effect is on line 20.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
/**
4
 * This file has the primary job of showing and editing people's profiles.
5
 * It also allows the user to change some of their or another's preferences,
6
 * and such things
7
 *
8
 * @name      ElkArte Forum
9
 * @copyright ElkArte Forum contributors
10
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
11
 *
12
 * This file contains code covered by:
13
 * copyright:	2011 Simple Machines (http://www.simplemachines.org)
14
 * license:		BSD, See included LICENSE.TXT for terms and conditions.
15
 *
16
 * @version 1.1 beta 1
17
 *
18
 */
19
20
if (!defined('ELK'))
21
	die('No access...');
22
23
/**
24
 * ProfileOptions_Controller Class.
25
 * Does the job of showing and editing people's profiles.
26
 * Interface to buddy list, ignore list, notifications, authentication options, forum profile
27
 * account settings, etc
28
 */
29
class ProfileOptions_Controller extends Action_Controller
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
30
{
31
	/**
32
	 * Member id for the profile being viewed
33
	 * @var int
34
	 */
35
	private $_memID = 0;
36
37
	/**
38
	 * Called before all other methods when coming from the dispatcher or
39
	 * action class.
40
	 *
41
	 * - If you initiate the class outside of those methods, call this method.
42
	 * or setup the class yourself else a horrible fate awaits you
43
	 */
44
	public function pre_dispatch()
45
	{
46
		$this->_memID = currentMemberID();
47
	}
48
49
	/**
50
	 * Default method, if another action is not called by the menu.
51
	 *
52
	 * @see Action_Controller::action_index()
53
	 */
54
	public function action_index()
55
	{
56
		// action_account() is the first to do
57
		// these subactions are mostly routed to from the profile
58
		// menu though.
59
	}
60
61
	/**
62
	 * Show all the users buddies, as well as a add/delete interface.
63
	 */
64
	public function action_editBuddyIgnoreLists()
65
	{
66
		global $context, $txt, $modSettings;
67
68
		// Do a quick check to ensure people aren't getting here illegally!
69
		if (!$context['user']['is_owner'] || empty($modSettings['enable_buddylist']))
70
			Errors::instance()->fatal_lang_error('no_access', false);
71
72
		loadTemplate('ProfileOptions');
73
74
		// Can we email the user direct?
75
		$context['can_moderate_forum'] = allowedTo('moderate_forum');
76
		$context['can_send_email'] = allowedTo('send_email_to_members');
77
78
		$subActions = array(
79
			'buddies' => array($this, 'action_editBuddies'),
80
			'ignore' => array($this, 'action_editIgnoreList'),
81
		);
82
83
		// Set a subaction
84
		$action = new Action();
85
		$subAction = $action->initialize($subActions, 'buddies');
86
87
		// Create the tabs for the template.
88
		$context[$context['profile_menu_name']]['tab_data'] = array(
89
			'title' => $txt['editBuddyIgnoreLists'],
90
			'description' => $txt['buddy_ignore_desc'],
91
			'class' => 'profile',
92
			'tabs' => array(
93
				'buddies' => array(),
94
				'ignore' => array(),
95
			),
96
		);
97
98
		// Pass on to the actual function.
99
		$action->dispatch($subAction);
100
	}
101
102
	/**
103
	 * Show all the users buddies, as well as a add/delete interface.
104
	 *
105
	 * @uses template_editBuddies()
106
	 */
107
	public function action_editBuddies()
108
	{
109
		global $context, $user_profile, $memberContext;
110
111
		loadTemplate('ProfileOptions');
112
113
		// We want to view what we're doing :P
114
		$context['sub_template'] = 'editBuddies';
115
116
		// Use suggest to find the right buddies
117
		loadJavascriptFile('suggest.js', array('defer' => true));
118
119
		// For making changes!
120
		$buddiesArray = explode(',', $user_profile[$this->_memID]['buddy_list']);
121
		foreach ($buddiesArray as $k => $dummy)
122
		{
123
			if ($dummy === '')
124
				unset($buddiesArray[$k]);
125
		}
126
127
		// Removing a buddy?
128
		if (isset($this->_req->query->remove))
129
		{
130
			checkSession('get');
131
132
			call_integration_hook('integrate_remove_buddy', array($this->_memID));
133
134
			// Heh, I'm lazy, do it the easy way...
135
			foreach ($buddiesArray as $key => $buddy)
136
			{
137
				if ($buddy == (int) $this->_req->query->remove)
138
					unset($buddiesArray[$key]);
139
			}
140
141
			// Make the changes.
142
			$user_profile[$this->_memID]['buddy_list'] = implode(',', $buddiesArray);
143
			require_once(SUBSDIR . '/Members.subs.php');
144
			updateMemberData($this->_memID, array('buddy_list' => $user_profile[$this->_memID]['buddy_list']));
145
146
			// Redirect off the page because we don't like all this ugly query stuff to stick in the history.
147
			redirectexit('action=profile;area=lists;sa=buddies;u=' . $this->_memID);
148
		}
149
		// Or adding a new one
150
		elseif (isset($this->_req->post->new_buddy))
151
		{
152
			checkSession();
153
154
			// Prepare the string for extraction...
155
			$new_buddy = strtr(Util::htmlspecialchars($this->_req->post->new_buddy, ENT_QUOTES), array('&quot;' => '"'));
156
			preg_match_all('~"([^"]+)"~', $new_buddy, $matches);
157
			$new_buddies = array_unique(array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $new_buddy))));
158
159 View Code Duplication
			foreach ($new_buddies as $k => $dummy)
160
			{
161
				$new_buddies[$k] = strtr(trim($new_buddies[$k]), array('\'' => '&#039;'));
162
163
				if (strlen($new_buddies[$k]) == 0 || in_array($new_buddies[$k], array($user_profile[$this->_memID]['member_name'], $user_profile[$this->_memID]['real_name'])))
164
					unset($new_buddies[$k]);
165
			}
166
167
			call_integration_hook('integrate_add_buddies', array($this->_memID, &$new_buddies));
168
169 View Code Duplication
			if (!empty($new_buddies))
170
			{
171
				// Now find out the id_member of the buddy.
172
				require_once(SUBSDIR . '/ProfileOptions.subs.php');
173
				$buddiesArray = getBuddiesID($new_buddies);
174
175
				// Now update the current users buddy list.
176
				$user_profile[$this->_memID]['buddy_list'] = implode(',', $buddiesArray);
177
				require_once(SUBSDIR . '/Members.subs.php');
178
				updateMemberData($this->_memID, array('buddy_list' => $user_profile[$this->_memID]['buddy_list']));
179
			}
180
181
			// Back to the buddy list!
182
			redirectexit('action=profile;area=lists;sa=buddies;u=' . $this->_memID);
183
		}
184
185
		// Get all the users "buddies"...
186
		$buddies = array();
187
188 View Code Duplication
		if (!empty($buddiesArray))
189
		{
190
			require_once(SUBSDIR . '/Members.subs.php');
191
			$result = getBasicMemberData($buddiesArray, array('sort' => 'real_name', 'limit' => substr_count($user_profile[$this->_memID]['buddy_list'], ',') + 1));
192
			foreach ($result as $row)
193
				$buddies[] = $row['id_member'];
194
		}
195
196
		$context['buddy_count'] = count($buddies);
197
198
		// Load all the members up.
199
		loadMemberData($buddies, false, 'profile');
200
201
		// Setup the context for each buddy.
202
		$context['buddies'] = array();
203 View Code Duplication
		foreach ($buddies as $buddy)
204
		{
205
			loadMemberContext($buddy, true);
206
			$context['buddies'][$buddy] = $memberContext[$buddy];
207
		}
208
209
		call_integration_hook('integrate_view_buddies', array($this->_memID));
210
	}
211
212
	/**
213
	 * Allows the user to view their ignore list,
214
	 *
215
	 * - Provides the option to manage members on it.
216
	 */
217
	public function action_editIgnoreList()
218
	{
219
		global $context, $user_profile, $memberContext;
220
221
		loadTemplate('ProfileOptions');
222
223
		// We want to view what we're doing :P
224
		$context['sub_template'] = 'editIgnoreList';
225
		loadJavascriptFile('suggest.js', array('defer' => true));
226
227
		// For making changes!
228
		$ignoreArray = explode(',', $user_profile[$this->_memID]['pm_ignore_list']);
229
		foreach ($ignoreArray as $k => $dummy)
230
		{
231
			if ($dummy === '')
232
				unset($ignoreArray[$k]);
233
		}
234
235
		// Removing a member from the ignore list?
236
		if (isset($this->_req->query->remove))
237
		{
238
			checkSession('get');
239
240
			// Heh, I'm lazy, do it the easy way...
241
			foreach ($ignoreArray as $key => $id_remove)
242
			{
243
				if ($id_remove == (int) $this->_req->query->remove)
244
					unset($ignoreArray[$key]);
245
			}
246
247
			// Make the changes.
248
			$user_profile[$this->_memID]['pm_ignore_list'] = implode(',', $ignoreArray);
249
			require_once(SUBSDIR . '/Members.subs.php');
250
			updateMemberData($this->_memID, array('pm_ignore_list' => $user_profile[$this->_memID]['pm_ignore_list']));
251
252
			// Redirect off the page because we don't like all this ugly query stuff to stick in the history.
253
			redirectexit('action=profile;area=lists;sa=ignore;u=' . $this->_memID);
254
		}
255
		elseif (isset($this->_req->post->new_ignore))
256
		{
257
			checkSession();
258
259
			// Prepare the string for extraction...
260
			$new_ignore = strtr(Util::htmlspecialchars($this->_req->post->new_ignore, ENT_QUOTES), array('&quot;' => '"'));
261
			preg_match_all('~"([^"]+)"~', $new_ignore, $matches);
262
			$new_entries = array_unique(array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $new_ignore))));
263
264 View Code Duplication
			foreach ($new_entries as $k => $dummy)
265
			{
266
				$new_entries[$k] = strtr(trim($new_entries[$k]), array('\'' => '&#039;'));
267
268
				if (strlen($new_entries[$k]) == 0 || in_array($new_entries[$k], array($user_profile[$this->_memID]['member_name'], $user_profile[$this->_memID]['real_name'])))
269
					unset($new_entries[$k]);
270
			}
271
272 View Code Duplication
			if (!empty($new_entries))
273
			{
274
				// Now find out the id_member for the members in question.
275
				require_once(SUBSDIR . '/ProfileOptions.subs.php');
276
				$ignoreArray = getBuddiesID($new_entries, false);
277
278
				// Now update the current users buddy list.
279
				$user_profile[$this->_memID]['pm_ignore_list'] = implode(',', $ignoreArray);
280
				require_once(SUBSDIR . '/Members.subs.php');
281
				updateMemberData($this->_memID, array('pm_ignore_list' => $user_profile[$this->_memID]['pm_ignore_list']));
282
			}
283
284
			// Back to the list of pitiful people!
285
			redirectexit('action=profile;area=lists;sa=ignore;u=' . $this->_memID);
286
		}
287
288
		// Initialise the list of members we're ignoring.
289
		$ignored = array();
290
291 View Code Duplication
		if (!empty($ignoreArray))
292
		{
293
			require_once(SUBSDIR . '/Members.subs.php');
294
			$result = getBasicMemberData($ignoreArray, array('sort' => 'real_name', 'limit' => substr_count($user_profile[$this->_memID]['pm_ignore_list'], ',') + 1));
295
			foreach ($result as $row)
296
				$ignored[] = $row['id_member'];
297
		}
298
299
		$context['ignore_count'] = count($ignored);
300
301
		// Load all the members up.
302
		loadMemberData($ignored, false, 'profile');
303
304
		// Setup the context for each buddy.
305
		$context['ignore_list'] = array();
306
		foreach ($ignored as $ignore_member)
307
		{
308
			loadMemberContext($ignore_member);
309
			$context['ignore_list'][$ignore_member] = $memberContext[$ignore_member];
310
		}
311
	}
312
313
	/**
314
	 * Allows the user to see or change their account info.
315
	 */
316
	public function action_account()
317
	{
318
		global $modSettings, $context, $txt;
319
320
		loadTemplate('ProfileOptions');
321
		$this->loadThemeOptions();
322
323
		if (allowedTo(array('profile_identity_own', 'profile_identity_any')))
324
			loadCustomFields($this->_memID, 'account');
325
326
		$context['sub_template'] = 'edit_options';
327
		$context['page_desc'] = $txt['account_info'];
328
329
		if (!empty($modSettings['enableOTP']))
330
		{
331
			setupProfileContext(
332
				array(
333
					'member_name', 'real_name', 'date_registered', 'posts', 'lngfile', 'hr',
334
					'id_group', 'hr',
335
					'email_address', 'hide_email', 'show_online', 'hr',
336
					'passwrd1', 'passwrd2', 'hr',
337
					'secret_question', 'secret_answer', 'hr',
338
					'enable_otp', 'otp_secret', 'hr'
339
				),
340
				'account'
341
			);
342
343
			loadJavascriptFile('qrcode.js');
344
			addInlineJavascript('
345
				var secret = document.getElementById("otp_secret").value;
346
347
				if (secret)
348
				{
349
					var qrcode = new QRCode("qrcode", {
350
						text: "otpauth://totp/' . $context['forum_name'] . '?secret=" + secret,
351
						width: 80,
352
						height: 80,
353
						colorDark : "#000000",
354
						colorLight : "#ffffff",
355
					});
356
				}
357
358
				/**
359
				* Generate a secret key for Google Authenticator
360
				*/
361
				function generateSecret() {
362
					var text = "",
363
						possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
364
						qr = document.getElementById("qrcode");
365
366
					for (var i = 0; i < 16; i++)
367
						text += possible.charAt(Math.floor(Math.random() * possible.length));
368
369
					document.getElementById("otp_secret").value = text;
370
371
					while (qr.firstChild) {
372
						qr.removeChild(qr.firstChild);
373
					}
374
375
					var qrcode = new QRCode("qrcode", {
376
						text: "otpauth://totp/' . $context['forum_name'] . '?secret=" + text,
377
						width: 80,
378
						height: 80,
379
						colorDark: "#000000",
380
						colorLight: "#ffffff",
381
					});
382
				}', true);
383
		}
384
		else
385
		{
386
			setupProfileContext(
387
				array(
388
					'member_name', 'real_name', 'date_registered', 'posts', 'lngfile', 'hr',
389
					'id_group', 'hr',
390
					'email_address', 'hide_email', 'show_online', 'hr',
391
					'passwrd1', 'passwrd2', 'hr',
392
					'secret_question', 'secret_answer', 'hr',
393
				),
394
				'account'
395
			);
396
		}
397
	}
398
	
399
400
	/**
401
	 * Allow the user to change the forum options in their profile.
402
	 */
403
	public function action_forumProfile()
404
	{
405
		global $context, $txt;
406
407
		loadTemplate('ProfileOptions');
408
		$this->loadThemeOptions();
409
410
		if (allowedTo(array('profile_extra_own', 'profile_extra_any')))
411
			loadCustomFields($this->_memID, 'forumprofile');
412
413
		$context['sub_template'] = 'edit_options';
414
		$context['page_desc'] = replaceBasicActionUrl($txt['forumProfile_info']);
415
		$context['show_preview_button'] = true;
416
417
		setupProfileContext(
418
			array(
419
				'avatar_choice', 'hr',
420
				'bday1', 'usertitle', 'hr',
421
				'signature', 'hr',
422
				'karma_good', 'hr',
423
				'website_title', 'website_url',
424
			),
425
			'forum'
426
		);
427
	}
428
429
	/**
430
	 * Allow the edit of *someone else's* personal message settings.
431
	 */
432
	public function action_pmprefs()
433
	{
434
		global $context, $txt;
435
436
		$this->loadThemeOptions();
437
		loadCustomFields($this->_memID, 'pmprefs');
438
		loadTemplate('ProfileOptions');
439
440
		$context['sub_template'] = 'edit_options';
441
		$context['page_desc'] = $txt['pm_settings_desc'];
442
443
		// Setup the profile context and call the 'integrate_pmprefs_profile_fields' hook
444
		setupProfileContext(
445
			array(
446
				'receive_from',
447
				'hr',
448
				'pm_settings',
449
			),
450
			'pmprefs'
451
		);
452
	}
453
454
	/**
455
	 * Allow the user to pick a theme.
456
	 *
457
	 */
458
	public function action_themepick()
459
	{
460
		global $txt, $context;
461
462
		$this->loadThemeOptions();
463
464
		if (allowedTo(array('profile_extra_own', 'profile_extra_any')))
465
			loadCustomFields($this->_memID, 'theme');
466
467
		loadTemplate('ProfileOptions');
468
469
		$context['sub_template'] = 'edit_options';
470
		$context['page_desc'] = $txt['theme_info'];
471
472
		setupProfileContext(
473
			array(
474
				'id_theme', 'smiley_set', 'hr',
475
				'time_format', 'time_offset', 'hr',
476
				'theme_settings',
477
			),
478
			'themepick'
479
		);
480
	}
481
482
	/**
483
	 * Changing authentication method?
484
	 * Only appropriate for people using OpenID.
485
	 *
486
	 * @param bool $saving = false
487
	 */
488
	public function action_authentication($saving = false)
0 ignored issues
show
Coding Style introduced by
action_authentication uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
489
	{
490
		global $context, $cur_profile, $post_errors, $modSettings;
491
492
		loadLanguage('Login');
493
		loadTemplate('ProfileOptions');
494
495
		// We are saving?
496
		if ($saving)
497
		{
498
			// Moving to password passed authentication?
499
			if ($this->_req->post->authenticate === 'passwd')
500
			{
501
				// Didn't enter anything?
502
				if ($this->_req->post->passwrd1 === '')
503
					$post_errors[] = 'no_password';
504
				// Do the two entries for the password even match?
505
				elseif (!isset($this->_req->post->passwrd2) || $this->_req->post->passwrd1 != $this->_req->post->passwrd2)
506
					$post_errors[] = 'bad_new_password';
507
				// Is it valid?
508
				else
509
				{
510
					require_once(SUBSDIR . '/Auth.subs.php');
511
					$passwordErrors = validatePassword($this->_req->post->passwrd1, $cur_profile['member_name'], array($cur_profile['real_name'], $cur_profile['email_address']));
512
513
					// Were there errors?
514
					if ($passwordErrors != null)
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $passwordErrors of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
515
						$post_errors[] = 'password_' . $passwordErrors;
516
				}
517
518
				if (empty($post_errors))
519
				{
520
					// Integration?
521
					call_integration_hook('integrate_reset_pass', array($cur_profile['member_name'], $cur_profile['member_name'], $this->_req->post->passwrd1));
522
523
					// Go then.
524
					require_once(SUBSDIR . '/Auth.subs.php');
525
					$new_pass = $this->_req->post->passwrd1;
526
					$passwd = validateLoginPassword($new_pass, '', $cur_profile['member_name'], true);
527
528
					// Do the important bits.
529
					require_once(SUBSDIR . '/Members.subs.php');
530
					updateMemberData($this->_memID, array('openid_uri' => '', 'passwd' => $passwd));
531
					if ($context['user']['is_owner'])
532
					{
533
						setLoginCookie(60 * $modSettings['cookieTime'], $this->_memID, hash('sha256', $new_pass . $cur_profile['password_salt']));
534
						redirectexit('action=profile;area=authentication;updated');
535
					}
536
					else
537
						redirectexit('action=profile;u=' . $this->_memID);
538
				}
539
540
				return true;
541
			}
542
			// Not right yet!
543
			elseif ($this->_req->post->authenticate === 'openid' && !empty($this->_req->post->openid_identifier))
544
			{
545
				require_once(SUBSDIR . '/OpenID.subs.php');
546
				require_once(SUBSDIR . '/Members.subs.php');
547
548
				$openID = new OpenID();
549
				$this->_req->post->openid_identifier = $openID->canonize($this->_req->post->openid_identifier);
550
551
				if (memberExists($this->_req->post->openid_identifier))
552
					$post_errors[] = 'openid_in_use';
553
				elseif (empty($post_errors))
554
				{
555
					// Authenticate using the new OpenID URI first to make sure they didn't make a mistake.
556
					if ($context['user']['is_owner'])
557
					{
558
						$_SESSION['new_openid_uri'] = $this->_req->post->openid_identifier;
559
						$openID->validate($this->_req->post->openid_identifier, false, null, 'change_uri');
560
					}
561
					else
562
						updateMemberData($this->_memID, array('openid_uri' => $this->_req->post->openid_identifier));
563
				}
564
			}
565
		}
566
567
		// Some stuff for the template
568
		$context['member']['openid_uri'] = $cur_profile['openid_uri'];
569
		$context['auth_method'] = empty($cur_profile['openid_uri']) ? 'password' : 'openid';
570
		$context['sub_template'] = 'authentication_method';
571
		loadJavascriptFile('register.js');
572
	}
573
574
	/**
575
	 * Display the notifications and settings for changes.
576
	 */
577
	public function action_notification()
578
	{
579
		global $txt, $scripturl, $user_profile, $context, $modSettings;
580
581
		loadTemplate('ProfileOptions');
582
583
		// Going to need this for the list.
584
		require_once(SUBSDIR . '/Boards.subs.php');
585
		require_once(SUBSDIR . '/Topic.subs.php');
586
		require_once(SUBSDIR . '/Profile.subs.php');
587
588
		$context['mention_types'] = getMemberNotificationsProfile($this->_memID);
589
590
		// Fine, start with the board list.
591
		$listOptions = array(
592
			'id' => 'board_notification_list',
593
			'width' => '100%',
594
			'no_items_label' => $txt['notifications_boards_none'] . '<br /><br />' . $txt['notifications_boards_howto'],
595
			'no_items_align' => 'left',
596
			'base_href' => $scripturl . '?action=profile;u=' . $this->_memID . ';area=notification',
597
			'default_sort_col' => 'board_name',
598
			'get_items' => array(
599
				'function' => array($this, 'list_getBoardNotifications'),
600
				'params' => array(
601
					$this->_memID,
602
				),
603
			),
604
			'columns' => array(
605
				'board_name' => array(
606
					'header' => array(
607
						'value' => $txt['notifications_boards'],
608
						'class' => 'lefttext',
609
					),
610
					'data' => array(
611
						'function' => function ($board) {
612
							global $txt;
613
614
							$link = $board['link'];
615
616
							if ($board['new'])
617
								$link .= ' <a href="' . $board['href'] . '"><span class="new_posts">' . $txt['new'] . '</span></a>';
618
619
							return $link;
620
						},
621
					),
622
					'sort' => array(
623
						'default' => 'name',
624
						'reverse' => 'name DESC',
625
					),
626
				),
627
				'delete' => array(
628
					'header' => array(
629
						'value' => '<input type="checkbox" onclick="invertAll(this, this.form);" />',
630
						'class' => 'centertext',
631
						'style' => 'width:4%;',
632
					),
633
					'data' => array(
634
						'sprintf' => array(
635
							'format' => '<input type="checkbox" name="notify_boards[]" value="%1$d" %2$s />',
636
							'params' => array(
637
								'id' => false,
638
								'checked' => false,
639
							),
640
						),
641
						'class' => 'centertext',
642
					),
643
				),
644
			),
645
			'form' => array(
646
				'href' => $scripturl . '?action=profile;area=notification',
647
				'include_sort' => true,
648
				'include_start' => true,
649
				'hidden_fields' => array(
650
					'u' => $this->_memID,
651
					'sa' => $context['menu_item_selected'],
652
					$context['session_var'] => $context['session_id'],
653
				),
654
				'token' => $context['token_check'],
655
			),
656
			'additional_rows' => array(
657
				array(
658
					'class' => 'submitbutton',
659
					'position' => 'bottom_of_list',
660
					'value' => '
661
						<input type="submit" name="edit_notify_boards" value="' . $txt['notifications_boards_update'] . '" />
662
						<input type="hidden" name="save" value="save" />',
663
				),
664
				array(
665
					'position' => 'after_title',
666
					'value' => getBoardNotificationsCount($this->_memID) == 0 ? $txt['notifications_boards_none'] . '<br />' . $txt['notifications_boards_howto'] : $txt['notifications_boards_current'],
667
				),
668
			),
669
		);
670
671
		// Create the board notification list.
672
		createList($listOptions);
673
674
		// Now do the topic notifications.
675
		$listOptions = array(
676
			'id' => 'topic_notification_list',
677
			'width' => '100%',
678
			'items_per_page' => $modSettings['defaultMaxMessages'],
679
			'no_items_label' => $txt['notifications_topics_none'] . '<br /><br />' . $txt['notifications_topics_howto'],
680
			'no_items_align' => 'left',
681
			'base_href' => $scripturl . '?action=profile;u=' . $this->_memID . ';area=notification',
682
			'default_sort_col' => 'last_post',
683
			'get_items' => array(
684
				'function' => array($this, 'list_getTopicNotifications'),
685
				'params' => array(
686
					$this->_memID,
687
				),
688
			),
689
			'get_count' => array(
690
				'function' => array($this, 'list_getTopicNotificationCount'),
691
				'params' => array(
692
					$this->_memID,
693
				),
694
			),
695
			'columns' => array(
696
				'subject' => array(
697
					'header' => array(
698
						'value' => $txt['notifications_topics'],
699
						'class' => 'lefttext',
700
					),
701
					'data' => array(
702
						'function' => function ($topic) {
703
							global $txt;
704
705
							$link = $topic['link'];
706
707
							if ($topic['new'])
708
								$link .= ' <a href="' . $topic['new_href'] . '"><span class="new_posts">' . $txt['new'] . '</span></a>';
709
710
							$link .= '<br /><span class="smalltext"><em>' . $txt['in'] . ' ' . $topic['board_link'] . '</em></span>';
711
712
							return $link;
713
						},
714
					),
715
					'sort' => array(
716
						'default' => 'ms.subject',
717
						'reverse' => 'ms.subject DESC',
718
					),
719
				),
720
				'started_by' => array(
721
					'header' => array(
722
						'value' => $txt['started_by'],
723
						'class' => 'lefttext',
724
					),
725
					'data' => array(
726
						'db' => 'poster_link',
727
					),
728
					'sort' => array(
729
						'default' => 'real_name_col',
730
						'reverse' => 'real_name_col DESC',
731
					),
732
				),
733
				'last_post' => array(
734
					'header' => array(
735
						'value' => $txt['last_post'],
736
							'class' => 'lefttext',
737
					),
738
					'data' => array(
739
						'sprintf' => array(
740
							'format' => '<span class="smalltext">%1$s<br />' . $txt['by'] . ' %2$s</span>',
741
							'params' => array(
742
								'updated' => false,
743
								'poster_updated_link' => false,
744
							),
745
						),
746
					),
747
					'sort' => array(
748
						'default' => 'ml.id_msg DESC',
749
						'reverse' => 'ml.id_msg',
750
					),
751
				),
752
				'delete' => array(
753
					'header' => array(
754
						'value' => '<input type="checkbox" onclick="invertAll(this, this.form);" />',
755
						'class' => 'centertext',
756
						'style' => 'width:4%;',
757
					),
758
					'data' => array(
759
						'sprintf' => array(
760
							'format' => '<input type="checkbox" name="notify_topics[]" value="%1$d" />',
761
							'params' => array(
762
								'id' => false,
763
							),
764
						),
765
						'class' => 'centertext',
766
					),
767
				),
768
			),
769
			'form' => array(
770
				'href' => $scripturl . '?action=profile;area=notification',
771
				'include_sort' => true,
772
				'include_start' => true,
773
				'hidden_fields' => array(
774
					'u' => $this->_memID,
775
					'sa' => $context['menu_item_selected'],
776
					$context['session_var'] => $context['session_id'],
777
				),
778
				'token' => $context['token_check'],
779
			),
780
			'additional_rows' => array(
781
				array(
782
					'class' => 'submitbutton',
783
					'position' => 'bottom_of_list',
784
					'value' => '
785
						<input type="submit" name="edit_notify_topics" value="' . $txt['notifications_update'] . '" />
786
						<input type="hidden" name="save" value="save" />',
787
				),
788
			),
789
		);
790
791
		// Create the notification list.
792
		createList($listOptions);
793
794
		// What options are set?
795
		$context['member'] += array(
796
			'notify_announcements' => $user_profile[$this->_memID]['notify_announcements'],
797
			'notify_send_body' => $user_profile[$this->_memID]['notify_send_body'],
798
			'notify_types' => $user_profile[$this->_memID]['notify_types'],
799
			'notify_regularity' => $user_profile[$this->_memID]['notify_regularity'],
800
		);
801
802
		$this->loadThemeOptions();
803
	}
804
805
	/**
806
	 * Callback for createList() in action_notification()
807
	 *
808
	 * - Retrieve topic notifications count.
809
	 *
810
	 * @param int $memID id_member the id of the member who's notifications we are loading
811
	 * @return integer
812
	 */
813
	public function list_getTopicNotificationCount($memID)
814
	{
815
		// Topic notifications count, for the list
816
		return topicNotificationCount($memID);
817
	}
818
819
	/**
820
	 * Callback for createList() in action_notification()
821
	 *
822
	 * @param int $start The item to start with (for pagination purposes)
823
	 * @param int $items_per_page  The number of items to show per page
824
	 * @param string $sort A string indicating how to sort the results
825
	 * @param int $memID id_member
826
	 * @return mixed array of topic notifications
827
	 */
828
	public function list_getTopicNotifications($start, $items_per_page, $sort, $memID)
829
	{
830
		// Topic notifications, for the list
831
		return topicNotifications($start, $items_per_page, $sort, $memID);
832
	}
833
834
	/**
835
	 * Callback for createList() in action_notification()
836
	 *
837
	 * @uses template_ignoreboards()
838
	 * @param int $start The item to start with (for pagination purposes)
839
	 * @param int $items_per_page  The number of items to show per page
840
	 * @param string $sort A string indicating how to sort the results
841
	 * @param int $memID id_member
842
	 * @return mixed[] array of board notifications
843
	 */
844
	public function list_getBoardNotifications($start, $items_per_page, $sort, $memID)
845
	{
846
		// Return boards you see and their notification status for the list
847
		return boardNotifications($start, $items_per_page, $sort, $memID);
848
	}
849
850
	/**
851
	 * Allows the user to see the list of their ignored boards.
852
	 * (and un-ignore them)
853
	 */
854
	public function action_ignoreboards()
855
	{
856
		global $context, $modSettings, $cur_profile;
857
858
		// Have the admins enabled this option?
859
		if (empty($modSettings['allow_ignore_boards']))
860
			Errors::instance()->fatal_lang_error('ignoreboards_disallowed', 'user');
861
862
		loadTemplate('ProfileOptions');
863
864
		$context['sub_template'] = 'ignoreboards';
865
		require_once(SUBSDIR . '/Boards.subs.php');
866
		$context += getBoardList(array('not_redirection' => true, 'ignore' => !empty($cur_profile['ignore_boards']) ? explode(',', $cur_profile['ignore_boards']) : array()));
867
868
		// Include a list of boards per category for easy toggling.
869 View Code Duplication
		foreach ($context['categories'] as $cat => &$category)
870
		{
871
			$context['boards_in_category'][$cat] = count($category['boards']);
872
			$category['child_ids'] = array_keys($category['boards']);
873
		}
874
875
		$this->loadThemeOptions();
876
	}
877
878
	/**
879
	 * Function to allow the user to choose group membership etc...
880
	 */
881
	public function action_groupMembership()
882
	{
883
		global $txt, $user_profile, $context;
884
885
		loadTemplate('ProfileOptions');
886
		$context['sub_template'] = 'groupMembership';
887
888
		$curMember = $user_profile[$this->_memID];
889
		$context['primary_group'] = $curMember['id_group'];
890
891
		// Can they manage groups?
892
		$context['can_manage_membergroups'] = allowedTo('manage_membergroups');
893
		$context['can_manage_protected'] = allowedTo('admin_forum');
894
		$context['can_edit_primary'] = $context['can_manage_protected'];
895
		$context['update_message'] = isset($this->_req->query->msg) && isset($txt['group_membership_msg_' . $this->_req->query->msg]) ? $txt['group_membership_msg_' . $this->_req->query->msg] : '';
896
897
		// Get all the groups this user is a member of.
898
		$groups = explode(',', $curMember['additional_groups']);
899
		$groups[] = $curMember['id_group'];
900
901
		// Ensure the query doesn't croak!
902
		if (empty($groups))
903
			$groups = array(0);
904
905
		// Just to be sure...
906
		$groups = array_map('intval', $groups);
907
908
		// Get all the membergroups they can join.
909
		require_once(SUBSDIR . '/ProfileOptions.subs.php');
910
		$context['groups'] = loadMembergroupsJoin($groups, $this->_memID);
911
912
		// Add registered members on the end.
913
		$context['groups']['member'][0] = array(
914
			'id' => 0,
915
			'name' => $txt['regular_members'],
916
			'desc' => $txt['regular_members_desc'],
917
			'type' => 0,
918
			'is_primary' => $context['primary_group'] == 0 ? true : false,
919
			'can_be_primary' => true,
920
			'can_leave' => 0,
921
		);
922
923
		// No changing primary one unless you have enough groups!
924
		if (count($context['groups']['member']) < 2)
925
			$context['can_edit_primary'] = false;
926
927
		// In the special case that someone is requesting membership of a group, setup some special context vars.
928
		if (isset($this->_req->query->request)
929
			&& isset($context['groups']['available'][(int) $this->_req->query->request])
930
			&& $context['groups']['available'][(int) $this->_req->query->request]['type'] == 2)
931
		{
932
			$context['group_request'] = $context['groups']['available'][(int) $this->_req->query->request];
933
		}
934
	}
935
936
	/**
937
	 * This function actually makes all the group changes
938
	 *
939
	 * @return string
940
	 */
941
	public function action_groupMembership2()
0 ignored issues
show
Coding Style introduced by
action_groupMembership2 uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
942
	{
943
		global $context, $user_profile, $modSettings, $scripturl, $language;
944
945
		// Let's be extra cautious...
946
		if (!$context['user']['is_owner'] || empty($modSettings['show_group_membership']))
947
			isAllowedTo('manage_membergroups');
948
949
		$group_id = $this->_req->getPost('gid', 'intval', $this->_req->getQuery('gid', 'intval', null));
950
951 View Code Duplication
		if (!isset($group_id) && !isset($this->_req->post->primary))
952
			Errors::instance()->fatal_lang_error('no_access', false);
953
954
		// GID may be from a link or a form
955
		checkSession(isset($this->_req->query->gid) ? 'get' : 'post');
956
957
		require_once(SUBSDIR . '/Membergroups.subs.php');
958
959
		$old_profile = &$user_profile[$this->_memID];
960
		$context['can_manage_membergroups'] = allowedTo('manage_membergroups');
961
		$context['can_manage_protected'] = allowedTo('admin_forum');
962
963
		// By default the new primary is the old one.
964
		$newPrimary = $old_profile['id_group'];
965
		$addGroups = array_flip(explode(',', $old_profile['additional_groups']));
966
		$canChangePrimary = $old_profile['id_group'] == 0 ? 1 : 0;
967
		$changeType = isset($this->_req->post->primary) ? 'primary' : (isset($this->_req->post->req) ? 'request' : 'free');
968
969
		// One way or another, we have a target group in mind...
970
		$group_id = isset($group_id) ? $group_id : (int) $this->_req->post->primary;
971
		$foundTarget = $changeType === 'primary' && $group_id == 0 ? true : false;
972
973
		// Sanity check!!
974
		if ($group_id == 1)
975
			isAllowedTo('admin_forum');
976
977
		// What ever we are doing, we need to determine if changing primary is possible!
978
		$groups_details = membergroupsById(array($group_id, $old_profile['id_group']), 0, true);
979
980
		// Protected groups require proper permissions!
981
		if ($group_id != 1 && $groups_details[$group_id]['group_type'] == 1)
982
			isAllowedTo('admin_forum');
983
984
		foreach ($groups_details as $key => $row)
985
		{
986
			// Is this the new group?
987
			if ($row['id_group'] == $group_id)
988
			{
989
				$foundTarget = true;
990
				$group_name = $row['group_name'];
991
992
				// Does the group type match what we're doing - are we trying to request a non-requestable group?
993
				if ($changeType === 'request' && $row['group_type'] != 2)
994
					Errors::instance()->fatal_lang_error('no_access', false);
995
				// What about leaving a requestable group we are not a member of?
996
				elseif ($changeType === 'free' && $row['group_type'] == 2 && $old_profile['id_group'] != $row['id_group'] && !isset($addGroups[$row['id_group']]))
997
					Errors::instance()->fatal_lang_error('no_access', false);
998
				elseif ($changeType === 'free' && $row['group_type'] != 3 && $row['group_type'] != 2)
999
					Errors::instance()->fatal_lang_error('no_access', false);
1000
1001
				// We can't change the primary group if this is hidden!
1002
				if ($row['hidden'] == 2)
1003
					$canChangePrimary = false;
1004
			}
1005
1006
			// If this is their old primary, can we change it?
1007 View Code Duplication
			if ($row['id_group'] == $old_profile['id_group'] && ($row['group_type'] > 1 || $context['can_manage_membergroups']) && $canChangePrimary !== false)
1008
				$canChangePrimary = 1;
1009
1010
			// If we are not doing a force primary move, don't do it automatically if current primary is not 0.
1011
			if ($changeType != 'primary' && $old_profile['id_group'] != 0)
1012
				$canChangePrimary = false;
1013
1014
			// If this is the one we are acting on, can we even act?
1015 View Code Duplication
			if ((!$context['can_manage_protected'] && $row['group_type'] == 1) || (!$context['can_manage_membergroups'] && $row['group_type'] == 0))
1016
				$canChangePrimary = false;
1017
		}
1018
1019
		// Didn't find the target?
1020
		if (!$foundTarget)
1021
			Errors::instance()->fatal_lang_error('no_access', false);
1022
1023
		// Final security check, don't allow users to promote themselves to admin.
1024
		require_once(SUBSDIR . '/ProfileOptions.subs.php');
1025
		if ($context['can_manage_membergroups'] && !allowedTo('admin_forum'))
1026
		{
1027
			$disallow = checkMembergroupChange($group_id);
1028
			if ($disallow)
1029
				isAllowedTo('admin_forum');
1030
		}
1031
1032
		// If we're requesting, add the note then return.
1033
		if ($changeType === 'request')
1034
		{
1035
			if (logMembergroupRequest($group_id, $this->_memID))
1036
				Errors::instance()->fatal_lang_error('profile_error_already_requested_group');
1037
1038
			// Send an email to all group moderators etc.
1039
			require_once(SUBSDIR . '/Mail.subs.php');
1040
1041
			// Do we have any group moderators?
1042
			require_once(SUBSDIR . '/Membergroups.subs.php');
1043
			$moderators = array_keys(getGroupModerators($group_id));
1044
1045
			// Otherwise this is the backup!
1046
			if (empty($moderators))
1047
			{
1048
				require_once(SUBSDIR . '/Members.subs.php');
1049
				$moderators = membersAllowedTo('manage_membergroups');
1050
			}
1051
1052
			if (!empty($moderators))
1053
			{
1054
				require_once(SUBSDIR . '/Members.subs.php');
1055
				$members = getBasicMemberData($moderators, array('preferences' => true, 'sort' => 'lngfile'));
1056
1057
				foreach ($members as $member)
1058
				{
1059
					if ($member['notify_types'] != 4)
1060
						continue;
1061
1062
					// Check whether they are interested.
1063 View Code Duplication
					if (!empty($member['mod_prefs']))
1064
					{
1065
						list (,, $pref_binary) = explode('|', $member['mod_prefs']);
1066
						if (!($pref_binary & 4))
1067
							continue;
1068
					}
1069
1070
					$replacements = array(
1071
						'RECPNAME' => $member['member_name'],
1072
						'APPYNAME' => $old_profile['member_name'],
1073
						'GROUPNAME' => $group_name,
0 ignored issues
show
Bug introduced by
The variable $group_name does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1074
						'REASON' => $this->_req->post->reason,
1075
						'MODLINK' => $scripturl . '?action=moderate;area=groups;sa=requests',
1076
					);
1077
1078
					$emaildata = loadEmailTemplate('request_membership', $replacements, empty($member['lngfile']) || empty($modSettings['userLanguage']) ? $language : $member['lngfile']);
1079
					sendmail($member['email_address'], $emaildata['subject'], $emaildata['body'], null, null, false, 2);
1080
				}
1081
			}
1082
1083
			return $changeType;
1084
		}
1085
		// Otherwise we are leaving/joining a group.
1086
		elseif ($changeType === 'free')
1087
		{
1088
			// Are we leaving?
1089
			if ($old_profile['id_group'] == $group_id || isset($addGroups[$group_id]))
1090
			{
1091
				if ($old_profile['id_group'] == $group_id)
1092
					$newPrimary = 0;
1093
				else
1094
					unset($addGroups[$group_id]);
1095
			}
1096
			// ... if not, must be joining.
1097
			else
1098
			{
1099
				// Can we change the primary, and do we want to?
1100
				if ($canChangePrimary)
0 ignored issues
show
Bug Best Practice introduced by
The expression $canChangePrimary of type false|integer is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1101
				{
1102
					if ($old_profile['id_group'] != 0)
1103
						$addGroups[$old_profile['id_group']] = -1;
1104
					$newPrimary = $group_id;
1105
				}
1106
				// Otherwise it's an additional group...
1107
				else
1108
					$addGroups[$group_id] = -1;
1109
			}
1110
		}
1111
		// Finally, we must be setting the primary.
1112
		elseif ($canChangePrimary)
0 ignored issues
show
Bug Best Practice introduced by
The expression $canChangePrimary of type false|integer is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1113
		{
1114
			if ($old_profile['id_group'] != 0)
1115
				$addGroups[$old_profile['id_group']] = -1;
1116
			if (isset($addGroups[$group_id]))
1117
				unset($addGroups[$group_id]);
1118
			$newPrimary = $group_id;
1119
		}
1120
1121
		// Finally, we can make the changes!
1122
		foreach ($addGroups as $id => $dummy)
1123
		{
1124
			if (empty($id))
1125
				unset($addGroups[$id]);
1126
		}
1127
		$addGroups = implode(',', array_flip($addGroups));
1128
1129
		// Ensure that we don't cache permissions if the group is changing.
1130 View Code Duplication
		if ($context['user']['is_owner'])
1131
			$_SESSION['mc']['time'] = 0;
1132
		else
1133
			updateSettings(array('settings_updated' => time()));
1134
1135
		require_once(SUBSDIR . '/Members.subs.php');
1136
		updateMemberData($this->_memID, array('id_group' => $newPrimary, 'additional_groups' => $addGroups));
1137
1138
		return $changeType;
1139
	}
1140
1141
	/**
1142
	 * Load the options for an user.
1143
	 */
1144
	public function loadThemeOptions()
1145
	{
1146
		global $context, $options, $cur_profile;
1147
1148 View Code Duplication
		if (isset($this->_req->post->default_options))
1149
			$this->_req->post->options = isset($this->_req->post->options) ? $this->_req->post->options + $this->_req->post->default_options : $this->_req->post->default_options;
1150
1151
		if ($context['user']['is_owner'])
1152
		{
1153
			$context['member']['options'] = $options;
1154
1155
			if (isset($this->_req->post->options) && is_array($this->_req->post->options))
1156
			{
1157
				foreach ($this->_req->post->options as $k => $v)
1158
					$context['member']['options'][$k] = $v;
1159
			}
1160
		}
1161
		else
1162
		{
1163
			require_once(SUBSDIR . '/Themes.subs.php');
1164
			$context['member']['options'] = loadThemeOptionsInto(array(1, (int) $cur_profile['id_theme']), array(-1, $this->_memID), $context['member']['options']);
0 ignored issues
show
Documentation introduced by
array(-1, $this->_memID) is of type array<integer,integer,{"...nteger","1":"integer"}>, but the function expects a integer|null.

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...
1165
1166
			if (isset($this->_req->post->options))
1167
			{
1168
				foreach ($this->_req->post->options as $var => $val)
1169
					$context['member']['options'][$var] = $val;
1170
			}
1171
		}
1172
	}
1173
}