How To Write a Pepper Plug-in for Mint · 1678 words posted 09/08/2005 10:47 AM

UPDATE: The Pepper API has changed since I wrote this article. Please see Shaun Inman’s Intro to Pepper Development.

One of the coolest things about Shaun Inman’s web stats package Mint is its extensibility API. Mint plug-ins are called “Pepper,” and add features that aren’t in the core installation. There are already four or five plug-ins available, including my plug-in Parsel.

The API isn’t documented yet, but it’s extremely easy to learn by looking at exisiting plug-in examples. Here’s a quick tutorial for writing your own plug-ins.

DISCLAIMER: I was not on the Mint beta and I don’t have any inside information about the Pepper API. Shaun has stated that the Pepper API is not stable. I am not responsible if you follow my instructions and end up with a plug-in that breaks your Mint installation or otherwise diminishes your self esteem. Also, to make the most of this tutorial you need to have a basic understanding of simple PHP and MySQL.

Finally, I strongly recommend that you back up your mint_visit table in your Mint database before trying to write a plug-in. Maybe that’s a good barrier to entry for using this tutorial: if you know enough MySQL to backup a table, you’re probably safe writing your own plug-ins. If not, spend some time learning MySQL and PHP and then come back here.

To follow along, grab the source code for Parsel (currently at version 0.0.8). I’ve added line numbers for reference. You can save the copy locally as class.php and change my code to suit your needs.

Goals for the Plug-in

The default installation of Mint doesn’t track visitors’ browser language settings. We want to accomplish the following tasks:

To get Mint to accomplish those tasks, we need to tell it:

Step by Step through the Plug-in

Pepper plug-ins are a PHP class with a series of functions. You’ll want to give your plug-in its own namespace, in other words, a name that doesn’t clash with a name that another developer might choose. For example, my name space is since1968. At lines 39 and 40, change the $install_plugin and class values to your namespace and the name of your plugin. My namespace and plugin name combined are since1968_Parsel.

Now let’s step through the functions. I’ll put line numbers in parentheses:

function since1968_Parsel()

This function (line 51) is the class constructor. That’s a fancy way of saying that the since1968_Parsel() function connects the plug-in to Mint and sets up basic information about the plug-in. Most of the fields are self-explanatory, but pay attention to the src and class values. The src tells Mint where to look for your plug-in. You’ll want to set up a folder structure like this:

/mint/pepper/yournamespace/yourpluginname

For example, Parsel is in the following folder:

/mint/pepper/since1968/parsel

For the src value, enter yournamespace/yourpluginname

Also, we need to specify which panes will show up in the Mint display. For example, at line 69 we tell Mint to display a pane called “Languages” with tabs called “Most Common” and “Most Recent” (shown to the left).

function install()

This function (line 80) runs when your user installs your plug-in. Mint stores its visitor data in a table called mint_visit, and by default it doesn’t track your visitor’s language. We need to add a field to the mint_visit table, and we do so with an ALTER TABLE command at line 81. Mint doesn’t protect the default fields in the mint_visit table; you want to create a field that won’t accidentally clash with other developers’ plug-ins. For example, I called my field since1968_language, consistent with my namespace.

function uninstall()

This function (line 101) runs when you uninstall your plug-in. Since we’ve added a field to the database during the installation, we need to clean up after ourselves during uninstall. At lines 102-103, we drop the since1968_language field from the mint_visit table.

function onRecord()

This function is fired whenever Mint inserts a new record in the database. We need to accomplish two things in this function:

It’s a good idea to keep this function as light and fast as possible: onRecord() fires EVERY TIME a user visits your site. If you need to clean up data, consider doing so when you pull it out of the database and not when you insert it. This will become clearer in the display functions, below.

Finally, Mint expects onRecord() to return an array every time—even if you’re not actually inserting anything into the database. Thus, at a minimum your onRecord() function should contain:

return array();

If you notice a “blank insert” problem while you’re developing your plug-in, make sure you’re returning an array!

function onJavaScript()

We don’t use this function with Parsel.

function onDisplay()

This function (line 144) sets up the display pane for your plug-in. We want to accomplish two tasks in this function:

The getHTML functions will create the actual output of the pane and return it to the onDisplay() function.

We skip the next four functions, since we don’t use a Widget and we don’t set preferences with the Parsel plug-in.

function getHTML_LanguagesRecent()

Mint displays its data in tables. This function needs to accomplish the following tasks:

Let’s look at each step.

Lines 210-215 set up our table structure: we want a table with column headers called “Languages” and “When.”

Next, we query the database (line 217). For recent languages, we simply grab the language string and the time it was inserted into the database. We order by time descending, and make sure we don’t grab any blank entries.

Assuming we have a result, we loop through the query at line 225. Remember, we only want to output the time and the language.

Lines 235-254 aren’t truly necessary. If we skipped them, our language output would look like es-ar. But that’s not very friendly, is it? Instead, we look up each value in the $since1968_languages array and grab the human-readable language name. es-ar becomes Spanish (Argentina).

Here, we revisit the point I made earlier about doing the heavy lifting when outputting Mint data instead of when inserting it. In one sense, lines 235-254 represent bad coding practice. Why should we clean up output every single time we want to see it? But I think it’s better to slow down Mint marginally by massaging output than to slow down your site by massaging input every time you get a visitor. This might not make a different for low traffic sites but I’m certain the difference would appear under load.

At line 256, we take our cleaned up language name along with the time posted and add it to the $tableData array.

Finally, we call the built-in function generateTable() and pass our $tableData array to it to output the table HTML (line 263).

getHTML_LanguagesCommon()

This function (line 273) works pretty much like getHTML_LanguagesRecent. The only difference is that we want to group the output with our SQL query and show how often each language appears. As with the previous function, we build a $tableData array and pass it to the generateTable() function to output the HTML.

And that’s it! Now you can deploy your plug-in. To do so, create a folder with your namespace in the /mint/pepper folder. Then create a new folder with the name of your plug-in and save the class file there. The full path would be:

/mint/pepper/yournamespace/yourplugin/class.php

Upload the file and use the Mint interface to install the plug-in.

Reiterating Best Practices

Again, two important best practices to consider:

I wrote this Pepper Mint tutorial in quick and dirty fashion, so if something sound uncommonly foolish or wrong please let me know in the comments.

Next week, I’ll post a tutorial for writing plug-ins that use preferences. Happy coding.

* * *


1. On Sep 9, 08:59 AM Scott said:
I hadn’t even looked through the code of a pepper before seeing your tutorial (heck, I read it through once before even looking at your code,) and I feel like I understand the process that you used pretty well. FWIW, I’d say that makes it a pretty well written tutorial. Well done. #

2. On Sep 9, 10:07 AM since1968 said:
Thank you Scott. #

3. On Sep 18, 04:40 PM Chris Ueland said:
Good job Scott! #

4. On Sep 19, 07:36 PM since1968 said:
Scott thanks you. I thank you too. ;-) #