12Nov/093

404 Errors When Integrating Zenphoto With WordPress

The Problem

In my previous post, 'A Basic WordPress And Zenphoto Integration', I noted that my Zenphoto integration had a problem with silent 404 errors. Although the pages of the gallery were being displayed nicely skinned with my WordPress theme and everything looked okay, behind the scenes they were being delivered to the browser with a HTTP status of 404, "not found". Obviously this is a very bad thing, as once I manage to get search engines indexing my site they would see the 404 and assume that the pages were not available, ignoring the fact that the content was actually there.

The Details

Some comments on the original post that I used to aid my integration suggested that this was being caused by the URL rewriting used by both WordPress and Zenphoto. Taking this lead, I did a few simple tests to narrow the location of the problem. First I disable the URL rewriting in Zenphoto. No change. Second, I disabled the URL rewriting in WordPress. Bingo; the gallery pages were now being served with a HTTP status of 200, but now my WordPress URLs were decidedly less than friendly.

Time for a bit of digging into how WordPress handles URL rewriting. Actually, not much digging was needed in this case. As the gallery is located in a sub-folder under the WordPress installation, I figured all that was needed was to make WordPress ignore this entire sub-folder when it comes to parsing rewritten URLs. This led me to 'WP_Rewrite' in the WordPress Codex. This class, defined in wp-includes/rewrite.php, handles all of the URL rewriting rules used by WordPress.

Using the single global instance of this class, $wp_rewrite, plugins can modify the rules at various points, such as specifically for permalink rewriting or maybe search URL rewriting. There are also two hooks for more global modifications. Plugins can add filters for 'rewrite_rules_array', which allows processing of the whole set of rewrite rules once they have been produced. Alternatively you can add an action for 'generate_rewrite_rules' which runs after all of the rules have been created.

The Solution

There are two possible solutions we could implement. We could add a filter for 'rewrite_rules_array' and insert a rewrite condition stating that the request URI should not start with our gallery path, such as:

  1. RewriteCond %{REQUEST_URI} !^zenphoto

Alternatively we can add an action for 'generate_rewrite_rules' to add a rewrite rule indicating that our gallery path should not be rewritten. The eventual rewrite rule would be something like:

  1. RewriteRule ^zenphoto - [L]

Using '-' as the substitution just means no substitution, i.e. no rewrite. An very basic example script for a plugin might be:

  1. add_action('generate_rewrite_rules', 'zp_add_rewrite_rules');
  2.  
  3. function zp_add_rewrite_rules($wp_rewrite)
  4. {
  5.    $new_rules = array('^zenphoto' => '-');
  6.    $wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
  7. }

This script simply defines the new rule as an associative array with the pattern as the key and the substitution as the value. This is then added to the start of the existing array of rules.  This is only a very basic example; there is much more that can be done with collections of rules but in this case this is all that is required. I have decided to go with this second option as it is pretty straight-forward and easy to understand. There is one gotcha with this method though. By default WordPress loads pre-prepared rewrite rules from the database, so our new action would never run. To avoid this issue, you must flush the stored rules on each request, to ensure that any new rules defined by your plugin are added. The following script will do this by defining an initialization action for your plugin:

  1. add_action('init', 'zp_flush_rewrite_rules');
  2.  
  3. function zp_flush_rewrite_rules()
  4. {
  5.    global $wp_rewrite;
  6.    $wp_rewrite->flush_rules();
  7. }

A combination of these two scripts make a plugin that will fix 404 errors in a WordPress and Zenphoto integration with a shared theme. This can be expanded with some logic borrowed and extended from Einar Egilsson's integration plugin that attempts to determine the path of the Zenphoto installation. This can be overridden by setting the $gallery_path variable:

  1. add_action('init', 'zp_flush_rewrite_rules');
  2.  
  3. function zp_flush_rewrite_rules()
  4. {
  5.    global $wp_rewrite;
  6.    $wp_rewrite->flush_rules();
  7. }
  8.  
  9. add_action('generate_rewrite_rules', 'zp_add_rewrite_rules');
  10.  
  11. function zp_add_rewrite_rules($wp_rewrite)
  12. {
  13.    $names = array('zenphoto', 'photos', 'gallery');
  14.    $gallery_path = '';
  15.  
  16.    if ($gallery_url == '')
  17.    {
  18.       foreach($names as $ix => $name)
  19.       {
  20.          // Will be at current level in WP and up a level in ZP
  21.          if (is_dir("$name") || is_dir("../$name"))
  22.          {
  23.             $new_rules = array("^$name" => '-');
  24.             $wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
  25.          }
  26.       }
  27.    }
  28.    else
  29.    {
  30.       $new_rules = array("^$gallery_path" => '-');
  31.    $wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
  32.    }
  33. }

Simply wrap this script up as a plugin and add it to your WordPress installation and once activated it will take immediate effect. Click here to download one I prepared earlier.

Comments (3) Trackbacks (0)
  1. Wow! Great fix. Was suffering that frustrating issue and thanks to your plugin it’s gone away. Much easier than dealing with htaccess headaches

  2. I’m having a crazy problem; tried this fix, but a no go. Have installed everything and edited everything…but the Zenphoto link in WP gives a “cannot load.” page error. I can access the zenphoto admin separately, but really, really need this stupid thing to work. I have spent days agonizing over photo album codes and finally thought I’d found a decent one… am starting to think I was wrong….


Leave a comment


No trackbacks yet.