Category Archives: Wordpress

WordPress – Stop screwing with the timezone!

So my dates were not displaying correctly and it turns out that WordPress is to blame.

After checking the data and finding that it was correct, I was confused as to why a wordpress page was displaying the wrong date for a correct unix timestamp.

WordPress was screwing with the timezone setting of PHP. This little factoid took a good 30 minutes for my decaffeinated brain to figure out.

So, here is a small function that will help out displaying a date with the correct info:

/**
* Echo's a date with the timezone setting unfuxed
* 
* @param mixed $format
* @param mixed $timestamp
*/
function echo_date($format,$timestamp) {
	$old_tz = date_default_timezone_get();
	date_default_timezone_set(get_option('timezone_string'));
	echo date($format,$timestamp);
	
	date_default_timezone_set($old_tz);
}

wpsc_update_custom_meta() nukes my custom post meta data

So today I was rather perplexed as to why my custom meta box on my post edit page was not playing ball. It would be set to a value and always stay at it, delete it from the database and give it a different value – and it would keep that too.St

Since I had used the update_post_meta() function before and it had never behaved this way, I looked through the mysql.log file on my server and saw this

4162 Query SELECT meta_id FROM wp_postmeta WHERE meta_key = 'my-plugin-key' AND post_id = 128
4162 Query UPDATE `wp_postmeta` SET `meta_value` = '0' WHERE `post_id` = 128 AND `meta_key` = 'my-plugin-key'
4162 Query SELECT meta_id FROM wp_postmeta WHERE meta_key = 'my-plugin-key' AND post_id = 128
4162 Query UPDATE `wp_postmeta` SET `meta_value` = '1' WHERE `post_id` = 128 AND `meta_key` = 'my-plugin-key'

What the? my value is set and then set back to what it was!? Time to find out where this was happening. Since I use Nusphere’s PhpEd to develop all my PHP projects, I fired up the trusty debugger and followed the code. Now take a guess where my setting is being undone!

Now I realise that I am playing in WP E-Commerce’s own playgound and that I need to play by their rules – but overwriting my changes – that’s just not cool!

The Fix

Go Last. Well, have wordpress call your save function after wp e-commerce. It’s rather simple actually – but a gotcha that cost me a couple of hours!

add_action( 'save_post', 'MyPluginHandleMetaBoxSaveData', 99);

WordPress, WP E-Commerce and the lack of ASYNC AJAX

Now Normally the A in AJAX means Asynchronous, meaning you can have several requests going at once, so it was very confused as to why my AJAX wasn’t. My WordPress plugin is a long running import process and I decided to use AJAX so that I can provide timely feedback to the user as to how far the import had gotten.

But these status updates were not working. I would get the entire output at the end of the process.

Then it dawned on me. WP E-Commerce is a pig and assumes that you want a session started all the time (even if you do not need it – which is rather bad for varnish caching), and PHP sessions are blocking, so that only one call with the same session id is handled at a time. AJAX sends cookies, and therefore WP E-Commerce starts the same session for all session requests.

So remember, if you are writing a long running plugin with lots of AJAX requests and you are not getting async output, check to see if there is a session cookie being sent!

The way I solved this problem is to use this code at the top and bottom of your plugin!

if ($_COOKIE['PHPSESSID']) {
	session_write_close();
}

if ($_COOKIE['PHPSESSID']) {
	session_start();
}

You do not have sufficient permissions to access this page.

Note to self: do not use non prefixed global variables in your wordpress plugin.

It causes all sorts of chaos. For example – gett the error “You do not have sufficient permissions to access this page.” whenever you load a page that is not your plugins.

For those playing at home, this is the code that I used to cause me headaches:

$plugin_page = add_action('admin_menu', function() {...});

Note that $plugin_page is used by wordpress, and overwriting it, well, makes things not work!

#FeelingLikeATurkey

Get the WordPress Plugin URL

So today I was writing a plugin that belongs in the tools section of the wordpress admin and I found myself wondering how to get the URL of the plugin. So I created a little function that creates the URL with all the params I need for me – and here it is! (obviously change the my_ to your own plugin namespace)

