Completed
Push — release-2.1 ( 5876a2...f30e04 )
by Mert
06:50
created

ManageMembergroups.php ➔ EditMembergroup()   F

Complexity

Conditions 115
Paths 0

Size

Total Lines 582
Code Lines 293

Duplication

Lines 65
Ratio 11.17 %
Metric Value
cc 115
eloc 293
nc 0
nop 0
dl 65
loc 582
rs 2

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 is concerned with anything in the Manage Membergroups admin screen.
5
 *
6
 * Simple Machines Forum (SMF)
7
 *
8
 * @package SMF
9
 * @author Simple Machines http://www.simplemachines.org
10
 * @copyright 2016 Simple Machines and individual contributors
11
 * @license http://www.simplemachines.org/about/smf/license.php BSD
12
 *
13
 * @version 2.1 Beta 3
14
 */
15
16
if (!defined('SMF'))
17
	die('No direct access...');
18
19
20
/**
21
 * Main dispatcher, the entrance point for all 'Manage Membergroup' actions.
22
 * It forwards to a function based on the given subaction, default being subaction 'index', or, without manage_membergroup
23
 * permissions, then 'settings'.
24
 * Called by ?action=admin;area=membergroups.
25
 * Requires the manage_membergroups or the admin_forum permission.
26
 *
27
 * @uses ManageMembergroups template.
28
 * @uses ManageMembers language file.
29
*/
30
function ModifyMembergroups()
31
{
32
	global $context, $txt, $sourcedir;
33
34
	$subActions = array(
35
		'add' => array('AddMembergroup', 'manage_membergroups'),
36
		'delete' => array('DeleteMembergroup', 'manage_membergroups'),
37
		'edit' => array('EditMembergroup', 'manage_membergroups'),
38
		'index' => array('MembergroupIndex', 'manage_membergroups'),
39
		'members' => array('MembergroupMembers', 'manage_membergroups', 'Groups.php'),
40
		'settings' => array('ModifyMembergroupsettings', 'admin_forum'),
41
	);
42
43
	// Default to sub action 'index' or 'settings' depending on permissions.
44
	$_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : (allowedTo('manage_membergroups') ? 'index' : 'settings');
45
46
	// Is it elsewhere?
47
	if (isset($subActions[$_REQUEST['sa']][2]))
48
		require_once($sourcedir . '/' . $subActions[$_REQUEST['sa']][2]);
49
50
	// Do the permission check, you might not be allowed her.
51
	isAllowedTo($subActions[$_REQUEST['sa']][1]);
52
53
	// Language and template stuff, the usual.
54
	loadLanguage('ManageMembers');
55
	loadTemplate('ManageMembergroups');
56
57
	// Setup the admin tabs.
58
	$context[$context['admin_menu_name']]['tab_data'] = array(
59
		'title' => $txt['membergroups_title'],
60
		'help' => 'membergroups',
61
		'description' => $txt['membergroups_description'],
62
	);
63
64
	call_integration_hook('integrate_manage_membergroups', array(&$subActions));
65
66
	// Call the right function.
67
	call_helper($subActions[$_REQUEST['sa']][0]);
68
}
69
70
/**
71
 * Shows an overview of the current membergroups.
72
 * Called by ?action=admin;area=membergroups.
73
 * Requires the manage_membergroups permission.
74
 * Splits the membergroups in regular ones and post count based groups.
75
 * It also counts the number of members part of each membergroup.
76
 *
77
 * @uses ManageMembergroups template, main.
78
 */
