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.
Getting Started
I'm assuming that you are a plugin developer and know the basics, but if in doubt, I suggest reading the following two articles:
- Two Ways to Develop WordPress Plugins: Functional Programming
- Two Ways to Develop WordPress Plugins: Object-Oriented Programming
What Are We Making?
With this plugin we want to create a shortcode such as [mpi slug='my-plugin-information' field='version']
that can accept two attributes: "slug" and "field", then based on that we then retrieve and display information of any plugin hosted in the WordPress.org repository.
Creating the Plugin Base
Lets start by creating a folder named my-plugin-information in your wp-content/plugins directory. Inside it, create a file named my-plugin-info.php and paste the below code in it:
<?php /* Plugin Name: My Plugin Info Plugin URI: http://myplugininfo.com Description: Communicate with WordPress.org Plugins API to retrive your Plugin Information Version: 0.1 Author: Harish Author Email: [email protected] License: GPL3 */ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly if ( ! class_exists( 'DOT_MyPluginInfo' ) ) { class DOT_MyPluginInfo { /** * Constructor */ function __construct() { //Hook up to the init action add_action( 'init', array( &$this, 'init_my_plugin_info' ) ); } /** * Runs when the plugin is initialized */ function init_my_plugin_info() { // Register the shortcode [mpi slug='my-plugin-info' field='version'] add_shortcode( 'mpi', array( &$this, 'render_mpi' ) ); } function render_mpi($atts) { } } // end class new DOT_MyPluginInfo(); } ?>
What Did We Do?
In the above code, we have created and initialized our plugin class DOT_MyPluginInfo
. Inside it are the general blocks of any plugin, for example the __construct()
method.
The function init_my_plugin_info
is hooked to the init
action so that it runs after WordPress is loaded but before any headers are sent. Inside the function init_my_plugin_info
we have registered our shortcode using the add_shortcode
function.
Note: To read more about add_shortcode
, check out the Codex.
The above plugin now has enough code to be recognized by WordPress from the plugin dashboard. If you have already created a file as instructed you can now visit the Plugins page and activate this plugin.
Setting Up the Shortcode
Since we want the flexibility to choose which information we want to display about a plugin, we created a shortcode with two attributes. The first called "slug" will be used to specify which plugin's data needs to be retrieved. The second attribute "field" will be used to specify which exact piece of information about a plugin we need to display.
So, for example, if we want to display the number of times this plugin has been downloaded, we simply need to add the text below the post editor and the end result should be something like "Downloaded 100 times."
Downloaded [mpi slug='my-plugin-information' field='downloaded'] times.
Using add_shortcode
we registered our shortcode so that whenever the shortcode is found in the post content, the function render_mpi()
will be called to process it. From now on, the rest of the code will be placed inside this function to handle our shortcode.
Processing the Shortcode With render_mpi()
To display plugin information we first need to process the shortcode to get the attributes. Add the code below inside the render_api
function:
// get our variable from $atts extract( shortcode_atts( array( 'slug' => '', //foo is a default value 'field' => '' ), $atts ) );
This extracts the two attributes "slug" and "field" if they are provided. Before going forward, we first check if values for "slug" and "field" exist, and if they don't, then we stop processing further.
/** * Check if slug exists */ if ( ! $slug ) { return false; } /** * Check if field exists * Return value based on the field attribute */ if ( ! $field ) { return false; } else { } // $field check
The code above will check if "slug" exists, and if it doesn't, then it will return false. If "slug" does exist, it will proceed towards checking the "field" attribute. Since we are only creating a shortcode to display a specific piece of information about a plugin, checking if both attributes exist before processing further will save unnecessary calls to the WordPress.org plugins API.
Now if values for "slug" and "field" attributes are provided in the shortcode, we proceed forward by first sanitizing both values.
// Sanitize attributes $slug = sanitize_title( $slug ); $field = sanitize_title( $field );
Storing Plugin Data in Transients
To avoid sending a request to WordPress.org every time a page containing this shortcode loads, we need to save the plugin information locally. This way, if you have placed more than one shortcode to display different details of the same plugin, we can then speed up the process by displaying data from the information saved locally on your website.
But what if the plugin updates and we continue showing old data? Well to sort that out, the quickest possible option is to save our individual plugin data using the Transients API and setting an expiry date on the data.
Another issue would be if you have shortcodes that are retrieving data about different plugins. If we store them with a single transient name, the result could be unexpected. To tackle this we give a unique name to the saved transients using the "slug" attribute.
Why Go Through All of This?
- To save information about each plugin separately
- To make fewer requests to WordPress.org
- To load data faster by serving it directly from your own website
Let's proceed by first creating a variable $mpi_transient_name
to save unique transient names based on the "slug" attribute.
// Create a empty array with variable name different based on plugin slug $mpi_transient_name = 'mpi-' . $slug;
Next we check, if the transient already exists:
/** * Check if transient with the plugin data exists */ $mpi_info = get_transient( $mpi_transient_name );
If the transient exists, we then proceed towards displaying data based on the "field" attribute or else we use plugins_api
to connect to WordPress.org and request the plugin information.
if ( empty( $mpi_info ) ) { /** * Connect to WordPress.org using plugins_api * About plugins_api - * http://wp.tutsplus.com/tutorials/plugins/communicating-with-the-wordpress-org-plugin-api/ */ require_once( ABSPATH . 'wp-admin/includes/plugin-install.php' ); $mpi_info = plugins_api( 'plugin_information', array( 'slug' => $slug ) ); // Check for errors with the data returned from WordPress.org if ( ! $mpi_info or is_wp_error( $mpi_info ) ) { return false; } // Set a transient with the plugin data // Use Options API with auto update cron job in next version. set_transient( $mpi_transient_name, $mpi_info, 1 * HOUR_IN_SECONDS ); }
In the code above, we did three things:
- We connected to WordPress.org and requested the plugin information. The request is then saved in a variable named
$mpi_info
- We then do error checking to ensure if data was returned without error
- Lastly we created a new transient with an expiration date of one hour
Now if the value of the slug attribute was "my-plugin-information
" then the name of the transient that stores the plugin information would be "mpi-my-plugin-information
".
Note: To learn more about plugins_api
refer to the first article of this series, shown at the top of this post.
Displaying Plugin Information
The last step involves returning specific information based on the value of the "field" attribute. To do this we simply use individual checks.
if ( $field == "downloaded" ) { return $mpi_info->downloaded; } if ( $field == "name" ) { return $mpi_info->name; } if ( $field == "slug" ) { return $mpi_info->slug; } if ( $field == "version" ) { return $mpi_info->version; } if ( $field == "author" ) { return $mpi_info->author; } if ( $field == "author_profile" ) { return $mpi_info->author_profile; } if ( $field == "last_updated" ) { return $mpi_info->last_updated; } if ( $field == "download_link" ) { return $mpi_info->download_link; }
Wrapping Up
Complete plugin code:
<?php /* Plugin Name: My Plugin Information Plugin URI: http://wp.tutsplus.com Description: Communicate with WordPress.org Plugins API to retrive your Plugin Information Version: 0.1.1 Author: Harish Author Email: [email protected] License: Copyright 2013 Harish This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly if ( ! class_exists( 'DOT_MyPluginInfo' ) ) { class DOT_MyPluginInfo { /** * Constructor */ function __construct() { //Hook up to the init action add_action( 'init', array( &$this, 'init_my_plugin_info' ) ); } /** * Runs when the plugin is initialized */ function init_my_plugin_info() { // Register the shortcode [mpi slug='my-plugin-info' field='version'] add_shortcode( 'mpi', array( &$this, 'render_mpi' ) ); } function render_mpi($atts) { // get our variable from $atts extract(shortcode_atts(array( 'slug' => '', //foo is a default value 'field' => '' ), $atts)); /** * Check if slug exists */ if ( ! $slug ) { return false; } /** * Check if field exists * Return value based on the field attribute */ if ( ! $field ) { return false; } else { // Sanitize attributes $slug = sanitize_title( $slug ); $field = sanitize_title( $field ); // Create a empty array with variable name different based on plugin slug $mpi_transient_name = 'mpi' . $slug; /** * Check if transient with the plugin data exists */ $mpi_info = get_transient( $mpi_transient_name ); if ( empty( $mpi_info ) ) { /** * Connect to WordPress.org using plugins_api * About plugins_api - * http://wp.tutsplus.com/tutorials/plugins/communicating-with-the-wordpress-org-plugin-api/ */ require_once( ABSPATH . 'wp-admin/includes/plugin-install.php' ); $mpi_info = plugins_api( 'plugin_information', array( 'slug' => $slug ) ); // Check for errors with the data returned from WordPress.org if ( ! $mpi_info or is_wp_error( $mpi_info ) ) { return false; } // Set a transient with the plugin data // Use Options API with auto update cron job in next version. set_transient( $mpi_transient_name, $mpi_info, 1 * HOUR_IN_SECONDS ); } if ( $field == "downloaded" ) { return $mpi_info->downloaded; } if ( $field == "name" ) { return $mpi_info->name; } if ( $field == "slug" ) { return $mpi_info->slug; } if ( $field == "version" ) { return $mpi_info->version; } if ( $field == "author" ) { return $mpi_info->author; } if ( $field == "author_profile" ) { return $mpi_info->author_profile; } if ( $field == "last_updated" ) { return $mpi_info->last_updated; } if ( $field == "download_link" ) { return $mpi_info->download_link; } } // $field check } // render_mpi() } // end class new DOT_MyPluginInfo(); } ?>
This plugin code is available on GitHub and you can also download it from WordPress.org
Putting It Into Action
Now you can simply go to your post editor and add a shortcode like:
Downloaded [mpi slug='my-plugin-information' field='downloaded'] times.
And it will display:
Downloaded 10 times.
Example Shortcode to Display Other Information About a Plugin
By replacing the value of the "field" attribute you can display different information such as:
- Plugin Name:
[mpi slug='my-plugin-information' field='name']
- Plugin version:
[mpi slug='my-plugin-information' field='version']
- Plugin Slug:
[mpi slug='my-plugin-information' field='slug']
- Plugin Author (returns a name and link):
[mpi slug='my-plugin-information' field='author']
- Author Profile (returns the profile address):
[mpi slug='my-plugin-information' field='author_profile']
- Last Updated:
[mpi slug='my-plugin-information' field='last_updated']
- Download Link:
[mpi slug='my-plugin-information' field='download_link']
Improvements
To keep things simple, I've used transients to save plugin information. Transients however, were never meant to be used for saving important data. An alternative method would be to save plugin data either using the Options API, add_options()
, or as post meta and then schedule a cron task to update the data hourly.
What Next?
Using plugins_api
we have demonstrated how easy it is to communicate and retrieve information of any plugin hosted on WordPress.org.
You might also want to look at other plugins such as Plugin Info (which also uses plugins_api
, and I Make Plugins, to see how they have accomplished the same task.
Comments