Passed
Push — master ( c0a3a7...3b84a4 )
by Jeroen
58:51
created

engine/lib/admin.php (1 issue)

1
<?php
2
/**
3
 * Elgg admin functions.
4
 *
5
 * Admin pages
6
 * Plugins no not need to provide their own page handler to add a page to the
7
 * admin area. A view placed at admin/<section>/<subsection> can be access
8
 * at http://example.org/admin/<section>/<subsection>. The title of the page
9
 * will be elgg_echo('admin:<section>:<subsection>'). For an example of how to
10
 * add a page to the admin area, see the diagnostics plugin.
11
 *
12
 * Admin notices
13
 * System messages (success and error messages) are used in both the main site
14
 * and the admin area. There is a special presistent message for the admin area
15
 * called an admin notice. It should be used when a plugin requires an
16
 * administrator to take an action. @see elgg_add_admin_notice()
17
 *
18
 *
19
 * @package Elgg.Core
20
 * @subpackage Admin
21
 */
22
23
/**
24
 * Get the admin users
25
 *
26
 * @param array $options Options array, @see elgg_get_entities() for parameters
27
 *
28
 * @return mixed Array of admin users or false on failure. If a count, returns int.
29
 * @since 1.8.0
30
 */
31
function elgg_get_admins(array $options = []) {
32 311
	$options['type'] = 'user';
33 311
	$options['metadata_name_value_pairs'] = elgg_extract('metadata_name_value_pairs', $options, []);
34
	
35 311
	$options['metadata_name_value_pairs']['admin'] = 'yes';
36
37 311
	return elgg_get_entities($options);
38
}
39
40
/**
41
 * Write a persistent message to the admin view.
42
 * Useful to alert the admin to take a certain action.
43
 * The id is a unique ID that can be cleared once the admin
44
 * completes the action.
45
 *
46
 * eg: add_admin_notice('twitter_services_no_api',
47
 * 	'Before your users can use Twitter services on this site, you must set up
48
 * 	the Twitter API key in the <a href="link">Twitter Services Settings</a>');
49
 *
50
 * @param string $id      A unique ID that your plugin can remember
51
 * @param string $message Body of the message
52
 *
53
 * @return ElggObject|bool
54
 * @since 1.8.0
55
 */
56
function elgg_add_admin_notice($id, $message) {
57 2
	return _elgg_services()->adminNotices->add($id, $message);
58
}
59
60
/**
61
 * Remove an admin notice by ID.
62
 *
63
 * @param string $id The unique ID assigned in add_admin_notice()
64
 *
65
 * @return bool
66
 * @since 1.8.0
67
 */
68
function elgg_delete_admin_notice($id) {
69 1
	return _elgg_services()->adminNotices->delete($id);
70
}
71
72
/**
73
 * Get admin notices. An admin must be logged in since the notices are private.
74
 *
75
 * @param array $options Query options
76
 *
77
 * @return ElggObject[] Admin notices
78
 * @since 1.8.0
79
 */
80
function elgg_get_admin_notices(array $options = []) {
81 1
	return _elgg_services()->adminNotices->find($options);
82
}
83
84
/**
85
 * Check if an admin notice is currently active. (Ignores access)
86
 *
87
 * @param string $id The unique ID used to register the notice.
88
 *
89
 * @return bool
90
 * @since 1.8.0
91
 */
92
function elgg_admin_notice_exists($id) {
93 2
	return _elgg_services()->adminNotices->exists($id);
94
}
95
96
/**
97
 * Add an admin notice when a new \ElggUpgrade object is created.
98
 *
99
 * @param string      $event  'create'
100
 * @param string      $type   'object'
101
 * @param \ElggObject $object the created object
102
 *
103
 * @return void
104
 *
105
 * @access private
106
 */
107
function _elgg_create_notice_of_pending_upgrade($event, $type, $object) {
108 199
	if (!$object instanceof \ElggUpgrade) {
109 199
		return;
110
	}
111
	
112
	// Link to the Upgrades section
113
	$link = elgg_view('output/url', [
114
		'href' => 'admin/upgrades',
115
		'text' => elgg_echo('admin:view_upgrades'),
116
	]);
117
118
	$message = elgg_echo('admin:pending_upgrades');
119
120
	elgg_add_admin_notice('pending_upgrades', "$message $link");
121
}
122
123
/**
124
 * Initialize the admin backend.
125
 * @return void
126
 * @access private
127
 */
