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

PostModeration.php ➔ PostModerationMain()   B

Complexity

Conditions 3
Paths 2

Size

Total Lines 27
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 14
nc 2
nop 0
dl 0
loc 27
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file's job is to handle things related to post moderation.
5
 *
6
 * Simple Machines Forum (SMF)
7
 *
8
 * @package SMF
9
 * @author Simple Machines http://www.simplemachines.org
10
 * @copyright 2017 Simple Machines and individual contributors
11
 * @license http://www.simplemachines.org/about/smf/license.php BSD
12
 *
13
 * @version 2.1 Beta 4
14
 */
15
16
if (!defined('SMF'))
17
	die('No direct access...');
18
19
/**
20
 * This is a handling function for all things post moderation.
21
 */
22
function PostModerationMain()
23
{
24
	global $sourcedir;
25
26
	 // @todo We'll shift these later bud.
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
27
	loadLanguage('ModerationCenter');
28
	loadTemplate('ModerationCenter');
29
30
	// Probably need this...
31
	require_once($sourcedir . '/ModerationCenter.php');
32
33
	// Allowed sub-actions, you know the drill by now!
34
	$subActions = array(
35
		'approve' => 'ApproveMessage',
36
		'attachments' => 'UnapprovedAttachments',
37
		'replies' => 'UnapprovedPosts',
38
		'topics' => 'UnapprovedPosts',
39
	);
40
41
	// Pick something valid...
42
	if (!isset($_REQUEST['sa']) || !isset($subActions[$_REQUEST['sa']]))
43
		$_REQUEST['sa'] = 'replies';
44
45
	call_integration_hook('integrate_post_moderation', array(&$subActions));
46
47
	call_helper($subActions[$_REQUEST['sa']]);
48
}
49
50
/**
51
 * View all unapproved posts.
52
 */
