Failed Conditions
Branch release-2.1 (4e22cf)
by Rick
06:39
created

Reports.php ➔ StaffReport()   F

Complexity

Conditions 16
Paths 840

Size

Total Lines 137
Code Lines 63

Duplication

Lines 4
Ratio 2.92 %

Importance

Changes 0
Metric Value
cc 16
eloc 63
nc 840
nop 0
dl 4
loc 137
rs 2.3966
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This file is exclusively for generating reports to help assist forum
5
 * administrators keep track of their forum configuration and state. The
6
 * core report generation is done in two areas. Firstly, a report "generator"
7
 * will fill context with relevant data. Secondly, the choice of sub-template
8
 * will determine how this data is shown to the user
9
 *
10
 * Functions ending with "Report" are responsible for generating data for reporting.
11
 * They are all called from ReportsMain.
12
 * Never access the context directly, but use the data handling functions to do so.
13
 *
14
 * Simple Machines Forum (SMF)
15
 *
16
 * @package SMF
17
 * @author Simple Machines http://www.simplemachines.org
18
 * @copyright 2017 Simple Machines and individual contributors
19
 * @license http://www.simplemachines.org/about/smf/license.php BSD
20
 *
21
 * @version 2.1 Beta 4
22
 */
23
24
if (!defined('SMF'))
25
	die('No direct access...');
26
27
/**
28
 * Handling function for generating reports.
29
 * Requires the admin_forum permission.
30
 * Loads the Reports template and language files.
31
 * Decides which type of report to generate, if this isn't passed
32
 * through the querystring it will set the report_type sub-template to
33
 * force the user to choose which type.
34
 * When generating a report chooses which sub_template to use.
35
 * Depends on the cal_enabled setting, and many of the other cal_
36
 * settings.
37
 * Will call the relevant report generation function.
38
 * If generating report will call finishTables before returning.
39
 * Accessed through ?action=admin;area=reports.
40
 */
41
function ReportsMain()
42
{
43
	global $txt, $context, $scripturl;
44
45
	// Only admins, only EVER admins!
46
	isAllowedTo('admin_forum');
47
48
	// Let's get our things running...
49
	loadTemplate('Reports');
50
	loadLanguage('Reports');
51
52
	$context['page_title'] = $txt['generate_reports'];
53
54
	// These are the types of reports which exist - and the functions to generate them.
55
	$context['report_types'] = array(
56
		'boards' => 'BoardReport',
57
		'board_perms' => 'BoardPermissionsReport',
58
		'member_groups' => 'MemberGroupsReport',
59
		'group_perms' => 'GroupPermissionsReport',
60
		'staff' => 'StaffReport',
61
	);
62
63
	call_integration_hook('integrate_report_types');
64
	// Load up all the tabs...
65
	$context[$context['admin_menu_name']]['tab_data'] = array(
66
		'title' => $txt['generate_reports'],
67
		'help' => '',
68
		'description' => $txt['generate_reports_desc'],
69
	);
70
71
	$is_first = 0;
72
	foreach ($context['report_types'] as $k => $temp)
73
		$context['report_types'][$k] = array(
74
			'id' => $k,
75
			'title' => isset($txt['gr_type_' . $k]) ? $txt['gr_type_' . $k] : $k,
76
			'description' => isset($txt['gr_type_desc_' . $k]) ? $txt['gr_type_desc_' . $k] : null,
77
			'function' => $temp,
78
			'is_first' => $is_first++ == 0,
79
		);
80
81
	// If they haven't chosen a report type which is valid, send them off to the report type chooser!
82
	if (empty($_REQUEST['rt']) || !isset($context['report_types'][$_REQUEST['rt']]))
83
	{
84
		$context['sub_template'] = 'report_type';
85
		return;
86
	}
87
	$context['report_type'] = $_REQUEST['rt'];
88
89
	// What are valid templates for showing reports?
90
	$reportTemplates = array(
91
		'main' => array(
92
			'layers' => null,
93
		),
94
		'print' => array(
95
			'layers' => array('print'),
96
		),
97
	);
98
99
	// Specific template? Use that instead of main!
100
	if (isset($_REQUEST['st']) && isset($reportTemplates[$_REQUEST['st']]))
101
	{
102
		$context['sub_template'] = $_REQUEST['st'];
103
104
		// Are we disabling the other layers - print friendly for example?
105
		if ($reportTemplates[$_REQUEST['st']]['layers'] !== null)
106
			$context['template_layers'] = $reportTemplates[$_REQUEST['st']]['layers'];
107
	}
108
109
	// Make the page title more descriptive.
110
	$context['page_title'] .= ' - ' . (isset($txt['gr_type_' . $context['report_type']]) ? $txt['gr_type_' . $context['report_type']] : $context['report_type']);
111
112
	// Build the reports button array.
113
	$context['report_buttons'] = array(
114
		'generate_reports' => array('text' => 'generate_reports', 'image' => 'print.png', 'url' => $scripturl . '?action=admin;area=reports', 'active' => true),
115
		'print' => array('text' => 'print', 'image' => 'print.png', 'url' => $scripturl . '?action=admin;area=reports;rt=' . $context['report_type'] . ';st=print', 'custom' => 'target="_blank"'),
116
	);
117
118
	// Allow mods to add additional buttons here
119
	call_integration_hook('integrate_report_buttons');
120
121
	// Now generate the data.
122
	$context['report_types'][$context['report_type']]['function']();
123
124
	// Finish the tables before exiting - this is to help the templates a little more.
125
	finishTables();
126
}
127
128
/**
129
 * Standard report about what settings the boards have.
130
 * functions ending with "Report" are responsible for generating data
131
 * for reporting.
132
 * they are all called from ReportsMain.
133
 * never access the context directly, but use the data handling
134
 * functions to do so.
135
 */