function my_plugin_url($variables) {
    $url_bits = parse_url('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
    $query = array();
    foreach (explode('&',$url_bits['query']) as $pair) {
        list($k,$v) = explode('=',$pair);
        $query[$k]=$v;
    }
    foreach ($variables as $k=>$v) {
        $query[$k] = $v;
    }

    return sprintf('%s://%s%s?%s', $url_bits['scheme'], $url_bits['host'], $url_bits['path'], http_build_query($query));
}

and you call it like this:

<a href="<?php echo my_plugin_url(array('param1'=>'value1'))?>">Example URL<a>

and it will output the url with your extra parameters

The case of the misbehaving wp e-commerce price sort

So we had an interesting issue where sorting product by price was not working correctly for wp e-commerce products.

The sorting was happening but MySQL was sorting the wp-postmeta.meta_value as a string, so 12.95 was coming AFTER 123.

The solution is nice and simple

$query->set('orderby','meta_value_num');
$query->set('order','ASC');

This way the MySQL does this:

was: ORDER BY wp_postmeta.meta_value
new: ORDER BY wp_postmeta.meta_value+0

Note the difference? The +0 forces MySQL to treat meta_value as a number and sort by that.

This tip comes from Tom @ http://www.tomandvez.com!

beware the trailing slash…

So, we had an interesting issue with wordpress plugins not using the correct path, so we had busted URLs for their resources. for example:

<img src='http://example.com/wp-content/plugins/var/www/example.com/htdocs/wp-content/plugins/myplugin/logo.png' alt='plugin logo'/>

Now, this is obviously ideal since the resource was not being loaded (bad mkay).

The fix is only 1 character believe it or not. Removing the trailing slash from the WP_PLUGIN_DIR config variable fixed the problem!

Why? Well the function that plugins call to get the path they need is called “plugin_basename” and plugin basename assumes that you do not have a trailing slash on your path – here is the code for it – Note the “/|^” and the “/#” to add the trailing slash onto your WP_PLUGIN_DIR and WPMU_PLUGIN_DIR paths.

$file = preg_replace('#^' . preg_quote($plugin_dir, '#') . '/|^' . preg_quote($mu_plugin_dir, '#') . '/#','',$file); // get relative path from plugins dir

register_activation_hook() not working

AAAARRRGGGHHHH

So I had an issue with my wordpress plugin not getting initialised properly, my activation hook was not working correctly. If you are in a hurry, my fix was this:

Make sure that the WP_PLUGIN_DIR does NOT have a trailing slash.

Yep, that’s it – two hours of my life tracking down Yet Another 1 Char Bug (I swear I have lost weeks of my life to bugs that are 1 character in nature!).

For more in depth trouble shooting, here are some things to know about the wordpress plugin activation process.

When you call register_activation_hook() it adds an action to the list with your callback associated with it. The action name is something like

activate_test.php

If it working correctly it should appear as above, otherwise it will look something like

activate_var/www/sitename.com/htdocs/wp-content/plugins/test.php

this is bad! The plugin_basename() function that is called has failed to match the WP_PLUGIN_DIR constant and remove it.

Here is the test plugin that I used to help me find the problem

<?php
/**
Plugin Name: test tickles
*/

syslog(LOG_ERR,'Testing @ ' . date('Y-m-d H:i:s') . ' ' . __FILE__);
syslog(LOG_ERR,'WP_PLUGIN_DIR = ' . WP_PLUGIN_DIR);
syslog(LOG_ERR,'plugin base name = ' . plugin_basename(__FILE__));
register_activation_hook(__FILE__, function() {
    syslog(LOG_ERR,"Here is an error");
});

Needless to say, you should keep an eye on the syslog with this code

sudo tail -f /var/log/syslog

And then activate your plugin, if all goes to plan you should see

Here is an error

In your syslog file, if you do not – then you will see the plugin path and the path that plugin_bashname() thinks that it should be. If you see the whole path to your plugin – you now can go and fix it!

Another Lazy Weekend

So here I am, chilling out – thinking how to make wordpress behave nicely with a software load balancing reverse proxy, particularly Varnish Cache. Why you may ask – well I need to get the best performance I can out of my shiny new web setup  at work and Varnish Cache by default does not cache anything that has a cookie.

There must be a way to put at least the front end wordpress stuff on a diet!