Completed
Push — master ( be3b3f...d1dc3f )
by Ismayil
13:04
created

admin.php ➔ _elgg_ajax_plugins_update()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 7
nc 1
nop 0
dl 0
loc 10
ccs 0
cts 7
cp 0
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 35 and the first side effect is on line 1032.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * Elgg admin functions.
4
 *
5
 * Admin menu items
6
 * Elgg has a convenience function for adding menu items to the sidebar of the
7
 * admin area. @see elgg_register_admin_menu_item()
8
 *
9
 * Admin pages
10
 * Plugins no not need to provide their own page handler to add a page to the
11
 * admin area. A view placed at admin/<section>/<subsection> can be access
12
 * at http://example.org/admin/<section>/<subsection>. The title of the page
13
 * will be elgg_echo('admin:<section>:<subsection>'). For an example of how to
14
 * add a page to the admin area, see the diagnostics plugin.
15
 *
16
 * Admin notices
17
 * System messages (success and error messages) are used in both the main site
18
 * and the admin area. There is a special presistent message for the admin area
19
 * called an admin notice. It should be used when a plugin requires an
20
 * administrator to take an action. @see elgg_add_admin_notice()
21
 *
22
 *
23
 * @package Elgg.Core
24
 * @subpackage Admin
25
 */
26
27
/**
28
 * Get the admin users
29
 *
30
 * @param array $options Options array, @see elgg_get_entities() for parameters
31
 *
32
 * @return mixed Array of admin users or false on failure. If a count, returns int.
33
 * @since 1.8.0
34
 */
35
function elgg_get_admins(array $options = array()) {
36
	global $CONFIG;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
37
38
	if (isset($options['joins'])) {
39
		if (!is_array($options['joins'])) {
40
			$options['joins'] = array($options['joins']);
41
		}
42
		$options['joins'][] = "join {$CONFIG->dbprefix}users_entity u on e.guid=u.guid";
43
	} else {
44
		$options['joins'] = array("join {$CONFIG->dbprefix}users_entity u on e.guid=u.guid");
45
	}
46
47
	if (isset($options['wheres'])) {
48
		if (!is_array($options['wheres'])) {
49
			$options['wheres'] = array($options['wheres']);
50
		}
51
		$options['wheres'][] = "u.admin = 'yes'";
52
	} else {
53
		$options['wheres'][] = "u.admin = 'yes'";
54
	}
55
56
	return elgg_get_entities($options);
57
}
58
59
/**
60
 * Write a persistent message to the admin view.
61
 * Useful to alert the admin to take a certain action.
62
 * The id is a unique ID that can be cleared once the admin
63
 * completes the action.
64
 *
65
 * eg: add_admin_notice('twitter_services_no_api',
66
 * 	'Before your users can use Twitter services on this site, you must set up
67
 * 	the Twitter API key in the <a href="link">Twitter Services Settings</a>');
68
 *
69
 * @param string $id      A unique ID that your plugin can remember
70
 * @param string $message Body of the message
71
 *
72
 * @return bool
73
 * @since 1.8.0
74
 */
75
function elgg_add_admin_notice($id, $message) {
76
	return _elgg_services()->adminNotices->add($id, $message);
77
}
78
79
/**
80
 * Remove an admin notice by ID.
81
 *
82
 * eg In actions/twitter_service/save_settings:
83
 * 	if (is_valid_twitter_api_key()) {
84
 * 		delete_admin_notice('twitter_services_no_api');
85
 * 	}
86
 *
87
 * @param string $id The unique ID assigned in add_admin_notice()
88
 *
89
 * @return bool
90
 * @since 1.8.0
91
 */
92
function elgg_delete_admin_notice($id) {
93
	return _elgg_services()->adminNotices->delete($id);
94
}
95
96
/**
97
 * Get admin notices. An admin must be logged in since the notices are private.
98
 *
99
 * @param int $limit Limit
100
 *
101
 * @return array Array of admin notices
102
 * @since 1.8.0
103
 */
104
function elgg_get_admin_notices($limit = 10) {
105
	return _elgg_services()->adminNotices->find($limit);
106
}
107
108
/**
109
 * Check if an admin notice is currently active.
110
 *
111
 * @param string $id The unique ID used to register the notice.
112
 *
113
 * @return bool
114
 * @since 1.8.0
115
 */
116
function elgg_admin_notice_exists($id) {
117
	return _elgg_services()->adminNotices->exists($id);
118
}
119
120
/**
121
 * Add an admin area section or child section.
122
 * This is a wrapper for elgg_register_menu_item().
123
 *
124
 * Used in conjuction with http://elgg.org/admin/section_id/child_section style
125
 * page handler. See the documentation at the top of this file for more details
126
 * on that.
127
 *
128
 * The text of the menu item is obtained from elgg_echo(admin:$parent_id:$menu_id)
129
 *
130
 * This function handles registering the parent if it has not been registered.
131
 *
132
 * @param string $section   The menu section to add to
133
 * @param string $menu_id   The unique ID of section
134
 * @param string $parent_id If a child section, the parent section id
135
 * @param int    $priority  The menu item priority
136
 *
137
 * @return bool
138
 * @since 1.8.0
139
 */
