Inside The WordPress Toolbar

Advertisement

The WordPress Admin Bar, first introduced in version 3.1, debuted to mixed reactions. A Google search for “wordpress admin bar” returns multiple articles about how to disable or remove it. Version 3.2 of WordPress introduced new features and functionality, and version 3.3 has not only further enhanced it but integrated the header of the admin section into the bar itself. Since this feature is not going anywhere and it figures largely in WordPress’ plan to implement front-end editing, I think we would all benefit from looking at where its features come from and how best to make this sometimes controversial feature work for us.

Inside the WordPress Toolbar

In addition to the explanations of how to get rid of the Admin Bar, you will also find on the Web no shortage of techniques and tips for customization, as well as a multitude of plugins that make working with the Admin Bar a little more enjoyable. While I am a huge fan of plugins, knowing where a feature comes from is important before deciding whether to customize it. In this article, we’ll look at the history of the Admin Bar, when (and from where) the bar is enabled, the particular functions that WordPress’ core developers have given us, and how to make the Admin Bar more personal and useful.

Genesis

In the beginning, the Admin Bar didn’t do a whole lot. I suspect this was the main cause of the negative feedback. Initially, it was enabled on the front end of the website and disabled in the admin section. If you were logged in while viewing a public page, the Admin Bar provided a new conduit to the admin section. It had:

  • Links to edit your profile, view the dashboard and log out;
  • An “Add New” drop-down menu, containing links for only “Post” and “Page”;
  • A link to the admin page for comments, alongside the number of comments pending approval;
  • An “Appearance” drop-down menu, with direct links to the admin section’s widget and menu pages;
  • A link to the admin page for updates, alongside the number of pending updates;
  • An “Edit Post” link displayed when viewing an individual post.

WordPress 3.1 Admin Bar
The Admin Bar in WordPress 3.1

While this was a great start, some found the limited functionality to be more of an eyesore than a revolutionary enhancement to the administration of their blog. Couldn’t the venerable minds that brought us custom fields, custom post types and automatic updates do more? Yes, they could.

Version 3.2 brought a lot of great new features and fixes to WordPress blogs, and the Admin Bar was on the receiving end of some of these enhancements. Most importantly, the new version distinguished between the Admin Bar on public pages and the one in the admin section. The Admin Bar was evolving, growing more dynamic. Although still not a game-changer by any stretch, it was an improvement.

The updates included the following:

  • The “Dashboard” link was moved from the user menu to its own slot on the public-facing Admin Bar;
  • A “View Post/Page” link was added to the admin section for when you’re editing a post or page;
  • “Media,” “Link,” “User,” “Theme” and “Plugin” links were added to the “Add New” drop-down menu;
  • “Themes,” “Background” and “Header” links were added to the “Appearance” drop-down menu.

Now we’re getting somewhere! These updates were an improvement, but we were still far from a WordPress-worthy tool. It still felt out of place and didn’t look like it belonged. The shouts were heard once more: “Give me an Admin Bar that WordPress can be proud of!”

Version 3.3 Steps Up

The server-stretching features that rolled out with the current 3.3 version are slick to say the least. Until this latest release, our poor Admin Bar, the one we were beginning to have such high hopes for, was practically lost in a forest of features. Now this update has brought the potential power of the Admin Bar into focus. No longer does the bar look like it’s hanging over the page: it’s sleek, it’s clean, it blends in. Now it looks like it’s supposed to be there. Finally, an Admin Bar we can get behind!

Foremost among the improvements: it’s not called the Admin Bar anymore! It is now the WordPress Toolbar. All of the admin section’s contact and informational links have been integrated into a drop-down menu denoted by the WordPress logo, which is more logical. The “Visit Site” link is now hidden under a drop-down menu displaying the website’s name (a nice addition for those of us who routinely use the admin sections of multiple websites). When the toolbar is displayed on a public page, the drop-down menu with the website’s name doubles as the old “Appearance” menu, linking to the most viewed pages of the admin section. Most importantly, it has been drastically simplified.

WordPress 3.3 Toolbar showing updates
The WordPress 3.3 Toolbar, showing updates.

