Passed
Push — master ( fa5f85...8b14e0 )
by John
10:17
created

UltimateMenu   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 416
Duplicated Lines 0 %

Test Coverage

Coverage 4.12%

Importance

Changes 6
Bugs 2 Features 0
Metric Value
eloc 214
c 6
b 2
f 0
dl 0
loc 416
rs 10
ccs 7
cts 170
cp 0.0412
wmc 29

13 Methods

Rating   Name   Duplication   Size   Complexity  
A updateButton() 0 18 4
B listGroups() 0 52 7
A total_getMenu() 0 17 2
A deleteButton() 0 11 1
A fetchButton() 0 28 1
A list_getMenu() 0 24 2
A deleteallButtons() 0 7 1
A rebuildMenu() 0 40 2
A list_getNumButtons() 0 14 1
A saveButton() 0 59 2
A checkButton() 0 20 2
A getButtonNames() 0 11 1
A flatten() 0 10 3
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 UltimateMenu
13
{
14
	/**
15
	 * Gets all membergroups and filters them according to the parameters.
16
	 *
17
	 * @param int[] $checked    list of all id_groups to be checked (have a mark in the checkbox).
18
	 *                          Default is an empty array.
19
	 * @param bool  $inherited  whether or not to filter out the inherited groups. Default is false.
20
	 *
21
	 * @return array all the membergroups filtered according to the parameters; empty array if something went wrong.
22
	 */
23
	public function listGroups(array $checked = [], $inherited = false)
24
	{
25
		global $modSettings, $smcFunc, $sourcedir, $txt;
26
27
		loadLanguage('ManageBoards');
28
		$groups = [
29
			-1 => [
30
				'name' => $txt['parent_guests_only'],
31
				'checked' => in_array(-1, $checked) || in_array(-3, $checked),
32
				'is_post_group' => false,
33
			],
34
			0 => [
35
				'name' => $txt['parent_members_only'],
36
				'checked' => in_array(0, $checked) || in_array(-3, $checked),
37
				'is_post_group' => false,
38
			],
39
		];
40
		$where = ['id_group NOT IN (1, 3)'];
41
42
		if (!$inherited)
43
		{
44
			$where[] = 'id_parent = {int:not_inherited}';
45
46
			if (empty($modSettings['permission_enable_postgroups']))
47
				$where[] = 'min_posts = {int:min_posts}';
48
		}
49
		$request = $smcFunc['db_query'](
50
			'',
51
			'
52
			SELECT
53
				group_name, id_group, min_posts
54
			FROM {db_prefix}membergroups
55
			WHERE ' . implode(
56
				'
57
				AND ',
58
				$where
59
			),
60
			[
61
				'not_inherited' => -2,
62
				'min_posts' => -1,
63
			]
64
		);
65
66
		while ($row = $smcFunc['db_fetch_assoc']($request))
67
			$groups[$row['id_group']] = [
68
				'name' => trim($row['group_name']),
69
				'checked' => in_array($row['id_group'], $checked) || in_array(-3, $checked),
70
				'is_post_group' => $row['min_posts'] != -1,
71
			];
72
		$smcFunc['db_free_result']($request);
73
74
		return $groups;
75
	}
76
77
	/**
78
	 * Loads all buttons from the db
79
	 *
80
	 * @return string[]
81
	 */
82
	public function total_getMenu()
83
	{
84
		global $smcFunc;
85
86
		$request = $smcFunc['db_query'](
87
			'',
88
			'
89
			SELECT
90
				id_button, name, target, type, position, link, status, permissions, parent
91
			FROM {db_prefix}um_menu'
92
		);
93
		$buttons = [];
94
95
		while ($row = $smcFunc['db_fetch_assoc']($request))
96
			$buttons[] = $row;
97
98
		return $buttons;
99
	}
100
101
	/**
102
	 * Createlist callback, used to display um entries
103
	 *
104
	 * @param int    $start
105
	 * @param int    $items_per_page
106
	 * @param string $sort
107
	 *
108
	 * @return string[]
109
	 */
110
	public function list_getMenu($start, $items_per_page, $sort)
