Groups::action_members()   F
last analyzed

Complexity

Conditions 48
Paths > 20000

Size

Total Lines 227
Code Lines 112

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2352

Importance

Changes 0
Metric Value
cc 48
eloc 112
nc 3317857
nop 0
dl 0
loc 227
ccs 0
cts 107
cp 0
crap 2352
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
 * This file currently just shows group info and allows certain privileged
5
 * members to add/remove members.
6
 *
7
 * @package   ElkArte Forum
8
 * @copyright ElkArte Forum contributors
9
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
10
 *
11
 * This file contains code covered by:
12
 * copyright: 2011 Simple Machines (http://www.simplemachines.org)
13
 *
14
 * @version 2.0 Beta 1
15
 *
16
 */
17
18
namespace ElkArte\Controller;
19
20
use ElkArte\AbstractController;
21
use ElkArte\Action;
22
use ElkArte\EventManager;
23
use ElkArte\Exceptions\Exception;
24
use ElkArte\Helper\Util;
25
use ElkArte\Languages\Txt;
26
use ElkArte\User;
27
28
/**
29
 * Shows group access and allows for add/remove group members
30
 */
31
class Groups extends AbstractController
32
{
33
	/**
34
	 * Set up templates and pre-requisites for any request processed by this class.
35
	 *
36
	 * - Called automagically before any action_() call.
37
	 * - It handles permission checks and puts the moderation bar on as required.
38 2
	 */
39
	public function pre_dispatch()
40 2
	{
41
		global $context, $txt;
42
43 2
		// Get the template stuff up and running.
44 2
		Txt::load('ManageMembers');
45 2
		Txt::load('ModerationCenter');
46
		theme()->getTemplates()->load('ManageMembergroups');
47
48 2
		// If we can see the moderation center, and this has a mod bar entry, add the mod center bar.
49
		if (User::$info->canMod(true) || allowedTo('manage_membergroups'))
0 ignored issues
show
Bug introduced by
The method canMod() does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

49
		if (User::$info->/** @scrutinizer ignore-call */ canMod(true) || allowedTo('manage_membergroups'))
Loading history...
50 2
		{
51 2
			$this->_req->query->area = $this->_req->getQuery('sa') === 'requests' ? 'groups' : 'viewgroups';
52 2
			$controller = new ModerationCenter(new EventManager());
53 2
			$controller->setUser(User::$info);
54 2
			$controller->pre_dispatch();
55
			$controller->prepareModcenter();
56
		}
57
		// Otherwise add something to the link tree, for normal people.
58
		else
59
		{
60
			isAllowedTo('view_mlist');
61
62
			$context['breadcrumbs'][] = [
63
				'url' => getUrl('group', ['action' => 'groups']),
64
				'name' => $txt['groups'],
65
			];
66 2
		}
67
	}
68
69
	/**
70
	 * Entry point to groups.
71
	 * It allows moderators and users to access the group showing functions.
72
	 *
73
	 * @see AbstractController::action_index
74 2
	 */
75
	public function action_index()
76 2
	{
77
		global $context;
78
79
		// Little short on the list here
80 2
		$subActions = [
81 2
			'list' => [$this, 'action_list', 'permission' => 'view_mlist'],
82 2
			'members' => [$this, 'action_members', 'permission' => 'view_mlist'],
83
			'requests' => [$this, 'action_requests'],
84
		];
85
86 2
		// I don't think we know what to do... throw dies?
87 2
		$action = new Action('groups');
88 2
		$subAction = $action->initialize($subActions, 'list');
89 2
		$context['sub_action'] = $subAction;
90 2
		$action->dispatch($subAction);
91
	}
92
93
	/**
94
	 * This very simply lists the groups, nothing snazzy.
95 2
	 */
96
	public function action_list(): void
97 2
	{
98
		global $txt, $context;
99 2
100 2
		$context['page_title'] = $txt['viewing_groups'];
101 2
		$current_area = $context['admin_menu_name'] ?? ($context['moderation_menu_name'] ?? '');
102
		if (!empty($current_area))
103 2
		{
104 2
			$context[$current_area]['tab_data'] = [
105
				'title' => $txt['mc_group_requests'],
106
			];
107
		}
108 2
109
		if (isset($context['admin_menu_name']))
110 2
		{
111 2
			$base_type = 'admin';
112
			$base_params = ['action' => 'admin', 'area' => 'membergroups', 'sa' => 'members'];
113
		}
114
		elseif (isset($context['moderation_menu_name']))
115
		{
116
			$base_type = 'moderate';
117
			$base_params = ['action' => 'moderate', 'area' => 'viewgroups', 'sa' => 'members'];
118
		}
119
		else
120
		{
121
			$base_type = 'group';
122
			$base_params = ['action' => 'groups', 'sa' => 'members'];
123
		}
124
125
		// Use the standard templates for showing this.
126 2
		$listOptions = [
127 2
			'id' => 'group_lists',
128 2
			'base_href' => getUrl($base_type, $base_params),
129
			'default_sort_col' => 'group',
130 2
			'get_items' => [
131 2
				'file' => SUBSDIR . '/Membergroups.subs.php',
132
				'function' => 'list_getMembergroups',
133 2
				'params' => [
134 2
					'regular',
135 2
					$this->user->id,
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
136 2
					allowedTo('manage_membergroups'),
137
					allowedTo('admin_forum'),
138
				],
139
			],
140
			'columns' => [
141
				'group' => [
142 2
					'header' => [
143
						'value' => $txt['name'],
144
					],
145
					'data' => [
146
						'function' => static function ($rowData) use ($base_type, $base_params) {
147 2
							// Since the moderator group has no explicit members, no link is needed.
148
							if ($rowData['id_group'] == 3)
149 2
							{
150
								$group_name = $rowData['group_name'];
151
							}
152
							else
153 2
							{
154 2
								$url = getUrl($base_type, array_merge($base_params, ['group' => $rowData['id_group']]));
155
								$group_name = sprintf('<a href="%1$s">%2$s</a>', $url, $rowData['group_name_color']);
156
							}
157
							// Add a help option for moderator and administrator.
158 2
							if ($rowData['id_group'] == 1)
159
							{
160 2
								$group_name .= ' (<a href="' . getUrl('action', ['action' => 'quickhelp', 'help' => 'membergroup_administrator']) . '" onclick="return reqOverlayDiv(this.href);" class="helpicon i-help"></a>)';
161
							}
162 2
							elseif ($rowData['id_group'] == 3)
163
							{
164 2
								$group_name .= ' (<a href="' . getUrl('action', ['action' => 'quickhelp', 'help' => 'membergroup_moderator']) . '" onclick="return reqOverlayDiv(this.href);" class="helpicon i-help"></a>)';
165
							}
166
							return $group_name;
167 2
						},
168 2
					],
169
					'sort' => [
170
						'default' => 'CASE WHEN mg.id_group < 4 THEN mg.id_group ELSE 4 END, mg.group_name',
171
						'reverse' => 'CASE WHEN mg.id_group < 4 THEN mg.id_group ELSE 4 END, mg.group_name DESC',
172
					],
173
				],
174
				'icons' => [
175
					'header' => [
176
						'value' => $txt['membergroups_icons'],
177 2
					],
178
					'data' => [
179
						'function' => static function ($rowData) {
180
							global $settings;
181 2
							if (empty($rowData['icons'][0]))
182
							{
183 2
								return '';
184
							}
185 2
							if (empty($rowData['icons'][1]))
186
							{
187
								return '';
188
							}
189
							return str_repeat('<img src="' . $settings['images_url'] . '/group_icons/' . $rowData['icons'][1] . '" alt="*" />', $rowData['icons'][0]);
190
						},
191 2
					],
192
					'sort' => [
193
						'default' => 'mg.icons',
194
						'reverse' => 'mg.icons DESC',
195
					]
196
				],
197
				'moderators' => [
198
					'header' => [
199
						'value' => $txt['moderators'],
200 2
					],
201
					'data' => [
202
						'function' => static function ($group) {
203
							global $txt;
204 2
							return empty($group['moderators']) ? '<em>' . $txt['membergroups_new_copy_none'] . '</em>' : implode(', ', $group['moderators']);
205
						},
206 2
					],
207 2
				],
208
				'members' => [
209
					'header' => [
210
						'value' => $txt['membergroups_members_top'],
211
					],
212 2
					'data' => [
213
						'function' => static function ($rowData) {
214
							global $txt;
215
							// No explicit members for the moderator group.
216 2
							return $rowData['id_group'] == 3 ? $txt['membergroups_guests_na'] : comma_format($rowData['num_members']);
217
						},
218
						'class' => 'centertext',
219 2
					],
220 2
					'sort' => [
221 2
						'default' => 'CASE WHEN mg.id_group < 4 THEN mg.id_group ELSE 4 END, 1',
222
						'reverse' => 'CASE WHEN mg.id_group < 4 THEN mg.id_group ELSE 4 END, 1 DESC',
223
					],
224
				],
225
			],
226
		];
227
228
		// Create the request list.
229
		createList($listOptions);
230
231
		$context['sub_template'] = 'show_list';
232 2
		$context['default_list'] = 'group_lists';
233
	}
234 2
235 2
	/**
236 2
	 * Display members of a group and allow adding of members to a group.
237
	 *
238
	 * What it does:
239
	 *
240
	 * - It can be called from ManageMembergroups if it needs templating within the admin environment.
241
	 * - It shows a list of members that are part of a given membergroup.
242
	 * - It is called by ?action=moderate;area=viewgroups;sa=members;group=x
243
	 * - It requires the manage_membergroups permission.
244
	 * - It allows adding and remove members from the selected membergroup.
245
	 * - It allows sorting on several columns.
246
	 * - It redirects to itself.
247
	 *
248
	 * @uses ManageMembergroups template, group_members sub template.
249
	 */
250
	public function action_members(): void
251
	{
252
		global $txt, $context, $modSettings, $settings;
253
254
		$current_group = $this->_req->getQuery('group', 'intval', 0);
255
256
		// These will be needed
257
		require_once(SUBSDIR . '/Membergroups.subs.php');
258
		require_once(SUBSDIR . '/Members.subs.php');
259
260
		// Load up the group details.
261
		$context['group'] = membergroupById($current_group, true, true);
262
263
		// No browsing of guests, membergroup 0 or moderators or non-existing groups.
264
		if ($context['group'] === false || in_array($current_group, [-1, 0, 3]))
265
		{
266
			throw new Exception('membergroup_does_not_exist', false);
267
		}
268
269
		$context['group']['id'] = $context['group']['id_group'];
270
		$context['group']['name'] = $context['group']['group_name'];
271
272
		// Fix the membergroup icons.
273
		$context['group']['icons'] = explode('#', $context['group']['icons']);
274
		$context['group']['icons'] = !empty($context['group']['icons'][0]) && !empty($context['group']['icons'][1]) ? str_repeat('<img src="' . $settings['images_url'] . '/group_icons/' . $context['group']['icons'][1] . '" alt="*" />', $context['group']['icons'][0]) : '';
275
		$context['group']['can_moderate'] = allowedTo('manage_membergroups') && (allowedTo('admin_forum') || $context['group']['group_type'] != 1);
276
277
		// The template is very needy
278
		$context['breadcrumbs'][] = [
279
			'url' => getUrl('group', ['action' => 'groups', 'sa' => 'members', 'group' => $context['group']['id'], 'name' => $context['group']['name']]),
280
			'name' => $context['group']['name'],
281
		];
282
		$context['can_send_email'] = allowedTo('send_email_to_members');
283
		$context['sort_direction'] = $this->_req->hasQuery('desc') ? 'down' : 'up';
284
		$context['start'] = $this->_req->getQuery('start', 'intval', 0);
285
		$context['can_moderate_forum'] = allowedTo('moderate_forum');
286
287
		// @todo: use createList
288
289
		// Load all the group moderators, for fun.
290
		$context['group']['moderators'] = [];
291
		$moderators = getGroupModerators($current_group);
292
		foreach ($moderators as $id_member => $name)
293
		{
294
			$context['group']['moderators'][] = [
295
				'id' => $id_member,
296
				'name' => $name
297
			];
298
			if ($this->user->id != $id_member)
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
299
			{
300
				continue;
301
			}
302
			if ($context['group']['group_type'] == 1)
303
			{
304
				continue;
305
			}
306
			$context['group']['can_moderate'] = true;
307
		}
308
309
		// If this group is hidden, then it can only "exist" if the user can moderate it!
310
		if ($context['group']['hidden'] && !$context['group']['can_moderate'])
311
		{
312
			throw new Exception('membergroup_does_not_exist', false);
313
		}
314
315
		// You can only assign membership if you are the moderator and/or can manage groups!
316
		if (!$context['group']['can_moderate'])
317
		{
318
			$context['group']['assignable'] = 0;
319
		}
320
		// Non-admins cannot assign admins.
321
		elseif ($context['group']['id'] == 1 && !allowedTo('admin_forum'))
322
		{
323
			$context['group']['assignable'] = 0;
324
		}
325
326
		// Removing member from a group?
327
		if (isset($this->_req->post->remove)
328
			&& !empty($this->_req->post->rem)
329
			&& is_array($this->_req->post->rem)
330
			&& $context['group']['assignable'])
331
		{
332
			// Security first
333
			checkSession();
334
			validateToken('mod-mgm');
335
336
			// Make sure we're dealing with integers only.
337
			$to_remove = array_map('intval', $this->_req->post->rem);
338
			removeMembersFromGroups($to_remove, $current_group, true);
339
		}
340
		// Must be adding new members to the group...
341
		elseif (isset($this->_req->post->add)
342
			&& (!empty($this->_req->post->toAdd) || !empty($this->_req->post->member_add)) && $context['group']['assignable'])
343
		{
344
			// Make sure you can do this
345
			checkSession();
346
			validateToken('mod-mgm');
347
348
			$member_query = [['and' => 'not_in_group']];
349
			$member_parameters = ['not_in_group' => $current_group];
350
351
			// Get all the members to be added... taking into account names can be quoted ;)
352
			$toAdd = strtr(Util::htmlspecialchars($this->_req->post->toAdd, ENT_QUOTES), ['&quot;' => '"']);
353
			preg_match_all('~"([^"]+)"~', $toAdd, $matches);
354
			$member_names = array_unique(array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $toAdd))));
355
356
			foreach (array_keys($member_names) as $index)
357
			{
358
				$member_names[$index] = trim(Util::strtolower($member_names[$index]));
359
				if ($member_names[$index] === '')
360
				{
361
					unset($member_names[$index]);
362
				}
363
			}
364
365
			// Any members passed by ID?
366
			$member_ids = [];
367
			if (!empty($this->_req->post->member_add))
368
			{
369
				foreach ($this->_req->post->member_add as $id)
370
				{
371
					if ($id > 0)
372
					{
373
						$member_ids[] = (int) $id;
374
					}
375
				}
376
			}
377
378
			// Construct the query elements, first for adding by name
379
			if (!empty($member_ids))
380
			{
381
				$member_query[] = ['or' => 'member_ids'];
382
				$member_parameters['member_ids'] = $member_ids;
383
			}
384
385
			// And then adds by ID
386
			if (!empty($member_names))
387
			{
388
				$member_query[] = ['or' => 'member_names'];
389
				$member_parameters['member_names'] = $member_names;
390
			}
391
392
			// Get back the ones that were not already in the group
393
			$members = membersBy($member_query, $member_parameters);
394
395
			// Do the updates...
396
			if (!empty($members))
397
			{
398
				addMembersToGroup($members, $current_group, $context['group']['hidden'] ? 'only_additional' : 'auto', true);
399
			}
400
		}
