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

ManageMail.php ➔ pauseMailQueueClear()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 30
Code Lines 16

Duplication

Lines 30
Ratio 100 %

Importance

Changes 0
Metric Value
cc 3
eloc 16
nc 4
nop 0
dl 30
loc 30
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file is all about mail, how we love it so. In particular it handles the admin side of
5
 * mail configuration, as well as reviewing the mail queue - if enabled.
6
 * @todo refactor as controller-model.
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
7
 *
8
 * Simple Machines Forum (SMF)
9
 *
10
 * @package SMF
11
 * @author Simple Machines http://www.simplemachines.org
12
 * @copyright 2017 Simple Machines and individual contributors
13
 * @license http://www.simplemachines.org/about/smf/license.php BSD
14
 *
15
 * @version 2.1 Beta 4
16
 */
17
18
if (!defined('SMF'))
19
	die('No direct access...');
20
21
/**
22
 * Main dispatcher. This function checks permissions and passes control through to the relevant section.
23
 */
24 View Code Duplication
function ManageMail()
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...
25
{
26
	global $context, $txt, $sourcedir;
27
28
	// You need to be an admin to edit settings!
29
	isAllowedTo('admin_forum');
30
31
	loadLanguage('Help');
32
	loadLanguage('ManageMail');
33
34
	// We'll need the utility functions from here.
35
	require_once($sourcedir . '/ManageServer.php');
36
37
	$context['page_title'] = $txt['mailqueue_title'];
38
	$context['sub_template'] = 'show_settings';
39
40
	$subActions = array(
41
		'browse' => 'BrowseMailQueue',
42
		'clear' => 'ClearMailQueue',
43
		'settings' => 'ModifyMailSettings',
44
	);
45
46
	// By default we want to browse
47
	$_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'browse';
48
	$context['sub_action'] = $_REQUEST['sa'];
49
50
	// Load up all the tabs...
51
	$context[$context['admin_menu_name']]['tab_data'] = array(
52
		'title' => $txt['mailqueue_title'],
53
		'help' => '',
54
		'description' => $txt['mailqueue_desc'],
55
	);
56
57
	call_integration_hook('integrate_manage_mail', array(&$subActions));
58
59
	// Call the right function for this sub-action.
60
	call_helper($subActions[$_REQUEST['sa']]);
61
}
62
63
/**
64
 * Display the mail queue...
65
 */
