TimThumb is popular PHP script for dymanic image resizing, and is often included in WordPress themes and plugins. It caches its processed images for performance reasons; its default cache directory is called cache
, one directory level up from the script itself. TimThumb itself helpfully allows users to define a custom cache directory with a constant (FILE_CACHE_DIRECTORY
) as well as a mechanism for loading this custom configuration (an optional timthumb-config.php
file).
This setup provides plenty of flexibility when you’re using TimThumb on a one-off site for a client. But when TimThumb is packaged with a theme or plugin, this method of configuring TT not very helpful. Take the case of WooThemes, which uses TimThumb in all of its themes. We use a number of these themes on the CUNY Academic Commons, where I keep tight reins on file permissions. Our Apache user can’t write to the subdirectories of wp-content/themes/
, which means that the versions of TimThumb in this directory can’t use the default cache location.
The problem is that there’s no easy way to fix this in a global way. Creating a /cache/
subdirectory in each of these theme directories and chmodding them to something more lax is out of the question in my scenario. After all, I already have a directory where Apache can write files: the WP uploads directories (wp-content/uploads
and wp-content/blogs.dir
).
But configuring TimThumb to put its cache in one of these places is difficult to accomplish globally. The obvious solution is to create appropriate timthumb-config.php
file in each of the theme directories in question. This stinks, though, because it means that my modifications will have to be reapplied each time I upgrade the themes. In fact, what I’ve actually done for the moment is a variation on this: I created a centralized timthumb-config.php
file, in a centralized location (wp-content
, in my case), containing a single line:
[code language=’php’]
[/code]
I wrote a short script that crawled over every one of my WP themes, and if it found an offender (in my case, any theme with ‘WooThemes’ in the Author tag), create a symlink to the global config. I’ll be including this script as part of my more general deployment scripts.
Of course, this is all extremely inelegant. There are a few things that the theme developers could have done to account for my sort of situation:
-
Stop putting a copy of your shared utilities (the “framework”) in every theme directory. I understand why the theme shop might make this architectural decision – I’m sure that the vast majority of their theme sales are to people running the theme on a non-networked, single site. But it causes a lot of problems for Multisite networks that offer many themes to their users: a single change in the framework means updating all themes, which becomes a real pain if the theme dev’s autoupdater also isn’t working properly. Allow your framework to be installed as a network-activated plugin, or at least dropped into the wp-content
directory. Better still: You can continue to ship the framework files with the themes, but only load them if the pluginified version is not found. That gives you the best of both worlds.
Now in the case of TimThumb, this schema wouldn’t have solved the problem. But it would have meant hacking a single file, rather than 50 different files spread out through my installation.
-
Put a wrapper around TimThumb, to allow more flexible placement of the config file. For instance, create a file called mytheme-thumb.php, which looks like this:
[code language=’php’]
[/code]
Then point all of your TimThumb-generated src
attributes to mytheme-thumb.php, instead of directly at TimThumb. This way, if a global config is found, it’s loaded first, otherwise it falls back on a local timthumb-config.php file, as specified by TT itself.
-
Pluginify TimThumb before using it In a perfect world, you would have the flexibility of WordPress behind TimThumb: the ability to store your cache location to the database, for example, or to filter the location using apply_filters()
. I did a bit of testing to see just how much overhead this would add. In my tests, TimThumb used about 700KB to load a simple picture. To load WordPress using the SHORTINIT
constant (which loads just enough of WP to get things like get_option()
and apply_filters()
) takes about 2800KB. So loading WP SHORTINIT + TimThumb would take about 3500KB, or about 5x what it takes to load the same image using TimThumb alone. This wouldn’t be so bad with aggressive caching, but it’s probably too much sacrifice for a script that may get called several times on every single page load.
So here’s another idea: Just drop in wp-includes/plugins.php
. I once heard someone say that a great way to improve any PHP package is to include this file, and I think they’re right. plugins.php
is self-contained (it doesn’t require the rest of WP), and it only adds another 50-100KB of overhead. Let’s take our mytheme-thumb.php file again, but add some plugins.php goodness:
[code language=’php’]
[/code]
Now in this example, thumb.php
wouldn’t have to be an out-of-the-box TimThumb instance. It could be filled with wonderful do_action()
and apply_filters()
goodness. And your global-timthumb-config.php
or timthumb-config.php
file wouldn’t just define constants – you could have full-fledged PHP functions, using WP’s hook infrastructure.
This means maintaining a fork of TimThumb, but it could be a great resource for WP theme developers.