Advertisement
Plugins

Building the Favorite Plugins Plugin

by

Now that it's possible to favorite plugins on WordPress.org, wouldn't it be great to be able to make your favorites available for speedy install from within the WordPress dashboard? Let's build a plugin to do just that!


Finding Your Favorite Plugins

Most of us who use WordPress have, at some time or another, trawled through the WordPress.org plugin directory looking for a plugin to add a particular piece of functionality to a website. Often there's more than one option, and it can take a little time to asses which is the one that does the job best. Perhaps after a while, you have a handful of plugins you use on every install, and maybe a few that you really like for specific tasks. How do you keep track of them? Do you just search the plugin directory every time?

Not too long ago the favorites feature was released on WordPress.org, so now you can mark certain plugins as 'favorites', allowing you to easily find them from your profile. This is an excellent start to keeping track of them.

Even more recently, a new argument was added to the WordPress.org Plugin API to search for plugins favorited by a specific user. So now it would be possible to write a plugin to bring this functionality into the WordPress dashboard.

I wrote a plugin called 'Favorite Plugins', and I'm going to walk you through building it now.

Note: This functionality is actually going to be a part of WordPress when version 3.5 is released in December. We're building this plugin as an exercise in plugin building, and using the WordPress.org Plugin API.


Step 1 Building the Base of the Plugin

When building a plugin, it's a good idea to plan things out before you get too far into the nitty gritty of the code. This helps keep you focussed, and saves you writing lines and lines of code, only to realise you've got more code than you need and you've overcomplicated things.

So here's what our plugin is going to do:

  • Add a new tab called 'Favorites' to the 'Install Plugins' screen in the WordPress admin
  • On the new tab, we'll have a form to enter the WordPress.org username to use
  • If we have a username, we ask WordPress.org for the favorites for that user
  • Below the form we display a table showing all the favorite plugins for the provided user (if there are any)
  • We'll also remember the username entered to keep things convenient. After all, that's what this plugin is all about!

Now let's get our files in order. Create yourself a directory under /wp-content/plugins/ called wptuts-favorite-plugins. Inside this new directory, create yourself a file called wptuts-favorite-plugins.php. Then open the file up and, as always when developing a plugin, add the plugin header as follows:

<?php
/*
Plugin Name: Wptuts+ Favorite Plugins
Plugin URI: http://wp.tutsplus.com/tutorials/plugins/building-the-favorite-plugins-plugin/
Description: Quickly and easily access and install your favorited plugins from WordPress.org, right from your dashboard.
Version: 0.7
Author: Japh
Author URI: http://wp.tutsplus.com/author/japh
License: GPL2
*/
Favorite Plugins plugin

Now we'll create the class and stubs for the methods we're going to use in this plugin. We use a class to build the plugin so we can take advantage of features provided by developing using object-oriented methods, and it also keeps all our functions nicely namespaced.

Here's the class stub and the methods we'll need:

class Wptuts_Favorite_Plugins {

	public $username = null;

	function __construct() {
		// The constructor is used to kick things off, as it's run when the object is created
	}

	function add_favorites_tab( $tabs ) {
		// This is where we put code to add a favorites tab to the.
		return $tabs;
	}

	function get_favorites() {
		// Someone wants to see what's on the favorites tab, so we'd better get some stuff to show them
	}

	function install_plugins_favorites() {
		// Output the form to accept the WordPress.org username
	}

}

function wptuts_execute() {
	if ( (float) get_bloginfo( 'version' ) < 3.5 ) {
		// Kick everything into action...
		$wptuts_favorite_plugins = new Wptuts_Favorite_Plugins();
	}
}
add_action( 'admin_init', 'wptuts_execute' );

That's it! That's all the functionality we're building into this theme. Because we're building for the WordPress admin, we're trying to take full advantage of everything that's done for us.

Also, note that I've wrapped the initilisation line in an if statement to stop the plugin working on WordPress 3.5+, which will have this functionality itself anyway.


Step 2 Adding the Favorites Tab

This is the quickest and easiest part, so let's get it done first, and then we can refresh to see any progress as we go through too.

Firstly, we need to add the following code into the __construct method of our class:

add_filter( 'install_plugins_tabs', array( $this, 'add_favorites_tab' ) );

Here we're hooking onto WordPress' 'install_plugins_tab' filter which is exactly what we need to add a tab.

What's that array( $this, 'function_name' ) code doing? As you may be aware, when using object-oriented programming, the $this reserved word is used to refer to the current object. When using hooks in WordPress, the second parameter can be a string with the name of the function to use, or when using an object it can be an array with the object and specific method of the object to use.

Read more about this under Avoiding Function Name Collisions on the WordPress Codex.

Then we make the add_favorites_tab method of our class look like the following:

