Building an Object-Oriented WordPress Plugin (xkcd-shortcode) – Part 3

This is Part 3 of a Tutorial Series on building an Object-Oriented WordPress plugin from scratch.

Series Navigation:

  1. Design
  2. Making Remote Requests
  3. Generating HTML
  4. Connecting to WordPress’s Shortcode API
  5. Implementing Caching

In Part 2 you made great progress by building the XKCDLoader class. Now you are going to use this object in the XKCDShortcode class and build HTML markup for the [xkcd] shortcode.

Getting Started

Your design from Part 1 called for a render method that will be wired to WordPress’s add_shortcode callback. WordPress gives you an associative array containing the parameters that the user entered. Your goal is to use these attributes and generate HTML that contains an img tag for a specific comic.

By now you will have gotten good at resisting the temptation of writing a bloated function! Instead here’s an outline of the render method.

function render($params) {
  /* if user didn't specify num, use `null` to imply latest comic */

  /* load the metadata for this comic */

  /* show errors if comic was invalid or loading failed */

  /* generate html and return it */

Mapping this to helper methods you get a sequence diagram like this.


Saving a Loader

First let’s get some initialization out of the way. You need an instance of your XKCDLoader to do the loading of the metadata. All [xkcd] shortcodes can use the same loader object, so it is a good idea to create it in the constructor.

function __construct() {
  $this->loader = new XKCDLoader();

Setting Up Defaults

When the user inputs [xkcd] without a num attribute you need to show the latest comic. This can be kept in a $defaults variable of the class. Since you have already implemented the loader to accept null to imply the current comic, null will be that default value.

public $defaults = array(
  "num" => null

Parsing User Input

WordPress provides a handy API function shortcode_atts. It merges a shortcode’s defaults and user input into an associative array that you can use as is. All you need to do is call it in your parse function.

function parse($params) {
  return shortcode_atts($this->defaults, $params);

Loading an XKCD comic

You will do the actual loading for the comic in the load helper that uses the local XKCDLoader instance.

function load($xkcd_num) {
  return $this->loader->load($xkcd_num);

Rendering HTML

The XKCDLoader returns an object that contains the metadata for a specific comic. You need to lookup the relevant keys from this object and build an img tag from it. To link back to the comic the img tag must be wrapped in an anchor linking to it’s main page.

  function renderJSON($json) {
    $src = $json->img;
    $href = '' . $json->num;

    // alt in html => title in json
    $alt = $json->title;

    // title in html => alt in json
    $title = $json->alt;

    $html = <<

    return $html;

Note the use of PHP heredocs strings like a microtemplate. The additional CSS classes help users target these tags and change there styling.

Back to XKCDShortcode#render

Using the earlier sequence diagram as a guide you can now bring the helpers together in the render method.

function render($params) {
  try {
    $params   = $this->parse($params);
    $xkcd_num = $params['num'];
    $json     = $this->load($xkcd_num);

    return $this->renderJSON($json);
  } catch (Exception $e) {
    $message = $e->getMessage();
    if (preg_match('/404/', $message)) {
      $message = 'Unknown XKCD Comic: ' . $xkcd_num;

    return '

' . $message . '

'; } }

Any errors from the XKCDLoader are trapped here. Further a 404 error is modified into a more user friendly error message. The Error messages themselves are wrapped in a paragraph with some CSS for styling.

Using XKCDShortcode

You now have an object that takes some attributes about a specific XKCD comic and generates suitable HTML markup for it. When using it you can ignore all it’s internals, even that it uses an XKCDLoader.

$shortcode = new XKCDShortcode();
$html = $shortcode->render(
  array('num' => 5)

Moving On

Another major part of the plugin is now ready, and you are nearly at the finish line! Next you will build the XKCDShortcodePlugin object that connects your plugin with the WordPress plugin API.

Stay tuned for Part 4.

Level Up your WordPress-Fu with Weekly Tips in your inbox. Find out just why query_posts() is evil and why you should stop using it. (No Spam)