2. The example plugin we are going to build is called Post Products. The goal of this plugin is to create
an easy way to add product data to posts. This plugin will include the following features:
➤ settings page using the Settings API
➤ widget for displaying newest products using the Widget class
➤ post meta box for adding product data to posts
➤ Shortcode support to easily display product data in a post
The first step in creating your plugin is to create your plugin files. For this plugin you’ll have two files:
post-products.php and uninstall.php. Because your plugin contains two files you’ll need to save
these files in a separate folder for your plugin named post-products. Next you need to set up your
plugin header and license.
To start you’ll be working in post-products.php. First you want to define your plugin header as shown
here:
<?php
/*
Plugin Name: Post Products
Plugin URI: http://webdevstudios.com/support/wordpress-plugins/
Description: Easily add product data to posts.
Version: 1. 0
Author: Fred
Author URI: http://webdevstudios.com
*/
/* Copyright 2010 Fred (email : brad@webdevstudios.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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
*/
As you can see you created the appropriate plugin header for your new plugin. Because you will be
releasing this plugin you’ll want to include the GPL software license below your plugin header.
3. Creating a Plugin Example
Next you are going to register all of the Action hooks needed for your plugin to work. It’s generally a
good idea to group all hook calls together. This helps other developers follow the logic of the plugin.
// Call function when plugin is activated
register_activation_hook( _ _FILE_ _,’pp_install’ );
// Action hook to initialize the plugin
add_action(’admin_init’ , ‘pp_init’);
// Action hook to register our option settings
add_action( ‘admin_init’ , ‘pp_register_settings’ );
// Action hook to add the post products menu item
add_action(’admin_menu’ , ‘pp_menu’);
// Action hook to save the meta box data when the post is saved
add_action(’save_post’,’pp_save_meta_box’ );
// Action hook to create the post products shortcode
add_shortcode(’pp’ , ‘pp_shortcode’);
// Action hook to create plugin widget
add_action( ‘widgets_init’ , ‘pp_register_widgets’ );
First you call the register_activation_hook function to set up your default plugin settings. Next
you call the admin_init hook to initialize your plugin, register your settings, and create your plugin
submenu item. You’ll be creating the functions for each Action hook next.
The first function you are going to create is pp_install, which is run when your plugin is activated:
function pp_install( ) {
//setup our default option values
$pp_options_arr=array(
"currency_sign"=>’$’
);
//save our default option values
update_option(’pp_options’ , $pp_options_arr);
}
The pp_install function is used to create your default option values. In this case, you want to set the
default currency sign to the dollar sign. After you’ve created your options array you’ll save the value
using the update_option function. The next function you’ll create is pp_menu as shown in the following
code:
//create the post products sub-menu
function pp_menu( ) {
add_options_page( _ _(’Post Products Settings Page’,’pp-plugin’) ,
_ _(’Post Products Settings’,’pp-plugin’) , ‘administrator’ ,
_ _FILE_ _, ‘pp_settings_page’);
}
As you can see this function is used to create your submenu item. Using the add_options_page function
your Post Products Settings submenu item will be located at the bottom of the Settings menu in
yourDashboard. You also set this menu item to only be viewable by an administrator. The next function
you’ll create is the pp_init:
//create post meta box
4. function pp_init( ) {
// create our custom meta box
add_meta_box(’pp-meta’, _ _(’Post Product Information’,’pp-plugin’) ,
‘pp_meta_box’,’post’,’side’,’default’ );
}
This function is used to create your Post Meta Box. You give your Meta Box a title of ‘‘Post Product
Information.’’ You also set the Meta Box to display in the side just below the Post Tags Meta Box on a
default installation of WordPress. Next you’re going to set up the plugin shortcode:
//create shortcode
function pp_shortcode($atts, $content = null) {
global $post;
extract(shortcode_atts(array(
"show" => ‘ ’
) , $atts));
//load options array
$pp_options = get_option(’pp_options’);
If ($show == ‘sku’ ) {
$pp_show = get_post_meta($post->ID,’pp_sku’,true);
}elseif ($show == ‘price’ ) {
$pp_show = $pp_options[’currency_sign’].
get_post_meta($post->ID,’pp_price’,true) ;
}elseif ($show == ‘weight’ ) {
$pp_show = get_post_meta($post->ID,’pp_weight’,true) ;
}elseif ($show == ‘color’ ) {
$pp_show = get_post_meta($post->ID,’pp_color’,true) ;
}elseif ($show == ‘inventory’ ) {
$pp_show = get_post_meta($post->ID,’pp_inventory’,true) ;
}
return $pp_show;
}
The first thing you do it initialize the global variable $post. This will bring in the $post->ID value for
the post in which you are using the shortcode. Next you extract the shortcode attributes that you’ve
defined, in this case show. Next you load your options array. The plugin settings are covered later in
this section. Finally, you check what attribute value is being sent to the shortcode to determine what
value to show. Using the shortcode like [pp show=price] would display the price of the product.
Next up is creating the Post Meta Box as shown here:
//build post product meta box
function pp_meta_box($post,$box) {
// retrieve our custom meta box values
$pp_sku = get_post_meta($post->ID,’pp_sku’,true) ;
$pp_price = get_post_meta($post->ID,’pp_price’,true); $pp_weight = get_post_meta($post-
>ID,’pp_weight’,true) ;
$pp_color = get_post_meta($post->ID,’pp_color’,true) ;
6. echo ‘ </table>’;
}
Your Post Product plugin saves five different product values on every post: sku, price, weight, color,
and inventory. As you can see the first step is to load these five custom field values. Next you displaythe
Meta Box form and fill in the current values if any exist. Below the Meta Box form you display a
simple shortcode legend to show the user what shortcode options are available
Now that you’ve created your custom Meta Box you need to save the data entered in the form as shown in
the following code:
//save meta box data
function pp_save_meta_box($post_id,$post) {
// if post is a revision skip saving our meta box data
if($post->post_type == ‘revision’ ) { return; }
// process form data if $_POST is set
if(isset($_POST[’pp_sku’] ) && $_POST[’pp_sku’ ] ! = ‘’ ) {
// save the meta box data as post meta using the post ID as a unique prefix
update_post_meta($post_id,’pp_sku’ , esc_attr($_POST[’pp_sku’])) ;
update_post_meta($post_id,’pp_price’ , esc_attr($_POST[’pp_price’])) ;
update_post_meta($post_id,’pp_weight’ , esc_attr($_POST[’pp_weight’])) ;
update_post_meta($post_id,’pp_color’ , esc_attr($_POST[’pp_color’])) ;
update_post_meta($post_id,’pp_inventory’,esc_attr($_POST[’pp_inventory’]));
}
}
First you verify that the post being saved is not a revision. Next you check that the post field pp_sku
exists and is not blank. The only required field is the product sku, so if this field is blank the post will
not be treated as a product and product data will not be saved. After you have verified that a sku exists
you save your custom product fields as post meta for the post you are creating.
Next up you are going to create your latest products widget:
//register our widget
function pp_register_widgets( ) {
register_widget( ‘pp_widget’ ) ;
}
//pp_widget class
class pp_widget extends WP_Widget {
First you have to register your widget as pp_widget. Next you extend the Widget class as pp_widget.
Now you need to create the four widget functions needed to build your widget:
//process our new widget
function pp_widget( ) {
$widget_ops = array(’classname’ => ‘pp_widget’ ,
’description’ => _ _(’Display Post Products’,’pp-plugin’ ) );
$this->WP_Widget(’pp_widget’ , _ _(’Post Products Widget’,’pp-plugin’) ,
$widget_ops);
}
The first function you create is the pp_widget function, also known as the constructor.
7. Here you set the widget title, description, and class name for your custom widget.
//build our widget settings form
function form($instance) {
$defaults = array( ‘title’ => _ _(’Products’,’pp-plugin’) ,
’number_products’ => ‘ ’ );
$instance = wp_parse_args( (array) $instance, $defaults ) ;
$title = strip_tags($instance[’title’]) ;
$number_products = strip_tags($instance[’number_products’ ] ) ;
?>
<p>
<?php _e(’Title’ , ‘pp-plugin’ ) ?>:
<input class="widefat" name=" <?php echo $this->get_field_name(’title’) ; ?>"
type="text" value=" <?php echo esc_attr($title) ; ?>" />
</p>
<p>
<?php _e(’Number of Products’ , ‘pp-plugin’ ) ?>:
<input name=" <?php echo $this->get_field_name(’number_products’) ; ?>"
type="text" value=" <?php echo esc_attr($number_products) ; ?>" size="2"
maxlength="2" />
</p>
<?php
}
The second function you define is the form function. This builds the form for saving your widget
settings. You are saving two settings in your widget: the widget title and the number of products to
display. First you define the setting defaults if no settings have been saved. Next you load in the saved
values for your two settings.
Finally, you display both setting form fields with the setting values if they exist.
//save our widget settings
function update($new_instance, $old_instance) {
$instance = $old_instance;
$instance[’title’ ] = strip_tags(esc_attr($new_instance[’title’])) ;
$instance[’number_products’ ] = intval($new_instance[’number_products’ ] );
return $instance;
}
The next function you create is the update function. This function saves your widget settings. Notice
how you utilize the strip_tags and esc_attr functions to sanitize your widget title. You also use the
PHP intval function to verify the number of products value is an integer.
//display our widget
function widget($args, $instance) {
global $post;
extract($args);
echo $before_widget;
$title = apply_filters(’widget_title’ , $instance[’title’ ] ) ;
$number_products = empty($instance[’number_products’] ) ?
’ ’ : apply_filters(’widget_number_products’ , $instance[’number_products’]);
if ( !empty( $title ) ) { echo $before_title . $title . $after_title; };
8. $dispProducts = new WP_Query() ;
$dispProducts->query(’meta_key=pp_sku&showposts=’.$number_products) ;
while ($dispProducts->have_posts() ) : $dispProducts->the_post();
//load options array
$pp_options = get_option(’pp_options’);
//load custom meta values
$pp_price = get_post_meta($post->ID,’pp_price’,true) ;
$pp_inventory = get_post_meta($post->ID,’pp_inventory’,true) ;
?><p><a href=" <?php the_permalink( ) ?>" rel="bookmark"
title=" <?php the_title_attribute() ; ?> Product Information" >
<?php the_title() ; ?></a></p><?php
echo ‘<p>’ . _ _(’Price’ , ‘pp-plugin’) . ‘ : ‘
.$pp_options[’currency_sign’].$pp_price .’ </p>’;
//check if Show Inventory option is enabled
If ($pp_options[’show_inventory’] ) {
echo ‘<p>’ . _ _(’Stock’ , ‘pp-plugin’) . ‘ : ‘ .$pp_inventory .’ </p>’ ;
}
echo ‘<hr />’;
endwhile;
echo $after_widget;
}
}
The final function defined is the widget function. This function displays your widget on the public side
of your web site. First you initialize the global $post variable and extract the $args for the widget.
Next you display the $before_widget variable. This variable can be set by theme and plugin developers
to display specified content before and after the plugin. Next you retrieve your two setting values. If the
$title value is not empty you use it, but if it is you’ll use the default title you defined earlier.
To display the products in your widget you are creating a custom Loop using WP_Query.
Remember, because this is not your main Loop you’ll want to use WP_Query to create your custom Loop
instead of query_posts. To define your custom Loop you pass in two parameters: one for the post meta
value and one for number of products to display. The first value (meta_key=pp_sku) tells your custom
Loop to only return posts that have this custom meta value set. The second value, showposts, determines
how many post products to display. This number is pulled from the widget options value set by the user.
Next you load your option values and the custom meta values you will be displaying in your widget.
Finally you display your post product values in the widget. If the option Show Inventory is enabled the
inventory value will be displayed.
The final part to your custom plugin is creating the plugin settings page:
function pp_register_settings( ) {
//register our array of settings
register_setting( ‘pp-settings-group’ , ‘pp_options’ );
}
function pp_settings_page( ) {
//load our options array
9. $pp_options = get_option(’pp_options’);
// if the show inventory option exists the checkbox needs to be checked
If ($pp_options[’show_inventory’] ) {
$checked = ‘ checked="checked" ‘ ;
}
$pp_currency = $pp_options[’currency_sign’] ;
?>
<div class="wrap" >
<h2><?php _e(’Post Products Options’ , ‘pp-plugin’ ) ?></h2>
<form method="post" action="options.php" >
<?php settings_fields( ‘pp-settings-group’ ) ; ?>
<table class="form-table">
<tr valign="top" >
<th scope="row" ><?php _e(’Show Product Inventory’ , ‘pp-plugin’ ) ?></th>
<td><input type="checkbox" name="pp_options[show_inventory] "
<?php echo $checked; ?> /></td>
</tr>
<tr valign="top" >
<th scope="row" ><?php _e(’Currency Sign’ , ‘pp-plugin’ ) ?></th>
<td><input type="text" name="pp_options[currency_sign] " value="
<?php echo $pp_currency; ?>" size="1" maxlength="1" /></td>
</tr>
</table>
<p class="submit" >
<input type="submit" class="button-primary" value="
<?php _e(’Save Changes’ , ‘pp-plugin’ ) ?>" />
</p>
</form>
</div>
<?php
}
?>
The first function is used to register your plugin settings. In this example you are saving all of your
setting values in an array so you need only one setting to be registered: pp_options. Next you create
the function to display your settings page called pp_settings_page.
First you load your plugin options array value. Next you check if the show inventory option should
be CHECKED. You also load in the current currency value into a variable for display. Next you display
your settings page form with both option form fields listed. Notice you are using the settings_fields
function to link your settings form to your registered setting you defined. You also set the name
for your form fields to your options array name with the unique option name in brackets like
pp_options[’show_inventory’ ] . This is the proper way to save your setting options in an array using
the Settings API. When the form is submitted WordPress will use the Settings API to sanitize the form
values and save them in the database.
10. The final step to your Post Products plugin is to create your uninstall.php file:
<?php
// If uninstall/delete not called from WordPress then exit
if( ! defined( ‘ABSPATH’ ) && ! defined( ‘WP_UNINSTALL_PLUGIN’ ) )
exit ();
// Delete options array from options table
delete_option( ‘pp_options’ ) ;
?>
The first thing you check is that ABSPATH and WP_UNINSTALL_PLUGIN constants exist. This means
they were called from WordPress and adds a layer of security on the uninstaller. After you have verified
the request is valid you delete your single option value from the database. You could also define other
uninstall functionality here if needed such as removing every product post meta value you saved in the
database.
That’s it! You just successfully built an entire plugin that includes many of the features covered in this
chapter. This is a fairly basic plugin but should give you the examples and tools needed to expand
upon.
Complete source code
<?php
/*
Plugin Name: Post Products
Plugin URI: http://webdevstudios.com/support/wordpress-plugins/
Description: Easily add product data to posts.
Version: 1. 0
Author: O.A
Author URI: http://oa.com
*/
/* Copyright 2010 Fred (email : brad@webdevstudios.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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.
*/
// Call function when plugin is activated
register_activation_hook( _ _FILE_ _,’pp_install’ );
// Action hook to initialize the plugin
add_action(’admin_init’ , ‘pp_init’);
// Action hook to register our option settings
add_action( ‘admin_init’ , ‘pp_register_settings’ );
11. // Action hook to add the post products menu item
add_action(’admin_menu’ , ‘pp_menu’);
// Action hook to save the meta box data when the post is saved
add_action(’save_post’,’pp_save_meta_box’);
// Action hook to create the post products shortcode
add_shortcode(’pp’ , ‘pp_shortcode’);
// Action hook to create plugin widget
add_action( ‘widgets_init’ , ‘pp_register_widgets’ ) ;
function pp_install( ) {
//setup our default option values
$pp_options_arr=array(
"currency_sign"=>’$’
);
//save our default option values
update_option(’pp_options’ , $pp_options_arr);
}
//create the post products sub-menu
function pp_menu( ) {
add_options_page( _ _(’Post Products Settings Page’,’pp-plugin’) ,
_ _(’Post Products Settings’,’pp-plugin’) , ‘administrator’ , _ _FILE_ _,
’pp_settings_page’) ;
}
//create post meta box
function pp_init( ) {
// create our custom meta box
add_meta_box(’pp-meta’, _ _(’Post Product Information’,’pp-plugin’),
‘pp_meta_box’,’post’,’side’,’default’) ;
}
//create shortcode
function pp_shortcode($atts, $content = null) {
global $post;
extract(shortcode_atts(array(
"show" => ‘ ’
) , $atts));
//load options array
$pp_options = get_option(’pp_options’);
If ($show == ‘sku’ ) {
$pp_show = get_post_meta($post->ID,’pp_sku’,true);
}elseif ($show == ‘price’ ) {
$pp_show = $pp_options[’currency_sign’] .
get_post_meta($post->ID,’pp_price’,true);
}elseif ($show == ‘weight’ ) {
$pp_show = get_post_meta($post->ID,’pp_weight’,true);
}elseif ($show == ‘color’ ) {