Completed
Push — release-2.1 ( 4c82a0...64d581 )
by Rick
09:29
created

ManageSmileys.php ➔ AddSmiley()   F

Complexity

Conditions 50
Paths > 20000

Size

Total Lines 245
Code Lines 130

Duplication

Lines 33
Ratio 13.47 %

Importance

Changes 0
Metric Value
cc 50
eloc 130
nc 62216
nop 0
dl 33
loc 245
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 takes care of all administration of smileys.
5
 *
6
 * Simple Machines Forum (SMF)
7
 *
8
 * @package SMF
9
 * @author Simple Machines http://www.simplemachines.org
10
 * @copyright 2016 Simple Machines and individual contributors
11
 * @license http://www.simplemachines.org/about/smf/license.php BSD
12
 *
13
 * @version 2.1 Beta 3
14
 */
15
16
if (!defined('SMF'))
17
	die('No direct access...');
18
19
/**
20
 * This is the dispatcher of smileys administration.
21
 */
22
function ManageSmileys()
23
{
24
	global $context, $txt, $modSettings;
25
26
	isAllowedTo('manage_smileys');
27
28
	loadLanguage('ManageSmileys');
29
	loadTemplate('ManageSmileys');
30
31
	$subActions = array(
32
		'addsmiley' => 'AddSmiley',
33
		'editicon' => 'EditMessageIcons',
34
		'editicons' => 'EditMessageIcons',
35
		'editsets' => 'EditSmileySets',
36
		'editsmileys' => 'EditSmileys',
37
		'import' => 'EditSmileySets',
38
		'modifyset' => 'EditSmileySets',
39
		'modifysmiley' => 'EditSmileys',
40
		'setorder' => 'EditSmileyOrder',
41
		'settings' => 'EditSmileySettings',
42
		'install' => 'InstallSmileySet'
43
	);
44
45
	// If customized smileys is disabled don't show the setting page
46
	if (empty($modSettings['smiley_enable']))
47
	{
48
		unset($subActions['addsmiley']);
49
		unset($subActions['editsmileys']);
50
		unset($subActions['setorder']);
51
		unset($subActions['modifysmiley']);
52
	}
53
	if (empty($modSettings['messageIcons_enable']))
54
	{
55
		unset($subActions['editicon']);
56
		unset($subActions['editicons']);
57
	}
58
59
	// Default the sub-action to 'edit smiley settings'.
60
	$_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'editsets';
61
62
	$context['page_title'] = $txt['smileys_manage'];
63
	$context['sub_action'] = $_REQUEST['sa'];
64
	$context['sub_template'] = $context['sub_action'];
65
66
	// Load up all the tabs...
67
	$context[$context['admin_menu_name']]['tab_data'] = array(
68
		'title' => $txt['smileys_manage'],
69
		'help' => 'smileys',
70
		'description' => $txt['smiley_settings_explain'],
71
		'tabs' => array(
72
			'editsets' => array(
73
				'description' => $txt['smiley_editsets_explain'],
74
			),
75
			'addsmiley' => array(
76
				'description' => $txt['smiley_addsmiley_explain'],
77
			),
78
			'editsmileys' => array(
79
				'description' => $txt['smiley_editsmileys_explain'],
80
			),
81
			'setorder' => array(
82
				'description' => $txt['smiley_setorder_explain'],
83
			),
84
			'editicons' => array(
85
				'description' => $txt['icons_edit_icons_explain'],
86
			),
87
			'settings' => array(
88
				'description' => $txt['smiley_settings_explain'],
89
			),
90
		),
91
	);
92
93
	// Some settings may not be enabled, disallow these from the tabs as appropriate.
94
	if (empty($modSettings['messageIcons_enable']))
95
		$context[$context['admin_menu_name']]['tab_data']['tabs']['editicons']['disabled'] = true;
96
	if (empty($modSettings['smiley_enable']))
97
	{
98
		$context[$context['admin_menu_name']]['tab_data']['tabs']['addsmiley']['disabled'] = true;
99
		$context[$context['admin_menu_name']]['tab_data']['tabs']['editsmileys']['disabled'] = true;
100
		$context[$context['admin_menu_name']]['tab_data']['tabs']['setorder']['disabled'] = true;
101
	}
102
103
	call_integration_hook('integrate_manage_smileys', array(&$subActions));
104
105
	// Call the right function for this sub-action.
106
	call_helper($subActions[$_REQUEST['sa']]);
107
}
108
109
/**
110
 * Handles modifying smileys settings.
111
 *
112
 * @param bool $return_config Whether or not to return the config_vars array (used for admin search)
113
 * @return void|array Returns nothing or returns the $config_vars array if $return_config is true
114
 */
115
function EditSmileySettings($return_config = false)
116
{
117
	global $modSettings, $context, $txt, $boarddir, $sourcedir, $scripturl;
118
119
	// The directories...
120
	$context['smileys_dir'] = empty($modSettings['smileys_dir']) ? $boarddir . '/Smileys' : $modSettings['smileys_dir'];
121
	$context['smileys_dir_found'] = is_dir($context['smileys_dir']);
122
123
	// Get the names of the smiley sets.
124
	$smiley_sets = explode(',', $modSettings['smiley_sets_known']);
125
	$set_names = explode("\n", $modSettings['smiley_sets_names']);
126
127
	$smiley_context = array();
128
	foreach ($smiley_sets as $i => $set)
129
		$smiley_context[$set] = $set_names[$i];
130
131
	// All the settings for the page...
132
	$config_vars = array(
133
		array('title', 'settings'),
134
			// Inline permissions.
135
			array('permissions', 'manage_smileys'),
136
		'',
137
			array('select', 'smiley_sets_default', $smiley_context),
138
			array('check', 'smiley_sets_enable'),
139
			array('check', 'smiley_enable', 'subtext' => $txt['smileys_enable_note']),
140
			array('text', 'smileys_url', 40),
141
			array('warning', !is_dir($context['smileys_dir']) ? 'setting_smileys_dir_wrong' : ''),
142
			array('text', 'smileys_dir', 'invalid' => !$context['smileys_dir_found'], 40),
143
		'',
144
			// Message icons.
145
			array('check', 'messageIcons_enable', 'subtext' => $txt['setting_messageIcons_enable_note']),
146
	);
147
148
	call_integration_hook('integrate_modify_smiley_settings', array(&$config_vars));
149
150
	if ($return_config)
151
		return $config_vars;
152
153
	// Setup the basics of the settings template.
154
	require_once($sourcedir . '/ManageServer.php');
155
	$context['sub_template'] = 'show_settings';
156
157
	// Finish up the form...
158
	$context['post_url'] = $scripturl . '?action=admin;area=smileys;save;sa=settings';
159
160
	// Saving the settings?
161
	if (isset($_GET['save']))
162
	{
163
		checkSession();
164
165
		// Validate the smiley set name.
166
		$_POST['smiley_sets_default'] = empty($smiley_context[$_POST['smiley_sets_default']]) ? 'default' : $_POST['smiley_sets_default'];
167
168
		call_integration_hook('integrate_save_smiley_settings');
169
170
		saveDBSettings($config_vars);
171
		$_SESSION['adm-save'] = true;
172
173
		cache_put_data('parsing_smileys', null, 480);
174
		cache_put_data('posting_smileys', null, 480);
175
176
		redirectexit('action=admin;area=smileys;sa=settings');
177
	}
178
179
	// We need this for the in-line permissions
180
	createToken('admin-mp');
181
182
	prepareDBSettingContext($config_vars);
183
}
184
185
/**
186
 * List, add, remove, modify smileys sets.
187
 */