136
function BoardReport()
137
{
138
	global $context, $txt, $sourcedir, $smcFunc, $modSettings;
139
140
	// Load the permission profiles.
141
	require_once($sourcedir . '/ManagePermissions.php');
142
	loadLanguage('ManagePermissions');
143
	loadPermissionProfiles();
144
145
	// Get every moderator.
146
	$request = $smcFunc['db_query']('', '
147
		SELECT mods.id_board, mods.id_member, mem.real_name
148
		FROM {db_prefix}moderators AS mods
149
			INNER JOIN {db_prefix}members AS mem ON (mem.id_member = mods.id_member)',
150
		array(
151
		)
152
	);
153
	$moderators = array();
154
	while ($row = $smcFunc['db_fetch_assoc']($request))
155
		$moderators[$row['id_board']][] = $row['real_name'];
156
	$smcFunc['db_free_result']($request);
157
158
	// Get every moderator gruop.
159
	$request = $smcFunc['db_query']('', '
160
		SELECT modgs.id_board, modgs.id_group, memg.group_name
161
		FROM {db_prefix}moderator_groups AS modgs
162
			INNER JOIN {db_prefix}membergroups AS memg ON (memg.id_group = modgs.id_group)',
163
		array(
164
		)
165
	);
166
	$moderator_groups = array();
167
	while ($row = $smcFunc['db_fetch_assoc']($request))
168
		$moderator_groups[$row['id_board']][] = $row['group_name'];
169
	$smcFunc['db_free_result']($request);
170
171
	// Get all the possible membergroups!
172
	$request = $smcFunc['db_query']('', '
173
		SELECT id_group, group_name, online_color
174
		FROM {db_prefix}membergroups',
175
		array(
176
		)
177
	);
178
	$groups = array(-1 => $txt['guest_title'], 0 => $txt['full_member']);
179 View Code Duplication
	while ($row = $smcFunc['db_fetch_assoc']($request))
180
		$groups[$row['id_group']] = empty($row['online_color']) ? $row['group_name'] : '<span style="color: ' . $row['online_color'] . '">' . $row['group_name'] . '</span>';
181
	$smcFunc['db_free_result']($request);
182
183
	// All the fields we'll show.
184
	$boardSettings = array(
185
		'category' => $txt['board_category'],
186
		'parent' => $txt['board_parent'],
187
		'redirect' => $txt['board_redirect'],
188
		'num_topics' => $txt['board_num_topics'],
189
		'num_posts' => $txt['board_num_posts'],
190
		'count_posts' => $txt['board_count_posts'],
191
		'theme' => $txt['board_theme'],
192
		'override_theme' => $txt['board_override_theme'],
193
		'profile' => $txt['board_profile'],
194
		'moderators' => $txt['board_moderators'],
195
		'moderator_groups' => $txt['board_moderator_groups'],
196
		'groups' => $txt['board_groups'],
197
	);
198
	if (!empty($modSettings['deny_boards_access']))
199
		$boardSettings['disallowed_groups'] = $txt['board_disallowed_groups'];
200
201
	// Do it in columns, it's just easier.
202
	setKeys('cols');
203
204
	// Go through each board!
205
	$request = $smcFunc['db_query']('order_by_board_order', '
206
		SELECT b.id_board, b.name, b.num_posts, b.num_topics, b.count_posts, b.member_groups, b.override_theme, b.id_profile, b.deny_member_groups,
207
			b.redirect, c.name AS cat_name, COALESCE(par.name, {string:text_none}) AS parent_name, COALESCE(th.value, {string:text_none}) AS theme_name
208
		FROM {db_prefix}boards AS b
209
			LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)
210
			LEFT JOIN {db_prefix}boards AS par ON (par.id_board = b.id_parent)
211
			LEFT JOIN {db_prefix}themes AS th ON (th.id_theme = b.id_theme AND th.variable = {string:name})
212
		ORDER BY b.board_order',
213
		array(
214
			'name' => 'name',
215
			'text_none' => $txt['none'],
216
		)
217
	);
218
219
	while ($row = $smcFunc['db_fetch_assoc']($request))
220
	{
221
		// Each board has it's own table.
222
		newTable($row['name'], '', 'left', 'auto', 'left', 200, 'left');
223
224
		$this_boardSettings = $boardSettings;
225
		if (empty($row['redirect']))
226
			unset($this_boardSettings['redirect']);
227
228
		// First off, add in the side key.
229
		addData($this_boardSettings);
230
231
		// Format the profile name.
232
		$profile_name = $context['profiles'][$row['id_profile']]['name'];
233
234
		// Create the main data array.
235
		$boardData = array(
236
			'category' => $row['cat_name'],
237
			'parent' => $row['parent_name'],
238
			'redirect' => $row['redirect'],
239
			'num_posts' => $row['num_posts'],
240
			'num_topics' => $row['num_topics'],
241
			'count_posts' => empty($row['count_posts']) ? $txt['yes'] : $txt['no'],
242
			'theme' => $row['theme_name'],
243
			'profile' => $profile_name,
244
			'override_theme' => $row['override_theme'] ? $txt['yes'] : $txt['no'],
245
			'moderators' => empty($moderators[$row['id_board']]) ? $txt['none'] : implode(', ', $moderators[$row['id_board']]),
246
			'moderator_groups' => empty($moderator_groups[$row['id_board']]) ? $txt['none'] : implode(', ', $moderator_groups[$row['id_board']]),
247
		);
248
249
		// Work out the membergroups who can and cannot access it (but only if enabled).
250
		$allowedGroups = explode(',', $row['member_groups']);
251 View Code Duplication
		foreach ($allowedGroups as $key => $group)
252
		{
253
			if (isset($groups[$group]))
254
				$allowedGroups[$key] = $groups[$group];
255
			else
256
				unset($allowedGroups[$key]);
257
		}
258
		$boardData['groups'] = implode(', ', $allowedGroups);
259
		if (!empty($modSettings['deny_boards_access']))
260
		{
261
			$disallowedGroups = explode(',', $row['deny_member_groups']);
262 View Code Duplication
			foreach ($disallowedGroups as $key => $group)
263
			{
264
				if (isset($groups[$group]))
265
					$disallowedGroups[$key] = $groups[$group];
266
				else
267
					unset($disallowedGroups[$key]);
268
			}
269
			$boardData['disallowed_groups'] = implode(', ', $disallowedGroups);
270
		}
271
272
		if (empty($row['redirect']))
273
			unset ($boardData['redirect']);
274
275
		// Next add the main data.
276
		addData($boardData);
277
	}
