Ron’s Beer Report Plugin – Getting something to work

Yesterday I talked about WHY I want to create a plugin. Today I’ll talk about the first thing I did – get something (anything, really) to work.

I said yesterday that it was hard to get the formatting the way I wanted it to be UNLESS I used HTML mode AND typed all the formatting stuff by hand. Actually, I think I used a more colloquial term – I’ll quote:

it’s a pain in the ass

These beer reports follow a template (maybe that would be a better idea than the plugin I’m thinking about now, I can make it a template – we’ll come back to that in the future, let’s make this stuff work first). This template comprises some introductory text followed by some number of parts of the dinner and concludes with a summary. The parts of the dinner all look similar, somewhat like this:

Part name:  Grade 

Beer: a Food: b

Beer pic Food pic

paragraph describing beer

paragraph describing food

paragraph describing combination

Some parts of the dinner aren’t beer & food pairings, but they also have grades. So I figured that I’d start with that grade part. It looks pretty self-contained, and I think I have an idea about what I want to page text to look like.

The first problem is WHAT should I implement. That involves looking at WHAT I do now and deciding WHAT I want to do in the future – software people sometimes call this “The Requirements”

The HTML/CSS code that implements the grade above is:

<strong>Part name: <em><span style="color: #339966; background: yellow;">&nbsp;Grade&nbsp;</span></em></strong>

Yeah, it’s a little ugly behind the scenes, isn’t it. This is what I think it could be like this:

[course name="Part name" grade="Grade"]

It could also be like this:

[course "Part name" "Grade"]

Both of those are better than the “what I do now” example – they’re simple and direct. They also allow me to easily change the formatting of EVERY grade without having to edit every one of them individually (in the HTML editor – did I mention that part yet?). The first example uses named parameters (the one named “name” has the name) and the second uses positional parameters (the first one is the name).

The [ and ] identify a WordPress concept called “shortcode.” A shortcode is a customizable special content/format tag that lets a plugin define how to turn its information into formatted text / images to present on the screen. There’s a WordPress API for telling WordPress that a shortcode exists (not surpringly called the “Shortcode API“). I’ll have to use that to make the course shortcode work.

The first one seems more direct and robust, so we’ll do that one first. Both will get done, but something has to be first. (Note also that the trailing _ in the examples is there only as a hack so that once I have the plugin implemented it won’t reformat my examples!)

The next problem is WHERE do I implement that shortcode. The Shortcode API describes how to use the API to create a shortcode, but it doesn’t really say where to put the code that uses the Shortcode API. That entails looking at some other WordPress documentation – this time related to plugins.

Fortunately, the WordPress community has provided some useful documentation on writing a plugin. It’s really easy to write enough stuff to have a plugin that does nothing, and that looks like a good place to put the shortcode API code.

Here’s the start of the Ron’s Beer Report Plugin plugin file:

Plugin Name: Ron's Beer Report plugin
Plugin URI:
Description: Write reports like Ron's beer dinner reports
Version: 0.1
Author: Ron Crocker
Author URI:
License: GPL2
/*  Copyright 2010  Ron Crocker  (email : ron at roncrocker dot com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2, 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
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

Now I just have to get the shortcode function plugged in there, upload the file to my blog, and it just works.

Now we know WHAT and some idea of HOW/WHERE, so the only thing left to do is actually make it work. Before I do that, I want some examples and test cases to make sure it works like I want it to. Let’s get those set up first. Here’s the ones I used.

[course] No parameters at all. Just make sure it’s working even a little bit.

<strong>NoName: <em><span style="color: #339966; background: yellow;">&nbsp;INCOMPLETE&nbsp;</span></em></strong>


[course name=”Part name” grade=”Grade”] Baseline example from above. We know what that should look like

<strong>Part name: <em><span style="color: #339966; background: yellow;">&nbsp;Grade&nbsp;</span></em></strong>

Part name:  Grade 

[course grade=”Grade” name=”Part name”] Swap parameter order – shouldn’t matter

<strong>Part name: <em><span style="color: #339966; background: yellow;">&nbsp;Grade&nbsp;</span></em></strong>

Part name:  Grade 

[course name=”Part name”] Only name parameter – use that course name and default grade

<strong>Part name: <em><span style="color: #339966; background: yellow;">&nbsp;INCOMPLETE&nbsp;</span></em></strong>

Part name:  INCOMPLETE 

[course grade=”Grade”] Only grade parameter – use that grade and default course name

<strong>No name: <em><span style="color: #339966; background: yellow;">&nbsp;Grade&nbsp;</span></em></strong>

NoName:  Grade 

[course grade=”Grade1″ grade=”Grade2″] Two grade parameters – use only the last one

<strong>No name: <em><span style="color: #339966; background: yellow;">&nbsp;Grade2&nbsp;</span></em></strong>

NoName:  Grade2 

I tried a bunch of different code to finally get it plugged in, and here’s what that looks like:

if (!function_exists('rbrp_shortcode_course')) {
    function rbrp_shortcode_course($atts) {
        $retval = '';
        $retval = $retval . "$name: ";
        $grade_str = "&nbsp;$grade&nbsp;";
        $grade_str = '<span style="color: #339966; background: yellow;">' .
            "$grade_str" . '';
        $retval = $retval . "<em>$grade_str</em>";
        $retval = '' . $retval . '';
        return $retval;
What the heck is all of that? I’ll hit the highlights:
  • Because I can’t really be sure that the plugin is only called the one time, I have to make sure that the functions are only defined once. To do that, I guard them with the test. Yes, that’s a scar – I had a problem during trying to figure out if it was working or not where somehow one of the functions was already defined when I tried to defined it the second time an error was triggered. I started looking at examples (another rule from eclipse – Monkey See, Monkey Do) and saw this pattern ALL OVER THE PLACE. That’s a hint – this is a good practice.
  • The functions start with “rbrp_” to denote that they belong to the Ron’s Beer Report Plugin. This is a way to ensure that there are no name conflicts.
  • I probably should create a style for the specific format strings, but for now I’m brute-forcing it.
  • A whole bunch of syntax errors and corner cases were discovered during development, most of which was dealt with by simplifying the code.
  • I like the “building a shipment to return” model of starting with an empty string and populating it – the first thing put into the return value is the course name, then the grade is built (with the coloring and spaces), wrapped with the emphasis tag, and the whole thing is made bold. Then that got returned.

Adding these two parts (header and code) together creates a complete plugin. Ron’s Beer Report Plugin, version 0.1 complete. You can get it here. The coloring and formatting of any course tags above come from that plugin (because I’ve installed it here).

So now I have a complete plugin that does something, but not enough to make it easy enough to use the visual editor for the entire post – all the rest of the stuff still needs help. That’s coming…

Leave a Reply