140
function elgg_register_admin_menu_item($section, $menu_id, $parent_id = null, $priority = 100) {
141
142
	// make sure parent is registered
143
	if ($parent_id && !elgg_is_menu_item_registered('page', $parent_id)) {
144
		elgg_register_admin_menu_item($section, $parent_id);
145
	}
146
147
	// in the admin section parents never have links
148
	if ($parent_id) {
149
		$href = "admin/$parent_id/$menu_id";
150
	} else {
151
		$href = null;
152
	}
153
154
	$name = $menu_id;
155
	if ($parent_id) {
156
		$name = "$parent_id:$name";
157
	}
158
159
	return elgg_register_menu_item('page', array(
160
		'name' => $name,
161
		'href' => $href,
162
		'text' => elgg_echo("admin:$name"),
163
		'context' => 'admin',
164
		'parent_name' => $parent_id,
165
		'priority' => $priority,
166
		'section' => $section
167
	));
168
}
169
170
/**
171
 * Add an admin notice when a new \ElggUpgrade object is created.
172
 *
173
 * @param string     $event
174
 * @param string     $type
175
 * @param \ElggObject $object
176
 * @access private
177
 */
178
function _elgg_create_notice_of_pending_upgrade($event, $type, $object) {
0 ignored issues
show
Unused Code introduced by
The parameter $event is not used and could be removed.

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

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

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

Loading history...
179
	if ($object instanceof \ElggUpgrade) {
180
		// Link to the Upgrades section
181
		$link = elgg_view('output/url', array(
182
			'href' => 'admin/upgrades',
183
			'text' => elgg_echo('admin:view_upgrades'),
184
		));
185
186
		$message = elgg_echo('admin:pending_upgrades');
187
188
		elgg_add_admin_notice('pending_upgrades', "$message $link");
189
	}
190
}
191
192
/**
193
 * Initialize the admin backend.
194
 * @return void
195
 * @access private
196
 */