128
function _elgg_admin_init() {
129
130 31
	elgg_register_css('elgg.admin', elgg_get_simplecache_url('admin.css'));
131
132 31
	elgg_extend_view('admin.css', 'lightbox/elgg-colorbox-theme/colorbox.css');
133
		
134 31
	elgg_register_plugin_hook_handler('register', 'menu:admin_header', '_elgg_admin_header_menu');
135 31
	elgg_register_plugin_hook_handler('register', 'menu:admin_footer', '_elgg_admin_footer_menu');
136 31
	elgg_register_plugin_hook_handler('register', 'menu:page', '_elgg_admin_page_menu');
137 31
	elgg_register_plugin_hook_handler('register', 'menu:page', '_elgg_admin_page_menu_plugin_settings');
138
139
	// maintenance mode
140 31
	if (elgg_get_config('elgg_maintenance_mode', null)) {
141
		elgg_register_plugin_hook_handler('route', 'all', '_elgg_admin_maintenance_handler', 600);
142
		elgg_register_plugin_hook_handler('action', 'all', '_elgg_admin_maintenance_action_check', 600);
143
		elgg_register_css('maintenance', elgg_get_simplecache_url('maintenance.css'));
144
145
		elgg_register_menu_item('topbar', [
146
			'name' => 'maintenance_mode',
147
			'href' => 'admin/configure_utilities/maintenance',
148
			'text' => elgg_echo('admin:maintenance_mode:indicator_menu_item'),
149
			'icon' => 'wrench',
150
			'priority' => 900,
151
		]);
152
	}
153
154 31
	elgg_register_action('admin/user/ban', '', 'admin');
155 31
	elgg_register_action('admin/user/unban', '', 'admin');
156 31
	elgg_register_action('admin/user/delete', '', 'admin');
157 31
	elgg_register_action('admin/user/resetpassword', '', 'admin');
158 31
	elgg_register_action('admin/user/makeadmin', '', 'admin');
159 31
	elgg_register_action('admin/user/removeadmin', '', 'admin');
160
161 31
	elgg_register_action('admin/site/update_basic', '', 'admin');
162 31
	elgg_register_action('admin/site/update_advanced', '', 'admin');
163 31
	elgg_register_action('admin/site/flush_cache', '', 'admin');
164 31
	elgg_register_action('admin/site/unlock_upgrade', '', 'admin');
165 31
	elgg_register_action('admin/site/set_robots', '', 'admin');
166 31
	elgg_register_action('admin/site/set_maintenance_mode', '', 'admin');
167
168 31
	elgg_register_action('admin/upgrades/upgrade_database_guid_columns', '', 'admin');
169 31
	elgg_register_action('admin/upgrade', '', 'admin');
170
171 31
	elgg_register_action('admin/menu/save', '', 'admin');
172
173 31
	elgg_register_action('admin/delete_admin_notice', '', 'admin');
174 31
	elgg_register_action('admin/delete_admin_notices', '', 'admin');
175
	
176 31
	elgg_register_action('admin/security/settings', '', 'admin');
177 31
	elgg_register_action('admin/security/regenerate_site_secret', '', 'admin');
178
	
179 31
	elgg_register_simplecache_view('admin.css');
180
181
	// widgets
182 31
	$widgets = ['online_users', 'new_users', 'content_stats', 'banned_users', 'admin_welcome', 'control_panel', 'cron_status'];
183 31
	foreach ($widgets as $widget) {
184 31
		elgg_register_widget_type(
185 31
				$widget,
186 31
				elgg_echo("admin:widget:$widget"),
187 31
				elgg_echo("admin:widget:$widget:help"),
188 31
				['admin']
189
		);
190
	}
191
192
	// automatic adding of widgets for admin
193 31
	elgg_register_event_handler('make_admin', 'user', '_elgg_add_admin_widgets');
194
	
195 31
	elgg_register_notification_event('user', '', ['make_admin', 'remove_admin']);
196 31
	elgg_register_plugin_hook_handler('get', 'subscriptions', '_elgg_admin_get_admin_subscribers_admin_action');
197 31
	elgg_register_plugin_hook_handler('get', 'subscriptions', '_elgg_admin_get_user_subscriber_admin_action');
198 31
	elgg_register_plugin_hook_handler('prepare', 'notification:make_admin:user:', '_elgg_admin_prepare_admin_notification_make_admin');
199 31
	elgg_register_plugin_hook_handler('prepare', 'notification:make_admin:user:', '_elgg_admin_prepare_user_notification_make_admin');
200 31
	elgg_register_plugin_hook_handler('prepare', 'notification:remove_admin:user:', '_elgg_admin_prepare_admin_notification_remove_admin');
201 31
	elgg_register_plugin_hook_handler('prepare', 'notification:remove_admin:user:', '_elgg_admin_prepare_user_notification_remove_admin');
202
	
203
	// Add notice about pending upgrades
204 31
	elgg_register_event_handler('create', 'object', '_elgg_create_notice_of_pending_upgrade');
205
206 31
	elgg_register_page_handler('admin', '_elgg_admin_page_handler');
207 31
	elgg_register_page_handler('admin_plugin_text_file', '_elgg_admin_markdown_page_handler');
208 31
	elgg_register_page_handler('robots.txt', '_elgg_robots_page_handler');
209 31
	elgg_register_page_handler('phpinfo', '_elgg_phpinfo_page_handler');
210 31
	elgg_register_page_handler('admin_plugins_refresh', '_elgg_ajax_plugins_update');
211 31
}
212
213
/**
214
 * Returns plugin listing and admin menu to the client (used after plugin (de)activation)
215
 *
216
 * @access private
217
 * @return Elgg\Http\OkResponse
218
 */