79
function MembergroupIndex()
80
{
81
	global $txt, $scripturl, $context, $sourcedir;
82
83
	$context['page_title'] = $txt['membergroups_title'];
84
85
	// The first list shows the regular membergroups.
86
	$listOptions = array(
87
		'id' => 'regular_membergroups_list',
88
		'title' => $txt['membergroups_regular'],
89
		'base_href' => $scripturl . '?action=admin;area=membergroups' . (isset($_REQUEST['sort2']) ? ';sort2=' . urlencode($_REQUEST['sort2']) : ''),
90
		'default_sort_col' => 'name',
91
		'get_items' => array(
92
			'file' => $sourcedir . '/Subs-Membergroups.php',
93
			'function' => 'list_getMembergroups',
94
			'params' => array(
95
				'regular',
96
			),
97
		),
98
		'columns' => array(
99
			'name' => array(
100
				'header' => array(
101
					'value' => $txt['membergroups_name'],
102
				),
103
				'data' => array(
104
					'function' => function ($rowData) use ($scripturl)
105
					{
106
						// Since the moderator group has no explicit members, no link is needed.
107
						if ($rowData['id_group'] == 3)
108
							$group_name = $rowData['group_name'];
109 View Code Duplication
						else
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
110
						{
111
							$color_style = empty($rowData['online_color']) ? '' : sprintf(' style="color: %1$s;"', $rowData['online_color']);
112
							$group_name = sprintf('<a href="%1$s?action=admin;area=membergroups;sa=members;group=%2$d"%3$s>%4$s</a>', $scripturl, $rowData['id_group'], $color_style, $rowData['group_name']);
113
						}
114
115
						// Add a help option for moderator and administrator.
116 View Code Duplication
						if ($rowData['id_group'] == 1)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
117
							$group_name .= sprintf(' (<a href="%1$s?action=helpadmin;help=membergroup_administrator" onclick="return reqOverlayDiv(this.href);">?</a>)', $scripturl);
118
						elseif ($rowData['id_group'] == 3)
119
							$group_name .= sprintf(' (<a href="%1$s?action=helpadmin;help=membergroup_moderator" onclick="return reqOverlayDiv(this.href);">?</a>)', $scripturl);
120
121
						return $group_name;
122
					},
123
				),
124
				'sort' => array(
125
					'default' => 'CASE WHEN mg.id_group < 4 THEN mg.id_group ELSE 4 END, mg.group_name',
126
					'reverse' => 'CASE WHEN mg.id_group < 4 THEN mg.id_group ELSE 4 END, mg.group_name DESC',
127
				),
128
			),
129
			'icons' => array(
130
				'header' => array(
131
					'value' => $txt['membergroups_icons'],
132
				),
133
				'data' => array(
134
					'db' => 'icons',
135
				),
136
				'sort' => array(
137
					'default' => 'mg.icons',
138
					'reverse' => 'mg.icons DESC',
139
				)
140
			),
141
			'members' => array(
142
				'header' => array(
143
					'value' => $txt['membergroups_members_top'],
144
					'class' => 'centercol',
145
				),
146
				'data' => array(
147 View Code Duplication
					'function' => function ($rowData) use ($txt)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
148
					{
149
						// No explicit members for the moderator group.
150
						return $rowData['id_group'] == 3 ? $txt['membergroups_guests_na'] : comma_format($rowData['num_members']);
151
					},
152
					'class' => 'centercol',
153
				),
154
				'sort' => array(
155
					'default' => 'CASE WHEN mg.id_group < 4 THEN mg.id_group ELSE 4 END, 1',
156
					'reverse' => 'CASE WHEN mg.id_group < 4 THEN mg.id_group ELSE 4 END, 1 DESC',
157
				),
158
			),
159
			'modify' => array(
160
				'header' => array(
161
					'value' => $txt['modify'],
162
					'class' => 'centercol',
163
				),
164
				'data' => array(
165
					'sprintf' => array(
166
						'format' => '<a href="' . $scripturl . '?action=admin;area=membergroups;sa=edit;group=%1$d">' . $txt['membergroups_modify'] . '</a>',
167
						'params' => array(
168
							'id_group' => false,
169
						),
170
					),
171
					'class' => 'centercol',
172
				),
173
			),
174
		),
175
		'additional_rows' => array(
176
			array(
177
				'position' => 'above_table_headers',
178
				'value' => '<a class="button_link" href="' . $scripturl . '?action=admin;area=membergroups;sa=add;generalgroup">' . $txt['membergroups_add_group'] . '</a>',
179
			),
180
			array(
181
				'position' => 'below_table_data',
182
				'value' => '<a class="button_link" href="' . $scripturl . '?action=admin;area=membergroups;sa=add;generalgroup">' . $txt['membergroups_add_group'] . '</a>',
183
			),
184
		),
185
	);
186
187
	require_once($sourcedir . '/Subs-List.php');
188
	createList($listOptions);
189
190
	// The second list shows the post count based groups.
191
	$listOptions = array(
192
		'id' => 'post_count_membergroups_list',
193
		'title' => $txt['membergroups_post'],
194
		'base_href' => $scripturl . '?action=admin;area=membergroups' . (isset($_REQUEST['sort']) ? ';sort=' . urlencode($_REQUEST['sort']) : ''),
195
		'default_sort_col' => 'required_posts',
196
		'request_vars' => array(
197
			'sort' => 'sort2',
198
			'desc' => 'desc2',
199
		),
200
		'get_items' => array(
201
			'file' => $sourcedir . '/Subs-Membergroups.php',
202
			'function' => 'list_getMembergroups',
203
			'params' => array(
204
				'post_count',
205
			),
206
		),
207
		'columns' => array(
208
			'name' => array(
209
				'header' => array(
210
					'value' => $txt['membergroups_name'],
211
				),
212
				'data' => array(
213
					'function' => function ($rowData) use ($scripturl)
214
					{
215
						$colorStyle = empty($rowData['online_color']) ? '' : sprintf(' style="color: %1$s;"', $rowData['online_color']);
216
						return sprintf('<a href="%1$s?action=moderate;area=viewgroups;sa=members;group=%2$d"%3$s>%4$s</a>', $scripturl, $rowData['id_group'], $colorStyle, $rowData['group_name']);
217
					},
218
				),
219
				'sort' => array(
220
					'default' => 'mg.group_name',
221
					'reverse' => 'mg.group_name DESC',
222
				),
223
			),
224
			'icons' => array(
225
				'header' => array(
226
					'value' => $txt['membergroups_icons'],
227
				),
228
				'data' => array(
229
					'db' => 'icons',
230
				),
231
				'sort' => array(
232
					'default' => 'CASE WHEN mg.id_group < 4 THEN mg.id_group ELSE 4 END, icons',
233
					'reverse' => 'CASE WHEN mg.id_group < 4 THEN mg.id_group ELSE 4 END, icons DESC',
234
				)
235
			),
236
			'members' => array(
237
				'header' => array(
238
					'value' => $txt['membergroups_members_top'],
239
					'class' => 'centercol',
240
				),
241
				'data' => array(
242
					'db' => 'num_members',
243
					'class' => 'centercol',
244
				),
245
				'sort' => array(
246
					'default' => '1 DESC',
247
					'reverse' => '1',
248
				),
249
			),
250
			'required_posts' => array(
251
				'header' => array(
252
					'value' => $txt['membergroups_min_posts'],
253
					'class' => 'centercol',
254
				),
255
				'data' => array(
256
					'db' => 'min_posts',
257
					'class' => 'centercol',
258
				),
259
				'sort' => array(
260
					'default' => 'mg.min_posts',
261
					'reverse' => 'mg.min_posts DESC',
262
				),
263
			),
264
			'modify' => array(
265
				'header' => array(
266
					'value' => $txt['modify'],
267
					'class' => 'centercol',
268
				),
269
				'data' => array(
270
					'sprintf' => array(
271
						'format' => '<a href="' . $scripturl . '?action=admin;area=membergroups;sa=edit;group=%1$d">' . $txt['membergroups_modify'] . '</a>',
272
						'params' => array(
273
							'id_group' => false,
274
						),
275
					),
276
					'class' => 'centercol',
277
				),
278
			),
279
		),
280
		'additional_rows' => array(
281
			array(
282
				'position' => 'below_table_data',
283
				'value' => '<a class="button_link" href="' . $scripturl . '?action=admin;area=membergroups;sa=add;postgroup">' . $txt['membergroups_add_group'] . '</a>',
284
			),
285
		),
286
	);
287
288
	createList($listOptions);
289
}
290
291
/**
292
 * This function handles adding a membergroup and setting some initial properties.
293
 * Called by ?action=admin;area=membergroups;sa=add.
294
 * It requires the manage_membergroups permission.
295
 * Allows to use a predefined permission profile or copy one from another group.
296
 * Redirects to action=admin;area=membergroups;sa=edit;group=x.
297
 *
298
 * @uses the new_group sub template of ManageMembergroups.
299
 */