188
function EditSmileySets()
189
{
190
	global $modSettings, $context, $txt;
191
	global $smcFunc, $scripturl, $sourcedir;
192
193
	// Set the right tab to be selected.
194
	$context[$context['admin_menu_name']]['current_subsection'] = 'editsets';
195
196
	// They must've been submitted a form.
197
	if (isset($_POST['smiley_save']))
198
	{
199
		checkSession();
200
		validateToken('admin-mss', 'request');
201
202
		// Delete selected smiley sets.
203
		if (!empty($_POST['delete']) && !empty($_POST['smiley_set']))
204
		{
205
			$set_paths = explode(',', $modSettings['smiley_sets_known']);
206
			$set_names = explode("\n", $modSettings['smiley_sets_names']);
207
			foreach ($_POST['smiley_set'] as $id => $val)
208
			{
209
				// If this is the set you've marked as default, or the only one remaining, you can't delete it
210
				if ($modSettings['smiley_sets_default'] != $set_paths[$id] && count($set_paths) != 1 && isset($set_paths[$id], $set_names[$id]))
211
					unset($set_paths[$id], $set_names[$id]);
212
			}
213
214
			// Shortcut... array_merge() on a single array resets the numeric keys
215
			$set_paths = array_merge($set_paths);
216
			$set_names = array_merge($set_names);
217
218
			updateSettings(array(
219
				'smiley_sets_known' => implode(',', $set_paths),
220
				'smiley_sets_names' => implode("\n", $set_names),
221
				'smiley_sets_default' => in_array($modSettings['smiley_sets_default'], $set_paths) ? $modSettings['smiley_sets_default'] : $set_paths[0],
222
			));
223
		}
224
		// Add a new smiley set.
225
		elseif (!empty($_POST['add']))
226
			$context['sub_action'] = 'modifyset';
227
		// Create or modify a smiley set.
228
		elseif (isset($_POST['set']))
229
		{
230
			$set_paths = explode(',', $modSettings['smiley_sets_known']);
231
			$set_names = explode("\n", $modSettings['smiley_sets_names']);
232
233
			// Create a new smiley set.
234
			if ($_POST['set'] == -1 && isset($_POST['smiley_sets_path']))
235
			{
236
				if (in_array($_POST['smiley_sets_path'], $set_paths))
237
					fatal_lang_error('smiley_set_already_exists');
238
239
				updateSettings(array(
240
					'smiley_sets_known' => $modSettings['smiley_sets_known'] . ',' . $_POST['smiley_sets_path'],
241
					'smiley_sets_names' => $modSettings['smiley_sets_names'] . "\n" . $_POST['smiley_sets_name'],
242
					'smiley_sets_default' => empty($_POST['smiley_sets_default']) ? $modSettings['smiley_sets_default'] : $_POST['smiley_sets_path'],
243
				));
244
			}
245
			// Modify an existing smiley set.
246
			else
247
			{
248
				// Make sure the smiley set exists.
249
				if (!isset($set_paths[$_POST['set']]) || !isset($set_names[$_POST['set']]))
250
					fatal_lang_error('smiley_set_not_found');
251
252
				// Make sure the path is not yet used by another smileyset.
253
				if (in_array($_POST['smiley_sets_path'], $set_paths) && $_POST['smiley_sets_path'] != $set_paths[$_POST['set']])
254
					fatal_lang_error('smiley_set_path_already_used');
255
256
				$set_paths[$_POST['set']] = $_POST['smiley_sets_path'];
257
				$set_names[$_POST['set']] = $_POST['smiley_sets_name'];
258
				updateSettings(array(
259
					'smiley_sets_known' => implode(',', $set_paths),
260
					'smiley_sets_names' => implode("\n", $set_names),
261
					'smiley_sets_default' => empty($_POST['smiley_sets_default']) ? $modSettings['smiley_sets_default'] : $_POST['smiley_sets_path']
262
				));
263
			}
264
265
			// The user might have checked to also import smileys.
266
			if (!empty($_POST['smiley_sets_import']))
267
				ImportSmileys($_POST['smiley_sets_path']);
268
		}
269
		cache_put_data('parsing_smileys', null, 480);
270
		cache_put_data('posting_smileys', null, 480);
271
	}
272
273
	// Load all available smileysets...
274
	$context['smiley_sets'] = explode(',', $modSettings['smiley_sets_known']);
275
	$set_names = explode("\n", $modSettings['smiley_sets_names']);
276 View Code Duplication
	foreach ($context['smiley_sets'] as $i => $set)
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...
277
		$context['smiley_sets'][$i] = array(
278
			'id' => $i,
279
			'path' => $smcFunc['htmlspecialchars']($set),
280
			'name' => $smcFunc['htmlspecialchars']($set_names[$i]),
281
			'selected' => $set == $modSettings['smiley_sets_default']
282
		);
283
284
	// Importing any smileys from an existing set?
285
	if ($context['sub_action'] == 'import')
286
	{
287
		checkSession('get');
288
		validateToken('admin-mss', 'request');
289
290
		$_GET['set'] = (int) $_GET['set'];
291
292
		// Sanity check - then import.
293
		if (isset($context['smiley_sets'][$_GET['set']]))
294
			ImportSmileys(un_htmlspecialchars($context['smiley_sets'][$_GET['set']]['path']));
295
296
		// Force the process to continue.
297
		$context['sub_action'] = 'modifyset';
298
		$context['sub_template'] = 'modifyset';
299
	}
300
	// If we're modifying or adding a smileyset, some context info needs to be set.
301
	if ($context['sub_action'] == 'modifyset')
302
	{
303
		$_GET['set'] = !isset($_GET['set']) ? -1 : (int) $_GET['set'];
304
		if ($_GET['set'] == -1 || !isset($context['smiley_sets'][$_GET['set']]))
305
			$context['current_set'] = array(
306
				'id' => '-1',
307
				'path' => '',
308
				'name' => '',
309
				'selected' => false,
310
				'is_new' => true,
311
			);
312
		else
313
		{
314
			$context['current_set'] = &$context['smiley_sets'][$_GET['set']];
315
			$context['current_set']['is_new'] = false;
316
317
			// Calculate whether there are any smileys in the directory that can be imported.
318
			if (!empty($modSettings['smiley_enable']) && !empty($modSettings['smileys_dir']) && is_dir($modSettings['smileys_dir'] . '/' . $context['current_set']['path']))
319
			{
320
				$smileys = array();
321
				$dir = dir($modSettings['smileys_dir'] . '/' . $context['current_set']['path']);
322 View Code Duplication
				while ($entry = $dir->read())
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...
323
				{
324
					if (in_array(strrchr($entry, '.'), array('.jpg', '.gif', '.jpeg', '.png')))
325
						$smileys[strtolower($entry)] = $entry;
326
				}
327
				$dir->close();
328
329
				if (empty($smileys))
330
					fatal_lang_error('smiley_set_dir_not_found', false, array($context['current_set']['name']));
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

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...
331
332
				// Exclude the smileys that are already in the database.
333
				$request = $smcFunc['db_query']('', '
334
					SELECT filename
335
					FROM {db_prefix}smileys
336
					WHERE filename IN ({array_string:smiley_list})',
337
					array(
338
						'smiley_list' => $smileys,
339
					)
340
				);
341 View Code Duplication
				while ($row = $smcFunc['db_fetch_assoc']($request))
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...
342
					if (isset($smileys[strtolower($row['filename'])]))
343
						unset($smileys[strtolower($row['filename'])]);
344
				$smcFunc['db_free_result']($request);
345
346
				$context['current_set']['can_import'] = count($smileys);
347
				$context['current_set']['import_url'] = $scripturl . '?action=admin;area=smileys;sa=import;set=' . $context['current_set']['id'] . ';' . $context['session_var'] . '=' . $context['session_id'];
348
			}
349
		}
350
351
		// Retrieve all potential smiley set directories.
352
		$context['smiley_set_dirs'] = array();
353
		if (!empty($modSettings['smileys_dir']) && is_dir($modSettings['smileys_dir']))
354
		{
355
			$dir = dir($modSettings['smileys_dir']);
356
			while ($entry = $dir->read())
357
			{
358
				if (!in_array($entry, array('.', '..')) && is_dir($modSettings['smileys_dir'] . '/' . $entry))
359
					$context['smiley_set_dirs'][] = array(
360
						'id' => $entry,
361
						'path' => $modSettings['smileys_dir'] . '/' . $entry,
362
						'selectable' => $entry == $context['current_set']['path'] || !in_array($entry, explode(',', $modSettings['smiley_sets_known'])),
363
						'current' => $entry == $context['current_set']['path'],
364
					);
365
			}
366
			$dir->close();
367
		}
368
	}
369
370
	// This is our save haven.
371
	createToken('admin-mss', 'request');
372
373
	// In case we need to import smileys, we need to add the token in now.
374
	if (isset($context['current_set']['import_url']))
375
		$context['current_set']['import_url'] .= ';' . $context['admin-mss_token_var'] . '=' . $context['admin-mss_token'];
376
377
	$listOptions = array(
378
		'id' => 'smiley_set_list',
379
		'title' => $txt['smiley_sets'],
380
		'no_items_label' => $txt['smiley_sets_none'],
381
		'base_href' => $scripturl . '?action=admin;area=smileys;sa=editsets',
382
		'default_sort_col' => 'default',
383
		'get_items' => array(
384
			'function' => 'list_getSmileySets',
385
		),
386
		'get_count' => array(
387
			'function' => 'list_getNumSmileySets',
388
		),
389
		'columns' => array(
390
			'default' => array(
391
				'header' => array(
392
					'value' => $txt['smiley_sets_default'],
393
					'class' => 'centercol',
394
				),
395
				'data' => array(
396
					'function' => function ($rowData)
397
					{
398
						return $rowData['selected'] ? '<span class="generic_icons valid"></span>' : '';
399
					},
400
					'class' => 'centercol',
401
				),
402
				'sort' => array(
403
					'default' => 'selected DESC',
404
				),
405
			),
406
			'name' => array(
407
				'header' => array(
408
					'value' => $txt['smiley_sets_name'],
409
				),
410
				'data' => array(
411
					'db_htmlsafe' => 'name',
412
				),
413
				'sort' => array(
414
					'default' => 'name',
415
					'reverse' => 'name DESC',
416
				),
417
			),
418
			'url' => array(
419
				'header' => array(
420
					'value' => $txt['smiley_sets_url'],
421
				),
422
				'data' => array(
423
					'sprintf' => array(
424
						'format' => $modSettings['smileys_url'] . '/<strong>%1$s</strong>/...',
425
						'params' => array(
426
							'path' => true,
427
						),
428
					),
429
				),
430
				'sort' => array(
431
					'default' => 'path',
432
					'reverse' => 'path DESC',
433
				),
434
			),
435
			'modify' => array(
436
				'header' => array(
437
					'value' => $txt['smiley_set_modify'],
438
					'class' => 'centercol',
439
				),
440
				'data' => array(
441
					'sprintf' => array(
442
						'format' => '<a href="' . $scripturl . '?action=admin;area=smileys;sa=modifyset;set=%1$d">' . $txt['smiley_set_modify'] . '</a>',
443
						'params' => array(
444
							'id' => true,
445
						),
446
					),
447
					'class' => 'centercol',
448
				),
449
			),
450
			'check' => array(
451
				'header' => array(
452
					'value' => '<input type="checkbox" onclick="invertAll(this, this.form);" class="input_check">',
453
					'class' => 'centercol',
454
				),
455
				'data' => array(
456
					'function' => function ($rowData)
457
					{
458
						return $rowData['selected'] ? '' : sprintf('<input type="checkbox" name="smiley_set[%1$d]" class="input_check">', $rowData['id']);
459
					},
460
					'class' => 'centercol',
461
				),
462
			),
463
		),
464
		'form' => array(
465
			'href' => $scripturl . '?action=admin;area=smileys;sa=editsets',
466
			'token' => 'admin-mss',
467
		),
468
		'additional_rows' => array(
469
			array(
470
				'position' => 'above_table_headers',
471
				'value' => '<input type="hidden" name="smiley_save"><input type="submit" name="delete" value="' . $txt['smiley_sets_delete'] . '" data-confirm="' . $txt['smiley_sets_confirm'] . '" class="button_submit you_sure"> <a class="button_link" href="' . $scripturl . '?action=admin;area=smileys;sa=modifyset' . '">' . $txt['smiley_sets_add'] . '</a> ',
472
			),
473
			array(
474
				'position' => 'below_table_data',
475
				'value' => '<input type="hidden" name="smiley_save"><input type="submit" name="delete" value="' . $txt['smiley_sets_delete'] . '" data-confirm="' . $txt['smiley_sets_confirm'] . '" class="button_submit you_sure"> <a class="button_link" href="' . $scripturl . '?action=admin;area=smileys;sa=modifyset' . '">' . $txt['smiley_sets_add'] . '</a> ',
476
			),
477
		),
478
	);
479
480
	require_once($sourcedir . '/Subs-List.php');
481
	createList($listOptions);
482
}
483
484
/**
485
 * Callback function for createList().
486
 * @todo to be moved to Subs-Smileys?
487
 *
488
 * @param int $start The item to start with (not used here)
489
 * @param int $items_per_page The number of items to show per page (not used here)
490
 * @param string $sort A string indicating how to sort the results
491
 * @return array An array of info about the smiley sets
492
 */
493
function list_getSmileySets($start, $items_per_page, $sort)
0 ignored issues
show
Unused Code introduced by
The parameter $start is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $items_per_page is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
494
{
495
	global $modSettings;
496
497
	$known_sets = explode(',', $modSettings['smiley_sets_known']);
498
	$set_names = explode("\n", $modSettings['smiley_sets_names']);
499
	$cols = array(
500
		'id' => array(),
501
		'selected' => array(),
502
		'path' => array(),
503
		'name' => array(),
504
	);
505
	foreach ($known_sets as $i => $set)
506
	{
507
		$cols['id'][] = $i;
508
		$cols['selected'][] = $i;
509
		$cols['path'][] = $set;
510
		$cols['name'][] = $set_names[$i];
511
	}
512
	$sort_flag = strpos($sort, 'DESC') === false ? SORT_ASC : SORT_DESC;
513
	if (substr($sort, 0, 4) === 'name')
514
		array_multisort($cols['name'], $sort_flag, SORT_REGULAR, $cols['path'], $cols['selected'], $cols['id']);
515
	elseif (substr($sort, 0, 4) === 'path')
516
		array_multisort($cols['path'], $sort_flag, SORT_REGULAR, $cols['name'], $cols['selected'], $cols['id']);
517
	else
518
		array_multisort($cols['selected'], $sort_flag, SORT_REGULAR, $cols['path'], $cols['name'], $cols['id']);
519
520
	$smiley_sets = array();
521 View Code Duplication
	foreach ($cols['id'] as $i => $id)
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...
522
		$smiley_sets[] = array(
523
			'id' => $id,
524
			'path' => $cols['path'][$i],
525
			'name' => $cols['name'][$i],
526
			'selected' => $cols['path'][$i] == $modSettings['smiley_sets_default']
527
		);
528
529
	return $smiley_sets;
530
}
531
532
/**
533
 * Callback function for createList().
534
 * @todo to be moved to Subs-Smileys?
535
 * @return int The total number of known smiley sets
536
 */