219
function _elgg_ajax_plugins_update() {
220
	elgg_admin_gatekeeper();
221
	elgg_set_context('admin');
222
223
	return elgg_ok_response([
224
		'list' => elgg_view('admin/plugins', ['list_only' => true]),
225
		'sidebar' => elgg_view('admin/sidebar'),
226
	]);
227
}
228
229
/**
230
 * Register menu items for the admin_header menu
231
 *
232
 * @param string          $hook   'register'
233
 * @param string          $type   'menu:admin_header'
234
 * @param \ElggMenuItem[] $return current return value
235
 * @param array           $params supplied params
236
 *
237
 * @return void|\ElggMenuItem
238
 *
239
 * @access private
240
 * @since 3.0
241
 */
242
function _elgg_admin_header_menu($hook, $type, $return, $params) {
243
	if (!elgg_in_context('admin') || !elgg_is_admin_logged_in()) {
244
		return;
245
	}
246
247
	$admin = elgg_get_logged_in_user_entity();
248
249
	$return[] = \ElggMenuItem::factory([
250
		'name' => 'account',
251
		'text' => $admin->getDisplayName(),
252
		'href' => $admin->getURL(),
253
		'icon' => elgg_view('output/img', [
254
			'src' => $admin->getIconURL('small'),
255
			'alt' => $admin->getDisplayName(),
256
		]),
257
		'priority' => 1000,
258
	]);
259
260
	$return[] = \ElggMenuItem::factory([
261
		'name' => 'admin_logout',
262
		'href' => 'action/logout',
263
		'text' => elgg_echo('logout'),
264
		'priority' => 900,
265
	]);
266
267
	$return[] = \ElggMenuItem::factory([
268
		'name' => 'view_site',
269
		'href' => elgg_get_site_url(),
270
		'text' => elgg_echo('admin:view_site'),
271
		'priority' => 800,
272
	]);
273
274
	if (elgg_get_config('elgg_maintenance_mode')) {
275
		$return[] = \ElggMenuItem::factory([
276
			'name' => 'maintenance',
277
			'href' => 'admin/configure_utilities/maintenance',
278
			'text' => elgg_echo('admin:configure_utilities:maintenance'),
279
			'link_class' => 'elgg-maintenance-mode-warning',
280
			'priority' => 700,
281
		]);
282
	}
283
	
284
	return $return;
285
}
286
287
/**
288
 * Register menu items for the admin_footer menu
289
 *
290
 * @param string          $hook   'register'
291
 * @param string          $type   'menu:admin_footer'
292
 * @param \ElggMenuItem[] $return current return value
293
 * @param array           $params supplied params
294
 *
295
 * @return void|\ElggMenuItem[]
296
 *
297
 * @access private
298
 * @since 3.0
299
 */
300
function _elgg_admin_footer_menu($hook, $type, $return, $params) {
301
	if (!elgg_in_context('admin') || !elgg_is_admin_logged_in()) {
302
		return;
303
	}
304
305
	$return[] = \ElggMenuItem::factory([
306
		'name' => 'faq',
307
		'text' => elgg_echo('admin:footer:faq'),
308
		'href' => 'http://learn.elgg.org/en/stable/appendix/faqs.html',
309
	]);
310
311
	$return[] = \ElggMenuItem::factory([
312
		'name' => 'manual',
313
		'text' => elgg_echo('admin:footer:manual'),
314
		'href' => 'http://learn.elgg.org/en/stable/admin/index.html',
315
	]);
316
317
	$return[] = \ElggMenuItem::factory([
318
		'name' => 'community_forums',
319
		'text' => elgg_echo('admin:footer:community_forums'),
320
		'href' => 'http://elgg.org/groups/all/',
321
	]);
322
323
	$return[] = \ElggMenuItem::factory([
324
		'name' => 'blog',
325
		'text' => elgg_echo('admin:footer:blog'),
326
		'href' => 'https://elgg.org/blog/all',
327
	]);
328
	
329
	return $return;
330
}
331
332
/**
333
 * Register menu items for the page menu
334
 *
335
 * @param \Elgg\Hook $hook 'register' 'menu:page'
336
 * @return array
337
 *
338
 * @access private
339
 * @see _elgg_default_widgets_init() for default widgets menu items setup
340
 * @since 3.0
341
 */
