WP_Admin_Bar   D
last analyzed

Complexity

Total Complexity 103

Size/Duplication

Total Lines 586
Duplicated Lines 4.27 %

Coupling/Cohesion

Components 2
Dependencies 1

Importance

Changes 0
Metric Value
dl 25
loc 586
rs 4.8717
c 0
b 0
f 0
wmc 103
lcom 2
cbo 1

21 Methods

Rating   Name   Duplication   Size   Complexity  
A __get() 0 10 4
B initialize() 0 45 6
A add_menu() 0 3 1
A remove_menu() 0 3 1
C add_node() 0 50 10
A _set_node() 0 3 1
A get_node() 0 4 2
A _get_node() 0 10 4
A get_nodes() 0 9 3
A _get_nodes() 0 6 2
A add_group() 0 5 1
A remove_node() 0 3 1
A _unset_node() 0 3 1
A render() 0 5 2
D _bind() 0 120 19
D _render() 0 34 9
A _render_container() 0 10 4
B _render_group() 4 19 6
A recursive_render() 0 4 1
B add_menus() 0 30 3
F _render_item() 21 84 22

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like WP_Admin_Bar often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use WP_Admin_Bar, and based on these observations, apply Extract Interface, too.

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
Documentation introduced by
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
Bug introduced by
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
Bug introduced by
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
Bug introduced by
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
Bug introduced by
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
Unused Code introduced by
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