Completed
Push — release-2.1 ( 6f6d35...abeae7 )
by Mathias
08:46
created

ManageNews.php ➔ SendMailing()   F

Complexity

Conditions 73
Paths > 20000

Size

Total Lines 357
Code Lines 200

Duplication

Lines 48
Ratio 13.45 %

Importance

Changes 0
Metric Value
cc 73
eloc 200
nc 429496.7295
nop 1
dl 48
loc 357
rs 2
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 manages... the news. :P
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
 * The news dispatcher; doesn't do anything, just delegates.
21
 * This is the entrance point for all News and Newsletter screens.
22
 * Called by ?action=admin;area=news.
23
 * It does the permission checks, and calls the appropriate function
24
 * based on the requested sub-action.
25
 */
26
function ManageNews()
27
{
28
	global $context, $txt;
29
30
	// First, let's do a quick permissions check for the best error message possible.
31
	isAllowedTo(array('edit_news', 'send_mail', 'admin_forum'));
32
33
	loadTemplate('ManageNews');
34
35
	// Format: 'sub-action' => array('function', 'permission')
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
36
	$subActions = array(
37
		'editnews' => array('EditNews', 'edit_news'),
38
		'mailingmembers' => array('SelectMailingMembers', 'send_mail'),
39
		'mailingcompose' => array('ComposeMailing', 'send_mail'),
40
		'mailingsend' => array('SendMailing', 'send_mail'),
41
		'settings' => array('ModifyNewsSettings', 'admin_forum'),
42
	);
43
44
	call_integration_hook('integrate_manage_news', array(&$subActions));
45
46
	// Default to sub action 'main' or 'settings' depending on permissions.
47
	$_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : (allowedTo('edit_news') ? 'editnews' : (allowedTo('send_mail') ? 'mailingmembers' : 'settings'));
48
49
	// Have you got the proper permissions?
50
	isAllowedTo($subActions[$_REQUEST['sa']][1]);
51
52
	// Create the tabs for the template.
53
	$context[$context['admin_menu_name']]['tab_data'] = array(
54
		'title' => $txt['news_title'],
55
		'help' => 'edit_news',
56
		'description' => $txt['admin_news_desc'],
57
		'tabs' => array(
58
			'editnews' => array(
59
			),
60
			'mailingmembers' => array(
61
				'description' => $txt['news_mailing_desc'],
62
			),
63
			'settings' => array(
64
				'description' => $txt['news_settings_desc'],
65
			),
66
		),
67
	);
68
69
	// Force the right area...
70
	if (substr($_REQUEST['sa'], 0, 7) == 'mailing')
71
		$context[$context['admin_menu_name']]['current_subsection'] = 'mailingmembers';
72
73
	call_helper($subActions[$_REQUEST['sa']][0]);
74
}
75
76
/**
77
 * Let the administrator(s) edit the news items for the forum.
78
 * It writes an entry into the moderation log.
79
 * This function uses the edit_news administration area.
80
 * Called by ?action=admin;area=news.
81
 * Requires the edit_news permission.
82
 * Can be accessed with ?action=admin;sa=editnews.
83
 *
84
 * @uses ManageNews template, edit_news sub template.
85
 */