342
function _elgg_admin_page_menu(\Elgg\Hook $hook) {
343 1
	if (!elgg_in_context('admin') || !elgg_is_admin_logged_in()) {
344 1
		return;
345
	}
346
	
347
	$return = $hook->getValue();
348
349
	// administer
350
	$return[] = \ElggMenuItem::factory([
351
		'name' => 'dashboard',
352
		'href' => 'admin',
353
		'text' => elgg_echo('admin:dashboard'),
354
		'priority' => 10,
355
		'section' => 'administer',
356
	]);
357
	
358
	$return[] = \ElggMenuItem::factory([
359
		'name' => 'plugins',
360
		'href' => 'admin/plugins',
361
		'text' => elgg_echo('admin:plugins'),
362
		'priority' => 30,
363
		'section' => 'administer',
364
	]);
365
366
	$return[] = \ElggMenuItem::factory([
367
		'name' => 'users',
368
		'text' => elgg_echo('admin:users'),
369
		'priority' => 40,
370
		'section' => 'administer',
371
	]);
372
	$return[] = \ElggMenuItem::factory([
373
		'name' => 'users:online',
374
		'text' => elgg_echo('admin:users:online'),
375
		'href' => 'admin/users/online',
376
		'priority' => 10,
377
		'section' => 'administer',
378
		'parent_name' => 'users',
379
	]);
380
	$return[] = \ElggMenuItem::factory([
381
		'name' => 'users:admins',
382
		'text' => elgg_echo('admin:users:admins'),
383
		'href' => 'admin/users/admins',
384
		'priority' => 20,
385
		'section' => 'administer',
386
		'parent_name' => 'users',
387
	]);
388
	$return[] = \ElggMenuItem::factory([
389
		'name' => 'users:newest',
390
		'text' => elgg_echo('admin:users:newest'),
391
		'href' => 'admin/users/newest',
392
		'priority' => 30,
393
		'section' => 'administer',
394
		'parent_name' => 'users',
395
	]);
396
	$return[] = \ElggMenuItem::factory([
397
		'name' => 'users:add',
398
		'text' => elgg_echo('admin:users:add'),
399
		'href' => 'admin/users/add',
400
		'priority' => 40,
401
		'section' => 'administer',
402
		'parent_name' => 'users',
403
	]);
404
	$return[] = \ElggMenuItem::factory([
405
		'name' => 'upgrades',
406
		'href' => 'admin/upgrades',
407
		'text' => elgg_echo('admin:upgrades'),
408
		'priority' => 600,
409
		'section' => 'administer',
410
	]);
411
	
412
	$return[] = \ElggMenuItem::factory([
413
		'name' => 'administer_utilities',
414
		'text' => elgg_echo('admin:administer_utilities'),
415
		'priority' => 50,
416
		'section' => 'administer',
417
	]);
418
	
419
	// configure
420
	$return[] = \ElggMenuItem::factory([
421
		'name' => 'settings:basic',
422
		'href' => 'admin/settings/basic',
423
		'text' => elgg_echo('admin:settings:basic'),
424
		'priority' => 10,
425
		'section' => 'configure',
426
	]);
427
	$return[] = \ElggMenuItem::factory([
428
		'name' => 'settings:advanced',
429
		'href' => 'admin/settings/advanced',
430
		'text' => elgg_echo('admin:settings:advanced'),
431
		'priority' => 20,
432
		'section' => 'configure',
433
	]);
434
	$return[] = \ElggMenuItem::factory([
435
		'name' => 'security',
436
		'href' => 'admin/security',
437
		'text' => elgg_echo('admin:security'),
438
		'priority' => 30,
439
		'section' => 'configure',
440
	]);
441
442
	$return[] = \ElggMenuItem::factory([
443
		'name' => 'configure_utilities',
444
		'text' => elgg_echo('admin:configure_utilities'),
445
		'priority' => 600,
446
		'section' => 'configure',
447
	]);
448
	$return[] = \ElggMenuItem::factory([
449
		'name' => 'configure_utilities:maintenance',
450
		'text' => elgg_echo('admin:configure_utilities:maintenance'),
451
		'href' => 'admin/configure_utilities/maintenance',
452
		'section' => 'configure',
453
		'parent_name' => 'configure_utilities',
454
	]);
455
	$return[] = \ElggMenuItem::factory([
456
		'name' => 'configure_utilities:menu_items',
457
		'text' => elgg_echo('admin:configure_utilities:menu_items'),
458
		'href' => 'admin/configure_utilities/menu_items',
459
		'section' => 'configure',
460
		'parent_name' => 'configure_utilities',
461
	]);
462
	$return[] = \ElggMenuItem::factory([
463
		'name' => 'configure_utilities:robots',
464
		'text' => elgg_echo('admin:configure_utilities:robots'),
465
		'href' => 'admin/configure_utilities/robots',
466
		'section' => 'configure',
467
		'parent_name' => 'configure_utilities',
468
	]);
469
	
470
	// information
471
	$return[] = \ElggMenuItem::factory([
472
		'name' => 'statistics',
473
		'href' => 'admin/statistics',
474
		'text' => elgg_echo('admin:statistics'),
475
		'section' => 'information',
476
	]);
477
	$return[] = \ElggMenuItem::factory([
478
		'name' => 'server',
479
		'href' => 'admin/server',
480
		'text' => elgg_echo('admin:server'),
481
		'section' => 'information',
482
	]);
483
		
484
	return $return;
485
}
486
487
/**
488
 * Register plugin settings menu items for the admin page menu
489
 *
490
 * @note Plugin settings are alphabetically sorted in the submenu
491
 *
492
 * @param \Elgg\Hook $hook 'register' 'menu:page'
493
 * @return array
494
 *
495
 * @access private
496
 * @since 3.0
497
 */