53
function UnapprovedPosts()
54
{
55
	global $txt, $scripturl, $context, $user_info, $smcFunc, $options, $modSettings;
56
57
	$context['current_view'] = isset($_GET['sa']) && $_GET['sa'] == 'topics' ? 'topics' : 'replies';
58
	$context['page_title'] = $txt['mc_unapproved_posts'];
59
60
	// Work out what boards we can work in!
61
	$approve_boards = boardsAllowedTo('approve_posts');
62
63
	// If we filtered by board remove ones outside of this board.
64
	// @todo Put a message saying we're filtered?
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
65
	if (isset($_REQUEST['brd']))
66
	{
67
		$filter_board = array((int) $_REQUEST['brd']);
68
		$approve_boards = $approve_boards == array(0) ? $filter_board : array_intersect($approve_boards, $filter_board);
69
	}
70
71 View Code Duplication
	if ($approve_boards == array(0))
72
		$approve_query = '';
73
	elseif (!empty($approve_boards))
74
		$approve_query = ' AND m.id_board IN (' . implode(',', $approve_boards) . ')';
75
	// Nada, zip, etc...
76
	else
77
		$approve_query = ' AND 1=0';
78
79
	// We also need to know where we can delete topics and/or replies to.
80
	if ($context['current_view'] == 'topics')
81
	{
82
		$delete_own_boards = boardsAllowedTo('remove_own');
83
		$delete_any_boards = boardsAllowedTo('remove_any');
84
		$delete_own_replies = array();
85
	}
86
	else
87
	{
88
		$delete_own_boards = boardsAllowedTo('delete_own');
89
		$delete_any_boards = boardsAllowedTo('delete_any');
90
		$delete_own_replies = boardsAllowedTo('delete_own_replies');
91
	}
92
93
	$toAction = array();
94
	// Check if we have something to do?
95 View Code Duplication
	if (isset($_GET['approve']))
96
		$toAction[] = (int) $_GET['approve'];
97
	// Just a deletion?
98
	elseif (isset($_GET['delete']))
99
		$toAction[] = (int) $_GET['delete'];
100
	// Lots of approvals?
101
	elseif (isset($_POST['item']))
102
		foreach ($_POST['item'] as $item)
103
			$toAction[] = (int) $item;
104
105
	// What are we actually doing.
106 View Code Duplication
	if (isset($_GET['approve']) || (isset($_POST['do']) && $_POST['do'] == 'approve'))
107
		$curAction = 'approve';
108
	elseif (isset($_GET['delete']) || (isset($_POST['do']) && $_POST['do'] == 'delete'))
109
		$curAction = 'delete';
110
111
	// Right, so we have something to do?
112
	if (!empty($toAction) && isset($curAction))
113
	{
114
		checkSession('request');
115
116
		// Handy shortcut.
117
		$any_array = $curAction == 'approve' ? $approve_boards : $delete_any_boards;
118
119
		// Now for each message work out whether it's actually a topic, and what board it's on.
120
		$request = $smcFunc['db_query']('', '
121
			SELECT m.id_msg, m.id_member, m.id_board, m.subject, t.id_topic, t.id_first_msg, t.id_member_started
122
			FROM {db_prefix}messages AS m
123
				INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic)
124
			LEFT JOIN {db_prefix}boards AS b ON (t.id_board = b.id_board)
125
			WHERE m.id_msg IN ({array_int:message_list})
126
				AND m.approved = {int:not_approved}
127
				AND {query_see_board}',
128
			array(
129
				'message_list' => $toAction,
130
				'not_approved' => 0,
131
			)
132
		);
133
		$toAction = array();
134
		$details = array();
135
		while ($row = $smcFunc['db_fetch_assoc']($request))
136
		{
137
			// If it's not within what our view is ignore it...
138
			if (($row['id_msg'] == $row['id_first_msg'] && $context['current_view'] != 'topics') || ($row['id_msg'] != $row['id_first_msg'] && $context['current_view'] != 'replies'))
139
				continue;
140
141
			$can_add = false;
142
			// If we're approving this is simple.
143
			if ($curAction == 'approve' && ($any_array == array(0) || in_array($row['id_board'], $any_array)))
144
			{
145
				$can_add = true;
146
			}
147
			// Delete requires more permission checks...
148 View Code Duplication
			elseif ($curAction == 'delete')
149
			{
150
				// Own post is easy!
151
				if ($row['id_member'] == $user_info['id'] && ($delete_own_boards == array(0) || in_array($row['id_board'], $delete_own_boards)))
152
					$can_add = true;
153
				// Is it a reply to their own topic?
154
				elseif ($row['id_member'] == $row['id_member_started'] && $row['id_msg'] != $row['id_first_msg'] && ($delete_own_replies == array(0) || in_array($row['id_board'], $delete_own_replies)))
155
					$can_add = true;
156
				// Someone elses?
157
				elseif ($row['id_member'] != $user_info['id'] && ($delete_any_boards == array(0) || in_array($row['id_board'], $delete_any_boards)))
158
					$can_add = true;
159
			}
160
161
			if ($can_add)
162
				$anItem = $context['current_view'] == 'topics' ? $row['id_topic'] : $row['id_msg'];
163
			$toAction[] = $anItem;
0 ignored issues
show
Bug introduced by
The variable $anItem 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...
164
165
			// All clear. What have we got now, what, what?
166
			$details[$anItem] = array();
167
			$details[$anItem]["subject"] = $row['subject'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal subject does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
168
			$details[$anItem]["topic"] = $row['id_topic'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal topic does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
169
			$details[$anItem]["member"] = ($context['current_view'] == 'topics') ? $row['id_member_started'] : $row['id_member'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal member does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
170
			$details[$anItem]["board"] = $row['id_board'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal board does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
171
		}
172
		$smcFunc['db_free_result']($request);
173
174
		// If we have anything left we can actually do the approving (etc).
175
		if (!empty($toAction))
176
		{
177
			if ($curAction == 'approve')
178
			{
179
				approveMessages($toAction, $details, $context['current_view']);
180
			}
181
			else
182
			{
183
				removeMessages($toAction, $details, $context['current_view']);
184
			}
185
		}
186
	}
187
188
	// How many unapproved posts are there?
189
	$request = $smcFunc['db_query']('', '
190
		SELECT COUNT(*)
191
		FROM {db_prefix}messages AS m
192
			INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic AND t.id_first_msg != m.id_msg)
193
			INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board)
194
		WHERE m.approved = {int:not_approved}
195
			AND {query_see_board}
196
			' . $approve_query,
197
		array(
198
			'not_approved' => 0,
199
		)
200
	);
201
	list ($context['total_unapproved_posts']) = $smcFunc['db_fetch_row']($request);
202
	$smcFunc['db_free_result']($request);
203
204
	// What about topics?  Normally we'd use the table alias t for topics but lets use m so we don't have to redo our approve query.
205
	$request = $smcFunc['db_query']('', '
206
		SELECT COUNT(m.id_topic)
207
		FROM {db_prefix}topics AS m
208
			INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
209
		WHERE m.approved = {int:not_approved}
210
			AND {query_see_board}
211
			' . $approve_query,
212
		array(
213
			'not_approved' => 0,
214
		)
215
	);
216
	list ($context['total_unapproved_topics']) = $smcFunc['db_fetch_row']($request);
217
	$smcFunc['db_free_result']($request);
218
219
	// Limit to how many? (obey the user setting)
220
	$limit = !empty($options['messages_per_page']) ? $options['messages_per_page'] : $modSettings['defaultMaxMessages'];
221
222
	$context['page_index'] = constructPageIndex($scripturl . '?action=moderate;area=postmod;sa=' . $context['current_view'] . (isset($_REQUEST['brd']) ? ';brd=' . (int) $_REQUEST['brd'] : ''), $_GET['start'], $context['current_view'] == 'topics' ? $context['total_unapproved_topics'] : $context['total_unapproved_posts'], $limit);
223
	$context['start'] = $_GET['start'];
224
225
	// We have enough to make some pretty tabs!
226
	$context[$context['moderation_menu_name']]['tab_data'] = array(
227
		'title' => $txt['mc_unapproved_posts'],
228
		'help' => 'postmod',
229
		'description' => $txt['mc_unapproved_posts_desc'],
230
	);
231
232
	// Update the tabs with the correct number of posts.
233
	$context['menu_data_' . $context['moderation_menu_id']]['sections']['posts']['areas']['postmod']['subsections']['posts']['label'] .= ' (' . $context['total_unapproved_posts'] . ')';
234
	$context['menu_data_' . $context['moderation_menu_id']]['sections']['posts']['areas']['postmod']['subsections']['topics']['label'] .= ' (' . $context['total_unapproved_topics'] . ')';
235
236
	// If we are filtering some boards out then make sure to send that along with the links.
237
	if (isset($_REQUEST['brd']))
238
	{
239
		$context['menu_data_' . $context['moderation_menu_id']]['sections']['posts']['areas']['postmod']['subsections']['posts']['add_params'] = ';brd=' . (int) $_REQUEST['brd'];
240
		$context['menu_data_' . $context['moderation_menu_id']]['sections']['posts']['areas']['postmod']['subsections']['topics']['add_params'] = ';brd=' . (int) $_REQUEST['brd'];
241
	}
242
243
	// Get all unapproved posts.
244
	$request = $smcFunc['db_query']('', '
245
		SELECT m.id_msg, m.id_topic, m.id_board, m.subject, m.body, m.id_member,
246
			COALESCE(mem.real_name, m.poster_name) AS poster_name, m.poster_time, m.smileys_enabled,
247
			t.id_member_started, t.id_first_msg, b.name AS board_name, c.id_cat, c.name AS cat_name
248
		FROM {db_prefix}messages AS m
249
			INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic)
250
			INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
251
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
252
			LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)
253
		WHERE m.approved = {int:not_approved}
254
			AND t.id_first_msg ' . ($context['current_view'] == 'topics' ? '=' : '!=') . ' m.id_msg
255
			AND {query_see_board}
256
			' . $approve_query . '
257
		LIMIT {int:start}, {int:limit}',
258
		array(
259
			'not_approved' => 0,
260
			'start' => $context['start'],
261
			'limit' => $limit,
262
		)
263
	);
