Most of you will have heard about WooCommerce extensions by now, and WooCommerce sure is great for extending because it has loads of hooks and filters to play with, but in truth you can extend any WordPress plugin in pretty much any way you want and without touching any of the plugin files.

Here is my personal choice on how to do this, along with some handy hints on getting around the problem of not having the right hook in place etc.

I have a template which I call a boilerplate, which I will embed below:

So the first thing to do is change all instances of PB to the name of the plugin you are creating, which, as it is an extension, should probably be the name of the original plugin plus something unique to your extension - possibly what it does. I once built an extension to the events manager plugin that allowed the site owner to pay commission to those who posted events - I called it Events Manager Commissions (events-manager-commissions).

If you do a find/replace for PB to Events Manager Commissions you are good to go except for the classname is no good, so it is better to do find replace for PB to Events_Manager_Commissions and then you only have the Plugin Name (in the top comments) to change from Events_Manager_Commissions to Events Manager Commissions and bobs your uncle.

Now on to the actual meat of the boilerplate, as I said I like to go for a class based approach (OOP) because it is easier to store data and to pass it around. We already changed the name of our class to Events_Manager_Commissions and so we just need to instantiate it. Now in some cases, if you rely on other classes you may have to hook into the plugins_loaded hook and instantiate the class there, but in most cases you can just go ahead and do it either above the class declaration or below. I always go for above:

global $PB;
$PB = new PB;

This instantiates the class and stores it to global as well. We could do this in one line

$GLOBALS[‘pb’] = new PB;

Now if we go into the class we first declare 2 very important variables we need in the plugin:

private $textdomain = "pb";
private $required_plugins = array();

The first one is the textdomain for i18n translation functions - you can change it to something more in line with the plugin name, or leave it as is. The next one is rather more important, because it can literally stop your plugin from being run. You insert into this array the required plugins for this extension. Following the examples we would make it private

$required_plugins = array(‘events-manager’,’events-manager-pro’);

And then the first function in the class checks that those plugins are active. See my last post for more on that function. Now on to the main function not only for this class (practically every class actually), but for my entire method of extending plugins…

function __construct() {
        if (!$this->have_required_plugins())
        load_plugin_textdomain($this->textdomain, false, dirname(plugin_basename(__FILE__)) . '/languages');

So here we call up our check for required plugins and exit (return;) if we don’t have them then we load the plugin textdomain up for the language related functions. Nothing spectacular there, but this is the main function because it is called automatically when the class is instantiated, and that means we can use it as an easy and central place to connect to any hooks we may need to.

Here is the __contstruct function from a recent Woocommece

function __construct() {
        if (!$this->have_required_plugins())
        $this->box_created = false;
        add_filter('woocommerce_subscription_settings', array($this, 'set_sub_product_settings'));
        add_action('admin_notices', array($this, 'need_box_product'));
        /* New */
        add_action('woocommerce_add_to_cart', array($this, 'sort_items'), 100, 6);
        add_filter('woocommerce_cart_item_price_html', array($this, 'add_per_month'), 100, 3);
        add_filter('woocommerce_cart_item_subtotal', array($this, 'add_per_month'), 100, 3);
        add_filter('woocommerce_create_order', array($this, 'prepare_pak'), 1000, 2);
        /* ENDS */


So you see that framework gives you a simple and central place from where you can hook into everything and anything you need to: multiple plugins, theme, enqueue styles and scripts anything all in one place. I am not saying it is perfect but for me it allows me to make extensions to any plugin very easily.

Dash I am already over 700 words and I haven’t covered anything about what to do if you don’t have a hook where you need it. Sure, you can add a hook and contact the plugin devs about adding it to the next release but more often than not a workaround can be found. Please comment if you are stuck in such a situation and I will make a post on that very subject for next week. If you liked this post and want to hear more tips and posts from me please like and share - thanks a million.