66
function BrowseMailQueue()
67
{
68
	global $scripturl, $context, $txt, $smcFunc;
69
	global $sourcedir, $modSettings;
70
71
	// First, are we deleting something from the queue?
72
	if (isset($_REQUEST['delete']))
73
	{
74
		checkSession();
75
76
		$smcFunc['db_query']('', '
77
			DELETE FROM {db_prefix}mail_queue
78
			WHERE id_mail IN ({array_int:mail_ids})',
79
			array(
80
				'mail_ids' => $_REQUEST['delete'],
81
			)
82
		);
83
	}
84
85
	// How many items do we have?
86
	$request = $smcFunc['db_query']('', '
87
		SELECT COUNT(*) AS queue_size, MIN(time_sent) AS oldest
88
		FROM {db_prefix}mail_queue',
89
		array(
90
		)
91
	);
92
	list ($mailQueueSize, $mailOldest) = $smcFunc['db_fetch_row']($request);
93
	$smcFunc['db_free_result']($request);
94
95
	$context['oldest_mail'] = empty($mailOldest) ? $txt['mailqueue_oldest_not_available'] : time_since(time() - $mailOldest);
96
	$context['mail_queue_size'] = comma_format($mailQueueSize);
97
98
	$listOptions = array(
99
		'id' => 'mail_queue',
100
		'title' => $txt['mailqueue_browse'],
101
		'items_per_page' => $modSettings['defaultMaxListItems'],
102
		'base_href' => $scripturl . '?action=admin;area=mailqueue',
103
		'default_sort_col' => 'age',
104
		'no_items_label' => $txt['mailqueue_no_items'],
105
		'get_items' => array(
106
			'function' => 'list_getMailQueue',
107
		),
108
		'get_count' => array(
109
			'function' => 'list_getMailQueueSize',
110
		),
111
		'columns' => array(
112
			'subject' => array(
113
				'header' => array(
114
					'value' => $txt['mailqueue_subject'],
115
				),
116
				'data' => array(
117
					'function' => function($rowData) use ($smcFunc)
118
					{
119
						return $smcFunc['strlen']($rowData['subject']) > 50 ? sprintf('%1$s...', $smcFunc['htmlspecialchars']($smcFunc['substr']($rowData['subject'], 0, 47))) : $smcFunc['htmlspecialchars']($rowData['subject']);
120
					},
121
					'class' => 'smalltext',
122
				),
123
				'sort' => array(
124
					'default' => 'subject',
125
					'reverse' => 'subject DESC',
126
				),
127
			),
128
			'recipient' => array(
129
				'header' => array(
130
					'value' => $txt['mailqueue_recipient'],
131
				),
132
				'data' => array(
133
					'sprintf' => array(
134
						'format' => '<a href="mailto:%1$s">%1$s</a>',
135
						'params' => array(
136
							'recipient' => true,
137
						),
138
					),
139
					'class' => 'smalltext',
140
				),
141
				'sort' => array(
142
					'default' => 'recipient',
143
					'reverse' => 'recipient DESC',
144
				),
145
			),
146
			'priority' => array(
147
				'header' => array(
148
					'value' => $txt['mailqueue_priority'],
149
				),
150
				'data' => array(
151
					'function' => function($rowData) use ($txt)
152
					{
153
						// We probably have a text label with your priority.
154
						$txtKey = sprintf('mq_mpriority_%1$s', $rowData['priority']);
155
156
						// But if not, revert to priority 0.
157
						return isset($txt[$txtKey]) ? $txt[$txtKey] : $txt['mq_mpriority_1'];
158
					},
159
					'class' => 'smalltext',
160
				),
161
				'sort' => array(
162
					'default' => 'priority',
163
					'reverse' => 'priority DESC',
164
				),
165
			),
166
			'age' => array(
167
				'header' => array(
168
					'value' => $txt['mailqueue_age'],
169
				),
170
				'data' => array(
171
					'function' => function($rowData)
172
					{
173
						return time_since(time() - $rowData['time_sent']);
174
					},
175
					'class' => 'smalltext',
176
				),
177
				'sort' => array(
178
					'default' => 'time_sent',
179
					'reverse' => 'time_sent DESC',
180
				),
181
			),
182
			'check' => array(
183
				'header' => array(
184
					'value' => '<input type="checkbox" onclick="invertAll(this, this.form);" class="input_check">',
185
				),
186
				'data' => array(
187
					'function' => function($rowData)
188
					{
189
						return '<input type="checkbox" name="delete[]" value="' . $rowData['id_mail'] . '" class="input_check">';
190
					},
191
					'class' => 'smalltext',
192
				),
193
			),
194
		),
195
		'form' => array(
196
			'href' => $scripturl . '?action=admin;area=mailqueue',
197
			'include_start' => true,
198
			'include_sort' => true,
199
		),
200
		'additional_rows' => array(
201
			array(
202
				'position' => 'top_of_list',
203
				'value' => '<input type="submit" name="delete_redirects" value="' . $txt['quickmod_delete_selected'] . '" data-confirm="' . $txt['quickmod_confirm'] . '" class="button_submit you_sure"><a class="button_link you_sure" href="' . $scripturl . '?action=admin;area=mailqueue;sa=clear;' . $context['session_var'] . '=' . $context['session_id'] . '" data-confirm="' . $txt['mailqueue_clear_list_warning'] . '">' . $txt['mailqueue_clear_list'] . '</a> ',
204
			),
205
			array(
206
				'position' => 'bottom_of_list',
207
				'value' => '<input type="submit" name="delete_redirects" value="' . $txt['quickmod_delete_selected'] . '" data-confirm="' . $txt['quickmod_confirm'] . '" class="button_submit you_sure"><a class="button_link you_sure" href="' . $scripturl . '?action=admin;area=mailqueue;sa=clear;' . $context['session_var'] . '=' . $context['session_id'] . '" data-confirm="' . $txt['mailqueue_clear_list_warning'] . '">' . $txt['mailqueue_clear_list'] . '</a> ',
208
			),
209
		),
210
	);
211
212
	require_once($sourcedir . '/Subs-List.php');
213
	createList($listOptions);
214
215
	loadTemplate('ManageMail');
216
	$context['sub_template'] = 'browse';
217
}
218
219
/**
220
 * This function grabs the mail queue items from the database, according to the params given.
221
 * Callback for $listOptions['get_items'] in BrowseMailQueue()
222
 *
223
 * @param int $start The item to start with (for pagination purposes)
224
 * @param int $items_per_page How many items to show on each page
225
 * @param string $sort A string indicating how to sort the results
226
 * @return array An array with info about the mail queue items
227
 */