111
	{
112
		global $smcFunc;
113
114
		$request = $smcFunc['db_query'](
115
			'',
116
			'
117
			SELECT
118
				id_button, name, target, type, position, link, status, parent
119
			FROM {db_prefix}um_menu
120
			ORDER BY {raw:sort}
121
			LIMIT {int:offset}, {int:limit}',
122
			[
123
				'sort' => $sort,
124
				'offset' => $start,
125
				'limit' => $items_per_page,
126
			]
127
		);
128
		$buttons = [];
129
130
		while ($row = $smcFunc['db_fetch_assoc']($request))
131
			$buttons[] = $row;
132
133
		return $buttons;
134
	}
135
136
	/**
137
	 * Createlist callback to determine the number of buttons
138
	 *
139
	 * @return int
140
	 */
141
	public function list_getNumButtons()
142
	{
143
		global $smcFunc;
144
145
		$request = $smcFunc['db_query'](
146
			'',
147
			'
148
			SELECT COUNT(*)
149
			FROM {db_prefix}um_menu'
150
		);
151
		 [$numButtons] = $smcFunc['db_fetch_row']($request);
152
		$smcFunc['db_free_result']($request);
153
154
		return $numButtons;
155
	}
156
157
	/**
158
	 * Sets the serialized array of buttons into settings
159
	 *
160
	 * Called whenever the menu structure is updated in the ACP
161
	 */
162
	public function rebuildMenu(): void
163
	{
164
		global $smcFunc;
165
166
		$request = $smcFunc['db_query'](
167
			'',
168
			'
169
			SELECT *
170
			FROM {db_prefix}um_menu'
171
		);
172
		$buttons = [];
173
174
		while ($row = $smcFunc['db_fetch_assoc']($request))
175
			$buttons['um_button_' . $row['id_button']] = json_encode($row);
176
		$smcFunc['db_free_result']($request);
177
178
		$request = $smcFunc['db_query'](
179
			'',
180
			'
181
			SELECT MAX(id_button)
182
			FROM {db_prefix}um_menu'
183
		);
184
		 [$max] = $smcFunc['db_fetch_row']($request);
185
		$smcFunc['db_free_result']($request);
186
187
		$smcFunc['db_query'](
188
			'',
189
			'
190
			DELETE FROM {db_prefix}settings
191
			WHERE variable LIKE {string:settings_search}
192
				AND variable NOT IN ({array_string:settings})',
193
			[
194
				'settings_search' => 'um_button%',
195
				'settings' => array_keys($buttons),
196
			]
197
		);
198
		updateSettings(
199
			[
200
				'um_count' => $max,
201
			] + $buttons
202
		);
203
	}
204
205
	/**
206
	 * Removes menu item(s) from the um system
207
	 *
208
	 * @param int[] $ids
209
	 */
210
	public function deleteButton(array $ids): void
211
	{
212
		global $smcFunc;
213
214
		$smcFunc['db_query'](
215
			'',
216
			'
217
			DELETE FROM {db_prefix}um_menu
218
			WHERE id_button IN ({array_int:button_list})',
219
			[
220
				'button_list' => $ids,
221
			]
222
		);
223
	}
224
225
	/**
226
	 * Changes the status of a button from active to inactive
227
	 *
228
	 */
229
	public function updateButton(array $updates): void
230
	{
231
		global $smcFunc;
232
233
		foreach ($this->total_getMenu() as $item)
234
		{
235
			$status = !empty($updates['status'][$item['id_button']]) ? 'active' : 'inactive';
236
237
			if ($status != $item['status'])
238
				$smcFunc['db_query'](
239
					'',
240
					'
241
					UPDATE {db_prefix}um_menu
242
					SET status = {string:status}
243
					WHERE id_button = {int:item}',
244
					[
245
						'status' => $status,
246
						'item' => $item['id_button'],
247
					]
248
				);
249
		}
250
	}
251
252
	/**
253
	 * Checks if there is an existing um id with the same name before saving
254
	 *
255
	 * @param int    $id
256
	 * @param string $name
257
	 *
258
	 * @return int
259
	 */
260
	public function checkButton($id, $name)
261
	{
262
		global $smcFunc;
263
264
		$request = $smcFunc['db_query'](
265
			'',
266
			'
267
			SELECT id_button
268
			FROM {db_prefix}um_menu
269
			WHERE name = {string:name}
270
				AND id_button != {int:id}',
271
			[
272
				'name' => $name,
273
				'id' => $id ?: 0,
274
			]
275
		);
276
		$check = $smcFunc['db_num_rows']($request);
277
		$smcFunc['db_free_result']($request);
278
279
		return $check;
280
	}
