loadAllPermissions()   F
last analyzed

Complexity

Conditions 30
Paths > 20000

Size

Total Lines 298
Code Lines 182

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 930

Importance

Changes 0
Metric Value
cc 30
eloc 182
nc 665984
nop 0
dl 0
loc 298
ccs 0
cts 86
cp 0
crap 930
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
 * Support functions and db interface functions for permissions
5
 *
6
 * @package   ElkArte Forum
7
 * @copyright ElkArte Forum contributors
8
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
9
 *
10
 * This file contains code covered by:
11
 * copyright: 2011 Simple Machines (http://www.simplemachines.org)
12
 *
13
 * @version 2.0 dev
14
 *
15
 */
16
17
use ElkArte\Helper\Util;
18
use ElkArte\Permissions;
19
20
/**
21
 * Set the permission level for a specific profile, group, or group for a profile.
22
 *
23
 * @param string $level The level ('restrict', 'standard', etc.)
24
 * @param int|null $group The group to set the permission for
25
 * @param int|null $profile = null, int id of the permissions group or 'null' if we're setting it for a group
26
 *
27
 * @throws \ElkArte\Exceptions\Exception no_access
28
 * @package Permissions
29
 *
30
 */
31
function setPermissionLevel($level, $group = null, $profile = null)
32
{
33
	$db = database();
34
35
	// we'll need to init illegal permissions.
36
	$permissionsObject = new Permissions();
37
	$illegal_permissions = $permissionsObject->getIllegalPermissions();
38
	$illegal_guest_permissions = $permissionsObject->getIllegalGuestPermissions();
39
40
	// Levels by group... restrict, standard, moderator, maintenance.
41
	$groupLevels = array(
42
		'board' => array('inherit' => array()),
43
		'group' => array('inherit' => array())
44
	);
45
	// Levels by board... standard, publish, free.
46
	$boardLevels = array('inherit' => array());
47
48
	// Restrictive - ie. guests.
49
	$groupLevels['global']['restrict'] = array(
50
		'search_posts',
51
		'calendar_view',
52
		'view_stats',
53
		'who_view',
54
		'profile_view_own',
55
		'profile_identity_own',
56
	);
57
	$groupLevels['board']['restrict'] = array(
58
		'poll_view',
59
		'post_new',
60
		'post_reply_own',
61
		'post_reply_any',
62
		'delete_own',
63
		'modify_own',
64
		'mark_any_notify',
65
		'mark_notify',
66
		'report_any',
67
	);
68
69
	// Standard - ie. members.  They can do anything Restrictive can.
70
	$groupLevels['global']['standard'] = array_merge($groupLevels['global']['restrict'], array(
71
		'view_mlist',
72
		'karma_edit',
73
		'like_posts',
74
		'like_posts_stats',
75
		'pm_read',
76
		'pm_send',
77
		'send_email_to_members',
78
		'profile_view_any',
79
		'profile_extra_own',
80
		'profile_set_avatar',
81
		'profile_remove_own',
82
	));
83
	$groupLevels['board']['standard'] = array_merge($groupLevels['board']['restrict'], array(
84
		'poll_vote',
85
		'poll_edit_own',
86
		'poll_post',
87
		'poll_add_own',
88
		'post_attachment',
89
		'lock_own',
90
		'remove_own',
91
		'view_attachments',
92
	));
93
94
	// Moderator - ie. moderators :P.  They can do what standard can, and more.
95
	$groupLevels['global']['moderator'] = array_merge($groupLevels['global']['standard'], array(
96
		'calendar_post',
97
		'calendar_edit_own',
98
		'access_mod_center',
99
		'issue_warning',
100
	));
101
	$groupLevels['board']['moderator'] = array_merge($groupLevels['board']['standard'], array(
102
		'make_sticky',
103
		'poll_edit_any',
104
		'delete_any',
105
		'modify_any',
106
		'lock_any',
107
		'remove_any',
108
		'move_any',
109
		'merge_any',
110
		'split_any',
111
		'poll_lock_any',
112
		'poll_remove_any',
113
		'poll_add_any',
114
		'approve_posts',
115
		'like_posts',
116
	));
117
118
	// Maintenance - wannabe admins.  They can do almost everything.
119
	$groupLevels['global']['maintenance'] = array_merge($groupLevels['global']['moderator'], array(
120
		'manage_attachments',
121
		'manage_smileys',
122
		'manage_boards',
123
		'moderate_forum',
124
		'manage_membergroups',
125
		'manage_bans',
126
		'admin_forum',
127
		'manage_permissions',
128
		'edit_news',
129
		'calendar_edit_any',
130
		'profile_identity_any',
131
		'profile_extra_any',
132
		'profile_title_any',
133
	));
134
	$groupLevels['board']['maintenance'] = array_merge($groupLevels['board']['moderator'], array());
135
136
	// Standard - nothing above the group permissions. (this SHOULD be empty.)
137
	$boardLevels['standard'] = array();
138
139
	// Locked - just that, you can't post here.
140
	$boardLevels['locked'] = array(
141
		'poll_view',
142
		'mark_notify',
143
		'report_any',
144
		'view_attachments',
145
	);
146
147
	// Publisher - just a little more...
148
	$boardLevels['publish'] = array_merge($boardLevels['locked'], array(
149
		'post_new',
150
		'post_reply_own',
151
		'post_reply_any',
152
		'delete_own',
153
		'modify_own',
154
		'mark_any_notify',
155
		'delete_replies',
156
		'modify_replies',
157
		'poll_vote',
158
		'poll_edit_own',
159
		'poll_post',
160
		'poll_add_own',
161
		'poll_remove_own',
162
		'post_attachment',
163
		'lock_own',
164
		'remove_own',
165
	));
166
167
	// Free for All - Scary.  Just scary.
168
	$boardLevels['free'] = array_merge($boardLevels['publish'], array(
169
		'poll_lock_any',
170
		'poll_edit_any',
171
		'poll_add_any',
172
		'poll_remove_any',
173
		'make_sticky',
174
		'lock_any',
175
		'remove_any',
176
		'delete_any',
177
		'split_any',
178
		'merge_any',
179
		'modify_any',
180
		'approve_posts',
181
	));
182
183
	// Make sure we're not granting someone too many permissions!
184
	foreach ($groupLevels['global'][$level] as $k => $permission)
185
	{
186
		if (!empty($illegal_permissions) && in_array($permission, $illegal_permissions))
187
		{
188
			unset($groupLevels['global'][$level][$k]);
189
		}
190
191
		if ($group == -1 && in_array($permission, $illegal_guest_permissions))
192
		{
193
			unset($groupLevels['global'][$level][$k]);
194
		}
195
	}
196
197
	if ($group == -1)
198
	{
199
		foreach ($groupLevels['board'][$level] as $k => $permission)
200
		{
201
			if (in_array($permission, $illegal_guest_permissions))
202
			{
203
				unset($groupLevels['board'][$level][$k]);
204
			}
205
		}
206
	}
207
208
	// Reset all cached permissions.
209
	updateSettings(array('settings_updated' => time()));
210
211
	// Setting group permissions.
212
	if ($profile === null && $group !== null)
213
	{
214
		$group = (int) $group;
215
216
		if (empty($groupLevels['global'][$level]))
217
		{
218
			return;
219
		}
220
221
		$db->query('', '
222
			DELETE FROM {db_prefix}permissions
223
			WHERE id_group = {int:current_group}
224
			' . (empty($illegal_permissions) ? '' : ' AND permission NOT IN ({array_string:illegal_permissions})'),
225
			array(
226
				'current_group' => $group,
227
				'illegal_permissions' => $illegal_permissions,
228
			)
229
		);
230
		$db->query('', '
231
			DELETE FROM {db_prefix}board_permissions
232
			WHERE id_group = {int:current_group}
233
				AND id_profile = {int:default_profile}',
234
			array(
235
				'current_group' => $group,
236
				'default_profile' => 1,
237
			)
238
		);
239
240
		$groupInserts = array();
241
		foreach ($groupLevels['global'][$level] as $permission)
242
		{
243
			$groupInserts[] = array($group, $permission);
244
		}
245
246
		$db->insert('insert',
247
			'{db_prefix}permissions',
248
			array('id_group' => 'int', 'permission' => 'string'),
249
			$groupInserts,
250
			array('id_group')
251
		);
252
253
		$boardInserts = array();
254
		foreach ($groupLevels['board'][$level] as $permission)
255
		{
256
			$boardInserts[] = array(1, $group, $permission);
257
		}
258
259
		$db->insert('insert',
260
			'{db_prefix}board_permissions',
261
			array('id_profile' => 'int', 'id_group' => 'int', 'permission' => 'string'),
262
			$boardInserts,
263
			array('id_profile', 'id_group')
264
		);
265
	}
266
	// Setting profile permissions for a specific group.
267
	elseif ($profile !== null && $group !== null && ($profile === 1 || $profile > 4))
268
	{
269
		$group = (int) $group;
270
		$profile = (int) $profile;
271
272
		if (!empty($groupLevels['global'][$level]))
273
		{
274
			$db->query('', '
275
				DELETE FROM {db_prefix}board_permissions
276
				WHERE id_group = {int:current_group}
277
					AND id_profile = {int:current_profile}',
278
				array(
279
					'current_group' => $group,
280
					'current_profile' => $profile,
281
				)
282
			);
283
		}
284
285
		if (!empty($groupLevels['board'][$level]))
286
		{
287
			$boardInserts = array();
288
			foreach ($groupLevels['board'][$level] as $permission)
289
			{
290
				$boardInserts[] = array($profile, $group, $permission);
291
			}
292
293
			$db->insert('insert',
294
				'{db_prefix}board_permissions',
295
				array('id_profile' => 'int', 'id_group' => 'int', 'permission' => 'string'),
296
				$boardInserts,
297
				array('id_profile', 'id_group')
298
			);
299
		}
300
	}
301
	// Setting profile permissions for all groups.
302
	elseif ($profile !== null && $group === null && ($profile === 1 || $profile > 4))
303
	{
304
		$profile = (int) $profile;
305
306
		$db->query('', '
307
			DELETE FROM {db_prefix}board_permissions
308
			WHERE id_profile = {int:current_profile}',
309
			array(
310
				'current_profile' => $profile,
311
			)
312
		);
313
314
		if (empty($boardLevels[$level]))
315
		{
316
			return;
317
		}
318
319
		// Get all the groups...
320
		$db->fetchQuery('
321
			SELECT 
322
				id_group
323
			FROM {db_prefix}membergroups
324
			WHERE id_group > {int:moderator_group}
325
			ORDER BY min_posts, CASE WHEN id_group < {int:newbie_group} THEN id_group ELSE 4 END, group_name',
326
			array(
327
				'moderator_group' => 3,
328
				'newbie_group' => 4,
329
			)
330
		)->fetch_callback(
331
			function ($row) use ($db, $boardLevels, $profile, $level) {
332
				$group = $row['id_group'];
333
334
				$boardInserts = array();
335
				foreach ($boardLevels[$level] as $permission)
336
				{
337
					$boardInserts[] = array($profile, $group, $permission);
338
				}
339
340
				$db->insert('insert',
341
					'{db_prefix}board_permissions',
342
					array('id_profile' => 'int', 'id_group' => 'int', 'permission' => 'string'),
343
					$boardInserts,
344
					array('id_profile', 'id_group')
345
				);
346
			}
347
		);
348
349
		// Add permissions for ungrouped members.
350
		$boardInserts = array();
351
		foreach ($boardLevels[$level] as $permission)
352
		{
353
			$boardInserts[] = array($profile, 0, $permission);
354
		}
355
356
		$db->insert('insert',
357
			'{db_prefix}board_permissions',
358
			array('id_profile' => 'int', 'id_group' => 'int', 'permission' => 'string'),
359
			$boardInserts,
360
			array('id_profile', 'id_group')
361
		);
362
	}
363
	// $profile and $group are both null!
364
	else
365
	{
366
		throw new \ElkArte\Exceptions\Exception('no_access', false);
367
	}
368
}
369
370
/**
371
 * Load permissions profiles.
372
 *
373
 * @package Permissions
374
 */
375
function loadPermissionProfiles()
376
{
377
	global $context, $txt;
378
379
	$db = database();
380
381
	$context['profiles'] = array();
382
	$db->fetchQuery('
383
		SELECT 
384
			id_profile, profile_name
385
		FROM {db_prefix}permission_profiles
386
		ORDER BY id_profile',
387
		array()
388
	)->fetch_callback(
389
		function ($row) use ($txt) {
390
			global $context;
391
392
			// Format the label nicely.
393
			$name = $txt['permissions_profile_' . $row['profile_name']] ?? $row['profile_name'];
394
395
			$context['profiles'][$row['id_profile']] = array(
396
				'id' => $row['id_profile'],
397
				'name' => $name,
398
				'can_modify' => $row['id_profile'] == 1 || $row['id_profile'] > 4,
399
				'unformatted_name' => $row['profile_name'],
400
			);
401
		}
402
	);
403
}
404
405
/**
406
 * Load permissions into $context['permissions'].
407
 *
408
 * @package Permissions
409
 */
410
function loadAllPermissions()
411
{
412
	global $context, $txt, $modSettings;
413
414
	// List of all the groups
415
	// Note to Mod authors - you don't need to stick your permission group here if you don't mind having it as the last group of the page.
416
	$permissionGroups = array(
417
		'membergroup' => array(
418
			'general',
419
			'pm',
420
			'calendar',
421
			'maintenance',
422
			'member_admin',
423
			'profile',
424
		),
425
		'board' => array(
426
			'general_board',
427
			'topic',
428
			'post',
429
			'poll',
430
			'notification',
431
			'attachment',
432
		),
433
	);
434
435
	/*   The format of this list is as follows:
436
		'membergroup' => array(
437
			'permissions_inside' => array(has_multiple_options, view_group),
438
		),
439
		'board' => array(
440
			'permissions_inside' => array(has_multiple_options, view_group),
441
		);
442
	*/
443
	$permissionList = array(
444
		'membergroup' => array(
445
			'view_stats' => array(false, 'general'),
446
			'view_mlist' => array(false, 'general'),
447
			'who_view' => array(false, 'general'),
448
			'search_posts' => array(false, 'general'),
449
			'karma_edit' => array(false, 'general'),
450
			'like_posts_stats' => array(false, 'general'),
451
			'disable_censor' => array(false, 'general'),
452
			'post_nofollow' => array(false, 'general'),
453
			'pm_read' => array(false, 'pm'),
454
			'pm_send' => array(false, 'pm'),
455
			'send_email_to_members' => array(false, 'pm'),
456
			'calendar_view' => array(false, 'calendar'),
457
			'calendar_post' => array(false, 'calendar'),
458
			'calendar_edit' => array(true, 'calendar'),
459
			'admin_forum' => array(false, 'maintenance'),
460
			'manage_boards' => array(false, 'maintenance'),
461
			'manage_attachments' => array(false, 'maintenance'),
462
			'manage_smileys' => array(false, 'maintenance'),
463
			'edit_news' => array(false, 'maintenance'),
464
			'access_mod_center' => array(false, 'maintenance'),
465
			'moderate_forum' => array(false, 'member_admin'),
466
			'manage_membergroups' => array(false, 'member_admin'),
467
			'manage_permissions' => array(false, 'member_admin'),
468
			'manage_bans' => array(false, 'member_admin'),
469
			'send_mail' => array(false, 'member_admin'),
470
			'issue_warning' => array(false, 'member_admin'),
471
			'profile_view' => array(true, 'profile'),
472
			'profile_identity' => array(true, 'profile'),
473
			'profile_extra' => array(true, 'profile'),
474
			'profile_title' => array(true, 'profile'),
475
			'profile_remove' => array(true, 'profile'),
476
			'profile_set_avatar' => array(false, 'profile'),
477
			'approve_emails' => array(false, 'member_admin'),
478
		),
479
		'board' => array(
480
			'moderate_board' => array(false, 'general_board'),
481
			'approve_posts' => array(false, 'general_board'),
482
			'post_new' => array(false, 'topic'),
483
			'post_unapproved_topics' => array(false, 'topic'),
484
			'post_unapproved_replies' => array(true, 'topic'),
485
			'post_reply' => array(true, 'topic'),
486
			'merge_any' => array(false, 'topic'),
487
			'split_any' => array(false, 'topic'),
488
			'make_sticky' => array(false, 'topic'),
489
			'move' => array(true, 'topic'),
490
			'lock' => array(true, 'topic'),
491
			'remove' => array(true, 'topic'),
492
			'modify_replies' => array(false, 'topic'),
493
			'delete_replies' => array(false, 'topic'),
494
			'announce_topic' => array(false, 'topic'),
495
			'delete' => array(true, 'post'),
496
			'modify' => array(true, 'post'),
497
			'report_any' => array(false, 'post'),
498
			'poll_view' => array(false, 'poll'),
499
			'poll_vote' => array(false, 'poll'),
500
			'poll_post' => array(false, 'poll'),
501
			'poll_add' => array(true, 'poll'),
502
			'poll_edit' => array(true, 'poll'),
503
			'poll_lock' => array(true, 'poll'),
504
			'poll_remove' => array(true, 'poll'),
505
			'mark_any_notify' => array(false, 'notification'),
506
			'mark_notify' => array(false, 'notification'),
507
			'view_attachments' => array(false, 'attachment'),
508
			'post_unapproved_attachments' => array(false, 'attachment'),
509
			'post_attachment' => array(false, 'attachment'),
510
			'postby_email' => array(false, 'topic'),
511
			'like_posts' => array(false, 'topic'),
512
		),
513
	);
514
515
	// All permission groups that will be shown in the left column.
516
	$leftPermissionGroups = array(
517
		'general',
518
		'calendar',
519
		'maintenance',
520
		'member_admin',
521
		'topic',
522
		'post',
523
	);
524
525
	// We need to know what permissions we can't give to guests.
526
	$permissionsObject = new Permissions();
527
	$illegal_guest_permissions = $permissionsObject->getIllegalGuestPermissions();
528
529
	// Some permissions are hidden if features are off.
530
	$hiddenPermissions = array();
531
	$relabelPermissions = array(); // Permissions to apply a different label to.
532
533
	if (featureEnabled('cd') === false)
534
	{
535
		$hiddenPermissions[] = 'calendar_view';
536
		$hiddenPermissions[] = 'calendar_post';
537
		$hiddenPermissions[] = 'calendar_edit';
538
	}
539
540
	if (featureEnabled('w') === false)
541
	{
542
		$hiddenPermissions[] = 'issue_warning';
543
	}
544
545
	if (featureEnabled('k') === false)
546
	{
547
		$hiddenPermissions[] = 'karma_edit';
548
	}
549
550
	if (featureEnabled('l') === false)
551
	{
552
		$hiddenPermissions[] = 'like_posts';
553
	}
554
555
	if (featureEnabled('pe') === false)
556
	{
557
		$hiddenPermissions[] = 'approve_emails';
558
		$hiddenPermissions[] = 'postby_email';
559
	}
560
561
	// Post moderation?
562
	if (!$modSettings['postmod_active'])
563
	{
564
		$hiddenPermissions[] = 'approve_posts';
565
		$hiddenPermissions[] = 'post_unapproved_topics';
566
		$hiddenPermissions[] = 'post_unapproved_replies';
567
		$hiddenPermissions[] = 'post_unapproved_attachments';
568
	}
569
	// If we show them on classic view we change the name.
570
	else
571
	{
572
		// Relabel the topics permissions
573
		$relabelPermissions['post_new'] = 'auto_approve_topics';
574
575
		// Relabel the reply permissions
576
		$relabelPermissions['post_reply'] = 'auto_approve_replies';
577
578
		// Relabel the attachment permissions
579
		$relabelPermissions['post_attachment'] = 'auto_approve_attachments';
580
	}
581
582
	// Are attachments enabled?
583
	if (empty($modSettings['attachmentEnable']))
584
	{
585
		$hiddenPermissions[] = 'manage_attachments';
586
		$hiddenPermissions[] = 'view_attachments';
587
		$hiddenPermissions[] = 'post_unapproved_attachments';
588
		$hiddenPermissions[] = 'post_attachment';
589
	}
590
591
	// Provide a practical way to modify permissions.
592
	call_integration_hook('integrate_load_permissions', array(&$permissionGroups, &$permissionList, &$leftPermissionGroups, &$hiddenPermissions, &$relabelPermissions));
593
594
	$context['permissions'] = array();
595
	$context['hidden_permissions'] = array();
596
	foreach ($permissionList as $permissionType => $currentPermissionList)
597
	{
598
		$context['permissions'][$permissionType] = array(
599
			'id' => $permissionType,
600
			'columns' => array()
601
		);
602
603
		foreach ($currentPermissionList as $permission => $permissionArray)
604
		{
605
			// If this is a guest permission we don't do it if it's the guest group.
606
			if (isset($context['group']['id']) && $context['group']['id'] == -1 && in_array($permission, $illegal_guest_permissions))
607
			{
608
				continue;
609
			}
610
611
			// What groups will this permission be in?
612
			$own_group = $permissionArray[1];
613
614
			// First, Do these groups actually exist - if not add them.
615
			if (!isset($permissionGroups[$permissionType][$own_group]))
616
			{
617
				$permissionGroups[$permissionType][$own_group] = true;
618
			}
619
620
			// What column should this be located into?
621
			$position = !in_array($own_group, $leftPermissionGroups) ? 1 : 0;
622
623
			// If the groups have not yet been created be sure to create them.
624
			$bothGroups = array();
625
626
			// Guests can have only any, registered users both
627
			if (!isset($context['group']['id']) || $context['group']['id'] != -1)
628
			{
629
				$bothGroups['own'] = $own_group;
630
			}
631
			else
632
			{
633
				$bothGroups['any'] = $own_group;
634
			}
635
636
			foreach ($bothGroups as $group)
637
			{
638
				if (!isset($context['permissions'][$permissionType]['columns'][$position][$group]['type']))
639
				{
640
					$context['permissions'][$permissionType]['columns'][$position][$group] = array(
641
						'type' => $permissionType,
642
						'id' => $group,
643
						'name' => $txt['permissiongroup_' . $group],
644
						'icon' => $txt['permissionicon_' . $group] ?? $txt['permissionicon'],
645
						'help' => $txt['permissionhelp_' . $group] ?? '',
646
						'hidden' => false,
647
						'permissions' => array()
648
					);
649
				}
650
			}
651
652
			// This is where we set up the permission.
653
			$context['permissions'][$permissionType]['columns'][$position][$own_group]['permissions'][$permission] = array(
654
				'id' => $permission,
655
				'name' => !isset($relabelPermissions[$permission]) ? $txt['permissionname_' . $permission] : $txt[$relabelPermissions[$permission]],
656
				'show_help' => isset($txt['permissionhelp_' . $permission]),
657
				'note' => $txt['permissionnote_' . $permission] ?? '',
658
				'has_own_any' => $permissionArray[0],
659
				'own' => array(
660
					'id' => $permission . '_own',
661
					'name' => $permissionArray[0] ? $txt['permissionname_' . $permission . '_own'] : ''
662
				),
663
				'any' => array(
664
					'id' => $permission . '_any',
665
					'name' => $permissionArray[0] ? $txt['permissionname_' . $permission . '_any'] : ''
666
				),
667
				'hidden' => in_array($permission, $hiddenPermissions),
668
			);
669
670
			if (in_array($permission, $hiddenPermissions))
671
			{
672
				if ($permissionArray[0])
673
				{
674
					$context['hidden_permissions'][] = $permission . '_own';
675
					$context['hidden_permissions'][] = $permission . '_any';
676
				}
677
				else
678
				{
679
					$context['hidden_permissions'][] = $permission;
680
				}
681
			}
682
		}
683
		ksort($context['permissions'][$permissionType]['columns']);
684
685
		// Check we don't leave any empty groups - and mark hidden ones as such.
686
		foreach ($context['permissions'][$permissionType]['columns'] as $column => $groups)
687
		{
688
			foreach ($groups as $id => $group)
689
			{
690
				if (empty($group['permissions']))
691
				{
692
					unset($context['permissions'][$permissionType]['columns'][$column][$id]);
693
				}
694
				else
695
				{
696
					$foundNonHidden = false;
697
					foreach ($group['permissions'] as $permission)
698
					{
699
						if (empty($permission['hidden']))
700
						{
701
							$foundNonHidden = true;
702
						}
703
					}
704
705
					if (!$foundNonHidden)
706
					{
707
						$context['permissions'][$permissionType]['columns'][$column][$id]['hidden'] = true;
708
					}
709
				}
710
			}
711
		}
712
	}
713
}
714
715
/**
716
 * Counts membergroup permissions.
717
 *
718
 * @param int[] $groups the group ids to return permission counts
719
 * @param string[]|null $hidden_permissions array of permission names to skip in the count totals
720
 *
721
 * @return int[] [id_group][num_permissions][denied] = count, [id_group][num_permissions][allowed] = count
722
 * @package Permissions
723
 */
724
function countPermissions($groups, $hidden_permissions = null)
725
{
726
	$db = database();
727
728
	$db->fetchQuery('
729
		SELECT 
730
			id_group, COUNT(*) AS num_permissions, add_deny
731
		FROM {db_prefix}permissions'
732
		. (isset($hidden_permissions) ? '' : 'WHERE permission NOT IN ({array_string:hidden_permissions})') . '
733
		GROUP BY id_group, add_deny',
734
		array(
735
			'hidden_permissions' => !isset($hidden_permissions) ? $hidden_permissions : array(),
736
		)
737
	)->fetch_callback(
738
		function ($row) use (&$groups) {
739
			if (isset($groups[(int) $row['id_group']]) && (!empty($row['add_deny']) || $row['id_group'] != -1))
740
			{
741
				$groups[$row['id_group']]['num_permissions'][empty($row['add_deny']) ? 'denied' : 'allowed'] = $row['num_permissions'];
742
			}
743
		}
744
	);
745
746
	return $groups;
747
}
748
749
/**
750
 * Counts board permissions.
751
 *
752
 * @param int[] $groups
753
 * @param string[]|null $hidden_permissions
754
 * @param int|null $profile_id
755
 *
756
 * @return int[]
757
 * @package Permissions
758
 */
759
function countBoardPermissions($groups, $hidden_permissions = null, $profile_id = null)
760
{
761
	$db = database();
762
763
	$db->fetchQuery('
764
		SELECT 
765
			' . (isset($profile_id) ? 'id_profile, ' : '') . 'id_group, add_deny, COUNT(*) AS num_permissions
766
		FROM {db_prefix}board_permissions
767
		WHERE 1 = 1'
768
		. (isset($profile_id) ? ' AND id_profile = {int:current_profile}' : '')
769
		. (empty($hidden_permissions) ? '' : ' AND permission NOT IN ({array_string:hidden_permissions})') . '
770
		GROUP BY ' . (isset($profile_id) ? 'id_profile, ' : '') . 'id_group, add_deny',
771
		array(
772
			'hidden_permissions' => !empty($hidden_permissions) ? $hidden_permissions : array(),
773
			'current_profile' => $profile_id,
774
		)
775
	)->fetch_callback(
776
		function ($row) use (&$groups) {
777
			if (isset($groups[(int) $row['id_group']]) && (!empty($row['add_deny']) || $row['id_group'] != -1))
778
			{
779
				$groups[$row['id_group']]['num_permissions'][empty($row['add_deny']) ? 'denied' : 'allowed'] += $row['num_permissions'];
780
			}
781
		}
782
	);
783
784
	return $groups;
785
}
786
787
/**
788
 * Used to assign a permission profile to a board.
789
 *
790
 * @param int $profile
791
 * @param int $board
792
 * @package Permissions
793
 */
794
function assignPermissionProfileToBoard($profile, $board)
795
{
796
	$db = database();
797
798
	$db->query('', '
799
		UPDATE {db_prefix}boards
800
		SET 
801
			id_profile = {int:current_profile}
802
		WHERE id_board IN ({array_int:board_list})',
803
		array(
804
			'board_list' => $board,
805
			'current_profile' => $profile,
806
		)
807
	);
808
}
809
810
/**
811
 * Copy a set of permissions from one group to another..
812
 *
813
 * @param int $copy_from
814
 * @param int[] $groups
815
 * @param string[] $illegal_permissions
816
 * @param string[] $non_guest_permissions
817
 * @todo another function with the same name in Membergroups.subs.php
818
 * @package Permissions
819
 */
820
function copyPermission($copy_from, $groups, $illegal_permissions, $non_guest_permissions = array())
821
{
822
	$db = database();
823
824
	// Retrieve current permissions of group.
825
	$target_perm = array();
826
	$db->fetchQuery('
827
		SELECT 
828
			permission, add_deny
829
		FROM {db_prefix}permissions
830
		WHERE id_group = {int:copy_from}',
831
		array(
832
			'copy_from' => $copy_from,
833
		)
834
	)->fetch_callback(
835
		function ($row) use (&$target_perm) {
836
			$target_perm[$row['permission']] = $row['add_deny'];
837
		}
838
	);
839
840
	$inserts = array();
841
	foreach ($groups as $group_id)
842
	{
843
		foreach ($target_perm as $perm => $add_deny)
844
		{
845
			// No dodgy permissions please!
846
			if (!empty($illegal_permissions) && in_array($perm, $illegal_permissions))
847
			{
848
				continue;
849
			}
850
851
			if ($group_id === -1 && in_array($perm, $non_guest_permissions))
852
			{
853
				continue;
854
			}
855
856
			if ($group_id !== 1 && $group_id !== 3)
857
			{
858
				$inserts[] = array('permission' => $perm, 'id_group' => $group_id, 'add_deny' => $add_deny);
859
			}
860
		}
861
	}
862
863
	// Delete the previous permissions...
864
	$db->query('', '
865
		DELETE FROM {db_prefix}permissions
866
		WHERE id_group IN ({array_int:group_list})
867
			' . (empty($illegal_permissions) ? '' : ' AND permission NOT IN ({array_string:illegal_permissions})'),
868
		array(
869
			'group_list' => $groups,
870
			'illegal_permissions' => $illegal_permissions,
871
		)
872
	);
873
874
	if (!empty($inserts))
875
	{
876
		// ..and insert the new ones.
877
		require_once(SUBSDIR . '/ManagePermissions.subs.php');
878
		replacePermission($inserts);
879
	}
880
}
881
882
/**
883
 * Copy a set of board permissions from one group to another..
884
 *
885
 * @param int $copy_from
886
 * @param int[] $groups The target groups
887
 * @param int $profile_id
888
 * @param string[] $non_guest_permissions
889
 * @package Permissions
890
 */
891
function copyBoardPermission($copy_from, $groups, $profile_id, $non_guest_permissions)
892
{
893
	$db = database();
894
895
	// Now do the same for the board permissions.
896
	$target_perm = array();
897
	$db->fetchQuery('
898
		SELECT 
899
			permission, add_deny
900
		FROM {db_prefix}board_permissions
901
		WHERE id_group = {int:copy_from}
902
			AND id_profile = {int:current_profile}',
903
		array(
904
			'copy_from' => $copy_from,
905
			'current_profile' => $profile_id,
906
		)
907
	)->fetch_callback(
908
		function ($row) use (&$target_perm) {
909
			$target_perm[$row['permission']] = $row['add_deny'];
910
		}
911
	);
912
913
	$inserts = array();
914
	foreach ($groups as $group_id)
915
	{
916
		foreach ($target_perm as $perm => $add_deny)
917
		{
918
			// Are these for guests?
919
			if ($group_id === -1 && in_array($perm, $non_guest_permissions))
920
			{
921
				continue;
922
			}
923
924
			$inserts[] = array($perm, $group_id, $add_deny, $profile_id);
925
		}
926
	}
927
928
	// Delete the previous global board permissions...
929
	deleteAllBoardPermissions($groups, $profile_id);
930
931
	// And insert the copied permissions.
932
	if (!empty($inserts))
933
	{
934
		require_once(SUBSDIR . '/ManagePermissions.subs.php');
935
		replaceBoardPermission($inserts);
936
	}
937
}
938
939
/**
940
 * Deletes membergroup permissions.
941
 *
942
 * @param int[] $groups
943
 * @param string $permission
944
 * @param string[] $illegal_permissions
945
 * @package Permissions
946
 */
947
function deletePermission($groups, $permission, $illegal_permissions)
948
{
949
	$db = database();
950
951
	$db->query('', '
952
		DELETE FROM {db_prefix}permissions
953
		WHERE id_group IN ({array_int:current_group_list})
954
			AND permission = {string:current_permission}
955
			' . (empty($illegal_permissions) ? '' : ' AND permission NOT IN ({array_string:illegal_permissions})'),
956
		array(
957
			'current_group_list' => $groups,
958
			'current_permission' => $permission,
959
			'illegal_permissions' => $illegal_permissions,
960
		)
961
	);
962
}
963
964
/**
965
 * Delete board permissions.
966
 *
967
 * @param int[] $group
968
 * @param int $profile_id
969
 * @param string $permission
970
 * @package Permissions
971
 */
972
function deleteBoardPermission($group, $profile_id, $permission)
973
{
974
	$db = database();
975
976
	$db->query('', '
977
		DELETE FROM {db_prefix}board_permissions
978
		WHERE id_group IN ({array_int:current_group_list})
979
			AND id_profile = {int:current_profile}
980
			AND permission = {string:current_permission}',
981
		array(
982
			'current_group_list' => $group,
983
			'current_profile' => $profile_id,
984
			'current_permission' => $permission,
985
		)
986
	);
987
}
988
989
/**
990
 * Replaces existing membergroup permissions with the given ones.
991
 *
992
 * @param mixed[] $permChange associative array permission, id_group, add_deny
993
 * @package Permissions
994
 */
995
function replacePermission($permChange)
996
{
997
	$db = database();
998
999
	if (!empty($permChange))
1000
	{
1001
		$db->replace(
1002
			'{db_prefix}permissions',
1003
			array('permission' => 'string', 'id_group' => 'int', 'add_deny' => 'int'),
1004
			$permChange,
1005
			array('permission', 'id_group')
1006
		);
1007
	}
1008
}
1009
1010
/**
1011
 * Replaces existing board permissions with the given ones.
1012
 *
1013
 * @param mixed[] $permChange associative array of 'permission', 'id_group', 'add_deny', 'id_profile'
1014 4
 * @package Permissions
1015
 */
1016 4
function replaceBoardPermission($permChange)
1017 4
{
1018 4
	$db = database();
1019 2
1020 4
	$db->replace(
1021
		'{db_prefix}board_permissions',
1022 4
		array('permission' => 'string', 'id_group' => 'int', 'add_deny' => 'int', 'id_profile' => 'int'),
1023
		$permChange,
1024
		array('permission', 'id_group', 'id_profile')
1025
	);
1026
}
1027
1028
/**
1029
 * Removes the moderator's permissions.
1030
 *
1031
 * @package Permissions
1032
 */
1033
function removeModeratorPermissions()
1034
{
1035
	$db = database();
1036
1037
	$db->query('', '
1038
		DELETE FROM {db_prefix}permissions
1039
		WHERE id_group = {int:moderator_group}',
1040
		array(
1041
			'moderator_group' => 3,
1042
		)
1043
	);
1044
}
1045
1046
/**
1047
 * Fetches membergroup permissions from the given group.
1048
 *
1049
 * @param int $id_group
1050
 * @return array
1051
 * @package Permissions
1052
 */
1053
function fetchPermissions($id_group)
1054
{
1055
	$db = database();
1056
1057
	$permissions = array(
1058
		'allowed' => array(),
1059
		'denied' => array(),
1060
	);
1061
1062
	$db->fetchQuery('
1063
		SELECT 
1064
			permission, add_deny
1065
		FROM {db_prefix}permissions
1066
		WHERE id_group = {int:current_group}',
1067
		array(
1068
			'current_group' => $id_group,
1069
		)
1070
	)->fetch_callback(
1071
		function ($row) use (&$permissions) {
1072
			$permissions[empty($row['add_deny']) ? 'denied' : 'allowed'][] = $row['permission'];
1073
		}
1074
	);
1075
1076
	return $permissions;
1077
}
1078
1079
/**
1080
 * Fetches board permissions from the given group.
1081
 *
1082
 * @param int $id_group
1083
 * @param string $permission_type
1084
 * @param int $profile_id
1085
 *
1086
 * @return array
1087
 * @package Permissions
1088
 *
1089
 */
1090
function fetchBoardPermissions($id_group, $permission_type, $profile_id)
1091
{
1092
	$db = database();
1093
1094
	$permissions = array(
1095
		'allowed' => array(),
1096
		'denied' => array(),
1097
	);
1098
1099
	$db->fetchQuery('
1100
		SELECT 
1101
			permission, add_deny
1102
		FROM {db_prefix}board_permissions
1103
		WHERE id_group = {int:current_group}
1104
			AND id_profile = {int:current_profile}',
1105
		array(
1106
			'current_group' => $id_group,
1107
			'current_profile' => $permission_type === 'membergroup' ? 1 : $profile_id,
1108
		)
1109
	)->fetch_callback(
1110
		function ($row) use (&$permissions) {
1111
			$permissions[empty($row['add_deny']) ? 'denied' : 'allowed'][] = $row['permission'];
1112
		}
1113
	);
1114
1115
	return $permissions;
1116
}
1117
1118
/**
1119
 * Deletes invalid permissions for the given group.
1120
 *
1121
 * @param int $id_group
1122
 * @param string[] $illegal_permissions
1123
 * @package Permissions
1124
 */
1125
function deleteInvalidPermissions($id_group, $illegal_permissions)
1126
{
1127
	$db = database();
1128
1129
	$db->query('', '
1130
		DELETE FROM {db_prefix}permissions
1131
		WHERE id_group = {int:current_group}
1132
		' . (empty($illegal_permissions) ? '' : ' AND permission NOT IN ({array_string:illegal_permissions})'),
1133
		array(
1134
			'current_group' => $id_group,
1135
			'illegal_permissions' => $illegal_permissions,
1136
		)
1137
	);
1138
}
1139
1140
/**
1141
 * Deletes a membergroup's board permissions from a specified permission profile.
1142
 *
1143
 * @param int[] $groups
1144
 * @param int $id_profile
1145
 * @package Permissions
1146
 */
1147
function deleteAllBoardPermissions(array $groups, $id_profile)
1148
{
1149
	$db = database();
1150
1151
	$db->query('', '
1152
		DELETE FROM {db_prefix}board_permissions
1153
		WHERE id_group IN ({array_int:current_group_list})
1154
			AND id_profile = {int:current_profile}',
1155
		array(
1156
			'current_group_list' => $groups,
1157
			'current_profile' => $id_profile,
1158
		)
1159
	);
1160
}
1161
1162
/**
1163
 * Deny permissions disabled? We need to clean the permission tables.
1164
 *
1165
 * @package Permissions
1166
 */
1167
function clearDenyPermissions()
1168
{
1169
	$db = database();
1170
1171
	$db->query('', '
1172
		DELETE FROM {db_prefix}permissions
1173
		WHERE add_deny = {int:denied}',
1174
		array(
1175
			'denied' => 0,
1176
		)
1177
	);
1178
	$db->query('', '
1179
		DELETE FROM {db_prefix}board_permissions
1180
		WHERE add_deny = {int:denied}',
1181
		array(
1182
			'denied' => 0,
1183
		)
1184
	);
1185
}
1186
1187
/**
1188
 * Permissions for post based groups disabled? We need to clean the permission
1189
 * tables, too.
1190
 *
1191
 * @package Permissions
1192
 */
1193
function clearPostgroupPermissions()
1194
{
1195
	$db = database();
1196
1197
	$post_groups = $db->fetchQuery('
1198
		SELECT 
1199
			id_group
1200
		FROM {db_prefix}membergroups
1201
		WHERE min_posts != {int:min_posts}',
1202
		array(
1203
			'min_posts' => -1,
1204
		)
1205
	)->fetch_callback(
1206
		function ($row) {
1207
			return $row['id_group'];
1208
		}
1209
	);
1210
1211
	// Remove'em.
1212
	$db->query('', '
1213
		DELETE FROM {db_prefix}permissions
1214
		WHERE id_group IN ({array_int:post_group_list})',
1215
		array(
1216
			'post_group_list' => $post_groups,
1217
		)
1218
	);
1219
	$db->query('', '
1220
		DELETE FROM {db_prefix}board_permissions
1221
		WHERE id_group IN ({array_int:post_group_list})',
1222
		array(
1223
			'post_group_list' => $post_groups,
1224
		)
1225
	);
1226
	$db->query('', '
1227
		UPDATE {db_prefix}membergroups
1228
		SET 
1229
			id_parent = {int:not_inherited}
1230
		WHERE id_parent IN ({array_int:post_group_list})',
1231
		array(
1232
			'post_group_list' => $post_groups,
1233
			'not_inherited' => -2,
1234
		)
1235
	);
1236
}
1237
1238
/**
1239
 * Copies a permission profile.
1240
 *
1241
 * @param string $profile_name
1242
 * @param int $copy_from
1243
 * @package Permissions
1244
 */
1245
function copyPermissionProfile($profile_name, $copy_from)
1246
{
1247
	$db = database();
1248
1249
	$profile_name = Util::htmlspecialchars($profile_name);
1250
	// Insert the profile itself.
1251
	$db->insert('',
1252
		'{db_prefix}permission_profiles',
1253
		array(
1254
			'profile_name' => 'string',
1255
		),
1256
		array(
1257
			$profile_name,
1258
		),
1259
		array('id_profile')
1260
	);
1261
	$profile_id = $db->insert_id('{db_prefix}permission_profiles');
1262
1263
	// Load the permissions from the one it's being copied from.
1264
	$inserts = $db->fetchQuery('
1265
		SELECT 
1266
			id_group, permission, add_deny
1267
		FROM {db_prefix}board_permissions
1268
		WHERE id_profile = {int:copy_from}',
1269
		array(
1270
			'copy_from' => $copy_from,
1271
		)
1272
	)->fetch_callback(
1273
		function ($row) use ($profile_id) {
1274
			return array($profile_id, $row['id_group'], $row['permission'], $row['add_deny']);
1275
		}
1276
	);
1277
1278
	if (!empty($inserts))
1279
	{
1280
		$db->insert('insert',
1281
			'{db_prefix}board_permissions',
1282
			array('id_profile' => 'int', 'id_group' => 'int', 'permission' => 'string', 'add_deny' => 'int'),
1283
			$inserts,
1284
			array('id_profile', 'id_group', 'permission')
1285
		);
1286
	}
1287
}
1288
1289
/**
1290
 * Rename a permission profile.
1291
 *
1292
 * @param int $id_profile
1293
 * @param string $name
1294
 * @package Permissions
1295
 */
1296
function renamePermissionProfile($id_profile, $name)
1297
{
1298
	$db = database();
1299
1300
	$name = Util::htmlspecialchars($name);
1301
1302
	$db->query('', '
1303
		UPDATE {db_prefix}permission_profiles
1304
		SET 
1305
			profile_name = {string:profile_name}
1306
		WHERE id_profile = {int:current_profile}',
1307
		array(
1308
			'current_profile' => $id_profile,
1309
			'profile_name' => $name,
1310
		)
1311
	);
1312
}
1313
1314
/**
1315
 * Delete a permission profile
1316
 *
1317
 * @param int[] $profiles
1318
 *
1319
 * @throws \ElkArte\Exceptions\Exception no_access
1320
 * @package Permissions
1321
 *
1322
 */
1323
function deletePermissionProfiles($profiles)
1324
{
1325
	$db = database();
1326
1327
	// Verify it's not in use...
1328
	$request = $db->query('', '
1329
		SELECT 
1330
			id_board
1331
		FROM {db_prefix}boards
1332
		WHERE id_profile IN ({array_int:profile_list})
1333
		LIMIT 1',
1334
		array(
1335
			'profile_list' => $profiles,
1336
		)
1337
	);
1338
	if ($request->num_rows() !== 0)
1339
	{
1340
		throw new \ElkArte\Exceptions\Exception('no_access', false);
1341
	}
1342
	$request->free_result();
1343
1344
	// Oh well, delete.
1345
	$db->query('', '
1346
		DELETE FROM {db_prefix}permission_profiles
1347
		WHERE id_profile IN ({array_int:profile_list})',
1348
		array(
1349
			'profile_list' => $profiles,
1350
		)
1351
	);
1352
}
1353
1354
/**
1355
 * Checks, if a permission profile is in use.
1356
 *
1357
 * @param int[] $profiles
1358
 *
1359
 * @return int[]
1360
 * @package Permissions
1361
 */
1362
function permProfilesInUse($profiles)
1363
{
1364
	$db = database();
1365
1366
	$db->fetchQuery('
1367
		SELECT 
1368
			id_profile, COUNT(id_board) AS board_count
1369
		FROM {db_prefix}boards
1370
		GROUP BY id_profile',
1371
		array()
1372
	)->fetch_callback(
1373
		function ($row) use (&$profiles) {
1374
			global $txt;
1375
1376
			if (isset($profiles[$row['id_profile']]))
1377
			{
1378
				$profiles[$row['id_profile']]['in_use'] = true;
1379
				$profiles[$row['id_profile']]['boards'] = $row['board_count'];
1380
				$profiles[$row['id_profile']]['boards_text'] = $row['board_count'] > 1 ? sprintf($txt['permissions_profile_used_by_many'], $row['board_count']) : $txt['permissions_profile_used_by_' . ($row['board_count'] ? 'one' : 'none')];
1381
			}
1382
		}
1383
	);
1384
1385
	return $profiles;
1386
}
1387
1388
/**
1389
 * Delete a board permission.
1390
 *
1391
 * @param mixed[] $groups array where the keys are the group id's
1392
 * @param int[] $profile
1393
 * @param string[] $permissions
1394
 * @package Permissions
1395
 */
1396
function deleteBoardPermissions($groups, $profile, $permissions)
1397
{
1398
	$db = database();
1399
1400
	// Start by deleting all the permissions relevant.
1401
	$db->query('', '
1402
		DELETE FROM {db_prefix}board_permissions
1403
		WHERE id_profile = {int:current_profile}
1404
			AND permission IN ({array_string:permissions})
1405
			AND id_group IN ({array_int:profile_group_list})',
1406
		array(
1407
			'profile_group_list' => array_keys($groups),
1408
			'current_profile' => $profile,
1409
			'permissions' => $permissions,
1410
		)
1411
	);
1412
}
1413
1414
/**
1415
 * Adds a new board permission to the board_permissions table.
1416
 *
1417
 * @param mixed[] $new_permissions
1418
 * @package Permissions
1419
 */
1420
function insertBoardPermission($new_permissions)
1421
{
1422
	$db = database();
1423
1424
	$db->insert('',
1425
		'{db_prefix}board_permissions',
1426
		array('id_profile' => 'int', 'id_group' => 'int', 'permission' => 'string', 'add_deny' => 'int'),
1427
		$new_permissions,
1428
		array('id_profile', 'id_group', 'permission')
1429
	);
1430
}
1431
1432
/**
1433
 * Lists the board permissions.
1434
 *
1435
 * @param int[] $group
1436
 * @param int $profile
1437
 * @param string[] $permissions
1438
 * @return array
1439
 * @package Permissions
1440
 */
1441
function getPermission($group, $profile, $permissions)
1442
{
1443
	$db = database();
1444
1445
	$groups = array();
1446
1447
	$db->fetchQuery('
1448
		SELECT 
1449
			id_group, permission, add_deny
1450
		FROM {db_prefix}board_permissions
1451
		WHERE id_profile = {int:current_profile}
1452
			AND permission IN ({array_string:permissions})
1453
			AND id_group IN ({array_int:profile_group_list})',
1454
		array(
1455
			'profile_group_list' => $group,
1456
			'current_profile' => $profile,
1457
			'permissions' => $permissions,
1458
		)
1459
	)->fetch_callback(
1460
		function ($row) use (&$groups) {
1461
			$groups[$row['id_group']][$row['add_deny'] ? 'add' : 'deny'][] = $row['permission'];
1462
		}
1463
	);
1464
1465
	return $groups;
1466
}
1467