86
function EditNews()
87
{
88
	global $txt, $modSettings, $context, $sourcedir, $scripturl;
89
	global $smcFunc;
90
91
	require_once($sourcedir . '/Subs-Post.php');
92
93
	// The 'remove selected' button was pressed.
94
	if (!empty($_POST['delete_selection']) && !empty($_POST['remove']))
95
	{
96
		checkSession();
97
98
		// Store the news temporarily in this array.
99
		$temp_news = explode("\n", $modSettings['news']);
100
101
		// Remove the items that were selected.
102
		foreach ($temp_news as $i => $news)
103
			if (in_array($i, $_POST['remove']))
104
				unset($temp_news[$i]);
105
106
		// Update the database.
107
		updateSettings(array('news' => implode("\n", $temp_news)));
108
109
		$context['saved_successful'] = true;
110
111
		logAction('news');
112
	}
113
	// The 'Save' button was pressed.
114
	elseif (!empty($_POST['save_items']))
115
	{
116
		checkSession();
117
118
		foreach ($_POST['news'] as $i => $news)
119
		{
120
			if (trim($news) == '')
121
				unset($_POST['news'][$i]);
122
			else
123
			{
124
				$_POST['news'][$i] = $smcFunc['htmlspecialchars']($_POST['news'][$i], ENT_QUOTES);
125
				preparsecode($_POST['news'][$i]);
126
			}
127
		}
128
129
		// Send the new news to the database.
130
		updateSettings(array('news' => implode("\n", $_POST['news'])));
131
132
		$context['saved_successful'] = true;
133
134
		// Log this into the moderation log.
135
		logAction('news');
136
	}
137
138
	// We're going to want this for making our list.
139
	require_once($sourcedir . '/Subs-List.php');
140
141
	$context['page_title'] = $txt['admin_edit_news'];
142
143
	// Use the standard templates for showing this.
144
	$listOptions = array(
145
		'id' => 'news_lists',
146
		'get_items' => array(
147
			'function' => 'list_getNews',
148
		),
149
		'columns' => array(
150
			'news' => array(
151
				'header' => array(
152
					'value' => $txt['admin_edit_news'],
153
				),
154
				'data' => array(
155
					'function' => function($news)
156
					{
157
						if (is_numeric($news['id']))
158
							return '<textarea id="data_' . $news['id'] . '" rows="3" cols="50" name="news[]" class="padding block">' . $news['unparsed'] . '</textarea>
159
							<div class="floatleft" id="preview_' . $news['id'] . '"></div>';
160
						else
161
							return $news['unparsed'];
162
					},
163
					'style' => 'width: 50%;',
164
				),
165
			),
166
			'preview' => array(
167
				'header' => array(
168
					'value' => $txt['preview'],
169
				),
170
				'data' => array(
171
					'function' => function($news)
172
					{
173
						return '<div id="box_preview_' . $news['id'] . '" style="overflow: auto; width: 100%; height: 10ex;">' . $news['parsed'] . '</div>';
174
					},
175
					'style' => 'width: 45%;',
176
				),
177
			),
178
			'check' => array(
179
				'header' => array(
180
					'value' => '<input type="checkbox" onclick="invertAll(this, this.form);">',
181
					'class' => 'centercol',
182
				),
183
				'data' => array(
184
					'function' => function($news)
185
					{
186
						if (is_numeric($news['id']))
187
							return '<input type="checkbox" name="remove[]" value="' . $news['id'] . '">';
188
						else
189
							return '';
190
					},
191
					'class' => 'centercol',
192
				),
193
			),
194
		),
195
		'form' => array(
196
			'href' => $scripturl . '?action=admin;area=news;sa=editnews',
197
			'hidden_fields' => array(
198
				$context['session_var'] => $context['session_id'],
199
			),
200
		),
201
		'additional_rows' => array(
202
			array(
203
				'position' => 'bottom_of_list',
204
				'value' => '
205
				<span id="moreNewsItems_link" class="floatleft" style="display: none;">
206
					<a class="button_link" href="javascript:void(0);" onclick="addNewsItem(); return false;">' . $txt['editnews_clickadd'] . '</a>
207
				</span>
208
				<input type="submit" name="save_items" value="' . $txt['save'] . '" class="button_submit">
209
				<input type="submit" name="delete_selection" value="' . $txt['editnews_remove_selected'] . '" data-confirm="' . $txt['editnews_remove_confirm'] . '" class="button_submit you_sure">',
210
			),
211
		),
212
		'javascript' => '
213
					document.getElementById(\'list_news_lists_last\').style.display = "none";
214
					document.getElementById("moreNewsItems_link").style.display = "";
215
					var last_preview = 0;
216
217
					$(document).ready(function () {
218
						$("div[id ^= \'preview_\']").each(function () {
219
							var preview_id = $(this).attr(\'id\').split(\'_\')[1];
220
							if (last_preview < preview_id)
221
								last_preview = preview_id;
222
							make_preview_btn(preview_id);
223
						});
224
					});
225
226
					function make_preview_btn (preview_id)
227
					{
228
						$("#preview_" + preview_id).addClass("button_link");
229
						$("#preview_" + preview_id).text(\'' . $txt['preview'] . '\').click(function () {
230
							$.ajax({
231
								type: "POST",
232
								url: "' . $scripturl . '?action=xmlhttp;sa=previews;xml",
233
								data: {item: "newspreview", news: $("#data_" + preview_id).val()},
234
								context: document.body,
235
								success: function(request){
236
									if ($(request).find("error").text() == \'\')
237
										$(document).find("#box_preview_" + preview_id).html($(request).text());
238
									else
239
										$(document).find("#box_preview_" + preview_id).text(\'' . $txt['news_error_no_news'] . '\');
240
								},
241
							});
242
						});
243
					}
244
245
					function addNewsItem ()
246
					{
247
						last_preview++;
248
						$("#list_news_lists_last").before(' . javaScriptEscape('
249
						<tr class="windowbg') . ' + (last_preview % 2 == 0 ? \'\' : \'2\') + ' . javaScriptEscape('">
250
							<td style="width: 50%;">
251
									<textarea id="data_') . ' + last_preview + ' . javaScriptEscape('" rows="3" cols="65" name="news[]" style="width: 95%;"></textarea>
252
									<br>
253
									<div class="floatleft" id="preview_') . ' + last_preview + ' . javaScriptEscape('"></div>
254
							</td>
255
							<td style="width: 45%;">
256
								<div id="box_preview_') . ' + last_preview + ' . javaScriptEscape('" style="overflow: auto; width: 100%; height: 10ex;"></div>
257
							</td>
258
							<td></td>
259
						</tr>') . ');
260
						make_preview_btn(last_preview);
261
					}',
262
	);
263
264
	// Create the request list.
265
	createList($listOptions);
266
267
	// And go!
268
	loadTemplate('ManageNews');
269
	$context['sub_template'] = 'news_lists';
270
}
271
272
/**
273
 * Prepares an array of the forum news items for display in the template
274
 *
275
 * @return array An array of information about the news items
276
 */
277
function list_getNews()
278
{
279
	global $modSettings;
280
281
	$admin_current_news = array();
282
	// Ready the current news.
283
	foreach (explode("\n", $modSettings['news']) as $id => $line)
284
		$admin_current_news[$id] = array(
285
			'id' => $id,
286
			'unparsed' => un_preparsecode($line),
287
			'parsed' => preg_replace('~<([/]?)form[^>]*?[>]*>~i', '<em class="smalltext">&lt;$1form&gt;</em>', parse_bbc($line)),
288
		);
289
290
	$admin_current_news['last'] = array(
291
		'id' => 'last',
292
		'unparsed' => '<div id="moreNewsItems"></div>
293
		<noscript><textarea rows="3" cols="65" name="news[]" style="width: 85%;"></textarea></noscript>',
294
		'parsed' => '<div id="moreNewsItems_preview"></div>',
295
	);
296
297
	return $admin_current_news;
298
}
299
300
/**
301
 * This function allows a user to select the membergroups to send their
302
 * mailing to.
303
 * Called by ?action=admin;area=news;sa=mailingmembers.
304
 * Requires the send_mail permission.
305
 * Form is submitted to ?action=admin;area=news;mailingcompose.
306
 *
307
 * @uses the ManageNews template and email_members sub template.
308
 */
309
function SelectMailingMembers()
310
{
311
	global $txt, $context, $modSettings, $smcFunc;
312
313
	// Is there any confirm message?
314
	$context['newsletter_sent'] = isset($_SESSION['newsletter_sent']) ? $_SESSION['newsletter_sent'] : '';
315
316
	$context['page_title'] = $txt['admin_newsletters'];
317
318
	$context['sub_template'] = 'email_members';
319
320
	$context['groups'] = array();
321
	$postGroups = array();
322
	$normalGroups = array();
323
324
	// If we have post groups disabled then we need to give a "ungrouped members" option.
325
	if (empty($modSettings['permission_enable_postgroups']))
326
	{
327
		$context['groups'][0] = array(
328
			'id' => 0,
329
			'name' => $txt['membergroups_members'],
330
			'member_count' => 0,
331
		);
332
		$normalGroups[0] = 0;
333
	}
334
335
	// Get all the extra groups as well as Administrator and Global Moderator.
336
	$request = $smcFunc['db_query']('', '
337
		SELECT mg.id_group, mg.group_name, mg.min_posts
338
		FROM {db_prefix}membergroups AS mg' . (empty($modSettings['permission_enable_postgroups']) ? '
339
		WHERE mg.min_posts = {int:min_posts}' : '') . '
340
		GROUP BY mg.id_group, mg.min_posts, mg.group_name
341
		ORDER BY mg.min_posts, CASE WHEN mg.id_group < {int:newbie_group} THEN mg.id_group ELSE 4 END, mg.group_name',
342
		array(
343
			'min_posts' => -1,
344
			'newbie_group' => 4,
345
		)
346
	);
347
	while ($row = $smcFunc['db_fetch_assoc']($request))
348
	{
349
		$context['groups'][$row['id_group']] = array(
350
			'id' => $row['id_group'],
351
			'name' => $row['group_name'],
352
			'member_count' => 0,
353
		);
354
355 View Code Duplication
		if ($row['min_posts'] == -1)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
356
			$normalGroups[$row['id_group']] = $row['id_group'];
357
		else
358
			$postGroups[$row['id_group']] = $row['id_group'];
359
	}
360
	$smcFunc['db_free_result']($request);
361
362
	// If we have post groups, let's count the number of members...
363
	if (!empty($postGroups))
364
	{
365
		$query = $smcFunc['db_query']('', '
366
			SELECT mem.id_post_group AS id_group, COUNT(*) AS member_count
367
			FROM {db_prefix}members AS mem
368
			WHERE mem.id_post_group IN ({array_int:post_group_list})
369
			GROUP BY mem.id_post_group',
370
			array(
371
				'post_group_list' => $postGroups,
372
			)
373
		);
374
		while ($row = $smcFunc['db_fetch_assoc']($query))
375
			$context['groups'][$row['id_group']]['member_count'] += $row['member_count'];
376
		$smcFunc['db_free_result']($query);
377
	}
378
379 View Code Duplication
	if (!empty($normalGroups))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
380
	{
381
		// Find people who are members of this group...
382
		$query = $smcFunc['db_query']('', '
383
			SELECT id_group, COUNT(*) AS member_count
384
			FROM {db_prefix}members
385
			WHERE id_group IN ({array_int:normal_group_list})
386
			GROUP BY id_group',
387
			array(
388
				'normal_group_list' => $normalGroups,
389
			)
390
		);
391
		while ($row = $smcFunc['db_fetch_assoc']($query))
392
			$context['groups'][$row['id_group']]['member_count'] += $row['member_count'];
393
		$smcFunc['db_free_result']($query);
394
395
		// Also do those who have it as an additional membergroup - this ones more yucky...
396
		$query = $smcFunc['db_query']('', '
397
			SELECT mg.id_group, COUNT(*) AS member_count
398
			FROM {db_prefix}membergroups AS mg
399
				INNER JOIN {db_prefix}members AS mem ON (mem.additional_groups != {string:blank_string}
400
					AND mem.id_group != mg.id_group
401
					AND FIND_IN_SET(mg.id_group, mem.additional_groups) != 0)
402
			WHERE mg.id_group IN ({array_int:normal_group_list})
403
			GROUP BY mg.id_group',
404
			array(
405
				'normal_group_list' => $normalGroups,
406
				'blank_string' => '',
407
			)
408
		);
409
		while ($row = $smcFunc['db_fetch_assoc']($query))
410
			$context['groups'][$row['id_group']]['member_count'] += $row['member_count'];
411
		$smcFunc['db_free_result']($query);
412
	}
413
414
	// Any moderators?
415
	$request = $smcFunc['db_query']('', '
416
		SELECT COUNT(DISTINCT id_member) AS num_distinct_mods
417
		FROM {db_prefix}moderators
418
		LIMIT 1',
419
		array(
420
		)
421
	);
422
	list ($context['groups'][3]['member_count']) = $smcFunc['db_fetch_row']($request);
423
	$smcFunc['db_free_result']($request);
424
425
	$context['can_send_pm'] = allowedTo('pm_send');
426
427
	loadJavaScriptFile('suggest.js', array('defer' => false), 'smf_suggest');
428
}
429
430
/**
431
 * Prepare subject and message of an email for the preview box
432
 * Used in ComposeMailing and RetrievePreview (Xml.php)
433
 */
434
function prepareMailingForPreview()
435
{
436
	global $context, $modSettings, $scripturl, $user_info, $txt;
437
	loadLanguage('Errors');
438
439
	$processing = array('preview_subject' => 'subject', 'preview_message' => 'message');
440
441
	// Use the default time format.
442
	$user_info['time_format'] = $modSettings['time_format'];
443
444
	$variables = array(
445
		'{$board_url}',
446
		'{$current_time}',
447
		'{$latest_member.link}',
448
		'{$latest_member.id}',
449
		'{$latest_member.name}'
450
	);
451
452
	$html = $context['send_html'];
453
454
	// We might need this in a bit
455
	$cleanLatestMember = empty($context['send_html']) || $context['send_pm'] ? un_htmlspecialchars($modSettings['latestRealName']) : $modSettings['latestRealName'];
456
457
	foreach ($processing as $key => $post)
458
	{
459
		$context[$key] = !empty($_REQUEST[$post]) ? $_REQUEST[$post] : '';
460
461
		if (empty($context[$key]) && empty($_REQUEST['xml']))
462
			$context['post_error']['messages'][] = $txt['error_no_' . $post];
463
		elseif (!empty($_REQUEST['xml']))
464
			continue;
465
466
		preparsecode($context[$key]);
467
		if ($html)
468
		{
469
			$enablePostHTML = $modSettings['enablePostHTML'];
470
			$modSettings['enablePostHTML'] = $context['send_html'];
471
			$context[$key] = parse_bbc($context[$key]);
472
			$modSettings['enablePostHTML'] = $enablePostHTML;
473
		}
474
475
		// Replace in all the standard things.
476
		$context[$key] = str_replace($variables,
477
			array(
478
				!empty($context['send_html']) ? '<a href="' . $scripturl . '">' . $scripturl . '</a>' : $scripturl,
479
				timeformat(forum_time(), false),
480
				!empty($context['send_html']) ? '<a href="' . $scripturl . '?action=profile;u=' . $modSettings['latestMember'] . '">' . $cleanLatestMember . '</a>' : ($context['send_pm'] ? '[url=' . $scripturl . '?action=profile;u=' . $modSettings['latestMember'] . ']' . $cleanLatestMember . '[/url]' : $cleanLatestMember),
481
				$modSettings['latestMember'],
482
				$cleanLatestMember
483
			), $context[$key]);
484
	}
485
}
486
487
/**
488
 * Shows a form to edit a forum mailing and its recipients.
489
 * Called by ?action=admin;area=news;sa=mailingcompose.
490
 * Requires the send_mail permission.
491
 * Form is submitted to ?action=admin;area=news;sa=mailingsend.
492
 *
493
 * @uses ManageNews template, email_members_compose sub-template.
494
 */
495
function ComposeMailing()
496
{
497
	global $txt, $sourcedir, $context, $smcFunc;
498
499
	// Setup the template!
500
	$context['page_title'] = $txt['admin_newsletters'];
501
	$context['sub_template'] = 'email_members_compose';
502
503
	$context['subject'] = !empty($_POST['subject']) ? $_POST['subject'] : $smcFunc['htmlspecialchars']($context['forum_name'] . ': ' . $txt['subject']);
504
	$context['message'] = !empty($_POST['message']) ? $_POST['message'] : $smcFunc['htmlspecialchars']($txt['message'] . "\n\n" . $txt['regards_team'] . "\n\n" . '{$board_url}');
505
506
	// Needed for the WYSIWYG editor.
507
	require_once($sourcedir . '/Subs-Editor.php');
508
509
	// Now create the editor.
510
	$editorOptions = array(
511
		'id' => 'message',
512
		'value' => $context['message'],
513
		'height' => '175px',
514
		'width' => '100%',
515
		'labels' => array(
516
			'post_button' => $txt['sendtopic_send'],
517
		),
518
		'preview_type' => 2,
519
		'required' => true,
520
	);
521
	create_control_richedit($editorOptions);
522
	// Store the ID for old compatibility.
523
	$context['post_box_name'] = $editorOptions['id'];
524
525
	if (isset($context['preview']))
526
	{
527
		require_once($sourcedir . '/Subs-Post.php');
528
		$context['recipients']['members'] = !empty($_POST['members']) ? explode(',', $_POST['members']) : array();
529
		$context['recipients']['exclude_members'] = !empty($_POST['exclude_members']) ? explode(',', $_POST['exclude_members']) : array();
530
		$context['recipients']['groups'] = !empty($_POST['groups']) ? explode(',', $_POST['groups']) : array();
531
		$context['recipients']['exclude_groups'] = !empty($_POST['exclude_groups']) ? explode(',', $_POST['exclude_groups']) : array();
532
		$context['recipients']['emails'] = !empty($_POST['emails']) ? explode(';', $_POST['emails']) : array();
533
		$context['email_force'] = !empty($_POST['email_force']) ? 1 : 0;
534
		$context['total_emails'] = !empty($_POST['total_emails']) ? (int) $_POST['total_emails'] : 0;
535
		$context['send_pm'] = !empty($_POST['send_pm']) ? 1 : 0;
536
		$context['send_html'] = !empty($_POST['send_html']) ? '1' : '0';
537
538
		return prepareMailingForPreview();
539
	}
540
541
	// Start by finding any members!
542
	$toClean = array();
543
	if (!empty($_POST['members']))
544
		$toClean[] = 'members';
545
	if (!empty($_POST['exclude_members']))
546
		$toClean[] = 'exclude_members';
547
	if (!empty($toClean))
548
	{
549
		require_once($sourcedir . '/Subs-Auth.php');
550
		foreach ($toClean as $type)
551
		{
552
			// Remove the quotes.
553
			$_POST[$type] = strtr($_POST[$type], array('\\"' => '"'));
0 ignored issues
show
Bug introduced by
It seems like $_POST[$type] can also be of type array; however, strtr() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
554
555
			preg_match_all('~"([^"]+)"~', $_POST[$type], $matches);
556
			$_POST[$type] = array_unique(array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $_POST[$type]))));
557
558 View Code Duplication
			foreach ($_POST[$type] as $index => $member)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
Bug introduced by
The expression $_POST[$type] of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
559
				if (strlen(trim($member)) > 0)
560
					$_POST[$type][$index] = $smcFunc['htmlspecialchars']($smcFunc['strtolower'](trim($member)));
561
				else
562
					unset($_POST[$type][$index]);
563
564
			// Find the members
565
			$_POST[$type] = implode(',', array_keys(findMembers($_POST[$type])));
0 ignored issues
show
Bug introduced by
It seems like $_POST[$type] can also be of type string; however, findMembers() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
566
		}
567
	}
568
569 View Code Duplication
	if (isset($_POST['member_list']) && is_array($_POST['member_list']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
570
	{
571
		$members = array();
572
		foreach ($_POST['member_list'] as $member_id)
573
			$members[] = (int) $member_id;
574
		$_POST['members'] = implode(',', $members);
575
	}
576
577 View Code Duplication
	if (isset($_POST['exclude_member_list']) && is_array($_POST['exclude_member_list']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
578
	{
579
		$members = array();
580
		foreach ($_POST['exclude_member_list'] as $member_id)
581
			$members[] = (int) $member_id;
582
		$_POST['exclude_members'] = implode(',', $members);
583
	}
584
585
	// Clean the other vars.
586
	SendMailing(true);
587
588
	// We need a couple strings from the email template file
589
	loadLanguage('EmailTemplates');
590
591
	// Get a list of all full banned users.  Use their Username and email to find them.  Only get the ones that can't login to turn off notification.
592
	$request = $smcFunc['db_query']('', '
593
		SELECT DISTINCT mem.id_member
594
		FROM {db_prefix}ban_groups AS bg
595
			INNER JOIN {db_prefix}ban_items AS bi ON (bg.id_ban_group = bi.id_ban_group)
596
			INNER JOIN {db_prefix}members AS mem ON (bi.id_member = mem.id_member)
597
		WHERE (bg.cannot_access = {int:cannot_access} OR bg.cannot_login = {int:cannot_login})
598
			AND (bg.expire_time IS NULL OR bg.expire_time > {int:current_time})',
599
		array(
600
			'cannot_access' => 1,
601
			'cannot_login' => 1,
602
			'current_time' => time(),
603
		)
604
	);
605
	while ($row = $smcFunc['db_fetch_assoc']($request))
606
		$context['recipients']['exclude_members'][] = $row['id_member'];
607
	$smcFunc['db_free_result']($request);
608
609
	$request = $smcFunc['db_query']('', '
610
		SELECT DISTINCT bi.email_address
611
		FROM {db_prefix}ban_items AS bi
612
			INNER JOIN {db_prefix}ban_groups AS bg ON (bg.id_ban_group = bi.id_ban_group)
613
		WHERE (bg.cannot_access = {int:cannot_access} OR bg.cannot_login = {int:cannot_login})
614
			AND (bg.expire_time IS NULL OR bg.expire_time > {int:current_time})
615
			AND bi.email_address != {string:blank_string}',
616
		array(
617
			'cannot_access' => 1,
618
			'cannot_login' => 1,
619
			'current_time' => time(),
620
			'blank_string' => '',
621
		)
622
	);
623
	$condition_array = array();
624
	$condition_array_params = array();
625
	$count = 0;
626
	while ($row = $smcFunc['db_fetch_assoc']($request))
627
	{
628
		$condition_array[] = '{string:email_' . $count . '}';
629
		$condition_array_params['email_' . $count++] = $row['email_address'];
630
	}
631
	$smcFunc['db_free_result']($request);
632
633
	if (!empty($condition_array))
634
	{
635
		$request = $smcFunc['db_query']('', '
636
			SELECT id_member
637
			FROM {db_prefix}members
638
			WHERE email_address IN(' . implode(', ', $condition_array) . ')',
639
			$condition_array_params
640
		);
641
		while ($row = $smcFunc['db_fetch_assoc']($request))
642
			$context['recipients']['exclude_members'][] = $row['id_member'];
643
		$smcFunc['db_free_result']($request);
644
	}
645
646
	// Did they select moderators - if so add them as specific members...
647
	if ((!empty($context['recipients']['groups']) && in_array(3, $context['recipients']['groups'])) || (!empty($context['recipients']['exclude_groups']) && in_array(3, $context['recipients']['exclude_groups'])))
648
	{
649
		$request = $smcFunc['db_query']('', '
650
			SELECT DISTINCT mem.id_member AS identifier
651
			FROM {db_prefix}members AS mem
652
				INNER JOIN {db_prefix}moderators AS mods ON (mods.id_member = mem.id_member)
653
			WHERE mem.is_activated = {int:is_activated}',
654
			array(
655
				'is_activated' => 1,
656
			)
657
		);
658
		while ($row = $smcFunc['db_fetch_assoc']($request))
659
		{
660
			if (in_array(3, $context['recipients']))
661
				$context['recipients']['exclude_members'][] = $row['identifier'];
662
			else
663
				$context['recipients']['members'][] = $row['identifier'];
664
		}
665
		$smcFunc['db_free_result']($request);
666
	}
667
668
	// For progress bar!
669
	$context['total_emails'] = count($context['recipients']['emails']);
670
	$request = $smcFunc['db_query']('', '
671
		SELECT COUNT(*)
672
		FROM {db_prefix}members',
673
		array(
674
		)
675
	);
676
	list ($context['total_members']) = $smcFunc['db_fetch_row']($request);
677
	$smcFunc['db_free_result']($request);
678
679
	// Clean up the arrays.
680
	$context['recipients']['members'] = array_unique($context['recipients']['members']);
681
	$context['recipients']['exclude_members'] = array_unique($context['recipients']['exclude_members']);
682
}
683
684
/**
685
 * Handles the sending of the forum mailing in batches.
686
 * Called by ?action=admin;area=news;sa=mailingsend
687
 * Requires the send_mail permission.
688
 * Redirects to itself when more batches need to be sent.
689
 * Redirects to ?action=admin;area=news;sa=mailingmembers after everything has been sent.
690
 *
691
 * @param bool $clean_only If set, it will only clean the variables, put them in context, then return.
692
 * @uses the ManageNews template and email_members_send sub template.
693
 */
694
function SendMailing($clean_only = false)
695
{
696
	global $txt, $sourcedir, $context, $smcFunc;
697
	global $scripturl, $modSettings, $user_info;
698
699
	if (isset($_POST['preview']))
700
	{
701
		$context['preview'] = true;
702
		return ComposeMailing();
703
	}
704
705
	// How many to send at once? Quantity depends on whether we are queueing or not.
706
	// @todo Might need an interface? (used in Post.php too with different limits)
707
	$num_at_once = 1000;
708
709
	// If by PM's I suggest we half the above number.
710
	if (!empty($_POST['send_pm']))
711
		$num_at_once /= 2;
712
713
	checkSession();
714
715
	// Where are we actually to?
716
	$context['start'] = isset($_REQUEST['start']) ? (int) $_REQUEST['start'] : 0;
717
	$context['email_force'] = !empty($_POST['email_force']) ? 1 : 0;
718
	$context['send_pm'] = !empty($_POST['send_pm']) ? 1 : 0;
719
	$context['total_emails'] = !empty($_POST['total_emails']) ? (int) $_POST['total_emails'] : 0;
720
	$context['send_html'] = !empty($_POST['send_html']) ? '1' : '0';
721
	$context['parse_html'] = !empty($_POST['parse_html']) ? '1' : '0';
722
723
	//One can't simply nullify things around
724
	if (empty($_REQUEST['total_members']))
725
	{
726
		$request = $smcFunc['db_query']('', '
727
			SELECT COUNT(*)
728
			FROM {db_prefix}members',
729
			array(
730
			)
731
		);
732
		list ($context['total_members']) = $smcFunc['db_fetch_row']($request);
733
		$smcFunc['db_free_result']($request);
734
	}
735
	else
736
	{
737
		$context['total_members'] = (int) $_REQUEST['total_members'];
738
	}
739
740
	// Create our main context.
741
	$context['recipients'] = array(
742
		'groups' => array(),
743
		'exclude_groups' => array(),
744
		'members' => array(),
745
		'exclude_members' => array(),
746
		'emails' => array(),
747
	);
748
749
	// Have we any excluded members?
750 View Code Duplication
	if (!empty($_POST['exclude_members']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
751
	{
752
		$members = explode(',', $_POST['exclude_members']);
753
		foreach ($members as $member)
754
			if ($member >= $context['start'])
755
				$context['recipients']['exclude_members'][] = (int) $member;
756
	}
757
758
	// What about members we *must* do?
759 View Code Duplication
	if (!empty($_POST['members']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
760
	{
761
		$members = explode(',', $_POST['members']);
762
		foreach ($members as $member)
763
			if ($member >= $context['start'])
764
				$context['recipients']['members'][] = (int) $member;
765
	}
766
	// Cleaning groups is simple - although deal with both checkbox and commas.
767 View Code Duplication
	if (isset($_POST['groups']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
768
	{
769
		if (is_array($_POST['groups']))
770
		{
771
			foreach ($_POST['groups'] as $group => $dummy)
772
				$context['recipients']['groups'][] = (int) $group;
773
		}
774
		else
775
		{
776
			$groups = explode(',', $_POST['groups']);
777
			foreach ($groups as $group)
778
				$context['recipients']['groups'][] = (int) $group;
779
		}
780
	}
781
	// Same for excluded groups
782 View Code Duplication
	if (isset($_POST['exclude_groups']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
783
	{
784
		if (is_array($_POST['exclude_groups']))
785
		{
786
			foreach ($_POST['exclude_groups'] as $group => $dummy)
787
				$context['recipients']['exclude_groups'][] = (int) $group;
788
		}
789
		// Ignore an empty string - we don't want to exclude "Regular Members" unless it's specifically selected
790
		elseif ($_POST['exclude_groups'] != '')
791
		{
792
			$groups = explode(',', $_POST['exclude_groups']);
793
			foreach ($groups as $group)
794
				$context['recipients']['exclude_groups'][] = (int) $group;
795
		}
796
	}
797
	// Finally - emails!
798
	if (!empty($_POST['emails']))
799
	{
800
		$addressed = array_unique(explode(';', strtr($_POST['emails'], array("\n" => ';', "\r" => ';', ',' => ';'))));
801
		foreach ($addressed as $curmem)
802
		{
803
			$curmem = trim($curmem);
804
			if ($curmem != '' && filter_var($curmem, FILTER_VALIDATE_EMAIL))
805
				$context['recipients']['emails'][$curmem] = $curmem;
806
		}
807
	}
808
809
	// If we're only cleaning drop out here.
810
	if ($clean_only)
811
		return;
812
813
	require_once($sourcedir . '/Subs-Post.php');
814
815
	// We are relying too much on writing to superglobals...
816
	$_POST['subject'] = !empty($_POST['subject']) ? $_POST['subject'] : '';
817
	$_POST['message'] = !empty($_POST['message']) ? $_POST['message'] : '';
818
819
	// Save the message and its subject in $context
820
	$context['subject'] = $smcFunc['htmlspecialchars']($_POST['subject'], ENT_QUOTES);
821
	$context['message'] = $smcFunc['htmlspecialchars']($_POST['message'], ENT_QUOTES);
822
823
	// Prepare the message for sending it as HTML
824
	if (!$context['send_pm'] && !empty($_POST['send_html']))
825
	{
826
		// Prepare the message for HTML.
827
		if (!empty($_POST['parse_html']))
828
			$_POST['message'] = str_replace(array("\n", '  '), array('<br>' . "\n", '&nbsp; '), $_POST['message']);
829
830
		// This is here to prevent spam filters from tagging this as spam.
831
		if (preg_match('~\<html~i', $_POST['message']) == 0)
832
		{
833
			if (preg_match('~\<body~i', $_POST['message']) == 0)
834
				$_POST['message'] = '<html><head><title>' . $_POST['subject'] . '</title></head>' . "\n" . '<body>' . $_POST['message'] . '</body></html>';
835
			else
836
				$_POST['message'] = '<html>' . $_POST['message'] . '</html>';
837
		}
838
	}
839
840
	if (empty($_POST['message']) || empty($_POST['subject']))
841
	{
842
		$context['preview'] = true;
843
		return ComposeMailing();
844
	}
845
846
	// Use the default time format.
847
	$user_info['time_format'] = $modSettings['time_format'];
848
849
	$variables = array(
850
		'{$board_url}',
851
		'{$current_time}',
852
		'{$latest_member.link}',
853
		'{$latest_member.id}',
854
		'{$latest_member.name}'
855
	);
856
857
	// We might need this in a bit
858
	$cleanLatestMember = empty($_POST['send_html']) || $context['send_pm'] ? un_htmlspecialchars($modSettings['latestRealName']) : $modSettings['latestRealName'];
859
860
	// Replace in all the standard things.
861
	$_POST['message'] = str_replace($variables,
862
		array(
863
			!empty($_POST['send_html']) ? '<a href="' . $scripturl . '">' . $scripturl . '</a>' : $scripturl,
864
			timeformat(forum_time(), false),
865
			!empty($_POST['send_html']) ? '<a href="' . $scripturl . '?action=profile;u=' . $modSettings['latestMember'] . '">' . $cleanLatestMember . '</a>' : ($context['send_pm'] ? '[url=' . $scripturl . '?action=profile;u=' . $modSettings['latestMember'] . ']' . $cleanLatestMember . '[/url]' : $scripturl . '?action=profile;u=' . $modSettings['latestMember']),
866
			$modSettings['latestMember'],
867
			$cleanLatestMember
868
		), $_POST['message']);
869
	$_POST['subject'] = str_replace($variables,
870
		array(
871
			$scripturl,
872
			timeformat(forum_time(), false),
873
			$modSettings['latestRealName'],
874
			$modSettings['latestMember'],
875
			$modSettings['latestRealName']
876
		), $_POST['subject']);
877
878
	$from_member = array(
879
		'{$member.email}',
880
		'{$member.link}',
881
		'{$member.id}',
882
		'{$member.name}'
883
	);
884
885
	// If we still have emails, do them first!
886
	$i = 0;
887
	foreach ($context['recipients']['emails'] as $k => $email)
888
	{
889
		// Done as many as we can?
890
		if ($i >= $num_at_once)
891
			break;
892
893
		// Don't sent it twice!
894
		unset($context['recipients']['emails'][$k]);
895
896
		// Dammit - can't PM emails!
897
		if ($context['send_pm'])
898
			continue;
899
900
		$to_member = array(
901
			$email,
902
			!empty($_POST['send_html']) ? '<a href="mailto:' . $email . '">' . $email . '</a>' : $email,
903
			'??',
904
			$email
905
		);
906
907
		sendmail($email, str_replace($from_member, $to_member, $_POST['subject']), str_replace($from_member, $to_member, $_POST['message']), null, 'news', !empty($_POST['send_html']), 5);
908
909
		// Done another...
910
		$i++;
911
	}
912
913
	if ($i < $num_at_once)
914
	{
915
		// Need to build quite a query!
916
		$sendQuery = '(';
917
		$sendParams = array();
918
		if (!empty($context['recipients']['groups']))
919
		{
920
			// Take the long route...
921
			$queryBuild = array();
922
			foreach ($context['recipients']['groups'] as $group)
923
			{
924
				$sendParams['group_' . $group] = $group;
925
				$queryBuild[] = 'mem.id_group = {int:group_' . $group . '}';
926
				if (!empty($group))
927
				{
928
					$queryBuild[] = 'FIND_IN_SET({int:group_' . $group . '}, mem.additional_groups) != 0';
929
					$queryBuild[] = 'mem.id_post_group = {int:group_' . $group . '}';
930
				}
931
			}
932
			if (!empty($queryBuild))
933
			$sendQuery .= implode(' OR ', $queryBuild);
934
		}
935
		if (!empty($context['recipients']['members']))
936
		{
937
			$sendQuery .= ($sendQuery == '(' ? '' : ' OR ') . 'mem.id_member IN ({array_int:members})';
938
			$sendParams['members'] = $context['recipients']['members'];
939
		}
940
941
		$sendQuery .= ')';
942
943
		// If we've not got a query then we must be done!
944
		if ($sendQuery == '()')
945
		{
946
			// Set a confirmation message.
947
			$_SESSION['newsletter_sent'] = 'queue_done';
948
			redirectexit('action=admin;area=news;sa=mailingmembers');
949
		}
950
951
		// Anything to exclude?
952
		if (!empty($context['recipients']['exclude_groups']) && in_array(0, $context['recipients']['exclude_groups']))
953
			$sendQuery .= ' AND mem.id_group != {int:regular_group}';
954
		if (!empty($context['recipients']['exclude_members']))
955
		{
956
			$sendQuery .= ' AND mem.id_member NOT IN ({array_int:exclude_members})';
957
			$sendParams['exclude_members'] = $context['recipients']['exclude_members'];
958
		}
959
960
		// Get the smelly people - note we respect the id_member range as it gives us a quicker query.
961
		$result = $smcFunc['db_query']('', '
962
			SELECT mem.id_member, mem.email_address, mem.real_name, mem.id_group, mem.additional_groups, mem.id_post_group
963
			FROM {db_prefix}members AS mem
964
			WHERE ' . $sendQuery . '
965
				AND mem.is_activated = {int:is_activated}
966
			ORDER BY mem.id_member ASC
967
			LIMIT {int:start}, {int:atonce}',
968
			array_merge($sendParams, array(
969
				'start' => $context['start'],
970
				'atonce' => $num_at_once,
971
				'regular_group' => 0,
972
				'is_activated' => 1,
973
			))
974
		);
975
		$rows = array();
976
		while ($row = $smcFunc['db_fetch_assoc']($result))
977
		{
978
			$rows[$row['id_member']] = $row;
979
		}
980
		$smcFunc['db_free_result']($result);
981
982
		// Load their alert preferences
983
		require_once($sourcedir . '/Subs-Notify.php');
984
		$prefs = getNotifyPrefs(array_keys($rows), 'announcements', true);
985
986
		foreach ($rows as $row)
987
		{
988
			// Force them to have it?
989
			if (empty($context['email_force']) && empty($prefs[$row['id_member']]['announcements']))
990
				continue;
991
992
			// What groups are we looking at here?
993
			if (empty($row['additional_groups']))
994
				$groups = array($row['id_group'], $row['id_post_group']);
995 View Code Duplication
			else
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
996
				$groups = array_merge(
997
					array($row['id_group'], $row['id_post_group']),
998
					explode(',', $row['additional_groups'])
999
				);
1000
1001
			// Excluded groups?
1002
			if (array_intersect($groups, $context['recipients']['exclude_groups']))
1003
				continue;
1004
1005
			// We might need this
1006
			$cleanMemberName = empty($_POST['send_html']) || $context['send_pm'] ? un_htmlspecialchars($row['real_name']) : $row['real_name'];
1007
1008
			// Replace the member-dependant variables
1009
			$message = str_replace($from_member,
1010
				array(
1011
					$row['email_address'],
1012
					!empty($_POST['send_html']) ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $cleanMemberName . '</a>' : ($context['send_pm'] ? '[url=' . $scripturl . '?action=profile;u=' . $row['id_member'] . ']' . $cleanMemberName . '[/url]' : $scripturl . '?action=profile;u=' . $row['id_member']),
1013
					$row['id_member'],
1014
					$cleanMemberName,
1015
				), $_POST['message']);
1016
1017
			$subject = str_replace($from_member,
1018
				array(
1019
					$row['email_address'],
1020
					$row['real_name'],
1021
					$row['id_member'],
1022
					$row['real_name'],
1023
				), $_POST['subject']);
1024
1025
			// Send the actual email - or a PM!
1026
			if (!$context['send_pm'])
1027
				sendmail($row['email_address'], $subject, $message, null, 'news', !empty($_POST['send_html']), 5);
1028
			else
1029
				sendpm(array('to' => array($row['id_member']), 'bcc' => array()), $subject, $message);
1030
		}
1031
	}
1032
1033
1034
	$context['start'] = $context['start'] + $num_at_once;
1035
	if (empty($context['recipients']['emails']) && ($context['start'] >= $context['total_members']))
1036
	{
1037
		// Log this into the admin log.
1038
		logAction('newsletter', array(), 'admin');
1039
		$_SESSION['newsletter_sent'] = 'queue_done';
1040
		redirectexit('action=admin;area=news;sa=mailingmembers');
1041
	}
1042
1043
	// Working out progress is a black art of sorts.
1044
	$percentEmails = $context['total_emails'] == 0 ? 0 : ((count($context['recipients']['emails']) / $context['total_emails']) * ($context['total_emails'] / ($context['total_emails'] + $context['total_members'])));
1045
	$percentMembers = ($context['start'] / $context['total_members']) * ($context['total_members'] / ($context['total_emails'] + $context['total_members']));
1046
	$context['percentage_done'] = round(($percentEmails + $percentMembers) * 100, 2);
1047
1048
	$context['page_title'] = $txt['admin_newsletters'];
1049
	$context['sub_template'] = 'email_members_send';
1050
}
1051
1052
/**
1053
 * Set general news and newsletter settings and permissions.
1054
 * Called by ?action=admin;area=news;sa=settings.
1055
 * Requires the forum_admin permission.
1056
 *
1057
 * @uses ManageNews template, news_settings sub-template.
1058
 * @param bool $return_config Whether or not to return the config_vars array (used for admin search)
1059
 * @return void|array Returns nothing or returns the config_vars array if $return_config is true
1060
 */
1061
function ModifyNewsSettings($return_config = false)
1062
{
1063
	global $context, $sourcedir, $txt, $scripturl;
1064
1065
	$config_vars = array(
1066
		array('title', 'settings'),
1067
			// Inline permissions.
1068
			array('permissions', 'edit_news', 'help' => ''),
1069
			array('permissions', 'send_mail'),
1070
		'',
1071
			// Just the remaining settings.
1072
			array('check', 'xmlnews_enable', 'onclick' => 'document.getElementById(\'xmlnews_maxlen\').disabled = !this.checked;'),
1073
			array('int', 'xmlnews_maxlen', 'subtext' => $txt['xmlnews_maxlen_note'], 10),
1074
			array('check', 'xmlnews_attachments', 'subtext' => $txt['xmlnews_attachments_note']),
1075
	);
1076
1077
	call_integration_hook('integrate_modify_news_settings', array(&$config_vars));
1078
1079
	if ($return_config)
1080
		return $config_vars;
1081
1082
	$context['page_title'] = $txt['admin_edit_news'] . ' - ' . $txt['settings'];
1083
	$context['sub_template'] = 'show_settings';
1084
1085
	// Needed for the settings template.
1086
	require_once($sourcedir . '/ManageServer.php');
1087
1088
	// Wrap it all up nice and warm...
1089
	$context['post_url'] = $scripturl . '?action=admin;area=news;save;sa=settings';
1090
1091
	// Add some javascript at the bottom...
1092
	addInlineJavaScript('
1093
	document.getElementById("xmlnews_maxlen").disabled = !document.getElementById("xmlnews_enable").checked;', true);
1094
1095
	// Saving the settings?
1096
	if (isset($_GET['save']))
1097
	{
1098
		checkSession();
1099
1100
		call_integration_hook('integrate_save_news_settings');
1101
1102
		saveDBSettings($config_vars);
1103
		$_SESSION['adm-save'] = true;
1104
		redirectexit('action=admin;area=news;sa=settings');
1105
	}
1106
1107
	// We need this for the in-line permissions
1108
	createToken('admin-mp');
1109
1110
	prepareDBSettingContext($config_vars);
1111
}
1112
1113
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

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

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

Loading history...