197
function _elgg_admin_init() {
198
199
	$url = elgg_get_simplecache_url('admin.css');
200
	elgg_register_css('elgg.admin', $url);
201
		
202
	elgg_register_plugin_hook_handler('register', 'menu:admin_header', '_elgg_admin_header_menu');
203
	elgg_register_plugin_hook_handler('register', 'menu:admin_footer', '_elgg_admin_footer_menu');
204
205
	// maintenance mode
206
	if (elgg_get_config('elgg_maintenance_mode', null)) {
0 ignored issues
show
Unused Code introduced by
The call to elgg_get_config() has too many arguments starting with null.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
207
		elgg_register_plugin_hook_handler('route', 'all', '_elgg_admin_maintenance_handler', 600);
208
		elgg_register_plugin_hook_handler('action', 'all', '_elgg_admin_maintenance_action_check', 600);
209
		elgg_register_css('maintenance', elgg_get_simplecache_url('maintenance.css'));
210
211
		elgg_register_menu_item('topbar', array(
212
			'name' => 'maintenance_mode',
213
			'href' => 'admin/administer_utilities/maintenance',
214
			'text' => elgg_echo('admin:maintenance_mode:indicator_menu_item'),
215
			'priority' => 900,
216
		));
217
	}
218
219
	elgg_register_action('admin/user/ban', '', 'admin');
220
	elgg_register_action('admin/user/unban', '', 'admin');
221
	elgg_register_action('admin/user/delete', '', 'admin');
222
	elgg_register_action('admin/user/resetpassword', '', 'admin');
223
	elgg_register_action('admin/user/makeadmin', '', 'admin');
224
	elgg_register_action('admin/user/removeadmin', '', 'admin');
225
226
	elgg_register_action('admin/site/update_basic', '', 'admin');
227
	elgg_register_action('admin/site/update_advanced', '', 'admin');
228
	elgg_register_action('admin/site/flush_cache', '', 'admin');
229
	elgg_register_action('admin/site/unlock_upgrade', '', 'admin');
230
	elgg_register_action('admin/site/set_robots', '', 'admin');
231
	elgg_register_action('admin/site/set_maintenance_mode', '', 'admin');
232
233
	elgg_register_action('admin/upgrades/upgrade_database_guid_columns', '', 'admin');
234
	elgg_register_action('admin/site/regenerate_secret', '', 'admin');
235
	elgg_register_action('admin/upgrade', '', 'admin');
236
237
	elgg_register_action('admin/menu/save', '', 'admin');
238
239
	elgg_register_action('admin/delete_admin_notice', '', 'admin');
240
	
241
	elgg_register_action('admin/security/settings', '', 'admin');
242
243
	elgg_register_action('profile/fields/reset', '', 'admin');
244
	elgg_register_action('profile/fields/add', '', 'admin');
245
	elgg_register_action('profile/fields/edit', '', 'admin');
246
	elgg_register_action('profile/fields/delete', '', 'admin');
247
	elgg_register_action('profile/fields/reorder', '', 'admin');
248
249
	elgg_register_simplecache_view('admin.css');
250
251
	elgg_register_js('jquery.jeditable', elgg_get_simplecache_url('jquery.jeditable.js'));
252
253
	// administer
254
	// dashboard
255
	elgg_register_menu_item('page', array(
256
		'name' => 'dashboard',
257
		'href' => 'admin/dashboard',
258
		'text' => elgg_echo('admin:dashboard'),
259
		'context' => 'admin',
260
		'priority' => 10,
261
		'section' => 'administer'
262
	));
263
	// statistics
264
	elgg_register_admin_menu_item('administer', 'statistics', null, 20);
265
	elgg_register_admin_menu_item('administer', 'overview', 'statistics');
266
	elgg_register_admin_menu_item('administer', 'server', 'statistics');
267
	//utilities
268
	elgg_register_admin_menu_item('administer', 'maintenance', 'administer_utilities');
269
	// security
270
	elgg_register_admin_menu_item('administer', 'settings', 'administer_security');
271
272
	// users
273
	elgg_register_admin_menu_item('administer', 'users', null, 20);
274
	elgg_register_admin_menu_item('administer', 'online', 'users', 10);
275
	elgg_register_admin_menu_item('administer', 'admins', 'users', 20);
276
	elgg_register_admin_menu_item('administer', 'newest', 'users', 30);
277
	elgg_register_admin_menu_item('administer', 'add', 'users', 40);
278
279
	// configure
280
	// upgrades
281
	elgg_register_menu_item('page', array(
282
		'name' => 'upgrades',
283
		'href' => 'admin/upgrades',
284
		'text' => elgg_echo('admin:upgrades'),
285
		'context' => 'admin',
286
		'priority' => 10,
287
		'section' => 'configure'
288
	));
289
290
	// plugins
291
	elgg_register_menu_item('page', array(
292
		'name' => 'plugins',
293
		'href' => 'admin/plugins',
294
		'text' => elgg_echo('admin:plugins'),
295
		'context' => 'admin',
296
		'priority' => 75,
297
		'section' => 'configure'
298
	));
299
300
	// settings
301
	elgg_register_admin_menu_item('configure', 'appearance', null, 50);
302
	elgg_register_admin_menu_item('configure', 'settings', null, 100);
303
	elgg_register_admin_menu_item('configure', 'basic', 'settings', 10);
304
	elgg_register_admin_menu_item('configure', 'advanced', 'settings', 20);
305
	// plugin settings are added in _elgg_admin_add_plugin_settings_menu() via the admin page handler
306
	// for performance reasons.
307
308
	// appearance
309
	elgg_register_admin_menu_item('configure', 'menu_items', 'appearance', 30);
310
	elgg_register_admin_menu_item('configure', 'profile_fields', 'appearance', 40);
311
	// default widgets is added via an event handler elgg_default_widgets_init() in widgets.php
312
	// because it requires additional setup.
313
314
	// configure utilities
315
	elgg_register_admin_menu_item('configure', 'robots', 'configure_utilities');
316
317
	// we want plugin settings menu items to be sorted alphabetical
318
	if (elgg_in_context('admin') && elgg_is_admin_logged_in()) {
319
		elgg_register_plugin_hook_handler('prepare', 'menu:page', '_elgg_admin_sort_page_menu');
320
	}
321
322
	// widgets
323
	$widgets = array('online_users', 'new_users', 'content_stats', 'banned_users', 'admin_welcome', 'control_panel', 'cron_status');
324
	foreach ($widgets as $widget) {
325
		elgg_register_widget_type(
326
				$widget,
327
				elgg_echo("admin:widget:$widget"),
328
				elgg_echo("admin:widget:$widget:help"),
329
				array('admin')
330
		);
331
	}
332
333
	// automatic adding of widgets for admin
334
	elgg_register_event_handler('make_admin', 'user', '_elgg_add_admin_widgets');
335
	
336
	elgg_register_notification_event('user', '', ['make_admin', 'remove_admin']);
337
	elgg_register_plugin_hook_handler('get', 'subscriptions', '_elgg_admin_get_admin_subscribers_admin_action');
338
	elgg_register_plugin_hook_handler('get', 'subscriptions', '_elgg_admin_get_user_subscriber_admin_action');
339
	elgg_register_plugin_hook_handler('prepare', 'notification:make_admin:user:', '_elgg_admin_prepare_admin_notification_make_admin');
340
	elgg_register_plugin_hook_handler('prepare', 'notification:make_admin:user:', '_elgg_admin_prepare_user_notification_make_admin');
341
	elgg_register_plugin_hook_handler('prepare', 'notification:remove_admin:user:', '_elgg_admin_prepare_admin_notification_remove_admin');
342
	elgg_register_plugin_hook_handler('prepare', 'notification:remove_admin:user:', '_elgg_admin_prepare_user_notification_remove_admin');
343
	
344
	// Add notice about pending upgrades
345
	elgg_register_event_handler('create', 'object', '_elgg_create_notice_of_pending_upgrade');
346
347
	elgg_register_page_handler('admin', '_elgg_admin_page_handler');
348
	elgg_register_page_handler('admin_plugin_text_file', '_elgg_admin_markdown_page_handler');
349
	elgg_register_page_handler('robots.txt', '_elgg_robots_page_handler');
350
	elgg_register_page_handler('admin_plugins_refresh', '_elgg_ajax_plugins_update');
351
}
352
353
/**
354
 * Returns plugin listing and admin menu to the client (used after plugin (de)activation)
355
 *
356
 * @access private
357
 * @return Elgg\Http\OkResponse
358
 */
