Convert error_reporting value constants into human-readable form:

I wanted to work out which errors were being logged given the error_reporting value from a php.ini file, so I spent 10 minutes writing this: (code below)

Error reporting value: Human readable format:

and here’s the code:

    function convert_error_constant_to_human_readable( value ) {
       var errors = {
        1: 'E_ERROR',
        2: 'E_WARNING',
        4: 'E_PARSE',
        8: 'E_NOTICE',
        16: 'E_CORE_ERROR',
        32: 'E_CORE_WARNING',
        64: 'E_COMPILE_ERROR',
        128: 'E_COMPILE_WARNING',
        256: 'E_USER_ERROR',
        512: 'E_USER_WARNING',
        1024: 'E_USER_NOTICE',      
        2048: 'E_STRICT',
        4096: 'E_RECOVERABLE_ERROR',
       var human_readable_errors = [];
       for (var error in errors) {
         if (errors.hasOwnProperty(error)) {
           if ( value >= error && (value - error) % ( 2 * error) == 0 ) {
               var value = value - error;
               human_readable_errors.push( errors[error] );
       return human_readable_errors;
    $('#convert-to-human-readable').on( 'click', function(){
        var value = $('#error-reporting').val();
        var human_readable = convert_error_constant_to_human_readable( value );
        $('#human-readable').val( human_readable.join("\n") );

The Brexit Argument Deconstructed

Tomorrow the UK will decide whether it should continue as part of the European Union, and recent polls indicate that it is too close to call. I don’t presume to think this post will change anyone’s views, but what follows is my attempt to expose the fallacies of the Brexit argument. It doesn’t focus on the reasons for the EU, although that is implicit in arguing against leaving it. For a more wider argument, I’d encourage you to read this article on the economist.


This is by far the biggest pillar of the Leave EU. It’s also the thorniest issue for the Remainers because a central tenant of the EU is the free movement of people, and net migration is almost at highest level. So what can be said? Firstly, there is a small number of people who oppose immigration on the basis of xenophobia or a feeling that there are “just too many” migrants in the country (This isn’t to be confused with concerns people may have with the effect of migration on public services – more on that later). These views are based on prejudice and self-entitlement, and often stem for a need to project blame for their own dissatisfaction with their lives, status or income (which is not to say it is their fault). It’s these kind of views, when they start to gain wider attraction, that serve as a cauldron for intimidation and de-humanisation of minority groups, and even genocide. This isn’t hyperbole, we have seen countless times through the last century, even in the nineties.

Now to claim that all Leave EU supporters are racist would be plain wrong. However those fronting the campaign, and in particular Nigel Farage have been stoking fears of public services and laying the blame at the door of the migrant. NHS, schools, housing, are all under-pressure because of migration. Are they?

Let’s take the NHS. A few years ago the Nuffield Trust conducted an analysis of the NHS. They found that major factor in increasing number of hospital admissions was… an ageing population. Now you might say, but surely stemming migration will help? Not necessarily. The percentage of EU nationals in the NHS roughly matches that of the percentage of EU nationals in the UK (about 5%) – in fact when you take doctors alone, that rises to 10%. In addition, with an end to free movement of people it becomes harder for the UK to attract nursing staff. The Royal College of Nursing concluded in this report:

Whilst some countries move towards opening up their immigration policy to encourage the inward migration of nursing staff, the fact that the UK is reforming its immigration rules – with a view to making it more difficult for nurses to remain in the UK – places it at a real and significant disadvantage.

I must stress that this was a report was an analysis of the affects to the tightening of non-EU migration into the UK in 2010. It is however, indicative of the consequences if we apply that to EU migrants too.

So what is putting strain on the NHS? As noted, Britain has an ageing population (largely the result of the post-war Baby Boom). It’s also under strain because of the Tory government’s austerity measures. While the government “boasts” that it is pouring in £8 million, the reality is that was the minimum required to keep services going.

We should also not forget that EU migrants contribute to the UK budget. (David Cameron also negotiated a deal with the EU by which non-UK EU citizens can only obtain full benefits after being in work for four years). This Full Fact article looked a couple of studies on the ‘net effect’ of EU migrants and has this to say:

As the studies cover sixteen years in which several trillion pounds were gathered and spent by the British state, these are relatively small differences, suggesting that EEA migrant tax revenues have been at least in the same ballpark as the money spent on them.

Lastly, if fear of what will happen to the NHS is your driving motivation in this referendum, I’d ask you to seriously consider the views of Gove & MEP Daniel Hannan, Johnson who said on this:

If NHS services continue to be free in this way, they will continue to be abused like any free service. If people have to pay for them, they will value them more… this extension of private funds into the NHS would help the Chancellor’s straitened circumstances.” – Boris Johnson, The Essential Boris Johnson, 2003

and Farage on the NHS.


This an easier argument to counter; the leave campaign have roundly lost the economy argument. The vast majority of economists predict that the damage done to the UK economy from Brexit would outweigh the money reclaimed from our EU contribution (a contribution which the Leave campaign misleading state as being twice as high).

The independent fact-finding charity Full Fact also point out that most economists predict (What would it mean for my job?) that in the near future, following a vote to leave, job creation will be stagnate. Additionally the economical impact of Brexit would leave the government with less money to fund public services, which would put the jobs of those working in the public sector at risl.

The TUC has released a report indicating the real value of average wages in 2030 will be £38 per week lower if the UK chooses to leave. This in addition to negative forecasts following a vote to leave from the OECD, Bank of England, CBI, IMF and others. If you think they have a vested interest consider that Federal Reserve Chair Janet Yellen has recently indicated that a vote to leave will have a negative impact on the US economy. This is important because the Federal Reserve is completely independent, its sole interest is in the US economy. However given the amount of trade between the US and UK, its findings are relevant as it has knock-on effects for the UK and EU.

The Leave campaign point to countries like Greece and Spain as examples of where the EU has failed. To date I’ve not seen any reasoning or evidence as to why they would have fared better outside of the EU, even less, if they are so concerned, what a UK outside of the EU would have done to help. Most claims put it down to their adoption of the Euro, which may well be right, but it’s an odd point to make when the UK (quite rightly) opted-out of the single currency.


The “65% of UK laws are made in Britain” statistic is misleading. It includes EU regulations (not just laws) which do not require any UK legislation to implement. The House of Commons published a report which put the figure closer to 13%. This statistic is further muddied by two further observations.

Firstly, it doesn’t consider rulings made by Judges which have the force of law. Secondly, it gives the false impression that laws passed by the EU are of equal importance to UK laws. For instance a few years ago, in a bid to improve (reduce) energy consumption the EU banned energy inefficient vacuum cleaners. While I’d agree this an important step in reducing our environment impact, it probably doesn’t rank as high in importance as the Parliament Act on Restructuring the NHS.

In deed, EU law tends to be focussed on issues such as trade, the environment, and consumer and worker rights. Welfare, education, criminal law and the NHS are less impacted by the EU except in as far as regulations on worker’s pay or use of banned environmentally-damaging substances etc.

Now the battle cry of Vote Leave is that we would have worker’s rights without the EU and that we would keep them. It’s of course true that a vote to leave wouldn’t trigger an automatic appeal of those laws. But it’s not hard to see that these would eroded over time. Labour MP & leave campaigner Gisela Stuart said that she (I paraphrase) “[trusted] voters to vote for a government who would protect those [worker] rights”. It’s an odd thing to claim from an opposition MP. It’s also not an issue of trust. At a General Election we vote between a few broad and typically very vague election manifestos, and UK government can be elected as with as little as 25% of popular support. In short it’s naive to assume that a UK government will protect the interests of all groups equally; they will use their election as mandate for pushing through laws which typically benefit their own supporters even if the majority of the electorate do not agree with those laws.

To give an example of one such law which was ‘imposed by Brussels’ on Britain; When Working Time Directive was implemented in 1988, 2 million people got paid leave for the first time. The directive limits the number of hours an employer can make you work (you can voluntarily opt-out) and the minimum number of hours between shifts. The Conservative government wants to reverse that legislation, I doubt that most of the electorate would support that.

Vote Leave have been far less vocal on less politically-sensitive topics such as (unfortunately) the environment. The EU has been an important bastion in this regard (as with worker and consumer rights) and there’s an important reason for this. Climate change, for example, is an issue without borders. The EU passes regulations (such as the one on vacuum cleaners) that help reduce the environmental impact of each of the member states. By applying this EU-wide, it prevents a race to the bottom with states competing on the less politically-hot topic of environment. I fear such ‘red tape’ will be the first to cut in a bid to make the UK, outside of the EU, more competitive. The same can be said for the EU-ban on pesticides considered harmful to health or various chemicals banned from food for the same reason. These are issues which the EU excel at, but they are simply not headline-grabbing.

More widely, membership of the EU is a trade-off. It allows a country to ‘buy’ access to a common market and all the economic benefit that brings (and as noted, it does). In return that country has to abide by range of minimum standards including those designed to protect workers, consumers and the environment. To say the EU has failed is to ignore the plethora of improvements that has brought in and maintains on those matters. In the age of globalisation it’s naive to assume these rights and protections are still solely national issues. The EU prevents a race to the bottom, with businesses and states undercutting each other at the expensive of pay, safety or environmental impact.

In short, the EU secures these various protections in return for economic benefit, preventing a race to the bottom between companies and states and where worker’s rights and environmental protections are likely to be the first victims. If you are not convinced consider that the “EU costs households £9,625 a year” claim by Leave is based on this study from the IEA which makes two assumptions: 1) That the UK would take the incredibly unlikely step of removing all barriers to trade with the rest of the world. 2) That the UK would abolish all EU environment and labour market regulations. You will not see that on Leave’s campaign posters.

Nor are British businesses “British businesses are drowning in EU red tape”. The UK is ranked is sixth by this survey by the World Bank for ‘ease of doing in business’. (Red tape, is any case a by-word for worker’s rights and environmental protection.)

It’s also worth pointing out that Norway and Switzerland (outside of the EU, but part of the European Economic Area) still have to pass substantial number of EU laws (and pay into the EU budget) to enjoy the common market. The difference is they have no say in those laws.

I’ll end this section on another claim that has been made by the Leave campaign, that the EU forces the UK to discriminate against non-EU workers. This is entirely false. It’s true that it’s easier to recruit people from within the EU but this is because there aren’t the barriers in place that they are for non-EU migrants (the very barriers they claim should be in place). Whatever checks or rules, or points system, the UK puts in place for non-EU migrants is entirely of the UK’s choosing. In deed, in 2010 the UK government made it harder for non-EU migrants to live and work in the UK. The result was a shortage in nursing staff, for which EU-migrants made up the shortfall. That was not the EU discriminating against non-EU, it was UK government policy.

In this respect, billionaire Dyson’s reasoning for leaving the EU is baffling. He claims:

“We’re not allowed to employ them, unless they’re from the EU. At the moment, if we want to hire a foreign engineer, it takes four-and-a-half months to go through the Home Office procedure. It’s crazy.”

His first statement is simply not true. However, he qualifies it in the second sentence to suggest that he is allowed to employ from outside the EU, it’s just harder. There are a number of reasons why his argument makes no sense. 1) The procedure for allocating visas to non-EU migrants is UK policy, not EU. Leaving the EU won’t improve that. 2) If anything, leaving the EU would increase the work-load of the Home Office in processing visas, causing further delays. 3) The EU allows Dyson to employ EU citizens without a “crazy” four-and-a-half month wait.

The Leave campaign have been consistently dishonest with voters, from the blatant “untruth” painted on their bus to the more subtle hint that a vote to leave would mean they could control immigration (but never, even when challenged, actually saying they will). They’ve brushed off legitimate concerns for the UK economy and it’s knock-on effect for our public services as ‘Project Fear’ while operating their own fear campaign that Britain is creaking at the seams, and it’s all due to migration. All the while, the largely Tory Leave campaign have been conning UK workers with false promises of being better off and urging an end to “red tape” while concealing from that that really means worker’s rights.

Front End Event Submissions

I’ve just announced another extension for Event Organiser: Event Organiser Frontend Submissions (or FES for short).

This plug-in allows you to create forms which allow users to submit their own events, which are then published (subsequent to admin moderation – if desired). It makes accepting user-contributed events much easier.

At the time of writing this plug-in is still in beta – but this is where you can help. I simply need people to use the plug-in, and report back with any issues they encounter. As a thank you, you’ll receive a free license key for when the plug-in goes on sale. This will entitle you to upgrades and support for an entire year.

Event Organiser FES is now available for purchase.

For more details, screenshots and to sign-up as a beta-tester, please see this page:

Grunt & WordPress development IV: Another task for internationalisation


This is part 4 in a series looking at using Grunt in WordPress plug-in/theme development.

  1. Grunt & WordPress development
  2. Grunt & WordPress development II: Installing Grunt
  3. Grunt & WordPress development III: Tasks for internationalisation
  4. Grunt & WordPress development IV: Another task for internationalisation

WordPress has recently (since 3.5) seen a shift towards a more JavaScript codebase. This shift is still minor (it currently accounts for less than 15%, according to its GitHub repository, in 3.9). But the introduction of Backbone.js and the re-factoring of particular the editor in the WordPress admin (media manager, shortcodes “objects” etc.) are testament to Matt Mullenweg’s comment:

I forgot to mention our biggest architectural change, which is already ongoing: an ever-increasing percentage of our codebase is shifting to Javascript instead of PHP. At some point I expect it to be the vast majority.

Matt Mullenweg,

However, a JavaScript codebase presents difficulties for WordPress in terms of internationalisation. I ran into this while working on Event Organiser Pro’s 1.7 release. This new release saw the booking form customiser rewritten to use Backbone. With so much JavaScript replacing PHP, there became a massive need to allow strings to be translatable (in a sane way).

Received wisdom is that you should use wp_localize_script() to allow strings in javascript files to be translated. Pippin covers the method excellently here but essentially when you enqueue your script you use wp_localize_script() to make a variable available which contains all you translated strings.

function my_load_scripts() {
    wp_enqueue_script( 'my-script', plugin_dir_url( __FILE__ ) . 'my-script.js');
    wp_localize_script('my-script', 'mynamespace', array(
         'helloworld' => __('Hello World', 'mydomain' )
add_action('wp_enqueue_scripts', 'my_load_scripts');

Then in your JavaScript file, instead of the string “Hello World” you would use mynamespace.helloworld. Although this method is common, there are a couple of things wrong with it when you pit it against some sort of gettext function:

It makes code harder to read. For me when reading code it’s much easier to see the actual text rather than a variable. (More so when reading other people’s code as this helps you link the sourcecode with what you actually see)

  alert( mynamespace.welcome_msg ); //ok
  alert( mynamespace.gettext( "Welcome to..." ) ); //better

At the very best its slightly more cryptic and uglier.

It makes it harder to maintain code. – When editing a JavaScript file, a gettext function allows me to edit the string there and then. If I use wp_localize_script(), I need to track down the .php file responsible for that and change it there – and then not forget that that string might have been used elsewhere.

It makes the translator’s job harder. – Hands up anyone who is very poor at providing translators with comments or providing a context when appropriate. Me at least. Regardless, .po files provide a line number so that, if necessary, translators can look up that line to get some sort of context for the string they are translating. It’s not very helpful when that line number points them to a large array in some obscure php file, rather than where the text is being used. Nor is it immediately obvious which JavaScript file(s) are using the string.

You may think that my reasons here are weak and pinnikity… and you might right… But I prefer using gettext-esque function for translating strings.

The problem(s)… (and how Grunt helps solve them)

There a couple of problems with using trying to use a gettext function in a JavaScript file, but they are all easily solved:

  1. There is no native gettext function
  2. How do you get the translations from .po to your JavaScript file
  3. How to get translatable strings from your JavaScript file to your .pot

There is no native gettext function in JavaScript

A very simple solution is to roll your own. Below are four functions which handle translatable strings, plurals and contexts. They all expect the translated strings to be found in mynamespace.locale.

mynamespace.gettext = function( msgid ){
    if( this.locale[msgid] !== undefined ){
        return this.locale[msgid];
    return msgid;

mynamespace.ngettext = function( msgid1, msgid2, n ){
    var key = ( n > 1 ? msgid1 + '_plural' : msgid1 );
    if( this.locale[key] !== undefined ){
        return this.locale[key];
    return ( n > 1 ? msgid2 : msgid1 );

mynamespace.pgettext = function( ctxt, msgid ){
    if( this.locale[msgid+'_'+ctxt] !== undefined ){
        return this.locale[msgid+'_'+ctxt];
    return msgid;

mynamespace.npgettext = function( ctxt, msgid1, msgid2, n ){
    var key = ( n > 1 ? msgid1 + '_' + ctxt + '_plural' : + '_' + ctxt + '_' + msgid1 );
    if( this.locale[key] !== undefined ){
        return this.locale[key];
    return ( n > 1 ? msgid2 : msgid1 );

You may have noticed that only one plural form is supported (so a string is either plural or singular), but some languages use more (and some less). There are ways around this, but the limitation is also a result of the Grunt task that’ll we’ll use later. Plural strings and strings with a context expect _plural and _{context} modifiers – I personally think this is less than ideal, but again is forced upon me by my choice of Grunt task. (This is just a start, and I’d like to see these limitations lifted).

Getting translations from .po to your JavaScript file

This is a two-step process:

  1. Use a Grunt task to generate a .json file for each .mo file
  2. Depending on the user’s choice of locale, load that .json file and use wp_localize_script() to make it available in you JavaScipt file.

I went with grunt-i18next-conv to generate the .json files. I found that converting .po to .json included untranslated strings, so I recommend you opt for converting .mo files to .json. (If you need a Grunt task for generating your .mo task, I recommend po2mo task I covered in my last article). It’s this task, by way of the format of the .json file it produces, that imposes some of the limitations already mentioned.

Next you, when enqueuing your JavaScript file, you use wp_localize_script() to ‘attach’ the relevant .json file to it. In the following I expect that the .json files are of the form /languages/mytextdomain-{locale}.json

 $locale = array();
 $file = plugin_dir_path( __FILE__ ) . 'languages/mytextdomain-'.get_locale().'.json';
 if( file_exists( file ) ){
      $locale = json_decode( file_get_contents( $file ), true );    

 wp_localize_script('my-script', 'mynamespace', array(
      'locale' => $locale

Getting the translatable strings from your JavaScript file to .pot

If you’re using grunt-pot this is easy. Simply include the functions above in the ‘keywords’ option:

  keywords: [ 

and ensure the files to search include your JavaScript file.


As discussed above there are currently two limitations:

  1. Poor support for plurals other than ‘single form plurals’
  2. Awkward ‘.json’ structure (not a massive issue…)

For the time being, however, and for use in Event Organiser’s booking form customiser, this method was ideal.

Get post content by ID

This post was originally published in November 2012, but was (accidentally) discarded during a migration. I used the wayback machine to retrieve the content and re-post it again.

As you may know the WordPress functions the_content() and get_the_content(), unlike their get_the_title() counterpart, cannot be used outside the loop. Naively ‘in the loop’ means just making sure the $post variable is global and points to the desired post.

So when someone asked why their code wasn’t working when they had used get_the_title() without passing it a post ID or declaring $post as global, the answer was simple.

What they said next threw me.

I find it extremely strange that the_content() works and that my $post variable is indeed an object full of data just like it should.

That is odd. But it turns out that get_the_content() doesn’t really use the $post global. Inspecting the source we see that it actually uses the $pages global. This stores the post’s content (pages as a post can carry across multiple pages). This is actually set up in: setup_postdata().

So while get_the_title() and co use the $post global, the_content() and get_the_content() rely on setup_postdata(). The upshot is that if using these outside the actual ‘Loop’ be sure to do both:

$posts = get_posts(array(...));
if( $posts ){
   foreach( $posts as $post ){
      global $post;

      //Use the template tags


Note, while setup_postdata() doesn’t set up the $post global, wp_reset_postdata() does reset it.

Then, while reading this post by Tom McFarlin I thought it might sometimes be useful to be able to retrieve post content by passing the post ID, the same way you can with get_the title()

Get The Content by ID

 * Display the post content. Optinally allows post ID to be passed
 * @uses the_content()
 * @param int $id Optional. Post ID.
 * @param string $more_link_text Optional. Content for when there is more text.
 * @param bool $stripteaser Optional. Strip teaser content before the more text. Default is false.
function sh_the_content_by_id( $post_id=0, $more_link_text = null, $stripteaser = false ){
    global $post;
    $post = &get_post($post_id);
    setup_postdata( $post, $more_link_text, $stripteaser );
    wp_reset_postdata( $post );

Example usage:


Grunt & WordPress development III: Tasks for internationalisation


This is part 3 in a series looking at using Grunt in WordPress plug-in/theme development.

  1. Grunt & WordPress development
  2. Grunt & WordPress development II: Installing Grunt
  3. Grunt & WordPress development III: Tasks for internationalisation
  4. Grunt & WordPress development IV: Another task for internationalisation

Internationalisation Tasks

One aspect of WordPress plug-in development that involves a lot of mundane work is that of internalisation: ensuring WordPress’ localisation functions are used correctly, generating a .pot file, compiling submitted .po files to .mo files. The latter two you can do with Poedit – but this still involves manually opening the .po/.pot file. These tasks can be completely automated so let’s do that:

po2mo – Compiling to .po files to .mo

The po2mo plug-in automatically compiles given .po files and produces a .mo file of the same name.

To install:

npm install grunt-po2mo --save-dev

<em>Please not an earlier version of this article executed the above as a super user (`sudo npm`). As pointed out by Lacy in the comments, this necessary and can cause permission issues with the npm cache.</em>

The following set up looks in the languages directory for any .po files and compiles them, creating the corresponding .mo in the same directory:

po2mo: {
    files: {
        src: 'languages/*.po',
        expand: true,

Finally load the task by adding grunt.loadNpmTasks('grunt-po2mo'); at the bottom of your Gruntfile.js, just after grunt.loadTasks('tasks');. Then whenever you add or change a .po file:

grunt po2mo

(You can see a live example of this task, and the others listed below, here.

pot – Create a .pot template file

For users to be able to translate your plug-in you’ll need to create a .po template file ( a .pot file). The pot plug-in does exactly that.

You just need to provide it with:

  • The files to search in,
  • The keywords to search for (and indicate which arguments are translatable strings, and which are context specifiers)
  • A text domain (used only for naming the the .pot file)
  • The directory where you wish to output the .pot file.

To install:

npm install grunt-pot --save-dev


pot: {
          text_domain: 'my-plugin', //Your text domain. Produces my-text-domain.pot
          dest: 'languages/', //directory to place the pot file
          keywords: [ //WordPress localisation functions
          src:  [ '**/*.php' ], //Parse all php files
          expand: true,

Finally load the task by adding grunt.loadNpmTasks('grunt-pot'); to the bottom. Then to generate your .pot file:

grunt pot

checktextdomain – Verify localisation functions have been used correctly

Having generated a .pot file, gathered translations for your plug-in and then compiled them – it would be entirely wasted if you haven’t used the WordPress localisations functions properly. In particular, if you had failed to specify the correct domain, your efforts would have been wasted.

When coding it’s easy to forget to specify a text domain, or to mistype it. Or perhaps you’ve been using a variable for the domain, and now want to switch to a literal string.

The checktextdomain – not only checks if you’ve used the correct textdomain in the localisation function it can also correct it for you.

Simply provide it with:

  • Files to look in,
  • Keywords to look for (important: you must provide a domain argument specifier)
  • A text-domain to check against
  • Whether you want mistakes corrected (it will not add missing domains… yet).

The plug-in will then

  • Warn you if some keywords have been used without a text domain
  • Warn you if some keywords have been used with an incorrect text domain (optionally correct it for you)
  • Warn you if some keywords have been used with a variable text domain (optionally correct it for you)

There are various options for this plug-in to enable you to check (and correct) the things you want to. You can see all the available options for this Grunt plug-in on its Github page.

To install:

npm install grunt-checktextdomain --save-dev

You’ll notice that the keywords option is very similar to grunt-pot. There is an important distinction. For this plug-in to work you must extend the keyword specifier and indicate where the domain should be.

E.g. 2d indicates that the domain should be passed as the second argument of the localisation function

checktextdomain: {
      text_domain: 'my-plugin',
      correct_domain: true, //Will correct missing/variable domains
      keywords: [ //WordPress localisation functions
   files: {
       src:  [ '**/*.php', ], //All php files
       expand: true,

Finally load the task by adding grunt.loadNpmTasks('grunt-checktextdomain'); to the bottom. Then to check your files:

grunt checktextdomain

I’m planning on improving this further to warn you of missing contexts which using functions that expect one.

Final remarks

Remembering to add grunt.loadNpmTasks(...); at the bottom of your Gruntfile.js, just after grunt.loadTasks('tasks'); is easily forgotten. But there’s a way around this which I’ll discuss in my next post.

Just before publishing Brady Vercher announced his Grunt plug-in, which allows you to utilize the internationalisation tools that WordPress uses. There’s a bit more set-up involved, but a notable advantage over grunt-pot is that it recognises theme template headers as translatable.

Grunt & WordPress development II: Installing Grunt


This is part 2 in a series looking at using Grunt in WordPress plug-in/theme development.

  1. Grunt & WordPress development
  2. Grunt & WordPress development II: Installing Grunt
  3. Grunt & WordPress development III: Tasks for internationalisation
  4. Grunt & WordPress development IV: Another task for internationalisation

1. Installing Node

Grunt runs on top of Node.js (version 0.8.0 or later). To check if you have Node installed (and what version), run

node --version

in your command line. If you don’t have it installed you’ll get an error message like “command not found”. If you have it installed, and an appropriate version, then you’re dandy and can skip to the next section.

Otherwise you can download node for your particular operating system here: Windows & Macs have their own installer, but if you can also install from source.

Installing Node for Linux

For Debian-based Linux distros (Debian, Ubuntu, Mint etc), first install the dependencies (you’ll probably have these)

  sudo apt-get install g++ curl libssl-dev apache2-utils

Install Git (again, you’ll probably have this)

  sudo apt-get install git-core

Clone the Node repository and run

  git clone git://
  cd node
  sudo make install

Finally to double check all went well:

  man node;

2. Installing NPM

NPM is the package manager for Node, and is used by grunt to install and manage plug-ins. This should come with Node, so you don’t have to worry about installing this.

3. Installing Grunt

First we want to install the grunt command line interface, and we want it to be globally available:

 npm install -g grunt-cli

This will put the grunt command in your system path, allowing it to be run from any directory.

This hasn’t installed Grunt (the task runner). In fact, you install grunt locally in each project you work on, allowing you to have multiple versions of Grunt on the same machine at once.

Grunt will be installed, alongside all the other plug-ins you list. Before they can be installed we need to prepare the package.json file:


Your package.json file should live in the root of your project. It provides details of your project & lists any dependencies for development (including Grunt!). You can then install these using NPM.

Here’s a minimal example which would install grunt, jshint and uglify

  "name": "my-project-name",
  "version": "0.1.0",
  "devDependencies": {
    "grunt": "~0.4.2",
    "grunt-contrib-jshint": "~0.6.3",
    "grunt-contrib-uglify": "~0.2.2"

(Note that if any of those plug-ins require another plug-in to function, that will also be installed).

So to finally to install Grunt and the other listed plug-ins:

sudo npm install

All going well, Grunt is now installed.

Once you’ve got a package.json set-up you can easily install additional plug-ins with

 sudo npm install [module] --save-dev

which will also automatically add the specified module to your package.json as a “devDependencies”.

4. Using Grunt

Once Grunt is installed we can prepare our first task. Your grunt tasks are declared and configured by your Gruntfile.js. This includes:

  • The “wrapper” function
  • Project and task configurations
  • Loading your Grunt plug-ins
  • Declaring default task(s) and custom tasks

If you’re getting lost at this point, don’t worry, a simple example will help. Don’t worry about the details too much – I’ll be covering that later in the series.

 module.exports = function(grunt) { //The wrapper function

 // Project configuration & task configuration
      pkg: grunt.file.readJSON('package.json'),

      //The uglify task and its configurations
      uglify: {
           options: {
                banner: '/*! <%= %> <%="yyyy-mm-dd") %> */\n'
           build: {
             files: [{
                expand: true,     // Enable dynamic expansion.
                src: ['js/*.js', '!js/*.min.js'], // Actual pattern(s) to match.
                ext: '.min.js',   // Dest filepaths will have this extension.

      //The jshint task and its configurations
     jshint: {
          all: [ 'js/*.js', '!js/*.min.js' ]


  //Loading the plug-ins

  // Default task(s), executed when you run 'grunt'
  grunt.registerTask('default', ['uglify']);

  //Creating a custom task
  grunt.registerTask('test', [ 'jshint' ] );


In that example our ‘test’ task triggers the jshint task, but it could trigger additional tasks such as unit testing tasks too (if we had that installed).

You’re done and ready to go:


will execute your default task, and

grunt test

will execute your ‘test’ task(s).

Real world example?

Feel free to checkout for a real-world example of Grunt used in development.

What’s next?

In the next few posts I’ll be going through my particular set-up for WordPress plug-in (& theme) development: the plug-ins I use, their configurations and the tasks I have set-up.

Grunt & WordPress development


This is the first post of a five part series looking at WordPress plug-in/theme development with Grunt.

  1. Grunt & WordPress development
  2. Grunt & WordPress development II: Installing Grunt
  3. Grunt & WordPress development III: Tasks for internationalisation
  4. Grunt & WordPress development IV: Another task for internationalisation

Back in August the WordPress core team announced they were going to use Grunt in WordPress’ development. This in my view is a major stride forward for WordPress (more so than the much celebrated ‘features as plug-ins’ – which itself marked an improvement to WordPress’ development cycle).

This series of articles however, will be focussed on using Grunt for WordPress plug-ins and themes (which are fundamentally the same thing), and the tasks I use in development. In this first post I’ll discuss the what and the whys:

What is Grunt?

Grunt is a javascript based task runner from Ben Alman. It performs repetitive task such as compression, unit testing, linting, concatenation, preprocessing etc. Almost any task in the development, building or deployment of your WordPress plug-in which can be automated can be performed by Grunt – freeing you from those tedious, and potentially human-error-prone routines.

(Once Grunt is installed) there are two files which set up Grunt for use in your project:

  • package.json – which details your project (in this case: a WordPress plug-in) and it’s dependencies (in this context, Grunt and any Grunt plug-ins you want to use).
  • Gruntfile.js – listing the tasks you wish to perform and their configuration

Those tasks can be executed simply by running

 grunt [task name] 

in your command line. You’ll probably have multiple tasks that you’d want to run one after than other (e.g. one task to copy/generate files from your development environment to a build directory, and another to upload that directory to an Amazon S3 server). Instead of calling each manually Grunt allows you to create tasks which simply call a collection of other tasks. For example

 grunt test

might be configured to trigger unit-test and linting tasks.

Why Grunt?

The idea of automating deployments, unit testing, compressing images, scripts & stylesheets and other tasks you may wish to perform in your plug-in’s development, build and release cycle is certainly not unique to Grunt. Before I switched to Grunt I had a home-grown Makefile to perform a lot of my routine tasks.

Grunt however, brings this all under one roof: giving a familiar command line procedure to execute task(s). Importantly it allows (Grunt) plug-ins, and their end-users to add structure to their tasks. By this I mean tasks being able to call other tasks, being able to initiate an entire list of tasks, being able to configure all your tasks in only one file and easy of portability. In fact, if you download a development repository for a plug-in which includes the package.json and Gruntfile.js files, in one command you can install all the Grunt plug-ins it requires for use in testing, building and deploying that plug-in. (This assumes you have Node.js installed, which I’ll cover in part two).

Grunt doesn’t offer much new – but it does offer a much better solution.

It’s also popular – and popularity is key for any library, platform or tool to succeed and to grow. Popularity brings greater number of developers, they drive the growth of plug-ins & features and the increased functionality drives popularity. (Perhaps not dissimilar to WordPress’ own growth). Grunt’s ecosystem is already very substantial: there’s phpunit for PHP unit testing, jshint for Javascript linting, there is uglifyjs for compressing javascript files and imagemin to optimise images.

The point is: it has a large, and growing ecosystem. In the majority cases, for any task you might want to perform, there will exist a grunt plug-in to perform it.

And if there isn’t? Grunt is incredibly well documented, open-source and easy to dive into. If you find a gap in its armoury, the chances are it’s easy enough to fill.

What’s next?

If you weren’t already sold on Grunt, hopefully that will do it. The next post will be on installing Grunt and executing your first task.

Front End Event Posting

Update: 2nd August 2014: The front-end submissions extension is now available for purchase.

Update: 2nd July 2014: An extension is now available for beta testing, which allows you to accept and moderate front-end submissions of events. For more details, see By comparison, this article is very limited in scope and for those who wish to implement something a bit more bespoke themselves.

One of the features for Event Organiser that has been requested a few times is that of ‘front-end’ event posting. People want their users to be able create events on the front-end. While this won’t make it into the core of the plug-in (since everyone will want it to work slightly differently) – it’s very easy to implement this yourself, as Event Organiser provides some very simple functions for creating and manipulating the events. In this post, I’m going to give a basic example of how you could implement front-end posting: feel free to edit it to your needs…

Front-end event (like post) creation is essentially a two step process:

  1. Create form to collect data
  2. Collect that data and use it create an event

You might want to implement a ‘success page’ that you redirect to afterwards, or return users to the form which errors highlighted, but at its core you just have two steps.

(Those who just want the entire source code, see this Gist).

Step 1: The form

In this post I’m going to create a shortcode to produce the form – this can then be used on an page or post (or event!).

Creating a shortcode is very easy, the following will create a shortcode [my_event_form] that will output a form only if the user is logged in (once its finished!). I strongly recommend not allowing logged-out users to create events.


function my_event_form_shortcode_handler( ){

    if( !is_user_logged_in() ){
        return '<p> Only logged in users can post events </p>'; 

     //Return form HTML mark-up
     return $html;

Now we just need to produce the HTML form mark-up. The rest of this step shows how to generate the HTML, and goes just above the comment //Return form HTML mark-up.

The following creates a nonce for the form and a hidden field which will use so we know what to do with the data sent.

$html = '<form method="POST">';

//Create hidden 'action' field and corresponding nonce
$html .= '<input type="hidden"  name="my-action" value="post-event" >';
$html .=wp_nonce_field( 'post-event', '_mynonce',false,false);

Next we produce some input forms. Let’s start with an event title and description:

//Event Title
$html .= sprintf('<p><label for="my-frontend-event-%1$s"> %2$s
            <input type="text" name="my_frontend_event[%1$s]" id="my-frontend-event-%1$s" >
        'Event Title'

//Event Description
$html .= sprintf('<p><label for="my-frontend-event-%1$s"> %2$s
            <textarea name="my_frontend_event[%1$s]" id="my-frontend-event-%1$s"></textarea>
        'Event Description'

Now we’ll add in fields for the start and end date (you can also add fields to specify a start and end time, but in this example I’ll just be creating all day events).

//Start date
$html .= sprintf('<p><label for="my-frontend-event-%1$s"> %2$s
            <input type="text" name="my_frontend_event[%1$s]" id="my-frontend-event-%1$s" class="my-frontend-event-datepicker" >
        'Start Date'

//End date
$html .= sprintf('<p><label for="my-frontend-event-%1$s"> %2$s
            <input type="text" name="my_frontend_event[%1$s]" id="my-frontend-event-%1$s" class="my-frontend-event-datepicker" >
        'End Date'

Next we’ll create a drop-down menu so users can select a venue. Venues are just taxonomy terms (of the event-venue taxonomy), so we’ll make use of the WordPress function wp_dropdown_categories

$html .= sprintf('<p><label for="my-frontend-event-%1$s"> %2$s %3$s </label></p>',
                'orderby'      => 'ID', 
                'order'        => 'ASC',
                'hide_empty'   => 0, 
                'echo'         => 0,
                'id'           => 'my-frontend-event-venue',
                'name'         => 'my_frontend_event[venue]',
                'taxonomy'     => 'event-venue'

We’ll also add a checkbox list for event categories. Again event categories are just taxonomy terms (this time of the event-category taxonomy).

//Category - checklist
$cats = get_terms('event-category',array('hide_empty'=>0));
if( $cats ){
    $html .= '<p><label for="my-frontend-event-category">Category <ul>';
    foreach ( $cats as $cat ){
        $html .= sprintf('<li><label>
                         <input type="checkbox" name="my_frontend_event[%1$s][]" value="%2$s">
    $html .= '</label></p>';

Finally we end the form with a submit button:

//The post button
$html .= '<p><input name="submit" type="submit" id="submit" value="Post Event"></p>';

$html .='</form>';

Step 2: Processing the data

The form should now render and post the data – but we’ll need to get hold of that data and do something with it. We’ll hook onto the init action, and check to see if our custom ‘action’ variable is set. If not, we don’t do anything.


function my_frontend_event_post_listner(){

    if( !isset($_POST['my-action']) || 'post-event' != $_POST['my-action'] )

    //Collect raw input
    $input = $_POST['my_frontend_event'];

    //Do something with the input


Before we do anything with the data we need to perform a few checks:

  • Is the user allowed to create events (in this example, only logged-in users can create events – you might want to perform other checks)
  • Did the users intended to post the form? (This is what the nonce are for?)
  • Is the data as you expect it? (This is called sanitisation, I’ve omitted it here. Its less of a security matter, and more of making sure that the data you using to create the event, makes sense).

For example:

//Check user is logged in:  
if( !is_user_logged_in() )  

//Check nonce  
check_admin_referer( 'post-event', '_mynonce');

*   IMPORTANT: Perform any other checks you need to here (e.g. should only users with a certain capability be able to post events?)  

To create the event we are going to use the plug-in provided function eo_insert_event(). This accepts two arrays: the first concerns ‘post data’ and is passed to wp_insert_post() (so it accepts anything that wp_insert_post() does. The second is for event data – and that is explained below.

First, collecting the post data (which includes an array of term IDs for the event-category and event-venue taxonomies – the latter should only contain one ID).

 * Set the post data (see
 * This includes event-category and event-venue (taxonomy terms)
//Event venue is just an ID
$event_venue = isset($input['venue']) ? (int) $input['venue'] : 0;

//Event cats are an array of IDs
$event_cats = !empty( $input['category'] ) ? $input['category'] : array();
$event_cats = array_map( 'intval', $event_cats );

$post_data =array(

Next the event data. For this function, any dates must be passed as DateTime objects. The easiest way to do this is to collect the date as string, $datestring, in Y-m-d format (or Y-m-d H:i format to specify a time too) and use

 new DateTime($datestring) 

The timezone will be UTC unless you specify otherwise, so its recommended you use eo_get_bog_timezone() for your blogs current timezone. See full documentation of this function.

 * Set the event data
//Start and end dates need to be given as DateTime objects (timezone is UTC unless a timezone is given)
$start = new DateTime($input['startdate'],eo_get_blog_timezone());
$end = new DateTime($input['enddate'],eo_get_blog_timezone());
$event_data =array(
    'schedule' =>'once',  //specifies the reoccurrence pattern
    'all_day' =>  1, //1 if its an all day event, 0 if not - if not you'll need to specify a start/end time for the DateTimeobjects
    'start' =>  $start, //start date (of first occurrence)  as a datetime object
    'end' => $end,  //end date (of first occurrence)  as a datetime object

Finally create the event!

//Finally, Insert event.
$post_id = eo_insert_event($post_data,$event_data);

The code in its entirety can be found at this Gist.

Good Business Ethics

Good Business Ethics

Tired of the Woo drama? Then skip to this section.

Earlier this month WooThemes announced a price increase. For this they have been praised by some for ensuring “their sustainability” and “that their lifetime will be much longer than it would have been just days ago”. Some very high profile and well-respected developers also came out in support, to name but a few Carl Hanock,

Brian Krogsgard and Pippin Williamson (albeit with some reservations about how it was handled).

However the changes caused a furore among a vast majority of their customer base. While some were angered by the perceived opportunism, the main focus of customers’ anger was towards the following paragraph in WooThemes’ announcement:

Any purchase made before today will be grandfather-ed into the new system with access to support and updates for 2 years. All theme purchases will also now have a license, which you’ll be able to use with the WooThemes Updater once all themes have been updated.

That is the changes would be applied retrospectively: customers who had purchased a product (license) with the understanding it was unlimited with regard to both sites and duration were told that this would no longer be the case. This is compounded by the fact that the in the month preceding their changes, WooThemes ran a sale – pushing sales with conditions that would abruptly change.

As noted, however, there were some who backed the changes, pointing to the fact that if WooThemes didn’t survive, then the licenses would die anyway along with their product, and possibly even parent company. However, this potentially illegal1 and highly unpopular move forced caused such a stir that it forced WooThemes to backtrack and give customers the option of moving back to the terms they had agreed to.

Even then, you have to opt out of the new license conditions, which is dubious to say the least.

… but haven’t they got a point? What Carl says is entirely true:

A lot of businesses, making a lot of money (so we’re told) rely on WooThemes to exist and continue to provide updates and support for their products. But here’s my point: when a customer makes a purchase from you, it’s a promise. The customer pays you money, and in return you provide them the product, and any promises of updates and support that went with that purchase. In legal terms, it’s a contract.

If you’ve promised more than you can provide, then the company must bear the cost of that. The customer cannot be penalised for the mistakes the company made – that’s good business ethics.

Good Business Ethics

But I don’t want this article to be focussing on the bad. Because, at around the same time another WordPress company realised that their current business model wasn’t working. Like WooThemes they too had offered liftetime support and updates, and like WooThemes they realised that this wasn’t sustainable and needed to change. In fact, this change was the third in one year. The man behind this business admitted his mistakes, and corrected them without punishing existing customers.

In fact he went one step further. He even gave existing customers – regardless of which model was in use when they purchased the product – lifetime updates and support.

The company is Thomas Griffin Media, and the founder Thomas Griffin and the product, Soliloquy.

Thomas has written up an excellent summary of the four business models he experimented with, along with the reasoning behind the one he’s chosen to stick with. It’s an insightful analysis, but more importantly it’s a demonstration of how businesses can do the right thing.

At the heart of any business, including WooThemes, are people – who, like everyone, are prone to making mistakes. We need to bear that in mind, and have grace for that, and resist temptation to consider them faceless entities whose sole intention is to extract money from us. And it has been good to see – as I’m sure Adii will appreciate – customers stating they would be willing to pay more to see the business thrive.

But businesses though must recognise that their promises need to mean something and that they should, at the very least, treat customers fairly and honour the commitments they make. The burden of doing that cannot be imposed upon the customer.

As consumers in a relatively young, albeit fast growing, marketplace we have the opportunity to define the characteristics we want to see in businesses. Do we value low cost, or high quality products? Do we value established brands, or indie developers? Do we value profit-driven businesses, which are able to grow and invest? Personally, I think we should be encouraging characteristics such integrity, transparency and honesty in our businesses. These are not white elephants. They can be found in businesses of all sizes. And I urge you to promote such businesses.

  1. In UK law there is enough to suggest that courts would deem this ‘unfair’ and so illegal.‎. But it’s really South African Law that applies here. Nevertheless, I would be willing to bet it is in fact illegal.