264
	$context['unapproved_items'] = array();
265
	for ($i = 1; $row = $smcFunc['db_fetch_assoc']($request); $i++)
266
	{
267
		// Can delete is complicated, let's solve it first... is it their own post?
268 View Code Duplication
		if ($row['id_member'] == $user_info['id'] && ($delete_own_boards == array(0) || in_array($row['id_board'], $delete_own_boards)))
269
			$can_delete = true;
270
		// Is it a reply to their own topic?
271
		elseif ($row['id_member'] == $row['id_member_started'] && $row['id_msg'] != $row['id_first_msg'] && ($delete_own_replies == array(0) || in_array($row['id_board'], $delete_own_replies)))
272
			$can_delete = true;
273
		// Someone elses?
274
		elseif ($row['id_member'] != $user_info['id'] && ($delete_any_boards == array(0) || in_array($row['id_board'], $delete_any_boards)))
275
			$can_delete = true;
276
		else
277
			$can_delete = false;
278
279
		$context['unapproved_items'][] = array(
280
			'id' => $row['id_msg'],
281
			'counter' => $context['start'] + $i,
282
			'href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'],
283
			'link' => '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'] . '">' . $row['subject'] . '</a>',
284
			'subject' => $row['subject'],
285
			'body' => parse_bbc($row['body'], $row['smileys_enabled'], $row['id_msg']),
