Introduction to Oempro plugin development

Oempro is a highly flexible, customisable email marketing software. It already comes with 99% source code open. But many of us hate touching the code for two reasons:

  1. Customizing the code may cause problems when upgrading the version
  2. and it may cause some bugs

Therefore, writing a plug-in is always a better way. Oempro includes a plug-in engine which lets you to integrate your own custom scripts and apps easily.

Currently, Oempro includes 40+ hooks which you can integrate your plugin. The list of available plugin hooks can be found here:

http://octeth.com/oempro/docs/developers/plugins/#section-13

In this post, we will be writing a simple Oempro plugin which will verify the email content for specific words and remove them from the email content.

Every plugin in Oempro has its own directory under [oempro_install_path]/plugins/. Therefore, in order to create a new plug-in, first we must create a directory inside plugins directory. For this example, we will name our plugin directory as “email_content_verifier”. So, let’s proceed and create the directory:

mkdir [oempro_install_path]/plugins/email_content_verifier

Inside the “email_content_verifier” directory, create the initial PHP script with the same name:

[oempro_install_path]/plugins/email_content_verifier/email_content_verifier.php

The plugin reference PHP script is mandatory and should have the same name with the plugin directory. There are also some required coding structures for this PHP script.

First of all, after the <?php tag, you must include the following comment lines to identify your plugin. Here’s the first 7 lines for our example plugin:

<?php
/**
* Email Content Verifier
* Name: Email Content Verifier
* Description: This plugin checks the email content and removes unwanted words
* Minimum Oempro Version: 4.4.0
*/

The Oempro plugin must be a class. Therefore, we will be creating our plugin class now:

class email_content_verifier extends Plugins
{
	function __construct() 
	{
	}
}

As you can see above, we have our main class structure for the plugin ready. There are pre-defined methods which are called on certain situations:

  • enable_email_content_verifier()
    This method is called when you (administrator) enables the plugin in Oempro admin area > plugin management section. This is the right method where you install plugin specific MySQL tables, perform installation, etc.
  • disable_email_content_verifier()
    This method is called when you (administrator) disable the plugin in Oempro admin area > plugin management section. Use this method to uninstall plug-in specific MySQL tables, remove files, etc.
  • load_email_content_verifier()
    This method is called once the plugin is loaded. It’s used for initiating the plugin, registering hooks, etc.

Here’s the example:

class email_content_verifier extends Plugins
{
	function __construct() 
	{
	}

	function enable_email_content_verifier()
	{
	// Plugin is enabled. Perform plugin 
	// related installation processes
	}

	function disable_email_content_verifier()
	{
	// Plugin is disabled. Perform plugin 
	// related removal process
	}

	function load_email_content_verifier()
	{
	// Plugin is being loaded. Initiate plugin 
	// variables, register hooks, etc.
	}
}

┬áReady to use “option” method calls

If you want to store small data about your plugin, such as preferences, you can use Oempro’s built-in option system. There are three method calls ready to be used in your plugin:

  • Database::$Interface->SaveOption(‘key’, ‘value’);
    Saves the value pointing to the key
  • Database::$Interface->RemoveOption(‘key’);
    Removes the key from Oempro option database
  • Database::$Interface->GetOption(‘key’);
    Gets the value of the key

Let’s say that you want to store the list of forbidden words which will be removed from email content. We can do this like the one shown below:

class email_content_verifier extends Plugins
{
	private static $ForbiddenWords = array();

	function __construct() 
	{
	}

	function enable_email_content_verifier()
	{
	// Plugin is enabled. Perform plugin 
	// related installation processes

	// Save forbidden words to Oempro options table
	Database::$Interface->SaveOption('EmailContentVerifier_ForbiddenWords', serialize(array('word1', 'word2', 'word3', 'word4')));
	}

	function disable_email_content_verifier()
	{
	// Plugin is disabled. Perform plugin 
	// related removal process

	// Remove the forbidden words from Oempro options table
	Database::$Interface->RemoveOption('EmailContentVerifier_ForbiddenWords');
	}

	function load_email_content_verifier()
	{
	// Plugin is being loaded. Initiate plugin 
	// variables, register hooks, etc.

	// Load the forbidden words and assign them to a property
	self::ForbiddenWords = Database::$Interface->GetOption('EmailContentVerifier_ForbiddenWords');
	self::ForbiddenWords = unserialize(self::ForbiddenWords[0]['OptionValue']);
	}
}

Registering plugin enable/disable functions

In order to trigger plugin enable and disable functions, you need to set hooks to the following listeners:

parent::RegisterEnableHook('email_content_verifier');
parent::RegisterDisableHook('email_content_verifier');