278
	$smcFunc['db_free_result']($request);
279
}
280
281
/**
282
 * Generate a report on the current permissions by board and membergroup.
283
 * functions ending with "Report" are responsible for generating data
284
 * for reporting.
285
 * they are all called from ReportsMain.
286
 * never access the context directly, but use the data handling
287
 * functions to do so.
288
 */
289
function BoardPermissionsReport()
290
{
291
	global $txt, $modSettings, $smcFunc;
292
293
	// Get as much memory as possible as this can be big.
294
	setMemoryLimit('256M');
295
296 View Code Duplication
	if (isset($_REQUEST['boards']))
297
	{
298
		if (!is_array($_REQUEST['boards']))
299
			$_REQUEST['boards'] = explode(',', $_REQUEST['boards']);
300
		foreach ($_REQUEST['boards'] as $k => $dummy)
301
			$_REQUEST['boards'][$k] = (int) $dummy;
302
303
		$board_clause = 'id_board IN ({array_int:boards})';
304
	}
305
	else
306
		$board_clause = '1=1';
307
308 View Code Duplication
	if (isset($_REQUEST['groups']))
309
	{
310
		if (!is_array($_REQUEST['groups']))
311
			$_REQUEST['groups'] = explode(',', $_REQUEST['groups']);
312
		foreach ($_REQUEST['groups'] as $k => $dummy)
313
			$_REQUEST['groups'][$k] = (int) $dummy;
314
315
		$group_clause = 'id_group IN ({array_int:groups})';
316
	}
317
	else
318
		$group_clause = '1=1';
319
320
	// Fetch all the board names.
321
	$request = $smcFunc['db_query']('', '
322
		SELECT id_board, name, id_profile
323
		FROM {db_prefix}boards
324
		WHERE ' . $board_clause . '
325
		ORDER BY id_board',
326
		array(
327
			'boards' => isset($_REQUEST['boards']) ? $_REQUEST['boards'] : array(),
328
		)
329
	);
330
	$profiles = array();
331
	while ($row = $smcFunc['db_fetch_assoc']($request))
332
	{
333
		$boards[$row['id_board']] = array(
0 ignored issues
show
Coding Style Comprehensibility introduced by
$boards was never initialized. Although not strictly required by PHP, it is generally a good practice to add $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...
334
			'name' => $row['name'],
335
			'profile' => $row['id_profile'],
336
			'mod_groups' => array(),
337
		);
338
		$profiles[] = $row['id_profile'];
339
	}
340
	$smcFunc['db_free_result']($request);
341
342
	// Get the ids of any groups allowed to moderate this board
343
	// Limit it to any boards and/or groups we're looking at
344
	$request = $smcFunc['db_query']('', '
345
		SELECT id_board, id_group
346
		FROM {db_prefix}moderator_groups
347
		WHERE ' . $board_clause . ' AND ' . $group_clause,
348
		array(
349
		)
350
	);
351
	while ($row = $smcFunc['db_fetch_assoc']($request))
352
	{
353
		$boards[$row['id_board']]['mod_groups'][] = $row['id_group'];
0 ignored issues
show
Bug introduced by
The variable $boards 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...
354
	}
355
	$smcFunc['db_free_result']($request);
356
357
	// Get all the possible membergroups, except admin!
358
	$request = $smcFunc['db_query']('', '
359
		SELECT id_group, group_name
360
		FROM {db_prefix}membergroups
361
		WHERE ' . $group_clause . '
362
			AND id_group != {int:admin_group}' . (empty($modSettings['permission_enable_postgroups']) ? '
363
			AND min_posts = {int:min_posts}' : '') . '
364
		ORDER BY min_posts, CASE WHEN id_group < {int:newbie_group} THEN id_group ELSE 4 END, group_name',
365
		array(
366
			'admin_group' => 1,
367
			'min_posts' => -1,
368
			'newbie_group' => 4,
369
			'groups' => isset($_REQUEST['groups']) ? $_REQUEST['groups'] : array(),
370
		)
371
	);
372 View Code Duplication
	if (!isset($_REQUEST['groups']) || in_array(-1, $_REQUEST['groups']) || in_array(0, $_REQUEST['groups']))
373
		$member_groups = array('col' => '', -1 => $txt['membergroups_guests'], 0 => $txt['membergroups_members']);
374
	else
375
		$member_groups = array('col' => '');
376 View Code Duplication
	while ($row = $smcFunc['db_fetch_assoc']($request))
377
		$member_groups[$row['id_group']] = $row['group_name'];
378
	$smcFunc['db_free_result']($request);
379
380
	// Make sure that every group is represented - plus in rows!
381
	setKeys('rows', $member_groups);
382
383
	// Certain permissions should not really be shown.
384
	$disabled_permissions = array();
385
	if (!$modSettings['postmod_active'])
386
	{
387
		$disabled_permissions[] = 'approve_posts';
388
		$disabled_permissions[] = 'post_unapproved_topics';
389
		$disabled_permissions[] = 'post_unapproved_replies_own';
390
		$disabled_permissions[] = 'post_unapproved_replies_any';
391
		$disabled_permissions[] = 'post_unapproved_attachments';
392
	}
393
394
	call_integration_hook('integrate_reports_boardperm', array(&$disabled_permissions));
395
396
	// Cache every permission setting, to make sure we don't miss any allows.
397
	$permissions = array();
398
	$board_permissions = array();
399
	$request = $smcFunc['db_query']('', '
400
		SELECT id_profile, id_group, add_deny, permission
401
		FROM {db_prefix}board_permissions
402
		WHERE id_profile IN ({array_int:profile_list})
403
			AND ' . $group_clause . (empty($modSettings['permission_enable_deny']) ? '
404
			AND add_deny = {int:not_deny}' : '') . '
405
		ORDER BY id_profile, permission',
406
		array(
407
			'profile_list' => $profiles,
408
			'not_deny' => 1,
409
			'groups' => isset($_REQUEST['groups']) ? $_REQUEST['groups'] : array(),
410
		)
411
	);
412
	while ($row = $smcFunc['db_fetch_assoc']($request))
413
	{
414
		if (in_array($row['permission'], $disabled_permissions))
415
			continue;
416
417
		foreach ($boards as $id => $board)
418
			if ($board['profile'] == $row['id_profile'])
419
				$board_permissions[$id][$row['id_group']][$row['permission']] = $row['add_deny'];
420
421
		// Make sure we get every permission.
422
		if (!isset($permissions[$row['permission']]))
423
		{
424
			// This will be reused on other boards.
425
			$permissions[$row['permission']] = array(
426
				'title' => isset($txt['board_perms_name_' . $row['permission']]) ? $txt['board_perms_name_' . $row['permission']] : $row['permission'],
427
			);
428
		}
429
	}
430
	$smcFunc['db_free_result']($request);
431
432
	// Now cycle through the board permissions array... lots to do ;)
433
	foreach ($board_permissions as $board => $groups)
434
	{
435
		// Create the table for this board first.
436
		newTable($boards[$board]['name'], 'x', 'all', 100, 'center', 200, 'left');
437
438
		// Add the header row - shows all the membergroups.
439
		addData($member_groups);
440
441
		// Add the separator.
442
		addSeparator($txt['board_perms_permission']);
443
444
		// Here cycle through all the detected permissions.
445
		foreach ($permissions as $ID_PERM => $perm_info)
446
		{
447
			// Default data for this row.
448
			$curData = array('col' => $perm_info['title']);
449
450
			// Now cycle each membergroup in this set of permissions.
451
			foreach ($member_groups as $id_group => $name)
452
			{
453
				// Don't overwrite the key column!
454
				if ($id_group === 'col')
455
					continue;
456
457
				$group_permissions = isset($groups[$id_group]) ? $groups[$id_group] : array();
458
459
				// Do we have any data for this group?
460
				if (isset($group_permissions[$ID_PERM]))
461
				{
462
					// Set the data for this group to be the local permission.
463
					$curData[$id_group] = $group_permissions[$ID_PERM];
464
				}
465
				// Is it inherited from Moderator?
466
				elseif (in_array($id_group, $boards[$board]['mod_groups']) && !empty($groups[3]) && isset($groups[3][$ID_PERM]))
467
				{
468
					$curData[$id_group] = $groups[3][$ID_PERM];
469
				}
470
				// Otherwise means it's set to disallow..
471
				else
472
				{
473
					$curData[$id_group] = 'x';
474
				}
475
476
				// Now actually make the data for the group look right.
477
				if (empty($curData[$id_group]))
478
					$curData[$id_group] = '<span class="red">' . $txt['board_perms_deny'] . '</span>';
479
				elseif ($curData[$id_group] == 1)
480
					$curData[$id_group] = '<span style="color: darkgreen;">' . $txt['board_perms_allow'] . '</span>';
481
				else
482
					$curData[$id_group] = 'x';
483
484
				// Embolden those permissions different from global (makes it a lot easier!)
485
				if (@$board_permissions[0][$id_group][$ID_PERM] != @$group_permissions[$ID_PERM])
486
					$curData[$id_group] = '<strong>' . $curData[$id_group] . '</strong>';
487
			}
488
489
			// Now add the data for this permission.
490
			addData($curData);
491
		}
492
	}
493
}
494
495
/**
496
 * Show what the membergroups are made of.
497
 * functions ending with "Report" are responsible for generating data
498
 * for reporting.
499
 * they are all called from ReportsMain.
500
 * never access the context directly, but use the data handling
501
 * functions to do so.
502
 */