The comments link has been replaced by a comments bubble, which is visually more descriptive, and the “Appearance” drop-down menu has been removed from the toolbar in the admin section since the addition of the fly-out menus has made it mostly redundant. The drive towards a more dynamic toolbar continues with the updates link being displayed only when a newer version has been detected, and it, too, has been replaced by an icon. These small but powerful changes all lead to the unmistakable feeling that the toolbar looks empty. We’ll get back to that in a minute.

Going To The Source

Back in August 2011, I wrote about how WordPress initializes itself when a page is requested from the server. In that post, I walk through, almost line by line, where the majority of WordPress’ core functionality comes from. The file wp-settings.php is responsible for loading the lion’s share of what we consider to be “WordPress,” including the toolbar. As of version 3.3, the toolbar’s code is required from an external file on line 145 of wp-settings.php. The name of this file is (oddly enough still) admin-bar.php, and it lives in the /wp-includes directory (along with the vast majority of the rest of WordPress’ core). This file is no slouch: it clocks in at 745 lines of code and defines a good deal of the functions needed for us to be able to work with the toolbar.

When analyzing the source code for WordPress, I turn to a certain command frequently to get a quick idea of the functionality that a file does (or doesn’t) provide. If you’re running Linux or on a Mac, try this in your favorite terminal (from your WordPress root directory):

cat wp-includes/admin-bar.php | grep ^function

That command should produce something similar to the following output:

function _wp_admin_bar_init() {
function wp_admin_bar_render() {
function wp_admin_bar_wp_menu( $wp_admin_bar ) {
function wp_admin_bar_my_account_item( $wp_admin_bar ) {
function wp_admin_bar_my_account_menu( $wp_admin_bar ) {
function wp_admin_bar_site_menu( $wp_admin_bar ) {
function wp_admin_bar_my_sites_menu( $wp_admin_bar ) {
function wp_admin_bar_shortlink_menu( $wp_admin_bar ) {
function wp_admin_bar_edit_menu( $wp_admin_bar ) {
function wp_admin_bar_new_content_menu( $wp_admin_bar ) {
function wp_admin_bar_comments_menu( $wp_admin_bar ) {
function wp_admin_bar_appearance_menu( $wp_admin_bar ) {
function wp_admin_bar_updates_menu( $wp_admin_bar ) {
function wp_admin_bar_search_menu( $wp_admin_bar ) {
function wp_admin_bar_add_secondary_groups( $wp_admin_bar ) {
function wp_admin_bar_header() { ?>
function _admin_bar_bump_cb() { ?>
function show_admin_bar( $show ) {
function is_admin_bar_showing() {
function _get_admin_bar_pref( $context = 'front', $user = 0 ) {

This obviously doesn’t tell us a whole lot about what exactly the file does, but the core developers have named functions descriptively enough to give us an inkling of the responsibilities of the files that define them.

The output above tells us that this file contains 20 functions. But you will eventually come across a file that outputs so many functions that you couldn’t possibly count them (I’m talking to you, functions.php!). To quickly count how many functions are in a file, you can append wc -l to the above command:

cat wp-includes/admin-bar.php | grep ^function | wc -l

This returns a line count in the output of the preceding grep command.

Enough command-line fu. Let’s talk about how these functions bestow the toolbar upon our website! With a quick glance, we can glean some valuable information from the names of these function. Obviously, the first one initializes the toolbar. The second is also pretty self-explanatory: it renders the toolbar. The next 14 functions add the default items to the toolbar and set its initial styling. The name _admin_bar_bump_cb() is not as revealing; this is a callback function that outputs to the page a style tag that creates enough margin at the top to display the toolbar. The final three are fairly easy: show_admin_bar() shows and hides the toolbar; is_admin_bar_showing() can be used in your plugin or theme’s functions.php file to check whether the toolbar should be displayed at all; and _get_admin_bar_pref() is used by is_admin_bar_showing().

By far the most important function is _wp_admin_bar_init(). On line 39 of admin-bar.php, this function is added to the init action hook. This hook is one of the last to be executed during WordPress’ initialization. If you look at this function, you will see its true importance: it is responsible for loading the WP_Admin_Bar class from class-wp-admin-bar.php. After instantiating this class, it executes two of its methods that use most of the functions discussed above: initialize() and add_menus(). The former is responsible for creating our toolbar object in memory, while the latter attaches 11 of the functions defined in admin-bar.php to the action hook admin_bar_menu, which ensures that they are executed at the right time. These 11 functions are responsible for populating the toolbar with all of its default functionality. Basically, admin-bar.php defines the functions that give life to the toolbar, and class-wp-admin-bar.php defines the methods that enable us to interact with it once it’s alive.

Boring!

I know, I know. Reading source code is never glamorous. But it is essential to learning about capabilities that are not apparent from other resources and tutorials. Earlier, I said that the toolbar in version 3.3 looks a little empty. And when I see empty space, I can’t help but want to fill it with cool stuff! So, let’s get our fingers dirty and start poking the toolbar to make it wake up and do some tricks. To keep these examples normalized, we’ll use the TwentyEleven theme for all of the following code. If you want to follow along at home, just pop open the functions.php file in TwentyEleven and hack along with me. Your mileage will vary with other themes.

Showing and Hiding

Let’s start with an easy task. We saw above that admin-bar.php defines the show_admin_bar() function. While you can disable the toolbar by unchecking a box in your user profile, let’s see how to do it in code. Add the following to the end of functions.php:

/**
* Hide the Toolbar if not in the admin section
*/
if ( ! is_admin() ) {
show_admin_bar(false);
}

Three lines — no more toolbar! Hardly a profound example, but it’s a start. This code first checks whether we are on an admin page, and if we are not, then we tell WordPress to hide the toolbar.

Removing Default Items

I’m not feeling that “+ New” menu. It has an attitude, and I want to show it who’s boss. Let’s dump it.

/**
* Remove the "+ New" menu from the Toolbar
*/
function remove_toolbar_new_menu() {
global $wp_admin_bar;
$wp_admin_bar->remove_menu('new-content');
}
add_action('admin_bar_menu', 'remove_toolbar_new_menu', 300);

Take that, “+ New” menu! The code is fairly straightforward, but let’s walk through it anyway. Back in admin-bar.php, the _wp_admin_bar_init() function assigns our new WP_Admin_Bar class to the variable $wp_admin_bar. So, first we have to use PHP’s global keyword to bring that variable into our function’s scope. After that, all we have to do is call the remove_menu() method and pass it the ID we want to remove.

The trick is getting this function to be called at the right time. There are a few ways to accomplish this. Remember that _wp_admin_bar_init() calls the add_menus() method after initialization. Looking at that method in class-wp-admin-bar.php, we see that all of the default items in the toolbar are created by adding them to the admin_menu_bar action hook. So, one way to do this is to have our custom function executed on the same hook after all of the defaults (which kind of makes sense since we are removing a default item). This is accomplished in the example above by passing the number 300, which is a priority argument that is passed to the add_action() hook, thus ensuring that our function executes after all of the defaults.

But this is a bit dirty. Messing around with the hook used to set up all of the defaults is not a good idea. For one thing, we don’t know when the priority numbers in the core will be changed. A cleaner way is to attach our custom function to a hook that is better suited to what we’re trying to do. The core developers always do a great job of providing additional hooks and filters for occasions such as this. Jumping back into admin-bar.php, we can see that the second function, wp_admin_bar_render(), wraps the call to the admin bar’s class method, render(), in before and after hooks. You’ll also notice that wp_admin_bar_render() is attached to the footer action hooks. This is a far more appropriate place to attach our custom function, because the priority numbers in the core are much more likely to change before these two hooks do. Let’s update our code, then, to future-proof it a bit:

/**
* Remove the "+ New" menu from the Toolbar
*/
function remove_toolbar_new_menu() {
global $wp_admin_bar;
$wp_admin_bar->remove_menu('new-content');
}
add_action('wp_before_admin_bar_render', 'remove_toolbar_new_menu');

Much better. However, these two techniques are explained elsewhere on the Web. Also, I lose focus easily; if the task at hand isn’t sufficiently engaging, I run the risk of Netflix-ing an old episode of Ancient Aliens, at which point my project is done for. One would also expect more from an article titled “Inside the WordPress Toolbar.” So, let’s do more… a lot more.

Outta This World

At 10:49 pm EST on 6 March 2009, a Delta II rocket lifted off from Launch Complex 17-B at Cape Canaveral Air Force Station in Florida. Atop the 10,000 gallons of liquid oxygen propellant sat a little telescope that was destined to forever change how we view our little corner of the Milky Way galaxy. Kepler — named after Johannes Kepler, who defined the laws of planetary motion, which later served as the foundation of Isaac Newton’s theory of universal gravitation — was engineered and constructed to study 100,000 stars in our galactic neighborhood for at least three and a half years. The mission’s goal is to find Earth-sized terrestrial extrasolar planets in the habitable zone of their host star(s).

To help our fellow WordPressers keep up on the progress of this monumental mission, as well as the ongoing efforts of other planet-hunters, we are going to build a menu for the Toolbar that displays the current number of confirmed exoplanets, as well as the number of candidates that have yet to be independently verified. We’ll use an API from the NASA Exoplanet Archive that enables us to query for both confirmed and unconfirmed exoplanet candidates in XML format. But before we get into the code, let’s outline what exactly the code needs to do.

  1. We need a new drop-down menu titled “ExoplanetArchive.”
  2. The title of the new menu should link to the archive’s home page, which will contain more information
  3. The menu should display the current number of both confirmed and candidate exoplanets.

Sounds easy enough. Let’s see if it is.

A New Item

I like seeing data quickly, so let’s put the new item in the top level of the toolbar. The WP_Admin_Bar class provides a method called add_menu() that (surprise!) does the opposite of what is done by the method that we used above (which got rid of the “+ New” menu). If you’re following along at home, add the following code to the bottom of the functions.php file:

/**
* Add the Smashing WP Exoplanets menu
*/
function smashing_wp_exoplanets_menu() {
global $wp_admin_bar;
$wp_admin_bar->add_menu(array(
'id' => 'smashing-wp-exoplanets',
'title' => __('ExoplanetArchive'),
'href' => 'http://exoplanetarchive.ipac.caltech.edu/index.html'
));
}
add_action('wp_before_admin_bar_render', 'smashing_wp_exoplanets_menu');

As you can see, the process of adding an item to the toolbar isn’t that different from removing one. We’ve defined a new custom function named smashing_wp_exoplanets_menu(); brought the WP_Admin_Bar class instance into our function’s scope with PHP’s global keyword; and instructed the class to add a new menu. The add_menu() method takes an array as an argument. Internally, the WP_Admin_Bar class will pass this array to another function, named add_node(), that handles all of the heavy lifting. The add_node() function will accept six elements from the array that you pass to add_menu():

  • id,
  • title,
  • parent,
  • href,
  • group
  • meta.

The id is required, and meta should be an array of additional attributes made up of the following six keys:

  • html,
  • class,
  • onclick,
  • target,
  • title,
  • tabindex.

We are using the same action hook to add our new menu to the toolbar right before it is rendered. If all has gone well on your end, the toolbar should now look like this:

Smashing WP Exoplanets 1
The beginning of the exoplanets menu in our WordPress installation for Smashing Magazine.

Drop Down Like It’s Hot

Not a bad start, but still far from what we’re aiming for. Still, with only nine lines of code, we’ve accomplished about half of the tasks we set out to do. The toolbar item has the correct title, and the title links to Exoplanet Archive’s home page. It’s not a drop-down menu yet, though. Fortunately, transforming this featureless link into a menu is a snap. Let’s update our custom function to include the following code:

/**
* Add the Smashing WP Exoplanets menu
*/
function smashing_wp_exoplanets_menu() {

…existing code…

$wp_admin_bar->add_menu(array(
'id' => 'smashing-wp-confirmed-count',
'parent' => 'smashing-wp-exoplanets',
'title' => __('Confirmed Exoplanets')
));

$wp_admin_bar->add_menu(array(
'id' => 'smashing-wp-candidate-count',
'parent' => 'smashing-wp-exoplanets',
'title' => __('Candidate Exoplanets')
));
}
add_action('wp_before_admin_bar_render', 'smashing_wp_exoplanets_menu');

I’ve omitted the existing code for brevity and so that you can see how simple adding items to a parent really is. We replaced the href attribute with a parent attribute that instructs WordPress to place this menu under our original. All we had to do was list the parent’s ID in the parent array element of each new menu. How great is that? Poof! Our link to the Exoplanet Archive magically becomes a drop-down menu. Of course, there really isn’t any magic — just the ingenuity of the core’s developers. When the toolbar is being rendered, a protected function named _bind() is called that handles all of the details about what belongs to what and where they’re supposed to be rendered. You gotta love WordPress!

Smashing WP Exoplanets 2
Dropping down our Exoplanets menu

Get Your Count On

Only one thing left: the counter for the number of exoplanets. Initially, I tried fetching the XML feeds using fetch_feed(). After some research, I decided that fetch_feed() should be used only when you need to pull in well-formed RSS. I decided instead to use the DOMDocument PHP class to create an instance of an XML document that can be queried and manipulated. It turns out that this works quite well. Here is the final code, from start to finish, with some helpful comments. This should now be at the bottom of your functions.php file:

/**
* Add the Smashing WP Exoplanets menu
*/
function smashing_wp_exoplanets_menu() {

// bring the admin bar class into this function's scope
global $wp_admin_bar;

// create new DOMDocuments to store the responses from the Exoplanet Archive
$confirmed_object = new DOMDocument();
$candidate_object = new DOMDocument();

// load XML feeds for confirmed and candidate exoplanets
$confirmed_object->load('http://exoplanetarchive.ipac.caltech.edu/cgi-bin/
nstedAPI/nph-nstedAPI?table=exoplanets&select=pl_hostname&format=xml');
$candidate_object->load('http://exoplanetarchive.ipac.caltech.edu/cgi-bin/
nstedAPI/nph-nstedAPI?table=keplercandidates&select=kepid&format=xml');

// get arrays of confirmed exoplanets and candidates
$confirmed = $confirmed_object->getElementsByTagName("TR");
$candidates = $candidate_object->getElementsByTagName("TR");

// create titles to be used in submenus
$confirmed_title = 'Confirmed Exoplanets: ' . $confirmed->length;
$candidate_title = 'Candidate Exoplanets: ' . $candidates->length;

// create top-level drop-down menu
$wp_admin_bar->add_menu(array(
'id' => 'smashing-wp-exoplanets',
'title' => __('ExoplanetArchive'),
'href' => 'http://exoplanetarchive.ipac.caltech.edu/index.html'
));

// create confirmed exoplanet submenu item
$wp_admin_bar->add_menu(array(
'id' => 'smashing-wp-confirmed-count',
'parent' => 'smashing-wp-exoplanets',
'title' => $confirmed_title
));

// create candidate exoplanet submenu item
$wp_admin_bar->add_menu(array(
'id' => 'smashing-wp-candidate-count',
'parent' => 'smashing-wp-exoplanets',
'title' => $candidate_title
));
}
add_action('wp_before_admin_bar_render', 'smashing_wp_exoplanets_menu');

In the final code here, we created two new instances of the DOMDocument class, and then called their load() method to pull in the XML feeds from the Exoplanet Archive. Once the feeds are loaded, we call getElementsByTagName() on each object to create an array of planets from each feed. If you look at the XML that is returned in a browser, you will see that each row from the Exoplanet Archive database is wrapped in a tr element. By creating an array of all tr elements, we are able to count the elements in the array to get the number of planets returned. You can see that we’re doing just that in the next step. We take the count (i.e. length) returned from each array and concatenate it onto the end of each title string. The only change to the code from the previous snippets is that we’re now using the title variables when creating each “submenu.”

Smashing WP Exoplanets 3
The final exoplanets menu, with planet counters.

This code will obviously strain your bandwidth because every single page load requires a call to the Exoplanets Archive to update the planet counters. The sample code above needs drastic optimization and refactoring cycles before it can be considered both robust and stable. For the purposes of this article, though, our hack-ish attempts to just make it work will have to do. This could be an ideal scenario in which to use the Transients API, which enables us to stick the planet counters in our database and assign an expiration value that triggers an update far less frequently. But that’s an article for another day. Perhaps we’ll follow up by turning this example into a full-blown toolbar plugin!

Conclusion

Despite the mixed reactions following the debut of the Admin Bar, tremendous progress has been made, and a lot of functionality has been added. If your toolbar is currently disabled, please give it a second look. You just might find that this tempting 28-pixel-tall canvas is not that difficult to customize. The core team had reasons for adding its features, even if they’re not immediately apparent.

This research has made use of the NASA Exoplanet Archive, which is operated by the California Institute of Technology, under contract with the National Aeronautics and Space Administration under the Exoplanet Exploration Program.

Other Resources

(al)

↑ Back to top

Dominic Giglio is a 30-something college student trying to make it in NYC. He blogs way to infrequently at humanshell.net and when he has the money he trades stocks, options and futures.

  1. 1

    Sincerely, only recently I’ve started using the Admin Bar in my workflow. I was quite annoyed by its presence in the past, since it could break the design of the page at some degree. But I admit it has potential. Thanks for illuminating on the topic.

    ps. We also have now tools for front-editing contents, which is just super awesome to integrate with the admin bar.

    0
  2. 2

    New knowledge, thank you…

    0
  3. 3

    Regardless of how they add to the admin bar in WordPress, I will still stay away from it. Why? Not because it occasionally messes up the theme design (frontend)… Not because it lacks features I want…

    Because I like the layer of abstraction that the admin panel gives between viewing & administrating. When you’re frontend you’re viewing. Administration side, you’re editing. It’s a clear & simple distinction. Anything that’s clear & obvious to clients is a winner.

    With the admin bar, it’s just one more thing to explain. One more thing to break. One more thing for the client to question you about. Does it save time? Maybe a second here or there. “Where has my admin bar gone?” – “You’re not logged in”. “Why has my design got this across the top?”. “Omg, the public (anyone) must be able to edit my site”. Dumb yes. Happened? Yes.

    One browser window, 2 tabs. Job done, with clarity.

    0
  4. 4

    Nice techniques to add toolbar inside the WordPress.Thank you.

    0
  5. 5

    Thanks for a excellent writeup on the inner-workings of the Toolbar. I also appreciate the shell commands, always a treat to add a tidbit to my arsenal of notes. I’ve always relied sort of heavily on my ability to search the Codex, so nice to have a bit of a shortcut! A couple of items of note for things you touched on that may be changing in 3.4:

    1) You’ll be happy to note that functions.php is being split up into separate files, though we’ll see if those patches make it in for 3.4 (#19552).

    2) When in the admin, wp_admin_bar_render has been moved to the in_admin_header hook because it made several slow-loading Dashboard pages look broken sans Toolbar when loading with the footer (#20161).

    0
    • 6

      I’m glad you got a little something from the article. Thank you for the links to those Trac tickets, I think breaking up functions.php is an excellent idea. I was planning on writing a whole article on just that file, I guess I’ll wait and write about the changes once they make it into core.

      0
  6. 7

    Please theme & plugin developers don’t use this as a place for your logo or other marketing.

    0
  7. 8

    Is very helpful for a network… definitely!

    0
  8. 9

    Does there any tweak how to add some menu on Favorite session? So we can access our favorit menu easily and quickly?

    0
  9. 10

    Dominic, very impressing and incredibly interesting. Thank you for such an in-depth walkthrough and contribution. Will have to read it at least twice more to get a better grip on things. Big ups!

    0
  10. 11

    Hey Dominic, which code editor (and which skin, theme..) did you use in the first screenshot. Looks great! :-)

    0
    • 12

      The post’s featured image uses a screenshot of my Vim setup (technically MacVim) – using the default Color Scheme: macvim. If you’re interested in learning how to setup a Vim environment you can see my dotfiles repo here:

      github.com/humanshell/dotfiles

      Everything I’ve learned about setting up and configuring Vim (.vimrc & bundles) comes from this repo:

      github.com/krisleech/vimfiles

      0
  11. 13

    Hello Dominic

    According to WordPress the preferred way to add items to the toolbar is to use the add_node() method instead of add_menu().

    “The Admin Bar is replaced with the toolbar since WordPress Version 3.3. The preferred way to add items to the toolbar is with add_node().”

    You mentioned the add_node method in this tutorial, is there any reason why you didn’t use this method instead of add_menu() in this tutorial?

    0
    • 14

      add_menu() is just a wrapper around add_node(). It’s used throughout admin-bar.php, so I decided to use it – but also to make sure that I mentioned that add_node() is ultimately the method being used internally to create the Toolbar items.

      0

Leave a Comment

Yay! You've decided to leave a comment. That's fantastic! Please keep in mind that comments are moderated and rel="nofollow" is in use. So, please do not use a spammy keyword or a domain as your name, or else it will be deleted. Let's have a personal and meaningful conversation instead. Thanks for dropping by!

↑ Back to top