[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/ -> admin-bar.php (source)

   1  <?php
   2  /**
   3   * Toolbar API: Top-level Toolbar functionality
   4   *
   5   * @package WordPress
   6   * @subpackage Toolbar
   7   * @since 3.1.0
   8   */
   9  
  10  /**
  11   * Instantiates the admin bar object and set it up as a global for access elsewhere.
  12   *
  13   * UNHOOKING THIS FUNCTION WILL NOT PROPERLY REMOVE THE ADMIN BAR.
  14   * For that, use show_admin_bar(false) or the {@see 'show_admin_bar'} filter.
  15   *
  16   * @since 3.1.0
  17   * @access private
  18   *
  19   * @global WP_Admin_Bar $wp_admin_bar
  20   *
  21   * @return bool Whether the admin bar was successfully initialized.
  22   */
  23  function _wp_admin_bar_init() {
  24      global $wp_admin_bar;
  25  
  26      if ( ! is_admin_bar_showing() ) {
  27          return false;
  28      }
  29  
  30      /* Load the admin bar class code ready for instantiation */
  31      require_once  ABSPATH . WPINC . '/class-wp-admin-bar.php';
  32  
  33      /* Instantiate the admin bar */
  34  
  35      /**
  36       * Filters the admin bar class to instantiate.
  37       *
  38       * @since 3.1.0
  39       *
  40       * @param string $wp_admin_bar_class Admin bar class to use. Default 'WP_Admin_Bar'.
  41       */
  42      $admin_bar_class = apply_filters( 'wp_admin_bar_class', 'WP_Admin_Bar' );
  43      if ( class_exists( $admin_bar_class ) ) {
  44          $wp_admin_bar = new $admin_bar_class();
  45      } else {
  46          return false;
  47      }
  48  
  49      $wp_admin_bar->initialize();
  50      $wp_admin_bar->add_menus();
  51  
  52      return true;
  53  }
  54  
  55  /**
  56   * Renders the admin bar to the page based on the $wp_admin_bar->menu member var.
  57   *
  58   * This is called very early on the {@see 'wp_body_open'} action so that it will render
  59   * before anything else being added to the page body.
  60   *
  61   * For backward compatibility with themes not using the 'wp_body_open' action,
  62   * the function is also called late on {@see 'wp_footer'}.
  63   *
  64   * It includes the {@see 'admin_bar_menu'} action which should be used to hook in and
  65   * add new menus to the admin bar. This also gives you access to the `$post` global,
  66   * among others.
  67   *
  68   * @since 3.1.0
  69   * @since 5.4.0 Called on 'wp_body_open' action first, with 'wp_footer' as a fallback.
  70   *
  71   * @global WP_Admin_Bar $wp_admin_bar
  72   */
  73  function wp_admin_bar_render() {
  74      global $wp_admin_bar;
  75      static $rendered = false;
  76  
  77      if ( $rendered ) {
  78          return;
  79      }
  80  
  81      if ( ! is_admin_bar_showing() || ! is_object( $wp_admin_bar ) ) {
  82          return;
  83      }
  84  
  85      /**
  86       * Loads all necessary admin bar items.
  87       *
  88       * This hook can add, remove, or manipulate admin bar items. The priority
  89       * determines the placement for new items, and changes to existing items
  90       * would require a high priority. To remove or manipulate existing nodes
  91       * without a specific priority, use `wp_before_admin_bar_render`.
  92       *
  93       * @since 3.1.0
  94       *
  95       * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance, passed by reference.
  96       */
  97      do_action_ref_array( 'admin_bar_menu', array( &$wp_admin_bar ) );
  98  
  99      /**
 100       * Fires before the admin bar is rendered.
 101       *
 102       * @since 3.1.0
 103       */
 104      do_action( 'wp_before_admin_bar_render' );
 105  
 106      $wp_admin_bar->render();
 107  
 108      /**
 109       * Fires after the admin bar is rendered.
 110       *
 111       * @since 3.1.0
 112       */
 113      do_action( 'wp_after_admin_bar_render' );
 114  
 115      $rendered = true;
 116  }
 117  
 118  /**
 119   * Returns inline SVG markup wrapped for use as an admin bar node icon.
 120   *
 121   * @since 7.2.0
 122   * @access private
 123   *
 124   * @param string $icon_name Namespaced icon name, e.g. 'core-admin/wordpress'.
 125   * @return string Admin bar icon markup. The wrapper is empty if the icon is not found.
 126   */
 127  function _wp_admin_bar_icon( $icon_name ) {
 128      return '<span class="ab-icon svg-icon" aria-hidden="true">' . wp_get_icon( $icon_name ) . '</span>';
 129  }
 130  
 131  /**
 132   * Adds the WordPress logo menu.
 133   *
 134   * @since 3.3.0
 135   *
 136   * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
 137   */
 138  function wp_admin_bar_wp_menu( $wp_admin_bar ) {
 139      if ( current_user_can( 'read' ) ) {
 140          $about_url      = self_admin_url( 'about.php' );
 141          $contribute_url = self_admin_url( 'contribute.php' );
 142      } elseif ( is_multisite() ) {
 143          $about_url      = get_dashboard_url( get_current_user_id(), 'about.php' );
 144          $contribute_url = get_dashboard_url( get_current_user_id(), 'contribute.php' );
 145      } else {
 146          $about_url      = false;
 147          $contribute_url = false;
 148      }
 149  
 150      $wp_logo_menu_args = array(
 151          'id'    => 'wp-logo',
 152          'title' => '<span class="ab-icon" aria-hidden="true"></span><span class="screen-reader-text">' .
 153                  /* translators: Hidden accessibility text. */
 154                  __( 'About WordPress' ) .
 155              '</span>',
 156          'href'  => $about_url,
 157          'meta'  => array(
 158              'menu_title' => __( 'About WordPress' ),
 159          ),
 160      );
 161  
 162      // Set tabindex="0" to make sub menus accessible when no URL is available.
 163      if ( ! $about_url ) {
 164          $wp_logo_menu_args['meta'] = array(
 165              'tabindex' => 0,
 166          );
 167      }
 168  
 169      $wp_admin_bar->add_node( $wp_logo_menu_args );
 170  
 171      if ( $about_url ) {
 172          // Add "About WordPress" link.
 173          $wp_admin_bar->add_node(
 174              array(
 175                  'parent' => 'wp-logo',
 176                  'id'     => 'about',
 177                  'title'  => __( 'About WordPress' ),
 178                  'href'   => $about_url,
 179              )
 180          );
 181      }
 182  
 183      if ( $contribute_url ) {
 184          // Add contribute link.
 185          $wp_admin_bar->add_node(
 186              array(
 187                  'parent' => 'wp-logo',
 188                  'id'     => 'contribute',
 189                  'title'  => __( 'Get Involved' ),
 190                  'href'   => $contribute_url,
 191              )
 192          );
 193      }
 194  
 195      // Add WordPress.org link.
 196      $wp_admin_bar->add_node(
 197          array(
 198              'parent' => 'wp-logo-external',
 199              'id'     => 'wporg',
 200              'title'  => __( 'WordPress.org' ),
 201              'href'   => __( 'https://wordpress.org/' ),
 202          )
 203      );
 204  
 205      // Add documentation link.
 206      $wp_admin_bar->add_node(
 207          array(
 208              'parent' => 'wp-logo-external',
 209              'id'     => 'documentation',
 210              'title'  => __( 'Documentation' ),
 211              'href'   => __( 'https://wordpress.org/documentation/' ),
 212          )
 213      );
 214  
 215      // Add learn link.
 216      $wp_admin_bar->add_node(
 217          array(
 218              'parent' => 'wp-logo-external',
 219              'id'     => 'learn',
 220              'title'  => __( 'Learn WordPress' ),
 221              'href'   => __( 'https://learn.wordpress.org/' ),
 222          )
 223      );
 224  
 225      // Add forums link.
 226      $wp_admin_bar->add_node(
 227          array(
 228              'parent' => 'wp-logo-external',
 229              'id'     => 'support-forums',
 230              'title'  => __( 'Support' ),
 231              'href'   => __( 'https://wordpress.org/support/forums/' ),
 232          )
 233      );
 234  
 235      // Add feedback link.
 236      $wp_admin_bar->add_node(
 237          array(
 238              'parent' => 'wp-logo-external',
 239              'id'     => 'feedback',
 240              'title'  => __( 'Feedback' ),
 241              'href'   => __( 'https://wordpress.org/support/forum/requests-and-feedback' ),
 242          )
 243      );
 244  }
 245  
 246  /**
 247   * Adds the sidebar toggle button.
 248   *
 249   * @since 3.8.0
 250   *
 251   * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
 252   */
 253  function wp_admin_bar_sidebar_toggle( $wp_admin_bar ) {
 254      if ( is_admin() ) {
 255          $wp_admin_bar->add_node(
 256              array(
 257                  'id'    => 'menu-toggle',
 258                  'title' => '<span class="ab-icon" aria-hidden="true"></span><span class="screen-reader-text">' .
 259                          /* translators: Hidden accessibility text. */
 260                          __( 'Menu' ) .
 261                      '</span>',
 262                  'href'  => '#',
 263              )
 264          );
 265      }
 266  }
 267  
 268  /**
 269   * Adds the "My Account" item.
 270   *
 271   * @since 3.3.0
 272   * @since 7.2.0 Removed "Howdy" from the item title and added a fallback to the
 273   *              user login when the display name is empty.
 274   *
 275   * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
 276   */
 277  function wp_admin_bar_my_account_item( $wp_admin_bar ) {
 278      $user_id = get_current_user_id();
 279      if ( ! $user_id ) {
 280          return;
 281      }
 282  
 283      if ( current_user_can( 'read' ) ) {
 284          $profile_url = get_edit_profile_url( $user_id );
 285      } elseif ( is_multisite() ) {
 286          $profile_url = get_dashboard_url( $user_id, 'profile.php' );
 287      } else {
 288          $profile_url = false;
 289      }
 290  
 291      $current_user = wp_get_current_user();
 292      $display_name = $current_user->display_name;
 293      if ( empty( $display_name ) ) {
 294          $display_name = $current_user->user_login;
 295      }
 296  
 297      $avatar = get_avatar( $user_id, 28 );
 298      $wp_admin_bar->add_node(
 299          array(
 300              'id'     => 'my-account',
 301              'parent' => 'top-secondary',
 302              'icon'   => empty( $avatar ) ? 'core-admin/people' : false,
 303              'title'  => '<span class="display-name user-display-name">' . $display_name . '</span>' . $avatar,
 304              'href'   => $profile_url,
 305              'meta'   => array(
 306                  'class'      => empty( $avatar ) ? '' : 'with-avatar',
 307                  'menu_title' => wp_strip_all_tags( $display_name ),
 308                  'tabindex'   => ( false !== $profile_url ) ? '' : 0,
 309              ),
 310          )
 311      );
 312  }
 313  
 314  /**
 315   * Adds the "My Account" submenu items.
 316   *
 317   * @since 3.1.0
 318   * @since 7.2.0 Added "Howdy" to the user info item and a fallback to the user
 319   *              login when the display name is empty.
 320   *
 321   * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
 322   */
 323  function wp_admin_bar_my_account_menu( $wp_admin_bar ) {
 324      $user_id      = get_current_user_id();
 325      $current_user = wp_get_current_user();
 326  
 327      if ( ! $user_id ) {
 328          return;
 329      }
 330  
 331      if ( current_user_can( 'read' ) ) {
 332          $profile_url = get_edit_profile_url( $user_id );
 333      } elseif ( is_multisite() ) {
 334          $profile_url = get_dashboard_url( $user_id, 'profile.php' );
 335      } else {
 336          $profile_url = false;
 337      }
 338  
 339      $wp_admin_bar->add_group(
 340          array(
 341              'parent' => 'my-account',
 342              'id'     => 'user-actions',
 343          )
 344      );
 345  
 346      $display_name = $current_user->display_name;
 347      if ( empty( $display_name ) ) {
 348          $display_name = $current_user->user_login;
 349      }
 350  
 351      /* translators: %s: Current user's display name. */
 352      $howdy = sprintf( __( 'Howdy, %s' ), "<span class='user-display-name'>" . $display_name . '</span>' );
 353  
 354      $user_info  = get_avatar( $user_id, 64 );
 355      $user_info .= "<span class='display-name howdy'>" . $howdy . '</span>';
 356  
 357      $username_hidden = ( $display_name === $current_user->user_login ) ? ' hidden' : '';
 358      $user_info      .= "<span class='username'{$username_hidden}>{$current_user->user_login}</span>";
 359  
 360      if ( false !== $profile_url ) {
 361          $user_info .= "<span class='display-name edit-profile'>" . __( 'Edit Profile' ) . '</span>';
 362      }
 363  
 364      $wp_admin_bar->add_node(
 365          array(
 366              'parent' => 'user-actions',
 367              'id'     => 'user-info',
 368              'title'  => $user_info,
 369              'href'   => $profile_url,
 370          )
 371      );
 372  
 373      $wp_admin_bar->add_node(
 374          array(
 375              'parent' => 'user-actions',
 376              'id'     => 'logout',
 377              'title'  => __( 'Log Out' ),
 378              'href'   => wp_logout_url(),
 379          )
 380      );
 381  }
 382  
 383  /**
 384   * Adds the "Site Name" menu.
 385   *
 386   * @since 3.3.0
 387   *
 388   * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
 389   */
 390  function wp_admin_bar_site_menu( $wp_admin_bar ) {
 391      // Don't show for logged out users.
 392      if ( ! is_user_logged_in() ) {
 393          return;
 394      }
 395  
 396      // Show only when the user is a member of this site, or they're a super admin.
 397      if ( ! is_user_member_of_blog() && ! current_user_can( 'manage_network' ) ) {
 398          return;
 399      }
 400  
 401      $blogname = get_bloginfo( 'name' );
 402  
 403      if ( ! $blogname ) {
 404          $blogname = preg_replace( '#^(https?://)?(www\.)?#', '', get_home_url() );
 405      }
 406  
 407      if ( is_network_admin() ) {
 408          /* translators: %s: Site title. */
 409          $blogname = sprintf( __( 'Network Admin: %s' ), esc_html( get_network()->site_name ) );
 410      } elseif ( is_user_admin() ) {
 411          /* translators: %s: Site title. */
 412          $blogname = sprintf( __( 'User Dashboard: %s' ), esc_html( get_network()->site_name ) );
 413      }
 414  
 415      $title = wp_html_excerpt( $blogname, 40, '&hellip;' );
 416      $meta  = array(
 417          'menu_title' => $title,
 418      );
 419  
 420      if ( ! is_network_admin() && ! is_user_admin() ) {
 421          /** This filter is documented in wp-includes/admin-bar.php */
 422          $show_site_icons = apply_filters( 'wp_admin_bar_show_site_icons', true );
 423  
 424          if ( true === $show_site_icons && has_site_icon() ) {
 425              $site_icon_url    = get_site_icon_url( 32 );
 426              $site_icon_url_2x = get_site_icon_url( 64 );
 427              $srcset           = ( $site_icon_url_2x && $site_icon_url !== $site_icon_url_2x ) ? sprintf( ' srcset="%s 2x"', esc_url( $site_icon_url_2x ) ) : '';
 428              $site_icon        = sprintf(
 429                  '<img class="site-icon" src="%s"%s alt="" width="20" height="20" />',
 430                  esc_url( $site_icon_url ),
 431                  $srcset
 432              );
 433  
 434              $title         = $site_icon . $title;
 435              $meta['class'] = 'has-site-icon';
 436          }
 437      }
 438  
 439      $links_to_home = is_admin() || ! current_user_can( 'read' );
 440  
 441      $wp_admin_bar->add_node(
 442          array(
 443              'id'    => 'site-name',
 444              'icon'  => $links_to_home ? 'core-admin/home' : 'core-admin/dashboard',
 445              'title' => $title,
 446              'href'  => $links_to_home ? home_url( '/' ) : admin_url(),
 447              'meta'  => $meta,
 448          )
 449      );
 450  
 451      // Create submenu items.
 452  
 453      if ( is_admin() ) {
 454          // Add an option to visit the site.
 455          $wp_admin_bar->add_node(
 456              array(
 457                  'parent' => 'site-name',
 458                  'id'     => 'view-site',
 459                  'title'  => __( 'Visit Site' ),
 460                  'href'   => home_url( '/' ),
 461              )
 462          );
 463  
 464          if ( is_blog_admin() && is_multisite() && current_user_can( 'manage_sites' ) ) {
 465              $wp_admin_bar->add_node(
 466                  array(
 467                      'parent' => 'site-name',
 468                      'id'     => 'edit-site',
 469                      'title'  => __( 'Manage Site' ),
 470                      'href'   => network_admin_url( 'site-info.php?id=' . get_current_blog_id() ),
 471                  )
 472              );
 473          }
 474      } elseif ( current_user_can( 'read' ) ) {
 475          // We're on the front end, link to the Dashboard.
 476          $wp_admin_bar->add_node(
 477              array(
 478                  'parent' => 'site-name',
 479                  'id'     => 'dashboard',
 480                  'title'  => __( 'Dashboard' ),
 481                  'href'   => admin_url(),
 482              )
 483          );
 484  
 485          // Add the appearance submenu items.
 486          wp_admin_bar_appearance_menu( $wp_admin_bar );
 487  
 488          // Add a Plugins link.
 489          if ( current_user_can( 'activate_plugins' ) ) {
 490              $wp_admin_bar->add_node(
 491                  array(
 492                      'parent' => 'site-name',
 493                      'id'     => 'plugins',
 494                      'title'  => __( 'Plugins' ),
 495                      'href'   => admin_url( 'plugins.php' ),
 496                  )
 497              );
 498          }
 499      }
 500  }
 501  
 502  /**
 503   * Adds the "Edit Site" link to the Toolbar.
 504   *
 505   * @since 5.9.0
 506   * @since 6.3.0 Added `$_wp_current_template_id` global for editing of current template directly from the admin bar.
 507   * @since 6.6.0 Added the `canvas` query arg to the Site Editor link.
 508   *
 509   * @global string $_wp_current_template_id
 510   *
 511   * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
 512   */
 513  function wp_admin_bar_edit_site_menu( $wp_admin_bar ) {
 514      global $_wp_current_template_id;
 515  
 516      // Don't show if a block theme is not activated.
 517      if ( ! wp_is_block_theme() ) {
 518          return;
 519      }
 520  
 521      // Don't show for users who can't edit theme options or when in the admin.
 522      if ( ! current_user_can( 'edit_theme_options' ) || is_admin() ) {
 523          return;
 524      }
 525  
 526      $wp_admin_bar->add_node(
 527          array(
 528              'id'    => 'site-editor',
 529              'icon'  => 'core-admin/brush',
 530              'title' => __( 'Edit Site' ),
 531              'href'  => add_query_arg(
 532                  array(
 533                      'postType' => 'wp_template',
 534                      'postId'   => $_wp_current_template_id,
 535                      'canvas'   => 'edit',
 536                  ),
 537                  admin_url( 'site-editor.php' )
 538              ),
 539          )
 540      );
 541  }
 542  
 543  /**
 544   * Adds the "Customize" link to the Toolbar.
 545   *
 546   * @since 4.3.0
 547   *
 548   * @global WP_Customize_Manager $wp_customize
 549   *
 550   * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
 551   */
 552  function wp_admin_bar_customize_menu( $wp_admin_bar ) {
 553      global $wp_customize;
 554  
 555      // Don't show if a block theme is activated and no plugins use the customizer.
 556      if ( wp_is_block_theme() && ! has_action( 'customize_register' ) ) {
 557          return;
 558      }
 559  
 560      // Don't show for users who can't access the customizer or when in the admin.
 561      if ( ! current_user_can( 'customize' ) || is_admin() ) {
 562          return;
 563      }
 564  
 565      // Don't show if the user cannot edit a given customize_changeset post currently being previewed.
 566      if ( is_customize_preview() && $wp_customize->changeset_post_id()
 567          && ! current_user_can( get_post_type_object( 'customize_changeset' )->cap->edit_post, $wp_customize->changeset_post_id() )
 568      ) {
 569          return;
 570      }
 571  
 572      $current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
 573      if ( is_customize_preview() && $wp_customize->changeset_uuid() ) {
 574          $current_url = remove_query_arg( 'customize_changeset_uuid', $current_url );
 575      }
 576  
 577      $customize_url = add_query_arg( 'url', urlencode( $current_url ), wp_customize_url() );
 578      if ( is_customize_preview() ) {
 579          $customize_url = add_query_arg( array( 'changeset_uuid' => $wp_customize->changeset_uuid() ), $customize_url );
 580      }
 581  
 582      $wp_admin_bar->add_node(
 583          array(
 584              'id'    => 'customize',
 585              'icon'  => 'core-admin/brush',
 586              'title' => __( 'Customize' ),
 587              'href'  => $customize_url,
 588              'meta'  => array(
 589                  'class' => 'hide-if-no-customize',
 590              ),
 591          )
 592      );
 593      add_action( 'wp_before_admin_bar_render', 'wp_customize_support_script' );
 594  }
 595  
 596  /**
 597   * Adds the "My Sites/[Site Name]" menu and all submenus.
 598   *
 599   * @since 3.1.0
 600   *
 601   * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
 602   */
 603  function wp_admin_bar_my_sites_menu( $wp_admin_bar ) {
 604      // Don't show for logged out users or single site mode.
 605      if ( ! is_user_logged_in() || ! is_multisite() ) {
 606          return;
 607      }
 608  
 609      // Show only when the user has at least one site, or they're a super admin.
 610      if ( count( $wp_admin_bar->user->blogs ) < 1 && ! current_user_can( 'manage_network' ) ) {
 611          return;
 612      }
 613  
 614      if ( $wp_admin_bar->user->active_blog ) {
 615          $my_sites_url = get_admin_url( $wp_admin_bar->user->active_blog->blog_id, 'my-sites.php' );
 616      } else {
 617          $my_sites_url = admin_url( 'my-sites.php' );
 618      }
 619  
 620      $wp_admin_bar->add_node(
 621          array(
 622              'id'    => 'my-sites',
 623              'icon'  => 'core-admin/sites',
 624              'title' => __( 'My Sites' ),
 625              'href'  => $my_sites_url,
 626          )
 627      );
 628  
 629      if ( current_user_can( 'manage_network' ) ) {
 630          $wp_admin_bar->add_group(
 631              array(
 632                  'parent' => 'my-sites',
 633                  'id'     => 'my-sites-super-admin',
 634              )
 635          );
 636  
 637          $wp_admin_bar->add_node(
 638              array(
 639                  'parent' => 'my-sites-super-admin',
 640                  'id'     => 'network-admin',
 641                  'title'  => __( 'Network Admin' ),
 642                  'href'   => network_admin_url(),
 643              )
 644          );
 645  
 646          $wp_admin_bar->add_node(
 647              array(
 648                  'parent' => 'network-admin',
 649                  'id'     => 'network-admin-d',
 650                  'title'  => __( 'Dashboard' ),
 651                  'href'   => network_admin_url(),
 652              )
 653          );
 654  
 655          if ( current_user_can( 'manage_sites' ) ) {
 656              $wp_admin_bar->add_node(
 657                  array(
 658                      'parent' => 'network-admin',
 659                      'id'     => 'network-admin-s',
 660                      'title'  => __( 'Sites' ),
 661                      'href'   => network_admin_url( 'sites.php' ),
 662                  )
 663              );
 664          }
 665  
 666          if ( current_user_can( 'manage_network_users' ) ) {
 667              $wp_admin_bar->add_node(
 668                  array(
 669                      'parent' => 'network-admin',
 670                      'id'     => 'network-admin-u',
 671                      'title'  => __( 'Users' ),
 672                      'href'   => network_admin_url( 'users.php' ),
 673                  )
 674              );
 675          }
 676  
 677          if ( current_user_can( 'manage_network_themes' ) ) {
 678              $wp_admin_bar->add_node(
 679                  array(
 680                      'parent' => 'network-admin',
 681                      'id'     => 'network-admin-t',
 682                      'title'  => __( 'Themes' ),
 683                      'href'   => network_admin_url( 'themes.php' ),
 684                  )
 685              );
 686          }
 687  
 688          if ( current_user_can( 'manage_network_plugins' ) ) {
 689              $wp_admin_bar->add_node(
 690                  array(
 691                      'parent' => 'network-admin',
 692                      'id'     => 'network-admin-p',
 693                      'title'  => __( 'Plugins' ),
 694                      'href'   => network_admin_url( 'plugins.php' ),
 695                  )
 696              );
 697          }
 698  
 699          if ( current_user_can( 'manage_network_options' ) ) {
 700              $wp_admin_bar->add_node(
 701                  array(
 702                      'parent' => 'network-admin',
 703                      'id'     => 'network-admin-o',
 704                      'title'  => __( 'Settings' ),
 705                      'href'   => network_admin_url( 'settings.php' ),
 706                  )
 707              );
 708          }
 709      }
 710  
 711      // Add site links.
 712      $wp_admin_bar->add_group(
 713          array(
 714              'parent' => 'my-sites',
 715              'id'     => 'my-sites-list',
 716              'meta'   => array(
 717                  'class' => current_user_can( 'manage_network' ) ? 'ab-sub-secondary' : '',
 718              ),
 719          )
 720      );
 721  
 722      /**
 723       * Filters whether to show the site icons in toolbar.
 724       *
 725       * Returning false to this hook is the recommended way to hide site icons in the toolbar.
 726       * A truthy return may have negative performance impact on large multisites.
 727       *
 728       * @since 6.0.0
 729       *
 730       * @param bool $show_site_icons Whether site icons should be shown in the toolbar. Default true.
 731       */
 732      $show_site_icons = apply_filters( 'wp_admin_bar_show_site_icons', true );
 733  
 734      $default_blavatar = '<div class="blavatar">' . wp_get_icon( 'core-admin/wordpress', array( 'size' => 16 ) ) . '</div>';
 735  
 736      foreach ( (array) $wp_admin_bar->user->blogs as $blog ) {
 737          switch_to_blog( $blog->userblog_id );
 738  
 739          if ( true === $show_site_icons && has_site_icon() ) {
 740              $blavatar = sprintf(
 741                  '<img class="blavatar" src="%s" srcset="%s 2x" alt="" width="16" height="16"%s />',
 742                  esc_url( get_site_icon_url( 16 ) ),
 743                  esc_url( get_site_icon_url( 32 ) ),
 744                  ( wp_lazy_loading_enabled( 'img', 'site_icon_in_toolbar' ) ? ' loading="lazy"' : '' )
 745              );
 746          } else {
 747              $blavatar = $default_blavatar;
 748          }
 749  
 750          $blogname = $blog->blogname;
 751  
 752          if ( ! $blogname ) {
 753              $blogname = preg_replace( '#^(https?://)?(www\.)?#', '', get_home_url() );
 754          }
 755  
 756          $menu_id = 'blog-' . $blog->userblog_id;
 757  
 758          if ( current_user_can( 'read' ) ) {
 759              $wp_admin_bar->add_node(
 760                  array(
 761                      'parent' => 'my-sites-list',
 762                      'id'     => $menu_id,
 763                      'title'  => $blavatar . $blogname,
 764                      'href'   => admin_url(),
 765                  )
 766              );
 767  
 768              $wp_admin_bar->add_node(
 769                  array(
 770                      'parent' => $menu_id,
 771                      'id'     => $menu_id . '-d',
 772                      'title'  => __( 'Dashboard' ),
 773                      'href'   => admin_url(),
 774                  )
 775              );
 776          } else {
 777              $wp_admin_bar->add_node(
 778                  array(
 779                      'parent' => 'my-sites-list',
 780                      'id'     => $menu_id,
 781                      'title'  => $blavatar . $blogname,
 782                      'href'   => home_url(),
 783                  )
 784              );
 785          }
 786  
 787          if ( current_user_can( get_post_type_object( 'post' )->cap->create_posts ) ) {
 788              $wp_admin_bar->add_node(
 789                  array(
 790                      'parent' => $menu_id,
 791                      'id'     => $menu_id . '-n',
 792                      'title'  => get_post_type_object( 'post' )->labels->new_item,
 793                      'href'   => admin_url( 'post-new.php' ),
 794                  )
 795              );
 796          }
 797  
 798          if ( current_user_can( 'edit_posts' ) ) {
 799              $wp_admin_bar->add_node(
 800                  array(
 801                      'parent' => $menu_id,
 802                      'id'     => $menu_id . '-c',
 803                      'title'  => __( 'Manage Comments' ),
 804                      'href'   => admin_url( 'edit-comments.php' ),
 805                  )
 806              );
 807          }
 808  
 809          $wp_admin_bar->add_node(
 810              array(
 811                  'parent' => $menu_id,
 812                  'id'     => $menu_id . '-v',
 813                  'title'  => __( 'Visit Site' ),
 814                  'href'   => home_url( '/' ),
 815              )
 816          );
 817  
 818          restore_current_blog();
 819      }
 820  }
 821  
 822  /**
 823   * Provides a shortlink.
 824   *
 825   * @since 3.1.0
 826   *
 827   * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
 828   */
 829  function wp_admin_bar_shortlink_menu( $wp_admin_bar ) {
 830      $short = wp_get_shortlink( 0, 'query' );
 831      $id    = 'get-shortlink';
 832  
 833      if ( empty( $short ) ) {
 834          return;
 835      }
 836  
 837      $html = '<input class="shortlink-input" type="text" readonly="readonly" value="' . esc_attr( $short ) . '" aria-label="' . __( 'Shortlink' ) . '" />';
 838  
 839      $wp_admin_bar->add_node(
 840          array(
 841              'id'    => $id,
 842              'title' => __( 'Shortlink' ),
 843              'href'  => $short,
 844              'meta'  => array( 'html' => $html ),
 845          )
 846      );
 847  }
 848  
 849  /**
 850   * Provides an edit link for posts and terms.
 851   *
 852   * @since 3.1.0
 853   * @since 5.5.0 Added a "View Post" link on Comments screen for a single post.
 854   *
 855   * @global WP_Term  $tag
 856   * @global WP_Query $wp_the_query WordPress Query object.
 857   * @global int      $user_id      The ID of the user being edited. Not to be confused with the
 858   *                                global $user_ID, which contains the ID of the current user.
 859   * @global int      $post_id      The ID of the post when editing comments for a single post.
 860   *
 861   * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
 862   */
 863  function wp_admin_bar_edit_menu( $wp_admin_bar ) {
 864      global $tag, $wp_the_query, $user_id, $post_id;
 865  
 866      if ( is_admin() ) {
 867          $current_screen   = get_current_screen();
 868          $post             = get_post();
 869          $post_type_object = null;
 870  
 871          if ( 'post' === $current_screen->base ) {
 872              $post_type_object = get_post_type_object( $post->post_type );
 873          } elseif ( 'edit' === $current_screen->base ) {
 874              $post_type_object = get_post_type_object( $current_screen->post_type );
 875          } elseif ( 'edit-comments' === $current_screen->base && $post_id ) {
 876              $post = get_post( $post_id );
 877              if ( $post ) {
 878                  $post_type_object = get_post_type_object( $post->post_type );
 879              }
 880          }
 881  
 882          if ( ( 'post' === $current_screen->base || 'edit-comments' === $current_screen->base )
 883              && 'add' !== $current_screen->action
 884              && ( $post_type_object )
 885              && current_user_can( 'read_post', $post->ID )
 886              && ( $post_type_object->public )
 887              && ( $post_type_object->show_in_admin_bar ) ) {
 888              if ( 'draft' === $post->post_status ) {
 889                  $preview_link = get_preview_post_link( $post );
 890                  $wp_admin_bar->add_node(
 891                      array(
 892                          'id'    => 'preview',
 893                          'title' => $post_type_object->labels->view_item,
 894                          'href'  => esc_url( $preview_link ),
 895                          'meta'  => array( 'target' => 'wp-preview-' . $post->ID ),
 896                      )
 897                  );
 898              } else {
 899                  $wp_admin_bar->add_node(
 900                      array(
 901                          'id'    => 'view',
 902                          'title' => $post_type_object->labels->view_item,
 903                          'href'  => get_permalink( $post->ID ),
 904                      )
 905                  );
 906              }
 907          } elseif ( 'edit' === $current_screen->base
 908              && ( $post_type_object )
 909              && ( $post_type_object->public )
 910              && ( $post_type_object->show_in_admin_bar )
 911              && ( get_post_type_archive_link( $post_type_object->name ) )
 912              && ! ( 'post' === $post_type_object->name && 'posts' === get_option( 'show_on_front' ) ) ) {
 913              $wp_admin_bar->add_node(
 914                  array(
 915                      'id'    => 'archive',
 916                      'title' => $post_type_object->labels->view_items,
 917                      'href'  => get_post_type_archive_link( $current_screen->post_type ),
 918                  )
 919              );
 920          } elseif ( 'term' === $current_screen->base && isset( $tag ) && is_object( $tag ) && ! is_wp_error( $tag ) ) {
 921              $tax = get_taxonomy( $tag->taxonomy );
 922              if ( is_term_publicly_viewable( $tag ) ) {
 923                  $wp_admin_bar->add_node(
 924                      array(
 925                          'id'    => 'view',
 926                          'title' => $tax->labels->view_item,
 927                          'href'  => get_term_link( $tag ),
 928                      )
 929                  );
 930              }
 931          } elseif ( 'user-edit' === $current_screen->base && isset( $user_id ) ) {
 932              $user_object = get_userdata( $user_id );
 933              $view_link   = get_author_posts_url( $user_object->ID );
 934              if ( $user_object->exists() && $view_link ) {
 935                  $wp_admin_bar->add_node(
 936                      array(
 937                          'id'    => 'view',
 938                          'title' => __( 'View User' ),
 939                          'href'  => $view_link,
 940                      )
 941                  );
 942              }
 943          }
 944      } else {
 945          $current_object = $wp_the_query->get_queried_object();
 946  
 947          if ( empty( $current_object ) ) {
 948              return;
 949          }
 950  
 951          if ( ! empty( $current_object->post_type ) ) {
 952              $post_type_object = get_post_type_object( $current_object->post_type );
 953              $edit_post_link   = get_edit_post_link( $current_object->ID );
 954              if ( $post_type_object
 955                  && $edit_post_link
 956                  && current_user_can( 'edit_post', $current_object->ID )
 957                  && $post_type_object->show_in_admin_bar ) {
 958                  $wp_admin_bar->add_node(
 959                      array(
 960                          'id'    => 'edit',
 961                          'icon'  => 'core-admin/pencil',
 962                          'title' => $post_type_object->labels->edit_item,
 963                          'href'  => $edit_post_link,
 964                      )
 965                  );
 966              }
 967          } elseif ( ! empty( $current_object->taxonomy ) ) {
 968              $tax            = get_taxonomy( $current_object->taxonomy );
 969              $edit_term_link = get_edit_term_link( $current_object->term_id, $current_object->taxonomy );
 970              if ( $tax && $edit_term_link && current_user_can( 'edit_term', $current_object->term_id ) ) {
 971                  $wp_admin_bar->add_node(
 972                      array(
 973                          'id'    => 'edit',
 974                          'icon'  => 'core-admin/pencil',
 975                          'title' => $tax->labels->edit_item,
 976                          'href'  => $edit_term_link,
 977                      )
 978                  );
 979              }
 980          } elseif ( $current_object instanceof WP_User && current_user_can( 'edit_user', $current_object->ID ) ) {
 981              $edit_user_link = get_edit_user_link( $current_object->ID );
 982              if ( $edit_user_link ) {
 983                  $wp_admin_bar->add_node(
 984                      array(
 985                          'id'    => 'edit',
 986                          'icon'  => 'core-admin/pencil',
 987                          'title' => __( 'Edit User' ),
 988                          'href'  => $edit_user_link,
 989                      )
 990                  );
 991              }
 992          }
 993      }
 994  }
 995  
 996  /**
 997   * Adds the command palette trigger button.
 998   *
 999   * Displays a button in the admin bar that shows the keyboard shortcut
1000   * for opening the command palette.
1001   *
1002   * @since 7.0.0
1003   *
1004   * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
1005   */
1006  function wp_admin_bar_command_palette_menu( WP_Admin_Bar $wp_admin_bar ): void {
1007      if ( ! is_admin() || ! wp_script_is( 'wp-core-commands', 'enqueued' ) ) {
1008          return;
1009      }
1010  
1011      $shortcut_labels = array(
1012          'appleOS' => _x( '⌘K', 'keyboard shortcut to open the command palette' ),
1013          'default' => _x( 'Ctrl+K', 'keyboard shortcut to open the command palette' ),
1014      );
1015      $apple_pattern   = 'Macintosh|Mac OS X|Mac_PowerPC';
1016      $is_apple_os     = (bool) preg_match( "/{$apple_pattern}/i", $_SERVER['HTTP_USER_AGENT'] ?? '' );
1017      $shortcut_label  = $is_apple_os ? $shortcut_labels['appleOS'] : $shortcut_labels['default'];
1018      $title           = sprintf(
1019          '<span class="ab-icon" aria-hidden="true"></span><span class="ab-label"><kbd>%s</kbd><span class="screen-reader-text"> %s</span></span>',
1020          $shortcut_label,
1021          /* translators: Hidden accessibility text. */
1022          __( 'Open command palette' ),
1023      );
1024      /*
1025       * Detect Apple OS via JavaScript for sites behind a CDN blocking the UA header.
1026       *
1027       * Running the script as the admin bar is rendered avoids a flash of incorrect content
1028       * for users with Apple OS when the UA header is blocked. It also prevents the need for
1029       * wp-i18n to be loaded as a dependency.
1030       */
1031      $function = <<<'JS'
1032          ( applePattern, appleOSLabel ) => {
1033              if ( ! ( new RegExp( applePattern, 'i' ) ).test( navigator.userAgent ) ) {
1034                  return;
1035              }
1036              const kbd = document.querySelector( '#wp-admin-bar-command-palette .ab-label kbd' );
1037              if ( kbd ) {
1038                  kbd.textContent = appleOSLabel;
1039              }
1040          }
1041      JS;
1042      $script   = sprintf(
1043          '( %s )( %s, %s );',
1044          $function,
1045          wp_json_encode( $apple_pattern, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ),
1046          wp_json_encode( $shortcut_labels['appleOS'], JSON_HEX_TAG | JSON_UNESCAPED_SLASHES )
1047      );
1048      $script  .= "\n//# sourceURL=" . rawurlencode( __FUNCTION__ );
1049      $wp_admin_bar->add_node(
1050          array(
1051              'id'    => 'command-palette',
1052              'title' => $title,
1053              'href'  => '#',
1054              'meta'  => array(
1055                  'class'   => 'hide-if-no-js',
1056                  'onclick' => 'wp.data.dispatch( "core/commands" ).open(); return false;',
1057                  'html'    => wp_get_inline_script_tag( $script ),
1058              ),
1059          )
1060      );
1061  }
1062  
1063  /**
1064   * Adds "Add New" menu.
1065   *
1066   * @since 3.1.0
1067   * @since 6.5.0 Added a New Site link for network installations.
1068   *
1069   * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
1070   */
1071  function wp_admin_bar_new_content_menu( $wp_admin_bar ) {
1072      $actions = array();
1073  
1074      $cpts = (array) get_post_types( array( 'show_in_admin_bar' => true ), 'objects' );
1075  
1076      if ( isset( $cpts['post'] ) && current_user_can( $cpts['post']->cap->create_posts ) ) {
1077          $actions['post-new.php'] = array( $cpts['post']->labels->name_admin_bar, 'new-post' );
1078      }
1079  
1080      if ( isset( $cpts['attachment'] ) && current_user_can( 'upload_files' ) ) {
1081          $actions['media-new.php'] = array( $cpts['attachment']->labels->name_admin_bar, 'new-media' );
1082      }
1083  
1084      if ( current_user_can( 'manage_links' ) ) {
1085          $actions['link-add.php'] = array( _x( 'Link', 'add new from admin bar' ), 'new-link' );
1086      }
1087  
1088      if ( isset( $cpts['page'] ) && current_user_can( $cpts['page']->cap->create_posts ) ) {
1089          $actions['post-new.php?post_type=page'] = array( $cpts['page']->labels->name_admin_bar, 'new-page' );
1090      }
1091  
1092      unset( $cpts['post'], $cpts['page'], $cpts['attachment'] );
1093  
1094      // Add any additional custom post types.
1095      foreach ( $cpts as $cpt ) {
1096          if ( ! current_user_can( $cpt->cap->create_posts ) ) {
1097              continue;
1098          }
1099  
1100          $key             = 'post-new.php?post_type=' . $cpt->name;
1101          $actions[ $key ] = array( $cpt->labels->name_admin_bar, 'new-' . $cpt->name );
1102      }
1103      // Avoid clash with parent node and a 'content' post type.
1104      if ( isset( $actions['post-new.php?post_type=content'] ) ) {
1105          $actions['post-new.php?post_type=content'][1] = 'add-new-content';
1106      }
1107  
1108      if ( current_user_can( 'create_users' ) || ( is_multisite() && current_user_can( 'promote_users' ) ) ) {
1109          $actions['user-new.php'] = array( _x( 'User', 'add new from admin bar' ), 'new-user' );
1110      }
1111  
1112      if ( ! $actions ) {
1113          return;
1114      }
1115  
1116      $title = '<span class="ab-icon" aria-hidden="true"></span><span class="ab-label">' . _x( 'New', 'admin bar menu group label' ) . '</span>';
1117  
1118      $wp_admin_bar->add_node(
1119          array(
1120              'id'    => 'new-content',
1121              'title' => $title,
1122              'href'  => admin_url( array_key_first( $actions ) ),
1123              'meta'  => array(
1124                  'menu_title' => _x( 'New', 'admin bar menu group label' ),
1125              ),
1126          )
1127      );
1128  
1129      foreach ( $actions as $link => $action ) {
1130          list( $title, $id ) = $action;
1131  
1132          $wp_admin_bar->add_node(
1133              array(
1134                  'parent' => 'new-content',
1135                  'id'     => $id,
1136                  'title'  => $title,
1137                  'href'   => admin_url( $link ),
1138              )
1139          );
1140      }
1141  
1142      if ( is_multisite() && current_user_can( 'create_sites' ) ) {
1143          $wp_admin_bar->add_node(
1144              array(
1145                  'parent' => 'new-content',
1146                  'id'     => 'add-new-site',
1147                  'title'  => _x( 'Site', 'add new from admin bar' ),
1148                  'href'   => network_admin_url( 'site-new.php' ),
1149              )
1150          );
1151      }
1152  }
1153  
1154  /**
1155   * Adds edit comments link with awaiting moderation count bubble.
1156   *
1157   * @since 3.1.0
1158   *
1159   * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
1160   */
1161  function wp_admin_bar_comments_menu( $wp_admin_bar ) {
1162      if ( ! current_user_can( 'edit_posts' ) ) {
1163          return;
1164      }
1165  
1166      $awaiting_mod  = wp_count_comments();
1167      $awaiting_mod  = $awaiting_mod->moderated;
1168      $awaiting_text = sprintf(
1169          /* translators: Hidden accessibility text. %s: Number of comments. */
1170          _n( '%s Comment in moderation', '%s Comments in moderation', $awaiting_mod ),
1171          number_format_i18n( $awaiting_mod )
1172      );
1173  
1174      $icon   = '<span class="ab-icon" aria-hidden="true"></span>';
1175      $title  = '<span class="ab-label awaiting-mod pending-count count-' . $awaiting_mod . '" aria-hidden="true">' . number_format_i18n( $awaiting_mod ) . '</span>';
1176      $title .= '<span class="screen-reader-text comments-in-moderation-text">' . $awaiting_text . '</span>';
1177  
1178      $wp_admin_bar->add_node(
1179          array(
1180              'id'    => 'comments',
1181              'title' => $icon . $title,
1182              'href'  => admin_url( 'edit-comments.php' ),
1183          )
1184      );
1185  }
1186  
1187  /**
1188   * Adds appearance submenu items to the "Site Name" menu.
1189   *
1190   * @since 3.1.0
1191   *
1192   * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
1193   */
1194  function wp_admin_bar_appearance_menu( $wp_admin_bar ) {
1195      $wp_admin_bar->add_group(
1196          array(
1197              'parent' => 'site-name',
1198              'id'     => 'appearance',
1199          )
1200      );
1201  
1202      if ( current_user_can( 'switch_themes' ) ) {
1203          $wp_admin_bar->add_node(
1204              array(
1205                  'parent' => 'appearance',
1206                  'id'     => 'themes',
1207                  'title'  => __( 'Themes' ),
1208                  'href'   => admin_url( 'themes.php' ),
1209              )
1210          );
1211      }
1212  
1213      if ( ! current_user_can( 'edit_theme_options' ) ) {
1214          return;
1215      }
1216  
1217      if ( current_theme_supports( 'widgets' ) ) {
1218          $wp_admin_bar->add_node(
1219              array(
1220                  'parent' => 'appearance',
1221                  'id'     => 'widgets',
1222                  'title'  => __( 'Widgets' ),
1223                  'href'   => admin_url( 'widgets.php' ),
1224              )
1225          );
1226      }
1227  
1228      if ( current_theme_supports( 'menus' ) || current_theme_supports( 'widgets' ) ) {
1229          $wp_admin_bar->add_node(
1230              array(
1231                  'parent' => 'appearance',
1232                  'id'     => 'menus',
1233                  'title'  => __( 'Menus' ),
1234                  'href'   => admin_url( 'nav-menus.php' ),
1235              )
1236          );
1237      }
1238  
1239      if ( current_theme_supports( 'custom-background' ) ) {
1240          $wp_admin_bar->add_node(
1241              array(
1242                  'parent' => 'appearance',
1243                  'id'     => 'background',
1244                  'title'  => _x( 'Background', 'custom background' ),
1245                  'href'   => admin_url( 'themes.php?page=custom-background' ),
1246                  'meta'   => array(
1247                      'class' => 'hide-if-customize',
1248                  ),
1249              )
1250          );
1251      }
1252  
1253      if ( current_theme_supports( 'custom-header' ) ) {
1254          $wp_admin_bar->add_node(
1255              array(
1256                  'parent' => 'appearance',
1257                  'id'     => 'header',
1258                  'title'  => _x( 'Header', 'custom image header' ),
1259                  'href'   => admin_url( 'themes.php?page=custom-header' ),
1260                  'meta'   => array(
1261                      'class' => 'hide-if-customize',
1262                  ),
1263              )
1264          );
1265      }
1266  }
1267  
1268  /**
1269   * Provides an update link if theme/plugin/core updates are available.
1270   *
1271   * @since 3.1.0
1272   *
1273   * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
1274   */
1275  function wp_admin_bar_updates_menu( $wp_admin_bar ) {
1276  
1277      $update_data = wp_get_update_data();
1278  
1279      if ( ! $update_data['counts']['total'] ) {
1280          return;
1281      }
1282  
1283      $updates_text = sprintf(
1284          /* translators: Hidden accessibility text. %s: Total number of updates available. */
1285          _n( '%s update available', '%s updates available', $update_data['counts']['total'] ),
1286          number_format_i18n( $update_data['counts']['total'] )
1287      );
1288  
1289      $icon   = '<span class="ab-icon" aria-hidden="true"></span>';
1290      $title  = '<span class="ab-label" aria-hidden="true">' . number_format_i18n( $update_data['counts']['total'] ) . '</span>';
1291      $title .= '<span class="screen-reader-text updates-available-text">' . $updates_text . '</span>';
1292  
1293      $wp_admin_bar->add_node(
1294          array(
1295              'id'    => 'updates',
1296              'title' => $icon . $title,
1297              'href'  => network_admin_url( 'update-core.php' ),
1298          )
1299      );
1300  }
1301  
1302  /**
1303   * Adds search form.
1304   *
1305   * @since 3.3.0
1306   *
1307   * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
1308   */
1309  function wp_admin_bar_search_menu( $wp_admin_bar ) {
1310      if ( is_admin() ) {
1311          return;
1312      }
1313  
1314      $form  = '<form action="' . esc_url( home_url( '/' ) ) . '" method="get" id="adminbarsearch">';
1315      $form .= _wp_admin_bar_icon( 'core-admin/search' );
1316      $form .= '<input class="adminbar-input" name="s" id="adminbar-search" type="text" value="" maxlength="150" />';
1317      $form .= '<label for="adminbar-search" class="screen-reader-text">' .
1318              /* translators: Hidden accessibility text. */
1319              __( 'Search' ) .
1320          '</label>';
1321      $form .= '<input type="submit" class="adminbar-button" value="' . __( 'Search' ) . '" />';
1322      $form .= '</form>';
1323  
1324      $wp_admin_bar->add_node(
1325          array(
1326              'parent' => 'top-secondary',
1327              'id'     => 'search',
1328              'title'  => $form,
1329              'meta'   => array(
1330                  'class'    => 'admin-bar-search',
1331                  'tabindex' => -1,
1332              ),
1333          )
1334      );
1335  }
1336  
1337  /**
1338   * Adds a link to exit recovery mode when Recovery Mode is active.
1339   *
1340   * @since 5.2.0
1341   *
1342   * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
1343   */
1344  function wp_admin_bar_recovery_mode_menu( $wp_admin_bar ) {
1345      if ( ! wp_is_recovery_mode() ) {
1346          return;
1347      }
1348  
1349      $url = wp_login_url();
1350      $url = add_query_arg( 'action', WP_Recovery_Mode::EXIT_ACTION, $url );
1351      $url = wp_nonce_url( $url, WP_Recovery_Mode::EXIT_ACTION );
1352  
1353      $wp_admin_bar->add_node(
1354          array(
1355              'parent' => 'top-secondary',
1356              'id'     => 'recovery-mode',
1357              'title'  => __( 'Exit Recovery Mode' ),
1358              'href'   => $url,
1359          )
1360      );
1361  }
1362  
1363  /**
1364   * Adds secondary menus.
1365   *
1366   * @since 3.3.0
1367   *
1368   * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
1369   */
1370  function wp_admin_bar_add_secondary_groups( $wp_admin_bar ) {
1371      $wp_admin_bar->add_group(
1372          array(
1373              'id'   => 'top-secondary',
1374              'meta' => array(
1375                  'class' => 'ab-top-secondary',
1376              ),
1377          )
1378      );
1379  
1380      $wp_admin_bar->add_group(
1381          array(
1382              'parent' => 'wp-logo',
1383              'id'     => 'wp-logo-external',
1384              'meta'   => array(
1385                  'class' => 'ab-sub-secondary',
1386              ),
1387          )
1388      );
1389  }
1390  
1391  /**
1392   * Enqueues inline style to hide the admin bar when printing.
1393   *
1394   * @since 6.4.0
1395   */
1396  function wp_enqueue_admin_bar_header_styles() {
1397      // Back-compat for plugins that disable functionality by unhooking this action.
1398      $action = is_admin() ? 'admin_head' : 'wp_head';
1399      if ( ! has_action( $action, 'wp_admin_bar_header' ) ) {
1400          return;
1401      }
1402      remove_action( $action, 'wp_admin_bar_header' );
1403  
1404      wp_add_inline_style( 'admin-bar', '@media print { #wpadminbar { display:none; } }' );
1405  }
1406  
1407  /**
1408   * Enqueues inline bump styles to make room for the admin bar.
1409   *
1410   * @since 6.4.0
1411   */
1412  function wp_enqueue_admin_bar_bump_styles() {
1413      if ( current_theme_supports( 'admin-bar' ) ) {
1414          $admin_bar_args  = get_theme_support( 'admin-bar' );
1415          $header_callback = $admin_bar_args[0]['callback'];
1416      }
1417  
1418      if ( empty( $header_callback ) ) {
1419          $header_callback = '_admin_bar_bump_cb';
1420      }
1421  
1422      if ( '_admin_bar_bump_cb' !== $header_callback ) {
1423          return;
1424      }
1425  
1426      // Back-compat for plugins that disable functionality by unhooking this action.
1427      if ( ! has_action( 'wp_head', $header_callback ) ) {
1428          return;
1429      }
1430      remove_action( 'wp_head', $header_callback );
1431  
1432      $css = '
1433          @media screen { html { margin-top: 32px !important; } }
1434          @media screen and ( max-width: 782px ) { html { margin-top: 46px !important; } }
1435      ';
1436      wp_add_inline_style( 'admin-bar', $css );
1437  }
1438  
1439  /**
1440   * Sets the display status of the admin bar.
1441   *
1442   * This can be called immediately upon plugin load. It does not need to be called
1443   * from a function hooked to the {@see 'init'} action.
1444   *
1445   * @since 3.1.0
1446   *
1447   * @global bool $show_admin_bar
1448   *
1449   * @param bool $show Whether to allow the admin bar to show.
1450   */
1451  function show_admin_bar( $show ) {
1452      global $show_admin_bar;
1453      $show_admin_bar = (bool) $show;
1454  }
1455  
1456  /**
1457   * Determines whether the admin bar should be showing.
1458   *
1459   * For more information on this and similar theme functions, check out
1460   * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
1461   * Conditional Tags} article in the Theme Developer Handbook.
1462   *
1463   * @since 3.1.0
1464   *
1465   * @global bool   $show_admin_bar
1466   * @global string $pagenow        The filename of the current screen.
1467   *
1468   * @return bool Whether the admin bar should be showing.
1469   */
1470  function is_admin_bar_showing() {
1471      global $show_admin_bar, $pagenow;
1472  
1473      // For all these types of requests, we never want an admin bar.
1474      if ( defined( 'XMLRPC_REQUEST' ) || defined( 'DOING_AJAX' ) || defined( 'IFRAME_REQUEST' ) || wp_is_json_request() ) {
1475          return false;
1476      }
1477  
1478      if ( is_embed() ) {
1479          return false;
1480      }
1481  
1482      // Integrated into the admin.
1483      if ( is_admin() ) {
1484          return true;
1485      }
1486  
1487      if ( ! isset( $show_admin_bar ) ) {
1488          if ( ! is_user_logged_in() || 'wp-login.php' === $pagenow ) {
1489              $show_admin_bar = false;
1490          } else {
1491              $show_admin_bar = _get_admin_bar_pref();
1492          }
1493      }
1494  
1495      /**
1496       * Filters whether to show the admin bar.
1497       *
1498       * Returning false to this hook is the recommended way to hide the admin bar.
1499       * The user's display preference is used for logged in users.
1500       *
1501       * @since 3.1.0
1502       *
1503       * @param bool $show_admin_bar Whether the admin bar should be shown. Default false.
1504       */
1505      $show_admin_bar = apply_filters( 'show_admin_bar', $show_admin_bar );
1506  
1507      return $show_admin_bar;
1508  }
1509  
1510  /**
1511   * Retrieves the admin bar display preference of a user.
1512   *
1513   * @since 3.1.0
1514   * @access private
1515   *
1516   * @param string $context Context of this preference check. Defaults to 'front'. The 'admin'
1517   *                        preference is no longer used.
1518   * @param int    $user    Optional. ID of the user to check, defaults to 0 for current user.
1519   * @return bool Whether the admin bar should be showing for this user.
1520   */
1521  function _get_admin_bar_pref( $context = 'front', $user = 0 ) {
1522      $pref = get_user_option( "show_admin_bar_{$context}", $user );
1523      if ( false === $pref ) {
1524          return true;
1525      }
1526  
1527      return 'true' === $pref;
1528  }


Generated : Sat Oct 24 08:20:34 2026 Cross-referenced by PHPXref