286
			'time' => timeformat($row['poster_time']),
287
			'poster' => array(
288
				'id' => $row['id_member'],
289
				'name' => $row['poster_name'],
290
				'link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['poster_name'] . '</a>' : $row['poster_name'],
291
				'href' => $scripturl . '?action=profile;u=' . $row['id_member'],
292
			),
293
			'topic' => array(
294
				'id' => $row['id_topic'],
295
			),
296
			'board' => array(
297
				'id' => $row['id_board'],
298
				'name' => $row['board_name'],
299
				'link' => '<a href="' . $scripturl . '?board=' . $row['id_board'] . '.0">' . $row['board_name'] . '</a>',
300
			),
301
			'category' => array(
302
				'id' => $row['id_cat'],
303
				'name' => $row['cat_name'],
304
				'link' => '<a href="' . $scripturl . '#c' . $row['id_cat'] . '">' . $row['cat_name'] . '</a>',
305
			),
306
			'can_delete' => $can_delete,
307
		);
308
	}
309
	$smcFunc['db_free_result']($request);
310
311
	$context['sub_template'] = 'unapproved_posts';
312
}
313
314
/**
315
 * View all unapproved attachments.
316
 */
317
function UnapprovedAttachments()
318
{
319
	global $txt, $scripturl, $context, $sourcedir, $smcFunc, $modSettings;
320
321
	$context['page_title'] = $txt['mc_unapproved_attachments'];
322
323
	// Once again, permissions are king!
324
	$approve_boards = boardsAllowedTo('approve_posts');
325
326 View Code Duplication
	if ($approve_boards == array(0))
327
		$approve_query = '';
328
	elseif (!empty($approve_boards))
329
		$approve_query = ' AND m.id_board IN (' . implode(',', $approve_boards) . ')';
330
	else
331
		$approve_query = ' AND 1=0';
332
333
	// Get together the array of things to act on, if any.
334
	$attachments = array();
335 View Code Duplication
	if (isset($_GET['approve']))
336
		$attachments[] = (int) $_GET['approve'];
337
	elseif (isset($_GET['delete']))
338
		$attachments[] = (int) $_GET['delete'];
339
	elseif (isset($_POST['item']))
340
		foreach ($_POST['item'] as $item)
341
			$attachments[] = (int) $item;
342
343
	// Are we approving or deleting?
344 View Code Duplication
	if (isset($_GET['approve']) || (isset($_POST['do']) && $_POST['do'] == 'approve'))
345
		$curAction = 'approve';
346
	elseif (isset($_GET['delete']) || (isset($_POST['do']) && $_POST['do'] == 'delete'))
347
		$curAction = 'delete';
348
349
	// Something to do, let's do it!
350
	if (!empty($attachments) && isset($curAction))
351
	{
352
		checkSession('request');
353
354
		// This will be handy.
355
		require_once($sourcedir . '/ManageAttachments.php');
356
357
		// Confirm the attachments are eligible for changing!
358
		$request = $smcFunc['db_query']('', '
359
			SELECT a.id_attach
360
			FROM {db_prefix}attachments AS a
361
				INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg)
362
				LEFT JOIN {db_prefix}boards AS b ON (m.id_board = b.id_board)
363
			WHERE a.id_attach IN ({array_int:attachments})
364
				AND a.approved = {int:not_approved}
365
				AND a.attachment_type = {int:attachment_type}
366
				AND {query_see_board}
367
				' . $approve_query,
368
			array(
369
				'attachments' => $attachments,
370
				'not_approved' => 0,
371
				'attachment_type' => 0,
372
			)
373
		);
374
		$attachments = array();
375
		while ($row = $smcFunc['db_fetch_assoc']($request))
376
			$attachments[] = $row['id_attach'];
377
		$smcFunc['db_free_result']($request);
378
379
		// Assuming it wasn't all like, proper illegal, we can do the approving.
380
		if (!empty($attachments))
381
		{
382
			if ($curAction == 'approve')
383
				ApproveAttachments($attachments);
384
			else
385
				removeAttachments(array('id_attach' => $attachments, 'do_logging' => true));
386
		}
387
	}
