Passed
Push — master ( 41f8ea...52ae2e )
by John
02:00
created

ManageUltimateMenu::getInput()   B

Complexity

Conditions 8
Paths 1

Size

Total Lines 63
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 38
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 63
rs 8.0675

How to fix   Long Method   

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
declare(strict_types=1);
4
5
/**
6
 * @package   Ultimate Menu mod
7
 * @version   1.1.0
8
 * @author    John Rayes <[email protected]>
9
 * @copyright Copyright (c) 2014, John Rayes
10
 * @license   http://opensource.org/licenses/MIT MIT
11
 */
12
class ManageUltimateMenu
13
{
14
	private $um;
15
16
	public function __construct()
17
	{
18
		global $context, $sourcedir, $txt;
19
20
		isAllowedTo('admin_forum');
21
22
		$context['page_title'] = $txt['admin_menu_title'];
23
		$context[$context['admin_menu_name']]['tab_data'] = [
24
			'title' => $txt['admin_menu'],
25
			'description' => $txt['admin_menu_desc'],
26
			'tabs' => [
27
				'manmenu' => [
28
					'description' => $txt['admin_manage_menu_desc'],
29
				],
30
				'addbutton' => [
31
					'description' => $txt['admin_menu_add_button_desc'],
32
				],
33
			],
34
		];
35
		loadTemplate('ManageUltimateMenu');
36
		require_once $sourcedir . '/Class-UltimateMenu.php';
37
		$this->um = new UltimateMenu;
38
39
		$subActions = [
40
			'manmenu' => 'ManageUltimateMenu',
41
			'addbutton' => 'AddButton',
42
			'editbutton' => 'EditButton',
43
			'savebutton' => 'SaveButton',
44
		];
45
46
		if (!isset($_GET['sa']) || !isset($subActions[$_GET['sa']]))
47
			$_GET['sa'] = 'manmenu';
48
		$this->{$subActions[$_GET['sa']]}();
49
	}
50
51
	public function ManageUltimateMenu(): void
52
	{
53
		// Get rid of all of em!
54
		if (!empty($_POST['removeAll']))
55
		{
56
			checkSession();
57
			$this->um->deleteallButtons();
58
			$this->um->rebuildMenu();
59
			redirectexit('action=admin;area=umen');
60
		}
61
		// User pressed the 'remove selection button'.
62
		elseif (isset($_POST['removeButtons'], $_POST['remove']) && is_array($_POST['remove']))
63
		{
64
			checkSession();
65
			$this->um->deleteButton(array_filter($_POST['remove'], 'ctype_digit'));
66
			$this->um->rebuildMenu();
67
			redirectexit('action=admin;area=umen');
68
		}
69
		// Changing the status?
70
		elseif (isset($_POST['save']))
71
		{
72
			checkSession();
73
			$this->um->updateButton($_POST);
74
			$this->um->rebuildMenu();
75
			redirectexit('action=admin;area=umen');
76
		}
77
		// New item?
78
		elseif (isset($_POST['new']))
79
			redirectexit('action=admin;area=umen;sa=addbutton');
80
81
		$this->ListButtons();
82
	}
83
84
	public function ListButtons(): void
85
	{
86
		global $context, $txt, $scripturl, $sourcedir;
87
88
		$button_names = $this->um->getButtonNames();
89
		$listOptions = [
90
			'id' => 'menu_list',
91
			'items_per_page' => 20,
92
			'base_href' => $scripturl . '?action=admin;area=umen;sa=manmenu',
93
			'default_sort_col' => 'name',
94
			'default_sort_dir' => 'desc',
95
			'get_items' => [
96
				'function' => [$this->um, 'list_getMenu'],
97
			],
98
			'get_count' => [
99
				'function' => [$this->um, 'list_getNumButtons'],
100
			],
101
			'no_items_label' => $txt['um_menu_no_buttons'],
102
			'columns' => [
103
				'name' => [
104
					'header' => [
105
						'value' => $txt['um_menu_button_name'],
106
					],
107
					'data' => [
108
						'db_htmlsafe' => 'name',
109
					],
110
					'sort' => [
111
						'default' => 'name',
112
						'reverse' => 'name DESC',
113
					],
114
				],
115
				'type' => [
116
					'header' => [
117
						'value' => $txt['um_menu_button_type'],
118
					],
119
					'data' => [
120
						'function' => function ($rowData) use ($txt)
121
						{
122
							return $txt['um_menu_' . $rowData['type'] . '_link'];
123
						},
124
					],
125
					'sort' => [
126
						'default' => 'type',
127
						'reverse' => 'type DESC',
128
					],
129
				],
130
				'position' => [
131
					'header' => [
132
						'value' => $txt['um_menu_button_position'],
133
					],
134
					'data' => [
135
						'function' => function ($rowData) use ($txt, $button_names)
136
						{
137
							return sprintf(
138
								'%s %s',
139
								$txt['um_menu_' . $rowData['position']],
140
								isset($button_names[$rowData['parent']])
141
									? $button_names[$rowData['parent']][1]
142
									: ucwords($rowData['parent'])
143
							);
144
						},
145
					],
146
					'sort' => [
147
						'default' => 'position',
148
						'reverse' => 'position DESC',
149
					],
150
				],
151
				'link' => [
152
					'header' => [
153
						'value' => $txt['um_menu_button_link'],
154
					],
155
					'data' => [
156
						'db_htmlsafe' => 'link',
157
					],
158
					'sort' => [
159
						'default' => 'link',
160
						'reverse' => 'link DESC',
161
					],
162
				],
163
				'status' => [
164
					'header' => [
165
						'value' => $txt['um_menu_button_active'],
166
						'class' => 'centertext',
167
					],
168
					'data' => [
169
						'function' => function ($rowData)
170
						{
171
							return sprintf(
172
								'<input type="checkbox" name="status[%1$s]" id="status_%1$s" value="%1$s"%2$s />',
173
								$rowData['id_button'],
174
								$rowData['status'] == 'inactive' ? '' : ' checked="checked"'
175
							);
176
						},
177
						'class' => 'centertext',
178
					],
179
					'sort' => [
180
						'default' => 'status',
181
						'reverse' => 'status DESC',
182
					],
183
				],
184
				'actions' => [
185
					'header' => [
186
						'value' => $txt['um_menu_actions'],
187
						'class' => 'centertext',
188
					],
189
					'data' => [
190
						'function' => function ($rowData) use ($scripturl, $txt)
191
						{
192
							return sprintf(
193
								'<a href="%s?action=admin;area=umen;sa=editbutton;in=%d">%s</a>',
194
								$scripturl,
195
								$rowData['id_button'],
196
								$txt['modify']
197
							);
198
						},
199
						'class' => 'centertext',
200
					],
201
				],
202
				'check' => [
203
					'header' => [
204
						'value' => '<input type="checkbox" onclick="invertAll(this, this.form);" class="input_check" />',
205
						'class' => 'centertext',
206
					],
207
					'data' => [
208
						'sprintf' => [
209
							'format' => '<input type="checkbox" name="remove[]" value="%d" class="input_check" />',
210
							'params' => [
211
								'id_button' => false,
212
							],
213
						],
214
						'class' => 'centertext',
215
					],
216
				],
217
			],
218
			'form' => [
219
				'href' => $scripturl . '?action=admin;area=umen;sa=manmenu',
220
			],
221
			'additional_rows' => [
222
				[
223
					'position' => 'below_table_data',
224
					'value' => sprintf(
225
						'
226
						<input type="submit" name="removeButtons" value="%s" onclick="return confirm(\'%s\');" class="button_submit" />
227
						<input type="submit" name="removeAll" value="%s" onclick="return confirm(\'%s\');" class="button_submit" />
228
						<input type="submit" name="new" value="%s" class="button_submit" />
229
						<input type="submit" name="save" value="%s" class="button_submit" />',
230
						$txt['um_menu_remove_selected'],
231
						$txt['um_menu_remove_confirm'],
232
						$txt['um_menu_remove_all'],
233
						$txt['um_menu_remove_all_confirm'],
234
						$txt['um_admin_add_button'],
235
						$txt['save']
236
					),
237
					'class' => 'righttext',
238
				],
239
			],
240
		];
241
		require_once $sourcedir . '/Subs-List.php';
242
		createList($listOptions);
243
		$context['sub_template'] = 'show_list';
244
		$context['default_list'] = 'menu_list';
245
	}
246
247
	public function getInput(): array
248
	{
249
		$member_groups = $this->um->listGroups([-3]);
250
		$button_names = $this->um->getButtonNames();
251
		$args = [
252
			'in' => FILTER_VALIDATE_INT,
253
			'name' => FILTER_UNSAFE_RAW,
254
			'position' => [
255
				'filter' => FILTER_CALLBACK,
256
				'options' => function ($v)
257
				{
258
					return in_array($v, ['before', 'child_of', 'after']) ? $v : false;
259
				},
260
			],
261
			'parent' => [
262
				'filter' => FILTER_CALLBACK,
263
				'options' => function ($v) use ($button_names)
264
				{
265
					return isset($button_names[$v]) ? $v : false;
266
				},
267
			],
268
			'type' => [
269
				'filter' => FILTER_CALLBACK,
270
				'options' => function ($v)
271
				{
272
					return in_array($v, ['forum', 'external']) ? $v : false;
273
				},
274
			],
275
			'link' => FILTER_UNSAFE_RAW,
276
			'permissions' => [
277
				'filter' => FILTER_CALLBACK,
278
				'flags' => FILTER_REQUIRE_ARRAY,
279
				'options' => function ($v) use ($member_groups)
280
				{
281
					return isset($member_groups[$v]) ? $v : false;
282
				},
283
			],
284
			'status' => [
285
				'filter' => FILTER_CALLBACK,
286
				'options' => function ($v)
287
				{
288
					return in_array($v, ['active', 'inactive']) ? $v : false;
289
				},
290
			],
291
			'target' => [
292
				'filter' => FILTER_CALLBACK,
293
				'options' => function ($v)
294
				{
295
					return in_array($v, ['_self', '_blank']) ? $v : false;
296
				},
297
			],
298
		];
299
300
		// Make sure we grab all of the content
301
		return array_replace(
302
			[
303
				'target' => '_self',
304
				'type' => 'forum',
305
				'position' => 'before',
306
				'status' => 'active',
307
				'parent' => 'home',
308
			],
309
			filter_input_array(INPUT_POST, $args) ?: []
0 ignored issues
show
Bug introduced by
It seems like filter_input_array(INPUT_POST, $args) ?: array() can also be of type null; however, parameter $replacements of array_replace() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

309
			/** @scrutinizer ignore-type */ filter_input_array(INPUT_POST, $args) ?: []
Loading history...
310
		);
311
	}
312
313
	public function validateInput(array $menu_entry): array
314
	{
315
		$post_errors = [];
316
		$required_fields = [
317
			'name',
318
			'link',
319
			'parent',
320
		];
321
322
		// If your session timed out, show an error, but do allow to re-submit.
323
		if (checkSession('post', '', false) != '')
324
			$post_errors[] = 'um_menu_session_verify_fail';
325
326
		// These fields are required!
327
		foreach ($required_fields as $required_field)
328
			if (empty($menu_entry[$required_field]))
329
				$post_errors[$required_field] = 'um_menu_empty_' . $required_field;
330
331
		// Stop making numeric names!
332
		if (is_numeric($menu_entry['name']))
333
			$post_errors['name'] = 'um_menu_numeric';
334
335
		// Let's make sure you're not trying to make a name that's already taken.
336
		if (!empty($this->um->checkButton($menu_entry['in'], $menu_entry['name'])))
337
			$post_errors['name'] = 'um_menu_mysql';
338
339
		return $post_errors;
340
	}
341
342
	public function SaveButton(): void
343
	{
344
		global $context, $txt;
345
346
		if (isset($_POST['submit']))
347
		{
348
			$menu_entry = $this->getInput();
349
			$post_errors = $this->validateInput($menu_entry);
350
351
			// I see you made it to the final stage, my young padawan.
352
			if (empty($post_errors))
353
			{
354
				$this->um->saveButton($menu_entry);
355
				$this->um->rebuildMenu();
356
357
				// Before we leave, we must clear the cache. See, SMF
358
				// caches its menu at level 2 or higher.
359
				clean_cache('menu_buttons');
360
361
				redirectexit('action=admin;area=umen');
362
			}
363
			else
364
			{
365
				$context['page_title'] = $txt['um_menu_edit_title'];
366
				$context['button_names'] = $this->um->getButtonNames();
367
				$context['post_error'] = $post_errors;
368
				$context['error_title'] = empty($menu_entry['in'])
369
					? 'um_menu_errors_create'
370
					: 'um_menu_errors_modify';
371
				$context['button_data'] = [
372
					'name' => $menu_entry['name'],
373
					'type' => $menu_entry['type'],
374
					'target' => $menu_entry['target'],
375
					'position' => $menu_entry['position'],
376
					'link' => $menu_entry['link'],
377
					'parent' => $menu_entry['parent'],
378
					'permissions' => $this->um->listGroups(
379
						array_filter($menu_entry['permissions'], 'strlen')
380
					),
381
					'status' => $menu_entry['status'],
382
					'id' => $menu_entry['in'],
383
				];
384
				$context['all_groups_checked'] = empty(array_diff_key(
385
					$context['button_data']['permissions'],
386
					array_flip(array_filter($menu_entry['permissions'], 'strlen'))
387
				));
388
				$context['template_layers'][] = 'form';
389
				$context['template_layers'][] = 'errors';
390
			}
391
		}
392
		else
393
			fatal_lang_error('no_access', false);
394
	}
395
396
	public function EditButton(): void
397
	{
398
		global $context, $txt;
399
400
		$row = isset($_GET['in']) ? $this->um->fetchButton($_GET['in']) : [];
401
		if (empty($row))
402
			fatal_lang_error('no_access', false);
403
404
		$context['button_data'] = [
405
			'id' => $row['id'],
406
			'name' => $row['name'],
407
			'target' => $row['target'],
408
			'type' => $row['type'],
409
			'position' => $row['position'],
410
			'permissions' => $this->um->listGroups($row['permissions']),
411
			'link' => $row['link'],
412
			'status' => $row['status'],
413
			'parent' => $row['parent'],
414
		];
415
		$context['all_groups_checked'] = empty(array_diff_key(
416
			$context['button_data']['permissions'],
417
			array_flip($row['permissions'])
418
		));
419
		$context['page_title'] = $txt['um_menu_edit_title'];
420
		$context['button_names'] = $this->um->getButtonNames();
421
		$context['template_layers'][] = 'form';
422
	}
423
424
	public function AddButton(): void
425
	{
426
		global $context, $txt;
427
428
		$context['button_data'] = [
429
			'name' => '',
430
			'link' => '',
431
			'target' => '_self',
432
			'type' => 'forum',
433
			'position' => 'before',
434
			'status' => 'active',
435
			'permissions' => $this->um->listGroups([-3]),
436
			'parent' => 'home',
437
			'id' => 0,
438
		];
439
		$context['all_groups_checked'] = true;
440
		$context['page_title'] = $txt['um_menu_add_title'];
441
		$context['button_names'] = $this->um->getButtonNames();
442
		$context['template_layers'][] = 'form';
443
	}
444
}
445