359
function _elgg_ajax_plugins_update() {
360
	elgg_admin_gatekeeper();
361
	_elgg_admin_add_plugin_settings_menu();
362
	elgg_set_context('admin');
363
364
	return elgg_ok_response([
365
		'list' => elgg_view('admin/plugins', ['list_only' => true]),
366
		'sidebar' => elgg_view('admin/sidebar'),
367
	]);
368
}
369
370
/**
371
 * Register menu items for the admin_header menu
372
 *
373
 * @param string $hook
374
 * @param string $type
375
 * @param array  $return
376
 * @param array  $params
377
 * @return array
378
 *
379
 * @access private
380
 *
381
 * @since 3.0
382
 */
383
function _elgg_admin_header_menu($hook, $type, $return, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

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

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

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

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

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

Loading history...
384
	if (!elgg_in_context('admin') || !elgg_is_admin_logged_in()) {
385
		return;
386
	}
387
388
	$admin = elgg_get_logged_in_user_entity();
389
390
	$return[] = \ElggMenuItem::factory([
391
		'name' => 'admin_logout',
392
		'href' => 'action/logout',
393
		'text' => elgg_echo('logout'),
394
		'is_trusted' => true,
395
		'priority' => 1000,
396
	]);
397
398
	$return[] = \ElggMenuItem::factory([
399
		'name' => 'view_site',
400
		'href' => elgg_get_site_url(),
401
		'text' => elgg_echo('admin:view_site'),
402
		'is_trusted' => true,
403
		'priority' => 900,
404
	]);
405
406
	$return[] = \ElggMenuItem::factory([
407
		'name' => 'admin_profile',
408
		'href' => false,
409
		'text' => elgg_echo('admin:loggedin', array($admin->name)),
410
		'priority' => 800,
411
	]);
412
413
	if (elgg_get_config('elgg_maintenance_mode', null)) {
0 ignored issues
show
Unused Code introduced by
The call to elgg_get_config() has too many arguments starting with null.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
414
		$return[] = \ElggMenuItem::factory([
415
			'name' => 'maintenance',
416
			'href' => 'admin/administer_utilities/maintenance',
417
			'text' => elgg_echo('admin:administer_utilities:maintenance'),
418
			'link_class' => 'elgg-maintenance-mode-warning',
419
			'priority' => 700,
420
		]);
421
	}
422
	
423
	return $return;
424
}
425
426
/**
427
 * Register menu items for the admin_footer menu
428
 *
429
 * @param string $hook
430
 * @param string $type
431
 * @param array  $return
432
 * @param array  $params
433
 * @return array
434
 *
435
 * @access private
436
 *
437
 * @since 3.0
438
 */
439
function _elgg_admin_footer_menu($hook, $type, $return, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

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

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

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

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

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

Loading history...
440
	if (!elgg_in_context('admin') || !elgg_is_admin_logged_in()) {
441
		return;
442
	}
443
444
	$return[] = \ElggMenuItem::factory([
445
		'name' => 'faq',
446
		'text' => elgg_echo('admin:footer:faq'),
447
		'href' => 'http://learn.elgg.org/en/stable/appendix/faqs.html',
448
	]);
449
450
	$return[] = \ElggMenuItem::factory([
451
		'name' => 'manual',
452
		'text' => elgg_echo('admin:footer:manual'),
453
		'href' => 'http://learn.elgg.org/en/stable/admin/index.html',
454
	]);
455
456
	$return[] = \ElggMenuItem::factory([
457
		'name' => 'community_forums',
458
		'text' => elgg_echo('admin:footer:community_forums'),
459
		'href' => 'http://elgg.org/groups/all/',
460
	]);
461
462
	$return[] = \ElggMenuItem::factory([
463
		'name' => 'blog',
464
		'text' => elgg_echo('admin:footer:blog'),
465
		'href' => 'https://elgg.org/blog/all',
466
	]);
467
	
468
	return $return;
469
}
470
471
/**
472
 * Create the plugin settings page menu.
473
 *
474
 * This is done in a separate function called from the admin
475
 * page handler because of performance concerns.
476
 *
477
 * @return void
478
 * @access private
479
 * @since 1.8.0
480
 */
