From a109cf8c6b70cfb0a9a208d2e36ddb68730442bd Mon Sep 17 00:00:00 2001 From: nacin Date: Thu, 1 Dec 2011 00:25:04 +0000 Subject: [PATCH] Finalize the WP_Admin_Bar architecture for 3.3. * Introduce a get_node() method for plugins. * Deprecate $wp_admin_bar->menu. Plugins will need to use get_node(), remove_node(), add_node() to make modifications. This finalizes a backwards incompatible change made earlier in the cycle. * Allow add_node() to take a node object (which could come from get_node(), then be modified). * Ensure that our underlying storage (the nodes property) is private to core. Introduce _set_node, _unset_node, _get_nodes, get_nodes as the only ways to interface with this. * Protect and finalize _render_item, and _render_group. render() remains public and technically overridable, though I would discourage this of plugin authors. * Deprecate recursive_render(). Use render() or _render_item(). More about the internals: * Late-binds a node's 'children' array. * Eliminates the root property, leverages a 'root' node. * Splits render() into _bind() and _render(), both protected and finalized. Fixes #19371. git-svn-id: http://svn.automattic.com/wordpress/trunk@19501 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/class-wp-admin-bar.php | 133 +++++++++++++++++++---------- 1 file changed, 90 insertions(+), 43 deletions(-) diff --git a/wp-includes/class-wp-admin-bar.php b/wp-includes/class-wp-admin-bar.php index 9755de879..2c4cd3d9a 100644 --- a/wp-includes/class-wp-admin-bar.php +++ b/wp-includes/class-wp-admin-bar.php @@ -1,22 +1,27 @@ proto = 'https://'; + public function __get( $name ) { + switch ( $name ) { + case 'proto' : + return is_ssl() ? 'https://' : 'http://'; + break; + case 'menu' : + _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 menu property.' ); + return array(); // Sorry, folks. + break; + } + } + public function initialize() { $this->user = new stdClass; - $this->root = (object) array( + + $this->add_node( array( 'id' => 'root', 'group' => false, - 'children' => array(), - ); + ) ); if ( is_user_logged_in() ) { /* Populate settings we need for the menu based on the current user. */ @@ -69,13 +74,16 @@ class WP_Admin_Bar { * - parent - string - The ID of the parent node. Optional. * - href - string - The link for the item. Optional. * - group - boolean - If the node is a group. Optional. Default false. - * - meta - array - Meta data including the following keys: html, class, onclick, target, title. + * - meta - array - Meta data including the following keys: html, class, onclick, target, title, tabindex. */ public function add_node( $args ) { // Shim for old method signature: add_node( $parent_id, $menu_obj, $args ) if ( func_num_args() >= 3 && is_string( func_get_arg(0) ) ) $args = array_merge( array( 'parent' => func_get_arg(0) ), func_get_arg(2) ); + if ( is_object( $args ) ) + $args = get_object_vars( $args ); + // Ensure we have a valid title. if ( empty( $args['id'] ) ) { if ( empty( $args['title'] ) ) @@ -96,52 +104,83 @@ class WP_Admin_Bar { ); // If the node already exists, keep any data that isn't provided. - if ( isset( $this->nodes[ $args['id'] ] ) ) - $defaults = (array) $this->nodes[ $args['id'] ]; + if ( $this->get_node( $args['id'] ) ) + $defaults = get_object_vars( $this->get_node( $args['id'] ) ); + + // Do the same for 'meta' items. + if ( ! empty( $defaults['meta'] ) && empty( $args['meta'] ) ) + $args['meta'] = wp_parse_args( $args['meta'], $defaults['meta'] ); $args = wp_parse_args( $args, $defaults ); - $args['children'] = array(); + $this->_set_node( $args ); + } + + final protected function _set_node( $args ) { $this->nodes[ $args['id'] ] = (object) $args; } + /** + * Gets a node. + * + * @return object Node. + */ + final public function get_node( $id ) { + if ( isset( $this->nodes[ $id ] ) ) + return $this->nodes[ $id ]; + } + + final protected function _get_nodes() { + return $this->nodes; + } + /** * Add a group to a menu node. * + * @since 3.3.0 + * * @param array $args - The arguments for each node. * - id - string - The ID of the item. * - parent - string - The ID of the parent node. Optional. Default root. * - meta - array - Meta data including the following keys: class, onclick, target, title. */ - public function add_group( $args ) { + final public function add_group( $args ) { $args['group'] = true; $this->add_node( $args ); } + /** + * Remove a node. + * + * @return object The removed node. + */ public function remove_node( $id ) { + $this->_unset_node( $id ); + } + + final protected function _unset_node( $id ) { unset( $this->nodes[ $id ] ); } public function render() { - global $is_IE, $is_iphone; + $this->_bind(); + $this->_render(); + } - // Link nodes to parents. - foreach ( $this->nodes as $node ) { + final protected function _bind() { + foreach ( $this->_get_nodes() as $node ) { + if ( 'root' == $node->id ) + continue; // Handle root menu items if ( empty( $node->parent ) ) { - $parent = $this->root; - - // If the parent node isn't registered, ignore the node. - } elseif ( ! isset( $this->nodes[ $node->parent ] ) ) { + $parent = $this->get_node( 'root' ); + } elseif ( ! $parent = $this->get_node( $node->parent ) ) { + // If the parent node isn't registered, ignore the node. continue; - - } else { - $parent = $this->nodes[ $node->parent ]; } - // Ensure that our tree is of the form "item -> group -> item -> group -> ..." if ( ! $parent->group && ! $node->group ) { // Both are items. // The default group is added here to allow groups that are @@ -160,9 +199,16 @@ class WP_Admin_Bar { // Update the parent ID (it might have changed). $node->parent = $parent->id; + if ( ! isset( $parent->children ) ) + $parent->children = array(); + // Add the node to the tree. $parent->children[] = $node; } + } + + final protected function _render() { + global $is_IE, $is_iphone; // Add browser classes. // We have to do this here since admin bar shows on the front end. @@ -181,8 +227,8 @@ class WP_Admin_Bar { ?> @@ -190,7 +236,7 @@ class WP_Admin_Bar { group ) return; @@ -211,36 +257,36 @@ class WP_Admin_Bar { $is_single_group = count( $groups ) === 1; - // If we don't have any subgroups, render the group. - if ( $is_single_group && ! empty( $node->children ) ): + if ( $is_single_group && ! empty( $node->children ) ) : if ( ! empty( $node->meta['class'] ) ) $class .= ' ' . $node->meta['class']; ?>
id}-container" ); ?>" class="ab-group-container" role="menu">render_group( $group, $class ); + $this->_render_group( $group, $class ); } ?>
group ) return; - $is_parent = (bool) $node->children; - $has_link = (bool) $node->href; - $tabindex = isset($node->meta['tabindex']) ? (int) $node->meta['tabindex'] : 10; + $is_parent = ! empty( $node->children ); + $has_link = ! empty( $node->href ); + + $tabindex = isset( $node->meta['tabindex'] ) ? (int) $node->meta['tabindex'] : 10; $menuclass = ''; $aria_attributes = 'tabindex="' . $tabindex . '" role="menuitem"'; @@ -278,7 +324,7 @@ class WP_Admin_Bar { echo $node->title; - if ( $has_link ): + if ( $has_link ) : ?>
children as $group ) { - $this->render_group( $group, 'ab-submenu' ); + $this->_render_group( $group, 'ab-submenu' ); } ?>
render_item( $node ); + public function recursive_render( $id, $node ) { + _deprecated_function( __METHOD__, '3.3', 'WP_Admin_bar::render(), WP_Admin_Bar::_render_item()' ); + $this->_render_item( $node ); } - function add_menus() { + public function add_menus() { // User related, aligned right. add_action( 'admin_bar_menu', 'wp_admin_bar_my_account_menu', 10 );