228
function list_getMailQueue($start, $items_per_page, $sort)
229
{
230
	global $smcFunc, $txt;
231
232
	$request = $smcFunc['db_query']('', '
233
		SELECT
234
			id_mail, time_sent, recipient, priority, private, subject
235
		FROM {db_prefix}mail_queue
236
		ORDER BY {raw:sort}
237
		LIMIT {int:start}, {int:items_per_page}',
238
		array(
239
			'start' => $start,
240
			'sort' => $sort,
241
			'items_per_page' => $items_per_page,
242
		)
243
	);
244
	$mails = array();
245
	while ($row = $smcFunc['db_fetch_assoc']($request))
246
	{
247
		// Private PM/email subjects and similar shouldn't be shown in the mailbox area.
248
		if (!empty($row['private']))
249
			$row['subject'] = $txt['personal_message'];
250
251
		$mails[] = $row;
252
	}
253
	$smcFunc['db_free_result']($request);
254
255
	return $mails;
256
}
257
258
/**
259
 * Returns the total count of items in the mail queue.
260
 * Callback for $listOptions['get_count'] in BrowseMailQueue
261
 * @return int The total number of mail queue items
262
 */
263
function list_getMailQueueSize()
264
{
265
	global $smcFunc;
266
267
	// How many items do we have?
268
	$request = $smcFunc['db_query']('', '
269
		SELECT COUNT(*) AS queue_size
270
		FROM {db_prefix}mail_queue',
271
		array(
272
		)
273
	);
274
	list ($mailQueueSize) = $smcFunc['db_fetch_row']($request);
275
	$smcFunc['db_free_result']($request);
276
277
	return $mailQueueSize;
278
}
279
280
/**
281
 * Allows to view and modify the mail settings.
282
 *
283
 * @param bool $return_config Whether to return the $config_vars array (used for admin search)
284
 * @return void|array Returns nothing or returns the $config_vars array if $return_config is true
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<*,array|string[]|s...g|boolean|double>>|null.

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...
285
 */