481
function _elgg_admin_add_plugin_settings_menu() {
482
483
	$active_plugins = elgg_get_plugins('active');
484
	if (!$active_plugins) {
485
		// nothing added because no items
486
		return;
487
	}
488
489
	foreach ($active_plugins as $plugin) {
490
		$plugin_id = $plugin->getID();
491
		$settings_view_old = 'settings/' . $plugin_id . '/edit';
492
		$settings_view_new = 'plugins/' . $plugin_id . '/settings';
493
		if (elgg_view_exists($settings_view_new) || elgg_view_exists($settings_view_old)) {
494
			elgg_register_menu_item('page', array(
495
				'name' => $plugin_id,
496
				'href' => "admin/plugin_settings/$plugin_id",
497
				'text' => $plugin->getManifest()->getName(),
498
				'parent_name' => 'settings',
499
				'context' => 'admin',
500
				'section' => 'configure',
501
			));
502
		}
503
	}
504
}
505
506
/**
507
 * Sort the plugin settings menu items
508
 *
509
 * @param string $hook
510
 * @param string $type
511
 * @param array  $return
512
 * @param array  $params
513
 *
514
 * @return void
515
 * @since 1.8.0
516
 * @access private
517
 */
518
function _elgg_admin_sort_page_menu($hook, $type, $return, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

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

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

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

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

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

Loading history...
519
	$configure_items = $return['configure'];
520
	if (is_array($configure_items)) {
521
		/* @var \ElggMenuItem[] $configure_items */
522
		foreach ($configure_items as $menu_item) {
523
			if ($menu_item->getName() == 'settings') {
524
				$settings = $menu_item;
525
			}
526
		}
527
528
		if (!empty($settings) && $settings instanceof \ElggMenuItem) {
529
			// keep the basic and advanced settings at the top
530
			/* @var \ElggMenuItem $settings */
531
			$children = $settings->getChildren();
532
			$site_settings = array_splice($children, 0, 2);
533
			usort($children, [\ElggMenuBuilder::class, 'compareByText']);
534
			array_splice($children, 0, 0, $site_settings);
535
			$settings->setChildren($children);
536
		}
537
	}
538
}
539
540
/**
541
 * Handle admin pages.  Expects corresponding views as admin/section/subsection
542
 *
543
 * @param array $page Array of pages
544
 *
545
 * @return bool
546
 * @access private
547
 */
548
function _elgg_admin_page_handler($page) {
549
	elgg_admin_gatekeeper();
550
	_elgg_admin_add_plugin_settings_menu();
551
	elgg_set_context('admin');
552
553
	elgg_unregister_css('elgg');
554
	elgg_require_js('elgg/admin');
555
556
	elgg_load_js('jquery.jeditable');
557
558
	// default to dashboard
559
	if (!isset($page[0]) || empty($page[0])) {
560
		$page = array('dashboard');
561
	}
562
563
	// was going to fix this in the page_handler() function but
564
	// it's commented to explicitly return a string if there's a trailing /
565
	if (empty($page[count($page) - 1])) {
566
		array_pop($page);
567
	}
568
569
	$vars = array('page' => $page);
570
571
	// special page for plugin settings since we create the form for them
572
	if ($page[0] == 'plugin_settings') {
573
		if (isset($page[1]) && (elgg_view_exists("settings/{$page[1]}/edit") ||
574
				elgg_view_exists("plugins/{$page[1]}/settings"))) {
575
576
			$view = 'admin/plugin_settings';
577
			$plugin = elgg_get_plugin_from_id($page[1]);
578
			$vars['plugin'] = $plugin;
579
580
			$title = elgg_echo("admin:{$page[0]}");
581
		} else {
582
			forward('', '404');
583
		}
584
	} else {
585
		$view = 'admin/' . implode('/', $page);
586
		$title = elgg_echo("admin:{$page[0]}");
587
		if (count($page) > 1) {
588
			$title .= ' : ' . elgg_echo('admin:' .  implode(':', $page));
589
		}
590
	}
591
592
	// gets content and prevents direct access to 'components' views
593
	if ($page[0] == 'components' || !($content = elgg_view($view, $vars))) {
0 ignored issues
show
Bug introduced by
The variable $view does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
594
		$title = elgg_echo('admin:unknown_section');
595
		$content = elgg_echo('admin:unknown_section');
596
	}
597
598
	$body = elgg_view_layout('admin', array('content' => $content, 'title' => $title));
0 ignored issues
show
Bug introduced by
The variable $title does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
599
	echo elgg_view_page($title, $body, 'admin');
600
	return true;
601
}
602
603
/**
604
 * Formats and serves out markdown files from plugins.
605
 *
606
 * URLs in format like admin_plugin_text_file/<plugin_id>/filename.ext
607
 *
608
 * The only valid files are:
609
 *	* README.txt
610
 *	* CHANGES.txt
611
 *	* INSTALL.txt
612
 *	* COPYRIGHT.txt
613
 *	* LICENSE.txt
614
 *
615
 * @param array $pages
616
 * @return bool
617
 * @access private
618
 */
