WordPress plugins – reStructure

By using a unified naming convention you know where the class you need is declared, to be able to load it into your code. The mind forgets easy, and you want to focus on solving your programmatical problems instead of trying to remember where you put your six weeks old myURLHelper class.

This is a follow up on my last post about the directory structure of WordPress plugins. Previously I grouped the PHP files in directories based on functionality, such as “admin”, “js” and “widget”. Now it’s time to refactor this. This does not apply only to WordPress plugins, but to all software development.

When using a programming language, it’s not a bad idea to follow some of the best practices that already exists. PEAR is a large PHP project repository. Most of the up-to-date packages there follow strict directory and file structures along with a set of coding standards. The classes use namespace alike names where each nested namespace is separated with an underscore. These classes are then placed in files named after the last part of the class name, in a directory hierarchy where each directory is named after each part of the namespace.

As an example, the class “Datafeel_Util_URL” is defined in the file “URL.php” under the directories “Datafeel/Util”.

If you have multiple projects that requires the same functionality, you keep all your files and directories under a single path, which you add to the PHP include path configuration parameter. If you create a PEAR package of your project, you can install it globally on your system, and PHP will most likely be able to find your files without changing the include path. Please note that setting up and creating PEAR packages can take some time if you haven’t done it before. Unless you have special needs, such as releasing the project on PEAR, you can happily change the include path and you are good to go.

I have been working on functionality for two WordPress sites lately, and those two sites require some of the same functionality. I started out by just copying the code from the first project to the second, but then all the hard work begins. I decide to rewrite the configuration handler, then add a new web service and fix some bugs related to file uploads. I think it’s hard to keep the plugins from the two projects in sync. Imagine if I had three projects, or ten…

WordPress plugins – Directory Structure

When you develop a plugin for WordPress that continuously grows with new functionality it can become very large with an unmanageable amount of files in the plugin directory. The files can grow that large that it becomes almost impossible to understand the flow and integrity of the code. This will also affect the gain of WordPress. One example is the plugin administration page that searches through all PHP files in all the subdirectories one level below the plugin directory for files with a valid plugin header.

This document contains some thoughts about a well structured plugin directory to speed up you plugin and keep the code for all the functionality in a maintainable structure.

If you only store one PHP file in the main directory of you plugin, a file we can call the “loader”, we might increase the gain a little. The only task of this file is to load the rest of the files in the plugin. This loader will load a controller that we name the “core”. The controllers tasks are, among others, to set up action and filter hooks to integrate into WordPress and other plugins and to control the flow of data inside the plugin.

The most important reason to arrange the files is to get a better overview. One way to do this is to make use of subdirectories based on functionality and file types. You could place all your Javascript files inside a “js” directory and your CSS files inside a “css” directory. If your plugin has a administration interface those files could be placed in a directory called “admin”, likewise could widget related files be located inside a “widget” directory. Keeping a structure like this demands a little extra code and will give you more files to keep in mind, but in return you’ll never see your files grow into huge monsters of several thousands lines. Files growing out of control can easily become a problem, which I have experienced myself when developing WordPress plugins.

An example with a directory structure for a plugin of a pretty large size:

my_plugin_loader.php
/actions/controller.php
/actions/widget.ajax.php
/admin/options.php
/core/my_plugin.php
/css/admin.options.css
/css/widget-css.php
/js/script-loader.php
/js/some_lib.js
/js/widget-js.php
/languages/my_plugin-nb_NO.po
/languages/my_plugin-nb_NO.mo
/widget/widget.control.php
/widget/widget.php

I have used some suitable file names. It is not necessary to specify the directory name as a part of the file name, as I have done for some of the files above, but you might want it if your editor only shows you the name of the file. I use Eclipse for development which only shows me the name of the file. That makes it harder to separate different files with the same name from each other.

In my example I have a file named “script-loader.php” which is used to load Javascript files. WordPress contains functionality to register scripts with a name, URL and dependencies. It is also possible to specify the version of the script, which becomes a part of the URL. This is useful to force browsers to downlad the new script file instead of using a cached one.

You might want to make directly calls on functionality in your plugin, not from a file in another plugin or a file in the selected theme, but maybe to load some data with a Javascript, execute an update or print a CSS or Javascript file requested by the browser. You need a front controller to handle these requests.

I use PHP5 and an object oriented structure when I develop plugins for WordPress, but the thoughts and suggestions in this article might be used perfectly with a structural, non object oriented, methodology. There are many pourly written plugins for WordPress, hacked together to give only the functionality needed at the given time. This makes it harder to maintain the plugin later when new requires show up and makes the integration with other plugins or newer versions of WordPress to a nighmare. Those plugins are then used as a base for other peoples plugins with the famous copy and paste method. I believe that better documentation with good examples can increase the code quality for plugins.