503
function MemberGroupsReport()
504
{
505
	global $txt, $settings, $modSettings, $smcFunc;
506
507
	// Fetch all the board names.
508
	$request = $smcFunc['db_query']('', '
509
		SELECT id_board, name, member_groups, id_profile, deny_member_groups
510
		FROM {db_prefix}boards',
511
		array(
512
		)
513
	);
514
	while ($row = $smcFunc['db_fetch_assoc']($request))
515
	{
516 View Code Duplication
		if (trim($row['member_groups']) == '')
517
			$groups = array(1);
518
		else
519
			$groups = array_merge(array(1), explode(',', $row['member_groups']));
520
521
		if (trim($row['deny_member_groups']) == '')
522
			$denyGroups = array();
523
		else
524
			$denyGroups = explode(',', $row['deny_member_groups']);
525
526
		$boards[$row['id_board']] = array(
0 ignored issues
show
Coding Style Comprehensibility introduced by
$boards was never initialized. Although not strictly required by PHP, it is generally a good practice to add $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...
527
			'id' => $row['id_board'],
528
			'name' => $row['name'],
529
			'profile' => $row['id_profile'],
530
			'groups' => $groups,
531
			'deny_groups' => $denyGroups,
532
		);
533
	}
534
	$smcFunc['db_free_result']($request);
535
536
	// Standard settings.
537
	$mgSettings = array(
538
		'name' => '',
539
		'#sep#1' => $txt['member_group_settings'],
540
		'color' => $txt['member_group_color'],
541
		'min_posts' => $txt['member_group_min_posts'],
542
		'max_messages' => $txt['member_group_max_messages'],
543
		'icons' => $txt['member_group_icons'],
544
		'#sep#2' => $txt['member_group_access'],
545
	);
546
547
	// Add on the boards!
548
	foreach ($boards as $board)
0 ignored issues
show
Bug introduced by
The variable $boards 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...
549
		$mgSettings['board_' . $board['id']] = $board['name'];
550
551
	// Add all the membergroup settings, plus we'll be adding in columns!
552
	setKeys('cols', $mgSettings);
553
554
	// Only one table this time!
555
	newTable($txt['gr_type_member_groups'], '-', 'all', 100, 'center', 200, 'left');
556
557
	// Get the shaded column in.
558
	addData($mgSettings);
559
560
	// Now start cycling the membergroups!
561
	$request = $smcFunc['db_query']('', '
562
		SELECT mg.id_group, mg.group_name, mg.online_color, mg.min_posts, mg.max_messages, mg.icons,
563
			CASE WHEN bp.permission IS NOT NULL OR mg.id_group = {int:admin_group} THEN 1 ELSE 0 END AS can_moderate
564
		FROM {db_prefix}membergroups AS mg
565
			LEFT JOIN {db_prefix}board_permissions AS bp ON (bp.id_group = mg.id_group AND bp.id_profile = {int:default_profile} AND bp.permission = {string:moderate_board})
566
		ORDER BY mg.min_posts, CASE WHEN mg.id_group < {int:newbie_group} THEN mg.id_group ELSE 4 END, mg.group_name',
567
		array(
568
			'admin_group' => 1,
569
			'default_profile' => 1,
570
			'newbie_group' => 4,
571
			'moderate_board' => 'moderate_board',
572
		)
573
	);
574
575
	// Cache them so we get regular members too.
576
	$rows = array(
577
		array(
578
			'id_group' => -1,
579
			'group_name' => $txt['membergroups_guests'],
580
			'online_color' => '',
581
			'min_posts' => -1,
582
			'max_messages' => null,
583
			'icons' => ''
584
		),
585
		array(
586
			'id_group' => 0,
587
			'group_name' => $txt['membergroups_members'],
588
			'online_color' => '',
589
			'min_posts' => -1,
590
			'max_messages' => null,
591
			'icons' => ''
592
		),
593
	);
594
	while ($row = $smcFunc['db_fetch_assoc']($request))
595
		$rows[] = $row;
596
	$smcFunc['db_free_result']($request);
597
598
	foreach ($rows as $row)
599
	{
600
		$row['icons'] = explode('#', $row['icons']);
601
602
		$group = array(
603
			'name' => $row['group_name'],
604
			'color' => empty($row['online_color']) ? '-' : '<span style="color: ' . $row['online_color'] . ';">' . $row['online_color'] . '</span>',
605
			'min_posts' => $row['min_posts'] == -1 ? 'N/A' : $row['min_posts'],
606
			'max_messages' => $row['max_messages'],
607
			'icons' => !empty($row['icons'][0]) && !empty($row['icons'][1]) ? str_repeat('<img src="' . $settings['images_url'] . '/membericons/' . $row['icons'][1] . '" alt="*">', $row['icons'][0]) : '',
608
		);
609
610
		// Board permissions.
611
		foreach ($boards as $board)
612
			$group['board_' . $board['id']] = in_array($row['id_group'], $board['groups']) ? '<span class="success">' . $txt['board_perms_allow'] . '</span>' : (!empty($modSettings['deny_boards_access']) && in_array($row['id_group'], $board['deny_groups']) ? '<span class="alert">' . $txt['board_perms_deny'] . '</span>' : 'x');
613
614
		addData($group);
615
	}
616
}
617
618
/**
619
 * Show the large variety of group permissions assigned to each membergroup.
620
 * functions ending with "Report" are responsible for generating data
621
 * for reporting.
622
 * they are all called from ReportsMain.
623
 * never access the context directly, but use the data handling
624
 * functions to do so.
625
 */