619
function _elgg_admin_markdown_page_handler($pages) {
620
	elgg_set_context('admin');
621
622
	echo elgg_view_resource('admin/plugin_text_file', [
623
		'plugin_id' => elgg_extract(0, $pages),
624
		'filename' => elgg_extract(1, $pages),
625
	]);
626
	return true;
627
}
628
629
/**
630
 * Handle request for robots.txt
631
 *
632
 * @access private
633
 */
634
function _elgg_robots_page_handler() {
635
	echo elgg_view_resource('robots.txt');
636
	return true;
637
}
638
639
/**
640
 * When in maintenance mode, should the given URL be handled normally?
641
 *
642
 * @param string $current_url Current page URL
643
 * @return bool
644
 *
645
 * @access private
646
 */
647
function _elgg_admin_maintenance_allow_url($current_url) {
648
	$site_path = preg_replace('~^https?~', '', elgg_get_site_url());
649
	$current_path = preg_replace('~^https?~', '', $current_url);
650
	if (0 === strpos($current_path, $site_path)) {
651
		$current_path = ($current_path === $site_path) ? '' : substr($current_path, strlen($site_path));
652
	} else {
653
		$current_path = false;
654
	}
655
656
	// allow plugins to control access for specific URLs/paths
657
	$params = array(
658
		'current_path' => $current_path,
659
		'current_url' => $current_url,
660
	);
661
	return (bool)elgg_trigger_plugin_hook('maintenance:allow', 'url', $params, false);
662
}
663
664
/**
665
 * Handle requests when in maintenance mode
666
 *
667
 * @access private
668
 */
669
function _elgg_admin_maintenance_handler($hook, $type, $info) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

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

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

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

Loading history...
670
	if (elgg_is_admin_logged_in()) {
671
		return;
672
	}
673
674
	if ($info['identifier'] == 'action' && $info['segments'][0] == 'login') {
675
		return;
676
	}
677
678
	if (_elgg_admin_maintenance_allow_url(current_page_url())) {
679
		return;
680
	}
681
682
	elgg_unregister_plugin_hook_handler('register', 'menu:login', '_elgg_login_menu_setup');
683
684
	echo elgg_view_resource('maintenance');
685
686
	return false;
687
}
688
689
/**
690
 * Prevent non-admins from using actions
691
 *
692
 * @access private
693
 *
694
 * @param string $hook Hook name
695
 * @param string $type Action name
696
 * @return bool
697
 */
698
function _elgg_admin_maintenance_action_check($hook, $type) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

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

Loading history...
699
	if (elgg_is_admin_logged_in()) {
700
		return true;
701
	}
702
703
	if ($type == 'login') {
704
		$username = get_input('username');
705
706
		$user = get_user_by_username($username);
707
708
		if (!$user) {
709
			$users = get_user_by_email($username);
710
			if ($users) {
711
				$user = $users[0];
712
			}
713
		}
714
715
		if ($user && $user->isAdmin()) {
716
			return true;
717
		}
718
	}
719
720
	if (_elgg_admin_maintenance_allow_url(current_page_url())) {
721
		return true;
722
	}
723
724
	register_error(elgg_echo('actionunauthorized'));
725
726
	return false;
727
}
728
729
/**
730
 * Adds default admin widgets to the admin dashboard.
731
 *
732
 * @param string $event
733
 * @param string $type
734
 * @param \ElggUser $user
735
 *
736
 * @return null|true
737
 * @access private
738
 */
739
function _elgg_add_admin_widgets($event, $type, $user) {
0 ignored issues
show
Unused Code introduced by
The parameter $event is not used and could be removed.

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

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

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

Loading history...
740
	elgg_set_ignore_access(true);
741
742
	// check if the user already has widgets
743
	if (elgg_get_widgets($user->getGUID(), 'admin')) {
744
		return true;
745
	}
746
747
	// In the form column => array of handlers in order, top to bottom
748
	$adminWidgets = array(
749
		1 => array('control_panel', 'admin_welcome'),
750
		2 => array('online_users', 'new_users', 'content_stats'),
751
	);
752
753
	foreach ($adminWidgets as $column => $handlers) {
754
		foreach ($handlers as $position => $handler) {
755
			$guid = elgg_create_widget($user->getGUID(), $handler, 'admin');
756
			if ($guid) {
757
				$widget = get_entity($guid);
758
				/* @var \ElggWidget $widget */
759
				$widget->move($column, $position);
760
			}
761
		}
762
	}
763
	elgg_set_ignore_access(false);
764
}
765
766
/**
767
 * Add the current site admins to the subscribers when making/removing an admin user
768
 *
769
 * @param string $hook         'get'
770
 * @param string $type         'subscribers'
771
 * @param array  $return_value current subscribers
772
 * @param arary  $params       supplied params
773
 *
774
 * @return void|array
775
 */