401
402
		// Sort out the sorting!
403
		$sort_methods = [
404
			'name' => 'real_name',
405
			'email' => allowedTo('moderate_forum') ? 'email_address' : ' ' . ($this->_req->hasQuery('desc') ? 'DESC' : 'ASC') . ', email_address',
406
			'active' => 'last_login',
407
			'registered' => 'date_registered',
408
			'posts' => 'posts',
409
		];
410
411
		// They didn't pick one, or tried a wrong one, so default to by name.
412
		$requested_sort = $this->_req->getQuery('sort', 'trim|strval');
413
		if ($requested_sort === null || !isset($sort_methods[$requested_sort]))
414
		{
415
			$context['sort_by'] = 'name';
416
			$querySort = 'real_name' . ($this->_req->hasQuery('desc') ? ' DESC' : ' ASC');
417
		}
418
		// Otherwise sort by what they asked
419
		else
420
		{
421
			$context['sort_by'] = $requested_sort;
422
			$querySort = $sort_methods[$requested_sort] . ($this->_req->hasQuery('desc') ? ' DESC' : ' ASC');
423
		}
424
425
		// The where on the query is interesting. Non-moderators should only see people who are in this group as primary.
426
		if ($context['group']['can_moderate'])
427
		{
428
			$where = $context['group']['is_post_group'] ? 'in_post_group' : 'in_group';
429
		}