626
function GroupPermissionsReport()
627
{
628
	global $txt, $modSettings, $smcFunc;
629
630
	if (isset($_REQUEST['groups']))
631
	{
632
		if (!is_array($_REQUEST['groups']))
633
			$_REQUEST['groups'] = explode(',', $_REQUEST['groups']);
634
		foreach ($_REQUEST['groups'] as $k => $dummy)
635
			$_REQUEST['groups'][$k] = (int) $dummy;
636
		$_REQUEST['groups'] = array_diff($_REQUEST['groups'], array(3));
637
638
		$clause = 'id_group IN ({array_int:groups})';
639
	}
640
	else
641
		$clause = 'id_group != {int:moderator_group}';
642
643
	// Get all the possible membergroups, except admin!
644
	$request = $smcFunc['db_query']('', '
645
		SELECT id_group, group_name
646
		FROM {db_prefix}membergroups
647
		WHERE ' . $clause . '
648
			AND id_group != {int:admin_group}' . (empty($modSettings['permission_enable_postgroups']) ? '
649
			AND min_posts = {int:min_posts}' : '') . '
650
		ORDER BY min_posts, CASE WHEN id_group < {int:newbie_group} THEN id_group ELSE 4 END, group_name',
651
		array(
652
			'admin_group' => 1,
653
			'min_posts' => -1,
654
			'newbie_group' => 4,
655
			'moderator_group' => 3,
656
			'groups' => isset($_REQUEST['groups']) ? $_REQUEST['groups'] : array(),
657
		)
658
	);
659 View Code Duplication
	if (!isset($_REQUEST['groups']) || in_array(-1, $_REQUEST['groups']) || in_array(0, $_REQUEST['groups']))
660
		$groups = array('col' => '', -1 => $txt['membergroups_guests'], 0 => $txt['membergroups_members']);
661
	else
662
		$groups = array('col' => '');
663 View Code Duplication
	while ($row = $smcFunc['db_fetch_assoc']($request))
664
		$groups[$row['id_group']] = $row['group_name'];
665
	$smcFunc['db_free_result']($request);
666
667
	// Make sure that every group is represented!
668
	setKeys('rows', $groups);
669
670
	// Create the table first.
671
	newTable($txt['gr_type_group_perms'], '-', 'all', 100, 'center', 200, 'left');
672
673
	// Show all the groups
674
	addData($groups);
675
676
	// Add a separator
677
	addSeparator($txt['board_perms_permission']);
678
679
	// Certain permissions should not really be shown.
680
	$disabled_permissions = array();
681
	if (empty($modSettings['cal_enabled']))
682
	{
683
		$disabled_permissions[] = 'calendar_view';
684
		$disabled_permissions[] = 'calendar_post';
685
		$disabled_permissions[] = 'calendar_edit_own';
686
		$disabled_permissions[] = 'calendar_edit_any';
687
	}
688
	if (empty($modSettings['warning_settings']) || $modSettings['warning_settings'][0] == 0)
689
		$disabled_permissions[] = 'issue_warning';
690
691
	call_integration_hook('integrate_reports_groupperm', array(&$disabled_permissions));
692
693
	// Now the big permission fetch!
694
	$request = $smcFunc['db_query']('', '
695
		SELECT id_group, add_deny, permission
696
		FROM {db_prefix}permissions
697
		WHERE ' . $clause . (empty($modSettings['permission_enable_deny']) ? '
698
			AND add_deny = {int:not_denied}' : '') . '
699
		ORDER BY permission',
700
		array(
701
			'not_denied' => 1,
702
			'moderator_group' => 3,
703
			'groups' => isset($_REQUEST['groups']) ? $_REQUEST['groups'] : array(),
704
		)
705
	);
706
	$lastPermission = null;
707
	$curData = array();
708
	while ($row = $smcFunc['db_fetch_assoc']($request))
709
	{
710
		if (in_array($row['permission'], $disabled_permissions))
711
			continue;
712
713
		// If this is a new permission flush the last row.
714
		if ($row['permission'] != $lastPermission)
715
		{
716
			// Send the data!
717
			if ($lastPermission !== null)
718
				addData($curData);
719
720
			// Add the permission name in the left column.
721
			$curData = array('col' => isset($txt['group_perms_name_' . $row['permission']]) ? $txt['group_perms_name_' . $row['permission']] : $row['permission']);
722
723
			$lastPermission = $row['permission'];
724
		}
725
726
		// Good stuff - add the permission to the list!
727
		if ($row['add_deny'])
728
			$curData[$row['id_group']] = '<span style="color: darkgreen;">' . $txt['board_perms_allow'] . '</span>';
729
		else
730
			$curData[$row['id_group']] = '<span class="red">' . $txt['board_perms_deny'] . '</span>';
731
	}
732
	$smcFunc['db_free_result']($request);
733
734
	// Flush the last data!
735
	addData($curData);
736
}
737
738
/**
739
 * Report for showing all the forum staff members - quite a feat!
740
 * functions ending with "Report" are responsible for generating data
741
 * for reporting.
742
 * they are all called from ReportsMain.
743
 * never access the context directly, but use the data handling
744
 * functions to do so.
745
 */