This is a translation of my norwegian blog post.

Configuring Linksys WRT54GL for a larger network

I have a passion for computer networks and configuring of network equipment and services. At home, both at my parents house and in my appartment, I have set up networks suitable for medium to large corporations. I run my own servers for DNS, DHCP, Web, Mail, printer and file sharing, databases and central authentication for wireless users.

I just bought a Linksys WRT54GL v1.1 wireless router that I will set up at my parents neighbors house, where my grandmother lives. My sister just moved in there and want Internet connection.

I have stretched CAT-6 Ethernet cable between the houses to give a stable network connection. This is a danger for data equipment in cases of lightning and other power faults. Therefore I bought an UPS from APC with surge protection for both power and network cables. I also saw the possibility to put up wireless network there, which is great to have when we are visiting my grandmothers house, for example at Christmas. Oh, yes, I am adicted to Internet.

System information about the routerOne of the first things I did with the new router was to install OpenWRT WhiteRussian, as an alternative firmware to the ones from Linksys. I found this firmware somehow featureless and thought of going back to Linksys firmware. Luckily I found DD-WRT which is based on the core of OpenWRT. This firmware had most of the features I was could think of, so I decided to go for this one, version 23 SP2.

Setup of IP addresses and DHCPI wanted a configuration where the router could send packets back and forth between the interfaces on the router, not only work as a NAT enabled Internet gateway. I am not very often home at my parents, because I live in Drammen, so I have to be able to remotely control those computers behind the router if anything should fail. I changed the DHCP service on the router to forward DHCP requests to my FreeBSD router in the house of my parents. The FreeBSD router runs a DHCP service, and that way I will have a centralized configuration point for IP addresses on my network. I configured a new /24 subnet in my DHCP service to be used on the router in the house next door.

Deactivated the SPI firewallDD-WRT has per default an active SPI firewall that filters all packets from the WAN interface that tries to establish a connection to computers behind the router. I had to deactivate this firewall to let the router pass DHCP response packets back from my DHCP service to the clients. I configured a static route on my main router at my parents house for the new /24 subnet to be routed via the WAN interface on the Linksys router.

It is important that the Linksys router receives a static IP address on the first subnet, the one at my parents house, because that is necessary to keep the static routing stable over time. I did this by configuring the DHCP server to give the Linksys router a static IP address.

This is a translation of my norwegian blog post over at http://www.hoven.ws/.

WordPress plugins – Front Controller

WordPress supports extensions through plugins. Plugins integrate into the core of WordPress with hooks. These hooks are executed at places in the WordPress code. An example of this is when a web page of posts is displayed, when a user is created or when a post is deleted.

There is an action hook that is called “init” that is executed the moment before the theme gets loaded and posts gets presented. When this hook is executed all plugins are loaded and options from the database are retrieved from the database, and therefore is this hook very suitable for what I am about to show you here.

I often need to call functions available from my plugin from a JavaScript, also known as Ajax, or from an HTML form. As an example I will describe how to create a filter that lets the user use a filter, such that only posts that matches this filter will be shown. I have written a plugin that makes use of this technique. The plugin is not publicly available, but I will show you how it can be done.

This filter sets a cookie in the users web browser. The user will then have the filter active until the users changes to some other filter. I will show you two examples, first where I use a regular HTML link to change to a different filter, then I will show you how Ajax can be used to retrieve a list of available filters. Filters can be placed in levels relative to each other, where a filter will have a parent filter. Think of it as categories in WordPress.

The link to change a filter can look something like this:

<a href="http://example.com/?myplugin=set&filter=sport">Sport</a>

When i click on this link I need my plugin to check for those parameters I send. In my examples I call my plugin for “myplugin”, although thats not the real name of it, but then again it’s only an example ;) . In the URL in the example above I have used the code word “myplugin”, the same as the name of the plugin. This is to reduce the possibility of name collisions with other plugins. In the PHP code of the plugin I have connected a function to the “init” hook that checks if the code word has been given as a parameter. It will then look for a suitable action to execute based on the value of the code word.

The following example shows the PHP code that accepts both a request to set a filter and to return a list of all filters that has a certain parent. If the first test matches a filter gets set and WordPress continues to load the page. In the second test you can see that the script dies the moment after it prints the list of requested filters. That is actually desired because we are going to make an asynchronous JavaScript call to this function that will want only this list, not a normal WordPress page. With the JavaScript call we are not going to reload the page, but only update a small part of the page, whether it is a <select> list, a list of checkbox’ or some other action decided by the JavaScript.



$myplugin = new MyPlugin();

add_action('init', array(&$myplugin, 'check_action'));

//

// The main class of the plugin

class MyPlugin {