388
389
	require_once($sourcedir . '/Subs-List.php');
390
391
	$listOptions = array(
392
		'id' => 'mc_unapproved_attach',
393
		'width' => '100%',
394
		'items_per_page' => $modSettings['defaultMaxListItems'],
395
		'no_items_label' => $txt['mc_unapproved_attachments_none_found'],
396
		'base_href' => $scripturl . '?action=moderate;area=attachmod;sa=attachments',
397
		'default_sort_col' => 'attach_name',
398
		'get_items' => array(
399
			'function' => 'list_getUnapprovedAttachments',
400
			'params' => array(
401
				$approve_query,
402
			),
403
		),
404
		'get_count' => array(
405
			'function' => 'list_getNumUnapprovedAttachments',
406
			'params' => array(
407
				$approve_query,
408
			),
409
		),
410
		'columns' => array(
411
			'attach_name' => array(
412
				'header' => array(
413
					'value' => $txt['mc_unapproved_attach_name'],
414
				),
415
				'data' => array(
416
					'db' => 'filename',
417
				),
418
				'sort' => array(
419
					'default' => 'a.filename',
420
					'reverse' => 'a.filename DESC',
421
				),
422
			),
423
			'attach_size' => array(
424
				'header' => array(
425
					'value' => $txt['mc_unapproved_attach_size'],
426
				),
427
				'data' => array(
428
					'db' => 'size',
429
				),
430
				'sort' => array(
431
					'default' => 'a.size',
432
					'reverse' => 'a.size DESC',
433
				),
434
			),
435
			'attach_poster' => array(
436
				'header' => array(
437
					'value' => $txt['mc_unapproved_attach_poster'],
438
				),
439
				'data' => array(
440
					'function' => function($data)
441
					{
442
						return $data['poster']['link'];
443
					},
444
				),
445
				'sort' => array(
446
					'default' => 'm.id_member',
447
					'reverse' => 'm.id_member DESC',
448
				),
449
			),
450
			'date' => array(
451
				'header' => array(
452
					'value' => $txt['date'],
453
					'style' => 'width: 18%;',
454
				),
455
				'data' => array(
456
					'db' => 'time',
457
					'class' => 'smalltext',
458
					'style' => 'white-space:nowrap;',
459
				),
460
				'sort' => array(
461
					'default' => 'm.poster_time',
462
					'reverse' => 'm.poster_time DESC',
463
				),
464
			),
465
			'message' => array(
466
				'header' => array(
467
					'value' => $txt['post'],
468
				),
469
				'data' => array(
470
					'function' => function($data)
471
					{
472
						return '<a href="' . $data['message']['href'] . '">' . shorten_subject($data['message']['subject'], 20) . '</a>';
473
					},
474
					'class' => 'smalltext',
475
					'style' => 'width:15em;',
476
				),
477
				'sort' => array(
478
					'default' => 'm.subject',
479
					'reverse' => 'm.subject DESC',
480
				),
481
			),
482
			'action' => array(
483
				'header' => array(
484
					'value' => '<input type="checkbox" class="input_check" onclick="invertAll(this, this.form);" checked>',
485
					'style' => 'width: 4%;',
486
					'class' => 'centercol',
487
				),
488
				'data' => array(
489
					'sprintf' => array(
490
						'format' => '<input type="checkbox" name="item[]" value="%1$d" checked class="input_check">',
491
						'params' => array(
492
							'id' => false,
493
						),
494
					),
495
					'class' => 'centercol',
496
				),
497
			),
498
		),
499
		'form' => array(
500
			'href' => $scripturl . '?action=moderate;area=attachmod;sa=attachments',
501
			'include_sort' => true,
502
			'include_start' => true,
503
			'hidden_fields' => array(
504
				$context['session_var'] => $context['session_id'],
505
			),
506
			'token' => 'mod-ap',
507
		),
508
		'additional_rows' => array(
509
			array(
510
				'position' => 'bottom_of_list',
511
				'value' => '
512
					<select name="do" onchange="if (this.value != 0 &amp;&amp; confirm(\'' . $txt['mc_unapproved_sure'] . '\')) submit();">
513
						<option value="0">' . $txt['with_selected'] . ':</option>
514
						<option value="0" disabled>-------------------</option>
515
						<option value="approve">&nbsp;--&nbsp;' . $txt['approve'] . '</option>
516
						<option value="delete">&nbsp;--&nbsp;' . $txt['delete'] . '</option>
517
					</select>
518
					<noscript><input type="submit" name="ml_go" value="' . $txt['go'] . '" class="button_submit"></noscript>',
519
				'class' => 'floatright',
520
			),
521
		),
522
	);