498
function _elgg_admin_page_menu_plugin_settings(\Elgg\Hook $hook) {
499 1
	if (!elgg_in_context('admin') || !elgg_is_admin_logged_in()) {
500 1
		return;
501
	}
502
	
503
	// plugin settings
504
	$active_plugins = elgg_get_plugins('active');
505
	if (!$active_plugins) {
506
		// nothing added because no items
507
		return;
508
	}
509
	
510
	$plugins_with_settings = [];
511
	
512
	foreach ($active_plugins as $plugin) {
513
		$plugin_id = $plugin->getID();
514
		
515
		if (!elgg_view_exists("plugins/{$plugin_id}/settings") ) {
516
			continue;
517
		}
518
		$plugin_name = $plugin->getDisplayName();
519
		$plugins_with_settings[$plugin_name] = [
520
			'name' => $plugin_id,
521
			'href' => "admin/plugin_settings/$plugin_id",
522
			'text' => $plugin_name,
523
			'parent_name' => 'plugin_settings',
524
			'section' => 'configure',
525
		];
526
	}
527
	
528
	if (empty($plugins_with_settings)) {
529
		return;
530
	}
531
532
	$return = $hook->getValue();
533
	
534
	$return[] = \ElggMenuItem::factory([
535
		'name' => 'plugin_settings',
536
		'text' => elgg_echo('admin:plugin_settings'),
537
		'section' => 'configure',
538
	]);
539
	
540
	ksort($plugins_with_settings);
541
	$priority = 0;
542
	foreach ($plugins_with_settings as $plugin_item) {
543
		$priority += 10;
544
		$plugin_item['priority'] = $priority;
545
		$return[] = \ElggMenuItem::factory($plugin_item);
546
	}
547
	
548
	return $return;
549
}
550
551
/**
552
 * Handle admin pages.  Expects corresponding views as admin/section/subsection
553
 *
554
 * @param array $page Array of pages
555
 *
556
 * @return bool
557
 * @access private
558
 */
559
function _elgg_admin_page_handler($page) {
560
	elgg_admin_gatekeeper();
561
	elgg_set_context('admin');
562
563
	elgg_unregister_css('elgg');
564
	elgg_require_js('elgg/admin');
565
566
	// default to dashboard
567
	if (!isset($page[0]) || empty($page[0])) {
568
		$page = ['dashboard'];
569
	}
570
571
	// was going to fix this in the page_handler() function but
572
	// it's commented to explicitly return a string if there's a trailing /
573
	if (empty($page[count($page) - 1])) {
574
		array_pop($page);
575
	}
576
577
	$vars = ['page' => $page];
578
579
	// special page for plugin settings since we create the form for them
580
	if ($page[0] == 'plugin_settings') {
581
		if (isset($page[1]) && (elgg_view_exists("plugins/{$page[1]}/settings"))) {
582
			$view = 'admin/plugin_settings';
583
			$plugin = elgg_get_plugin_from_id($page[1]);
584
			$vars['plugin'] = $plugin;
585
586
			$title = elgg_echo("admin:{$page[0]}");
587
		} else {
588
			forward('', '404');
589
		}
590
	} else {
591
		$view = 'admin/' . implode('/', $page);
592
		$title = elgg_echo("admin:{$page[0]}");
593
		if (count($page) > 1) {
594
			$title .= ' : ' . elgg_echo('admin:' .  implode(':', $page));
595
		}
596
	}
597
598
	// gets content and prevents direct access to 'components' views
599
	if ($page[0] == 'components' || !($content = elgg_view($view, $vars))) {
600
		$title = elgg_echo('admin:unknown_section');
601
		$content = elgg_echo('admin:unknown_section');
602
	}
603
604
	$body = elgg_view_layout('admin', ['content' => $content, 'title' => $title]);
1 ignored issue
show
Comprehensibility Best Practice introduced by Ismayil Khayredinov
The variable $title does not seem to be defined for all execution paths leading up to this point.
Loading history...
605
	echo elgg_view_page($title, $body, 'admin');
606
	return true;
607
}
608
609
/**
610
 * Formats and serves out markdown files from plugins.
611
 *
612
 * URLs in format like admin_plugin_text_file/<plugin_id>/filename.ext
613
 *
614
 * The only valid files are:
615
 *	* README.txt
616
 *	* CHANGES.txt
617
 *	* INSTALL.txt
618
 *	* COPYRIGHT.txt
619
 *	* LICENSE.txt
620
 *
621
 * @param array $pages URL segments
622
 * @return bool
623
 * @access private
624
 */