430
		else
431
		{
432
			$where = $context['group']['is_post_group'] ? 'in_post_group' : 'in_group_no_add';
433
		}
434
435
		// Count members of the group.
436
		$context['total_members'] = countMembersBy($where, [$where => $current_group]);
437
		$context['total_members'] = comma_format($context['total_members']);
438
439
		// Create the page index.
440
		$context['page_index'] = constructPageIndex('{scripturl}?action=' . ($context['group']['can_moderate'] ? 'moderate;area=viewgroups' : 'groups') . ';sa=members;group=' . $current_group . ';sort=' . $context['sort_by'] . ($this->_req->hasQuery('desc') ? ';desc' : ''), $context['start'], $context['total_members'], $modSettings['defaultMaxMembers']);
441
442
		// Fetch the members that meet the where criteria
443
		$query_params = [$where => $current_group, 'order' => $querySort, 'start' => $context['start'], 'limit' => $modSettings['defaultMaxMembers']];
444
		$context['members'] = membersBy($where, $query_params, true);
445
		foreach ($context['members'] as $id => $row)
446
		{
447
			$last_online = empty($row['last_login']) ? $txt['never'] : standardTime($row['last_login']);
448
449
			// Italicize the online note if they aren't activated.
450
			if ($row['is_activated'] % 10 !== 1)
451
			{
452
				$last_online = '<em title="' . $txt['not_activated'] . '">' . $last_online . '</em>';
453
			}
454
455
			$context['members'][$id] = [
456
				'id' => $row['id_member'],
457
				'name' => '<a href="' . getUrl('profile', ['action' => 'profile', 'u' => $row['id_member'], 'name' => $row['real_name']]) . '">' . $row['real_name'] . '</a>',
458
				'email' => $row['email_address'],
459
				'show_email' => showEmailAddress($row['id_member']),
460
				'ip' => '<a href="' . getUrl('action', ['action' => 'trackip', 'searchip' => $row['member_ip']]) . '">' . $row['member_ip'] . '</a>',
461
				'registered' => standardTime($row['date_registered']),
462
				'last_online' => $last_online,
463
				'posts' => comma_format($row['posts']),
464
				'is_activated' => $row['is_activated'] % 10 === 1,
465
			];
466
		}
