wp/wp-includes/class-wp-admin-bar.php
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
     1 <?php
     1 <?php
     2 /**
     2 /**
     3  * The WordPress Toolbar
     3  * Toolbar API: WP_Admin_Bar class
     4  *
       
     5  * @since 3.1.0
       
     6  *
     4  *
     7  * @package WordPress
     5  * @package WordPress
     8  * @subpackage Toolbar
     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
     9  */
    14  */
    10 class WP_Admin_Bar {
    15 class WP_Admin_Bar {
    11 	private $nodes = array();
    16 	private $nodes = array();
    12 	private $bound = false;
    17 	private $bound = false;
    13 	public $user;
    18 	public $user;
    14 
    19 
       
    20 	/**
       
    21 	 * @param string $name
       
    22 	 * @return string|array|void
       
    23 	 */
    15 	public function __get( $name ) {
    24 	public function __get( $name ) {
    16 		switch ( $name ) {
    25 		switch ( $name ) {
    17 			case 'proto' :
    26 			case 'proto' :
    18 				return is_ssl() ? 'https://' : 'http://';
    27 				return is_ssl() ? 'https://' : 'http://';
    19 
    28 
    20 			case 'menu' :
    29 			case 'menu' :
    21 				_deprecated_argument( 'WP_Admin_Bar', '3.3', '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.' );
    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.' );
    22 				return array(); // Sorry, folks.
    31 				return array(); // Sorry, folks.
    23 		}
    32 		}
    24 	}
    33 	}
    25 
    34 
       
    35 	/**
       
    36 	 */
    26 	public function initialize() {
    37 	public function initialize() {
    27 		$this->user = new stdClass;
    38 		$this->user = new stdClass;
    28 
    39 
    29 		if ( is_user_logged_in() ) {
    40 		if ( is_user_logged_in() ) {
    30 			/* Populate settings we need for the menu based on the current user. */
    41 			/* Populate settings we need for the menu based on the current user. */
    67 		 * @since 3.1.0
    78 		 * @since 3.1.0
    68 		 */
    79 		 */
    69 		do_action( 'admin_bar_init' );
    80 		do_action( 'admin_bar_init' );
    70 	}
    81 	}
    71 
    82 
       
    83 	/**
       
    84 	 * @param array $node
       
    85 	 */
    72 	public function add_menu( $node ) {
    86 	public function add_menu( $node ) {
    73 		$this->add_node( $node );
    87 		$this->add_node( $node );
    74 	}
    88 	}
    75 
    89 
       
    90 	/**
       
    91 	 * @param string $id
       
    92 	 */
    76 	public function remove_menu( $id ) {
    93 	public function remove_menu( $id ) {
    77 		$this->remove_node( $id );
    94 		$this->remove_node( $id );
    78 	}
    95 	}
    79 
    96 
    80 	/**
    97 	/**
    81 	 * Add a node to the menu.
    98 	 * Adds a node to the menu.
       
    99 	 *
       
   100 	 * @since 3.1.0
       
   101 	 * @since 4.5.0 Added the ability to pass 'lang' and 'dir' meta data.
    82 	 *
   102 	 *
    83 	 * @param array $args {
   103 	 * @param array $args {
    84 	 *     Arguments for adding a node.
   104 	 *     Arguments for adding a node.
    85 	 *
   105 	 *
    86 	 *     @type string $id     ID of the item.
   106 	 *     @type string $id     ID of the item.
    87 	 *     @type string $title  Title of the node.
   107 	 *     @type string $title  Title of the node.
    88 	 *     @type string $parent Optional. ID of the parent node.
   108 	 *     @type string $parent Optional. ID of the parent node.
    89 	 *     @type string $href   Optional. Link for the item.
   109 	 *     @type string $href   Optional. Link for the item.
    90 	 *     @type bool   $group  Optional. Whether or not the node is a group. Default false.
   110 	 *     @type bool   $group  Optional. Whether or not the node is a group. Default false.
    91 	 *     @type array  $meta   Meta data including the following keys: 'html', 'class', 'rel',
   111 	 *     @type array  $meta   Meta data including the following keys: 'html', 'class', 'rel', 'lang', 'dir',
    92 	 *                          'onclick', 'target', 'title', 'tabindex'. Default empty.
   112 	 *                          'onclick', 'target', 'title', 'tabindex'. Default empty.
    93 	 * }
   113 	 * }
    94 	 */
   114 	 */
    95 	public function add_node( $args ) {
   115 	public function add_node( $args ) {
    96 		// Shim for old method signature: add_node( $parent_id, $menu_obj, $args )
   116 		// Shim for old method signature: add_node( $parent_id, $menu_obj, $args )
   103 		// Ensure we have a valid title.
   123 		// Ensure we have a valid title.
   104 		if ( empty( $args['id'] ) ) {
   124 		if ( empty( $args['id'] ) ) {
   105 			if ( empty( $args['title'] ) )
   125 			if ( empty( $args['title'] ) )
   106 				return;
   126 				return;
   107 
   127 
   108 			_doing_it_wrong( __METHOD__, __( 'The menu ID should not be empty.' ), '3.3' );
   128 			_doing_it_wrong( __METHOD__, __( 'The menu ID should not be empty.' ), '3.3.0' );
   109 			// Deprecated: Generate an ID from the title.
   129 			// Deprecated: Generate an ID from the title.
   110 			$args['id'] = esc_attr( sanitize_title( trim( $args['title'] ) ) );
   130 			$args['id'] = esc_attr( sanitize_title( trim( $args['title'] ) ) );
   111 		}
   131 		}
   112 
   132 
   113 		$defaults = array(
   133 		$defaults = array(
   141 		}
   161 		}
   142 
   162 
   143 		$this->_set_node( $args );
   163 		$this->_set_node( $args );
   144 	}
   164 	}
   145 
   165 
       
   166 	/**
       
   167 	 * @param array $args
       
   168 	 */
   146 	final protected function _set_node( $args ) {
   169 	final protected function _set_node( $args ) {
   147 		$this->nodes[ $args['id'] ] = (object) $args;
   170 		$this->nodes[ $args['id'] ] = (object) $args;
   148 	}
   171 	}
   149 
   172 
   150 	/**
   173 	/**
   151 	 * Gets a node.
   174 	 * Gets a node.
   152 	 *
   175 	 *
       
   176 	 * @param string $id
   153 	 * @return object Node.
   177 	 * @return object Node.
   154 	 */
   178 	 */
   155 	final public function get_node( $id ) {
   179 	final public function get_node( $id ) {
   156 		if ( $node = $this->_get_node( $id ) )
   180 		if ( $node = $this->_get_node( $id ) )
   157 			return clone $node;
   181 			return clone $node;
   158 	}
   182 	}
   159 
   183 
       
   184 	/**
       
   185 	 * @param string $id
       
   186 	 * @return object|void
       
   187 	 */
   160 	final protected function _get_node( $id ) {
   188 	final protected function _get_node( $id ) {
   161 		if ( $this->bound )
   189 		if ( $this->bound )
   162 			return;
   190 			return;
   163 
   191 
   164 		if ( empty( $id ) )
   192 		if ( empty( $id ) )
   166 
   194 
   167 		if ( isset( $this->nodes[ $id ] ) )
   195 		if ( isset( $this->nodes[ $id ] ) )
   168 			return $this->nodes[ $id ];
   196 			return $this->nodes[ $id ];
   169 	}
   197 	}
   170 
   198 
       
   199 	/**
       
   200 	 * @return array|void
       
   201 	 */
   171 	final public function get_nodes() {
   202 	final public function get_nodes() {
   172 		if ( ! $nodes = $this->_get_nodes() )
   203 		if ( ! $nodes = $this->_get_nodes() )
   173 			return;
   204 			return;
   174 
   205 
   175 		foreach ( $nodes as &$node ) {
   206 		foreach ( $nodes as &$node ) {
   176 			$node = clone $node;
   207 			$node = clone $node;
   177 		}
   208 		}
   178 		return $nodes;
   209 		return $nodes;
   179 	}
   210 	}
   180 
   211 
       
   212 	/**
       
   213 	 * @return array|void
       
   214 	 */
   181 	final protected function _get_nodes() {
   215 	final protected function _get_nodes() {
   182 		if ( $this->bound )
   216 		if ( $this->bound )
   183 			return;
   217 			return;
   184 
   218 
   185 		return $this->nodes;
   219 		return $this->nodes;
   206 	}
   240 	}
   207 
   241 
   208 	/**
   242 	/**
   209 	 * Remove a node.
   243 	 * Remove a node.
   210 	 *
   244 	 *
   211 	 * @param string The ID of the item.
   245 	 * @param string $id The ID of the item.
   212 	 */
   246 	 */
   213 	public function remove_node( $id ) {
   247 	public function remove_node( $id ) {
   214 		$this->_unset_node( $id );
   248 		$this->_unset_node( $id );
   215 	}
   249 	}
   216 
   250 
       
   251 	/**
       
   252 	 * @param string $id
       
   253 	 */
   217 	final protected function _unset_node( $id ) {
   254 	final protected function _unset_node( $id ) {
   218 		unset( $this->nodes[ $id ] );
   255 		unset( $this->nodes[ $id ] );
   219 	}
   256 	}
   220 
   257 
       
   258 	/**
       
   259 	 */
   221 	public function render() {
   260 	public function render() {
   222 		$root = $this->_bind();
   261 		$root = $this->_bind();
   223 		if ( $root )
   262 		if ( $root )
   224 			$this->_render( $root );
   263 			$this->_render( $root );
   225 	}
   264 	}
   226 
   265 
       
   266 	/**
       
   267 	 * @return object|void
       
   268 	 */
   227 	final protected function _bind() {
   269 	final protected function _bind() {
   228 		if ( $this->bound )
   270 		if ( $this->bound )
   229 			return;
   271 			return;
   230 
   272 
   231 		// Add the root node.
   273 		// Add the root node.
   343 		$root = $this->_get_node( 'root' );
   385 		$root = $this->_get_node( 'root' );
   344 		$this->bound = true;
   386 		$this->bound = true;
   345 		return $root;
   387 		return $root;
   346 	}
   388 	}
   347 
   389 
       
   390 	/**
       
   391 	 *
       
   392 	 * @global bool $is_IE
       
   393 	 * @param object $root
       
   394 	 */
   348 	final protected function _render( $root ) {
   395 	final protected function _render( $root ) {
   349 		global $is_IE;
   396 		global $is_IE;
   350 
   397 
   351 		// Add browser classes.
   398 		// Add browser classes.
   352 		// We have to do this here since admin bar shows on the front end.
   399 		// We have to do this here since admin bar shows on the front end.
   378 		</div>
   425 		</div>
   379 
   426 
   380 		<?php
   427 		<?php
   381 	}
   428 	}
   382 
   429 
       
   430 	/**
       
   431 	 * @param object $node
       
   432 	 */
   383 	final protected function _render_container( $node ) {
   433 	final protected function _render_container( $node ) {
   384 		if ( $node->type != 'container' || empty( $node->children ) )
   434 		if ( $node->type != 'container' || empty( $node->children ) )
   385 			return;
   435 			return;
   386 
   436 
   387 		?><div id="<?php echo esc_attr( 'wp-admin-bar-' . $node->id ); ?>" class="ab-group-container"><?php
   437 		?><div id="<?php echo esc_attr( 'wp-admin-bar-' . $node->id ); ?>" class="ab-group-container"><?php
   389 				$this->_render_group( $group );
   439 				$this->_render_group( $group );
   390 			}
   440 			}
   391 		?></div><?php
   441 		?></div><?php
   392 	}
   442 	}
   393 
   443 
       
   444 	/**
       
   445 	 * @param object $node
       
   446 	 */
   394 	final protected function _render_group( $node ) {
   447 	final protected function _render_group( $node ) {
   395 		if ( $node->type == 'container' )
   448 		if ( $node->type == 'container' ) {
   396 			return $this->_render_container( $node );
   449 			$this->_render_container( $node );
   397 
   450 			return;
       
   451 		}
   398 		if ( $node->type != 'group' || empty( $node->children ) )
   452 		if ( $node->type != 'group' || empty( $node->children ) )
   399 			return;
   453 			return;
   400 
   454 
   401 		if ( ! empty( $node->meta['class'] ) )
   455 		if ( ! empty( $node->meta['class'] ) )
   402 			$class = ' class="' . esc_attr( trim( $node->meta['class'] ) ) . '"';
   456 			$class = ' class="' . esc_attr( trim( $node->meta['class'] ) ) . '"';
   408 				$this->_render_item( $item );
   462 				$this->_render_item( $item );
   409 			}
   463 			}
   410 		?></ul><?php
   464 		?></ul><?php
   411 	}
   465 	}
   412 
   466 
       
   467 	/**
       
   468 	 * @param object $node
       
   469 	 */
   413 	final protected function _render_item( $node ) {
   470 	final protected function _render_item( $node ) {
   414 		if ( $node->type != 'item' )
   471 		if ( $node->type != 'item' )
   415 			return;
   472 			return;
   416 
   473 
   417 		$is_parent = ! empty( $node->children );
   474 		$is_parent = ! empty( $node->children );
   418 		$has_link  = ! empty( $node->href );
   475 		$has_link  = ! empty( $node->href );
   419 
   476 
   420 		$tabindex = isset( $node->meta['tabindex'] ) ? (int) $node->meta['tabindex'] : '';
   477 		// Allow only numeric values, then casted to integers, and allow a tabindex value of `0` for a11y.
   421 		$aria_attributes = $tabindex ? 'tabindex="' . $tabindex . '"' : '';
   478 		$tabindex = ( isset( $node->meta['tabindex'] ) && is_numeric( $node->meta['tabindex'] ) ) ? (int) $node->meta['tabindex'] : '';
       
   479 		$aria_attributes = ( '' !== $tabindex ) ? ' tabindex="' . $tabindex . '"' : '';
   422 
   480 
   423 		$menuclass = '';
   481 		$menuclass = '';
   424 
   482 
   425 		if ( $is_parent ) {
   483 		if ( $is_parent ) {
   426 			$menuclass = 'menupop ';
   484 			$menuclass = 'menupop ';
   435 
   493 
   436 		?>
   494 		?>
   437 
   495 
   438 		<li id="<?php echo esc_attr( 'wp-admin-bar-' . $node->id ); ?>"<?php echo $menuclass; ?>><?php
   496 		<li id="<?php echo esc_attr( 'wp-admin-bar-' . $node->id ); ?>"<?php echo $menuclass; ?>><?php
   439 			if ( $has_link ):
   497 			if ( $has_link ):
   440 				?><a class="ab-item" <?php echo $aria_attributes; ?> href="<?php echo esc_url( $node->href ) ?>"<?php
   498 				?><a class="ab-item"<?php echo $aria_attributes; ?> href="<?php echo esc_url( $node->href ) ?>"<?php
   441 					if ( ! empty( $node->meta['onclick'] ) ) :
   499 					if ( ! empty( $node->meta['onclick'] ) ) :
   442 						?> onclick="<?php echo esc_js( $node->meta['onclick'] ); ?>"<?php
   500 						?> onclick="<?php echo esc_js( $node->meta['onclick'] ); ?>"<?php
   443 					endif;
   501 					endif;
   444 				if ( ! empty( $node->meta['target'] ) ) :
   502 				if ( ! empty( $node->meta['target'] ) ) :
   445 					?> target="<?php echo esc_attr( $node->meta['target'] ); ?>"<?php
   503 					?> target="<?php echo esc_attr( $node->meta['target'] ); ?>"<?php
   448 					?> title="<?php echo esc_attr( $node->meta['title'] ); ?>"<?php
   506 					?> title="<?php echo esc_attr( $node->meta['title'] ); ?>"<?php
   449 				endif;
   507 				endif;
   450 				if ( ! empty( $node->meta['rel'] ) ) :
   508 				if ( ! empty( $node->meta['rel'] ) ) :
   451 					?> rel="<?php echo esc_attr( $node->meta['rel'] ); ?>"<?php
   509 					?> rel="<?php echo esc_attr( $node->meta['rel'] ); ?>"<?php
   452 				endif;
   510 				endif;
       
   511 				if ( ! empty( $node->meta['lang'] ) ) :
       
   512 					?> lang="<?php echo esc_attr( $node->meta['lang'] ); ?>"<?php
       
   513 				endif;
       
   514 				if ( ! empty( $node->meta['dir'] ) ) :
       
   515 					?> dir="<?php echo esc_attr( $node->meta['dir'] ); ?>"<?php
       
   516 				endif;
   453 				?>><?php
   517 				?>><?php
   454 			else:
   518 			else:
   455 				?><div class="ab-item ab-empty-item" <?php echo $aria_attributes;
   519 				?><div class="ab-item ab-empty-item"<?php echo $aria_attributes;
   456 				if ( ! empty( $node->meta['title'] ) ) :
   520 				if ( ! empty( $node->meta['title'] ) ) :
   457 					?> title="<?php echo esc_attr( $node->meta['title'] ); ?>"<?php
   521 					?> title="<?php echo esc_attr( $node->meta['title'] ); ?>"<?php
       
   522 				endif;
       
   523 				if ( ! empty( $node->meta['lang'] ) ) :
       
   524 					?> lang="<?php echo esc_attr( $node->meta['lang'] ); ?>"<?php
       
   525 				endif;
       
   526 				if ( ! empty( $node->meta['dir'] ) ) :
       
   527 					?> dir="<?php echo esc_attr( $node->meta['dir'] ); ?>"<?php
   458 				endif;
   528 				endif;
   459 				?>><?php
   529 				?>><?php
   460 			endif;
   530 			endif;
   461 
   531 
   462 			echo $node->title;
   532 			echo $node->title;
   480 
   550 
   481 			?>
   551 			?>
   482 		</li><?php
   552 		</li><?php
   483 	}
   553 	}
   484 
   554 
       
   555 	/**
       
   556 	 * Renders toolbar items recursively.
       
   557 	 *
       
   558 	 * @since 3.1.0
       
   559 	 * @deprecated 3.3.0 Use WP_Admin_Bar::_render_item() or WP_Admin_bar::render() instead.
       
   560 	 * @see WP_Admin_Bar::_render_item()
       
   561 	 * @see WP_Admin_Bar::render()
       
   562 	 *
       
   563 	 * @param string $id    Unused.
       
   564 	 * @param object $node
       
   565 	 */
   485 	public function recursive_render( $id, $node ) {
   566 	public function recursive_render( $id, $node ) {
   486 		_deprecated_function( __METHOD__, '3.3', 'WP_Admin_bar::render(), WP_Admin_Bar::_render_item()' );
   567 		_deprecated_function( __METHOD__, '3.3.0', 'WP_Admin_bar::render(), WP_Admin_Bar::_render_item()' );
   487 		$this->_render_item( $node );
   568 		$this->_render_item( $node );
   488 	}
   569 	}
   489 
   570 
       
   571 	/**
       
   572 	 */
   490 	public function add_menus() {
   573 	public function add_menus() {
   491 		// User related, aligned right.
   574 		// User related, aligned right.
   492 		add_action( 'admin_bar_menu', 'wp_admin_bar_my_account_menu', 0 );
   575 		add_action( 'admin_bar_menu', 'wp_admin_bar_my_account_menu', 0 );
   493 		add_action( 'admin_bar_menu', 'wp_admin_bar_search_menu', 4 );
   576 		add_action( 'admin_bar_menu', 'wp_admin_bar_search_menu', 4 );
   494 		add_action( 'admin_bar_menu', 'wp_admin_bar_my_account_item', 7 );
   577 		add_action( 'admin_bar_menu', 'wp_admin_bar_my_account_item', 7 );
   496 		// Site related.
   579 		// Site related.
   497 		add_action( 'admin_bar_menu', 'wp_admin_bar_sidebar_toggle', 0 );
   580 		add_action( 'admin_bar_menu', 'wp_admin_bar_sidebar_toggle', 0 );
   498 		add_action( 'admin_bar_menu', 'wp_admin_bar_wp_menu', 10 );
   581 		add_action( 'admin_bar_menu', 'wp_admin_bar_wp_menu', 10 );
   499 		add_action( 'admin_bar_menu', 'wp_admin_bar_my_sites_menu', 20 );
   582 		add_action( 'admin_bar_menu', 'wp_admin_bar_my_sites_menu', 20 );
   500 		add_action( 'admin_bar_menu', 'wp_admin_bar_site_menu', 30 );
   583 		add_action( 'admin_bar_menu', 'wp_admin_bar_site_menu', 30 );
   501 		add_action( 'admin_bar_menu', 'wp_admin_bar_updates_menu', 40 );
   584 		add_action( 'admin_bar_menu', 'wp_admin_bar_customize_menu', 40 );
       
   585 		add_action( 'admin_bar_menu', 'wp_admin_bar_updates_menu', 50 );
   502 
   586 
   503 		// Content related.
   587 		// Content related.
   504 		if ( ! is_network_admin() && ! is_user_admin() ) {
   588 		if ( ! is_network_admin() && ! is_user_admin() ) {
   505 			add_action( 'admin_bar_menu', 'wp_admin_bar_comments_menu', 60 );
   589 			add_action( 'admin_bar_menu', 'wp_admin_bar_comments_menu', 60 );
   506 			add_action( 'admin_bar_menu', 'wp_admin_bar_new_content_menu', 70 );
   590 			add_action( 'admin_bar_menu', 'wp_admin_bar_new_content_menu', 70 );