Dynamic Plugins and Caching
How I got the Democracy poll plugin to work with WP-Cache
WP-Cache is a useful plugin. Although I've never been Slashdotted, other people who have and are using Wordpress swear by it. It does have a minor flaw. I have a poll plugin, Democracy, that is obviously supposed to be dynamic. It's rather lame to go to a page, vote on a poll, and not see any results because the page is cached. It turns out that WP-Cache has a mechanism for getting around this, allowing dynamic plugins on static cached pages.
It's a little complicated, but WP-Cache lets you use two functions, mclude and mfunc, to include and call PHP functions. The part that gets tricky is that the dynamic environment for WP-Cache is stripped down considerably from the original Wordpress environment. When Wordpress is loading pages dynamically, many Wordpress functions are included and called; none of these functions are initially available for a page loaded from the cache, since the caching captures the HTML/CSS/JavaScript output of the various PHP functions and places it in a temporary file. WP-Cache is a Wordpress-sterile environment, but using mclude and mfunc, we can bring back the Wordpress functions we need to get our plugins to work.
Our goal is to load the minimum number of PHP files required to get the plugin to work. When I was trying to get Democracy to work, I had to chase down a few dependencies, following the trail of errors as a required function would fail to load or a method would be missing. My first step was to locate where Democracy was being called. I run Democracy in the sidebar, so I needed to edit sidebar.php in whichever Wordpress theme I'm using.
For my first attempt, I tried the mfunc syntax, which I got from the WP-Cache readme, wrapping the original call to Democracy around mfunc tags:
<!--mfunc jal_democracy(); -->
<?php jal_democracy(); ?>
<!--/mfunc-->
It didn't work, of course. As far as the cached environment could tell, jal_democracy() had not been defined. So I threw in an mclude to the democracy.php file where jal_democracy is defined:
<!--mclude /wp-content/plugins/democracy/democracy.php-->
<?php require_once(ABSPATH . '/wp-content/plugins/democracy/democracy.php'); ?>
<!--/mclude-->
<!--mfunc jal_democracy(); -->
<?php jal_democracy(); ?>
<!--/mfunc-->
This didn't work either, but I was getting some useful information, in the form of a fatal error: Call to a member function get_row() on a non-object. My first attempt to fix this was to explicitly instantiate the non-object (a variable called $wpdb) in democracy.php. This is when I realized I needed the class definition. And then I wondered how the caching environment could know the class definition. I thought I had found the class definition in classes.php (a logical place to look, after all), but I continued getting the error (and therefore seeing only the header, left sidebar and the search bar in the right sidebar before the PHP error stopped the cache output).
After some thought, I felt I understood what was going on with the caching environment: I had caught on to the fact that it was eliminating all Wordpress functions. No wonder I couldn't create the object or call its method; as far as the caching environment knew, they didn't exist. So I started searching for function definitions, which led me to wp-db.php. By looking at democracy.php, I knew it needed to access the database, and was using Wordpress's database functions for this. I knew I was about to embark on a dependency hunt, so I grabbed my favorite text editor (TextPad) and opened all the files in the wp-includes folder. Then, after specifying the *.php filetype, I searched in all files for function definitions, starting with get_row(). The exact query I used was function get_row(, which told me that the function definition was in wp-db.php. So I added that to growing list of includes:
<!--mclude /wp-includes/wp-db.php-->
<?php require_once(ABSPATH . '/wp-includes/wp-db.php'); ?>
<!--/mclude-->
<!--mclude /wp-content/plugins/democracy/democracy.php-->
<?php require_once(ABSPATH . '/wp-content/plugins/democracy/democracy.php'); ?>
<!--/mclude-->
<!--mfunc jal_democracy(); -->
<?php jal_democracy(); ?>
<!--/mfunc-->
This eliminated the get_row error, but created another fatal error: Call to undefined function: get_bloginfo(). So I searched within the files in the wp-includes folder for function get_bloginfo(, finding it in template-functions-general.php. I added that to the list, only to find that I needed get_settings(). I found that in functions.php. Adding that, I found that I needed wp_cache_get (Wordpress has its own caching functionality, and this function is referencing those functions and not a WP-Cache plugin function). I found that in cache.php. This left me with a final list of:
<!--mclude /wp-includes/cache.php-->
<?php require_once(ABSPATH . '/wp-includes/cache.php'); ?>
<!--/mclude-->
<!--mclude /wp-includes/functions.php-->
<?php require_once(ABSPATH . '/wp-includes/functions.php'); ?>
<!--/mclude-->
<!--mclude /wp-includes/template-functions-general.php-->
<?php require_once(ABSPATH . '/wp-includes/template-functions-general.php'); ?>
<!--/mclude-->
<!--mclude /wp-includes/wp-db.php-->
<?php require_once(ABSPATH . '/wp-includes/wp-db.php'); ?>
<!--/mclude-->
<!--mclude /wp-content/plugins/democracy/democracy.php-->
<?php require_once(ABSPATH . '/wp-content/plugins/democracy/democracy.php'); ?>
<!--/mclude-->
<!--mfunc jal_democracy(); -->
<?php jal_democracy(); ?>
<!--/mfunc-->
At this point, however, Democracy was still not working; I had one final error to chase down: Call to a member function get() on a non-object in cache.php on line 29. This was interesting; it seemed that I had reached the end of the line in terms of finding undefined functions, because line 29 is where the wp_cache_get function returns its value:
function wp_cache_get($id, $flag = '') {
global $wp_object_cache;
return $wp_object_cache->get($id, $flag);
}
I was right back where I started, with a non-instantiated object trying to make undeclared use of a method. The fix was relatively simple: edit democracy.php and run the class constructor to initialize the $wp_object_cache variable. I located the jal_democracy() function definition in democracy.php and added the line wp_cache_init(); right at the beginning and just before the $where variable declaration. The first thing jal_democracy does now is initialize the Wordpress cache class. I'm curious as to whether this has an adverse effect on running Democracy without WP-Cache; if the global variables are already initialized, do they lose their values? I'll have to explore this further, but at least I have a record of how I got this to work, so when I next switch themes, it shouldn't be a big deal to re-create.

If you care, this made my head explode. That'll teach me to click on read the rest of the post.