How To Code Your Own WordPress ShortCode Plugin Tutorial (Part 2)

WordPress ShortCode 2

Welcome to the second installment in the How To Code Your Own WordPress ShortCode Plugin Tutorial series of articles. This series of articles aims to provide you with the knowledge required to develop a WordPress ShortCode plugin from start to finish. At the end of this series of tutorials you will have a working shortcode plugin that allows you to insert a list of posts matching your criteria into any of your posts. It is aimed at all levels of technical ability but ideally you should be familiar with WordPress and have some basic PHP knowledge. If you have not already read Part 1 of the tutorial (or you need to refresh your memory) you should follow the link in the Related Posts section at the end of the post before continuing.

Choosing The Attributes

Before doing anything further a decision needs to be made on what attributes will need to be specified to meet the objective of returning a list of posts. We could specify many attributes at this stage and this would result in a very flexible plugin and these possibilities will hopefully be discussed in a future part of this tutorial series but to keep things simple we will limit to the following entries.

  • categorylist - a comma separated list of category identifier(s) of the posts that we want listing (string)
  • headingstart - HTML that will be output before the list of posts (html string)
  • headingend - HTML that will be output at the end of the list of posts (html string)
  • liststart - HTML that will be output to start the list of posts (html string)
  • listend - HTML that will be output to finish the list of posts (html string)
  • itemstart - HTML the will be output to indicate the start of an item (html string)
  • itemend - HTML that will be output to indicate the finish of an item (html string)

Using The WordPress Provided Functions

WordPress provides several functions that are generally always used when writing a shortcode plugin.

  • shortcode_atts - this function combines a list of known valid attributes for the shortcode plugin with the list of attributes specified in the post, it will also process any default values and remove any unknown elements.
  • wp_specialchars - this function processes special HTML entities (&, <, >, ", and ') so when output they are correctly encoded for valid HTML - generally speaking when outputting any text it should be sent to this function first. This function avoids double encoding so there is no harm done always using this function (apart from some negligible additional CPU usage).
  • wp_specialchars_decode - this function reverses the actions of the wp_specialchars function. This is an essential function as all string data received from a shortcode specified in a post will be encoded so if attributes are specifying HTML text (like ours) this decode function needs to be used before outputting the value.

Updating The Code

For the purpose of this demonstration the categorylist attributes will be treated as a normal integer value and the plugin will output this number of test items to demonstrate the plugin is picking up values specified in the post. To keep things simple no checking is carried out for no items (for example, the heading is always output regardless of the value of categorylist). For further explanation refer to the individual line commentary below the code snippet.

<?php
/*
Plugin Name: DEMO List Posts
Plugin URI: http://www.reallyeffective.co.uk/knowledge-base
Description: DEMO List Posts
Version: 0.2 Beta
Author: Paul McKnight
Author URI: http://www.reallyeffective.co.uk
*/

/*
DEMO List Posts (WordPress Plugin)
Copyright (C) 2009 Paul McKnight
Contact me at http://www.reallyeffective.co.uk

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 3 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, see <http://www.gnu.org/licenses/>.
*/

//define plugin defaults
DEFINE("DEMOLP_CATEGORYLIST", "");
DEFINE("DEMOLP_HEADINGSTART", "<h4>See Also</h4>");
DEFINE("DEMOLP_HEADINGEND", "");
DEFINE("DEMOLP_LISTSTART", "<ul>");
DEFINE("DEMOLP_LISTEND", "</ul>");
DEFINE("DEMOLP_ITEMSTART", "<li>");
DEFINE("DEMOLP_ITEMEND", "</li>"); 

//tell wordpress to register the demolistposts shortcode
add_shortcode("demo-list-posts", "demolistposts_handler");

function demolistposts_handler($incomingfrompost) {
  //process incoming attributes assigning defaults if required
  $incomingfrompost=shortcode_atts(array(
    "categorylist" => DEMOLP_CATEGORYLIST,
    "headingstart" => DEMOLP_HEADINGSTART,
    "headingend" => DEMOLP_HEADINGEND,
    "liststart" => DEMOLP_LISTSTART,
    "listend" => DEMOLP_LISTEND,
    "itemstart" => DEMOLP_ITEMSTART,
    "itemend" => DEMOLP_ITEMEND
  ), $incomingfrompost);
  //run function that actually does the work of the plugin
  $demolph_output = demolistposts_function($incomingfrompost);
  //send back text to replace shortcode in post
  return $demolph_output;
}

//use wp_specialchars_decode so html is treated as html and not text
//use wp_specialchars when outputting text to ensure it is valid html
function demolistposts_function($incomingfromhandler) {
  //add heading start
  $demolp_output = wp_specialchars_decode($incomingfromhandler["headingstart"]);
  //add list start
  $demolp_output .= wp_specialchars_decode($incomingfromhandler["liststart"]);
  for ($demolp_count = 1; $demolp_count <= $incomingfromhandler["categorylist"]; $demolp_count++) {
    $demolp_output .= wp_specialchars_decode($incomingfromhandler["itemstart"]);
    $demolp_output .= $demolp_count;
    $demolp_output .= " of ";
    $demolp_output .= wp_specialchars($incomingfromhandler["categorylist"]);
    $demolp_output .= wp_specialchars_decode($incomingfromhandler["itemend"]);
  }
  //add list end
  $demolp_output .= wp_specialchars_decode($incomingfromhandler["listend"]);
  //add heading end
  $demolp_output .= wp_specialchars_decode($incomingfromhandler["headingend"]);
  //send back text to calling function
  return $demolp_output;
}
?>

Lines 31-37: Define some PHP constants that will contain the default values of attributes to use in the shortcode if a specific attribute is not specified.

Line 42: Add a parameter to the handler function that WordPress will automatically use to pass an array of the attributes used in the post.

Lines 44-52: Create and initialise an array containing the default values for the shortcode. Use the WordPress provided shortcode_atts function to assign values from the shortcode specific in the post to the appropriate array elements overriding any defaults that have been assigned.

Line 54/61: Send the function that "does the work" the array containing the sanitised list of variables with their values for processing.

Lines 62-78: Build up and return the text that should replace the call to the shortcode in the post. Any attribute that contains HTML text should be output using the wp_specialchars_decode function (so it is processed as HTML instead of it being output as text). Any other text is output using the wp_specialchars function (in this case it is just a number that should never require special processing but for good practice and to get in the routine of always remembering to use this function it is used anyway).

See It In Action

Open the demo-list-posts.php file you created in Part 1 of the tutorial in your choice of text editor and copy and paste the code above. Before changing any posts view your previous test post - you will notice that the default heading value is now displayed instead of the text Hello World!

Edit this previously created test post (or create a new test post for Part 2 of the tutorial) and update the existing [demo-list-posts] entries to include the attributes you require and then publish/preview your post to see the result.

Some suitable examples would be [demo-list-posts categorylist="2"] (use default values for all attributes apart from the categorylist - 2 test items will be output) or [demo-list-posts categoryid="3" liststart="

    " listend="
"] (use default values for all attributes apart from categorylist - 3 test items will be output and specify that an ordered list should be used instead of the default unordered list).

What Next

The plugin now demonstrates how to pass attributes from your posts to the plugin and importantly use them safely (more on this in the next part). The next part in this tutorial will describe how to update the code so the attributes provided at the post level are used to display a list of posts depending on the value of the attributes specified.

When Part 3 is available it will appear in the Navigation and Related Posts section below and be announced on the main page. You can also join the RSS feed using the icon at the top right of each page.

If you have any questions or feedback please contact us via the usual methods.

Screenshots