I know that it’s not been long since the last release, but 0.5 exacerbated a few annoying, and long-running, problems that the plugin had.
I’ve had some spare time over the last week (yay for Easter!), so I decided to really get to grips with these issues, and hopefully eradicate them.
I didn’t ‘officially’ announce a beta this time around, as I had some brilliant assistance from Derek and Tom, who tested several iterations of the in-development code and helped to iron out many issues and bugs along the way. Many thanks again to them!
Here’s a run-down of the changes:
The plugin has always had issues with memory, especially with large numbers of events and feeds. The changes in 0.5, that allowed you to specify a much greater date retrieval range and therefore potentially retrieve many more events, really pushed things too far and have caused many people’s sites to run into their (perfectly reasonable) PHP memory limits.
Unfortunately, the major cause of the memory issues was the SimplePie feed parser on which the plugin relied to do much of the hard work. SimplePie (with some help from WordPress’
class-feed.php) took care of feed retrieval, feed parsing and caching, meaning the plugin didn’t have to be bothered about any of this. However, the memory problems were too great to ignore any longer; SimplePie had to go!
Don’t get me wrong, SimplePie is great, it made things really simple (hence the name, I guess), but I just don’t think it’s quite the right solution for the plugin any longer.
So, the plugin now takes care of retrieval, parsing and caching itself. The result is a massive reduction in memory usage.
Don’t hold me to any figures, but I’ve done quite a bit of unscientific testing, and the reduction is roughly between 75-90%.
As I mentioned above, caching wasn’t directly controlled by the plugin in 0.5 and below. While this made things simple from a coding point of view, it wasn’t ideal. I won’t go into the details, as it’s complicated (and boring) but essentially the plugin created far too many caches of feed data, and never really cleaned up expired caches. Also, the feed data was cached in a completely raw state, meaning it was enormous and had to be processed from scratch each time. On top of that, the plugin couldn’t really keep track of what cached data existed, so it couldn’t be cleared on demand.
All of the problems above are addressed in 0.6:
- One feed, one cache – Now, there is one cache of feed data per feed. That’s it. You don’t need to worry about your database filling up with useless cached data, as the same cache will always be overwritten for each feed.
- Much less is cached – Now, the plugin caches processed data rather than the raw feed. This means that only useful information is stored. All the extra stuff sent along with the feed that the plugin doesn’t need is discarded, so there’s much less to keep in the database.
- Only processed once – As I said, the plugin processes the feed before caching it. Therefore some of the work only needs to be done once per cache, rather than every time a grid or list is requested.
- Refresh on demand – There’s a new ‘Refresh’ option for each feed you have added. This will clear the cache of the feed, forcing it to be recreated next time a grid or list is requested. This means it is no longer necessary to faff about changing the cache duration option to 0 in order to retrieve the most up-to-date data.
Of course, none of this solves the problem of existing, useless feed data that has been created by previous versions of the plugin. To address this, I have built in some functionality that detects whether you’re upgrading from 0.5 or below, and asks you whether or not you’d like to empty your database of expired cached data. This appears the first time you visit the plugin options screen after upgrading.
I would definitely recommend that you do clear the useless cached data, but you can choose to ignore it.
I’ve done a bit of a ‘performance overhaul’ of the plugin. I fired up XDebug and WinCacheGrind and looked for bottlenecks. I’m sure that there’s more optimisation that could be done, but now the plugin should:
- Load faster – You may not notice it, but page load times should be faster due to generally more efficient code.
- Make fewer database queries – Maybe only a couple fewer here and there, but the less database hits, the better.
- Be quicker on AJAX requests – The plugin checks more carefully to ensure that only necessary stuff is done on AJAX requests. This should make month navigation in AJAX grids a little faster.
These bits and bobs may not sound much, but every little helps, especially on high traffic sites. Coupled with the major memory usage and caching improvements, the plugin is a much more efficient piece of software than it used to be.
Another handy side effect of the changes is that I was able to put together an improved error handling system.
In previous versions of the plugin, using multiple feeds in one grid / list, if any of the feeds were not parsed successfully, no events would be displayed, even if the remaining feeds were fine. Now, the plugin will ignore ‘broken’ feeds and continue to display events from any working feeds.
As a logged-in admin user, you will see error messages explaining the problems that are preventing each feed from being displayed. These messages are much more specific to the problem than the generic message displayed in previous versions of the plugin.
Other Changes / Additions
I’ve also implemented a few other miscellaneous things:
- Optimise event retrieval – There’s a new option in the general plugin settings. When enabled, the plugin will use experimental parameter of the Google Data Protocol, called
fields. This parameter allows the plugin to specify exactly what data it needs, so that Google doesn’t send back any extra information that isn’t useful. This makes the feed data much smaller, meaning it takes less time to transfer, less time to process and uses less memory, resulting in a significant performance improvement. However, this is an experimental feature, so Google could potentially remove or change it an any time, possibly causing the plugin to break. Even though this is unlikely, I’ve made it an option rather than hard-code it into the plugin, just in case. Hopefully, Google will make this a ‘proper’ feature eventually… it’s awesome!
- Custom stylesheet – If you specify a custom stylesheet, it will be included as well as the default stylesheet, rather than instead of. This is so that if the custom stylesheet gets deleted or overwritten (for example, during plugin updates, as quite a few people have experienced!), the default one will still be there to ensure that the basic CSS rules required to prevent things going wonky are in place. This also means you don’t need to make a copy of the default stylesheet, you add only the CSS you want to change / override.
- Uninstall – If you delete the plugin via the WordPress plugin admin screen, it will ‘uninstall’ itself. This means it will remove all trace of itself from your database, including saved feeds and cached data.
- Now doesn’t mean now – In version 0.5, if you used the ‘Now’ option of either of the ‘Retrieve events from’ or ‘Retrieve events until’ settings, the plugin interpreted this as literally now, to the second. This had the effect of reducing the cache duration to 1 second, regardless of the cache duration option. In this version, the plugin rounds now to the previous minute, so that the minimum cache duration is also 1 minute when using the ‘Now’ options (unless you set the cache duration lower, but… don’t!). Events in Google Calendar are only precise to minutes anyway.
- Check for PHP 5.2 – The plugin requires PHP 5.2, as it now makes use of
json_decode. The plugin has required PHP 5 for a long time, so this shouldn’t affect many, if any, existing users. There’s now a check to ensure that PHP 5.2+ is installed, if not, the plugin won’t activate and will display a message explaining why not. WordPress itself will also require PHP 5.2 (5.2.4 to be exact) as of version 3.2. I got the idea and implementation for this from Yoast.
- Improved multi-day event handling – Multi-day events are now handled correctly. They used to display outside of the specified date retrieval range, they don’t any more (Thanks Chris!).
- More event display builder shortcodes – I’ve added 3 new shortcodes:
[length]. Take a look at the event display builder guide for explanations of these.
- Improved ‘human’ time differences – For the
[end-human]event display builder shortcodes, the plugin was using the WordPress
human_time_difffunction. It works well, but is limited to minutes, hours and days. So, the plugin now uses an improved version of this function, as suggested in a WordPress trac ticket by Viper007Bond, which displays weeks, months and years too.
I’ve fixed a couple of bugs too:
ctzparameter – Links created in the event display builder (with
[link-path]) were missing the current timezone (
ctz) parameter. This meant that anyone not currently logged into a Google account who clicked on one of these links would see event times in UTC time, rather than the correct timezone (Thanks to Jodi for spotting and reporting this).
- Clickable URLs – When using the simple display options, URLs in the description of an event would be automatically made into a ‘proper’ link. This should have occurred in the event display builder too, but didn’t. It does now (Thanks to Jim for pointing this out).
HTTPSURLs – At some point, Google seems to have changed the default protocol for calendar feed URLs to
https. On some server configurations, these
httpsURLs failed to work (although simply changing
httpfixed the problem). Another side effect of the changes in this release is that this problem can be avoided, so both protocols should work just fine.
I think that’s about it. I’m hoping this release will be well received, as although it doesn’t add any terribly exciting features, it does solve some long running problems, which will allow the features added in 0.5 to really be used to their full potential.
You can update the plugin automatically from within your WordPress admin, or download it from the plugin directory.