286
function ModifyMailSettings($return_config = false)
287
{
288
	global $txt, $scripturl, $context, $modSettings, $txtBirthdayEmails;
289
290
	loadLanguage('EmailTemplates');
291
292
	$body = $txtBirthdayEmails[(empty($modSettings['birthday_email']) ? 'happy_birthday' : $modSettings['birthday_email']) . '_body'];
293
	$subject = $txtBirthdayEmails[(empty($modSettings['birthday_email']) ? 'happy_birthday' : $modSettings['birthday_email']) . '_subject'];
294
295
	$emails = array();
296
	$processedBirthdayEmails = array();
297
	foreach ($txtBirthdayEmails as $key => $value)
298
	{
299
		$index = substr($key, 0, strrpos($key, '_'));
300
		$element = substr($key, strrpos($key, '_') + 1);
301
		$processedBirthdayEmails[$index][$element] = $value;
302
	}
303
	foreach ($processedBirthdayEmails as $index => $dummy)
304
		$emails[$index] = $index;
305
306
	$config_vars = array(
307
			// Mail queue stuff, this rocks ;)
308
			array('int', 'mail_limit', 'subtext' => $txt['zero_to_disable']),
309
			array('int', 'mail_quantity'),
310
		'',
311
			// SMTP stuff.
312
			array('select', 'mail_type', array($txt['mail_type_default'], 'SMTP', 'SMTP - STARTTLS')),
313
			array('text', 'smtp_host'),
314
			array('text', 'smtp_port'),
315
			array('text', 'smtp_username'),
316
			array('password', 'smtp_password'),
317
		'',
318
			array('select', 'birthday_email', $emails, 'value' => array('subject' => $subject, 'body' => $body), 'javascript' => 'onchange="fetch_birthday_preview()"'),
319
			'birthday_subject' => array('var_message', 'birthday_subject', 'var_message' => $processedBirthdayEmails[empty($modSettings['birthday_email']) ? 'happy_birthday' : $modSettings['birthday_email']]['subject'], 'disabled' => true, 'size' => strlen($subject) + 3),
320
			'birthday_body' => array('var_message', 'birthday_body', 'var_message' => nl2br($body), 'disabled' => true, 'size' => ceil(strlen($body) / 25)),
321
	);
322
323
	call_integration_hook('integrate_modify_mail_settings', array(&$config_vars));
324
325
	if ($return_config)
326
		return $config_vars;
327
328
	// Saving?
329
	if (isset($_GET['save']))
330
	{
331
		// Make the SMTP password a little harder to see in a backup etc.
332
		if (!empty($_POST['smtp_password'][1]))
333
		{
334
			$_POST['smtp_password'][0] = base64_encode($_POST['smtp_password'][0]);
335
			$_POST['smtp_password'][1] = base64_encode($_POST['smtp_password'][1]);
336
		}
337
		checkSession();
338
339
		// We don't want to save the subject and body previews.
340
		unset($config_vars['birthday_subject'], $config_vars['birthday_body']);
341
		call_integration_hook('integrate_save_mail_settings');
342
343
		saveDBSettings($config_vars);
344
		redirectexit('action=admin;area=mailqueue;sa=settings');
345
	}
346
347
	$context['post_url'] = $scripturl . '?action=admin;area=mailqueue;save;sa=settings';
348
	$context['settings_title'] = $txt['mailqueue_settings'];
349
350
	prepareDBSettingContext($config_vars);
351
352
	$context['settings_insert_above'] = '
353
	<script>
354
		var bDay = {';
355
356
	$i = 0;
357
	foreach ($processedBirthdayEmails as $index => $email)
358
	{
359
		$is_last = ++$i == count($processedBirthdayEmails);
360
		$context['settings_insert_above'] .= '
361
			' . $index . ': {
362
				subject: ' . JavaScriptEscape($email['subject']) . ',
363
				body: ' . JavaScriptEscape(nl2br($email['body'])) . '
364
			}' . (!$is_last ? ',' : '');
365
	}
366
	$context['settings_insert_above'] .= '
367
		};
368
		function fetch_birthday_preview()
369
		{
370
			var index = document.getElementById(\'birthday_email\').value;
371
			document.getElementById(\'birthday_subject\').innerHTML = bDay[index].subject;
372
			document.getElementById(\'birthday_body\').innerHTML = bDay[index].body;
373
		}
374
	</script>';
375
}
376
377
/**
378
 * This function clears the mail queue of all emails, and at the end redirects to browse.
379
 */
380
function ClearMailQueue()
381
{
382
	global $sourcedir, $smcFunc;
383
384
	checkSession('get');
385
386
	// This is certainly needed!
387
	require_once($sourcedir . '/ScheduledTasks.php');
388
389
	// If we don't yet have the total to clear, find it.
390
	if (!isset($_GET['te']))
391
	{
392
		// How many items do we have?
393
		$request = $smcFunc['db_query']('', '
394
			SELECT COUNT(*) AS queue_size
395
			FROM {db_prefix}mail_queue',
396
			array(
397
			)
398
		);
399
		list ($_GET['te']) = $smcFunc['db_fetch_row']($request);
400
		$smcFunc['db_free_result']($request);
401
	}
402
	else
403
		$_GET['te'] = (int) $_GET['te'];
404
405
	$_GET['sent'] = isset($_GET['sent']) ? (int) $_GET['sent'] : 0;
406
407
	// Send 50 at a time, then go for a break...
408
	while (ReduceMailQueue(50, true, true) === true)
409
	{
410
		// Sent another 50.
411
		$_GET['sent'] += 50;
412
		pauseMailQueueClear();
413
	}
414
415
	return BrowseMailQueue();
416
}
417
418
/**
419
 * Used for pausing the mail queue.
420
 */
421 View Code Duplication
function pauseMailQueueClear()
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...
422
{
423
	global $context, $txt, $time_start;
424
425
	// Try get more time...
426
	@set_time_limit(600);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
427
	if (function_exists('apache_reset_timeout'))
428
		@apache_reset_timeout();
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
429
430
	// Have we already used our maximum time?
431
	if (time() - array_sum(explode(' ', $time_start)) < 5)
432
		return;
433
434
	$context['continue_get_data'] = '?action=admin;area=mailqueue;sa=clear;te=' . $_GET['te'] . ';sent=' . $_GET['sent'] . ';' . $context['session_var'] . '=' . $context['session_id'];
435
	$context['page_title'] = $txt['not_done_title'];
436
	$context['continue_post_data'] = '';
437
	$context['continue_countdown'] = '2';
438
	$context['sub_template'] = 'not_done';
439
440
	// Keep browse selected.
441
	$context['selected'] = 'browse';
442
443
	// What percent through are we?
444
	$context['continue_percent'] = round(($_GET['sent'] / $_GET['te']) * 100, 1);
445
446
	// Never more than 100%!
447
	$context['continue_percent'] = min($context['continue_percent'], 100);
448
449
	obExit();
450
}
451
452
/**
453
 * Little utility function to calculate how long ago a time was.
454
 *
455
 * @param int $time_diff The time difference, in seconds
456
 * @return string A string indicating how many days, hours, minutes or seconds (depending on $time_diff)
457
 */
458
function time_since($time_diff)
459
{
460
	global $txt;
461
462
	if ($time_diff < 0)
463
		$time_diff = 0;
464
465
	// Just do a bit of an if fest...
466
	if ($time_diff > 86400)
467
	{
468
		$days = round($time_diff / 86400, 1);
469
		return sprintf($days == 1 ? $txt['mq_day'] : $txt['mq_days'], $time_diff / 86400);
470
	}
471
	// Hours?
472
	elseif ($time_diff > 3600)
473
	{
474
		$hours = round($time_diff / 3600, 1);
475
		return sprintf($hours == 1 ? $txt['mq_hour'] : $txt['mq_hours'], $hours);
476
	}
477
	// Minutes?
478
	elseif ($time_diff > 60)
479
	{
480
		$minutes = (int) ($time_diff / 60);
481
		return sprintf($minutes == 1 ? $txt['mq_minute'] : $txt['mq_minutes'], $minutes);
482
	}
483
	// Otherwise must be second
484
	else
485
		return sprintf($time_diff == 1 ? $txt['mq_second'] : $txt['mq_seconds'], $time_diff);
486
}
487
488
?>