Issues (4967)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/wp-includes/class-wp-admin-bar.php (6 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Toolbar API: WP_Admin_Bar class
4
 *
5
 * @package WordPress
6
 * @subpackage Toolbar
7
 * @since 3.1.0
8
 */
9
10
/**
11
 * Core class used to implement the Toolbar API.
12
 *
13
 * @since 3.1.0
14
 */
15
class WP_Admin_Bar {
16
	private $nodes = array();
17
	private $bound = false;
18
	public $user;
19
20
	/**
21
	 * @param string $name
22
	 * @return string|array|void
23
	 */
24
	public function __get( $name ) {
25
		switch ( $name ) {
26
			case 'proto' :
27
				return is_ssl() ? 'https://' : 'http://';
28
29
			case 'menu' :
30
				_deprecated_argument( 'WP_Admin_Bar', '3.3.0', 'Modify admin bar nodes with WP_Admin_Bar::get_node(), WP_Admin_Bar::add_node(), and WP_Admin_Bar::remove_node(), not the <code>menu</code> property.' );
31
				return array(); // Sorry, folks.
32
		}
33
	}
34
35
	/**
36
	 * @access public
37
	 */
38
	public function initialize() {
39
		$this->user = new stdClass;
40
41
		if ( is_user_logged_in() ) {
42
			/* Populate settings we need for the menu based on the current user. */
43
			$this->user->blogs = get_blogs_of_user( get_current_user_id() );
44
			if ( is_multisite() ) {
45
				$this->user->active_blog = get_active_blog_for_user( get_current_user_id() );
46
				$this->user->domain = empty( $this->user->active_blog ) ? user_admin_url() : trailingslashit( get_home_url( $this->user->active_blog->blog_id ) );
47
				$this->user->account_domain = $this->user->domain;
48
			} else {
49
				$this->user->active_blog = $this->user->blogs[get_current_blog_id()];
50
				$this->user->domain = trailingslashit( home_url() );
51
				$this->user->account_domain = $this->user->domain;
52
			}
53
		}
54
55
		add_action( 'wp_head', 'wp_admin_bar_header' );
56
57
		add_action( 'admin_head', 'wp_admin_bar_header' );
58
59
		if ( current_theme_supports( 'admin-bar' ) ) {
60
			/**
61
			 * To remove the default padding styles from WordPress for the Toolbar, use the following code:
62
			 * add_theme_support( 'admin-bar', array( 'callback' => '__return_false' ) );
63
			 */
64
			$admin_bar_args = get_theme_support( 'admin-bar' );
65
			$header_callback = $admin_bar_args[0]['callback'];
66
		}
67
68
		if ( empty($header_callback) )
69
			$header_callback = '_admin_bar_bump_cb';
70
71
		add_action('wp_head', $header_callback);
72
73
		wp_enqueue_script( 'admin-bar' );
74
		wp_enqueue_style( 'admin-bar' );
75
76
		/**
77
		 * Fires after WP_Admin_Bar is initialized.
78
		 *
79
		 * @since 3.1.0
80
		 */
81
		do_action( 'admin_bar_init' );
82
	}
83
84
	/**
85
	 * @param array $node
86
	 */
87
	public function add_menu( $node ) {
88
		$this->add_node( $node );
89
	}
90
91
	/**
92
	 * @param string $id
93
	 */
94
	public function remove_menu( $id ) {
95
		$this->remove_node( $id );
96
	}
97
98
	/**
99
	 * Adds a node to the menu.
100
	 *
101
	 * @since 3.1.0
102
	 * @since 4.5.0 Added the ability to pass 'lang' and 'dir' meta data.
103
	 * @access public
104
	 *
105
	 * @param array $args {
106
	 *     Arguments for adding a node.
107
	 *
108
	 *     @type string $id     ID of the item.
109
	 *     @type string $title  Title of the node.
110
	 *     @type string $parent Optional. ID of the parent node.
111
	 *     @type string $href   Optional. Link for the item.
112
	 *     @type bool   $group  Optional. Whether or not the node is a group. Default false.
113
	 *     @type array  $meta   Meta data including the following keys: 'html', 'class', 'rel', 'lang', 'dir',
114
	 *                          'onclick', 'target', 'title', 'tabindex'. Default empty.
115
	 * }
116
	 */
117
	public function add_node( $args ) {
118
		// Shim for old method signature: add_node( $parent_id, $menu_obj, $args )
119
		if ( func_num_args() >= 3 && is_string( func_get_arg(0) ) )
120
			$args = array_merge( array( 'parent' => func_get_arg(0) ), func_get_arg(2) );
121
122
		if ( is_object( $args ) )
123
			$args = get_object_vars( $args );
124
125
		// Ensure we have a valid title.
126
		if ( empty( $args['id'] ) ) {
127
			if ( empty( $args['title'] ) )
128
				return;
129
130
			_doing_it_wrong( __METHOD__, __( 'The menu ID should not be empty.' ), '3.3.0' );
131
			// Deprecated: Generate an ID from the title.
132
			$args['id'] = esc_attr( sanitize_title( trim( $args['title'] ) ) );
133
		}
134
135
		$defaults = array(
136
			'id'     => false,
137
			'title'  => false,
138
			'parent' => false,
139
			'href'   => false,
140
			'group'  => false,
141
			'meta'   => array(),
142
		);
143
144
		// If the node already exists, keep any data that isn't provided.
145
		if ( $maybe_defaults = $this->get_node( $args['id'] ) )
146
			$defaults = get_object_vars( $maybe_defaults );
147
148
		// Do the same for 'meta' items.
149
		if ( ! empty( $defaults['meta'] ) && ! empty( $args['meta'] ) )
150
			$args['meta'] = wp_parse_args( $args['meta'], $defaults['meta'] );
151
152
		$args = wp_parse_args( $args, $defaults );
153
154
		$back_compat_parents = array(
155
			'my-account-with-avatar' => array( 'my-account', '3.3' ),
156
			'my-blogs'               => array( 'my-sites',   '3.3' ),
157
		);
158
159
		if ( isset( $back_compat_parents[ $args['parent'] ] ) ) {
160
			list( $new_parent, $version ) = $back_compat_parents[ $args['parent'] ];
161
			_deprecated_argument( __METHOD__, $version, sprintf( 'Use <code>%s</code> as the parent for the <code>%s</code> admin bar node instead of <code>%s</code>.', $new_parent, $args['id'], $args['parent'] ) );
162
			$args['parent'] = $new_parent;
163
		}
164
165
		$this->_set_node( $args );
166
	}
167
168
	/**
169
	 * @param array $args
170
	 */
171
	final protected function _set_node( $args ) {
172
		$this->nodes[ $args['id'] ] = (object) $args;
173
	}
174
175
	/**
176
	 * Gets a node.
177
	 *
178
	 * @param string $id
179
	 * @return object Node.
0 ignored issues
show
Should the return type not be object|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
180
	 */
181
	final public function get_node( $id ) {
182
		if ( $node = $this->_get_node( $id ) )
183
			return clone $node;
184
	}
185
186
	/**
187
	 * @param string $id
188
	 * @return object|void
189
	 */
190
	final protected function _get_node( $id ) {
191
		if ( $this->bound )
192
			return;
193
194
		if ( empty( $id ) )
195
			$id = 'root';
196
197
		if ( isset( $this->nodes[ $id ] ) )
198
			return $this->nodes[ $id ];
199
	}
200
201
	/**
202
	 * @return array|void
203
	 */
204
	final public function get_nodes() {
205
		if ( ! $nodes = $this->_get_nodes() )
206
			return;
207
208
		foreach ( $nodes as &$node ) {
209
			$node = clone $node;
210
		}
211
		return $nodes;
212
	}
213
214
	/**
215
	 * @return array|void
216
	 */
217
	final protected function _get_nodes() {
218
		if ( $this->bound )
219
			return;
220
221
		return $this->nodes;
222
	}
223
224
	/**
225
	 * Add a group to a menu node.
226
	 *
227
	 * @since 3.3.0
228
	 *
229
	 * @param array $args {
230
	 *     Array of arguments for adding a group.
231
	 *
232
	 *     @type string $id     ID of the item.
233
	 *     @type string $parent Optional. ID of the parent node. Default 'root'.
234
	 *     @type array  $meta   Meta data for the group including the following keys:
235
	 *                         'class', 'onclick', 'target', and 'title'.
236
	 * }
237
	 */
238
	final public function add_group( $args ) {
239
		$args['group'] = true;
240
241
		$this->add_node( $args );
242
	}
243
244
	/**
245
	 * Remove a node.
246
	 *
247
	 * @param string $id The ID of the item.
248
	 */
249
	public function remove_node( $id ) {
250
		$this->_unset_node( $id );
251
	}
252
253
	/**
254
	 * @param string $id
255
	 */
256
	final protected function _unset_node( $id ) {
257
		unset( $this->nodes[ $id ] );
258
	}
259
260
	/**
261
	 * @access public
262
	 */
263
	public function render() {
264
		$root = $this->_bind();
265
		if ( $root )
266
			$this->_render( $root );
267
	}
268
269
	/**
270
	 * @return object|void
271
	 */
272
	final protected function _bind() {
273
		if ( $this->bound )
274
			return;
275
276
		// Add the root node.
277
		// Clear it first, just in case. Don't mess with The Root.
278
		$this->remove_node( 'root' );
279
		$this->add_node( array(
280
			'id'    => 'root',
281
			'group' => false,
282
		) );
283
284
		// Normalize nodes: define internal 'children' and 'type' properties.
285
		foreach ( $this->_get_nodes() as $node ) {
0 ignored issues
show
The expression $this->_get_nodes() of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
286
			$node->children = array();
287
			$node->type = ( $node->group ) ? 'group' : 'item';
288
			unset( $node->group );
289
290
			// The Root wants your orphans. No lonely items allowed.
291
			if ( ! $node->parent )
292
				$node->parent = 'root';
293
		}
294
295
		foreach ( $this->_get_nodes() as $node ) {
0 ignored issues
show
The expression $this->_get_nodes() of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
296
			if ( 'root' == $node->id )
297
				continue;
298
299
			// Fetch the parent node. If it isn't registered, ignore the node.
300
			if ( ! $parent = $this->_get_node( $node->parent ) ) {
0 ignored issues
show
Are you sure the assignment to $parent is correct as $this->_get_node($node->parent) (which targets WP_Admin_Bar::_get_node()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
301
				continue;
302
			}
303
304
			// Generate the group class (we distinguish between top level and other level groups).
305
			$group_class = ( $node->parent == 'root' ) ? 'ab-top-menu' : 'ab-submenu';
306
307
			if ( $node->type == 'group' ) {
308
				if ( empty( $node->meta['class'] ) )
309
					$node->meta['class'] = $group_class;
310
				else
311
					$node->meta['class'] .= ' ' . $group_class;
312
			}
313
314
			// Items in items aren't allowed. Wrap nested items in 'default' groups.
315
			if ( $parent->type == 'item' && $node->type == 'item' ) {
316
				$default_id = $parent->id . '-default';
317
				$default    = $this->_get_node( $default_id );
318
319
				// The default group is added here to allow groups that are
320
				// added before standard menu items to render first.
321
				if ( ! $default ) {
322
					// Use _set_node because add_node can be overloaded.
323
					// Make sure to specify default settings for all properties.
324
					$this->_set_node( array(
325
						'id'        => $default_id,
326
						'parent'    => $parent->id,
327
						'type'      => 'group',
328
						'children'  => array(),
329
						'meta'      => array(
330
							'class'     => $group_class,
331
						),
332
						'title'     => false,
333
						'href'      => false,
334
					) );
335
					$default = $this->_get_node( $default_id );
336
					$parent->children[] = $default;
337
				}
338
				$parent = $default;
339
340
			// Groups in groups aren't allowed. Add a special 'container' node.
341
			// The container will invisibly wrap both groups.
342
			} elseif ( $parent->type == 'group' && $node->type == 'group' ) {
343
				$container_id = $parent->id . '-container';
344
				$container    = $this->_get_node( $container_id );
345
346
				// We need to create a container for this group, life is sad.
347
				if ( ! $container ) {
348
					// Use _set_node because add_node can be overloaded.
349
					// Make sure to specify default settings for all properties.
350
					$this->_set_node( array(
351
						'id'       => $container_id,
352
						'type'     => 'container',
353
						'children' => array( $parent ),
354
						'parent'   => false,
355
						'title'    => false,
356
						'href'     => false,
357
						'meta'     => array(),
358
					) );
359
360
					$container = $this->_get_node( $container_id );
361
362
					// Link the container node if a grandparent node exists.
363
					$grandparent = $this->_get_node( $parent->parent );
364
365
					if ( $grandparent ) {
366
						$container->parent = $grandparent->id;
367
368
						$index = array_search( $parent, $grandparent->children, true );
369
						if ( $index === false )
370
							$grandparent->children[] = $container;
371
						else
372
							array_splice( $grandparent->children, $index, 1, array( $container ) );
373
					}
374
375
					$parent->parent = $container->id;
376
				}
377
378
				$parent = $container;
379
			}
380
381
			// Update the parent ID (it might have changed).
382
			$node->parent = $parent->id;
383
384
			// Add the node to the tree.
385
			$parent->children[] = $node;
386
		}
387
388
		$root = $this->_get_node( 'root' );
0 ignored issues
show
Are you sure the assignment to $root is correct as $this->_get_node('root') (which targets WP_Admin_Bar::_get_node()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
389
		$this->bound = true;
390
		return $root;
391
	}
392
393
	/**
394
	 *
395
	 * @global bool $is_IE
396
	 * @param object $root
397
	 */
398
	final protected function _render( $root ) {
399
		global $is_IE;
400
401
		// Add browser classes.
402
		// We have to do this here since admin bar shows on the front end.
403
		$class = 'nojq nojs';
404
		if ( $is_IE ) {
405
			if ( strpos( $_SERVER['HTTP_USER_AGENT'], 'MSIE 7' ) )
406
				$class .= ' ie7';
407
			elseif ( strpos( $_SERVER['HTTP_USER_AGENT'], 'MSIE 8' ) )
408
				$class .= ' ie8';
409
			elseif ( strpos( $_SERVER['HTTP_USER_AGENT'], 'MSIE 9' ) )
410
				$class .= ' ie9';
411
		} elseif ( wp_is_mobile() ) {
412
			$class .= ' mobile';
413
		}
414
415
		?>
416
		<div id="wpadminbar" class="<?php echo $class; ?>">
417
			<?php if ( ! is_admin() ) { ?>
418
				<a class="screen-reader-shortcut" href="#wp-toolbar" tabindex="1"><?php _e( 'Skip to toolbar' ); ?></a>
419
			<?php } ?>
420
			<div class="quicklinks" id="wp-toolbar" role="navigation" aria-label="<?php esc_attr_e( 'Toolbar' ); ?>" tabindex="0">
421
				<?php foreach ( $root->children as $group ) {
422
					$this->_render_group( $group );
423
				} ?>
424
			</div>
425
			<?php if ( is_user_logged_in() ) : ?>
426
			<a class="screen-reader-shortcut" href="<?php echo esc_url( wp_logout_url() ); ?>"><?php _e('Log Out'); ?></a>
427
			<?php endif; ?>
428
		</div>
429
430
		<?php
431
	}
432
433
	/**
434
	 * @param object $node
435
	 */
436
	final protected function _render_container( $node ) {
437
		if ( $node->type != 'container' || empty( $node->children ) )
438
			return;
439
440
		?><div id="<?php echo esc_attr( 'wp-admin-bar-' . $node->id ); ?>" class="ab-group-container"><?php
441
			foreach ( $node->children as $group ) {
442
				$this->_render_group( $group );
443
			}
444
		?></div><?php
445
	}
446
447
	/**
448
	 * @param object $node
449
	 */
450
	final protected function _render_group( $node ) {
451
		if ( $node->type == 'container' ) {
452
			$this->_render_container( $node );
453
			return;
454
		}
455
		if ( $node->type != 'group' || empty( $node->children ) )
456
			return;
457
458 View Code Duplication
		if ( ! empty( $node->meta['class'] ) )
459
			$class = ' class="' . esc_attr( trim( $node->meta['class'] ) ) . '"';
460
		else
461
			$class = '';
462
463
		?><ul id="<?php echo esc_attr( 'wp-admin-bar-' . $node->id ); ?>"<?php echo $class; ?>><?php
464
			foreach ( $node->children as $item ) {
465
				$this->_render_item( $item );
466
			}
467
		?></ul><?php
468
	}
469
470
	/**
471
	 * @param object $node
472
	 */
473
	final protected function _render_item( $node ) {
474
		if ( $node->type != 'item' )
475
			return;
476
477
		$is_parent = ! empty( $node->children );
478
		$has_link  = ! empty( $node->href );
479
480
		// Allow only numeric values, then casted to integers, and allow a tabindex value of `0` for a11y.
481
		$tabindex = ( isset( $node->meta['tabindex'] ) && is_numeric( $node->meta['tabindex'] ) ) ? (int) $node->meta['tabindex'] : '';
482
		$aria_attributes = ( '' !== $tabindex ) ? ' tabindex="' . $tabindex . '"' : '';
483
484
		$menuclass = '';
485
486
		if ( $is_parent ) {
487
			$menuclass = 'menupop ';
488
			$aria_attributes .= ' aria-haspopup="true"';
489
		}
490
491
		if ( ! empty( $node->meta['class'] ) )
492
			$menuclass .= $node->meta['class'];
493
494
		if ( $menuclass )
495
			$menuclass = ' class="' . esc_attr( trim( $menuclass ) ) . '"';
496
497
		?>
498
499
		<li id="<?php echo esc_attr( 'wp-admin-bar-' . $node->id ); ?>"<?php echo $menuclass; ?>><?php
500
			if ( $has_link ):
501
				?><a class="ab-item"<?php echo $aria_attributes; ?> href="<?php echo esc_url( $node->href ) ?>"<?php
502
					if ( ! empty( $node->meta['onclick'] ) ) :
503
						?> onclick="<?php echo esc_js( $node->meta['onclick'] ); ?>"<?php
504
					endif;
505
				if ( ! empty( $node->meta['target'] ) ) :
506
					?> target="<?php echo esc_attr( $node->meta['target'] ); ?>"<?php
507
				endif;
508 View Code Duplication
				if ( ! empty( $node->meta['title'] ) ) :
509
					?> title="<?php echo esc_attr( $node->meta['title'] ); ?>"<?php
510
				endif;
511 View Code Duplication
				if ( ! empty( $node->meta['rel'] ) ) :
512
					?> rel="<?php echo esc_attr( $node->meta['rel'] ); ?>"<?php
513
				endif;
514 View Code Duplication
				if ( ! empty( $node->meta['lang'] ) ) :
515
					?> lang="<?php echo esc_attr( $node->meta['lang'] ); ?>"<?php
516
				endif;
517 View Code Duplication
				if ( ! empty( $node->meta['dir'] ) ) :
518
					?> dir="<?php echo esc_attr( $node->meta['dir'] ); ?>"<?php
519
				endif;
520
				?>><?php
521
			else:
522
				?><div class="ab-item ab-empty-item"<?php echo $aria_attributes;
523 View Code Duplication
				if ( ! empty( $node->meta['title'] ) ) :
524
					?> title="<?php echo esc_attr( $node->meta['title'] ); ?>"<?php
525
				endif;
526 View Code Duplication
				if ( ! empty( $node->meta['lang'] ) ) :
527
					?> lang="<?php echo esc_attr( $node->meta['lang'] ); ?>"<?php
528
				endif;
529 View Code Duplication
				if ( ! empty( $node->meta['dir'] ) ) :
530
					?> dir="<?php echo esc_attr( $node->meta['dir'] ); ?>"<?php
531
				endif;
532
				?>><?php
533
			endif;
534
535
			echo $node->title;
536
537
			if ( $has_link ) :
538
				?></a><?php
539
			else:
540
				?></div><?php
541
			endif;
542
543
			if ( $is_parent ) :
544
				?><div class="ab-sub-wrapper"><?php
545
					foreach ( $node->children as $group ) {
546
						$this->_render_group( $group );
547
					}
548
				?></div><?php
549
			endif;
550
551
			if ( ! empty( $node->meta['html'] ) )
552
				echo $node->meta['html'];
553
554
			?>
555
		</li><?php
556
	}
557
558
	/**
559
	 * @param string $id    Unused.
560
	 * @param object $node
561
	 */
562
	public function recursive_render( $id, $node ) {
0 ignored issues
show
The parameter $id 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...
563
		_deprecated_function( __METHOD__, '3.3.0', 'WP_Admin_bar::render(), WP_Admin_Bar::_render_item()' );
564
		$this->_render_item( $node );
565
	}
566
567
	/**
568
	 * @access public
569
	 */
570
	public function add_menus() {
571
		// User related, aligned right.
572
		add_action( 'admin_bar_menu', 'wp_admin_bar_my_account_menu', 0 );
573
		add_action( 'admin_bar_menu', 'wp_admin_bar_search_menu', 4 );
574
		add_action( 'admin_bar_menu', 'wp_admin_bar_my_account_item', 7 );
575
576
		// Site related.
577
		add_action( 'admin_bar_menu', 'wp_admin_bar_sidebar_toggle', 0 );
578
		add_action( 'admin_bar_menu', 'wp_admin_bar_wp_menu', 10 );
579
		add_action( 'admin_bar_menu', 'wp_admin_bar_my_sites_menu', 20 );
580
		add_action( 'admin_bar_menu', 'wp_admin_bar_site_menu', 30 );
581
		add_action( 'admin_bar_menu', 'wp_admin_bar_customize_menu', 40 );
582
		add_action( 'admin_bar_menu', 'wp_admin_bar_updates_menu', 50 );
583
584
		// Content related.
585
		if ( ! is_network_admin() && ! is_user_admin() ) {
586
			add_action( 'admin_bar_menu', 'wp_admin_bar_comments_menu', 60 );
587
			add_action( 'admin_bar_menu', 'wp_admin_bar_new_content_menu', 70 );
588
		}
589
		add_action( 'admin_bar_menu', 'wp_admin_bar_edit_menu', 80 );
590
591
		add_action( 'admin_bar_menu', 'wp_admin_bar_add_secondary_groups', 200 );
592
593
		/**
594
		 * Fires after menus are added to the menu bar.
595
		 *
596
		 * @since 3.1.0
597
		 */
598
		do_action( 'add_admin_bar_menus' );
599
	}
600
}
601