<?php
	function add_favorites_tab( $tabs ) {
		// This is where we put code to add a favorites tab to the.
		$tabs['favorites'] = __( 'Favorites' );
		return $tabs;
	}
?>

This simply adds an element to the $tabs array with a value of 'Favorites' to be displayed as the tab text. If you go to the 'Install Plugins' screen in your WordPress admin now, by clicking on 'Plugins' -> 'Add New', you'll see the 'Favorites' tab added there. Clicking it now will show you a lovely blank tab. Let's put some stuff on it.

Favorites tab

Step 3 Putting The Form in Our New Tab

Keep in mind that the tab is ultimately on the same page ('install_plugins') as the other tabs, and this page is actually just waiting for something to do depending on which tab is active. It also has hooks that use the tab name, such as 'install_plugins_pre_{$tab}', and 'install_plugins_{$tab}', both of which we're going to use.

What this means is that adding the form for the user to enter their WordPress.org username is also relatively simple. Add this line to the __construct method of our class:

add_action( 'install_plugins_favorites', array( $this, 'install_plugins_favorites' ), 10, 1 );

The install_plugins_{$tab} action happens in the body of the tab, and it expects two parameters. The second parameter is for the current page in paginaton. We don't need pagination for our form, so we supply the callback function and the default priority, and then specify that we're only going to pass one parameter.

Now we fill out our function to output the form:

	function install_plugins_favorites() {
		// Output the form to accept the WordPress.org username
		$this->username = isset( $_REQUEST['user'] ) ? stripslashes( $_REQUEST['user'] ) : $this->username;
		?>
			<p class="install-help"><?php _e( 'If you have marked plugins as favorites on WordPress.org, you can browse them here.' ); ?></p>
			<form method="get" action="">
				<input type="hidden" name="tab" value="favorites" />
				<p>
					<label for="user"><?php _e( 'Your WordPress.org username:' ); ?></label>
					<input type="search" id="user" name="user" value="<?php echo esc_attr( $this->username ); ?>" />
					<input type="submit" class="button" value="<?php esc_attr_e( 'Get Favorites' ); ?>" />
				</p>
			</form>
		<?php
	}
?>
Username form

First of all, we're setting the username to the one submitted through the form, if there is one. Otherwise, we grab the one we already have (we'll be setting this a little later in the tutorial).

Next we're providing some text to explain to users what this form is for. In the form, we have a hidden field for the tab value, so that when we submit it we come back to the same tab. The rest is the input field, the username field, and the submit button.


Step 4 We Have a Username, Let's Get Some Favorites

Users can submit a form with their username now, but nothing happens... we need to make a request to the WordPress.org Plugin API with the username, and then display the results.

Again we need to add a line to the __construct method of our class to add a method to a WordPress action. This time it's the install_plugins_pre_{$tab} hook, which runs earlier in the page processing. A good place for an API call.

add_action( 'install_plugins_pre_favorites', array( $this, 'get_favorites' ) );

I guess if we're calling that method we better make it do something useful:

	function get_favorites() {
		// Someone wants to see what's on the favorites tab, so we'd better get some stuff to show them
		global $wp_list_table;

		$this->username = isset( $_REQUEST['user'] ) ? stripslashes( $_REQUEST['user'] ) : $this->username;

		if ( $this->username ) {
			$args = array( 'user' => $this->username );
			update_user_meta( get_current_user_id(), 'wporg_favorites', $this->username );

			$api = plugins_api( 'query_plugins', $args );

			$wp_list_table->items = $api->plugins;
			$wp_list_table->set_pagination_args(
				array(
					'total_items' => $api->info['results'],
					'per_page' => 24,
				)
			);
		} else {
			$args = false;
		}
	}

This function also checks is there's a freshly submitted username, otherwise falls back to a saved one. We then check if the username is empty, because if it is there's no point making an API request. If the username wasn't blank, we first update a user meta value with a key of 'wporg_favorites' to be the current username.

We also set a variable called $args to be an array with a key 'user', and a value of the username to find favorites for. This is passed to the plugins_api() function, which we then essentially pass the return value of to $wp_list_table, and set some argument values for that too. We set the total_items and the per_page arguments, which is enough for what we need.

If you try running this now, you'll see we still get a blank page. That's because we haven't yet told the page to display the table of results. We are actually getting results from the API, we're just not displaying them.

Now, because the 'Install Plugins' page is already ready and willing to display these results, this part is super easy. Just add WordPress' built-in display_plugins_table function to the install_plugins_{$tab} action in our __construct method, like so:

add_action( 'install_plugins_favorites', 'display_plugins_table');

Voila! Like magic, we now have a pretty impressive table showing our favorite plugins!