523
524
	// Create the request list.
525
	createToken('mod-ap');
526
	createList($listOptions);
527
528
	$context['sub_template'] = 'show_list';
529
	$context['default_list'] = 'mc_unapproved_attach';
530
531
	$context[$context['moderation_menu_name']]['tab_data'] = array(
532
		'title' => $txt['mc_unapproved_attachments'],
533
		'help' => '',
534
		'description' => $txt['mc_unapproved_attachments_desc']
535
	);
536
}
537
538
/**
539
 * Callback function for UnapprovedAttachments
540
 * retrieve all the attachments waiting for approval the approver can approve
541
 *
542
 * @param int $start The item to start with (for pagination purposes)
543
 * @param int $items_per_page How many items to show on each page
544
 * @param string $sort A string indicating how to sort the results
545
 * @param string $approve_query Additional restrictions based on the boards the approver can see
546
 * @return array An array of information about the unapproved attachments
547
 */
548
function list_getUnapprovedAttachments($start, $items_per_page, $sort, $approve_query)
549
{
550
	global $smcFunc, $scripturl;
551
552
	// Get all unapproved attachments.
553
	$request = $smcFunc['db_query']('', '
554
		SELECT a.id_attach, a.filename, a.size, m.id_msg, m.id_topic, m.id_board, m.subject, m.body, m.id_member,
555
			COALESCE(mem.real_name, m.poster_name) AS poster_name, m.poster_time,
556
			t.id_member_started, t.id_first_msg, b.name AS board_name, c.id_cat, c.name AS cat_name
557
		FROM {db_prefix}attachments AS a
558
			INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg)
559
			INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic)
560
			INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
561
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
562
			LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)
563
		WHERE a.approved = {int:not_approved}
564
			AND a.attachment_type = {int:attachment_type}
565
			AND {query_see_board}
566
			{raw:approve_query}
567
		ORDER BY {raw:sort}
568
		LIMIT {int:start}, {int:items_per_page}',
569
		array(
570
			'not_approved' => 0,
571
			'attachment_type' => 0,
572
			'start' => $start,
573
			'sort' => $sort,
574
			'items_per_page' => $items_per_page,
575
			'approve_query' => $approve_query,
576
		)
577
	);
578
579
	$unapproved_items = array();
580
	while ($row = $smcFunc['db_fetch_assoc']($request))
581
	{
582
		$unapproved_items[] = array(
583
			'id' => $row['id_attach'],
584
			'filename' => $row['filename'],
585
			'size' => round($row['size'] / 1024, 2),
586
			'time' => timeformat($row['poster_time']),
587
			'poster' => array(
588
				'id' => $row['id_member'],
589
				'name' => $row['poster_name'],
590
				'link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['poster_name'] . '</a>' : $row['poster_name'],
591
				'href' => $scripturl . '?action=profile;u=' . $row['id_member'],
592
			),
593
			'message' => array(
594
				'id' => $row['id_msg'],
595
				'subject' => $row['subject'],
596
				'body' => parse_bbc($row['body']),
597
				'time' => timeformat($row['poster_time']),
598
				'href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'],
599
			),
600
			'topic' => array(
601
				'id' => $row['id_topic'],
602
			),
603
			'board' => array(
604
				'id' => $row['id_board'],
605
				'name' => $row['board_name'],
606
			),
607
			'category' => array(
608
				'id' => $row['id_cat'],
609
				'name' => $row['cat_name'],
610
			),
611
		);