537
function list_getNumSmileySets()
538
{
539
	global $modSettings;
540
541
	return count(explode(',', $modSettings['smiley_sets_known']));
542
}
543
544
/**
545
 * Add a smiley, that's right.
546
 */
547
function AddSmiley()
548
{
549
	global $modSettings, $context, $txt, $boarddir, $smcFunc;
550
551
	// Get a list of all known smiley sets.
552
	$context['smileys_dir'] = empty($modSettings['smileys_dir']) ? $boarddir . '/Smileys' : $modSettings['smileys_dir'];
553
	$context['smileys_dir_found'] = is_dir($context['smileys_dir']);
554
	$context['smiley_sets'] = explode(',', $modSettings['smiley_sets_known']);
555
	$set_names = explode("\n", $modSettings['smiley_sets_names']);
556 View Code Duplication
	foreach ($context['smiley_sets'] as $i => $set)
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...
557
		$context['smiley_sets'][$i] = array(
558
			'id' => $i,
559
			'path' => $smcFunc['htmlspecialchars']($set),
560
			'name' => $smcFunc['htmlspecialchars']($set_names[$i]),
561
			'selected' => $set == $modSettings['smiley_sets_default']
562
		);
563
564
	// Submitting a form?
565
	if (isset($_POST[$context['session_var']], $_POST['smiley_code']))
566
	{
567
		checkSession();
568
569
		// Some useful arrays... types we allow - and ports we don't!
570
		$allowedTypes = array('jpeg', 'jpg', 'gif', 'png', 'bmp');
571
		$disabledFiles = array('con', 'com1', 'com2', 'com3', 'com4', 'prn', 'aux', 'lpt1', '.htaccess', 'index.php');
572
573
		$_POST['smiley_code'] = htmltrim__recursive($_POST['smiley_code']);
574
		$_POST['smiley_location'] = empty($_POST['smiley_location']) || $_POST['smiley_location'] > 2 || $_POST['smiley_location'] < 0 ? 0 : (int) $_POST['smiley_location'];
575
		$_POST['smiley_filename'] = htmltrim__recursive($_POST['smiley_filename']);
576
577
		// Make sure some code was entered.
578
		if (empty($_POST['smiley_code']))
579
			fatal_lang_error('smiley_has_no_code');
580
581
		// Check whether the new code has duplicates. It should be unique.
582
		$request = $smcFunc['db_query']('', '
583
			SELECT id_smiley
584
			FROM {db_prefix}smileys
585
			WHERE code = {raw:mysql_binary_statement} {string:smiley_code}',
586
			array(
587
				'mysql_binary_statement' => $smcFunc['db_title'] == 'MySQL' ? 'BINARY' : '',
588
				'smiley_code' => $_POST['smiley_code'],
589
			)
590
		);
591
		if ($smcFunc['db_num_rows']($request) > 0)
592
			fatal_lang_error('smiley_not_unique');
593
		$smcFunc['db_free_result']($request);
594
595
		// If we are uploading - check all the smiley sets are writable!
596
		if ($_POST['method'] != 'existing')
597
		{
598
			$writeErrors = array();
599
			foreach ($context['smiley_sets'] as $set)
600
			{
601
				if (!is_writable($context['smileys_dir'] . '/' . un_htmlspecialchars($set['path'])))
602
					$writeErrors[] = $set['path'];
603
			}
604
			if (!empty($writeErrors))
605
				fatal_lang_error('smileys_upload_error_notwritable', true, array(implode(', ', $writeErrors)));
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a string.

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...
606
		}
607
608
		// Uploading just one smiley for all of them?
609
		if (isset($_POST['sameall']) && isset($_FILES['uploadSmiley']['name']) && $_FILES['uploadSmiley']['name'] != '')
610
		{
611 View Code Duplication
			if (!is_uploaded_file($_FILES['uploadSmiley']['tmp_name']) || (ini_get('open_basedir') == '' && !file_exists($_FILES['uploadSmiley']['tmp_name'])))
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...
612
				fatal_lang_error('smileys_upload_error');
613
614
			// Sorry, no spaces, dots, or anything else but letters allowed.
615
			$_FILES['uploadSmiley']['name'] = preg_replace(array('/\s/', '/\.[\.]+/', '/[^\w_\.\-]/'), array('_', '.', ''), $_FILES['uploadSmiley']['name']);
616
617
			// We only allow image files - it's THAT simple - no messing around here...
618 View Code Duplication
			if (!in_array(strtolower(substr(strrchr($_FILES['uploadSmiley']['name'], '.'), 1)), $allowedTypes))
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...
619
				fatal_lang_error('smileys_upload_error_types', false, array(implode(', ', $allowedTypes)));
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

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...
620
621
			// We only need the filename...
622
			$destName = basename($_FILES['uploadSmiley']['name']);
623
624
			// Make sure they aren't trying to upload a nasty file - for their own good here!
625
			if (in_array(strtolower($destName), $disabledFiles))
626
				fatal_lang_error('smileys_upload_error_illegal');
627
628
			// Check if the file already exists... and if not move it to EVERY smiley set directory.
629
			$i = 0;
630
			// Keep going until we find a set the file doesn't exist in. (or maybe it exists in all of them?)
631
			while (isset($context['smiley_sets'][$i]) && file_exists($context['smileys_dir'] . '/' . un_htmlspecialchars($context['smiley_sets'][$i]['path']) . '/' . $destName))
632
				$i++;
633
634
			// Okay, we're going to put the smiley right here, since it's not there yet!
635
			if (isset($context['smiley_sets'][$i]['path']))
636
			{
637
				$smileyLocation = $context['smileys_dir'] . '/' . un_htmlspecialchars($context['smiley_sets'][$i]['path']) . '/' . $destName;
638
				move_uploaded_file($_FILES['uploadSmiley']['tmp_name'], $smileyLocation);
639
				smf_chmod($smileyLocation, 0644);
640
641
				// Now, we want to move it from there to all the other sets.
642
				for ($n = count($context['smiley_sets']); $i < $n; $i++)
643
				{
644
					$currentPath = $context['smileys_dir'] . '/' . un_htmlspecialchars($context['smiley_sets'][$i]['path']) . '/' . $destName;
645
646
					// The file is already there!  Don't overwrite it!
647
					if (file_exists($currentPath))
648
						continue;
649
650
					// Okay, so copy the first one we made to here.
651
					copy($smileyLocation, $currentPath);
652
					smf_chmod($currentPath, 0644);
653
				}
654
			}
655
656
			// Finally make sure it's saved correctly!
657
			$_POST['smiley_filename'] = $destName;
658
		}
659
		// What about uploading several files?
660
		elseif ($_POST['method'] != 'existing')
661
		{
662
			$newName = '';
663
			foreach ($_FILES as $name => $data)
664
			{
665
				if ($_FILES[$name]['name'] == '')
666
					fatal_lang_error('smileys_upload_error_blank');
667
668
				if (empty($newName))
669
					$newName = basename($_FILES[$name]['name']);
670
				elseif (basename($_FILES[$name]['name']) != $newName)
671
					fatal_lang_error('smileys_upload_error_name');
672
			}
673
674
			foreach ($context['smiley_sets'] as $i => $set)
675
			{
676
				$set['name'] = un_htmlspecialchars($set['name']);
677
				$set['path'] = un_htmlspecialchars($set['path']);
678
679
				if (!isset($_FILES['individual_' . $set['name']]['name']) || $_FILES['individual_' . $set['name']]['name'] == '')
680
					continue;
681
682
				// Got one...
683
				if (!is_uploaded_file($_FILES['individual_' . $set['name']]['tmp_name']) || (ini_get('open_basedir') == '' && !file_exists($_FILES['individual_' . $set['name']]['tmp_name'])))
684
					fatal_lang_error('smileys_upload_error');
685
686
				// Sorry, no spaces, dots, or anything else but letters allowed.
687
				$_FILES['individual_' . $set['name']]['name'] = preg_replace(array('/\s/', '/\.[\.]+/', '/[^\w_\.\-]/'), array('_', '.', ''), $_FILES['individual_' . $set['name']]['name']);
688
689
				// We only allow image files - it's THAT simple - no messing around here...
690 View Code Duplication
				if (!in_array(strtolower(substr(strrchr($_FILES['individual_' . $set['name']]['name'], '.'), 1)), $allowedTypes))
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...
691
					fatal_lang_error('smileys_upload_error_types', false, array(implode(', ', $allowedTypes)));
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

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...
692
693
				// We only need the filename...
694
				$destName = basename($_FILES['individual_' . $set['name']]['name']);
695
696
				// Make sure they aren't trying to upload a nasty file - for their own good here!
697
				if (in_array(strtolower($destName), $disabledFiles))
698
					fatal_lang_error('smileys_upload_error_illegal');
699
700
				// If the file exists - ignore it.
701
				$smileyLocation = $context['smileys_dir'] . '/' . $set['path'] . '/' . $destName;
702
				if (file_exists($smileyLocation))
703
					continue;
704
705
				// Finally - move the image!
706
				move_uploaded_file($_FILES['individual_' . $set['name']]['tmp_name'], $smileyLocation);
707
				smf_chmod($smileyLocation, 0644);
708
709
				// Should always be saved correctly!
710
				$_POST['smiley_filename'] = $destName;
711
			}
712
		}
713
714
		// Also make sure a filename was given.
715
		if (empty($_POST['smiley_filename']))
716
			fatal_lang_error('smiley_has_no_filename');
717
718
		// Find the position on the right.
719
		$smiley_order = '0';
720
		if ($_POST['smiley_location'] != 1)
721
		{
722
			$request = $smcFunc['db_query']('', '
723
				SELECT MAX(smiley_order) + 1
724
				FROM {db_prefix}smileys
725
				WHERE hidden = {int:smiley_location}
726
					AND smiley_row = {int:first_row}',
727
				array(
728
					'smiley_location' => $_POST['smiley_location'],
729
					'first_row' => 0,
730
				)
731
			);
732
			list ($smiley_order) = $smcFunc['db_fetch_row']($request);
733
			$smcFunc['db_free_result']($request);
734
735
			if (empty($smiley_order))
736
				$smiley_order = '0';
737
		}
738
		$smcFunc['db_insert']('',
739
			'{db_prefix}smileys',
740
			array(
741
				'code' => 'string-30', 'filename' => 'string-48', 'description' => 'string-80', 'hidden' => 'int', 'smiley_order' => 'int',
742
			),
743
			array(
744
				$_POST['smiley_code'], $_POST['smiley_filename'], $_POST['smiley_description'], $_POST['smiley_location'], $smiley_order,
745
			),
746
			array('id_smiley')
747
		);
748
749
		cache_put_data('parsing_smileys', null, 480);
750
		cache_put_data('posting_smileys', null, 480);
751
752
		// No errors? Out of here!
753
		redirectexit('action=admin;area=smileys;sa=editsmileys');
754
	}
755
756
	$context['selected_set'] = $modSettings['smiley_sets_default'];
757
758
	// Get all possible filenames for the smileys.
759
	$context['filenames'] = array();
760 View Code Duplication
	if ($context['smileys_dir_found'])
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...
761
	{
762
		foreach ($context['smiley_sets'] as $smiley_set)
763
		{
764
			if (!file_exists($context['smileys_dir'] . '/' . un_htmlspecialchars($smiley_set['path'])))
765
				continue;
766
767
			$dir = dir($context['smileys_dir'] . '/' . un_htmlspecialchars($smiley_set['path']));
768
			while ($entry = $dir->read())
769
			{
770
				if (!in_array($entry, $context['filenames']) && in_array(strrchr($entry, '.'), array('.jpg', '.gif', '.jpeg', '.png')))
771
					$context['filenames'][strtolower($entry)] = array(
772
						'id' => $smcFunc['htmlspecialchars']($entry),
773
						'selected' => false,
774
					);
775
			}
776
			$dir->close();
777
		}
778
		ksort($context['filenames']);
779
	}
780
781
	// Create a new smiley from scratch.
782
	$context['filenames'] = array_values($context['filenames']);
783
	$context['current_smiley'] = array(
784
		'id' => 0,
785
		'code' => '',
786
		'filename' => $context['filenames'][0]['id'],
787
		'description' => $txt['smileys_default_description'],
788
		'location' => 0,
789
		'is_new' => true,
790
	);
791
}
792
793
/**
794
 * Add, remove, edit smileys.
795
 */