300
function AddMembergroup()
301
{
302
	global $context, $txt, $sourcedir, $modSettings, $smcFunc;
303
304
	// A form was submitted, we can start adding.
305
	if (isset($_POST['group_name']) && trim($_POST['group_name']) != '')
306
	{
307
		checkSession();
308
		validateToken('admin-mmg');
309
310
		$postCountBasedGroup = isset($_POST['min_posts']) && (!isset($_POST['postgroup_based']) || !empty($_POST['postgroup_based']));
311
		$_POST['group_type'] = !isset($_POST['group_type']) || $_POST['group_type'] < 0 || $_POST['group_type'] > 3 || ($_POST['group_type'] == 1 && !allowedTo('admin_forum')) ? 0 : (int) $_POST['group_type'];
312
313
		// @todo Check for members with same name too?
314
315
		$request = $smcFunc['db_query']('', '
316
			SELECT MAX(id_group)
317
			FROM {db_prefix}membergroups',
318
			array(
319
			)
320
		);
321
		list ($id_group) = $smcFunc['db_fetch_row']($request);
322
		$smcFunc['db_free_result']($request);
323
		$id_group++;
324
325
		$smcFunc['db_insert']('',
326
			'{db_prefix}membergroups',
327
			array(
328
				'id_group' => 'int', 'description' => 'string', 'group_name' => 'string-80', 'min_posts' => 'int',
329
				'icons' => 'string', 'online_color' => 'string', 'group_type' => 'int',
330
			),
331
			array(
332
				$id_group, '', $smcFunc['htmlspecialchars']($_POST['group_name'], ENT_QUOTES), ($postCountBasedGroup ? (int) $_POST['min_posts'] : '-1'),
333
				'1#icon.png', '', $_POST['group_type'],
334
			),
335
			array('id_group')
336
		);
337
338
		call_integration_hook('integrate_add_membergroup', array($id_group, $postCountBasedGroup));
339
340
		// Update the post groups now, if this is a post group!
341
		if (isset($_POST['min_posts']))
342
			updateStats('postgroups');
343
344
		// You cannot set permissions for post groups if they are disabled.
345
		if ($postCountBasedGroup && empty($modSettings['permission_enable_postgroups']))
346
			$_POST['perm_type'] = '';
347
348
		if ($_POST['perm_type'] == 'predefined')
349
		{
350
			// Set default permission level.
351
			require_once($sourcedir . '/ManagePermissions.php');
352
			setPermissionLevel($_POST['level'], $id_group, 'null');
353
		}
354
		// Copy or inherit the permissions!
355
		elseif ($_POST['perm_type'] == 'copy' || $_POST['perm_type'] == 'inherit')
356
		{
357
			$copy_id = $_POST['perm_type'] == 'copy' ? (int) $_POST['copyperm'] : (int) $_POST['inheritperm'];
358
359
			// Are you a powerful admin?
360
			if (!allowedTo('admin_forum'))
361
			{
362
				$request = $smcFunc['db_query']('', '
363
					SELECT group_type
364
					FROM {db_prefix}membergroups
365
					WHERE id_group = {int:copy_from}
366
					LIMIT {int:limit}',
367
					array(
368
						'copy_from' => $copy_id,
369
						'limit' => 1,
370
					)
371
				);
372
				list ($copy_type) = $smcFunc['db_fetch_row']($request);
373
				$smcFunc['db_free_result']($request);
374
375
				// Protected groups are... well, protected!
376
				if ($copy_type == 1)
377
					fatal_lang_error('membergroup_does_not_exist');
378
			}
379
380
			// Don't allow copying of a real priviledged person!
381
			require_once($sourcedir . '/ManagePermissions.php');
382
			loadIllegalPermissions();
383
384
			$request = $smcFunc['db_query']('', '
385
				SELECT permission, add_deny
386
				FROM {db_prefix}permissions
387
				WHERE id_group = {int:copy_from}',
388
				array(
389
					'copy_from' => $copy_id,
390
				)
391
			);
392
			$inserts = array();
393
			while ($row = $smcFunc['db_fetch_assoc']($request))
394
			{
395
				if (empty($context['illegal_permissions']) || !in_array($row['permission'], $context['illegal_permissions']))
396
					$inserts[] = array($id_group, $row['permission'], $row['add_deny']);
397
			}
398
			$smcFunc['db_free_result']($request);
399
400
			if (!empty($inserts))
401
				$smcFunc['db_insert']('insert',
402
					'{db_prefix}permissions',
403
					array('id_group' => 'int', 'permission' => 'string', 'add_deny' => 'int'),
404
					$inserts,
405
					array('id_group', 'permission')
406
				);
407
408
			$request = $smcFunc['db_query']('', '
409
				SELECT id_profile, permission, add_deny
410
				FROM {db_prefix}board_permissions
411
				WHERE id_group = {int:copy_from}',
412
				array(
413
					'copy_from' => $copy_id,
414
				)
415
			);
416
			$inserts = array();
417
			while ($row = $smcFunc['db_fetch_assoc']($request))
418
				$inserts[] = array($id_group, $row['id_profile'], $row['permission'], $row['add_deny']);
419
			$smcFunc['db_free_result']($request);
420
421 View Code Duplication
			if (!empty($inserts))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
422
				$smcFunc['db_insert']('insert',
423
					'{db_prefix}board_permissions',
424
					array('id_group' => 'int', 'id_profile' => 'int', 'permission' => 'string', 'add_deny' => 'int'),
425
					$inserts,
426
					array('id_group', 'id_profile', 'permission')
427
				);
428
429
			// Also get some membergroup information if we're copying and not copying from guests...
430
			if ($copy_id > 0 && $_POST['perm_type'] == 'copy')
431
			{
432
				$request = $smcFunc['db_query']('', '
433
					SELECT online_color, max_messages, icons
434
					FROM {db_prefix}membergroups
435
					WHERE id_group = {int:copy_from}
436
					LIMIT 1',
437
					array(
438
						'copy_from' => $copy_id,
439
					)
440
				);
441
				$group_info = $smcFunc['db_fetch_assoc']($request);
442
				$smcFunc['db_free_result']($request);
443
444
				// ...and update the new membergroup with it.
445
				$smcFunc['db_query']('', '
446
					UPDATE {db_prefix}membergroups
447
					SET
448
						online_color = {string:online_color},
449
						max_messages = {int:max_messages},
450
						icons = {string:icons}
451
					WHERE id_group = {int:current_group}',
452
					array(
453
						'max_messages' => $group_info['max_messages'],
454
						'current_group' => $id_group,
455
						'online_color' => $group_info['online_color'],
456
						'icons' => $group_info['icons'],
457
					)
458
				);
459
			}
460
			// If inheriting say so...
461
			elseif ($_POST['perm_type'] == 'inherit')
462
			{
463
				$smcFunc['db_query']('', '
464
					UPDATE {db_prefix}membergroups
465
					SET id_parent = {int:copy_from}
466
					WHERE id_group = {int:current_group}',
467
					array(
468
						'copy_from' => $copy_id,
469
						'current_group' => $id_group,
470
					)
471
				);
472
			}
473
		}
474
475
		// Make sure all boards selected are stored in a proper array.
476
		$accesses = empty($_POST['boardaccess']) || !is_array($_POST['boardaccess']) ? array() : $_POST['boardaccess'];
477
		$changed_boards['allow'] = array();
0 ignored issues
show
Coding Style Comprehensibility introduced by
$changed_boards was never initialized. Although not strictly required by PHP, it is generally a good practice to add $changed_boards = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
478
		$changed_boards['deny'] = array();
479
		$changed_boards['ignore'] = array();
480
		foreach ($accesses as $group_id => $action)
481
			$changed_boards[$action][] = (int) $group_id;
482
483
		foreach (array('allow', 'deny') as $board_action)
484
		{
485
			// Only do this if they have special access requirements.
486
			if (!empty($changed_boards[$board_action]))
487
				$smcFunc['db_query']('', '
488
					UPDATE {db_prefix}boards
489
					SET {raw:column} = CASE WHEN {raw:column} = {string:blank_string} THEN {string:group_id_string} ELSE CONCAT({raw:column}, {string:comma_group}) END
490
					WHERE id_board IN ({array_int:board_list})',
491
					array(
492
						'board_list' => $changed_boards[$board_action],
493
						'blank_string' => '',
494
						'group_id_string' => (string) $id_group,
495
						'comma_group' => ',' . $id_group,
496
						'column' => $board_action == 'allow' ? 'member_groups' : 'deny_member_groups',
497
					)
498
				);
499
		}
500
501
		// If this is joinable then set it to show group membership in people's profiles.
502
		if (empty($modSettings['show_group_membership']) && $_POST['group_type'] > 1)
503
			updateSettings(array('show_group_membership' => 1));
504
505
		// Rebuild the group cache.
506
		updateSettings(array(
507
			'settings_updated' => time(),
508
		));
509
510
		// We did it.
511
		logAction('add_group', array('group' => $smcFunc['htmlspecialchars']($_POST['group_name'])), 'admin');
512
513
		// Go change some more settings.
514
		redirectexit('action=admin;area=membergroups;sa=edit;group=' . $id_group);
515
	}
516
517
	// Just show the 'add membergroup' screen.
518
	$context['page_title'] = $txt['membergroups_new_group'];
519
	$context['sub_template'] = 'new_group';
520
	$context['post_group'] = isset($_REQUEST['postgroup']);
521
	$context['undefined_group'] = !isset($_REQUEST['postgroup']) && !isset($_REQUEST['generalgroup']);
522
	$context['allow_protected'] = allowedTo('admin_forum');
523
524
	if (!empty($modSettings['deny_boards_access']))
525
		loadLanguage('ManagePermissions');
526
527
	$result = $smcFunc['db_query']('', '
528
		SELECT id_group, group_name
529
		FROM {db_prefix}membergroups
530
		WHERE (id_group > {int:moderator_group} OR id_group = {int:global_mod_group})' . (empty($modSettings['permission_enable_postgroups']) ? '
531
			AND min_posts = {int:min_posts}' : '') . (allowedTo('admin_forum') ? '' : '
532
			AND group_type != {int:is_protected}') . '
533
		ORDER BY min_posts, id_group != {int:global_mod_group}, group_name',
534
		array(
535
			'moderator_group' => 3,
536
			'global_mod_group' => 2,
537
			'min_posts' => -1,
538
			'is_protected' => 1,
539
		)
540
	);
541
	$context['groups'] = array();
542
	while ($row = $smcFunc['db_fetch_assoc']($result))
543
		$context['groups'][] = array(
544
			'id' => $row['id_group'],
545
			'name' => $row['group_name']
546
		);
547
	$smcFunc['db_free_result']($result);
548
549
	$request = $smcFunc['db_query']('', '
550
		SELECT b.id_cat, c.name AS cat_name, b.id_board, b.name, b.child_level
551
		FROM {db_prefix}boards AS b
552
			LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)
553
		ORDER BY board_order',
554
		array(
555
		)
556
	);