612
	}
613
	$smcFunc['db_free_result']($request);
614
615
	return $unapproved_items;
616
}
617
618
/**
619
 * Callback function for UnapprovedAttachments
620
 * count all the attachments waiting for approval that this approver can approve
621
 *
622
 * @param string $approve_query Additional restrictions based on the boards the approver can see
623
 * @return int The number of unapproved attachments
624
 */
625 View Code Duplication
function list_getNumUnapprovedAttachments($approve_query)
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

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

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

Loading history...
626
{
627
	global $smcFunc;
628
629
	// How many unapproved attachments in total?
630
	$request = $smcFunc['db_query']('', '
631
		SELECT COUNT(*)
632
		FROM {db_prefix}attachments AS a
633
			INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg)
634
			INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
635
		WHERE a.approved = {int:not_approved}
636
			AND a.attachment_type = {int:attachment_type}
637
			AND {query_see_board}
638
			' . $approve_query,
639
		array(
640
			'not_approved' => 0,
641
			'attachment_type' => 0,
642
		)
643
	);
644
	list ($total_unapproved_attachments) = $smcFunc['db_fetch_row']($request);
645
	$smcFunc['db_free_result']($request);
646
647
	return $total_unapproved_attachments;
648
}
649
650
/**
651
 * Approve a post, just the one.
652
 */
653
function ApproveMessage()
654
{
655
	global $user_info, $topic, $board, $sourcedir, $smcFunc;
656
657
	checkSession('get');
658
659
	$_REQUEST['msg'] = (int) $_REQUEST['msg'];
660
661
	require_once($sourcedir . '/Subs-Post.php');
662
663
	isAllowedTo('approve_posts');
664
665
	$request = $smcFunc['db_query']('', '
666
		SELECT t.id_member_started, t.id_first_msg, m.id_member, m.subject, m.approved
667
		FROM {db_prefix}messages AS m
668
			INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic})
669
		WHERE m.id_msg = {int:id_msg}
670
			AND m.id_topic = {int:current_topic}
671
		LIMIT 1',
672
		array(
673
			'current_topic' => $topic,
674
			'id_msg' => $_REQUEST['msg'],
675
		)
676
	);
677
	list ($starter, $first_msg, $poster, $subject, $approved) = $smcFunc['db_fetch_row']($request);
678
	$smcFunc['db_free_result']($request);
679
680
	// If it's the first in a topic then the whole topic gets approved!
681
	if ($first_msg == $_REQUEST['msg'])
682
	{
683
		approveTopics($topic, !$approved);
684
685 View Code Duplication
		if ($starter != $user_info['id'])
686
			logAction(($approved ? 'un' : '') . 'approve_topic', array('topic' => $topic, 'subject' => $subject, 'member' => $starter, 'board' => $board));
687
	}
688
	else
689
	{
690
		approvePosts($_REQUEST['msg'], !$approved);
0 ignored issues
show
Documentation introduced by
$_REQUEST['msg'] is of type integer, but the function expects a array.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
691
692 View Code Duplication
		if ($poster != $user_info['id'])
693
			logAction(($approved ? 'un' : '') . 'approve', array('topic' => $topic, 'subject' => $subject, 'member' => $poster, 'board' => $board));
694
	}
695
696
	redirectexit('topic=' . $topic . '.msg' . $_REQUEST['msg'] . '#msg' . $_REQUEST['msg']);
697
}
698
699
/**
700
 * Approve a batch of posts (or topics in their own right)
701
 *
702
 * @param array $messages The IDs of the messages to approve
703
 * @param array $messageDetails An array of information about each message, for the log
704
 * @param string $current_view What type of unapproved items we're approving - can be 'topics' or 'replies'
705
 */