Favorite plugins table

Step 5 Remember Me?

The last thing to do is make the form remember you when you come back later. At the moment, it'll remember you just fine between searches but if you browse away from the tab and back again, it'll have forgotten you.

This is just a matter of adding a small line to the __construct method of our class:

$this->username = get_user_option( 'wporg_favorites' );

All this line does is get the value of the user meta key 'wporg_favorites' and put it in the variable we're using in our plugin object.

Because we were stil saving it before, but not using it, even just refreshing the favorites tab now will use the last username you did put into the form.

So here's what the final __construct method should now look like:

	function __construct() {
		// The constructor is used to kick things off, as it's run when the object is created

		add_filter( 'install_plugins_tabs', array( $this, 'add_favorites_tab' ) );
		add_action( 'install_plugins_favorites', array( $this, 'install_plugins_favorites' ), 10, 1 );
		add_action( 'install_plugins_pre_favorites', array( $this, 'get_favorites' ) );
		add_action( 'install_plugins_favorites', 'display_plugins_table');

		$this->username = get_user_option( 'wporg_favorites' );
	}

Conclusion

That was surprisingly easy, right? We added an entirely new tab, did an API call, and output a table full of information, but we relied heavily on built-in WordPress functionality, which sure did save us a lot of work.

Whenever you're working on WordPress projects and are adding admin functionality, think of the DRY principal: Don't Repeat Yourself, or for that matter, Don't Repeat WordPress. Look for opportunities to take advantage of what WordPress already provides for you.

Let me know what you think of this plugin in the comments. This same feature is coming to WordPress in version 3.5, do you think it adds value to the favoriting functionality on WordPress.org?

Related Posts
  • Code
    Plugins
    Distributing Your Plugins in GitHub with Automatic UpdatesSensorsthumbnail
    This article will teach you that, with a little creative coding, you can host your own WordPress plugins in GitHub while still retaining the automatic update feature.Read More…
  • Code
    Theme Development
    Creating a WordPress Theme From Static HTML: The Footer FileCreating wordpress theme from html 400
    In this series, you've been learning how to create a WordPress theme form static HTML. Up to this point, you have: prepared your markup for WordPress converted your HTML to PHP and split your file into template files edited the stylesheet and uploaded your theme to WordPress added a loop to your index file added meta tags, the wp_head hook and the site title and description to your header file added a navigation menu added widget areas to the header and sidebar. Read More…
  • Code
    PHP
    Validation and Exception Handling: From the UI to the BackendProcedural to oop php retina preview
    Sooner or later in your programming career you will be faced with the dilemma of validation and exception handling. This was the case with me and my team also. A couple or so years ago we reached a point when we had to take architectural actions to accommodate all the exceptional cases our quite large software project needed to handle. Below is a list of practices we came to value and apply when it comes to validation and exception handling.Read More…
  • Code
    Plugins
    Using HighCharts in WP-AdminHighcharts 400
    Charts are a great way to present data. They make data more digestible by making it visually appealing. In WordPress, there is no built-in method for getting posts and pages data in a graphical form. Although, there are certain plugins available which integrate Google Analytics with WordPress, but they are overkill if you want to get only a portion of that data. Also, nothing should keep you from learning new techniques and to dive straight into the subject is the best way to learn.Read More…
  • Code
    Plugins
    Displaying Information of a WordPress.org Plugin on Your WebsiteWordpressdotorg plugin api border 400
    In the first part of this article, we discussed how to use built-in functions to communicate with WordPress.org and retrieve plugin details. In this tutorial we will put the theory in action to create a simple plugin which will allow us to display details of any plugin hosted on WordPress.org on our WordPress website using shortcodes.Read More…
  • Code
    Creative Coding
    A Look at the WordPress HTTP API: A Practical Example of wp_remote_postDiagram http api
    In the previous article, we reviewed the previous articles regarding GET requests, the native PHP facilities for making requests, and reviewed WordPress wp_remote_post API function along with the arguments that it offers. In this article, we're going to make use of wp_remote_post such that we're actually able to see it in action. Remember that this - like wp_remote_post - is part of the HTTP API of which there are other functions worth reviewing. But, for now, we're going to put wp_remote_post to work. Specifically, we're going to do the following: When the page loads, we're going to submit some information to a custom script The script will examine the information and return it to our page We'll then display the data on the page Sure, it's a bit of a contrived example but it will give us the experience of creating a separate PHP script that can be used for operations triggered by the use of wp_remote_post. Anyway, for the purposes of this example, we are going to use the PHP $_SERVER collection to log when the user has submitted their preference rather than require that they have logged in. Finally, the source code will be made available on GitHub and accessible at the end of this series in the following article. For now however, let's get started with working on the plugin.Read More…