Issues (1697)

sources/ElkArte/AdminController/Admin.php (5 issues)

1
<?php
2
3
/**
4
 * This file, unpredictable as this might be, handles basic administration.
5
 *
6
 * @package   ElkArte Forum
7
 * @copyright ElkArte Forum contributors
8
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
9
 *
10
 * This file contains code covered by:
11
 * copyright: 2011 Simple Machines (http://www.simplemachines.org)
12
 *
13
 * @version 2.0 dev
14
 *
15
 */
16
17
namespace ElkArte\AdminController;
18
19
use ElkArte\AbstractController;
20
use ElkArte\Action;
21
use ElkArte\AdminSettingsSearch;
22
use ElkArte\EventManager;
23
use ElkArte\Exceptions\Exception;
24
use ElkArte\Hooks;
25
use ElkArte\Languages\Txt;
26
use ElkArte\Menu\Menu;
27
use ElkArte\Packages\Packages;
28
use ElkArte\Packages\PackageServers;
29
use ElkArte\User;
30
use ElkArte\XmlArray;
31
32
/**
33
 * Admin controller class.
34
 *
35
 * What it does:
36
 *
37
 * - This class handles the first general admin screens: home,
38
 * - Handles admin area search actions and end admin session.
39
 *
40
 * @package Admin
41
 */