625
function _elgg_admin_markdown_page_handler($pages) {
626
	elgg_set_context('admin');
627
628
	echo elgg_view_resource('admin/plugin_text_file', [
629
		'plugin_id' => elgg_extract(0, $pages),
630
		'filename' => elgg_extract(1, $pages),
631
	]);
632
	return true;
633
}
634
635
/**
636
 * Handle request for robots.txt
637
 *
638
 * @return true
639
 *
640
 * @access private
641
 */
642
function _elgg_robots_page_handler() {
643
	echo elgg_view_resource('robots.txt');
644
	return true;
645
}
646
647
/**
648
 * Handle request for phpinfo
649
 *
650
 * @return true
651
 *
652
 * @access private
653
 */
654
function _elgg_phpinfo_page_handler() {
655
	echo elgg_view_resource('phpinfo');
656
	return true;
657
}
658
659
/**
660
 * When in maintenance mode, should the given URL be handled normally?
661
 *
662
 * @param string $current_url Current page URL
663
 * @return bool
664
 *
665
 * @access private
666
 */
667
function _elgg_admin_maintenance_allow_url($current_url) {
668
	$site_path = preg_replace('~^https?~', '', elgg_get_site_url());
669
	$current_path = preg_replace('~^https?~', '', $current_url);
670
	if (0 === strpos($current_path, $site_path)) {
671
		$current_path = ($current_path === $site_path) ? '' : substr($current_path, strlen($site_path));
672
	} else {
673
		$current_path = false;
674
	}
675
676
	// allow plugins to control access for specific URLs/paths
677
	$params = [
678
		'current_path' => $current_path,
679
		'current_url' => $current_url,
680
	];
681
	return (bool) elgg_trigger_plugin_hook('maintenance:allow', 'url', $params, false);
682
}
683
684
/**
685
 * Handle requests when in maintenance mode
686
 *
687
 * @param string $hook 'route'
688
 * @param string $type 'all'
689
 * @param array  $info current return value
690
 *
691
 * @return void|false
692
 *
693
 * @access private
694
 */
695
function _elgg_admin_maintenance_handler($hook, $type, $info) {
696
	if (elgg_is_admin_logged_in()) {
697
		return;
698
	}
699
700
	if ($info['identifier'] == 'action' && $info['segments'][0] == 'login') {
701
		return;
702
	}
703
704
	if (_elgg_admin_maintenance_allow_url(current_page_url())) {
705
		return;
706
	}
707
708
	elgg_unregister_plugin_hook_handler('register', 'menu:login', '_elgg_login_menu_setup');
709
710
	echo elgg_view_resource('maintenance');
711
712
	return false;
713
}
714
715
/**
716
 * Prevent non-admins from using actions
717
 *
718
 * @access private
719
 *
720
 * @param string $hook Hook name
721
 * @param string $type Action name
722
 * @return bool
723
 */
724
function _elgg_admin_maintenance_action_check($hook, $type) {
725
	if (elgg_is_admin_logged_in()) {
726
		return true;
727
	}
728
729
	if ($type == 'login') {
730
		$username = get_input('username');
731
732
		$user = get_user_by_username($username);
733
734
		if (!$user) {
735
			$users = get_user_by_email($username);
736
			if ($users) {
737
				$user = $users[0];
738
			}
739
		}
740
741
		if ($user && $user->isAdmin()) {
742
			return true;
743
		}
744
	}
745
746
	if (_elgg_admin_maintenance_allow_url(current_page_url())) {
747
		return true;
748
	}
749
750
	register_error(elgg_echo('actionunauthorized'));
751
752
	return false;
753
}
754
755
/**
756
 * Adds default admin widgets to the admin dashboard.
757
 *
758
 * @param string    $event 'make_admin'
759
 * @param string    $type  'user'
760
 * @param \ElggUser $user  affected user
761
 *
762
 * @return void
763
 * @access private
764
 */
765
function _elgg_add_admin_widgets($event, $type, $user) {
766 6
	$ia = elgg_set_ignore_access(true);
767
768
	// check if the user already has widgets
769 6
	if (elgg_get_widgets($user->getGUID(), 'admin')) {
770
		elgg_set_ignore_access($ia);
771
		return;
772
	}
773
774
	// In the form column => array of handlers in order, top to bottom
775
	$adminWidgets = [
776 6
		1 => ['control_panel', 'admin_welcome'],
777
		2 => ['online_users', 'new_users', 'content_stats'],
778
	];
779
780 6
	foreach ($adminWidgets as $column => $handlers) {
781 6
		foreach ($handlers as $position => $handler) {
782 6
			$guid = elgg_create_widget($user->getGUID(), $handler, 'admin');
783 6
			if ($guid) {
784 6
				$widget = get_entity($guid);
785
				/* @var \ElggWidget $widget */
786 6
				$widget->move($column, $position);
787
			}
788
		}
789
	}
790
	
791 6
	elgg_set_ignore_access($ia);
792 6
}
793
794
/**
795
 * Add the current site admins to the subscribers when making/removing an admin user
796
 *
797
 * @param string $hook         'get'
798
 * @param string $type         'subscribers'
799
 * @param array  $return_value current subscribers
800
 * @param array  $params       supplied params
801
 *
802
 * @return void|array
803
 */