776
function _elgg_admin_get_admin_subscribers_admin_action($hook, $type, $return_value, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

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

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

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

Loading history...
777
	
778
	if (!elgg_get_config('security_notify_admins')) {
779
		return;
780
	}
781
	
782
	$event = elgg_extract('event', $params);
783
	if (!($event instanceof \Elgg\Notifications\Event)) {
784
		return;
785
	}
786
	
787
	if (!in_array($event->getAction(), ['make_admin', 'remove_admin'])) {
788
		return;
789
	}
790
	
791
	$user = $event->getObject();
792
	if (!($user instanceof \ElggUser)) {
793
		return;
794
	}
795
	
796
	/* @var $admin_batch \Elgg\BatchResult */
797
	$admin_batch = elgg_get_admins([
798
		'limit' => false,
799
		'wheres' => [
800
			"e.guid <> {$user->getGUID()}",
801
		],
802
		'batch' => true,
803
	]);
804
	
805
	/* @var $admin \ElggUser */
806
	foreach ($admin_batch as $admin) {
807
		$return_value[$admin->getGUID()] = ['email'];
808
	}
809
	
810
	return $return_value;
811
}
812
813
/**
814
 * Prepare the notification content for site admins about making a site admin
815
 *
816
 * @param string                           $hook         'prepare'
817
 * @param string                           $type         'notification:make_admin:user:'
818
 * @param \Elgg\Notifications\Notification $return_value current notification content
819
 * @param array                            $params       supplied params
820
 *
821
 * @return void|\Elgg\Notifications\Notification
822
 */
823
function _elgg_admin_prepare_admin_notification_make_admin($hook, $type, $return_value, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

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

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

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

Loading history...
824
	
825
	if (!($return_value instanceof \Elgg\Notifications\Notification)) {
826
		return;
827
	}
828
	
829
	$recipient = elgg_extract('recipient', $params);
830
	$object = elgg_extract('object', $params);
831
	$actor = elgg_extract('sender', $params);
832
	$language = elgg_extract('language', $params);
833
	
834
	if (!($recipient instanceof ElggUser) || !($object instanceof ElggUser) || !($actor instanceof ElggUser)) {
835
		return;
836
	}
837
	
838
	if ($recipient->getGUID() === $object->getGUID()) {
839
		// recipient is the user being acted on, this is handled elsewhere
840
		return;
841
	}
842
	
843
	$site = elgg_get_site_entity();
844
	
845
	$return_value->subject = elgg_echo('admin:notification:make_admin:admin:subject', [$site->name], $language);
846
	$return_value->body = elgg_echo('admin:notification:make_admin:admin:body', [
847
		$recipient->name,
848
		$actor->name,
849
		$object->name,
850
		$site->name,
851
		$object->getURL(),
852
		$site->getURL(),
853
	], $language);
854
855
	$return_value->url = elgg_normalize_url('admin/users/admins');
856
	
857
	return $return_value;
858
}
859
860
/**
861
 * Prepare the notification content for site admins about removing a site admin
862
 *
863
 * @param string                           $hook         'prepare'
864
 * @param string                           $type         'notification:remove_admin:user:'
865
 * @param \Elgg\Notifications\Notification $return_value current notification content
866
 * @param array                            $params       supplied params
867
 *
868
 * @return void|\Elgg\Notifications\Notification
869
 */
870
function _elgg_admin_prepare_admin_notification_remove_admin($hook, $type, $return_value, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

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

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

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

Loading history...
871
	
872
	if (!($return_value instanceof \Elgg\Notifications\Notification)) {
873
		return;
874
	}
875
	
876
	$recipient = elgg_extract('recipient', $params);
877
	$object = elgg_extract('object', $params);
878
	$actor = elgg_extract('sender', $params);
879
	$language = elgg_extract('language', $params);
880
	
881
	if (!($recipient instanceof ElggUser) || !($object instanceof ElggUser) || !($actor instanceof ElggUser)) {
882
		return;
883
	}
884
	
885
	if ($recipient->getGUID() === $object->getGUID()) {
886
		// recipient is the user being acted on, this is handled elsewhere
887
		return;
888
	}
889
	
890
	$site = elgg_get_site_entity();
891
	
892
	$return_value->subject = elgg_echo('admin:notification:remove_admin:admin:subject', [$site->name], $language);
893
	$return_value->body = elgg_echo('admin:notification:remove_admin:admin:body', [
894
		$recipient->name,
895
		$actor->name,
896
		$object->name,
897
		$site->name,
898
		$object->getURL(),
899
		$site->getURL(),
900
	], $language);
901
902
	$return_value->url = elgg_normalize_url('admin/users/admins');
903
	
904
	return $return_value;
905
}
906
907
/**
908
 * Add the user to the subscribers when making/removing the admin role
909
 *
910
 * @param string $hook         'get'
911
 * @param string $type         'subscribers'
912
 * @param array  $return_value current subscribers
913
 * @param arary  $params       supplied params
914
 *
915
 * @return void|array
916
 */
