Tag: php


WooCommerce: Purchase Order Payment Gateway

Update: Version 1.1 released on 26th August 2018, on the plugin repository. See changelog on the plugin repository for more information.

A recent project required the ability for customers on a client’s WooCommerce website to be able to request an invoice for their order (and thus pay offline) – but with the added twist that it required a Purchase Order number. This twist meant that simply changing the name of WooCommerce’s built-in “Offline” gateway was not enough.

I had a quick look around and found an existing plugin for WooCommerce that added this functionality, but as seems to be common when I do this, the functionality left a little bit to be desired.

First of all, the plugin required the customer to enter a postal address for the invoice (and curiously, didn’t automatically pull through the customer’s billing address) – I only needed a Purchase Order number field.

Additionally, it wasn’t very well internationalised – some strings were set as translated, but others – particularly in the HTML output that the plugin generated on the front-end and the admin back-end, were not.

So, I’ve taken it upon myself to learn a bit more about WooCommerce’s Payment Gateway API, and have written my own – which you can download below.

Plugin Features

  • Adds an offline payment gateway for WooCommerce with the name Purchase Order
  • Allows the administrator to set the plugin to ask for a Purchase Order number (or not) – and whether to make it mandatory if one is asked for
  • Has a setting that gets the plugin to ask for a postal address for the invoice to be sent to
  • Has another setting that, if an address is being asked for, will pre-fill the address with the customer’s billing address if they are logged in to WooCommerce during checkout
  • Adds the submitted Purchase Order details to the Edit Order screen in the WooCommerce back-end
  • Has full internationalisation (i18n) and localisation (l10n) support – so if you want to translate the plugin into your own language, please get in touch!


The gateway itself looks very straightforward – the screenshot below has the “ask for address” options turned off, though. When turned on, the plugin asks for a Contact Name, Company/Organisation, and an address (two lines, plus city, county and postcode).

In the WordPress back-end, Purchase Order information is shown under the General Details section on the Edit Order screen:


As with all WordPress plugins, you just need to drop the plugin folder into your wp-content/plugins folder and then activate the “GazChap’s WooCommerce Purchase Order Payment Gateway” plugin.


I’m using WordPress 4.9.4 and WooCommerce 3.2.6 – please let me know in the comments if it doesn’t work on other versions. I believe it requires at least WooCommerce 3.0.0.


Download the plugin from the WordPress Plugin Repository (5.2KiB Zip)


This plugin is open-source – view the source code on the GitHub repository.


How to enable checkbox lists for non-hierarchical taxonomies in WordPress

WordPress’ taxonomy features are one of the most powerful aspects of the platform, giving you the capabilities to group posts (including custom post types) in pretty much as many ways as you can think of.

There are two types of WordPress taxonomy – hierarchical and non-hierarchical. In case it’s not obvious from the name, a hierarchical taxonomy has a hierarchy – that is, you can create terms that are children of a parent term (and even children of those children) – standard post categories in WordPress are an “out of the box” example of a hierarchical taxonomy.

A non-hierarchical taxonomy has no parent/child structure, and is basically just a “flat” list of terms. Post tags are the “out of the box” example here.

When you’re developing a plugin for WordPress (or maybe even a theme) you may find that you have a need to create custom taxonomies – for example, if creating a plugin for a property/real estate website, you may have a custom taxonomy for “Property Type”, that contains terms like “House”, “Apartment” etc.

It’s at this point that you may run into a bit of an annoyance with the default WordPress user interface:

A comparison between the default WordPress user interface for hierarchical and non-hierarchical taxonomies

The example given above (Property Type) is non-hierarchical. By default, this means that an administrator creating or editing a new post with that taxonomy needs to manually type in the relevant Property Type(s) in the box and wait for it to auto-complete, or click the “choose from the most used” option and hope that the ones they want are in there.

It makes a lot more sense, in some circumstances at least, for non-hierarchical taxonomies to also use the same “checkbox list” user interface used for hierarchical taxonomies, as shown above. This way, the user is presented with a list of all of the available options without having to recall them from memory, and can still add new ones if necessary.