42
class Admin extends AbstractController
43
{
44
	/** @var string[] areas to find current installed status and installed version */
45
	private array $_checkFor = ['gd', 'imagick', 'db_server', 'php', 'server',
46
		'zend', 'apc', 'memcache', 'memcached', 'opcache'];
47
48
	/**
49
	 * Pre Dispatch, called before other methods.
50
	 *
51
	 * - Loads integration hooks
52
	 */
53
	public function pre_dispatch()
54
	{
55
		global $context, $modSettings;
56
57
		Hooks::instance()->loadIntegrationsSettings();
58
59
		// The Admin functions require Jquery UI ....
60
		$modSettings['jquery_include_ui'] = true;
61
62
		// No indexing evil stuff.
63
		$context['robot_no_index'] = true;
64
65
		// Need these to do much
66
		require_once(SUBSDIR . '/Admin.subs.php');
67
	}
68
69
	/**
70
	 * The main admin handling function.
71
	 *
72
	 * What it does:
73
	 *
74
	 * - It initializes all the basic context required for the admin center.
75
	 * - It passes execution onto the relevant admin section.
76
	 * - If the passed section is not found it shows the admin home page.
77
	 * - Accessed by ?action=admin.
78
	 */
79
	public function action_index()
80
	{
81
		// Make sure the administrator has a valid session...
82
		validateSession();
83
84
		// Load the language and templates....
85
		Txt::load('Admin');
86
		theme()->getTemplates()->load('Admin');
87
		loadCSSFile('admin.css');
88
		loadJavascriptFile('admin.js', [], 'admin_script');
89
90
		// Actually create the menu!
91
		$admin_include_data = $this->loadMenu();
92
		$this->buildBreadCrumbs($admin_include_data);
93
94
		// And off we go, only one action, the chosen menu area
95
		$action = new Action();
96
		$action->initialize(['action' => $admin_include_data]);
97
		$action->dispatch('action');
98
	}
99
100
	/**
101
	 * Load the admin_areas array
102
	 *
103
	 * What it does:
104
	 *
105
	 * - Creates the admin menu
106
	 * - Allows integrations to add/edit menu with addMenu event and integrate_admin_include
107
	 *
108
	 * @event integrate_admin_include used add files to include for administration
109
	 * @event addMenu passed admin area, allows active modules registered to this event to add items to the admin menu,
110
	 * @event integrate_admin_areas passed admin area, used to add items to the admin menu
111 2
	 *
112
	 * @return array
113 2
	 * @throws Exception no_access
114
	 */
115
	private function loadMenu(): array
116 2
	{
117
		global $txt, $context, $modSettings, $settings;
118
119
		// Need these to do much
120 1
		require_once(SUBSDIR . '/Menu.subs.php');
121 2
122
		// Define the menu structure - see subs/Menu.subs.php for details!
123
		$admin_areas = [
124
			'forum' => [
125 2
				'title' => $txt['admin_main'],
126 2
				'permission' => ['admin_forum', 'manage_permissions', 'moderate_forum', 'manage_membergroups', 'manage_bans', 'send_mail', 'edit_news', 'manage_boards', 'manage_smileys', 'manage_attachments'],
127 2
				'areas' => [
128 2
					'index' => [
129 2
						'label' => $txt['admin_center'],
130
						'controller' => Admin::class,
131
						'function' => 'action_home',
132 2
						'class' => 'i-home i-admin',
133 2
					],
134 2
					'credits' => [
135 2
						'label' => $txt['support_credits_title'],
136 2
						'controller' => Admin::class,
137
						'function' => 'action_credits',
138
						'class' => 'i-support i-admin',
139 2
					],
140 2
					'maillist' => [
141 2
						'label' => $txt['mail_center'],
142 2
						'controller' => ManageMaillist::class,
143 2
						'function' => 'action_index',
144
						'class' => 'i-envelope-blank i-admin',
145 2
						'permission' => ['approve_emails', 'admin_forum'],
146
						'enabled' => featureEnabled('pe'),
147 2
						'subsections' => [
148 2
							'emaillist' => [$txt['mm_emailerror'], 'approve_emails'],
149 2
							'emailfilters' => [$txt['mm_emailfilters'], 'admin_forum'],
150 2
							'emailparser' => [$txt['mm_emailparsers'], 'admin_forum'],
151 2
							'emailtemplates' => [$txt['mm_emailtemplates'], 'approve_emails'],
152
							'emailsettings' => [$txt['mm_emailsettings'], 'admin_forum'],
153
						],
154
					],
155 2
					'news' => [
156 2
						'label' => $txt['news_title'],
157 2
						'controller' => ManageNews::class,
158 2
						'function' => 'action_index',
159 2
						'class' => 'i-post-text i-admin',
160
						'permission' => ['edit_news', 'send_mail', 'admin_forum'],
161
						'subsections' => [
162 2
							'editnews' => [$txt['admin_edit_news'], 'edit_news'],
163 2
							'mailingmembers' => [$txt['admin_newsletters'], 'send_mail'],
164 2
							'settings' => [$txt['settings'], 'admin_forum'],
165
						],
166
					],
167
					'packages' => [
168 2
						'label' => $txt['package'],
169 2
						'controller' => Packages::class,
170 2
						'function' => 'action_index',
171
						'permission' => ['admin_forum'],
172 2
						'class' => 'i-package i-admin',
173 2
						'subsections' => [
174
							'browse' => [$txt['browse_packages']],
175 2
							'servers' => [$txt['add_packages']],
176 2
							'options' => [$txt['package_settings']],
177 2
						],
178 2
					],
179 2
					'packageservers' => [
180 2
						'label' => $txt['package_servers'],
181
						'controller' => PackageServers::class,
182
						'function' => 'action_index',
183
						'permission' => ['admin_forum'],
184 2
						'class' => 'i-package i-admin',
185 2
						'hidden' => true,
186 2
					],
187
					'search' => [
188 2
						'controller' => Admin::class,
189 2
						'function' => 'action_search',
190
						'permission' => ['admin_forum'],
191
						'class' => 'i-search i-admin',
192
						'select' => 'index',
193
						'hidden' => true,
194
					],
195
					'adminlogoff' => [
196
						'controller' => Admin::class,
197
						'function' => 'action_endsession',
198
						'label' => $txt['admin_logoff'],
199 2
						'enabled' => empty($modSettings['securityDisable']),
200 2
						'class' => 'i-sign-out i-admin',
201 2
					],
202 2
				],
203 2
			],
204 2
			'config' => [
205
				'title' => $txt['admin_config'],
206
				'permission' => ['admin_forum'],
207
				'areas' => [
208
					'corefeatures' => [
209 2
						'label' => $txt['core_settings_title'],
210
						'controller' => CoreFeatures::class,
211
						'function' => 'action_index',
212
						'class' => 'i-cog i-admin',
213 2
					],
214 2
					'featuresettings' => [
215 2
						'label' => $txt['modSettings_title'],
216 2
						'controller' => ManageFeatures::class,
217 2
						'function' => 'action_index',
218
						'class' => 'i-switch-on i-admin',
219
						'subsections' => [
220 2
							'basic' => [$txt['mods_cat_features']],
221 2
							'layout' => [$txt['mods_cat_layout']],
222 2
							'mention' => [$txt['mention']],
223 2
							'pwa' => [$txt['pwa_label']],
224 2
							'pmsettings' => [$txt['personal_messages']],
225
							'sig' => [$txt['signature_settings_short']],
226 2
							'profile' => [$txt['custom_profile_shorttitle'], 'enabled' => featureEnabled('cp')],
227 2
							'karma' => [$txt['karma'], 'enabled' => featureEnabled('k')],
228 2
							'likes' => [$txt['likes'], 'enabled' => featureEnabled('l')],
229 2
						],
230 2
					],
231 2
					'serversettings' => [
232 2
						'label' => $txt['admin_server_settings'],
233 2
						'controller' => ManageServer::class,
234
						'function' => 'action_index',
235
						'class' => 'i-menu i-admin',
236
						'subsections' => [
237 2
							'general' => [$txt['general_settings']],
238 2
							'database' => [$txt['database_paths_settings']],
239 2
							'cookie' => [$txt['cookies_sessions_settings']],
240 2
							'cache' => [$txt['caching_settings']],
241 2
							'loads' => [$txt['loadavg_settings']],
242
							'phpinfo' => [$txt['phpinfo_settings']],
243 2
						],
244 2
					],
245 2
					'securitysettings' => [
246 2
						'label' => $txt['admin_security_moderation'],
247 2
						'controller' => ManageSecurity::class,
248 2
						'function' => 'action_index',
249
						'class' => 'i-key i-admin',
250
						'subsections' => [
251
							'general' => [$txt['mods_cat_security_general']],
252 2
							'spam' => [$txt['antispam_title']],
253 2
							'moderation' => [$txt['moderation_settings_short'], 'enabled' => !empty($modSettings['warning_enable'])],
254 2
						],
255 2
					],
256 2
					'theme' => [
257
						'label' => $txt['theme_admin'],
258 2
						'controller' => ManageThemes::class,
259 2
						'function' => 'action_index',
260 2
						'custom_url' => getUrl('admin', ['action' => 'admin', 'area' => 'theme']),
261 2
						'class' => 'i-modify i-admin',
262
						'subsections' => [
263
							'admin' => [$txt['themeadmin_admin_title']],
264
							'list' => [$txt['themeadmin_list_title']],
265 2
							'reset' => [$txt['themeadmin_reset_title']],
266 2
						],
267 2
					],
268 2
					'current_theme' => [
269 2
						'label' => $txt['theme_current_settings'],
270 2
						'controller' => ManageThemes::class,
271
						'function' => 'action_index',
272 2
						'custom_url' => getUrl('admin', ['action' => 'admin', 'area' => 'theme', 'sa' => 'list', 'th' => $settings['theme_id']]),
273 2
						'class' => 'i-paint i-admin',
274 2
					],
275 2
					'languages' => [
276 2
						'label' => $txt['language_configuration'],
277 2
						'controller' => ManageLanguages::class,
278
						'function' => 'action_index',
279
						'class' => 'i-language i-admin',
280
						'subsections' => [
281 2
							'edit' => [$txt['language_edit']],
282 2
							// 'add' => array($txt['language_add']),
283 2
							'settings' => [$txt['language_settings']],
284 2
						],
285 2
					],
286 2
					'addonsettings' => [
287
						'label' => $txt['admin_modifications'],
288
						'controller' => AddonSettings::class,
289 2
						'function' => 'action_index',
290 2
						'class' => 'i-puzzle i-admin',
291 2
						'subsections' => [
292 2
							'general' => [$txt['mods_cat_modifications_misc']],
293 2
						],
294
					],
295 2
				],
296
			],
297 2
			'layout' => [
298
				'title' => $txt['layout_controls'],
299
				'permission' => ['manage_boards', 'admin_forum', 'manage_smileys', 'manage_attachments', 'moderate_forum'],
300
				'areas' => [
301 2
					'manageboards' => [
302 2
						'label' => $txt['admin_boards'],
303 2
						'controller' => ManageBoards::class,
304 2
						'function' => 'action_index',
305 2
						'class' => 'i-directory i-admin',
306
						'permission' => ['manage_boards'],
307 2
						'subsections' => [
308
							'main' => [$txt['boardsEdit']],
309
							'newcat' => [$txt['mboards_new_cat']],
310
							'settings' => [$txt['settings'], 'admin_forum'],
311
						],
312
					],
313 2
					'postsettings' => [
314
						'label' => $txt['manageposts'],
315
						'controller' => ManagePosts::class,
316
						'function' => 'action_index',
317 2
						'permission' => ['admin_forum'],
318 2
						'class' => 'i-post-text i-admin',
319 2
						'subsections' => [
320 2
							'posts' => [$txt['manageposts_settings']],
321 2
							'censor' => [$txt['admin_censored_words']],
322
							'topics' => [$txt['manageposts_topic_settings']],
323
						],
324 2
					],
325 2
					'editor' => [
326 2
						'label' => $txt['editor_manage'],
327
						'controller' => ManageEditor::class,
328
						'function' => 'action_index',
329
						'class' => 'i-modify i-admin',
330 2
						'permission' => ['manage_bbc'],
331 2
					],
332 2
					'smileys' => [
333
						'label' => $txt['smileys_manage'],
334 2
						'controller' => ManageSmileys::class,
335 2
						'function' => 'action_index',
336
						'class' => 'i-smiley-blank i-admin',
337 2
						'permission' => ['manage_smileys'],
338 2
						'subsections' => [
339 2
							'editsets' => [$txt['smiley_sets']],
340 2
							'addsmiley' => [$txt['smileys_add']],
341
							'editsmileys' => [$txt['smileys_edit']],
342
							'setorder' => [$txt['smileys_set_order']],
343
							'editicons' => [$txt['icons_edit_message_icons'], 'enabled' => !empty($modSettings['messageIcons_enable'])],
344 2
							'settings' => [$txt['settings']],
345 2
						],
346 2
					],
347 2
					'manageattachments' => [
348 2
						'label' => $txt['attachments_avatars'],
349
						'controller' => ManageAttachments::class,
350
						'function' => 'action_index',
351
						'class' => 'i-paperclip i-admin',
352 2
						'permission' => ['manage_attachments'],
353 2
						'subsections' => [
354 2
							'browse' => [$txt['attachment_manager_browse']],
355 2
							'attachments' => [$txt['attachment_manager_settings']],
356 2
							'avatars' => [$txt['attachment_manager_avatar_settings']],
357
							'attachpaths' => [$txt['attach_directories']],
358
							'maintenance' => [$txt['attachment_manager_maintenance']],
359 2
						],
360 2
					],
361 2
					'managesearch' => [
362 2
						'label' => $txt['manage_search'],
363 2
						'controller' => ManageSearch::class,
364 2
						'function' => 'action_index',
365
						'class' => 'i-search i-admin',
366
						'permission' => ['admin_forum'],
367
						'subsections' => [
368 2
							'method' => [$txt['search_method']],
369 2
							'weights' => [$txt['search_weights']],
370 2
							'managesphinxql' => [$txt['search_sphinx']],
371 2
							'managemanticore' => [$txt['search_manticore']],
372 2
							'settings' => [$txt['settings']],
373
						],
374
					],
375 2
				],
376 2
			],
377 2
			'members' => [
378 2
				'title' => $txt['admin_manage_members'],
379 2
				'permission' => ['moderate_forum', 'manage_membergroups', 'manage_bans', 'manage_permissions', 'admin_forum'],
380
				'areas' => [
381
					'viewmembers' => [
382
						'label' => $txt['admin_users'],
383 2
						'controller' => ManageMembers::class,
384 2
						'function' => 'action_index',
385 2
						'class' => 'i-user i-admin',
386 2
						'permission' => ['moderate_forum'],
387 2
					],
388
					'membergroups' => [
389
						'label' => $txt['admin_groups'],
390 2
						'controller' => ManageMembergroups::class,
391 2
						'function' => 'action_index',
392 2
						'class' => 'i-users',
393 2
						'permission' => ['manage_membergroups'],
394
						'subsections' => [
395
							'index' => [$txt['membergroups_edit_groups'], 'manage_membergroups'],
396
							'add' => [$txt['membergroups_new_group'], 'manage_membergroups'],
397
							'settings' => [$txt['settings'], 'admin_forum'],
398
						],
399 2
					],
400
					'permissions' => [
401
						'label' => $txt['edit_permissions'],
402
						'controller' => ManagePermissions::class,
403 2
						'function' => 'action_index',
404 2
						'class' => 'i-key i-admin',
405 2
						'permission' => ['manage_permissions'],
406 2
						'subsections' => [
407 2
							'index' => [$txt['permissions_groups'], 'manage_permissions'],
408
							'board' => [$txt['permissions_boards'], 'manage_permissions'],
409
							'profiles' => [$txt['permissions_profiles'], 'manage_permissions'],
410 2
							'postmod' => [$txt['permissions_post_moderation'], 'manage_permissions', 'enabled' => $modSettings['postmod_active']],
411 2
							'settings' => [$txt['settings'], 'admin_forum'],
412
						],
413
					],
414
					'ban' => [
415 2
						'label' => $txt['ban_title'],
416 2
						'controller' => ManageBans::class,
417 2
						'function' => 'action_index',
418 2
						'class' => 'i-thumbdown i-admin',
419 2
						'permission' => 'manage_bans',
420
						'subsections' => [
421
							'list' => [$txt['ban_edit_list']],
422 2
							'add' => [$txt['ban_add_new']],
423 2
							'browse' => [$txt['ban_trigger_browse']],
424 2
							'log' => [$txt['ban_log']],
425
						],
426
					],
427
					'regcenter' => [
428 2
						'label' => $txt['registration_center'],
429 2
						'controller' => ManageRegistration::class,
430 2
						'function' => 'action_index',
431 2
						'class' => 'i-user-plus i-admin',
432 2
						'permission' => ['admin_forum', 'moderate_forum'],
433
						'subsections' => [
434
							'register' => [$txt['admin_browse_register_new'], 'moderate_forum'],
435 2
							'agreement' => [$txt['registration_agreement'], 'admin_forum'],
436 2
							'privacypol' => [$txt['privacy_policy'], 'admin_forum'],
437 2
							'reservednames' => [$txt['admin_reserved_set'], 'admin_forum'],
438 2
							'settings' => [$txt['settings'], 'admin_forum'],
439 2
						],
440
					],
441
					'sengines' => [
442
						'label' => $txt['search_engines'],
443 2
						'enabled' => featureEnabled('sp'),
444 2
						'controller' => ManageSearchEngines::class,
445 2
						'function' => 'action_index',
446 2
						'class' => 'i-website i-admin',
447 2
						'permission' => 'admin_forum',
448 2
						'subsections' => [
449
							'stats' => [$txt['spider_stats']],
450 2
							'logs' => [$txt['spider_logs']],
451 2
							'spiders' => [$txt['spiders']],
452 2
							'settings' => [$txt['settings']],
453 2
						],
454
					],
455
					'paidsubscribe' => [
456
						'label' => $txt['paid_subscriptions'],
457 2
						'enabled' => featureEnabled('ps'),
458 2
						'controller' => ManagePaid::class,
459 2
						'class' => 'i-credit i-admin',
460 2
						'function' => 'action_index',
461 2
						'permission' => 'admin_forum',
462
						'subsections' => [
463
							'view' => [$txt['paid_subs_view']],
464 2
							'settings' => [$txt['settings']],
465 2
						],
466 2
					],
467 2
				],
468 2
			],
469
			'maintenance' => [
470
				'title' => $txt['admin_maintenance'],
471
				'permission' => ['admin_forum'],
472 2
				'areas' => [
473 2
					'maintain' => [
474 2
						'label' => $txt['maintain_title'],
475 2
						'controller' => Maintenance::class,
476 2
						'function' => 'action_index',
477 2
						'class' => 'i-cog i-admin',
478 2
						'subsections' => [
479
							'routine' => [$txt['maintain_sub_routine'], 'admin_forum'],
480 2
							'database' => [$txt['maintain_sub_database'], 'admin_forum'],
481 2
							'members' => [$txt['maintain_sub_members'], 'admin_forum'],
482 2
							'topics' => [$txt['maintain_sub_topics'], 'admin_forum'],
483 2
							'hooks' => [$txt['maintain_sub_hooks_list'], 'admin_forum'],
484
							'attachments' => [$txt['maintain_sub_attachments'], 'admin_forum'],
485
						],
486
					],
487 2
					'logs' => [
488 2
						'label' => $txt['logs'],
489 2
						'controller' => AdminLog::class,
490 2
						'function' => 'action_index',
491 2
						'class' => 'i-comments i-admin',
492 2
						'subsections' => [
493 2
							'errorlog' => [$txt['errlog'], 'admin_forum', 'enabled' => !empty($modSettings['enableErrorLogging']), 'url' => getUrl('admin', ['action' => 'admin', 'area' => 'logs', 'sa' => 'errorlog', 'desc'])],
494
							'adminlog' => [$txt['admin_log'], 'admin_forum', 'enabled' => featureEnabled('ml')],
495 2
							'modlog' => [$txt['moderation_log'], 'admin_forum', 'enabled' => featureEnabled('ml')],
496 2
							'banlog' => [$txt['ban_log'], 'manage_bans'],
497
							'spiderlog' => [$txt['spider_logs'], 'admin_forum', 'enabled' => featureEnabled('sp')],
498
							'tasklog' => [$txt['scheduled_log'], 'admin_forum'],
499
							'pruning' => [$txt['settings'], 'admin_forum'],
500
						],
501
					],
502 2
					'scheduledtasks' => [
503
						'label' => $txt['maintain_tasks'],
504
						'controller' => ManageScheduledTasks::class,
505
						'function' => 'action_index',
506 2
						'class' => 'i-calendar i-admin',
507 2
						'subsections' => [
508 2
							'tasks' => [$txt['maintain_tasks'], 'admin_forum'],
509 2
							'tasklog' => [$txt['scheduled_log'], 'admin_forum'],
510 2
						],
511
					],
512 2
					'mailqueue' => [
513 2
						'label' => $txt['mailqueue_title'],
514 2
						'controller' => ManageMail::class,
515 2
						'function' => 'action_index',
516 2
						'class' => 'i-envelope-blank i-admin',
517 2
						'subsections' => [
518
							'browse' => [$txt['mailqueue_browse'], 'admin_forum'],
519
							'test' => [$txt['mailqueue_test'], 'admin_forum'],
520
							'settings' => [$txt['mailqueue_settings'], 'admin_forum'],
521 2
						],
522 2
					],
523 2
					'reports' => [
524 2
						'enabled' => featureEnabled('rg'),
525 2
						'label' => $txt['generate_reports'],
526
						'controller' => Reports::class,
527 2
						'function' => 'action_index',
528 2
						'class' => 'i-pie-chart i-admin',
529 2
					],
530 2
					'repairboards' => [
531 2
						'label' => $txt['admin_repair'],
532 2
						'controller' => RepairBoards::class,
533 2
						'function' => 'action_repairboards',
534 2
						'select' => 'maintain',
535
						'hidden' => true,
536
					],
537
				],
538 2
			],
539 2
		];
540 2
541 2
		$this->_events->trigger('addMenu', ['admin_areas' => &$admin_areas]);
542 2
543
		// Any files to include for administration?
544 2
		call_integration_include_hook('integrate_admin_include');
545 2
546
		$menuOptions = [
547
			'hook' => 'admin',
548
		];
549 2
550 2
		// Actually create the admin menu!
551 2
		$admin_include_data = (new Menu())
552 2
			->addMenuData($admin_areas)
553 2
			->addOptions($menuOptions)
554
			->prepareMenu()
555 2
			->setContext()
556 2
			->getIncludeData();
557
558
		unset($admin_areas);
559
560 2
		// Make a note of the Unique ID for this menu.
561 2
		$context['admin_menu_id'] = $context['max_menu_id'];
562 2
		$context['admin_menu_name'] = 'menu_data_' . $context['admin_menu_id'];
563 2
564 2
		// Where in the admin are we?
565 2
		$context['admin_area'] = $admin_include_data['current_area'];
566
567
		return $admin_include_data;
568 2
	}
569 2
570 2
	/**
571 2
	 * Builds out the navigation link tree for the admin area
572
	 *
573
	 * @param array $admin_include_data
574
	 */
575
	private function buildBreadCrumbs(array $admin_include_data): void
576
	{
577
		global $txt, $context;
578 2
579
		// Build the link tree.
580
		$context['breadcrumbs'][] = [
581 2
			'url' => getUrl('admin', ['action' => 'admin']),
582
			'name' => $txt['admin_center'],
583
		];
584 2
585
		if (isset($admin_include_data['current_area']) && $admin_include_data['current_area'] !== 'index')
586
		{
587
			$context['breadcrumbs'][] = [
588 2
				'url' => getUrl('admin', ['action' => 'admin', 'area' => $admin_include_data['current_area'], '{session_data}']),
589 2
				'name' => $admin_include_data['label'],
590 2
			];
591 2
		}
592 2
593 2
		if (!isset($admin_include_data['current_subsection'], $admin_include_data['subsections'][$admin_include_data['current_subsection']]))
594
		{
595
			return;
596 2
		}
597 2
598
		if ($admin_include_data['subsections'][$admin_include_data['current_subsection']]['label'] === $admin_include_data['label'])
599
		{
600 2
			return;
601
		}
602 2
603
		$context['breadcrumbs'][] = [
604
			'url' => getUrl('admin', ['action' => 'admin', 'area' => $admin_include_data['current_area'], 'sa' => $admin_include_data['current_subsection'], '{session_data}']),
605
			'name' => $admin_include_data['subsections'][$admin_include_data['current_subsection']]['label'],
606
		];
607
	}
608
609
	/**
610
	 * The main administration section.
611
	 *
612
	 * What it does:
613
	 *
614
	 * - It prepares all the data necessary for the administration front page.
615
	 * - It uses the Admin template along with the admin sub template.
616
	 * - It requires the moderate_forum, manage_membergroups, manage_bans,
617
	 * admin_forum, manage_permissions, manage_attachments, manage_smileys,
618
	 * manage_boards, edit_news, or send_mail permission.
619
	 * - It uses the index administrative area.
620
	 * - Accessed by ?action=admin.
621
	 */
622
	public function action_home(): void
623
	{
624
		global $txt, $context;
625
626
		// We need a little help
627
		require_once(SUBSDIR . '/Membergroups.subs.php');
628
629
		// You have to be able to do at least one of the below to see this page.
630
		isAllowedTo(['admin_forum', 'manage_permissions', 'moderate_forum', 'manage_membergroups', 'manage_bans', 'send_mail', 'edit_news', 'manage_boards', 'manage_smileys', 'manage_attachments']);
631
632
		// Find all of this forum's administrators...
633
		if (listMembergroupMembers_Href($context['administrators'], 1, 32) && allowedTo('manage_membergroups'))
634
		{
635
			// Add a 'more'-link if there are more than 32.
636
			$context['more_admins_link'] = '<a href="' . getUrl('moderate', ['action' => 'moderate', 'area' => 'viewgroups', 'sa' => 'members', 'group' => 1]) . '">' . $txt['more'] . '</a>';
637
		}
638
639
		// This makes it easier to get the latest news with your time format.
640
		$context['time_format'] = urlencode($this->user->time_format);
0 ignored issues
show
It seems like $this->user->time_format can also be of type null; however, parameter $string of urlencode() does only seem to accept string, 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

640
		$context['time_format'] = urlencode(/** @scrutinizer ignore-type */ $this->user->time_format);
Loading history...
Bug Best Practice introduced by
The property time_format does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
641
		$context['forum_version'] = FORUM_VERSION;
642
643
		// Get a list of current server versions.
644
		$context['current_versions'] = getServerVersions($this->_checkFor);
645
		$context['can_admin'] = allowedTo('admin_forum');
646
		$context['sub_template'] = 'admin';
647
		$context['page_title'] = $txt['admin_center'];
648
		$context[$context['admin_menu_name']]['object']->prepareTabData([
649
			'title' => 'admin_center',
650
			'description' => '
651
				<span class="bbc_strong">' . $txt['hello_guest'] . ' ' . $context['user']['name'] . '!</span>
652
				' . sprintf($txt['admin_main_welcome'], $txt['admin_control_panel']),
653
		]);
654
655
		// Load in the admin quick tasks
656
		$context['quick_admin_tasks'] = getQuickAdminTasks();
657
	}
658
659
	/**
660
	 * The credits section in admin panel.
661
	 *
662
	 * What it does:
663
	 *
664
	 * - Determines the current level of support functions from the server, such as
665
	 * current level of caching engine or graphics library's installed.
666
	 * - Accessed by ?action=admin;area=credits
667
	 */
668
	public function action_credits(): void
669
	{
670
		global $txt, $context;
671
672
		// We need a little help from our friends
673
		require_once(SUBSDIR . '/Membergroups.subs.php');
674
		require_once(SUBSDIR . '/Who.subs.php');
675
		require_once(SUBSDIR . '/Admin.subs.php');
676
677
		// You have to be able to do at least one of the below to see this page.
678
		isAllowedTo(['admin_forum', 'manage_permissions', 'moderate_forum', 'manage_membergroups', 'manage_bans', 'send_mail', 'edit_news', 'manage_boards', 'manage_smileys', 'manage_attachments']);
679
680
		// Find all of this forum's administrators...
681
		if (listMembergroupMembers_Href($context['administrators'], 1, 32) && allowedTo('manage_membergroups'))
682
		{
683
			// Add a 'more'-link if there are more than 32.
684
			$context['more_admins_link'] = '<a href="' . getUrl('moderate', ['action' => 'moderate', 'area' => 'viewgroups', 'sa' => 'members', 'group' => 1]) . '">' . $txt['more'] . '</a>';
685
		}
686
687
		// Load credits.
688
		$context[$context['admin_menu_name']]['object']->prepareTabData([
689
			'title' => 'support_credits_title',
690
			'description' => 'support_credits_desc',
691
		]);
692
		Txt::load('About');
693
		require_once(SUBSDIR . '/About.subs.php');
694
		$context += prepareCreditsData();
695
696
		// This makes it easier to get the latest news with your time format.
697
		$context['time_format'] = urlencode($this->user->time_format);
0 ignored issues
show
Bug Best Practice introduced by
The property time_format does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
It seems like $this->user->time_format can also be of type null; however, parameter $string of urlencode() does only seem to accept string, 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

697
		$context['time_format'] = urlencode(/** @scrutinizer ignore-type */ $this->user->time_format);
Loading history...
698
		$context['forum_version'] = FORUM_VERSION;
699
700
		// Get a list of current server versions.
701
		$context['current_versions'] = getServerVersions($this->_checkFor);
702
		$context['can_admin'] = allowedTo('admin_forum');
703
		$context['sub_template'] = 'credits';
704
		$context['page_title'] = $txt['support_credits_title'];
705
706
		// Load in the admin quick tasks
707
		$context['quick_admin_tasks'] = getQuickAdminTasks();
708
709
		$index = 'new_in_' . str_replace(['ElkArte ', '.'], ['', '_'], FORUM_VERSION);
710
		if (isset($txt[$index]))
711
		{
712
			$context['latest_updates'] = replaceBasicActionUrl($txt[$index]);
713
			require_once(SUBSDIR . '/Themes.subs.php');
714
715
			updateThemeOptions([1, $this->user->id, 'dismissed_' . $index, 1]);
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
716
		}
717
	}
718
719
	/**
720
	 * This function allocates out all the search stuff.
721
	 *
722
	 * What it does:
723
	 *
724
	 * - Accessed with /index.php?action=admin;area=search[;search_type=x]
725
	 * - Sets up an array of applicable sub-actions (search types) and the function that goes with each
726
	 * - Search type specified by "search_type" request variable (either from a
727
	 * form or from the query string) Defaults to 'internal'
728
	 * - Calls the appropriate sub action based on the search_type
729
	 */
730
	public function action_search(): void
731
	{
732
		global $txt, $context;
733
734
		// What can we search for?
735
		$subActions = [
736
			'internal' => [$this, 'action_search_internal', 'permission' => 'admin_forum'],
737
			'online' => [$this, 'action_search_doc', 'permission' => 'admin_forum'],
738
			'member' => [$this, 'action_search_member', 'permission' => 'admin_forum'],
739
		];
740
741
		// Set the subaction
742
		$action = new Action('admin_search');
743
		$subAction = $action->initialize($subActions, 'internal');
744
745
		// Keep track of what the admin wants in terms of advanced or not
746
		if (empty($context['admin_preferences']['sb']) || $context['admin_preferences']['sb'] != $subAction)
747
		{
748
			$context['admin_preferences']['sb'] = $subAction;
749
750
			// Update the preferences.
751
			require_once(SUBSDIR . '/Admin.subs.php');
752
			updateAdminPreferences();
753
		}
754
755
		// Setup for the template
756
		$context['search_type'] = $subAction;
757
		$context['search_term'] = $this->_req->getPost('search_term', 'trim|\\ElkArte\\Helper\\Util::htmlspecialchars[ENT_QUOTES]');
758
		$context['sub_template'] = 'admin_search_results';
759
		$context['page_title'] = $txt['admin_search_results'];
760
761
		// You did remember to enter something to search for, otherwise its easy
762
		if ($context['search_term'] === '')
763
		{
764
			$context['search_results'] = [];
765
		}
766
		else
767
		{
768
			$action->dispatch($subAction);
769
		}
770
	}
771
772
	/**
773
	 * A complicated but relatively quick internal search.
774
	 *
775
	 * What it does:
776
	 *
777
	 * - Can be accessed with /index.php?action=admin;sa=search;search_term=x) or from the admin search form ("Task/Setting" option)
778
	 * - Polls the controllers for their configuration settings
779
	 * - Calls integrate_admin_search to allow addons to add search configs
780
	 * - Loads up the "Help" language file and all "Manage" language files
781
	 * - Loads up information about each item it found for the template
782
	 *
783
	 * @event integrate_admin_search Allows integration to add areas to the internal admin search
784
	 * @event search Allows active modules registered to search to add settings for internal search
785
	 */
786
	public function action_search_internal(): void
787
	{
788
		global $context, $txt;
789
790
		// Try to get some more memory.
791
		detectServer()->setMemoryLimit('128M');
792
793
		// Load a lot of language files.
794
		$language_files = [
795
			'Help', 'ManageMail', 'ManageSettings', 'ManageBoards', 'ManagePaid', 'ManagePermissions', 'Search',
796
			'Login', 'ManageSmileys', 'Maillist', 'Mentions', 'Addons'
797
		];
798
799
		// All the files we need to include to search for settings
800
		$include_files = [];
801
802
		// This is a special array of functions that contain setting data
803
		// - we query all these to simply pull all setting bits!
804
		$settings_search = [
805
			['settings_search', 'area=addonsettings;sa=general', AddonSettings::class],
806
			['settings_search', 'area=logs;sa=pruning', AdminLog::class],
807
			['config_vars', 'area=corefeatures', CoreFeatures::class],
808
			['settings_search', 'area=manageattachments;sa=attachments', ManageAttachments::class],
809
			['settings_search', 'area=manageattachments;sa=avatars', ManageAvatars::class],
810
			['settings_search', 'area=manageboards;sa=settings', ManageBoards::class],
811
			['settings_search', 'area=postsettings;sa=bbc', ManageEditor::class],
812
			['basicSettings_search', 'area=featuresettings;sa=basic', ManageFeatures::class],
813
			['layoutSettings_search', 'area=featuresettings;sa=layout', ManageFeatures::class],
814
			['karmaSettings_search', 'area=featuresettings;sa=karma', ManageFeatures::class],
815
			['signatureSettings_search', 'area=featuresettings;sa=pmsettings', ManageFeatures::class],
816
			['likesSettings_search', 'area=featuresettings;sa=likes', ManageFeatures::class],
817 2
			['mentionSettings_search', 'area=featuresettings;sa=mention', ManageFeatures::class],
818
			['signatureSettings_search', 'area=featuresettings;sa=sig', ManageFeatures::class],
819 2
			['settings_search', 'area=languages;sa=settings', ManageLanguages::class],
820
			['settings_search', 'area=mailqueue;sa=settings', ManageMail::class],
821
			['settings_search', 'area=maillist;sa=emailsettings', ManageMaillist::class],
822 2
			['filter_search', 'area=maillist;sa=emailsettings', ManageMaillist::class],
823
			['parser_search', 'area=maillist;sa=emailsettings', ManageMaillist::class],
824
			['settings_search', 'area=membergroups;sa=settings', ManageMembergroups::class],
825
			['settings_search', 'area=news;sa=settings', ManageNews::class],
826 2
			['settings_search', 'area=paidsubscribe;sa=settings', ManagePaid::class],
827
			['settings_search', 'area=permissions;sa=settings', ManagePermissions::class],
828
			['settings_search', 'area=postsettings;sa=posts', ManagePosts::class],
829
			['settings_search', 'area=regcenter;sa=settings', ManageRegistration::class],
830
			['settings_search', 'area=managesearch;sa=settings', ManageSearch::class],
831 2
			['settings_search', 'area=sengines;sa=settings', ManageSearchEngines::class],
832
			['securitySettings_search', 'area=securitysettings;sa=general', ManageSecurity::class],
833
			['spamSettings_search', 'area=securitysettings;sa=spam', ManageSecurity::class],
834
			['moderationSettings_search', 'area=securitysettings;sa=moderation', ManageSecurity::class],
835
			['generalSettings_search', 'area=serversettings;sa=general', ManageServer::class],
836 2
			['databaseSettings_search', 'area=serversettings;sa=database', ManageServer::class],
837
			['cookieSettings_search', 'area=serversettings;sa=cookie', ManageServer::class],
838
			['cacheSettings_search', 'area=serversettings;sa=cache', ManageServer::class],
839
			['balancingSettings_search', 'area=serversettings;sa=loads', ManageServer::class],
840
			['settings_search', 'area=smileys;sa=settings', ManageSmileys::class],
841
			['settings_search', 'area=postsettings;sa=topics', ManageTopics::class],
842
		];
843
844
		// Allow integration to add settings to search
845
		call_integration_hook('integrate_admin_search', [&$language_files, &$include_files, &$settings_search]);
846
847
		// Allow active modules to add settings for internal search
848
		$this->_events->trigger('addSearch', ['language_files' => &$language_files, 'include_files' => &$include_files, 'settings_search' => &$settings_search]);
849
850
		// Go through all the search data trying to find this text!
851
		$context['search_results'] = [];
852
		if (isset($context['search_term']))
853
		{
854
			$search_term = strtolower(un_htmlspecialchars($context['search_term']));
855
			$search = new AdminSettingsSearch($language_files, $include_files, $settings_search);
856
			$search->initSearch($context['admin_menu_name'], [
857
				['COPPA', 'area=regcenter;sa=settings'],
858
				['CAPTCHA', 'area=securitysettings;sa=spam'],
859
			]);
860
			$context['search_results'] = $search->doSearch($search_term);
861
		}
862
863
		$context['page_title'] = $txt['admin_search_results'];
864
	}
865
866
	/**
867
	 * All this does is pass through to manage members.
868
	 */
869
	public function action_search_member(): void
870
	{
871
		global $context;
872
873
		// @todo once Action.class is changed
874 2
		$_REQUEST['sa'] = 'query';
875
876
		// Set the query values
877 2
		$this->_req->post->sa = 'query';
878
		$this->_req->post->membername = un_htmlspecialchars($context['search_term']);
879
		$this->_req->post->types = '';
880 2
881 2
		$manageMembers = new ManageMembers(new EventManager());
882 2
		$manageMembers->setUser(User::$info);
883 2
		$manageMembers->pre_dispatch();
884
		$manageMembers->action_index();
885
	}
886
887 2
	/**
888 2
	 * This file allows the user to search the wiki documentation for a little help.
889 2
	 *
890
	 * What it does:
891
	 *   - Creates an exception since GitHub does not yet support API wiki searches so the connection
892
	 * will fail.
893
	 */
894
	public function action_search_doc(): void
895
	{
896
		global $context;
897
898
		$context['doc_apiurl'] = 'https://github.com/elkarte/Elkarte/wiki/api.php';
899
		$context['doc_scripturl'] = 'https://github.com/elkarte/Elkarte/wiki/';
900
901
		// Set all the parameters search might expect.
902
		$postVars = explode(' ', $context['search_term']);
903
904
		// Encode the search data.
905
		foreach ($postVars as $k => $v)
906
		{
907
			$postVars[$k] = urlencode($v);
908
		}
909
910
		// This is what we will send.
911
		$postVars = implode('+', $postVars);
912
913
		// Get the results from the doc site.
914
		require_once(SUBSDIR . '/Package.subs.php');
915
		// Demo URL:
916
		// https://github.com/elkarte/Elkarte/wiki/api.php?action=query&list=search&srprop=timestamp|snippet&format=xml&srwhat=text&srsearch=template+eval
917
		$search_results = fetch_web_data($context['doc_apiurl'] . '?action=query&list=search&srprop=timestamp|snippet&format=xml&srwhat=text&srsearch=' . $postVars);
918
919
		// If we didn't get any xml back we are in trouble - perhaps the doc site is overloaded?
920
		if (!$search_results || preg_match('~<\?xml\sversion="\d+\.\d+"\?>\s*(<api>.+?</api>)~is', $search_results, $matches) !== 1)
921
		{
922
			throw new Exception('cannot_connect_doc_site');
923
		}
924
925
		$search_results = empty($matches[1]) ? '' : $matches[1];
926
927
		// Otherwise we simply walk through the XML and stick it in context for display.
928
		$context['search_results'] = [];
929
930
		// Get the results loaded into an array for processing!
931
		$results = new XmlArray($search_results, false);
932
933
		// Move through the api layer.
934
		if (!$results->exists('api'))
935
		{
936
			throw new Exception('cannot_connect_doc_site');
937
		}
938
939
		// Are there actually some results?
940
		if ($results->exists('api/query/search/p'))
941
		{
942
			$relevance = 0;
943
			foreach ($results->set('api/query/search/p') as $result)
944
			{
945
				$title = $result->fetch('@title');
946
				$context['search_results'][$title] = [
947
					'title' => $title,
948
					'relevance' => $relevance++,
949
					'snippet' => str_replace("class='searchmatch'", 'class="highlight"', un_htmlspecialchars($result->fetch('@snippet'))),
950
				];
951
			}
952
		}
953
	}
954
955
	/**
956
	 * This ends a admin session, requiring authentication to access the ACP again.
957
	 */
958
	public function action_endsession(): void
959
	{
960
		// This is so easy!
961
		unset($_SESSION['admin_time']);
962
963
		// Clean any admin tokens as well.
964
		cleanTokens(false, '-admin');
965
966
		if (isset($this->_req->query->redir, $_SERVER['HTTP_REFERER']))
967
		{
968
			redirectexit($_SERVER['HTTP_REFERER']);
969
		}
970
971
		redirectexit();
972
	}
973
}
974