706
function approveMessages($messages, $messageDetails, $current_view = 'replies')
707
{
708
	global $sourcedir;
709
710
	require_once($sourcedir . '/Subs-Post.php');
711
	if ($current_view == 'topics')
712
	{
713
		approveTopics($messages);
714
		// and tell the world about it
715 View Code Duplication
		foreach ($messages as $topic)
716
		{
717
			logAction('approve_topic', array('topic' => $topic, 'subject' => $messageDetails[$topic]['subject'], 'member' => $messageDetails[$topic]['member'], 'board' => $messageDetails[$topic]['board']));
718
		}
719
	}
720
	else
721
	{
722
		approvePosts($messages);
723
		// and tell the world about it again
724 View Code Duplication
		foreach ($messages as $post)
725
		{
726
			logAction('approve', array('topic' => $messageDetails[$post]['topic'], 'subject' => $messageDetails[$post]['subject'], 'member' => $messageDetails[$post]['member'], 'board' => $messageDetails[$post]['board']));
727
		}
728
	}
729
}
730
731
/**
732
 * This is a helper function - basically approve everything!
733
 */
734
function approveAllData()
735
{
736
	global $smcFunc, $sourcedir;
737
738
	// Start with messages and topics.
739
	$request = $smcFunc['db_query']('', '
740
		SELECT id_msg
741
		FROM {db_prefix}messages
742
		WHERE approved = {int:not_approved}',
743
		array(
744
			'not_approved' => 0,
745
		)
746
	);
747
	$msgs = array();
748
	while ($row = $smcFunc['db_fetch_row']($request))
749
		$msgs[] = $row[0];
750
	$smcFunc['db_free_result']($request);
751
752
	if (!empty($msgs))
753
	{
754
		require_once($sourcedir . '/Subs-Post.php');
755
		approvePosts($msgs);
756
	}
757
758
	// Now do attachments
759
	$request = $smcFunc['db_query']('', '
760
		SELECT id_attach
761
		FROM {db_prefix}attachments
762
		WHERE approved = {int:not_approved}',
763
		array(
764
			'not_approved' => 0,
765
		)
766
	);
767
	$attaches = array();
768
	while ($row = $smcFunc['db_fetch_row']($request))
769
		$attaches[] = $row[0];
770
	$smcFunc['db_free_result']($request);
771
772
	if (!empty($attaches))
773
	{
774
		require_once($sourcedir . '/ManageAttachments.php');
775
		ApproveAttachments($attaches);
776
	}
777
}
778
779
/**
780
 * Remove a batch of messages (or topics)
781
 *
782
 * @param array $messages The IDs of the messages to remove
783
 * @param array $messageDetails An array of information about the messages for the log
784
 * @param string $current_view What type of item we're removing - can be 'topics' or 'replies'
785
 */
786
function removeMessages($messages, $messageDetails, $current_view = 'replies')
787
{
788
	global $sourcedir, $modSettings;
789
790
	// @todo something's not right, removeMessage() does check permissions,
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
791
	// removeTopics() doesn't
792
	require_once($sourcedir . '/RemoveTopic.php');
793
	if ($current_view == 'topics')
794
	{
795
		removeTopics($messages);
796
		// and tell the world about it
797
		foreach ($messages as $topic)
798
			// Note, only log topic ID in native form if it's not gone forever.
799
			logAction('remove', array(
800
				(empty($modSettings['recycle_enable']) || $modSettings['recycle_board'] != $messageDetails[$topic]['board'] ? 'topic' : 'old_topic_id') => $topic, 'subject' => $messageDetails[$topic]['subject'], 'member' => $messageDetails[$topic]['member'], 'board' => $messageDetails[$topic]['board']));
801
	}
802
	else
803
	{
804
		foreach ($messages as $post)
805
		{
806
			removeMessage($post);
807
			logAction('delete', array(
808
				(empty($modSettings['recycle_enable']) || $modSettings['recycle_board'] != $messageDetails[$post]['board'] ? 'topic' : 'old_topic_id') => $messageDetails[$post]['topic'], 'subject' => $messageDetails[$post]['subject'], 'member' => $messageDetails[$post]['member'], 'board' => $messageDetails[$post]['board']));
809
		}
810
	}
811
}
812
813
?>