796
function EditSmileys()
797
{
798
	global $modSettings, $context, $txt, $boarddir;
799
	global $smcFunc, $scripturl, $sourcedir;
800
801
	// Force the correct tab to be displayed.
802
	$context[$context['admin_menu_name']]['current_subsection'] = 'editsmileys';
803
804
	// Submitting a form?
805
	if (isset($_POST['smiley_save']) || isset($_POST['smiley_action']))
806
	{
807
		checkSession();
808
809
		// Changing the selected smileys?
810
		if (isset($_POST['smiley_action']) && !empty($_POST['checked_smileys']))
811
		{
812
			foreach ($_POST['checked_smileys'] as $id => $smiley_id)
813
				$_POST['checked_smileys'][$id] = (int) $smiley_id;
814
815
			if ($_POST['smiley_action'] == 'delete')
816
				$smcFunc['db_query']('', '
817
					DELETE FROM {db_prefix}smileys
818
					WHERE id_smiley IN ({array_int:checked_smileys})',
819
					array(
820
						'checked_smileys' => $_POST['checked_smileys'],
821
					)
822
				);
823
			// Changing the status of the smiley?
824
			else
825
			{
826
				// Check it's a valid type.
827
				$displayTypes = array(
828
					'post' => 0,
829
					'hidden' => 1,
830
					'popup' => 2
831
				);
832
				if (isset($displayTypes[$_POST['smiley_action']]))
833
					$smcFunc['db_query']('', '
834
						UPDATE {db_prefix}smileys
835
						SET hidden = {int:display_type}
836
						WHERE id_smiley IN ({array_int:checked_smileys})',
837
						array(
838
							'checked_smileys' => $_POST['checked_smileys'],
839
							'display_type' => $displayTypes[$_POST['smiley_action']],
840
						)
841
					);
842
			}
843
		}
844
		// Create/modify a smiley.
845
		elseif (isset($_POST['smiley']))
846
		{
847
			// Is it a delete?
848
			if (!empty($_POST['deletesmiley']))
849
			{
850
				$smcFunc['db_query']('', '
851
					DELETE FROM {db_prefix}smileys
852
					WHERE id_smiley = {int:current_smiley}',
853
					array(
854
						'current_smiley' => $_POST['smiley'],
855
					)
856
				);
857
			}
858
			// Otherwise an edit.
859
			else
860
			{
861
				$_POST['smiley'] = (int) $_POST['smiley'];
862
				$_POST['smiley_code'] = htmltrim__recursive($_POST['smiley_code']);
863
				$_POST['smiley_filename'] = htmltrim__recursive($_POST['smiley_filename']);
864
				$_POST['smiley_location'] = empty($_POST['smiley_location']) || $_POST['smiley_location'] > 2 || $_POST['smiley_location'] < 0 ? 0 : (int) $_POST['smiley_location'];
865
866
				// Make sure some code was entered.
867
				if (empty($_POST['smiley_code']))
868
					fatal_lang_error('smiley_has_no_code');
869
870
				// Also make sure a filename was given.
871
				if (empty($_POST['smiley_filename']))
872
					fatal_lang_error('smiley_has_no_filename');
873
874
				// Check whether the new code has duplicates. It should be unique.
875
				$request = $smcFunc['db_query']('', '
876
					SELECT id_smiley
877
					FROM {db_prefix}smileys
878
					WHERE code = {raw:mysql_binary_type} {string:smiley_code}' . (empty($_POST['smiley']) ? '' : '
879
						AND id_smiley != {int:current_smiley}'),
880
					array(
881
						'current_smiley' => $_POST['smiley'],
882
						'mysql_binary_type' => $smcFunc['db_title'] == 'MySQL' ? 'BINARY' : '',
883
						'smiley_code' => $_POST['smiley_code'],
884
					)
885
				);
886
				if ($smcFunc['db_num_rows']($request) > 0)
887
					fatal_lang_error('smiley_not_unique');
888
				$smcFunc['db_free_result']($request);
889
890
				$smcFunc['db_query']('', '
891
					UPDATE {db_prefix}smileys
892
					SET
893
						code = {string:smiley_code},
894
						filename = {string:smiley_filename},
895
						description = {string:smiley_description},
896
						hidden = {int:smiley_location}
897
					WHERE id_smiley = {int:current_smiley}',
898
					array(
899
						'smiley_location' => $_POST['smiley_location'],
900
						'current_smiley' => $_POST['smiley'],
901
						'smiley_code' => $_POST['smiley_code'],
902
						'smiley_filename' => $_POST['smiley_filename'],
903
						'smiley_description' => $_POST['smiley_description'],
904
					)
905
				);
906
			}
907
		}
908
909
		cache_put_data('parsing_smileys', null, 480);
910
		cache_put_data('posting_smileys', null, 480);
911
	}
912
913
	// Load all known smiley sets.
914
	$context['smiley_sets'] = explode(',', $modSettings['smiley_sets_known']);
915
	$set_names = explode("\n", $modSettings['smiley_sets_names']);
916 View Code Duplication
	foreach ($context['smiley_sets'] as $i => $set)
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...
917
		$context['smiley_sets'][$i] = array(
918
			'id' => $i,
919
			'path' => $smcFunc['htmlspecialchars']($set),
920
			'name' => $smcFunc['htmlspecialchars']($set_names[$i]),
921
			'selected' => $set == $modSettings['smiley_sets_default']
922
		);
923
924
	// Prepare overview of all (custom) smileys.
925
	if ($context['sub_action'] == 'editsmileys')
926
	{
927
		// Determine the language specific sort order of smiley locations.
928
		$smiley_locations = array(
929
			$txt['smileys_location_form'],
930
			$txt['smileys_location_hidden'],
931
			$txt['smileys_location_popup'],
932
		);
933
		asort($smiley_locations);
934
935
		// Create a list of options for selecting smiley sets.
936
		$smileyset_option_list = '
937
			<select name="set" onchange="changeSet(this.options[this.selectedIndex].value);">';
938
		foreach ($context['smiley_sets'] as $smiley_set)
939
			$smileyset_option_list .= '
940
				<option value="' . $smiley_set['path'] . '"' . ($modSettings['smiley_sets_default'] == $smiley_set['path'] ? ' selected' : '') . '>' . $smiley_set['name'] . '</option>';
941
		$smileyset_option_list .= '
942
			</select>';
943
944
		$listOptions = array(
945
			'id' => 'smiley_list',
946
			'title' => $txt['smileys_edit'],
947
			'items_per_page' => 40,
948
			'base_href' => $scripturl . '?action=admin;area=smileys;sa=editsmileys',
949
			'default_sort_col' => 'filename',
950
			'get_items' => array(
951
				'function' => 'list_getSmileys',
952
			),
953
			'get_count' => array(
954
				'function' => 'list_getNumSmileys',
955
			),
956
			'no_items_label' => $txt['smileys_no_entries'],
957
			'columns' => array(
958
				'picture' => array(
959
					'data' => array(
960
						'sprintf' => array(
961
							'format' => '<a href="' . $scripturl . '?action=admin;area=smileys;sa=modifysmiley;smiley=%1$d"><img src="' . $modSettings['smileys_url'] . '/' . $modSettings['smiley_sets_default'] . '/%2$s" alt="%3$s" style="padding: 2px;" id="smiley%1$d"><input type="hidden" name="smileys[%1$d][filename]" value="%2$s"></a>',
962
							'params' => array(
963
								'id_smiley' => false,
964
								'filename' => true,
965
								'description' => true,
966
							),
967
						),
968
						'class' => 'centercol',
969
					),
970
				),
971
				'code' => array(
972
					'header' => array(
973
						'value' => $txt['smileys_code'],
974
					),
975
					'data' => array(
976
						'db_htmlsafe' => 'code',
977
					),
978
					'sort' => array(
979
						'default' => 'code',
980
						'reverse' => 'code DESC',
981
					),
982
				),
983
				'filename' => array(
984
					'header' => array(
985
						'value' => $txt['smileys_filename'],
986
					),
987
					'data' => array(
988
						'db_htmlsafe' => 'filename',
989
					),
990
					'sort' => array(
991
						'default' => 'filename',
992
						'reverse' => 'filename DESC',
993
					),
994
				),
995
				'location' => array(
996
					'header' => array(
997
						'value' => $txt['smileys_location'],
998
					),
999
					'data' => array(
1000
						'function' => function ($rowData) use ($txt)
1001
						{
1002
							if (empty($rowData['hidden']))
1003
								return $txt['smileys_location_form'];
1004
							elseif ($rowData['hidden'] == 1)
1005
								return $txt['smileys_location_hidden'];
1006
							else
1007
								return $txt['smileys_location_popup'];
1008
						},
1009
					),
1010
					'sort' => array(
1011
						'default' => 'FIND_IN_SET(hidden, \'' . implode(',', array_keys($smiley_locations)) . '\')',
1012
						'reverse' => 'FIND_IN_SET(hidden, \'' . implode(',', array_keys($smiley_locations)) . '\') DESC',
1013
					),
1014
				),
1015
				'tooltip' => array(
1016
					'header' => array(
1017
						'value' => $txt['smileys_description'],
1018
					),
1019
					'data' => array(
1020
						'function' => function ($rowData) use ($modSettings, $context, $txt, $modSettings, $smcFunc)
1021
						{
1022
							if (empty($modSettings['smileys_dir']) || !is_dir($modSettings['smileys_dir']))
1023
								return $smcFunc['htmlspecialchars']($rowData['description']);
1024
1025
							// Check if there are smileys missing in some sets.
1026
							$missing_sets = array();
1027
							foreach ($context['smiley_sets'] as $smiley_set)
1028
								if (!file_exists(sprintf('%1$s/%2$s/%3$s', $modSettings['smileys_dir'], $smiley_set['path'], $rowData['filename'])))
1029
									$missing_sets[] = $smiley_set['path'];
1030
1031
							$description = $smcFunc['htmlspecialchars']($rowData['description']);
1032
1033
							if (!empty($missing_sets))
1034
								$description .= sprintf('<br><span class="smalltext"><strong>%1$s:</strong> %2$s</span>', $txt['smileys_not_found_in_set'], implode(', ', $missing_sets));
1035
1036
							return $description;
1037
						},
1038
					),
1039
					'sort' => array(
1040
						'default' => 'description',
1041
						'reverse' => 'description DESC',
1042
					),
1043
				),
1044
				'modify' => array(
1045
					'header' => array(
1046
						'value' => $txt['smileys_modify'],
1047
						'class' => 'centercol',
1048
					),
1049
					'data' => array(
1050
						'sprintf' => array(
1051
							'format' => '<a href="' . $scripturl . '?action=admin;area=smileys;sa=modifysmiley;smiley=%1$d">' . $txt['smileys_modify'] . '</a>',
1052
							'params' => array(
1053
								'id_smiley' => false,
1054
							),
1055
						),
1056
						'class' => 'centercol',
1057
					),
1058
				),
1059
				'check' => array(
1060
					'header' => array(
1061
						'value' => '<input type="checkbox" onclick="invertAll(this, this.form);" class="input_check">',
1062
						'class' => 'centercol',
1063
					),
1064
					'data' => array(
1065
						'sprintf' => array(
1066
							'format' => '<input type="checkbox" name="checked_smileys[]" value="%1$d" class="input_check">',
1067
							'params' => array(
1068
								'id_smiley' => false,
1069
							),
1070
						),
1071
						'class' => 'centercol',
1072
					),
1073
				),
1074
			),
1075
			'form' => array(
1076
				'href' => $scripturl . '?action=admin;area=smileys;sa=editsmileys',
1077
				'name' => 'smileyForm',
1078
			),
1079
			'additional_rows' => array(
1080
				array(
1081
					'position' => 'above_column_headers',
1082
					'value' => $smileyset_option_list,
1083
					'class' => 'righttext',
1084
				),
1085
				array(
1086
					'position' => 'below_table_data',
1087
					'value' => '
1088
						<select name="smiley_action" onchange="makeChanges(this.value);">
1089
							<option value="-1">' . $txt['smileys_with_selected'] . ':</option>
1090
							<option value="-1" disabled>--------------</option>
1091
							<option value="hidden">' . $txt['smileys_make_hidden'] . '</option>
1092
							<option value="post">' . $txt['smileys_show_on_post'] . '</option>
1093
							<option value="popup">' . $txt['smileys_show_on_popup'] . '</option>
1094
							<option value="delete">' . $txt['smileys_remove'] . '</option>
1095
						</select>
1096
						<noscript>
1097
							<input type="submit" name="perform_action" value="' . $txt['go'] . '" class="button_submit">
1098
						</noscript>',
1099
					'class' => 'righttext',
1100
				),
1101
			),
1102
			'javascript' => '
1103
				function makeChanges(action)
1104
				{
1105
					if (action == \'-1\')
1106
						return false;
1107
					else if (action == \'delete\')
1108
					{
1109
						if (confirm(\'' . $txt['smileys_confirm'] . '\'))
1110
							document.forms.smileyForm.submit();
1111
					}
1112
					else
1113
						document.forms.smileyForm.submit();
1114
					return true;
1115
				}
1116
				function changeSet(newSet)
1117
				{
1118
					var currentImage, i, knownSmileys = [];
1119
1120
					if (knownSmileys.length == 0)
1121
					{
1122
						for (var i = 0, n = document.images.length; i < n; i++)
1123
							if (document.images[i].id.substr(0, 6) == \'smiley\')
1124
								knownSmileys[knownSmileys.length] = document.images[i].id.substr(6);
1125
					}
1126
1127
					for (i = 0; i < knownSmileys.length; i++)
1128
					{
1129
						currentImage = document.getElementById("smiley" + knownSmileys[i]);
1130
						currentImage.src = "' . $modSettings['smileys_url'] . '/" + newSet + "/" + document.forms.smileyForm["smileys[" + knownSmileys[i] + "][filename]"].value;
1131
					}
1132
				}',
1133
		);
1134
1135
		require_once($sourcedir . '/Subs-List.php');
1136
		createList($listOptions);
1137
1138
		// The list is the only thing to show, so make it the main template.
1139
		$context['default_list'] = 'smiley_list';
1140
		$context['sub_template'] = 'show_list';
1141
	}
1142
	// Modifying smileys.
1143
	elseif ($context['sub_action'] == 'modifysmiley')
1144
	{
1145
		// Get a list of all known smiley sets.
1146
		$context['smileys_dir'] = empty($modSettings['smileys_dir']) ? $boarddir . '/Smileys' : $modSettings['smileys_dir'];
1147
		$context['smileys_dir_found'] = is_dir($context['smileys_dir']);
1148
		$context['smiley_sets'] = explode(',', $modSettings['smiley_sets_known']);
1149
		$set_names = explode("\n", $modSettings['smiley_sets_names']);
1150 View Code Duplication
		foreach ($context['smiley_sets'] as $i => $set)
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...
1151
			$context['smiley_sets'][$i] = array(
1152
				'id' => $i,
1153
				'path' => $smcFunc['htmlspecialchars']($set),
1154
				'name' => $smcFunc['htmlspecialchars']($set_names[$i]),
1155
				'selected' => $set == $modSettings['smiley_sets_default']
1156
			);
1157
1158
		$context['selected_set'] = $modSettings['smiley_sets_default'];
1159
1160
		// Get all possible filenames for the smileys.
1161
		$context['filenames'] = array();
1162 View Code Duplication
		if ($context['smileys_dir_found'])
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...
1163
		{
1164
			foreach ($context['smiley_sets'] as $smiley_set)
1165
			{
1166
				if (!file_exists($context['smileys_dir'] . '/' . un_htmlspecialchars($smiley_set['path'])))
1167
					continue;
1168
1169
				$dir = dir($context['smileys_dir'] . '/' . un_htmlspecialchars($smiley_set['path']));
1170
				while ($entry = $dir->read())
1171
				{
1172
					if (!in_array($entry, $context['filenames']) && in_array(strrchr($entry, '.'), array('.jpg', '.gif', '.jpeg', '.png')))
1173
						$context['filenames'][strtolower($entry)] = array(
1174
							'id' => $smcFunc['htmlspecialchars']($entry),
1175
							'selected' => false,
1176
						);
1177
				}
1178
				$dir->close();
1179
			}
1180
			ksort($context['filenames']);
1181
		}
1182
1183
		$request = $smcFunc['db_query']('', '
1184
			SELECT id_smiley AS id, code, filename, description, hidden AS location, 0 AS is_new
1185
			FROM {db_prefix}smileys
1186
			WHERE id_smiley = {int:current_smiley}',
1187
			array(
1188
				'current_smiley' => (int) $_REQUEST['smiley'],
1189
			)
1190
		);
1191
		if ($smcFunc['db_num_rows']($request) != 1)
1192
			fatal_lang_error('smiley_not_found');
1193
		$context['current_smiley'] = $smcFunc['db_fetch_assoc']($request);
1194
		$smcFunc['db_free_result']($request);
1195
1196
		$context['current_smiley']['code'] = $smcFunc['htmlspecialchars']($context['current_smiley']['code']);
1197
		$context['current_smiley']['filename'] = $smcFunc['htmlspecialchars']($context['current_smiley']['filename']);
1198
		$context['current_smiley']['description'] = $smcFunc['htmlspecialchars']($context['current_smiley']['description']);
1199
1200
		if (isset($context['filenames'][strtolower($context['current_smiley']['filename'])]))
1201
			$context['filenames'][strtolower($context['current_smiley']['filename'])]['selected'] = true;
1202
	}
1203
}
1204
1205
/**
1206
 * Callback function for createList().
1207
 *
1208
 * @param int $start The item to start with (not used here)
1209
 * @param int $items_per_page The number of items to show per page (not used here)
1210
 * @param string $sort A string indicating how to sort the results
1211
 * @return array An array of info about the smileys
1212
 */
1213 View Code Duplication
function list_getSmileys($start, $items_per_page, $sort)
0 ignored issues
show
Unused Code introduced by
The parameter $start is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $items_per_page is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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...
1214
{
1215
	global $smcFunc;
1216
1217
	$request = $smcFunc['db_query']('', '
1218
		SELECT id_smiley, code, filename, description, smiley_row, smiley_order, hidden
1219
		FROM {db_prefix}smileys
1220
		ORDER BY {raw:sort}',
1221
		array(
1222
			'sort' => $sort,
1223
		)
1224
	);
1225
	$smileys = array();
1226
	while ($row = $smcFunc['db_fetch_assoc']($request))
1227
		$smileys[] = $row;
1228
	$smcFunc['db_free_result']($request);
1229
1230
	return $smileys;
1231
}
1232
1233
/**
1234
 * Callback function for createList().
1235
 * @return int The number of smileys
1236
 */
1237
function list_getNumSmileys()
1238
{
1239
	global $smcFunc;
1240
1241
	$request = $smcFunc['db_query']('', '
1242
		SELECT COUNT(*)
1243
		FROM {db_prefix}smileys',
1244
		array()
1245
	);
1246
	list($numSmileys) = $smcFunc['db_fetch_row'];
1247
	$smcFunc['db_free_result']($request);
1248
1249
	return $numSmileys;
1250
}
1251
1252
/**
1253
 * Allows to edit smileys order.
1254
 */
1255
function EditSmileyOrder()
1256
{
1257
	global $context, $txt, $smcFunc;
1258
1259
	// Move smileys to another position.
1260
	if (isset($_REQUEST['reorder']))
1261
	{
1262
		checkSession('get');
1263
1264
		$_GET['location'] = empty($_GET['location']) || $_GET['location'] != 'popup' ? 0 : 2;
1265
		$_GET['source'] = empty($_GET['source']) ? 0 : (int) $_GET['source'];
1266
1267
		if (empty($_GET['source']))
1268
			fatal_lang_error('smiley_not_found');
1269
1270
		if (!empty($_GET['after']))
1271
		{
1272
			$_GET['after'] = (int) $_GET['after'];
1273
1274
			$request = $smcFunc['db_query']('', '
1275
				SELECT smiley_row, smiley_order, hidden
1276
				FROM {db_prefix}smileys
1277
				WHERE hidden = {int:location}
1278
					AND id_smiley = {int:after_smiley}',
1279
				array(
1280
					'location' => $_GET['location'],
1281
					'after_smiley' => $_GET['after'],
1282
				)
1283
			);
1284
			if ($smcFunc['db_num_rows']($request) != 1)
1285
				fatal_lang_error('smiley_not_found');
1286
			list ($smiley_row, $smiley_order, $smileyLocation) = $smcFunc['db_fetch_row']($request);
1287
			$smcFunc['db_free_result']($request);
1288
		}
1289
		else
1290
		{
1291
			$smiley_row = (int) $_GET['row'];
1292
			$smiley_order = -1;
1293
			$smileyLocation = (int) $_GET['location'];
1294
		}
1295
1296
		$smcFunc['db_query']('', '
1297
			UPDATE {db_prefix}smileys
1298
			SET smiley_order = smiley_order + 1
1299
			WHERE hidden = {int:new_location}
1300
				AND smiley_row = {int:smiley_row}
1301
				AND smiley_order > {int:smiley_order}',
1302
			array(
1303
				'new_location' => $_GET['location'],
1304
				'smiley_row' => $smiley_row,
1305
				'smiley_order' => $smiley_order,
1306
			)
1307
		);
1308
1309
		$smcFunc['db_query']('', '
1310
			UPDATE {db_prefix}smileys
1311
			SET
1312
				smiley_order = {int:smiley_order} + 1,
1313
				smiley_row = {int:smiley_row},
1314
				hidden = {int:new_location}
1315
			WHERE id_smiley = {int:current_smiley}',
1316
			array(
1317
				'smiley_order' => $smiley_order,
1318
				'smiley_row' => $smiley_row,
1319
				'new_location' => $smileyLocation,
1320
				'current_smiley' => $_GET['source'],
1321
			)
1322
		);
1323
1324
		cache_put_data('parsing_smileys', null, 480);
1325
		cache_put_data('posting_smileys', null, 480);
1326
	}
1327
1328
	$request = $smcFunc['db_query']('', '
1329
		SELECT id_smiley, code, filename, description, smiley_row, smiley_order, hidden
1330
		FROM {db_prefix}smileys
1331
		WHERE hidden != {int:popup}
1332
		ORDER BY smiley_order, smiley_row',
1333
		array(
1334
			'popup' => 1,
1335
		)
1336
	);
1337
	$context['smileys'] = array(
1338
		'postform' => array(
1339
			'rows' => array(),
1340
		),
1341
		'popup' => array(
1342
			'rows' => array(),
1343
		),
1344
	);
1345
	while ($row = $smcFunc['db_fetch_assoc']($request))
1346
	{
1347
		$location = empty($row['hidden']) ? 'postform' : 'popup';
1348
		$context['smileys'][$location]['rows'][$row['smiley_row']][] = array(
1349
			'id' => $row['id_smiley'],
1350
			'code' => $smcFunc['htmlspecialchars']($row['code']),
1351
			'filename' => $smcFunc['htmlspecialchars']($row['filename']),
1352
			'description' => $smcFunc['htmlspecialchars']($row['description']),
1353
			'row' => $row['smiley_row'],
1354
			'order' => $row['smiley_order'],
1355
			'selected' => !empty($_REQUEST['move']) && $_REQUEST['move'] == $row['id_smiley'],
1356
		);
1357
	}
1358
	$smcFunc['db_free_result']($request);
1359
1360
	$context['move_smiley'] = empty($_REQUEST['move']) ? 0 : (int) $_REQUEST['move'];
1361
1362
	// Make sure all rows are sequential.
1363
	foreach (array_keys($context['smileys']) as $location)
1364
		$context['smileys'][$location] = array(
1365
			'id' => $location,
1366
			'title' => $location == 'postform' ? $txt['smileys_location_form'] : $txt['smileys_location_popup'],
1367
			'description' => $location == 'postform' ? $txt['smileys_location_form_description'] : $txt['smileys_location_popup_description'],
1368
			'last_row' => count($context['smileys'][$location]['rows']),
1369
			'rows' => array_values($context['smileys'][$location]['rows']),
1370
		);
1371
1372
	// Check & fix smileys that are not ordered properly in the database.
1373
	foreach (array_keys($context['smileys']) as $location)
1374
	{
1375
		foreach ($context['smileys'][$location]['rows'] as $id => $smiley_row)
1376
		{
1377
			// Fix empty rows if any.
1378
			if ($id != $smiley_row[0]['row'])
1379
			{
1380
				$smcFunc['db_query']('', '
1381
					UPDATE {db_prefix}smileys
1382
					SET smiley_row = {int:new_row}
1383
					WHERE smiley_row = {int:current_row}
1384
						AND hidden = {int:location}',
1385
					array(
1386
						'new_row' => $id,
1387
						'current_row' => $smiley_row[0]['row'],
1388
						'location' => $location == 'postform' ? '0' : '2',
1389
					)
1390
				);
1391
				// Only change the first row value of the first smiley (we don't need the others :P).
1392
				$context['smileys'][$location]['rows'][$id][0]['row'] = $id;
1393
			}
1394
			// Make sure the smiley order is always sequential.
1395
			foreach ($smiley_row as $order_id => $smiley)
1396
				if ($order_id != $smiley['order'])
1397
					$smcFunc['db_query']('', '
1398
						UPDATE {db_prefix}smileys
1399
						SET smiley_order = {int:new_order}
1400
						WHERE id_smiley = {int:current_smiley}',
1401
						array(
1402
							'new_order' => $order_id,
1403
							'current_smiley' => $smiley['id'],
1404
						)
1405
					);
1406
		}
1407
	}
1408
1409
	cache_put_data('parsing_smileys', null, 480);
1410
	cache_put_data('posting_smileys', null, 480);
1411
}
1412
1413
/**
1414
 * Install a smiley set.
1415
 */
1416
function InstallSmileySet()
1417
{
1418
	global $sourcedir, $boarddir, $packagesdir, $modSettings, $smcFunc, $scripturl, $context, $txt, $user_info;
1419
1420
	isAllowedTo('manage_smileys');
1421
	checkSession('request');
1422
	// One of these two may be necessary
1423
	loadLanguage('Errors');
1424
	loadLanguage('Packages');
1425
1426
	require_once($sourcedir . '/Subs-Package.php');
1427
1428
	// Installing unless proven otherwise
1429
	$testing = false;
1430
1431
	if (isset($_REQUEST['set_gz']))
1432
	{
1433
		$base_name = strtr(basename($_REQUEST['set_gz']), ':/', '-_');
1434
		$name = $smcFunc['htmlspecialchars'](strtok(basename($_REQUEST['set_gz']), '.'));
1435
		$name_pr = preg_replace(array('/\s/', '/\.[\.]+/', '/[^\w_\.\-]/'), array('_', '.', ''), $name);
0 ignored issues
show
Unused Code introduced by
$name_pr is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1436
		$context['filename'] = $base_name;
1437
1438
		// Check that the smiley is from simplemachines.org, for now... maybe add mirroring later.
1439
		if (preg_match('~^http://[\w_\-]+\.simplemachines\.org/~', $_REQUEST['set_gz']) == 0 || strpos($_REQUEST['set_gz'], 'dlattach') !== false)
1440
			fatal_lang_error('not_on_simplemachines');
1441
1442
		$destination = $packagesdir . '/' . $base_name;
1443
1444
		if (file_exists($destination))
1445
			fatal_lang_error('package_upload_error_exists');
1446
1447
		// Let's copy it to the Packages directory
1448
		file_put_contents($destination, fetch_web_data($_REQUEST['set_gz']));
1449
		$testing = true;
1450
	}
1451
	elseif (isset($_REQUEST['package']))
1452
	{
1453
		$base_name = basename($_REQUEST['package']);
1454
		$name = $smcFunc['htmlspecialchars'](strtok(basename($_REQUEST['package']), '.'));
1455
		$name_pr = preg_replace(array('/\s/', '/\.[\.]+/', '/[^\w_\.\-]/'), array('_', '.', ''), $name);
0 ignored issues
show
Unused Code introduced by
$name_pr is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1456
		$context['filename'] = $base_name;
1457
1458
		$destination = $packagesdir . '/' . basename($_REQUEST['package']);
1459
	}
1460
1461
	if (!file_exists($destination))
0 ignored issues
show
Bug introduced by
The variable $destination 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...
1462
		fatal_lang_error('package_no_file', false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

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...
1463
1464
	// Make sure temp directory exists and is empty.
1465
	if (file_exists($packagesdir . '/temp'))
1466
		deltree($packagesdir . '/temp', false);
1467
1468
	if (!mktree($packagesdir . '/temp', 0755))
1469
	{
1470
		deltree($packagesdir . '/temp', false);
1471
		if (!mktree($packagesdir . '/temp', 0777))
1472
		{
1473
			deltree($packagesdir . '/temp', false);
1474
			// @todo not sure about url in destination_url
1475
			create_chmod_control(array($packagesdir . '/temp/delme.tmp'), array('destination_url' => $scripturl . '?action=admin;area=smileys;sa=install;set_gz=' . $_REQUEST['set_gz'], 'crash_on_error' => true));
1476
1477
			deltree($packagesdir . '/temp', false);
1478
			if (!mktree($packagesdir . '/temp', 0777))
1479
				fatal_lang_error('package_cant_download', false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

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...
1480
		}
1481
	}
1482
1483
	$extracted = read_tgz_file($destination, $packagesdir . '/temp');
1484
	if (!$extracted)
1485
		fatal_lang_error('packageget_unable', false, array('http://custom.simplemachines.org/mods/index.php?action=search;type=12;basic_search=' . $name));
0 ignored issues
show
Bug introduced by
The variable $name 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...
Documentation introduced by
false is of type boolean, but the function expects a string.

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...
1486
	if ($extracted && !file_exists($packagesdir . '/temp/package-info.xml'))
1487
		foreach ($extracted as $file)
1488
			if (basename($file['filename']) == 'package-info.xml')
1489
			{
1490
				$base_path = dirname($file['filename']) . '/';
1491
				break;
1492
			}
1493
1494
	if (!isset($base_path))
1495
		$base_path = '';
1496
1497
	if (!file_exists($packagesdir . '/temp/' . $base_path . 'package-info.xml'))
1498
		fatal_lang_error('package_get_error_missing_xml', false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

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...
1499
1500
	$smileyInfo = getPackageInfo($context['filename']);
1501
	if (!is_array($smileyInfo))
1502
		fatal_lang_error($smileyInfo);
1503
1504
	// See if it is installed?
1505
	$request = $smcFunc['db_query']('', '
1506
		SELECT version, themes_installed, db_changes
1507
		FROM {db_prefix}log_packages
1508
		WHERE package_id = {string:current_package}
1509
			AND install_state != {int:not_installed}
1510
		ORDER BY time_installed DESC
1511
		LIMIT 1',
1512
		array(
1513
			'not_installed'	=> 0,
1514
			'current_package' => $smileyInfo['id'],
1515
		)
1516
	);
1517
1518
	if ($smcFunc['db_num_rows']($request) > 0)
1519
		fata_lang_error('package_installed_warning1');
1520
1521
	// Everything is fine, now it's time to do something
1522
	$actions = parsePackageInfo($smileyInfo['xml'], true, 'install');
1523
1524
	$context['post_url'] = $scripturl . '?action=admin;area=smileys;sa=install;package=' . $base_name;
0 ignored issues
show
Bug introduced by
The variable $base_name 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...
1525
	$has_readme = false;
0 ignored issues
show
Unused Code introduced by
$has_readme is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1526
	$context['has_failure'] = false;
1527
	$context['actions'] = array();
1528
	$context['ftp_needed'] = false;
1529
1530
	foreach ($actions as $action)
1531
	{
1532
		if ($action['type'] == 'readme' || $action['type'] == 'license')
1533
		{
1534
			$has_readme = true;
0 ignored issues
show
Unused Code introduced by
$has_readme is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1535
			$type = 'package_' . $action['type'];
1536 View Code Duplication
			if (file_exists($packagesdir . '/temp/' . $base_path . $action['filename']))
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...
1537
				$context[$type] = $smcFunc['htmlspecialchars'](trim(file_get_contents($packagesdir . '/temp/' . $base_path . $action['filename']), "\n\r"));
1538
			elseif (file_exists($action['filename']))
1539
				$context[$type] = $smcFunc['htmlspecialchars'](trim(file_get_contents($action['filename']), "\n\r"));
1540
1541
			if (!empty($action['parse_bbc']))
1542
			{
1543
				require_once($sourcedir . '/Subs-Post.php');
1544
				preparsecode($context[$type]);
1545
				$context[$type] = parse_bbc($context[$type]);
1546
			}
1547
			else
1548
				$context[$type] = nl2br($context[$type]);
1549
1550
			continue;
1551
		}
1552
		elseif ($action['type'] == 'require-dir')
1553
		{
1554
			// Do this one...
1555
			$thisAction = array(
1556
				'type' => $txt['package_extract'] . ' ' . ($action['type'] == 'require-dir' ? $txt['package_tree'] : $txt['package_file']),
1557
				'action' => $smcFunc['htmlspecialchars'](strtr($action['destination'], array($boarddir => '.')))
1558
			);
1559
1560
			$file =  $packagesdir . '/temp/' . $base_path . $action['filename'];
1561
			if (isset($action['filename']) && (!file_exists($file) || !is_writable(dirname($action['destination']))))
1562
			{
1563
				$context['has_failure'] = true;
1564
1565
				$thisAction += array(
1566
					'description' => $txt['package_action_error'],
1567
					'failed' => true,
1568
				);
1569
			}
1570
			// @todo None given?
1571 View Code Duplication
			if (empty($thisAction['description']))
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...
1572
				$thisAction['description'] = isset($action['description']) ? $action['description'] : '';
1573
1574
			$context['actions'][] = $thisAction;
1575
		}
1576 View Code Duplication
		elseif ($action['type'] == 'credits')
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...
1577
		{
1578
			// Time to build the billboard
1579
			$credits_tag = array(
1580
				'url' => $action['url'],
1581
				'license' => $action['license'],
1582
				'copyright' => $action['copyright'],
1583
				'title' => $action['title'],
1584
			);
1585
		}
1586
	}
1587
1588
	if ($testing)
1589
	{
1590
		$context['sub_template'] = 'view_package';
1591
		$context['uninstalling'] = false;
1592
		$context['is_installed'] = false;
1593
		$context['package_name'] = $smileyInfo['name'];
1594
		loadTemplate('Packages');
1595
	}
1596
	// Do the actual install
1597
	else
1598
	{
1599
		$actions = parsePackageInfo($smileyInfo['xml'], false, 'install');
0 ignored issues
show
Unused Code introduced by
$actions is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1600
		foreach ($context['actions'] as $action)
1601
		{
1602
			updateSettings(array(
1603
				'smiley_sets_known' => $modSettings['smiley_sets_known'] . ',' . basename($action['action']),
1604
				'smiley_sets_names' => $modSettings['smiley_sets_names'] . "\n" . $smileyInfo['name'] . (count($context['actions']) > 1 ? ' ' .  (!empty($action['description']) ? $smcFunc['htmlspecialchars']($action['description']) : basename($action['action'])) : ''),
1605
			));
1606
		}
1607
1608
		package_flush_cache();
1609
1610
		// Credits tag?
1611
		$credits_tag = (empty($credits_tag)) ? '' : json_encode($credits_tag);
1612
		$smcFunc['db_insert']('',
1613
			'{db_prefix}log_packages',
1614
			array(
1615
				'filename' => 'string', 'name' => 'string', 'package_id' => 'string', 'version' => 'string',
1616
				'id_member_installed' => 'int', 'member_installed' => 'string','time_installed' => 'int',
1617
				'install_state' => 'int', 'failed_steps' => 'string', 'themes_installed' => 'string',
1618
				'member_removed' => 'int', 'db_changes' => 'string', 'credits' => 'string',
1619
			),
1620
			array(
1621
				$smileyInfo['filename'], $smileyInfo['name'], $smileyInfo['id'], $smileyInfo['version'],
1622
				$user_info['id'], $user_info['name'], time(),
1623
				1, '', '',
1624
				0, '', $credits_tag,
1625
			),
1626
			array('id_install')
1627
		);
1628
1629
		logAction('install_package', array('package' => $smcFunc['htmlspecialchars']($smileyInfo['name']), 'version' => $smcFunc['htmlspecialchars']($smileyInfo['version'])), 'admin');
1630
1631
		cache_put_data('parsing_smileys', null, 480);
1632
		cache_put_data('posting_smileys', null, 480);
1633
	}
1634
1635
	if (file_exists($packagesdir . '/temp'))
1636
		deltree($packagesdir . '/temp');
1637
1638
	if (!$testing)
1639
		redirectexit('action=admin;area=smileys');
1640
}
1641
1642
/**
1643
 * A function to import new smileys from an existing directory into the database.
1644
 *
1645
 * @param string $smileyPath The path to the directory to import smileys from
1646
 */
1647
function ImportSmileys($smileyPath)
1648
{
1649
	global $modSettings, $smcFunc;
1650
1651
	if (empty($modSettings['smileys_dir']) || !is_dir($modSettings['smileys_dir'] . '/' . $smileyPath))
1652
		fatal_lang_error('smiley_set_unable_to_import');
1653
1654
	$smileys = array();
1655
	$dir = dir($modSettings['smileys_dir'] . '/' . $smileyPath);
1656 View Code Duplication
	while ($entry = $dir->read())
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...
1657
	{
1658
		if (in_array(strrchr($entry, '.'), array('.jpg', '.gif', '.jpeg', '.png')))
1659
			$smileys[strtolower($entry)] = $entry;
1660
	}
1661
	$dir->close();
1662
1663
	// Exclude the smileys that are already in the database.
1664
	$request = $smcFunc['db_query']('', '
1665
		SELECT filename
1666
		FROM {db_prefix}smileys
1667
		WHERE filename IN ({array_string:smiley_list})',
1668
		array(
1669
			'smiley_list' => $smileys,
1670
		)
1671
	);
1672 View Code Duplication
	while ($row = $smcFunc['db_fetch_assoc']($request))
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...
1673
		if (isset($smileys[strtolower($row['filename'])]))
1674
			unset($smileys[strtolower($row['filename'])]);
1675
	$smcFunc['db_free_result']($request);
1676
1677
	$request = $smcFunc['db_query']('', '
1678
		SELECT MAX(smiley_order)
1679
		FROM {db_prefix}smileys
1680
		WHERE hidden = {int:postform}
1681
			AND smiley_row = {int:first_row}',
1682
		array(
1683
			'postform' => 0,
1684
			'first_row' => 0,
1685
		)
1686
	);
1687
	list ($smiley_order) = $smcFunc['db_fetch_row']($request);
1688
	$smcFunc['db_free_result']($request);
1689
1690
	$new_smileys = array();
1691
	foreach ($smileys as $smiley)
1692
		if (strlen($smiley) <= 48)
1693
			$new_smileys[] = array(':' . strtok($smiley, '.') . ':', $smiley, strtok($smiley, '.'), 0, ++$smiley_order);
1694
1695
	if (!empty($new_smileys))
1696
	{
1697
		$smcFunc['db_insert']('',
1698
			'{db_prefix}smileys',
1699
			array(
1700
				'code' => 'string-30', 'filename' => 'string-48', 'description' => 'string-80', 'smiley_row' => 'int', 'smiley_order' => 'int',
1701
			),
1702
			$new_smileys,
1703
			array('id_smiley')
1704
		);
1705
1706
		cache_put_data('parsing_smileys', null, 480);
1707
		cache_put_data('posting_smileys', null, 480);
1708
	}
1709
}
1710
1711
/**
1712
 * Handles editing message icons
1713
 */
1714
function EditMessageIcons()
1715
{
1716
	global $context, $settings, $txt;
1717
	global $smcFunc, $scripturl, $sourcedir;
1718
1719
	// Get a list of icons.
1720
	$context['icons'] = array();
1721
	$request = $smcFunc['db_query']('', '
1722
		SELECT m.id_icon, m.title, m.filename, m.icon_order, m.id_board, b.name AS board_name
1723
		FROM {db_prefix}message_icons AS m
1724
			LEFT JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
1725
		WHERE ({query_see_board} OR b.id_board IS NULL)
1726
		ORDER BY m.icon_order',
1727
		array(
1728
		)
1729
	);
1730
	$last_icon = 0;
1731
	$trueOrder = 0;
1732
	while ($row = $smcFunc['db_fetch_assoc']($request))
1733
	{
1734
		$context['icons'][$row['id_icon']] = array(
1735
			'id' => $row['id_icon'],
1736
			'title' => $row['title'],
1737
			'filename' => $row['filename'],
1738
			'image_url' => $settings[file_exists($settings['theme_dir'] . '/images/post/' . $row['filename'] . '.png') ? 'actual_images_url' : 'default_images_url'] . '/post/' . $row['filename'] . '.png',
1739
			'board_id' => $row['id_board'],
1740
			'board' => empty($row['board_name']) ? $txt['icons_edit_icons_all_boards'] : $row['board_name'],
1741
			'order' => $row['icon_order'],
1742
			'true_order' => $trueOrder++,
1743
			'after' => $last_icon,
1744
		);
1745
		$last_icon = $row['id_icon'];
1746
	}
1747
	$smcFunc['db_free_result']($request);
1748
1749
	// Submitting a form?
1750
	if (isset($_POST['icons_save']))
1751
	{
1752
		checkSession();
1753
1754
		// Deleting icons?
1755
		if (isset($_POST['delete']) && !empty($_POST['checked_icons']))
1756
		{
1757
			$deleteIcons = array();
1758
			foreach ($_POST['checked_icons'] as $icon)
1759
				$deleteIcons[] = (int) $icon;
1760
1761
			// Do the actual delete!
1762
			$smcFunc['db_query']('', '
1763
				DELETE FROM {db_prefix}message_icons
1764
				WHERE id_icon IN ({array_int:icon_list})',
1765
				array(
1766
					'icon_list' => $deleteIcons,
1767
				)
1768
			);
1769
		}
1770
		// Editing/Adding an icon?
1771
		elseif ($context['sub_action'] == 'editicon' && isset($_GET['icon']))
1772
		{
1773
			$_GET['icon'] = (int) $_GET['icon'];
1774
1775
			// Do some preperation with the data... like check the icon exists *somewhere*
1776
			if (strpos($_POST['icon_filename'], '.png') !== false)
1777
				$_POST['icon_filename'] = substr($_POST['icon_filename'], 0, -4);
1778
			if (!file_exists($settings['default_theme_dir'] . '/images/post/' . $_POST['icon_filename'] . '.png'))
1779
				fatal_lang_error('icon_not_found');
1780
			// There is a 16 character limit on message icons...
1781
			elseif (strlen($_POST['icon_filename']) > 16)
1782
				fatal_lang_error('icon_name_too_long');
1783
			elseif ($_POST['icon_location'] == $_GET['icon'] && !empty($_GET['icon']))
1784
				fatal_lang_error('icon_after_itself');
1785
1786
			// First do the sorting... if this is an edit reduce the order of everything after it by one ;)
1787
			if ($_GET['icon'] != 0)
1788
			{
1789
				$oldOrder = $context['icons'][$_GET['icon']]['true_order'];
1790
				foreach ($context['icons'] as $id => $data)
1791
					if ($data['true_order'] > $oldOrder)
1792
						$context['icons'][$id]['true_order']--;
1793
			}
1794
1795
			// If there are no existing icons and this is a new one, set the id to 1 (mainly for non-mysql)
1796
			if (empty($_GET['icon']) && empty($context['icons']))
1797
				$_GET['icon'] = 1;
1798
1799
			// Get the new order.
1800
			$newOrder = $_POST['icon_location'] == 0 ? 0 : $context['icons'][$_POST['icon_location']]['true_order'] + 1;
1801
			// Do the same, but with the one that used to be after this icon, done to avoid conflict.
1802
			foreach ($context['icons'] as $id => $data)
1803
				if ($data['true_order'] >= $newOrder)
1804
					$context['icons'][$id]['true_order']++;
1805
1806
			// Finally set the current icon's position!
1807
			$context['icons'][$_GET['icon']]['true_order'] = $newOrder;
1808
1809
			// Simply replace the existing data for the other bits.
1810
			$context['icons'][$_GET['icon']]['title'] = $_POST['icon_description'];
1811
			$context['icons'][$_GET['icon']]['filename'] = $_POST['icon_filename'];
1812
			$context['icons'][$_GET['icon']]['board_id'] = (int) $_POST['icon_board'];
1813
1814
			// Do a huge replace ;)
1815
			$iconInsert = array();
1816
			$iconInsert_new = array();
1817
			foreach ($context['icons'] as $id => $icon)
1818
			{
1819
				if ($id != 0)
1820
				{
1821
					$iconInsert[] = array($id, $icon['board_id'], $icon['title'], $icon['filename'], $icon['true_order']);
1822
				}
1823
				else
1824
				{
1825
					$iconInsert_new[] = array($icon['board_id'], $icon['title'], $icon['filename'], $icon['true_order']);
1826
				}
1827
			}
1828
1829
			$smcFunc['db_insert']('replace',
1830
				'{db_prefix}message_icons',
1831
				array('id_icon' => 'int', 'id_board' => 'int', 'title' => 'string-80', 'filename' => 'string-80', 'icon_order' => 'int'),
1832
				$iconInsert,
1833
				array('id_icon')
1834
			);
1835
1836
			if (!empty($iconInsert_new))
1837
			{
1838
				$smcFunc['db_insert']('replace',
1839
					'{db_prefix}message_icons',
1840
					array('id_board' => 'int', 'title' => 'string-80', 'filename' => 'string-80', 'icon_order' => 'int'),
1841
					$iconInsert_new,
1842
					array('id_icon')
1843
				);
1844
			}
1845
		}
1846
1847
		// Unless we're adding a new thing, we'll escape
1848
		if (!isset($_POST['add']))
1849
			redirectexit('action=admin;area=smileys;sa=editicons');
1850
	}
1851
1852
	$context[$context['admin_menu_name']]['current_subsection'] = 'editicons';
1853
1854
	$listOptions = array(
1855
		'id' => 'message_icon_list',
1856
		'title' => $txt['icons_edit_message_icons'],
1857
		'base_href' => $scripturl . '?action=admin;area=smileys;sa=editicons',
1858
		'get_items' => array(
1859
			'function' => 'list_getMessageIcons',
1860
		),
1861
		'no_items_label' => $txt['icons_no_entries'],
1862
		'columns' => array(
1863
			'icon' => array(
1864
				'data' => array(
1865
					'function' => function ($rowData) use ($settings, $smcFunc)
1866
					{
1867
						$images_url = $settings[file_exists(sprintf('%1$s/images/post/%2$s.png', $settings['theme_dir'], $rowData['filename'])) ? 'actual_images_url' : 'default_images_url'];
1868
						return sprintf('<img src="%1$s/post/%2$s.png" alt="%3$s">', $images_url, $rowData['filename'], $smcFunc['htmlspecialchars']($rowData['title']));
1869
					},
1870
					'class' => 'centercol',
1871
				),
1872
			),
1873
			'filename' => array(
1874
				'header' => array(
1875
					'value' => $txt['smileys_filename'],
1876
				),
1877
				'data' => array(
1878
					'sprintf' => array(
1879
						'format' => '%1$s.png',
1880
						'params' => array(
1881
							'filename' => true,
1882
						),
1883
					),
1884
				),
1885
			),
1886
			'tooltip' => array(
1887
				'header' => array(
1888
					'value' => $txt['smileys_description'],
1889
				),
1890
				'data' => array(
1891
					'db_htmlsafe' => 'title',
1892
				),
1893
			),
1894
			'board' => array(
1895
				'header' => array(
1896
					'value' => $txt['icons_board'],
1897
				),
1898
				'data' => array(
1899
					'function' => function ($rowData) use ($txt)
1900
					{
1901
						return empty($rowData['board_name']) ? $txt['icons_edit_icons_all_boards'] : $rowData['board_name'];
1902
					},
1903
				),
1904
			),
1905
			'modify' => array(
1906
				'header' => array(
1907
					'value' => $txt['smileys_modify'],
1908
					'class' => 'centercol',
1909
				),
1910
				'data' => array(
1911
					'sprintf' => array(
1912
						'format' => '<a href="' . $scripturl . '?action=admin;area=smileys;sa=editicon;icon=%1$s">' . $txt['smileys_modify'] . '</a>',
1913
						'params' => array(
1914
							'id_icon' => false,
1915
						),
1916
					),
1917
					'class' => 'centercol',
1918
				),
1919
			),
1920
			'check' => array(
1921
				'header' => array(
1922
					'value' => '<input type="checkbox" onclick="invertAll(this, this.form);" class="input_check">',
1923
					'class' => 'centercol',
1924
				),
1925
				'data' => array(
1926
					'sprintf' => array(
1927
						'format' => '<input type="checkbox" name="checked_icons[]" value="%1$d" class="input_check">',
1928
						'params' => array(
1929
							'id_icon' => false,
1930
						),
1931
					),
1932
					'class' => 'centercol',
1933
				),
1934
			),
1935
		),
1936
		'form' => array(
1937
			'href' => $scripturl . '?action=admin;area=smileys;sa=editicons',
1938
		),
1939
		'additional_rows' => array(
1940
			array(
1941
				'position' => 'below_table_data',
1942
				'value' => '<input type="submit" name="delete" value="' . $txt['quickmod_delete_selected'] . '" class="button_submit"> <a class="button_link" href="' . $scripturl . '?action=admin;area=smileys;sa=editicon">' . $txt['icons_add_new'] . '</a>',
1943
			),
1944
		),
1945
	);
1946
1947
	require_once($sourcedir . '/Subs-List.php');
1948
	createList($listOptions);
1949
1950
	// If we're adding/editing an icon we'll need a list of boards
1951
	if ($context['sub_action'] == 'editicon' || isset($_POST['add']))
1952
	{
1953
		// Force the sub_template just in case.
1954
		$context['sub_template'] = 'editicon';
1955
1956
		$context['new_icon'] = !isset($_GET['icon']);
1957
1958
		// Get the properties of the current icon from the icon list.
1959
		if (!$context['new_icon'])
1960
			$context['icon'] = $context['icons'][$_GET['icon']];
1961
1962
		// Get a list of boards needed for assigning this icon to a specific board.
1963
		$boardListOptions = array(
1964
			'use_permissions' => true,
1965
			'selected_board' => isset($context['icon']['board_id']) ? $context['icon']['board_id'] : 0,
1966
		);
1967
		require_once($sourcedir . '/Subs-MessageIndex.php');
1968
		$context['categories'] = getBoardList($boardListOptions);
1969
	}
1970
}
1971
1972
/**
1973
 * Callback function for createList().
1974
 *
1975
 * @param int $start The item to start with (not used here)
1976
 * @param int $items_per_page The number of items to display per page (not used here)
1977
 * @param string $sort A string indicating how to sort the items (not used here)
1978
 * @return array An array of information about message icons
1979
 */
1980 View Code Duplication
function list_getMessageIcons($start, $items_per_page, $sort)
0 ignored issues
show
Unused Code introduced by
The parameter $start is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $items_per_page is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $sort is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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...
1981
{
1982
	global $smcFunc;
1983
1984
	$request = $smcFunc['db_query']('', '
1985
		SELECT m.id_icon, m.title, m.filename, m.icon_order, m.id_board, b.name AS board_name
1986
		FROM {db_prefix}message_icons AS m
1987
			LEFT JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
1988
		WHERE ({query_see_board} OR b.id_board IS NULL)
1989
		ORDER BY m.icon_order',
1990
		array()
1991
	);
1992
1993
	$message_icons = array();
1994
	while ($row = $smcFunc['db_fetch_assoc']($request))
1995
		$message_icons[] = $row;
1996
	$smcFunc['db_free_result']($request);
1997
1998
	return $message_icons;
1999
}
2000
2001
?>
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...