746
function StaffReport()
747
{
748
	global $sourcedir, $txt, $smcFunc;
749
750
	require_once($sourcedir . '/Subs-Members.php');
751
752
	// Fetch all the board names.
753
	$request = $smcFunc['db_query']('', '
754
		SELECT id_board, name
755
		FROM {db_prefix}boards',
756
		array(
757
		)
758
	);
759
	$boards = array();
760 View Code Duplication
	while ($row = $smcFunc['db_fetch_assoc']($request))
761
		$boards[$row['id_board']] = $row['name'];
762
	$smcFunc['db_free_result']($request);
763
764
	// Get every moderator.
765
	$request = $smcFunc['db_query']('', '
766
		SELECT mods.id_board, mods.id_member
767
		FROM {db_prefix}moderators AS mods',
768
		array(
769
		)
770
	);
771
	$moderators = array();
772
	$local_mods = array();
773
	while ($row = $smcFunc['db_fetch_assoc']($request))
774
	{
775
		$moderators[$row['id_member']][] = $row['id_board'];
776
		$local_mods[$row['id_member']] = $row['id_member'];
777
	}
778
	$smcFunc['db_free_result']($request);
779
780
	// Get any additional boards they can moderate through group-based board moderation
781
	$request = $smcFunc['db_query']('', '
782
		SELECT mem.id_member, modgs.id_board
783
		FROM {db_prefix}members AS mem
784
			INNER JOIN {db_prefix}moderator_groups AS modgs ON (modgs.id_group = mem.id_group OR FIND_IN_SET(modgs.id_group, mem.additional_groups) != 0)',
785
		array(
786
		)
787
	);
788
789
	// Add each board/member to the arrays, but only if they aren't already there
790
	while ($row = $smcFunc['db_fetch_assoc']($request))
791
	{
792
		// Either we don't have them as a moderator at all or at least not as a moderator of this board
793
		if (!array_key_exists($row['id_member'], $moderators) || !in_array($row['id_board'], $moderators[$row['id_member']]))
794
			$moderators[$row['id_member']][] = $row['id_board'];
795
796
		// We don't have them listed as a moderator yet
797
		if (!array_key_exists($row['id_member'], $local_mods))
798
			$local_mods[$row['id_member']] = $row['id_member'];
799
	}
800
801
	// Get a list of global moderators (i.e. members with moderation powers).
802
	$global_mods = array_intersect(membersAllowedTo('moderate_board', 0), membersAllowedTo('approve_posts', 0), membersAllowedTo('remove_any', 0), membersAllowedTo('modify_any', 0));
803
804
	// How about anyone else who is special?
805
	$allStaff = array_merge(membersAllowedTo('admin_forum'), membersAllowedTo('manage_membergroups'), membersAllowedTo('manage_permissions'), $local_mods, $global_mods);
806
807
	// Make sure everyone is there once - no admin less important than any other!
808
	$allStaff = array_unique($allStaff);
809
810
	// This is a bit of a cop out - but we're protecting their forum, really!
811
	if (count($allStaff) > 300)
812
		fatal_lang_error('report_error_too_many_staff');
813
814
	// Get all the possible membergroups!
815
	$request = $smcFunc['db_query']('', '
816
		SELECT id_group, group_name, online_color
817
		FROM {db_prefix}membergroups',
818
		array(
819
		)
820
	);
821
	$groups = array(0 => $txt['full_member']);
822 View Code Duplication
	while ($row = $smcFunc['db_fetch_assoc']($request))
823
		$groups[$row['id_group']] = empty($row['online_color']) ? $row['group_name'] : '<span style="color: ' . $row['online_color'] . '">' . $row['group_name'] . '</span>';
824
	$smcFunc['db_free_result']($request);
825
826
	// All the fields we'll show.
827
	$staffSettings = array(
828
		'position' => $txt['report_staff_position'],
829
		'moderates' => $txt['report_staff_moderates'],
830
		'posts' => $txt['report_staff_posts'],
831
		'last_login' => $txt['report_staff_last_login'],
832
	);
833
834
	// Do it in columns, it's just easier.
835
	setKeys('cols');
836
837
	// Get each member!
838
	$request = $smcFunc['db_query']('', '
839
		SELECT id_member, real_name, id_group, posts, last_login
840
		FROM {db_prefix}members
841
		WHERE id_member IN ({array_int:staff_list})
842
		ORDER BY real_name',
843
		array(
844
			'staff_list' => $allStaff,
845
		)
846
	);
847
	while ($row = $smcFunc['db_fetch_assoc']($request))
848
	{
849
		// Each member gets their own table!.
850
		newTable($row['real_name'], '', 'left', 'auto', 'left', 200, 'center');
851
852
		// First off, add in the side key.
853
		addData($staffSettings);
854
855
		// Create the main data array.
856
		$staffData = array(
857
			'position' => isset($groups[$row['id_group']]) ? $groups[$row['id_group']] : $groups[0],
858
			'posts' => $row['posts'],
859
			'last_login' => timeformat($row['last_login']),
860
			'moderates' => array(),
861
		);
862
863
		// What do they moderate?
864
		if (in_array($row['id_member'], $global_mods))
865
			$staffData['moderates'] = '<em>' . $txt['report_staff_all_boards'] . '</em>';
866
		elseif (isset($moderators[$row['id_member']]))
867
		{
868
			// Get the names
869
			foreach ($moderators[$row['id_member']] as $board)
870
				if (isset($boards[$board]))
871
					$staffData['moderates'][] = $boards[$board];
872
873
			$staffData['moderates'] = implode(', ', $staffData['moderates']);
874
		}
875
		else
876
			$staffData['moderates'] = '<em>' . $txt['report_staff_no_boards'] . '</em>';
877
878
		// Next add the main data.
879
		addData($staffData);
880
	}
881
	$smcFunc['db_free_result']($request);
882
}
883
884
/**
885
 * This function creates a new table of data, most functions will only use it once.
886
 * The core of this file, it creates a new, but empty, table of data in
887
 * context, ready for filling using addData().
888
 * Fills the context variable current_table with the ID of the table created.
889
 * Keeps track of the current table count using context variable table_count.
890
 *
891
 * @param string $title Title to be displayed with this data table.
892
 * @param string $default_value Value to be displayed if a key is missing from a row.
893
 * @param string $shading Should the left, top or both (all) parts of the table beshaded?
894
 * @param string $width_normal The width of an unshaded column (auto means not defined).
895
 * @param string $align_normal The alignment of data in an unshaded column.
896
 * @param string $width_shaded The width of a shaded column (auto means not defined).
897
 * @param string $align_shaded The alignment of data in a shaded column.
898
 */