467
468
		if (!empty($context['group']['assignable']))
469
		{
470
			loadJavascriptFile('suggest.js', ['defer' => true]);
471
		}
472
473
		// Select the template.
474
		$context['sub_template'] = 'group_members';
475
		$context['page_title'] = $txt['membergroups_members_title'] . ': ' . $context['group']['name'];
476
		createToken('mod-mgm');
477
	}
478
479
	/**
480
	 * Show and manage all group requests.
481
	 */
482
	public function action_requests(): void
483
	{
484
		global $txt, $context, $modSettings;
485
486
		// Set up the template stuff...
487
		$context['page_title'] = $txt['mc_group_requests'];
488
		$context['sub_template'] = 'show_list';
489
		$context[$context['moderation_menu_name']]['object']->prepareTabData([
490
			'title' => $txt['mc_group_requests'],
491
		]);
492
493
		// Verify we can be here.
494
		if ($this->user->mod_cache['gq'] === '0=1')
0 ignored issues
show
Bug Best Practice introduced by
The property mod_cache does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
495
		{
496
			isAllowedTo('manage_membergroups');
497
		}
498
499
		// Normally, we act normally...
500
		$where = $this->user->mod_cache['gq'] === '1=1' || $this->user->mod_cache['gq'] === '0=1' ? $this->user->mod_cache['gq'] : 'lgr.' . $this->user->mod_cache['gq'];
501
		$where_parameters = [];
502
503
		// We've submitted?
504
		if (isset($this->_req->post->{$context['session_var']})
505
			&& !empty($this->_req->post->groupr)
506
			&& !empty($this->_req->post->req_action))
507
		{
508
			checkSession();
509
			validateToken('mod-gr');
510
511
			require_once(SUBSDIR . '/Membergroups.subs.php');
512
513
			// Clean the values.
514
			$this->_req->post->groupr = array_map('intval', $this->_req->post->groupr);
515
516
			// If we are giving a reason (And why shouldn't we?), then we don't do much.
517
			if ($this->_req->post->req_action === 'reason')
518
			{
519
				// Different sub template...
520
				$context['sub_template'] = 'group_request_reason';
521
522
				// And a limitation. We don't care that the page number bit makes no sense, as we don't need it!
523
				$where .= ' AND lgr.id_request IN ({array_int:request_ids})';
524
				$where_parameters['request_ids'] = $this->_req->post->groupr;
525
526
				$context['group_requests'] = list_getGroupRequests(0, $modSettings['defaultMaxMessages'], 'lgr.id_request', $where, $where_parameters);
527
				createToken('mod-gr');
528
529
				// Let obExit etc sort things out.
530
				obExit();
531
			}
532
			// Otherwise we do something!
533
			else
534
			{
535
				// Get the details of all the members concerned...
536
				require_once(SUBSDIR . '/Members.subs.php');
537
				$concerned = getConcernedMembers($this->_req->post->groupr, $where, $this->_req->post->req_action === 'approve');
538
539
				// Cleanup old group requests.
540
				deleteGroupRequests($this->_req->post->groupr);
541
542
				// Ensure everyone who is online gets their changes right away.
543
				updateSettings(['settings_updated' => time()]);
544
545
				if (!empty($concerned['email_details']))
546
				{
547
					require_once(SUBSDIR . '/Mail.subs.php');
548
549
					// They are being approved?
550
					if ($this->_req->post->req_action === 'approve')
551
					{
552
						// Make the group changes.
553
						foreach ($concerned['group_changes'] as $id => $groups)
554
						{
555
							// Sanity check!
556
							foreach ($groups['add'] as $key => $value)
557
							{
558
								if ($value == 0 || trim($value) === '')
559
								{
560
									unset($groups['add'][$key]);
561
								}
562
							}
563
564
							assignGroupsToMember($id, $groups['primary'], $groups['add']);
565
						}
566
567
						foreach ($concerned['email_details'] as $email)
568
						{
569
							$replacements = [
570
								'USERNAME' => $email['member_name'],
571
								'GROUPNAME' => $email['group_name'],
572
							];
573
574
							$emaildata = loadEmailTemplate('mc_group_approve', $replacements, $email['language']);
575
576
							sendmail($email['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 2);
577
						}
578
					}
579
					// Otherwise, they are getting rejected (With or without a reason).
580
					else
581
					{
582
						// Same as for approving, kind of.
583
						foreach ($concerned['email_details'] as $email)
584
						{
585
							$custom_reason = $this->_req->post->groupreason[$email['rid']] ?? '';
586
587
							$replacements = [
588
								'USERNAME' => $email['member_name'],
589
								'GROUPNAME' => $email['group_name'],
590
							];
591
592
							if (!empty($custom_reason))
593
							{
594
								$replacements['REASON'] = $custom_reason;
595
							}
596
597
							$emaildata = loadEmailTemplate(empty($custom_reason) ? 'mc_group_reject' : 'mc_group_reject_reason', $replacements, $email['language']);
598
599
							sendmail($email['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 2);
600
						}
601
					}
602
				}
603
604
				// Restore the current language.
605
				Txt::load('ModerationCenter');
606
			}
607
		}
608
609
		// We're going to want this for making our list.
610
		require_once(SUBSDIR . '/Membergroups.subs.php');
611
612
		// This is all the information required for a group listing.
613
		$listOptions = [
614
			'id' => 'group_request_list',
615
			'width' => '100%',
616
			'items_per_page' => $modSettings['defaultMaxMessages'],
617
			'no_items_label' => $txt['mc_groupr_none_found'],
618
			'base_href' => getUrl('group', ['action' => 'groups', 'sa' => 'requests']),
619
			'default_sort_col' => 'member',
620
			'get_items' => [
621
				'function' => 'list_getGroupRequests',
622
				'params' => [
623
					$where,
624
					$where_parameters,
625
				],
626
			],
627
			'get_count' => [
628
				'function' => 'list_getGroupRequestCount',
629
				'params' => [
630
					$where,
631
					$where_parameters,
632
				],
633
			],
634
			'columns' => [
635
				'member' => [
636
					'header' => [
637
						'value' => $txt['mc_groupr_member'],
638
					],
639
					'data' => [
640
						'db' => 'member_link',
641
					],
642
					'sort' => [
643
						'default' => 'mem.member_name',
644
						'reverse' => 'mem.member_name DESC',
645
					],
646
				],
647
				'group' => [
648
					'header' => [
649
						'value' => $txt['mc_groupr_group'],
650
					],
651
					'data' => [
652
						'db' => 'group_link',
653
					],
654
					'sort' => [
655
						'default' => 'mg.group_name',
656
						'reverse' => 'mg.group_name DESC',
657
					],
658
				],
659
				'reason' => [
660
					'header' => [
661
						'value' => $txt['mc_groupr_reason'],
662
					],
663
					'data' => [
664
						'db' => 'reason',
665
					],
666
				],
667
				'date' => [
668
					'header' => [
669
						'value' => $txt['date'],
670
						'style' => 'width: 18%; white-space:nowrap;',
671
					],
672
					'data' => [
673
						'db' => 'time_submitted',
674
					],
675
				],
676
				'action' => [
677
					'header' => [
678
						'value' => '<input type="checkbox" class="input_check" onclick="invertAll(this, this.form);" />',
679
						'style' => 'width: 4%;text-align: center;',
680
					],
681
					'data' => [
682
						'sprintf' => [
683
							'format' => '<input type="checkbox" name="groupr[]" value="%1$d" class="input_check" />',
684
							'params' => [
685
								'id' => false,
686
							],
687
						],
688
						'class' => 'centertext',
689
					],
690
				],
691
			],
692
			'form' => [
693
				'href' => getUrl('group', ['action' => 'groups', 'sa' => 'requests']),
694
				'include_sort' => true,
695
				'include_start' => true,
696
				'hidden_fields' => [
697
					$context['session_var'] => $context['session_id'],
698
				],
699
				'token' => 'mod-gr',
700
			],
701
			'additional_rows' => [
702
				[
703
					'position' => 'bottom_of_list',
704
					'value' => '
705
						<select name="req_action" onchange="if (this.value != 0 &amp;&amp; (this.value === \'reason\' || confirm(\'' . $txt['mc_groupr_warning'] . '\'))) this.form.submit();">
706
							<option value="0">' . $txt['with_selected'] . ':</option>
707
							<option value="0" disabled="disabled">' . str_repeat('&#8212;', strlen($txt['mc_groupr_approve'])) . '</option>
708
							<option value="approve">&#10148;&nbsp;' . $txt['mc_groupr_approve'] . '</option>
709
							<option value="reject">&#10148;&nbsp;' . $txt['mc_groupr_reject'] . '</option>
710
							<option value="reason">&#10148;&nbsp;' . $txt['mc_groupr_reject_w_reason'] . '</option>
711
						</select>
712
						<input type="submit" name="go" value="' . $txt['go'] . '" onclick="var sel = document.getElementById(\'req_action\'); if (sel.value != 0 &amp;&amp; sel.value !== \'reason\' &amp;&amp; !confirm(\'' . $txt['mc_groupr_warning'] . '\')) return false;" />',
713
					'class' => 'floatright',
714
				],
715
			],
716
		];
717
718
		// Create the request list.
719
		createToken('mod-gr');
720
		createList($listOptions);
721
722
		$context['default_list'] = 'group_request_list';
723
	}
724
}
725