The good news is, that starting from WordPress 3.7 (which was released quite a while ago, at the time of writing WordPress is at version 4.9), it’s possible to tell WordPress to use the checkbox UI for non-hierarchical taxonomies – with a caveat.

Let’s continue with the Property Type example. Here’s our (basic) code for registering the custom taxonomy for it:

add_action( 'init', 'create_property_type_taxonomy' );

function create_property_type_taxonomy() {
        'propertytype', // the slug for the new taxonomy
        'property', // the slug of the custom post type that this taxonomy applies to
            'label' => __( 'Type' ),
            'rewrite' => array( 'slug' => 'property-type' ),
            'hierarchical' => false,

This creates a non-hierarchical taxonomy, with the default UI as shown above. To switch the UI over to the checkbox style above, we just need one more line:

add_action( 'init', 'create_property_type_taxonomy' );

function create_property_type_taxonomy() {
        'propertytype', // the slug for the new taxonomy
        'property', // the slug of the custom post type that this taxonomy applies to
            'label' => __( 'Type' ),
            'rewrite' => array( 'slug' => 'property-type' ),
            'hierarchical' => false,

            'meta_box_cb' => 'post_categories_meta_box',

The newly-added meta_box_cb argument tells WordPress which function to use to generate the meta box for displaying the taxonomy on the post edit screen. You could use this to create your own meta box style, but here we are just telling it to use the existing post_categories_meta_box function, which is what displays the checkbox style UI for hierarchical taxonomies.

So, all good, right?

No, not quite. Even though our taxonomy is non-hierarchical, if the user selects the “Add new” option, they are shown the box to add in a new term, but also a drop-down select menu for choosing the parent for this new term. If the user selects a parent, WordPress will add the new term as a child of that parent, but because the taxonomy is non-hierarchical it will not be selectable, either with the checkboxes or with the default UI.

You could just tell your users not to select a parent, but a good UI will not give the user options that they shouldn’t use, so we need to remove that parent menu.

Fortunately, version 4.4 of WordPress introduced a filter – post_edit_category_parent_dropdown_args – that could be used to control the parent terms shown in these meta boxes. It’s designed to let the developer change the terms listed, for example excluding certain categories, or only showing “top level” parent terms and not their descendants. There is no control that is designed to stop the menu being shown at all, but there is one that allows us to trick WordPress into hiding the parent drop-down select.

Here’s the filter that you need:

add_filter( 'post_edit_category_parent_dropdown_args', 'hide_parent_dropdown_select' );

function hide_parent_dropdown_select( $args ) {
    if ( 'propertytype' == $args['taxonomy'] ) {
        $args['echo'] = false;
    return $args;

Why does this work? The echo argument is set to true by default, and makes WordPress echo the dropdown select into the meta box. By setting this to false, WordPress instead returns the HTML instead, so it doesn’t get rendered to the browser.

You’ll also notice that I’ve added a check into the filter that makes sure we’re only doing this for the ‘propertytype’ taxonomy – we don’t want this filter to remove the parent dropdown selector from all of the hierarchical taxonomies after all!

Update: Converting term IDs to term names

Something that I hadn’t banked on when I created this post originally was that, when sending the selected terms back to WordPress from the post editing screens, hierarchical taxonomies send them each term’s ID, whereas non-hierarchical taxonomies send the term names instead.

Because we’re now using the hierarchical UI for our non-hierarchical taxonomy, WordPress receives the term ID (as a string) and creates a new term with the ID as the name, losing the relationship with the original term in the process. Sounds confusing, and is.

To get around this, we need to take these ID strings and convert them to integers. To do this, we just need to hook into the admin_init action hook and convert them:

add_action( 'admin_init', 'convert_taxonomy_terms_to_integers' );

function convert_taxonomy_terms_to_integers() {
    $taxonomy = 'propertytype';
    if ( isset( $_POST['tax_input'][ $taxonomy ] ) && is_array( $_POST['tax_input'][ $taxonomy ] ) ) {
        $terms = $_POST['tax_input'][ $taxonomy ];
        $new_terms = array_map( 'intval', $terms );
        $_POST['tax_input'][ $taxonomy ] = $new_terms;

And there you have it, all done. If you found this helpful, please let me know in the comments below.