557
	$context['num_boards'] = $smcFunc['db_num_rows']($request);
558
559
	$context['categories'] = array();
560
	while ($row = $smcFunc['db_fetch_assoc']($request))
561
	{
562
		// This category hasn't been set up yet..
563
		if (!isset($context['categories'][$row['id_cat']]))
564
			$context['categories'][$row['id_cat']] = array(
565
				'id' => $row['id_cat'],
566
				'name' => $row['cat_name'],
567
				'boards' => array()
568
			);
569
570
		// Set this board up, and let the template know when it's a child.  (indent them..)
571
		$context['categories'][$row['id_cat']]['boards'][$row['id_board']] = array(
572
			'id' => $row['id_board'],
573
			'name' => $row['name'],
574
			'child_level' => $row['child_level'],
575
			'allow' => false,
576
			'deny' => false
577
		);
578
579
	}
580
	$smcFunc['db_free_result']($request);
581
582
	// Now, let's sort the list of categories into the boards for templates that like that.
583
	$temp_boards = array();
584 View Code Duplication
	foreach ($context['categories'] as $category)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
585
	{
586
		$temp_boards[] = array(
587
			'name' => $category['name'],
588
			'child_ids' => array_keys($category['boards'])
589
		);
590
		$temp_boards = array_merge($temp_boards, array_values($category['boards']));
591
592
		// Include a list of boards per category for easy toggling.
593
		$context['categories'][$category['id']]['child_ids'] = array_keys($category['boards']);
594
	}
595
596
	createToken('admin-mmg');
597
}
598
599
/**
600
 * Deleting a membergroup by URL (not implemented).
601
 * Called by ?action=admin;area=membergroups;sa=delete;group=x;session_var=y.
602
 * Requires the manage_membergroups permission.
603
 * Redirects to ?action=admin;area=membergroups.
604
 *
605
 * @todo look at this
606
 */
