: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* @since 6.5.0 Added `$menu_title` parameter to allow an ARIA menu name.
* @param string|bool $menu_title The accessible name of this ARIA menu or false if not provided.
final protected function _render_group( $node, $menu_title = false ) {
if ( 'container' === $node->type ) {
$this->_render_container( $node );
if ( 'group' !== $node->type || empty( $node->children ) ) {
if ( ! empty( $node->meta['class'] ) ) {
$class = ' class="' . esc_attr( trim( $node->meta['class'] ) ) . '"';
if ( empty( $menu_title ) ) {
echo "<ul role='menu' id='" . esc_attr( 'wp-admin-bar-' . $node->id ) . "'$class>";
echo "<ul role='menu' aria-label='" . esc_attr( $menu_title ) . "' id='" . esc_attr( 'wp-admin-bar-' . $node->id ) . "'$class>";
foreach ( $node->children as $item ) {
$this->_render_item( $item );
final protected function _render_item( $node ) {
if ( 'item' !== $node->type ) {
$is_parent = ! empty( $node->children );
$has_link = ! empty( $node->href );
$is_root_top_item = 'root-default' === $node->parent;
$is_top_secondary_item = 'top-secondary' === $node->parent;
// Allow only numeric values, then casted to integers, and allow a tabindex value of `0` for a11y.
$tabindex = ( isset( $node->meta['tabindex'] ) && is_numeric( $node->meta['tabindex'] ) ) ? (int) $node->meta['tabindex'] : '';
$aria_attributes = ( '' !== $tabindex ) ? ' tabindex="' . $tabindex . '"' : '';
$aria_attributes .= ' role="menuitem"';
$aria_attributes .= ' aria-expanded="false"';
if ( ! empty( $node->meta['class'] ) ) {
$menuclass .= $node->meta['class'];
// Print the arrow icon for the menu children with children.
if ( ! $is_root_top_item && ! $is_top_secondary_item && $is_parent ) {
$arrow = '<span class="wp-admin-bar-arrow" aria-hidden="true"></span>';
$menuclass = ' class="' . esc_attr( trim( $menuclass ) ) . '"';
echo "<li role='group' id='" . esc_attr( 'wp-admin-bar-' . $node->id ) . "'$menuclass>";
$attributes = array( 'onclick', 'target', 'title', 'rel', 'lang', 'dir' );
echo "<a class='ab-item'$aria_attributes href='" . esc_url( $node->href ) . "'";
$attributes = array( 'onclick', 'target', 'title', 'rel', 'lang', 'dir' );
echo '<div class="ab-item ab-empty-item"' . $aria_attributes;
foreach ( $attributes as $attribute ) {
if ( empty( $node->meta[ $attribute ] ) ) {
if ( 'onclick' === $attribute ) {
echo " $attribute='" . esc_js( $node->meta[ $attribute ] ) . "'";
echo " $attribute='" . esc_attr( $node->meta[ $attribute ] ) . "'";
echo ">{$arrow}{$node->title}";
echo '<div class="ab-sub-wrapper">';
foreach ( $node->children as $group ) {
if ( empty( $node->meta['menu_title'] ) ) {
$this->_render_group( $group, false );
$this->_render_group( $group, $node->meta['menu_title'] );
if ( ! empty( $node->meta['html'] ) ) {
echo $node->meta['html'];
* Renders toolbar items recursively.
* @deprecated 3.3.0 Use WP_Admin_Bar::_render_item() or WP_Admin_bar::render() instead.
* @see WP_Admin_Bar::_render_item()
* @see WP_Admin_Bar::render()
* @param string $id Unused.
public function recursive_render( $id, $node ) {
_deprecated_function( __METHOD__, '3.3.0', 'WP_Admin_bar::render(), WP_Admin_Bar::_render_item()' );
$this->_render_item( $node );
* Adds menus to the admin bar.
public function add_menus() {
// User-related, aligned right.
add_action( 'admin_bar_menu', 'wp_admin_bar_my_account_menu', 0 );
add_action( 'admin_bar_menu', 'wp_admin_bar_my_account_item', 9991 );
add_action( 'admin_bar_menu', 'wp_admin_bar_recovery_mode_menu', 9992 );
add_action( 'admin_bar_menu', 'wp_admin_bar_search_menu', 9999 );
add_action( 'admin_bar_menu', 'wp_admin_bar_sidebar_toggle', 0 );
add_action( 'admin_bar_menu', 'wp_admin_bar_wp_menu', 10 );
add_action( 'admin_bar_menu', 'wp_admin_bar_my_sites_menu', 20 );
add_action( 'admin_bar_menu', 'wp_admin_bar_site_menu', 30 );
add_action( 'admin_bar_menu', 'wp_admin_bar_edit_site_menu', 40 );
add_action( 'admin_bar_menu', 'wp_admin_bar_customize_menu', 40 );
add_action( 'admin_bar_menu', 'wp_admin_bar_updates_menu', 50 );
if ( ! is_network_admin() && ! is_user_admin() ) {
add_action( 'admin_bar_menu', 'wp_admin_bar_comments_menu', 60 );
add_action( 'admin_bar_menu', 'wp_admin_bar_new_content_menu', 70 );
add_action( 'admin_bar_menu', 'wp_admin_bar_edit_menu', 80 );
add_action( 'admin_bar_menu', 'wp_admin_bar_add_secondary_groups', 200 );
* Fires after menus are added to the menu bar.
do_action( 'add_admin_bar_menus' );