899
function newTable($title = '', $default_value = '', $shading = 'all', $width_normal = 'auto', $align_normal = 'center', $width_shaded = 'auto', $align_shaded = 'auto')
900
{
901
	global $context;
902
903
	// Set the table count if needed.
904
	if (empty($context['table_count']))
905
		$context['table_count'] = 0;
906
907
	// Create the table!
908
	$context['tables'][$context['table_count']] = array(
909
		'title' => $title,
910
		'default_value' => $default_value,
911
		'shading' => array(
912
			'left' => $shading == 'all' || $shading == 'left',
913
			'top' => $shading == 'all' || $shading == 'top',
914
		),
915
		'width' => array(
916
			'normal' => $width_normal,
917
			'shaded' => $width_shaded,
918
		),
919
		/* Align usage deprecated due to HTML5 */
920
		'align' => array(
921
			'normal' => $align_normal,
922
			'shaded' => $align_shaded,
923
		),
924
		'data' => array(),
925
	);
926
927
	$context['current_table'] = $context['table_count'];
928
929
	// Increment the count...
930
	$context['table_count']++;
931
}
932
933
/**
934
 * Adds an array of data into an existing table.
935
 * if there are no existing tables, will create one with default
936
 * attributes.
937
 * if custom_table isn't specified, it will use the last table created,
938
 * if it is specified and doesn't exist the function will return false.
939
 * if a set of keys have been specified, the function will check each
940
 * required key is present in the incoming data. If this data is missing
941
 * the current tables default value will be used.
942
 * if any key in the incoming data begins with '#sep#', the function
943
 * will add a separator across the table at this point.
944
 * once the incoming data has been sanitized, it is added to the table.
945
 *
946
 * @param array $inc_data The data to include
947
 * @param null|string $custom_table = null The ID of a custom table to put the data in
948
 * @return void|false Doesn't return anything unless we've specified an invalid custom_table
949
 */