607
function DeleteMembergroup()
608
{
609
	global $sourcedir;
610
611
	checkSession('get');
612
613
	require_once($sourcedir . '/Subs-Membergroups.php');
614
	$result = deleteMembergroups((int) $_REQUEST['group']);
615
	// Need to throw a warning if it went wrong, but this is the only one we have a message for...
616
	if ($result === 'group_cannot_delete_sub')
617
		fatal_lang_error('membergroups_cannot_delete_paid', false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
618
619
	// Go back to the membergroup index.
620
	redirectexit('action=admin;area=membergroups;');
621
}
622
623
/**
624
 * Editing a membergroup.
625
 * Screen to edit a specific membergroup.
626
 * Called by ?action=admin;area=membergroups;sa=edit;group=x.
627
 * It requires the manage_membergroups permission.
628
 * Also handles the delete button of the edit form.
629
 * Redirects to ?action=admin;area=membergroups.
630
 *
631
 * @uses the edit_group sub template of ManageMembergroups.
632
 */
633
function EditMembergroup()
634
{
635
	global $context, $txt, $sourcedir, $modSettings, $smcFunc, $settings;
636
637
	$_REQUEST['group'] = isset($_REQUEST['group']) && $_REQUEST['group'] > 0 ? (int) $_REQUEST['group'] : 0;
638
639
	if (!empty($modSettings['deny_boards_access']))
640
		loadLanguage('ManagePermissions');
641
642
	// Make sure this group is editable.
643
	if (!empty($_REQUEST['group']))
644
	{
645
		$request = $smcFunc['db_query']('', '
646
			SELECT id_group
647
			FROM {db_prefix}membergroups
648
			WHERE id_group = {int:current_group}' . (allowedTo('admin_forum') ? '' : '
649
				AND group_type != {int:is_protected}') . '
650
			LIMIT {int:limit}',
651
			array(
652
				'current_group' => $_REQUEST['group'],
653
				'is_protected' => 1,
654
				'limit' => 1,
655
			)
656
		);
657
		list ($_REQUEST['group']) = $smcFunc['db_fetch_row']($request);
658
		$smcFunc['db_free_result']($request);
659
	}
660
661
	// Now, do we have a valid id?
662
	if (empty($_REQUEST['group']))
663
		fatal_lang_error('membergroup_does_not_exist', false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
664
665
	// People who can manage boards are a bit special.
666
	require_once($sourcedir . '/Subs-Members.php');
667
	$board_managers = groupsAllowedTo('manage_boards', null);
668
	$context['can_manage_boards'] = in_array($_REQUEST['group'], $board_managers['allowed']);
669
670
	// Can this group moderate any boards?
671
	$request = $smcFunc['db_query']('', '
672
		SELECT COUNT(id_board)
673
		FROM {db_prefix}moderator_groups
674
		WHERE id_group = {int:current_group}',
675
		array(
676
			'current_group' => $_REQUEST['group'],
677
		)
678
	);
679
680
	// Why don't we have a $smcFunc['db_result'] function?
681
	$result = $smcFunc['db_fetch_row']($request);
682
	$context['is_moderator_group'] = ($result[0] > 0);
683
	$smcFunc['db_free_result']($request);
684
685
	// The delete this membergroup button was pressed.
686
	if (isset($_POST['delete']))
687
	{
688
		checkSession();
689
		validateToken('admin-mmg');
690
691
		require_once($sourcedir . '/Subs-Membergroups.php');
692
		$result = deleteMembergroups($_REQUEST['group']);
693
		// Need to throw a warning if it went wrong, but this is the only one we have a message for...
694
		if ($result === 'group_cannot_delete_sub')
695
			fatal_lang_error('membergroups_cannot_delete_paid', false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
696
697
		redirectexit('action=admin;area=membergroups;');
698
	}
699
	// A form was submitted with the new membergroup settings.
700
	elseif (isset($_POST['save']))
701
	{
702
		// Validate the session.
703
		checkSession();
704
		validateToken('admin-mmg');
705
706
		// Can they really inherit from this group?
707
		if ($_REQUEST['group'] > 1 && $_REQUEST['group'] != 3 && isset($_POST['group_inherit']) && $_POST['group_inherit'] != -2 && !allowedTo('admin_forum'))
708
		{
709
			$request = $smcFunc['db_query']('', '
710
				SELECT group_type
711
				FROM {db_prefix}membergroups
712
				WHERE id_group = {int:inherit_from}
713
				LIMIT {int:limit}',
714
				array(
715
					'inherit_from' => $_POST['group_inherit'],
716
					'limit' => 1,
717
				)
718
			);
719
			list ($inherit_type) = $smcFunc['db_fetch_row']($request);
720
			$smcFunc['db_free_result']($request);
721
		}
722
723
		// Set variables to their proper value.
724
		$_POST['max_messages'] = isset($_POST['max_messages']) ? (int) $_POST['max_messages'] : 0;
725
		$_POST['min_posts'] = isset($_POST['min_posts']) && isset($_POST['group_type']) && $_POST['group_type'] == -1 && $_REQUEST['group'] > 3 ? abs($_POST['min_posts']) : ($_REQUEST['group'] == 4 ? 0 : -1);
726
		$_POST['icons'] = (empty($_POST['icon_count']) || $_POST['icon_count'] < 0) ? '' : min((int) $_POST['icon_count'], 99) . '#' . $_POST['icon_image'];
727
		$_POST['group_desc'] = isset($_POST['group_desc']) && ($_REQUEST['group'] == 1 || (isset($_POST['group_type']) && $_POST['group_type'] != -1)) ? trim($_POST['group_desc']) : '';
728
		$_POST['group_type'] = !isset($_POST['group_type']) || $_POST['group_type'] < 0 || $_POST['group_type'] > 3 || ($_POST['group_type'] == 1 && !allowedTo('admin_forum')) ? 0 : (int) $_POST['group_type'];
729
		$_POST['group_hidden'] = empty($_POST['group_hidden']) || $_POST['min_posts'] != -1 || $_REQUEST['group'] == 3 ? 0 : (int) $_POST['group_hidden'];
730
		$_POST['group_inherit'] = $_REQUEST['group'] > 1 && $_REQUEST['group'] != 3 && (empty($inherit_type) || $inherit_type != 1) ? (int) $_POST['group_inherit'] : -2;
0 ignored issues
show
Bug introduced by
The variable $inherit_type 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...
731
		$_POST['group_tfa_force'] = (empty($modSettings['tfa_mode']) || $modSettings['tfa_mode'] != 2 || empty($_POST['group_tfa_force'])) ? 0 : 1;
732
733
		//@todo Don't set online_color for the Moderators group?
734
735
		// Do the update of the membergroup settings.
736
		$smcFunc['db_query']('', '
737
			UPDATE {db_prefix}membergroups
738
			SET group_name = {string:group_name}, online_color = {string:online_color},
739
				max_messages = {int:max_messages}, min_posts = {int:min_posts}, icons = {string:icons},
740
				description = {string:group_desc}, group_type = {int:group_type}, hidden = {int:group_hidden},
741
				id_parent = {int:group_inherit}, tfa_required = {int:tfa_required}
742
			WHERE id_group = {int:current_group}',
743
			array(
744
				'max_messages' => $_POST['max_messages'],
745
				'min_posts' => $_POST['min_posts'],
746
				'group_type' => $_POST['group_type'],
747
				'group_hidden' => $_POST['group_hidden'],
748
				'group_inherit' => $_POST['group_inherit'],
749
				'current_group' => (int) $_REQUEST['group'],
750
				'group_name' => $smcFunc['htmlspecialchars']($_POST['group_name']),
751
				'online_color' => $_POST['online_color'],
752
				'icons' => $_POST['icons'],
753
				'group_desc' => $_POST['group_desc'],
754
				'tfa_required' => $_POST['group_tfa_force'],
755
			)
756
		);
757
758
		call_integration_hook('integrate_save_membergroup', array((int) $_REQUEST['group']));
759
760
		// Time to update the boards this membergroup has access to.
761
		if ($_REQUEST['group'] == 2 || $_REQUEST['group'] > 3)
762
		{
763
			$accesses = empty($_POST['boardaccess']) || !is_array($_POST['boardaccess']) ? array() : $_POST['boardaccess'];
764
765
			// If they can manage boards, the rules are a bit different. They can see everything.
766
			if ($context['can_manage_boards'])
767
			{
768
				$accesses = array();
769
				$request = $smcFunc['db_query']('', '
770
					SELECT id_board
771
					FROM {db_prefix}boards');
772
				while ($row = $smcFunc['db_fetch_assoc']($request))
773
					$accesses[(int) $row['id_board']] = 'allow';
774
				$smcFunc['db_free_result']($request);
775
			}
776
777
			$changed_boards['allow'] = array();
0 ignored issues
show
Coding Style Comprehensibility introduced by
$changed_boards was never initialized. Although not strictly required by PHP, it is generally a good practice to add $changed_boards = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
778
			$changed_boards['deny'] = array();
779
			$changed_boards['ignore'] = array();
780
			foreach ($accesses as $group_id => $action)
781
				$changed_boards[$action][] = (int) $group_id;
782
783
			foreach (array('allow', 'deny') as $board_action)
784
			{
785
				// Find all board this group is in, but shouldn't be in.
786
				$request = $smcFunc['db_query']('', '
787
					SELECT id_board, {raw:column}
788
					FROM {db_prefix}boards
789
					WHERE FIND_IN_SET({string:current_group}, {raw:column}) != 0' . (empty($changed_boards[$board_action]) ? '' : '
790
						AND id_board NOT IN ({array_int:board_access_list})'),
791
					array(
792
						'current_group' => (int) $_REQUEST['group'],
793
						'board_access_list' => $changed_boards[$board_action],
794
						'column' => $board_action == 'allow' ? 'member_groups' : 'deny_member_groups',
795
					)
796
				);
797
				while ($row = $smcFunc['db_fetch_assoc']($request))
798
					$smcFunc['db_query']('', '
799
						UPDATE {db_prefix}boards
800
						SET {raw:column} = {string:member_group_access}
801
						WHERE id_board = {int:current_board}',
802
						array(
803
							'current_board' => $row['id_board'],
804
							'member_group_access' => implode(',', array_diff(explode(',', $row['member_groups']), array($_REQUEST['group']))),
805
							'column' => $board_action == 'allow' ? 'member_groups' : 'deny_member_groups',
806
						)
807
					);
808
				$smcFunc['db_free_result']($request);
809
810
				// Add the membergroup to all boards that hadn't been set yet.
811
				if (!empty($changed_boards[$board_action]))
812
					$smcFunc['db_query']('', '
813
						UPDATE {db_prefix}boards
814
						SET {raw:column} = CASE WHEN {raw:column} = {string:blank_string} THEN {string:group_id_string} ELSE CONCAT({raw:column}, {string:comma_group}) END
815
						WHERE id_board IN ({array_int:board_list})
816
							AND FIND_IN_SET({int:current_group}, {raw:column}) = 0',
817
						array(
818
							'board_list' => $changed_boards[$board_action],
819
							'blank_string' => '',
820
							'current_group' => (int) $_REQUEST['group'],
821
							'group_id_string' => (string) (int) $_REQUEST['group'],
822
							'comma_group' => ',' . $_REQUEST['group'],
823
							'column' => $board_action == 'allow' ? 'member_groups' : 'deny_member_groups',
824
						)
825
					);
826
			}
827
		}
828
829
		// Remove everyone from this group!
830
		if ($_POST['min_posts'] != -1)
831
		{
832
			$smcFunc['db_query']('', '
833
				UPDATE {db_prefix}members
834
				SET id_group = {int:regular_member}
835
				WHERE id_group = {int:current_group}',
836
				array(
837
					'regular_member' => 0,
838
					'current_group' => (int) $_REQUEST['group'],
839
				)
840
			);
841
842
			$request = $smcFunc['db_query']('', '
843
				SELECT id_member, additional_groups
844
				FROM {db_prefix}members
845
				WHERE FIND_IN_SET({string:current_group}, additional_groups) != 0',
846
				array(
847
					'current_group' => (int) $_REQUEST['group'],
848
				)
849
			);
850
			$updates = array();
851 View Code Duplication
			while ($row = $smcFunc['db_fetch_assoc']($request))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
852
				$updates[$row['additional_groups']][] = $row['id_member'];
853
			$smcFunc['db_free_result']($request);
854
855 View Code Duplication
			foreach ($updates as $additional_groups => $memberArray)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
856
				updateMemberData($memberArray, array('additional_groups' => implode(',', array_diff(explode(',', $additional_groups), array((int) $_REQUEST['group'])))));
857
858
			// Sorry, but post groups can't moderate boards
859
			$request = $smcFunc['db_query']('', '
0 ignored issues
show
Unused Code introduced by
$request is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
860
				DELETE FROM {db_prefix}moderator_groups
861
				WHERE id_group = {int:current_group}',
862
				array(
863
					'current_group' => (int) $_REQUEST['group'],
864
				)
865
			);
866
		}
867
		elseif ($_REQUEST['group'] != 3)
868
		{
869
			// Making it a hidden group? If so remove everyone with it as primary group (Actually, just make them additional).
870
			if ($_POST['group_hidden'] == 2)
871
			{
872
				$request = $smcFunc['db_query']('', '
873
					SELECT id_member, additional_groups
874
					FROM {db_prefix}members
875
					WHERE id_group = {int:current_group}
876
						AND FIND_IN_SET({int:current_group}, additional_groups) = 0',
877
					array(
878
						'current_group' => (int) $_REQUEST['group'],
879
					)
880
				);
881
				$updates = array();
882 View Code Duplication
				while ($row = $smcFunc['db_fetch_assoc']($request))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
883
					$updates[$row['additional_groups']][] = $row['id_member'];
884
				$smcFunc['db_free_result']($request);
885
886
				foreach ($updates as $additional_groups => $memberArray)
887
				{
888
					$new_groups = (!empty($additional_groups) ? $additional_groups . ',' : '') . $_REQUEST['group']; // We already validated this a while ago.
889
					updateMemberData($memberArray, array('additional_groups' => $new_groups));
890
				}
891
892
				$smcFunc['db_query']('', '
893
					UPDATE {db_prefix}members
894
					SET id_group = {int:regular_member}
895
					WHERE id_group = {int:current_group}',
896
					array(
897
						'regular_member' => 0,
898
						'current_group' => $_REQUEST['group'],
899
					)
900
				);
901
902
				// Hidden groups can't moderate boards
903
				$smcFunc['db_query']('', '
904
					DELETE FROM {db_prefix}moderator_groups
905
					WHERE id_group = {int:current_group}',
906
					array(
907
						'current_group' => $_REQUEST['group'],
908
					)
909
				);
910
			}
911
912
			// Either way, let's check our "show group membership" setting is correct.
913
			$request = $smcFunc['db_query']('', '
914
				SELECT COUNT(*)
915
				FROM {db_prefix}membergroups
916
				WHERE group_type > {int:non_joinable}',
917
				array(
918
					'non_joinable' => 1,
919
				)
920
			);
921
			list ($have_joinable) = $smcFunc['db_fetch_row']($request);
922
			$smcFunc['db_free_result']($request);
923
924
			// Do we need to update the setting?
925
			if ((empty($modSettings['show_group_membership']) && $have_joinable) || (!empty($modSettings['show_group_membership']) && !$have_joinable))
926
				updateSettings(array('show_group_membership' => $have_joinable ? 1 : 0));
927
		}
928
929
		// Do we need to set inherited permissions?
930
		if ($_POST['group_inherit'] != -2 && $_POST['group_inherit'] != $_POST['old_inherit'])
931
		{
932
			require_once($sourcedir . '/ManagePermissions.php');
933
			updateChildPermissions($_POST['group_inherit']);
934
		}
935
936
		// Finally, moderators!
937
		$moderator_string = isset($_POST['group_moderators']) ? trim($_POST['group_moderators']) : '';
938
		$smcFunc['db_query']('', '
939
			DELETE FROM {db_prefix}group_moderators
940
			WHERE id_group = {int:current_group}',
941
			array(
942
				'current_group' => $_REQUEST['group'],
943
			)
944
		);
945
		if ((!empty($moderator_string) || !empty($_POST['moderator_list'])) && $_POST['min_posts'] == -1 && $_REQUEST['group'] != 3)
946
		{
947
			$group_moderators = array();
948
949
			// Get all the usernames from the string
950
			if (!empty($moderator_string))
951
			{
952
				$moderator_string = strtr(preg_replace('~&amp;#(\d{4,5}|[2-9]\d{2,4}|1[2-9]\d);~', '&#$1;', $smcFunc['htmlspecialchars']($moderator_string, ENT_QUOTES)), array('&quot;' => '"'));
953
				preg_match_all('~"([^"]+)"~', $moderator_string, $matches);
954
				$moderators = array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $moderator_string)));
955 View Code Duplication
				for ($k = 0, $n = count($moderators); $k < $n; $k++)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
956
				{
957
					$moderators[$k] = trim($moderators[$k]);
958
959
					if (strlen($moderators[$k]) == 0)
960
						unset($moderators[$k]);
961
				}
962
963
				// Find all the id_member's for the member_name's in the list.
964 View Code Duplication
				if (!empty($moderators))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
965
				{
966
					$request = $smcFunc['db_query']('', '
967
						SELECT id_member
968
						FROM {db_prefix}members
969
						WHERE member_name IN ({array_string:moderators}) OR real_name IN ({array_string:moderators})
970
						LIMIT {int:count}',
971
						array(
972
							'moderators' => $moderators,
973
							'count' => count($moderators),
974
						)
975
					);
976
					while ($row = $smcFunc['db_fetch_assoc']($request))
977
						$group_moderators[] = $row['id_member'];
978
					$smcFunc['db_free_result']($request);
979
				}
980
			}
981
982 View Code Duplication
			if (!empty($_POST['moderator_list']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
983
			{
984
				$moderators = array();
985
				foreach ($_POST['moderator_list'] as $moderator)
986
					$moderators[] = (int) $moderator;
987
988
				if (!empty($moderators))
989
				{
990
					$request = $smcFunc['db_query']('', '
991
						SELECT id_member
992
						FROM {db_prefix}members
993
						WHERE id_member IN ({array_int:moderators})
994
						LIMIT {int:num_moderators}',
995
						array(
996
							'moderators' => $moderators,
997
							'num_moderators' => count($moderators),
998
						)
999
					);
1000
					while ($row = $smcFunc['db_fetch_assoc']($request))
1001
						$group_moderators[] = $row['id_member'];
1002
					$smcFunc['db_free_result']($request);
1003
				}
1004
			}
1005
1006
			// Make sure we don't have any duplicates first...
1007
			$group_moderators = array_unique($group_moderators);
1008
1009
			// Found some?
1010
			if (!empty($group_moderators))
1011
			{
1012
				$mod_insert = array();
1013
				foreach ($group_moderators as $moderator)
1014
					$mod_insert[] = array($_REQUEST['group'], $moderator);
1015
1016
				$smcFunc['db_insert']('insert',
1017
					'{db_prefix}group_moderators',
1018
					array('id_group' => 'int', 'id_member' => 'int'),
1019
					$mod_insert,
1020
					array('id_group', 'id_member')
1021
				);
1022
			}
1023
		}
1024
1025
		// There might have been some post group changes.
1026
		updateStats('postgroups');
1027
		// We've definitely changed some group stuff.
1028
		updateSettings(array(
1029
			'settings_updated' => time(),
1030
		));
1031
1032
		// Log the edit.
1033
		logAction('edited_group', array('group' => $smcFunc['htmlspecialchars']($_POST['group_name'])), 'admin');
1034
1035
		redirectexit('action=admin;area=membergroups');
1036
	}
1037
1038
	// Fetch the current group information.
1039
	$request = $smcFunc['db_query']('', '
1040
		SELECT group_name, description, min_posts, online_color, max_messages, icons, group_type, hidden, id_parent, tfa_required
1041
		FROM {db_prefix}membergroups
1042
		WHERE id_group = {int:current_group}
1043
		LIMIT 1',
1044
		array(
1045
			'current_group' => (int) $_REQUEST['group'],
1046
		)
1047
	);
1048
	if ($smcFunc['db_num_rows']($request) == 0)
1049
		fatal_lang_error('membergroup_does_not_exist', false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1050
	$row = $smcFunc['db_fetch_assoc']($request);
1051
	$smcFunc['db_free_result']($request);
1052
1053
	$row['icons'] = explode('#', $row['icons']);
1054
1055
	$context['group'] = array(
1056
		'id' => $_REQUEST['group'],
1057
		'name' => $row['group_name'],
1058
		'description' => $smcFunc['htmlspecialchars']($row['description'], ENT_QUOTES),
1059
		'editable_name' => $row['group_name'],
1060
		'color' => $row['online_color'],
1061
		'min_posts' => $row['min_posts'],
1062
		'max_messages' => $row['max_messages'],
1063
		'icon_count' => (int) $row['icons'][0],
1064
		'icon_image' => isset($row['icons'][1]) ? $row['icons'][1] : '',
1065
		'is_post_group' => $row['min_posts'] != -1,
1066
		'type' => $row['min_posts'] != -1 ? 0 : $row['group_type'],
1067
		'hidden' => $row['min_posts'] == -1 ? $row['hidden'] : 0,
1068
		'inherited_from' => $row['id_parent'],
1069
		'allow_post_group' => $_REQUEST['group'] == 2 || $_REQUEST['group'] > 4,
1070
		'allow_delete' => $_REQUEST['group'] == 2 || $_REQUEST['group'] > 4,
1071
		'allow_protected' => allowedTo('admin_forum'),
1072
		'tfa_required' => $row['tfa_required'],
1073
	);
1074
1075
	// Get any moderators for this group
1076
	$request = $smcFunc['db_query']('', '
1077
		SELECT mem.id_member, mem.real_name
1078
		FROM {db_prefix}group_moderators AS mods
1079
			INNER JOIN {db_prefix}members AS mem ON (mem.id_member = mods.id_member)
1080
		WHERE mods.id_group = {int:current_group}',
1081
		array(
1082
			'current_group' => $_REQUEST['group'],
1083
		)
1084
	);
1085
	$context['group']['moderators'] = array();
1086
	while ($row = $smcFunc['db_fetch_assoc']($request))
1087
		$context['group']['moderators'][$row['id_member']] = $row['real_name'];
1088
	$smcFunc['db_free_result']($request);
1089
1090
	$context['group']['moderator_list'] = empty($context['group']['moderators']) ? '' : '&quot;' . implode('&quot;, &quot;', $context['group']['moderators']) . '&quot;';
1091
1092 View Code Duplication
	if (!empty($context['group']['moderators']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1093
		list ($context['group']['last_moderator_id']) = array_slice(array_keys($context['group']['moderators']), -1);
1094
1095
	// Get a list of boards this membergroup is allowed to see.
1096
	$context['boards'] = array();
1097
	if ($_REQUEST['group'] == 2 || $_REQUEST['group'] > 3)
1098
	{
1099
		$request = $smcFunc['db_query']('', '
1100
			SELECT b.id_cat, c.name as cat_name, b.id_board, b.name, b.child_level,
1101
			FIND_IN_SET({string:current_group}, b.member_groups) != 0 AS can_access, FIND_IN_SET({string:current_group}, b.deny_member_groups) != 0 AS cannot_access
1102
			FROM {db_prefix}boards AS b
1103
				LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)
1104
			ORDER BY board_order',
1105
			array(
1106
				'current_group' => (int) $_REQUEST['group'],
1107
			)
1108
		);
1109
		$context['categories'] = array();
1110
		while ($row = $smcFunc['db_fetch_assoc']($request))
1111
		{
1112
			// This category hasn't been set up yet..
1113
			if (!isset($context['categories'][$row['id_cat']]))
1114
				$context['categories'][$row['id_cat']] = array(
1115
					'id' => $row['id_cat'],
1116
					'name' => $row['cat_name'],
1117
					'boards' => array()
1118
				);
1119
1120
			// Set this board up, and let the template know when it's a child.  (indent them..)
1121
			$context['categories'][$row['id_cat']]['boards'][$row['id_board']] = array(
1122
				'id' => $row['id_board'],
1123
				'name' => $row['name'],
1124
				'child_level' => $row['child_level'],
1125
				'allow' => !(empty($row['can_access']) || $row['can_access'] == 'f'),
1126
				'deny' => !(empty($row['cannot_access']) || $row['cannot_access'] == 'f'),
1127
			);
1128
		}
1129
		$smcFunc['db_free_result']($request);
1130
1131
		// Now, let's sort the list of categories into the boards for templates that like that.
1132
		$temp_boards = array();
1133 View Code Duplication
		foreach ($context['categories'] as $category)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1134
		{
1135
			$temp_boards[] = array(
1136
				'name' => $category['name'],
1137
				'child_ids' => array_keys($category['boards'])
1138
			);
1139
			$temp_boards = array_merge($temp_boards, array_values($category['boards']));
1140
1141
			// Include a list of boards per category for easy toggling.
1142
			$context['categories'][$category['id']]['child_ids'] = array_keys($category['boards']);
1143
		}
1144
1145
		$max_boards = ceil(count($temp_boards) / 2);
1146
		if ($max_boards == 1)
1147
			$max_boards = 2;
0 ignored issues
show
Unused Code introduced by
$max_boards is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1148
	}
1149
1150
	// Get a list of all the image formats we can select.
1151
	$imageExts = array('png', 'jpg', 'jpeg', 'bmp', 'gif');
1152
1153
	// Scan the directory.
1154
	$context['possible_icons'] = array();
1155
	if ($files = scandir($settings['default_theme_dir'] . '/images/membericons'))
1156
	{
1157
		// Loop through every file in the directory.
1158
		foreach ($files as $value)
1159
		{
1160
			// Grab the image extension.
1161
			$ext = pathinfo($settings['default_theme_dir'] . '/images/membericons/' . $value, PATHINFO_EXTENSION);
1162
1163
			// If the extension is not empty, and it is valid
1164
			if (!empty($ext) && in_array($ext, $imageExts))
1165
			{
1166
				// Get the size of the image.
1167
				$image_info = getimagesize($settings['default_theme_dir'] . '/images/membericons/' . $value);
1168
1169
				// If this is bigger than 128 in width or 32 in height, skip this one.
1170
				if ($image_info == false || $image_info[0] > 128 || $image_info[1] > 32)
1171
					continue;
1172
1173
				// Else it's valid. Add it in.
1174
				else
1175
					$context['possible_icons'][] = $value;
1176
			}
1177
		}
1178
	}
1179
1180
	// Insert our JS, if we have possible icons.
1181
	if (!empty($context['possible_icons']))
1182
		loadJavascriptFile('icondropdown.js', array('validate' => true), 'smf_icondropdown');
1183
1184
		loadJavascriptFile('suggest.js', array('defer' => false), 'smf_suggest');
1185
1186
	// Finally, get all the groups this could be inherited off.
1187
	$request = $smcFunc['db_query']('', '
1188
		SELECT id_group, group_name
1189
		FROM {db_prefix}membergroups
1190
		WHERE id_group != {int:current_group}' .
1191
			(empty($modSettings['permission_enable_postgroups']) ? '
1192
			AND min_posts = {int:min_posts}' : '') . (allowedTo('admin_forum') ? '' : '
1193
			AND group_type != {int:is_protected}') . '
1194
			AND id_group NOT IN (1, 3)
1195
			AND id_parent = {int:not_inherited}',
1196
		array(
1197
			'current_group' => (int) $_REQUEST['group'],
1198
			'min_posts' => -1,
1199
			'not_inherited' => -2,
1200
			'is_protected' => 1,
1201
		)
1202
	);
1203
	$context['inheritable_groups'] = array();
1204
	while ($row = $smcFunc['db_fetch_assoc']($request))
1205
		$context['inheritable_groups'][$row['id_group']] = $row['group_name'];
1206
	$smcFunc['db_free_result']($request);
1207
1208
	call_integration_hook('integrate_view_membergroup');
1209
1210
	$context['sub_template'] = 'edit_group';
1211
	$context['page_title'] = $txt['membergroups_edit_group'];
1212
1213
	createToken('admin-mmg');
1214
}
1215
1216
/**
1217
 * Set some general membergroup settings and permissions.
1218
 * Called by ?action=admin;area=membergroups;sa=settings
1219
 * Requires the admin_forum permission (and manage_permissions for changing permissions)
1220
 * Redirects to itself.
1221
 *
1222
 * @uses membergroup_settings sub template of ManageMembergroups.
1223
 */
1224
function ModifyMembergroupsettings()
1225
{
1226
	global $context, $sourcedir, $scripturl, $txt;
1227
1228
	$context['sub_template'] = 'show_settings';
1229
	$context['page_title'] = $txt['membergroups_settings'];
1230
1231
	// Needed for the settings functions.
1232
	require_once($sourcedir . '/ManageServer.php');
1233
1234
	// Only one thing here!
1235
	$config_vars = array(
1236
			array('permissions', 'manage_membergroups'),
1237
	);
1238
1239
	call_integration_hook('integrate_modify_membergroup_settings', array(&$config_vars));
1240
1241
	if (isset($_REQUEST['save']))
1242
	{
1243
		checkSession();
1244
		call_integration_hook('integrate_save_membergroup_settings');
1245
1246
		// Yeppers, saving this...
1247
		saveDBSettings($config_vars);
1248
		$_SESSION['adm-save'] = true;
1249
		redirectexit('action=admin;area=membergroups;sa=settings');
1250
	}
1251
1252
	// Some simple context.
1253
	$context['post_url'] = $scripturl . '?action=admin;area=membergroups;save;sa=settings';
1254
	$context['settings_title'] = $txt['membergroups_settings'];
1255
1256
	// We need this for the in-line permissions
1257
	createToken('admin-mp');
1258
1259
	prepareDBSettingContext($config_vars);
1260
}
1261
1262
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...