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!

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!