ProfileAccount::action_issuewarning()   F
last analyzed

Complexity

Conditions 26
Paths > 20000

Size

Total Lines 163
Code Lines 78

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 26
eloc 78
nc 41473
nop 0
dl 0
loc 163
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Handles actions made against a user's profile.
5
 *
6
 * @package   ElkArte Forum
7
 * @copyright ElkArte Forum contributors
8
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
9
 *
10
 * This file contains code covered by:
11
 * copyright: 2011 Simple Machines (http://www.simplemachines.org)
12
 *
13
 * @version 2.0 dev
14
 *
15
 */
16
17
namespace ElkArte\Profile;
18
19
use BBC\ParserWrapper;
20
use ElkArte\AbstractController;
21
use ElkArte\Controller\Auth;
22
use ElkArte\EventManager;
23
use ElkArte\Exceptions\Exception;
24
use ElkArte\Languages\Txt;
25
use ElkArte\Member;
26
use ElkArte\MembersList;
27
use ElkArte\User;
28
29
/**
30
 * Processes user warnings, account activation and account deletion
31
 */
32
class ProfileAccount extends AbstractController
33
{
34
	/** @var int Member id for the account being worked on */
35
	private $_memID = 0;
36
37
	/** @var Member The \ElkArte\Member object is stored here to avoid some global */
38
	private $_profile;
39
40
	/** @var array Holds any errors that were generated when issuing a warning */
41
	private $_issueErrors = [];
42
43
	/**
44
	 * Called before all other methods when coming from the dispatcher or
45
	 * action class.
46
	 */
47
	public function pre_dispatch()
48
	{
49
		$this->_memID = currentMemberID();
50
		$this->_profile = MembersList::get($this->_memID);
0 ignored issues
show
Documentation Bug introduced by
It seems like ElkArte\MembersList::get($this->_memID) can also be of type anonymous//sources/ElkArte/MembersList.php$0. However, the property $_profile is declared as type ElkArte\Member. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

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

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
51
	}
52
53
	/**
54
	 * Entry point for this class.
55
	 *
56
	 * @see AbstractController::action_index()
57
	 */
58
	public function action_index()
59
	{
60
		// figure out what action to do... if we're called directly
61
		// actions in this class are called from the Profile menu, though.
62
	}
63
64
	/**
65
	 * Issue/manage a user's warning status.
66
	 *
67
	 * @throws Exception
68
	 * @uses Profile template
69
	 * @uses template_issueWarning sub template in ProfileAccount
70
	 */
71
	public function action_issuewarning()
72
	{
73
		global $txt, $scripturl, $modSettings, $mbname, $context, $cur_profile;
74
75
		// Make sure the sub-template is set...
76
		theme()->getTemplates()->load('ProfileAccount');
77
		$context['sub_template'] = 'issueWarning';
78
79
		// We need this because of template_load_warning_variables
80
		theme()->getTemplates()->load('Profile');
81
		loadJavascriptFile('profile.js');
82
83
		// jQuery-UI FTW!
84
		$modSettings['jquery_include_ui'] = true;
85
		loadCSSFile('jquery.ui.slider.css');
86
		loadCSSFile('jquery.ui.theme.min.css');
87
88
		// Get all the actual settings.
89
		[$modSettings['warning_enable'], $modSettings['user_limit']] = explode(',', $modSettings['warning_settings']);
90
91
		// Doesn't hurt to be overly cautious.
92
		if (empty($modSettings['warning_enable'])
93
			|| ($context['user']['is_owner'] && !$cur_profile['warning'])
94
			|| !allowedTo('issue_warning'))
95
		{
96
			throw new Exception('no_access', false);
97
		}
98
99
		// Get the base (errors related) stuff done.
100
		Txt::load('Errors');
101
		$context['custom_error_title'] = $txt['profile_warning_errors_occurred'];
102
103
		// Make sure things which are disabled stay disabled.
104
		$modSettings['warning_watch'] = empty($modSettings['warning_watch']) ? 110 : $modSettings['warning_watch'];
105
		$modSettings['warning_moderate'] = !empty($modSettings['warning_moderate']) && !empty($modSettings['postmod_active']) ? $modSettings['warning_moderate'] : 110;
106
		$modSettings['warning_mute'] = empty($modSettings['warning_mute']) ? 110 : $modSettings['warning_mute'];
107
108
		$context['warning_limit'] = allowedTo('admin_forum') ? 0 : $modSettings['user_limit'];
109
		$context['member']['warning'] = $cur_profile['warning'];
110
		$context['member']['name'] = $cur_profile['real_name'];
111
112
		// What are the limits we can apply?
113
		$context['min_allowed'] = 0;
114
		$context['max_allowed'] = 100;
115
		if ($context['warning_limit'] > 0)
116
		{
117
			require_once(SUBSDIR . '/Moderation.subs.php');
118
			$current_applied = warningDailyLimit($this->_memID);
119
120
			$context['min_allowed'] = max(0, $cur_profile['warning'] - $current_applied - $context['warning_limit']);
121
			$context['max_allowed'] = min(100, $cur_profile['warning'] - $current_applied + $context['warning_limit']);
122
		}
123
124
		// Defaults.
125
		$context['warning_data'] = [
126
			'reason' => '',
127
			'notify' => '',
128
			'notify_subject' => '',
129
			'notify_body' => '',
130
		];
131
132
		// Are we saving?
133
		$this->_save_warning();
134
135
		// Perhaps taking a look first? Good idea that one.
136
		$this->_preview_warning();
137
138
		// If we have errors, lets set them for the template
139
		if (!empty($this->_issueErrors))
140
		{
141
			// Fill in the suite of errors.
142
			$context['post_errors'] = [];
143
			foreach ($this->_issueErrors as $error)
144
			{
145
				$context['post_errors'][] = $txt[$error];
146
			}
147
		}
148
149
		$context['page_title'] = $txt['profile_issue_warning'];
150
151
		// Let's use a generic list to get all the current warnings
152
		require_once(SUBSDIR . '/Profile.subs.php');
153
154
		// Work our the various levels.
155
		$context['level_effects'] = [
156
			0 => $txt['profile_warning_effect_none'],
157
		];
158
159
		foreach (['watch', 'moderate', 'mute'] as $status)
160
		{
161
			if ($modSettings['warning_' . $status] != 110)
162
			{
163
				$context['level_effects'][$modSettings['warning_' . $status]] = $txt['profile_warning_effect_' . $status];
164
			}
165
		}
166
167
		$context['current_level'] = 0;
168
169
		foreach ($context['level_effects'] as $limit => $dummy)
170
		{
171
			if ($context['member']['warning'] >= $limit)
172
			{
173
				$context['current_level'] = $limit;
174
			}
175
		}
176
177
		// Build a listing to view the previous warnings for this user
178
		$this->_create_issued_warnings_list();
179
180
		$warning_for_message = $this->_req->getQuery('msg', 'intval', false);
181
		$warned_message_subject = '';
182
183
		// Are they warning because of a message?
184
		if (!empty($warning_for_message) && $warning_for_message > 0)
185
		{
186
			require_once(SUBSDIR . '/Messages.subs.php');
187
			$message = basicMessageInfo($warning_for_message);
188
189
			if (!empty($message))
190
			{
191
				$warned_message_subject = $message['subject'];
192
			}
193
		}
194
195
		require_once(SUBSDIR . '/Maillist.subs.php');
196
197
		// Any custom templates?
198
		$context['notification_templates'] = [];
199
		$notification_templates = maillist_templates('warntpl');
200
201
		foreach ($notification_templates as $row)
202
		{
203
			// If we're not warning for a message skip any that are.
204
			if ($warning_for_message === false && strpos($row['body'], '{MESSAGE}') !== false)
205
			{
206
				continue;
207
			}
208
209
			$context['notification_templates'][] = [
210
				'title' => $row['title'],
211
				'body' => $row['body'],
212
			];
213
		}
214
215
		// Setup the "default" templates.
216
		foreach (['spamming', 'offence', 'insulting'] as $type)
217
		{
218
			$context['notification_templates'][] = [
219
				'title' => $txt['profile_warning_notify_title_' . $type],
220
				'body' => sprintf($txt['profile_warning_notify_template_outline' . (empty($warning_for_message) ? '' : '_post')], $txt['profile_warning_notify_for_' . $type]),
221
			];
222
		}
223
224
		// Replace all the common variables in the templates.
225
		foreach ($context['notification_templates'] as $k => $name)
226
		{
227
			$context['notification_templates'][$k]['body'] = strtr($name['body'],
228
				[
229
					'{MEMBER}' => un_htmlspecialchars($context['member']['name']),
230
					'{MESSAGE}' => '[url=' . getUrl('action', ['msg' => $warning_for_message]) . ']' . un_htmlspecialchars($warned_message_subject) . '[/url]',
231
					'{SCRIPTURL}' => $scripturl,
232
					'{FORUMNAME}' => $mbname,
233
					'{REGARDS}' => replaceBasicActionUrl($txt['regards_team'])
234
				]
235
			);
236
		}
237
	}
238
239
	/**
240
	 * Does the actual issuing of a warning to a member
241
	 *
242
	 * What it does:
243
	 *
244
	 * - Validates the inputs
245
	 * - Sends the warning PM if required, to the member
246
	 * - Logs the action
247
	 * - Updates the user data with the new warning level
248
	 */
249
	private function _save_warning()
250
	{
251
		global $txt, $context, $cur_profile;
252
253
		if (isset($this->_req->post->save))
254
		{
255
			// Security is good here.
256
			checkSession();
257
258
			// There must be a reason, and use of flowery words is allowed.
259
			$warn_reason = $this->_req->getPost('warn_reason', 'trim|\\ElkArte\\Helper\\Util::htmlspecialchars', '');
260
			if ($warn_reason === '' && !$context['user']['is_owner'])
261
			{
262
				$this->_issueErrors[] = 'warning_no_reason';
263
			}
264
265
			// If the value hasn't changed it's either no JS or a real no change (Which this will pass)
266
			if ($warn_reason === 'SAME')
267
			{
268
				$this->_req->post->warning_level = $this->_req->post->warning_level_nojs;
269
			}
270
271
			// Set and contain the level and level changes
272
			$warning_level = (int) $this->_req->post->warning_level;
273
			$warning_level = max(0, min(100, $warning_level));
274
275
			if ($warning_level < $context['min_allowed'])
276
			{
277
				$warning_level = $context['min_allowed'];
278
			}
279
			elseif ($warning_level > $context['max_allowed'])
280
			{
281
				$warning_level = $context['max_allowed'];
282
			}
283
284
			// We need this to log moderation notices
285
			require_once(SUBSDIR . '/Moderation.subs.php');
286
287
			// Do we actually have to issue them with a PM?
288
			$id_notice = $this->_issue_warning_pm();
289
290
			// What have we changed?
291
			$level_change = $warning_level - $cur_profile['warning'];
292
293
			// No errors? Proceed! Only log if you're not the owner.
294
			if (empty($this->_issueErrors))
295
			{
296
				// Log what we've done!
297
				if (!$context['user']['is_owner'])
298
				{
299
					logWarning($this->_memID, $cur_profile['real_name'], $id_notice, $level_change, $warn_reason);
300
				}
301
302
				// Make the change.
303
				require_once(SUBSDIR . '/Members.subs.php');
304
				updateMemberData($this->_memID, ['warning' => $warning_level]);
305
306
				// Leave a lovely message.
307
				$context['profile_updated'] = $context['user']['is_owner'] ? $txt['profile_updated_own'] : $txt['profile_warning_success'];
308
			}
309
			else
310
			{
311
				// Try to remember some bits.
312
				$context['warning_data'] = [
313
					'reason' => $warn_reason,
314
					'notify' => !empty($this->_req->post->warn_notify),
315
					'notify_subject' => $this->_req->getPost('warn_sub', 'trim', ''),
316
					'notify_body' => $this->_req->getPost('warn_body', 'trim', ''),
317
				];
318
			}
319
320
			// Show the new improved warning level.
321
			$context['member']['warning'] = $warning_level;
322
		}
323
	}
324
325
	/**
326
	 * Issue a pm to the member getting the warning
327
	 *
328
	 * @return int
329
	 * @throws Exception
330
	 */
331
	private function _issue_warning_pm()
332
	{
333
		global $context, $modSettings;
334
335
		$id_notice = 0;
336
		if (!empty($this->_req->post->warn_notify) && empty($this->_issueErrors))
337
		{
338
			$warn_sub = $this->_req->getPost('warn_sub', 'trim', '');
339
			$warn_body = $this->_req->getPost('warn_body', 'trim', '');
340
341
			if (empty($warn_sub) || empty($warn_body))
342
			{
343
				$this->_issueErrors[] = 'warning_notify_blank';
344
			}
345
			// Send the PM?
346
			else
347
			{
348
				require_once(SUBSDIR . '/PersonalMessage.subs.php');
349
				$from = [
350
					'id' => 0,
351
					'name' => $context['forum_name'],
352
					'username' => $context['forum_name'],
353
				];
354
355
				// No sense in sending a PbE
356
				$modSettings['maillist_enabled'] = 0;
357
				sendpm(['to' => [$this->_memID], 'bcc' => []], $warn_sub, $warn_body, false, $from);
358
359
				// Log the notice.
360
				$id_notice = logWarningNotice($warn_sub, $warn_body);
361
			}
362
		}
363
364
		return $id_notice;
365
	}
366
367
	/**
368
	 * Prepares a warning preview
369
	 */
370
	private function _preview_warning()
371
	{
372
		global $context;
373
374
		if (isset($this->_req->post->preview))
375
		{
376
			$warning_body = empty($this->_req->post->warn_body) ? '' : trim(censor($this->_req->post->warn_body));
377
378
			if (empty($this->_req->post->warn_sub) || empty($this->_req->post->warn_body))
379
			{
380
				$this->_issueErrors[] = 'warning_notify_blank';
381
			}
382
383
			if (!empty($this->_req->post->warn_body))
384
			{
385
				require_once(SUBSDIR . '/Post.subs.php');
386
387
				$bbc_parser = ParserWrapper::instance();
388
				preparsecode($warning_body);
389
				$warning_body = $bbc_parser->parseNotice($warning_body);
390
			}
391
392
			// Try to remember some bits.
393
			$context['preview_subject'] = $this->_req->getPost('warn_sub', 'trim|\\ElkArte\\Helper\\Util::htmlspecialchars', '');
394
			$context['warning_data'] = [
395
				'reason' => $this->_req->post->warn_reason,
396
				'notify' => !empty($this->_req->post->warn_notify),
397
				'notify_subject' => $this->_req->getPost('warn_sub', 'trim', ''),
398
				'notify_body' => $this->_req->getPost('warn_body', 'trim', ''),
399
				'body_preview' => $warning_body,
400
			];
401
		}
402
	}
403
404
	/**
405
	 * Creates the listing of issued warnings
406
	 */
407
	private function _create_issued_warnings_list()
408
	{
409
		global $txt, $modSettings;
410
411
		$listOptions = [
412
			'id' => 'issued_warnings',
413
			'title' => $txt['profile_viewwarning_previous_warnings'],
414
			'items_per_page' => $modSettings['defaultMaxMessages'],
415
			'no_items_label' => $txt['profile_viewwarning_no_warnings'],
416
			'base_href' => getUrl('action', ['action' => 'profile', 'area' => 'issuewarning', 'sa' => 'user', 'u' => $this->_memID]),
417
			'default_sort_col' => 'log_time',
418
			'get_items' => [
419
				'function' => fn($start, $items_per_page, $sort) => $this->list_getUserWarnings($start, $items_per_page, $sort),
420
			],
421
			'get_count' => [
422
				'function' => fn() => $this->list_getUserWarningCount(),
423
			],
424
			'columns' => [
425
				'issued_by' => [
426
					'header' => [
427
						'value' => $txt['profile_warning_previous_issued'],
428
						'class' => 'grid20',
429
					],
430
					'data' => [
431
						'function' => static fn($warning) => $warning['issuer']['link'],
432
					],
433
					'sort' => [
434
						'default' => 'lc.member_name DESC',
435
						'reverse' => 'lc.member_name',
436
					],
437
				],
438
				'log_time' => [
439
					'header' => [
440
						'value' => $txt['profile_warning_previous_time'],
441
						'class' => 'grid30',
442
					],
443
					'data' => [
444
						'db' => 'time',
445
					],
446
					'sort' => [
447
						'default' => 'lc.log_time DESC',
448
						'reverse' => 'lc.log_time',
449
					],
450
				],
451
				'reason' => [
452
					'header' => [
453
						'value' => $txt['profile_warning_previous_reason'],
454
					],
455
					'data' => [
456
						'function' => static function ($warning) {
457
							global $txt;
458
459
							$ret = '
460
							<div class="floatleft">
461
								' . $warning['reason'] . '
462
							</div>';
463
464
							// If a notice was sent, provide a way to view it
465
							if (!empty($warning['id_notice']))
466
							{
467
								$ret .= '
468
							<div class="floatright">
469
								<a href="' . getUrl('action', ['action' => 'moderate', 'area' => 'notice', 'nid' => $warning['id_notice']]) . '" onclick="window.open(this.href, \'\', \'scrollbars=yes,resizable=yes,width=400,height=250\');return false;" target="_blank" class="new_win" title="' . $txt['profile_warning_previous_notice'] . '"><i class="icon icon-small i-search"></i></a>
470
							</div>';
471
							}
472
473
							return $ret;
474
						},
475
					],
476
				],
477
				'level' => [
478
					'header' => [
479
						'value' => $txt['profile_warning_previous_level'],
480
						'class' => 'grid8',
481
					],
482
					'data' => [
483
						'db' => 'counter',
484
					],
485
					'sort' => [
486
						'default' => 'lc.counter DESC',
487
						'reverse' => 'lc.counter',
488
					],
489
				],
490
			],
491
		];
492
493
		// Create the list for viewing.
494
		createList($listOptions);
495
	}
496
497
	/**
498
	 * Callback for createList(). Called by action_hooks
499
	 *
500
	 * @param int $start The item to start with (for pagination purposes)
501
	 * @param int $items_per_page The number of items to show per page
502
	 * @param string $sort A string indicating how to sort the results
503
	 *
504
	 * @return array
505
	 */
506
	public function list_getUserWarnings($start, $items_per_page, $sort)
507
	{
508
		return list_getUserWarnings($start, $items_per_page, $sort, $this->_memID);
509
	}
510
511
	/**
512
	 * Simply returns the total count of warnings
513
	 * Callback for createList().
514
	 *
515
	 * @return int
516
	 */
517
	public function list_getUserWarningCount()
518
	{
519
		return list_getUserWarningCount($this->_memID);
520
	}
521
522
	/**
523
	 * Present a screen to make sure the user wants to be deleted.
524
	 */
525
	public function action_deleteaccount()
526
	{
527
		global $txt, $context, $modSettings, $cur_profile;
528
529
		if (!$context['user']['is_owner'])
530
		{
531
			isAllowedTo('profile_remove_any');
532
		}
533
		elseif (!allowedTo('profile_remove_any'))
534
		{
535
			isAllowedTo('profile_remove_own');
536
		}
537
538
		// Permissions for removing stuff...
539
		$context['can_delete_posts'] = !$context['user']['is_owner'] && allowedTo('moderate_forum');
540
541
		// Can they do this, or will they need approval?
542
		$context['needs_approval'] = $context['user']['is_owner'] && !empty($modSettings['approveAccountDeletion']) && !allowedTo('moderate_forum');
543
		$context['page_title'] = $txt['deleteAccount'] . ': ' . $cur_profile['real_name'];
544
545
		// make sure the sub-template is set...
546
		theme()->getTemplates()->load('ProfileAccount');
547
		$context['sub_template'] = 'deleteAccount';
548
	}
549
550
	/**
551
	 * Actually delete an account.
552
	 */
553
	public function action_deleteaccount2()
554
	{
555
		global $context, $cur_profile, $modSettings;
556
557
		// Try get more time...
558
		detectServer()->setTimeLimit(600);
559
560
		// @todo Add a way to delete pms as well?
561
		if (!$context['user']['is_owner'])
562
		{
563
			isAllowedTo('profile_remove_any');
564
		}
565
		elseif (!allowedTo('profile_remove_any'))
566
		{
567
			isAllowedTo('profile_remove_own');
568
		}
569
570
		checkSession();
571
572
		// Check we got here as we should have!
573
		if ((int) $cur_profile->id_member !== (int) $this->_profile->id_member)
574
		{
575
			throw new Exception('no_access', false);
576
		}
577
578
		// This file is needed for our utility functions.
579
		require_once(SUBSDIR . '/Members.subs.php');
580
581
		// Too often, people remove/delete their own only administrative account.
582
		if (in_array(1, array_map('intval', explode(',', $cur_profile['additional_groups'])), true) || (int) $cur_profile['id_group'] === 1)
583
		{
584
			// Are you allowed to administrate the forum, as they are?
585
			isAllowedTo('admin_forum');
586
587
			$another = isAnotherAdmin($this->_memID);
588
589
			if (empty($another))
590
			{
591
				throw new Exception('at_least_one_admin', 'critical');
592
			}
593
		}
594
595
		// Do you have permission to delete others profiles, or is that your profile you wanna delete?
596
		if ($this->_memID != $this->user->id)
597
		{
598
			isAllowedTo('profile_remove_any');
599
600
			// Now, have you been naughty and need your posts deleting?
601
			// @todo Should this check board permissions?
602
			if ($this->_req->post->remove_type !== 'none' && allowedTo('moderate_forum'))
603
			{
604
				// Include subs/Topic.subs.php - essential for this type of work!
605
				require_once(SUBSDIR . '/Topic.subs.php');
606
				require_once(SUBSDIR . '/Messages.subs.php');
607
608
				// First off we delete any topics the member has started - if they wanted topics being done.
609
				if ($this->_req->post->remove_type === 'topics')
610
				{
611
					// Fetch all topics started by this user.
612
					$topicIDs = topicsStartedBy($this->_memID);
613
614
					// Actually remove the topics.
615
					// @todo This needs to check permissions, but we'll let it slide for now because of moderate_forum already being had.
616
					removeTopics($topicIDs);
617
				}
618
619
				// Now delete the remaining messages.
620
				removeNonTopicMessages($this->_memID);
621
			}
622
623
			// Only delete this poor member's account if they are actually being booted out of camp.
624
			if (isset($this->_req->post->deleteAccount))
625
			{
626
				deleteMembers($this->_memID);
627
			}
628
		}
629
		// Do they need approval to delete?
630
		elseif (!empty($modSettings['approveAccountDeletion']) && !allowedTo('moderate_forum'))
631
		{
632
			// Setup their account for deletion ;)
633
			require_once(SUBSDIR . '/Members.subs.php');
634
			updateMemberData($this->_memID, ['is_activated' => 4]);
635
636
			// Another account needs approval...
637
			updateSettings(['unapprovedMembers' => true], true);
638
		}
639
		// Also check if you typed your password correctly.
640
		else
641
		{
642
			deleteMembers($this->_memID);
643
644
			$controller = new Auth(new EventManager());
645
			$controller->setUser(User::$info);
646
			$controller->action_logout(true);
647
648
			redirectexit();
649
		}
650
	}
651
652
	/**
653
	 * Activate an account.
654
	 *
655
	 * - This function is called from the profile account actions area.
656
	 */
657
	public function action_activateaccount()
658
	{
659
		global $context, $modSettings;
660
661
		isAllowedTo('moderate_forum');
662
663
		$this->_profile['is_activated'] = (int) $this->_profile['is_activated'];
664
		if (isset($this->_req->query->save, $this->_profile['is_activated'])
665
			&& $this->_profile['is_activated'] !== 1)
666
		{
667
			require_once(SUBSDIR . '/Members.subs.php');
668
669
			// If we are approving the deletion of an account, we do something special ;)
670
			if ($this->_profile['is_activated'] === 4)
671
			{
672
				deleteMembers($context['id_member']);
673
				redirectexit();
674
			}
675
676
			// Actually update this member now, as it guarantees the unapproved count can't get corrupted.
677
			approveMembers(['members' => [$context['id_member']], 'activated_status' => $this->_profile['is_activated']]);
678
679
			// Log what we did?
680
			logAction('approve_member', ['member' => $this->_memID], 'admin');
681
682
			// If we are doing approval, update the stats for the member just in case.
683
			if (in_array($this->_profile['is_activated'], [3, 4, 5, 13, 14, 15]))
684
			{
685
				updateSettings(['unapprovedMembers' => ($modSettings['unapprovedMembers'] > 1 ? $modSettings['unapprovedMembers'] - 1 : 0)]);
686
			}
687
688
			// Make sure we update the stats too.
689
			require_once(SUBSDIR . '/Members.subs.php');
690
			updateMemberStats();
691
		}
692
693
		// Leave it be...
694
		redirectexit('action=profile;u=' . $this->_memID . ';area=summary');
695
	}
696
}
697