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.
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.
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.
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.
- We need a new drop-down menu titled “ExoplanetArchive.�
- The title of the new menu should link to the archive’s home page, which will contain more information
- 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:
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!
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.�
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)
© Dominic Giglio for Smashing Magazine, 2012.