804
function _elgg_admin_get_admin_subscribers_admin_action($hook, $type, $return_value, $params) {
805
	
806 2
	if (!_elgg_config()->security_notify_admins) {
807
		return;
808
	}
809
	
810 2
	$event = elgg_extract('event', $params);
811 2
	if (!($event instanceof \Elgg\Notifications\Event)) {
812 2
		return;
813
	}
814
	
815
	if (!in_array($event->getAction(), ['make_admin', 'remove_admin'])) {
816
		return;
817
	}
818
	
819
	$user = $event->getObject();
820
	if (!($user instanceof \ElggUser)) {
821
		return;
822
	}
823
	
824
	/* @var $admin_batch \Elgg\BatchResult */
825
	$admin_batch = elgg_get_admins([
826
		'limit' => false,
827
		'wheres' => [
828
			"e.guid <> {$user->getGUID()}",
829
		],
830
		'batch' => true,
831
	]);
832
	
833
	/* @var $admin \ElggUser */
834
	foreach ($admin_batch as $admin) {
835
		$return_value[$admin->getGUID()] = ['email'];
836
	}
837
	
838
	return $return_value;
839
}
840
841
/**
842
 * Prepare the notification content for site admins about making a site admin
843
 *
844
 * @param string                           $hook         'prepare'
845
 * @param string                           $type         'notification:make_admin:user:'
846
 * @param \Elgg\Notifications\Notification $return_value current notification content
847
 * @param array                            $params       supplied params
848
 *
849
 * @return void|\Elgg\Notifications\Notification
850
 */
851
function _elgg_admin_prepare_admin_notification_make_admin($hook, $type, $return_value, $params) {
852
	
853
	if (!($return_value instanceof \Elgg\Notifications\Notification)) {
854
		return;
855
	}
856
	
857
	$recipient = elgg_extract('recipient', $params);
858
	$object = elgg_extract('object', $params);
859
	$actor = elgg_extract('sender', $params);
860
	$language = elgg_extract('language', $params);
861
	
862
	if (!($recipient instanceof ElggUser) || !($object instanceof ElggUser) || !($actor instanceof ElggUser)) {
863
		return;
864
	}
865
	
866
	if ($recipient->getGUID() === $object->getGUID()) {
867
		// recipient is the user being acted on, this is handled elsewhere
868
		return;
869
	}
870
	
871
	$site = elgg_get_site_entity();
872
	
873
	$return_value->subject = elgg_echo('admin:notification:make_admin:admin:subject', [$site->name], $language);
874
	$return_value->body = elgg_echo('admin:notification:make_admin:admin:body', [
875
		$recipient->name,
876
		$actor->name,
877
		$object->name,
878
		$site->name,
879
		$object->getURL(),
880
		$site->getURL(),
881
	], $language);
882
883
	$return_value->url = elgg_normalize_url('admin/users/admins');
884
	
885
	return $return_value;
886
}
887
888
/**
889
 * Prepare the notification content for site admins about removing a site admin
890
 *
891
 * @param string                           $hook         'prepare'
892
 * @param string                           $type         'notification:remove_admin:user:'
893
 * @param \Elgg\Notifications\Notification $return_value current notification content
894
 * @param array                            $params       supplied params
895
 *
896
 * @return void|\Elgg\Notifications\Notification
897
 */
898
function _elgg_admin_prepare_admin_notification_remove_admin($hook, $type, $return_value, $params) {
899
	
900
	if (!($return_value instanceof \Elgg\Notifications\Notification)) {
901
		return;
902
	}
903
	
904
	$recipient = elgg_extract('recipient', $params);
905
	$object = elgg_extract('object', $params);
906
	$actor = elgg_extract('sender', $params);
907
	$language = elgg_extract('language', $params);
908
	
909
	if (!($recipient instanceof ElggUser) || !($object instanceof ElggUser) || !($actor instanceof ElggUser)) {
910
		return;
911
	}
912
	
913
	if ($recipient->getGUID() === $object->getGUID()) {
914
		// recipient is the user being acted on, this is handled elsewhere
915
		return;
916
	}
917
	
918
	$site = elgg_get_site_entity();
919
	
920
	$return_value->subject = elgg_echo('admin:notification:remove_admin:admin:subject', [$site->name], $language);
921
	$return_value->body = elgg_echo('admin:notification:remove_admin:admin:body', [
922
		$recipient->name,
923
		$actor->name,
924
		$object->name,
925
		$site->name,
926
		$object->getURL(),
927
		$site->getURL(),
928
	], $language);
929
930
	$return_value->url = elgg_normalize_url('admin/users/admins');
931
	
932
	return $return_value;
933
}
934
935
/**
936
 * Add the user to the subscribers when making/removing the admin role
937
 *
938
 * @param string $hook         'get'
939
 * @param string $type         'subscribers'
940
 * @param array  $return_value current subscribers
941
 * @param array  $params       supplied params
942
 *
943
 * @return void|array
944
 */