281
282
	/**
283
	 * Saves a new or updates an existing button
284
	 */
285
	public function saveButton(array $menu_entry): void
286
	{
287
		global $smcFunc;
288
289
		if (!empty($menu_entry['in']))
290
		{
291
			$smcFunc['db_query'](
292
				'',
293
				'
294
				UPDATE {db_prefix}um_menu
295
				SET
296
					name = {string:name},
297
					type = {string:type},
298
					target = {string:target},
299
					position = {string:position},
300
					link = {string:link},
301
					status = {string:status},
302
					permissions = {string:permissions},
303
					parent = {string:parent}
304
				WHERE id_button = {int:id}',
305
				[
306
					'id' => $menu_entry['in'],
307
					'name' => $menu_entry['name'],
308
					'type' => $menu_entry['type'],
309
					'target' => $menu_entry['target'],
310
					'position' => $menu_entry['position'],
311
					'link' => $menu_entry['link'],
312
					'status' => $menu_entry['status'],
313
					'permissions' => implode(',', array_filter($menu_entry['permissions'], 'strlen')),
314
					'parent' => $menu_entry['parent'],
315
				]
316
			);
317
		}
318
		else
319
		{
320
			$smcFunc['db_insert'](
321
				'insert',
322
				'{db_prefix}um_menu',
323
				[
324
					'name' => 'string',
325
					'type' => 'string',
326
					'target' => 'string',
327
					'position' => 'string',
328
					'link' => 'string',
329
					'status' => 'string',
330
					'permissions' => 'string',
331
					'parent' => 'string',
332
				],
333
				[
334
					$menu_entry['name'],
335
					$menu_entry['type'],
336
					$menu_entry['target'],
337
					$menu_entry['position'],
338
					$menu_entry['link'],
339
					$menu_entry['status'],
340
					implode(',', array_filter($menu_entry['permissions'], 'strlen')),
341
					$menu_entry['parent'],
342
				],
343
				['id_button']
344
			);
345
		}
346
	}
347
348
	/**
349
	 * Fetch a specific button
350
	 *
351
	 * @param int $id
352
	 *
353
	 * @return array
354
	 */
355
	public function fetchButton($id)
356
	{
357
		global $smcFunc;
358
359
		$request = $smcFunc['db_query'](
360
			'',
361
			'
362
			SELECT
363
				id_button, name, target, type, position, link, status, permissions, parent
364
			FROM {db_prefix}um_menu
365
			WHERE id_button = {int:button}',
366
			[
367
				'button' => $id,
368
			]
369
		);
370
		$row = $smcFunc['db_fetch_assoc']($request);
371
		$smcFunc['db_free_result']($request);
372
373
		return [
374
			'id' => $row['id_button'],
375
			'name' => $row['name'],
376
			'target' => $row['target'],
377
			'type' => $row['type'],
378
			'position' => $row['position'],
379
			'permissions' => explode(',', $row['permissions']),
380
			'link' => $row['link'],
381
			'status' => $row['status'],
382
			'parent' => $row['parent'],
383
		];
384
	}
385
386
	/**
387
	 * Removes all buttons
388
	 */
389
	public function deleteallButtons(): void
390
	{
391
		global $smcFunc;
392
393
		$smcFunc['db_query'](
394
			'',
395
			'
396
			TRUNCATE {db_prefix}um_menu'
397
		);
398
	}
399
400
	/**
401
	 * Fetches the names of all SMF menu buttons.
402
	 *
403
	 * @return array
404
	 */
405
	public function getButtonNames()
406
	{
407
		global $context;
408
409
		// It's expected to be present.
410
		$context['user']['unread_messages'] = 0;
411
412
		// Load SMF's default menu context
413
		setupMenuContext();
414
415
		return $this->flatten($context['menu_buttons']);
416
	}
417
418 1
	public function flatten(array $array, int $i = 0): array
419
	{
420 1
		$result = array();
421 1
		foreach ($array as $key => $value)
422
		{
423 1
			$result[$key] = [$i, $value['title']];
424 1
			if (!empty($value['sub_buttons']))
425 1
				$result += $this->flatten($value['sub_buttons'], ++$i);
426
		}
427 1
		return $result;
428
	}
429
}