950
function addData($inc_data, $custom_table = null)
951
{
952
	global $context;
953
954
	// No tables? Create one even though we are probably already in a bad state!
955
	if (empty($context['table_count']))
956
		newTable();
957
958
	// Specific table?
959 View Code Duplication
	if ($custom_table !== null && !isset($context['tables'][$custom_table]))
960
		return false;
961
	elseif ($custom_table !== null)
962
		$table = $custom_table;
963
	else
964
		$table = $context['current_table'];
965
966
	// If we have keys, sanitise the data...
967
	if (!empty($context['keys']))
968
	{
969
		// Basically, check every key exists!
970
		foreach ($context['keys'] as $key => $dummy)
971
		{
972
			$data[$key] = array(
0 ignored issues
show
Coding Style Comprehensibility introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = 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...
973
				'v' => empty($inc_data[$key]) ? $context['tables'][$table]['default_value'] : $inc_data[$key],
974
			);
975
			// Special "hack" the adding separators when doing data by column.
976 View Code Duplication
			if (substr($key, 0, 5) == '#sep#')
977
				$data[$key]['separator'] = true;
978
		}
979
	}
980
	else
981
	{
982
		$data = $inc_data;
983
		foreach ($data as $key => $value)
984
		{
985
			$data[$key] = array(
986
				'v' => $value,
987
			);
988 View Code Duplication
			if (substr($key, 0, 5) == '#sep#')
989
				$data[$key]['separator'] = true;
990
		}
991
	}
992
993
	// Is it by row?
994
	if (empty($context['key_method']) || $context['key_method'] == 'rows')
995
	{
996
		// Add the data!
997
		$context['tables'][$table]['data'][] = $data;
0 ignored issues
show
Bug introduced by
The variable $data 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...
998
	}
999
	// Otherwise, tricky!
1000
	else
1001
	{
1002
		foreach ($data as $key => $item)
1003
			$context['tables'][$table]['data'][$key][] = $item;
1004
	}
1005
}
1006
1007
/**
1008
 * Add a separator row, only really used when adding data by rows.
1009
 *
1010
 * @param string $title The title of the separator
1011
 * @param null|string $custom_table The ID of the custom table
1012
 *
1013
 * @return void|bool Returns false if there are no tables
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use null|false.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
1014
 */
1015
function addSeparator($title = '', $custom_table = null)
1016
{
1017
	global $context;
1018
1019
	// No tables - return?
1020
	if (empty($context['table_count']))
1021
		return;
1022
1023
	// Specific table?
1024 View Code Duplication
	if ($custom_table !== null && !isset($context['tables'][$table]))
0 ignored issues
show
Bug introduced by
The variable $table seems only to be defined at a later point. As such the call to isset() seems to always evaluate to false.

This check marks calls to isset(...) or empty(...) that are found before the variable itself is defined. These will always have the same result.

This is likely the result of code being shifted around. Consider removing these calls.

Loading history...
1025
		return false;
1026
	elseif ($custom_table !== null)
1027
		$table = $custom_table;
1028
	else
1029
		$table = $context['current_table'];
1030
1031
	// Plumb in the separator
1032
	$context['tables'][$table]['data'][] = array(0 => array(
1033
		'separator' => true,
1034
		'v' => $title
1035
	));
1036
}
1037
1038
/**
1039
 * This does the necessary count of table data before displaying them.
1040
 * is (unfortunately) required to create some useful variables for templates.
1041
 * foreach data table created, it will count the number of rows and
1042
 * columns in the table.
1043
 * will also create a max_width variable for the table, to give an
1044
 * estimate width for the whole table * * if it can.
1045
 */
1046
function finishTables()
1047
{
1048
	global $context;
1049
1050
	if (empty($context['tables']))
1051
		return;
1052
1053
	// Loop through each table counting up some basic values, to help with the templating.
1054
	foreach ($context['tables'] as $id => $table)
1055
	{
1056
		$context['tables'][$id]['id'] = $id;
1057
		$context['tables'][$id]['row_count'] = count($table['data']);
1058
		$curElement = current($table['data']);
1059
		$context['tables'][$id]['column_count'] = count($curElement);
1060
1061
		// Work out the rough width - for templates like the print template. Without this we might get funny tables.
1062
		if ($table['shading']['left'] && $table['width']['shaded'] != 'auto' && $table['width']['normal'] != 'auto')
1063
			$context['tables'][$id]['max_width'] = $table['width']['shaded'] + ($context['tables'][$id]['column_count'] - 1) * $table['width']['normal'];
1064
		elseif ($table['width']['normal'] != 'auto')
1065
			$context['tables'][$id]['max_width'] = $context['tables'][$id]['column_count'] * $table['width']['normal'];
1066
		else
1067
			$context['tables'][$id]['max_width'] = 'auto';
1068
	}
1069
}
1070
1071
/**
1072
 * Set the keys in use by the tables - these ensure entries MUST exist if the data isn't sent.
1073
 *
1074
 * sets the current set of "keys" expected in each data array passed to
1075
 * addData. It also sets the way we are adding data to the data table.
1076
 * method specifies whether the data passed to addData represents a new
1077
 * column, or a new row.
1078
 * keys is an array whose keys are the keys for data being passed to
1079
 * addData().
1080
 * if reverse is set to true, then the values of the variable "keys"
1081
 * are used as opposed to the keys(!
1082
 *
1083
 * @param string $method The method. Can be 'rows' or 'columns'
1084
 * @param array $keys The keys
1085
 * @param bool $reverse Whether we want to use the values as the keys
1086
 */
1087
function setKeys($method = 'rows', $keys = array(), $reverse = false)
1088
{
1089
	global $context;
1090
1091
	// Do we want to use the keys of the keys as the keys? :P
1092
	if ($reverse)
1093
		$context['keys'] = array_flip($keys);
1094
	else
1095
		$context['keys'] = $keys;
1096
1097
	// Rows or columns?
1098
	$context['key_method'] = $method == 'rows' ? 'rows' : 'cols';
1099
}
1100
1101
?>