917
function _elgg_admin_get_user_subscriber_admin_action($hook, $type, $return_value, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

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

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

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

Loading history...
918
	
919
	if (!elgg_get_config('security_notify_user_admin')) {
920
		return;
921
	}
922
	
923
	$event = elgg_extract('event', $params);
924
	if (!($event instanceof \Elgg\Notifications\Event)) {
925
		return;
926
	}
927
	
928
	if (!in_array($event->getAction(), ['make_admin', 'remove_admin'])) {
929
		return;
930
	}
931
	
932
	$user = $event->getObject();
933
	if (!($user instanceof \ElggUser)) {
934
		return;
935
	}
936
	
937
	$return_value[$user->getGUID()] = ['email'];
938
	
939
	return $return_value;
940
}
941
942
/**
943
 * Prepare the notification content for the user being made as a site admins
944
 *
945
 * @param string                           $hook         'prepare'
946
 * @param string                           $type         'notification:make_admin:user:'
947
 * @param \Elgg\Notifications\Notification $return_value current notification content
948
 * @param array                            $params       supplied params
949
 *
950
 * @return void|\Elgg\Notifications\Notification
951
 */
952
function _elgg_admin_prepare_user_notification_make_admin($hook, $type, $return_value, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

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

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

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

Loading history...
953
	
954
	if (!($return_value instanceof \Elgg\Notifications\Notification)) {
955
		return;
956
	}
957
	
958
	$recipient = elgg_extract('recipient', $params);
959
	$object = elgg_extract('object', $params);
960
	$actor = elgg_extract('sender', $params);
961
	$language = elgg_extract('language', $params);
962
	
963
	if (!($recipient instanceof ElggUser) || !($object instanceof ElggUser) || !($actor instanceof ElggUser)) {
964
		return;
965
	}
966
	
967
	if ($recipient->getGUID() !== $object->getGUID()) {
968
		// recipient is some other user, this is handled elsewhere
969
		return;
970
	}
971
	
972
	$site = elgg_get_site_entity();
973
	
974
	$return_value->subject = elgg_echo('admin:notification:make_admin:user:subject', [$site->name], $language);
975
	$return_value->body = elgg_echo('admin:notification:make_admin:user:body', [
976
		$recipient->name,
977
		$actor->name,
978
		$site->name,
979
		$site->getURL(),
980
	], $language);
981
982
	$return_value->url = elgg_normalize_url('admin');
983
	
984
	return $return_value;
985
}
986
987
/**
988
 * Prepare the notification content for the user being removed as a site admins
989
 *
990
 * @param string                           $hook         'prepare'
991
 * @param string                           $type         'notification:remove_admin:user:'
992
 * @param \Elgg\Notifications\Notification $return_value current notification content
993
 * @param array                            $params       supplied params
994
 *
995
 * @return void|\Elgg\Notifications\Notification
996
 */
997
function _elgg_admin_prepare_user_notification_remove_admin($hook, $type, $return_value, $params) {
0 ignored issues
show
Unused Code introduced by
The parameter $hook is not used and could be removed.

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

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

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

Loading history...
998
	
999
	if (!($return_value instanceof \Elgg\Notifications\Notification)) {
1000
		return;
1001
	}
1002
	
1003
	$recipient = elgg_extract('recipient', $params);
1004
	$object = elgg_extract('object', $params);
1005
	$actor = elgg_extract('sender', $params);
1006
	$language = elgg_extract('language', $params);
1007
	
1008
	if (!($recipient instanceof ElggUser) || !($object instanceof ElggUser) || !($actor instanceof ElggUser)) {
1009
		return;
1010
	}
1011
	
1012
	if ($recipient->getGUID() !== $object->getGUID()) {
1013
		// recipient is some other user, this is handled elsewhere
1014
		return;
1015
	}
1016
	
1017
	$site = elgg_get_site_entity();
1018
	
1019
	$return_value->subject = elgg_echo('admin:notification:remove_admin:user:subject', [$site->name], $language);
1020
	$return_value->body = elgg_echo('admin:notification:remove_admin:user:body', [
1021
		$recipient->name,
1022
		$actor->name,
1023
		$site->name,
1024
		$site->getURL(),
1025
	], $language);
1026
1027
	$return_value->url = false;
0 ignored issues
show
Documentation Bug introduced by
The property $url was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
1028
	
1029
	return $return_value;
1030
}
1031
1032
return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {
0 ignored issues
show
Unused Code introduced by
The parameter $hooks is not used and could be removed.

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

Loading history...
1033
	$events->registerHandler('init', 'system', '_elgg_admin_init');
1034
};
1035