945
function _elgg_admin_get_user_subscriber_admin_action($hook, $type, $return_value, $params) {
946
	
947 2
	if (!_elgg_config()->security_notify_user_admin) {
948 2
		return;
949
	}
950
	
951
	$event = elgg_extract('event', $params);
952
	if (!($event instanceof \Elgg\Notifications\Event)) {
953
		return;
954
	}
955
	
956
	if (!in_array($event->getAction(), ['make_admin', 'remove_admin'])) {
957
		return;
958
	}
959
	
960
	$user = $event->getObject();
961
	if (!($user instanceof \ElggUser)) {
962
		return;
963
	}
964
	
965
	$return_value[$user->getGUID()] = ['email'];
966
	
967
	return $return_value;
968
}
969
970
/**
971
 * Prepare the notification content for the user being made as a site admins
972
 *
973
 * @param string                           $hook         'prepare'
974
 * @param string                           $type         'notification:make_admin:user:'
975
 * @param \Elgg\Notifications\Notification $return_value current notification content
976
 * @param array                            $params       supplied params
977
 *
978
 * @return void|\Elgg\Notifications\Notification
979
 */
980
function _elgg_admin_prepare_user_notification_make_admin($hook, $type, $return_value, $params) {
981
	
982
	if (!($return_value instanceof \Elgg\Notifications\Notification)) {
983
		return;
984
	}
985
	
986
	$recipient = elgg_extract('recipient', $params);
987
	$object = elgg_extract('object', $params);
988
	$actor = elgg_extract('sender', $params);
989
	$language = elgg_extract('language', $params);
990
	
991
	if (!($recipient instanceof ElggUser) || !($object instanceof ElggUser) || !($actor instanceof ElggUser)) {
992
		return;
993
	}
994
	
995
	if ($recipient->getGUID() !== $object->getGUID()) {
996
		// recipient is some other user, this is handled elsewhere
997
		return;
998
	}
999
	
1000
	$site = elgg_get_site_entity();
1001
	
1002
	$return_value->subject = elgg_echo('admin:notification:make_admin:user:subject', [$site->name], $language);
1003
	$return_value->body = elgg_echo('admin:notification:make_admin:user:body', [
1004
		$recipient->name,
1005
		$actor->name,
1006
		$site->name,
1007
		$site->getURL(),
1008
	], $language);
1009
1010
	$return_value->url = elgg_normalize_url('admin');
1011
	
1012
	return $return_value;
1013
}
1014
1015
/**
1016
 * Prepare the notification content for the user being removed as a site admins
1017
 *
1018
 * @param string                           $hook         'prepare'
1019
 * @param string                           $type         'notification:remove_admin:user:'
1020
 * @param \Elgg\Notifications\Notification $return_value current notification content
1021
 * @param array                            $params       supplied params
1022
 *
1023
 * @return void|\Elgg\Notifications\Notification
1024
 */
1025
function _elgg_admin_prepare_user_notification_remove_admin($hook, $type, $return_value, $params) {
1026
	
1027
	if (!($return_value instanceof \Elgg\Notifications\Notification)) {
1028
		return;
1029
	}
1030
	
1031
	$recipient = elgg_extract('recipient', $params);
1032
	$object = elgg_extract('object', $params);
1033
	$actor = elgg_extract('sender', $params);
1034
	$language = elgg_extract('language', $params);
1035
	
1036
	if (!($recipient instanceof ElggUser) || !($object instanceof ElggUser) || !($actor instanceof ElggUser)) {
1037
		return;
1038
	}
1039
	
1040
	if ($recipient->getGUID() !== $object->getGUID()) {
1041
		// recipient is some other user, this is handled elsewhere
1042
		return;
1043
	}
1044
	
1045
	$site = elgg_get_site_entity();
1046
	
1047
	$return_value->subject = elgg_echo('admin:notification:remove_admin:user:subject', [$site->name], $language);
1048
	$return_value->body = elgg_echo('admin:notification:remove_admin:user:body', [
1049
		$recipient->name,
1050
		$actor->name,
1051
		$site->name,
1052
		$site->getURL(),
1053
	], $language);
1054
1055
	$return_value->url = false;
1056
	
1057
	return $return_value;
1058
}
1059
1060
/**
1061
 * @see \Elgg\Application::loadCore Do not do work here. Just register for events.
1062
 */
1063
return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {
1064 18
	$events->registerHandler('init', 'system', '_elgg_admin_init');
1065
};
1066