We strongly recommend you to set hooks inside the plugin loader method as displayed below:

	function load_email_content_verifier()
	{
	// Plugin is being loaded. Initiate plugin 
	// variables, register hooks, etc.

	// Set hooks
	parent::RegisterEnableHook('email_content_verifier');
	parent::RegisterDisableHook('email_content_verifier');

	// Load the forbidden words and assign them to a property
	self::ForbiddenWords = Database::$Interface->GetOption('EmailContentVerifier_ForbiddenWords');
	self::ForbiddenWords = unserialize(self::ForbiddenWords[0]['OptionValue']);
	}

Registering required hooks to filter email contents

In order to manipulate the process of Oempro, you need to set hooks to specific listeners. There are two listener types:

  • Actions
    Hooks executed on actions may affect the process, such as pausing an email delivery or cancelling list create process
  • Filters
    Hooks executed on filters may only change inputs, such as changing the email content or email subject

For this plugin, we need to monitor email content and filter it against forbidden words. The listener we need to hook is:

Email.Send.Before

Now simply register the hook for this listener:

	function load_email_content_verifier()
	{
	// Plugin is being loaded. Initiate plugin 
	// variables, register hooks, etc.

	// Set hooks
	parent::RegisterEnableHook('email_content_verifier');
	parent::RegisterDisableHook('email_content_verifier');
	parent::RegisterHook('Filter', 'Email.Send.Before', 'email_content_verifier', 'FilterContent', 10, 4);

	// Load the forbidden words and assign them to a property
	self::ForbiddenWords = Database::$Interface->GetOption('EmailContentVerifier_ForbiddenWords');
	self::ForbiddenWords = unserialize(self::ForbiddenWords[0]['OptionValue']);
	}

	// This is the function which will be executed by Email.Send.Before listener
	// Please note that the number of variables should be equal to the number
	// of variables listed on listener page:
	// http://octeth.com/oempro/docs/developers/plugins/hooks/email.send.before/
	// 
	// The return variable should be array and values should be in the same order
	function FilterContent($Subject, $HTMLBody, $PlainBody, $Subscriber)
	{
	foreach (self::ForbiddenWords as $ForbiddenWord)
		{
		$Subject = preg_replace('/'.preg_quote($ForbiddenWord).'/i', ' ', $Subject);
		$HTMLBody = preg_replace('/'.preg_quote($ForbiddenWord).'/i', ' ', $HTMLBody);
		$PlainBody = preg_replace('/'.preg_quote($ForbiddenWord).'/i', ' ', $PlainBody);
		}
	return array($Subject, $HTMLBody, $PlainBody, $Subscriber);
	}

Activating the plugin

Once your plugin is ready, you need to activate it:

  1. Login to Oempro admin area
  2. Click “Settings” on the top menu
  3. Click “Plugins” menu on the sidebar
  4. Click “Enable” link next to your plugin

That’s all. Your plugin is now activated and it will be monitoring email contents.

The complete source code

<?php
/**
* Email Content Verifier
* Name: Email Content Verifier
* Description: This plugin checks the email content and removes unwanted words
* Minimum Oempro Version: 4.4.0
*/
class email_content_verifier extends Plugins
{
	private static $ForbiddenWords = array();

	function __construct() 
	{
	}