    function check_action() {

        $action = _REQUEST['myplugin'];

        switch($action) {

            case 'set':

                $this->set_filter($_REQUEST['filter']);

                break;

            case 'list':

                $list = $this->get_list($_REQUEST['parent']);

                echo $list;

                exit;

        }

    }

    // Set a new filter

    function set_filter($filter = '') {

        // use setcookie to set the filter in the web browsers cookie

    }

    // Returns a list of filters with a given parent

    function get_list($parent = '') {

        // lookup all the filters with the parent given as a parameter

    }

}

I will not go into details of how JavaScript can be used to make asynchronous calls. It would be too big and too many details to dig into in this article. There are many good resources on the Internet about Ajax, and Google knows about most of them. It can be a good thing to check out Cross-Browser XMLHttpRequest that makes it a lot easier to use Ajax without all the pain of different techniques and implementations between web browsers. Prototype and jQuery are two very powerful JavaScript libraries that are worth to have a look at as well. Beware that those two are per default not compatible with each other, use either Prototype or jQuery if you are not already familiar with them.

This article is a translation of my norwegian article from march 8.

A new category structure in WordPress

The proposal

I personally don’t like the way wordpress presents categories, with URLs such as “http://example.tld/category/some-category”, and especially not the possiblity to put a post inside several categories. That’s a job for tags. Therefore I suggests a new category structure where we use a page as the parent (or category) of posts.

URL hierarchy

Pages gets a URL like “http://example.tld/my-page”. By using a page as the category of our post we can have a URL like “http://example.tld/my-page/my-post” or “http://example.tld/my-page/2007/04/14/my-post” for our posts. As a bonus the “category” page would work as SEO Siloing.

New page template

This would also bring up the need for a new page template similar to the archive template, where the latest posts inside the category/page can be displayed together with the content of the page. An example would be that the five last posts in that category/page could be listed beneath the page content. This would replace the category templates where the file name of the template files ends with the ID of the category, such as “category-14.php”, which is much harder to maintain on a page with many categories.

Post templates

With this solution the posts will have only one category, the page it was assigned. That way it is possible to have post templates based on the nicename of the page. This will solve the problem that I have today when I need different layout of my posts based on which category it belongs to.

Default page for posts

The default category for posts will then (of course) be the front page, and a post on the front page will get a URL as “http://example.tld/my-post”.

Database structure

Posts and pages uses the same database table ($wpdb->prefix . ‘posts’) and we then need a link between a post and a page to make this relation possible. My purpose would be to create a new table ($wpdb->prefix . ‘post2page’) to handle the relation between posts and pages where we will have two columns, one primary key that would be the “post_id” and the other would be the “page_id”, both referring to the same posts table and the column “ID”. This is because I want to leave the posts table as is and as well making it easier to extend this relation later on.

Category management

There would then be no need for the categories as we know it from todays WordPress. Tags, that will come with the WordPress 2.2 release, will be able to replace the functionality of adding a post to multiple categories.

I wrote this as a ticket on WordPress Trac.

Update: 15.04.2007

A category can have subcategories to make up a hierarchy, but pages can also be ordered like that. A page can be a subpage of another page.

It might be desirable to have pages that are not behaving as a category for posts. This functionality can be achieved by adding a checkbox to control this the same way comments and pings can be turned on and off on a page. Alternatively the author of the page can select a template that doesn’t display any posts related with the page.

There are users that insist on placing a post inside several categories. A solution to this will then be to allow for multiple posts-to-pages associations by using a combined primary key in the post2page table over both the “post_id” and “page_id” columns.

Update 15.04.2007 (2)

I know it is a bit radical thinking and a big change to WordPress by doing this, but you might want to write posts that are related to your page. For example if you write a page with information about WordPress and your plugin development, then you probably want to publish your new plugins as posts, not as subpages of the WordPress page. The exception from this is pages such as “about”, “legal” and so on, but with the ability to disable posting to those certain pages (see above) this makes it possible.

It was just a suggestion to improve WordPress. It is not a specific issue I’m having any longer, since I managed to give posts in different categories the diffent look I needed by placing both the logic and the view/html inside a plugin. A bad solution, I know, but it works. I didn’t want too much logic in the theme files that are dependent on some plugin. The different looks I needed was not only when displaying the posts on the category page, but also when using the “single” template.

Welcome

Welcome to Datafeel.

My name is Knut-Olav Hoven and I am a software developer at a company named Linpro. You can find my (more) personal web site at http://www.hoven.ws.

Datafeel is my own registered company with zero income and zero expenses. I actually wonder why I registered it, I guess I just thought “Datafeel” was a nite name for a company :-) .

I recently found a good use for this web site, to use it as a base for my software and techniques I want to share with the rest of the world. To begin with I started to write some information about WordPress and will be sharing my plugins.