Function Documentation

WordPress Function Documentation Progress

Writing Plugins: What is the Class Callback Format?

Prior to WordPress 2.3.0, there was a bug that prevented object referenced method callbacks from being removed. In WordPress 2.3.x and upcoming WordPress 2.5, in order to remove the original method in the class, you have to use the original object reference. In PHP4, where objects are passed by value, this can be a problem, but PHP5 users shouldn’t have much to worry about as long as the variable they are using holds the original class reference.

Explanation of Problem Prior to WordPress 2.3

To demonstrate the problem, take a look at this code. If you were to run this prior to WordPress 2.3, the hook would not be removed because you changed the class property $test.

class MyPlugin
{
    var $test;

    function MyPlugin() {
        $this->test = false;
        add_action('init', array(&$this, '_init'));
        $this->test = true;
    }

    function init() {
        remove_action('init', array(&$this, '_init));
    }
}

This is a poor example, in that the ‘init’ hook will never run again. Other hooks will demonstrate the problem better in real world practice. That said, the method of adding callbacks to the hook array wouldn’t have allowed you to remove the hook until the state of the class was back in its original form prior to the addition of adding the MyPlugin::_init() to the init hook.

It is a little complicated to explain, but basically, once you changed the properties of the class, you wouldn’t be able to remove any hook you added prior to the change. For most plugins this was a huge deal since they had everything in one Singleton class (big mistake, will detail in later post).

How Method Callbacks are handled in WordPress 2.3+

A new private function was introduced to manage object referenced method callbacks. The form of which is below.

$myplugin = new MyPlugin();

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

As you can see, the callback references the $myplugin variable along with the method in the second element. The reason this can cause a problem, is if you unset the variable afterwards.

$myplugin = new MyPlugin();

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

unset($myplugin);

If you think this will magically remove the reference in the hook array, you are mistaken. PHP will retain the reference to the object and will call the method. This will hinder, but not prevent the removal of the object’s callbacks later.

For a workaround, you can recreate the object reference and it should (purely conjecture) recreate the needed hook string to reference to previously added object reference callback. This will not work if two or more object references of the same class were created, so it is assumed that in most cases only one object reference will be created. If only one were created and destroyed, it might be possible to remove the callbacks from the action or filter using the Plugin API.

New format

The new format for the above object referenced method callbacks are always: class name, followed immediately by the method name, followed by the amount of previously added (classname+methodname). For classes, this allows you to add as many object referenced classes and add methods which don’t override each other.

For static method callbacks, the format is always: class name followed immediately by method name. There is no need to protect against overrides because no two classes can have the same class name (yes, I do know there is an exception to this rule).

For functions, nothing changes, it is just the function name.

January 13, 2008 Posted by | Writing Plugins Series | , , , | 5 Comments

Writing Plugins: The ‘all’ Hook

The ‘all’ hook is run on every action and filter hook. It is good for debugging and not much else. Also, prior to WordPress 2.5, the ‘all’ hook was broken and shouldn’t be hooked into.

The fix removes the logic that merges the all hook into the rest of the other hooks. This should have a nice benefit of speeding up the plugin cycle. The all hook will also only be processed if there is a function that was added to it. For almost all users, they will never run the all hook.

The ‘all’ hook is technically an action since it does not offer an interface for returning data to other functions that are in the ‘all’ hook. However, it will run for all actions and filters, but will not have access to the filter contents.

Well, for filters, the ‘all’ hook will have access to the initial parameter value or values if there is more than one parameter (more on that later), but will not have access to the completed value after all of the functions in the hook have processed the initial value.

Adding a Function to the ‘all’ Hook

add_action('all', 'myplugin_all_hook');

function myplugin_all_hook( $parameters ) {
    // Do stuff here
}

The all hook has access to the parameters that were passed to the hook as an array and that will be passed to the functions. The ‘all’ hook does not have access to manipulate those parameter values before they get to the filter or action functions.

The $parameters is an array, which holds all of the values for from each of the parameters. You can count the array, test the contents of the parameters, test the types of the values.

Use Cases

What the ‘all’ hook can do however is a few evaluations.

  1. Do sanity checks against how many parameters the current hook (Will be discussed in a later post) should have verses how many were actually passed.
  2. Count how many times a hook was called during a run of WordPress and for each page. (The ‘all’ hook will not be able to profile how long each hook took to process however.)
  3. Using debug_backtrace(), can figure out which functions called the hook.
  4. Fine tune your plugin by seeing what the hook you are plugin to is giving your function.

Those are the common use cases of the ‘all’ hook. However, like it has already been stated, only debuggers are likely to plugin to the ‘all’ hook. Most plugin authors and users should not concern themselves. However, if you wish to debug the hooks, then there is a built-in way to do so.

January 10, 2008 Posted by | Writing Plugins Series | , , , | Leave a comment