	function enable_email_content_verifier()
	{
		// Plugin is enabled. Perform plugin 
		// related installation processes

		// Save forbidden words to Oempro options table
		Database::$Interface-&gt;SaveOption(&#039;EmailContentVerifier_ForbiddenWords&#039;, serialize(array(&#039;word1&#039;, &#039;word2&#039;, &#039;word3&#039;, &#039;word4&#039;)));
	}

	function disable_email_content_verifier()
	{
		// Plugin is disabled. Perform plugin 
		// related removal process

		// Remove the forbidden words from Oempro options table
		Database::$Interface-&gt;RemoveOption(&#039;EmailContentVerifier_ForbiddenWords&#039;);
	}

	function load_email_content_verifier()
	{
		// Plugin is being loaded. Initiate plugin 
		// variables, register hooks, etc.

		// Set hooks
		parent::RegisterEnableHook(&#039;email_content_verifier&#039;);
		parent::RegisterDisableHook(&#039;email_content_verifier&#039;);
		parent::RegisterHook(&#039;Filter&#039;, &#039;Email.Send.Before&#039;, &#039;email_content_verifier&#039;, &#039;FilterContent&#039;, 10, 4);

		// Load the forbidden words and assign them to a property
		self::ForbiddenWords = Database::$Interface-&gt;GetOption(&#039;EmailContentVerifier_ForbiddenWords&#039;);
		self::ForbiddenWords = unserialize(self::ForbiddenWords[0][&#039;OptionValue&#039;]);
	}

	// This is the function which will be executed by Email.Send.Before listener
	// Please note that the number of variables should be equal to the number
	// of variables listed on listener page:
	// http://octeth.com/oempro/docs/developers/plugins/hooks/email.send.before/
	// 
	// The return variable should be array and values should be in the same order
	function FilterContent($Subject, $HTMLBody, $PlainBody, $Subscriber)
	{
		foreach (self::ForbiddenWords as $ForbiddenWord)
		{
		$Subject = preg_replace(&#039;/&#039;.preg_quote($ForbiddenWord).&#039;/i&#039;, &#039; &#039;, $Subject);
		$HTMLBody = preg_replace(&#039;/&#039;.preg_quote($ForbiddenWord).&#039;/i&#039;, &#039; &#039;, $HTMLBody);
		$PlainBody = preg_replace(&#039;/&#039;.preg_quote($ForbiddenWord).&#039;/i&#039;, &#039; &#039;, $PlainBody);
		}
		return array($Subject, $HTMLBody, $PlainBody, $Subscriber);
	}
}

13 thoughts on “Introduction to Oempro plugin development

  1. Hi
    Useful article but are you aware that different hooks reference links in your website are broken ? (ie: Filter Hooks, User Interface Hooks, Menu Hooks)

    Luca

    1. Hi Luca, yes, we will be opening a new developer portal and you will have more details. Until then, you can search for that hook in the source code to learn what kind of parameters it gets.

  2. This is great thanks.

    One important part that had me stuck for a bit was the syntax of the comment block at the top of the php.

    Make sure those asterix are fully left aligned, no extra spaces, otherwise your plugin will not be picked up in the admin settings.

    ta,

  3. what about reopen a customer to customer forum reserved to registered customers, where we can keep on sharing tips and experience?

  4. This is great and whilst it works for your example. I’m having difficulty getting ‘Actions’ to fire anything. It works fine for ‘Filters’.

    Can you confirm that the actions are working correctly?

    1. Chris, actions are just similar. In action hooks, you can simply do whatever you need but the output will not be taken into consideration. In “filter” hooks, you can change the submitted email content for example. In actions, you can send a notification email to the admin or trigger another process.

  5. Is there any way we can get subscriber’s geographical location? I have seen other software which show the campaign open statistics based on the subscriber’s geographical location. Are there any existing oempro plugins for this function?

    1. Hi Sara, because of the licensing issues, we are unable to include IP location database (which is provided by third parties) in Oempro distribution package. However, starting from Oempro v5, the geo-location support will be included. You will need to enable this feature by purchasing the IP location database from third parties such as Maxmind.

  6. Hi guys,

    I’m creating a few plugins and I have a question about returning data from the plugin to the $CampaignInformation array – mainly for the following in the controller_campaign.php around line 143:

    		// Plug-in hook - Start
    		Plugins::HookListener('Action', 'Campaign.OnView', array (
    				$CampaignInformation 
    		));
    		// Plug-in hook - End
    

    My question is, if my plugin wants to add a variable which can then be used in the view, how do I set it? As if I modify the passed in $CampaignInformation and return it from my view I can’t access it in the view. But I can if I modify the hook code to be:

    		// Plug-in hook - Start
    		$CampaignInformation = Plugins::HookListener('Action', 'Campaign.OnView', array (
    				$CampaignInformation 
    		));
    		// Plug-in hook - End
    

    I would love to how to return vars from plugins for use in views.

    cheers,
    Paul

    1. Hi Paul,

      “Action” hook listeners do not process returned vars. Therefore, even you modify the $CampaignInformation array inside your plugin, it will not be passed back to Oempro’s core. If the hook listener was “filter”, it would work.

      What you can do is, you can add your own hook listener to that section, such as;


      $PlugInReturnVars = Plugins::HookListener('Action', 'Custom.Campaign.OnView', array ($CampaignInformation));
      $CampaignInformation = $PlugInReturnVars[1];

      The example above will work for you. If you need further help, let us know.

      By the way, we are re-writing our plugin development manual here:
      http://octeth.com/help/plugin-development/

      The new manual will include all details you will need about hooks, global functions, etc.

      On the other hand, we almost completed a plugin framework/boilerplate here:
      https://github.com/octeth/oempro_plugin_framework

      Lastly, come and join Oempro Plugin Developers Community here, not announced yet officially but spreading the word out :)
      https://www.facebook.com/groups/oempro.plugin.developers/

      Cheers.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="">