skip to Main Content

How to create your own trigger with Automator

Custom Triggers & Actions
1. How to create your own integration with Automator
2. How to create your own trigger with Automator
3. Comparison between 2.x and 3.x Automator code
4. How to create a simple trigger with Automator
5. How to create a simple Automator action

Difficulty: Medium

Creating a trigger with Automator 3.0 is a lot easier than you might think. To get started, you can download this sample from our Github repository.

Start by creating a new plugin in your dev environment and define your plugin file:

<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName

/**
 * @wordpress-plugin
 * Plugin Name:       Your plugin name
 * Plugin URI:        Your plugin URI
 * Description:       Your plugin description
 * Version:           1.0.0
 * Author:            Author
 * Author URI:        Author URI
 * License:           GPL-3.0+
 * License URI:       http://www.gnu.org/licenses/gpl-3.0.txt
 */

After this step, it’s up to you now how you go ahead and define your trigger. You can use either of the following code examples:

class Uncanny_Automator_Trigger_Only {
	/**
	 * Uncanny_Automator_Trigger_Only constructor.
	 */
	public function __construct() {
		add_action( 'automator_configuration_complete', array( $this, 'load_triggers' ) );
	}

	/**
	 * @return bool|null
	 */
	public function load_triggers() {
		// Let's find integration by name so that trigger can be added it's list.
		$add_to_integration = automator_get_integration_by_name( 'Uncanny Automator' );
		if ( empty( $add_to_integration ) ) {
			return null;
		}
        // Add a php trigger file in the same folder and name it uoa-recipenotcompleted.php
		$trigger = __DIR__ . '/uoa-recipenotcompleted.php';
		automator_add_trigger( $trigger, $add_to_integration );
	}
}

new Uncanny_Automator_Trigger_Only();

Class implementataion

function load_my_custom_triggers() {
	// Let's find integration by name so that trigger can be added it's list.
	$add_to_integration = automator_get_integration_by_name( 'Uncanny Automator' );
	if ( empty( $add_to_integration ) ) {
		return null;
	}
    // Add a php trigger file in the same folder and name it uoa-recipenotcompleted.php
	$trigger = __DIR__ . '/uoa-recipenotcompleted.php';
	automator_add_trigger( $trigger, $add_to_integration );
}

add_action( 'automator_configuration_complete', 'load_my_custom_triggers' );

Simple implementation

Once the trigger is defined, you will now create a file in plugin folder (if not created yet) and name it uoa-recipenotcompleted.php.

Automator usually uses integration’s shortcode as the prefix of the file and class name, i.e., uoa is the shortcode of Uncanny Automator integration and recipenotcompleted is somewhat meaningful name of the trigger’s functionality. The classname from filename uoa-recipenotcompleted will become UOA_RECIPENOTCOMPLETED.

Now in trigger file, start by adding use Uncanny_Automator\Recipe namespace. Declare your class.

<?php

use Uncanny_Automator\Recipe;

/**
 * Class UOA_RECIPENOTCOMPLETED
 */
class UOA_RECIPENOTCOMPLETED {
}

Automator 3.0 uses PHP’s Traits to implement consistent code across all integration files. Add use Recipe\Triggers inside your class as:

<?php

use Uncanny_Automator\Recipe;

/**
 * Class UOA_RECIPENOTCOMPLETED
 */
class UOA_RECIPENOTCOMPLETED {
	use Recipe\Triggers;

}

As soon as use Recipe\Triggers is added, your IDE should throw a notice that there are few abstract functions that are required to be added in to the file. These function are mandatory to run a trigger and has to be added in the trigger file. Your site will also throw a Fatal error if not added. These functions are:

protected function setup_trigger(){}    // Is used to declare trigger
protected function validate_trigger(){} // Is used to validate trigger once it's triggered
protected function prepare_to_run(){}   // Is used to set some values to help the trigger process

In addition to above functions, an optional override function can be added in the trigger which is explained further down:

protected function do_action_args() {}

You will now add placeholder functions like:

<?php

use Uncanny_Automator\Recipe;

/**
 * Class UOA_RECIPENOTCOMPLETED
 */
class UOA_RECIPENOTCOMPLETED {
	use Recipe\Triggers;

	protected function setup_trigger() {
	}

	protected function do_action_args( $args ) {
	}

	protected function validate_trigger( $args ) {
	}

	protected function prepare_to_run( $args ) {
	}
}

Once you are done adding placeholder functions, next step is to actually setup_trigger() so that it’s added in Automator’s Recipe UI. To do that, add __construct() and call setup_trigger().

<?php

use Uncanny_Automator\Recipe;

/**
 * Class UOA_RECIPENOTCOMPLETED
 */
class UOA_RECIPENOTCOMPLETED {
	use Recipe\Triggers;

    public function __construct() {
		$this->setup_trigger();
	}

	protected function setup_trigger() {
	}

	protected function do_action_args( $args ) {
	}

	protected function validate_trigger( $args ) {
	}

	protected function prepare_to_run( $args ) {
	}
}

You will use following functions in order to define a trigger:

$this->set_integration(); // Display this trigger under specific integration 

$this->set_trigger_code(); // Unique Trigger code

$this->set_trigger_meta(); // Re-useable meta, selectable value in blue boxes

$this->set_sentence(); // Sentence to appear when trigger is added.

$this->set_readable_sentence(); // Non-active state sentence to show

$this->add_action(); // which do_action() triggers this trigger 

$this->set_options(); // Adding options so that Automator could display it in Recipe UI 

$this->register_trigger(); // Registering this trigger

To get the list of all available functions for setup_trigger(), please refer to Trigger_Setup developer’s guide here.

Now let’s start to set up this trigger by adding above functions in setup_trigger() as follows:

<?php

use Uncanny_Automator\Recipe;

/**
 * Class UOA_RECIPENOTCOMPLETED
 */
class UOA_RECIPENOTCOMPLETED {
	use Recipe\Triggers;

    public function __construct() {
		$this->setup_trigger();
	}

	protected function setup_trigger() {

		$this->set_integration( 'UOA' ); // Display this trigger under UOA integration 

		$this->set_trigger_code( 'UOARECIPESNOTCOMPLETED' ); // Unique Trigger code

		$this->set_trigger_meta( 'UOARECIPE' ); // Reuseable meta, selectable value in blue boxes

		/* Translators: Some information for translators */
		$this->set_sentence( sprintf( esc_attr__( '{{A recipe:%1$s}} is not completed', 'uncanny-automator' ), $this->get_trigger_meta() ) ); // Sentence to appear when trigger is added. {{A recipe:%1$s}} will be presented in blue box as selectable value

		/* Translators: Some information for translators */
		$this->set_readable_sentence( esc_attr__( '{{A recipe}} is not completed', 'uncanny-automator' ) ); // Non-active state sentence to show

		$this->add_action( 'automator_recipe_completed_with_errors', 90, 4 ); // which do_action() triggers this trigger 

		$options = array(
			Automator()->helpers->recipe->uncanny_automator->options->get_recipes(), // Add your options for this trigger
		);

		$this->set_options( $options ); // Adding options so that {{A recipe:%1$s}} could display it in Recipe UI 

		$this->register_trigger(); // Registering this trigger
	}

	protected function do_action_args( $args ) {
	}

	protected function validate_trigger( $args ) {
	}

	protected function prepare_to_run( $args ) {
	}
}

At this point, if all goes well, the trigger should start to show up in Recipe UI as:

Trigger in the Recipe UI

Trigger displaying option(s)

Trigger once option(s) is selected

The trigger is technically ready for use on your Automator installation site.

But wait, what happens when the trigger fires?

This is handled in the following functions that you added before as placeholders:

protected function do_action_args( $args ) {}

protected function validate_trigger( $args ) {}

protected function prepare_to_run( $args ) {}

By default, all triggers are going to call Triggers::validate() function. This function accepts any number of arguments by using Splat Operator ... in the form of an array. For this trigger, automator_recipe_completed_with_errors is passing 4 arguments to this function:

do_action( 
'automator_recipe_completed_with_errors', 
    $recipe_id,     // Recipe ID
    $user_id,       // User ID
    $recipe_log_id, // Recipe log ID from DB
    $args           // $args array passed to this function
);

Once Trigger::validate(...$args) is called, each of the above 4 arguments will be available in an indexed array respectively.

As a developer of the trigger, you can parse these arguments in to an associative array just to make things easier in future steps by overriding do_action_args() function:

protected function do_action_args( $args ) {
	return array(
		'recipe_id'     => $args[0], // ...$args no. 1
		'user_id'       => $args[1], // ...$args no. 2
		'recipe_log_id' => $args[2], // ...$args no. 3
		'args'          => $args[3], // ...$args no. 4
	);
}

The trigger file at this point will look something like this:

<?php

use Uncanny_Automator\Recipe;

/**
 * Class UOA_RECIPENOTCOMPLETED
 */
class UOA_RECIPENOTCOMPLETED {
	use Recipe\Triggers;

    public function __construct() {
		$this->setup_trigger();
	}

	protected function setup_trigger() {

		$this->set_integration( 'UOA' ); // Display this trigger under UOA integration 

		$this->set_trigger_code( 'UOARECIPESNOTCOMPLETED' ); // Unique Trigger code

		$this->set_trigger_meta( 'UOARECIPE' ); // Reuseable meta, selectable value in blue boxes

		/* Translators: Some information for translators */
		$this->set_sentence( sprintf( esc_attr__( '{{A recipe:%1$s}} is not completed', 'uncanny-automator' ), $this->get_trigger_meta() ) ); // Sentence to appear when trigger is added. {{A recipe:%1$s}} will be presented in blue box as selectable value

		/* Translators: Some information for translators */
		$this->set_readable_sentence( esc_attr__( '{{A recipe}} is not completed', 'uncanny-automator' ) ); // Non-active state sentence to show

		$this->add_action( 'automator_recipe_completed_with_errors', 90, 4 ); // which do_action() triggers this trigger 

		$options = array(
			Automator()->helpers->recipe->uncanny_automator->options->get_recipes(), // Add your options for this trigger
		);

		$this->set_options( $options ); // Adding options so that {{A recipe:%1$s}} could display it in Recipe UI 

		$this->register_trigger(); // Registering this trigger
	}

    protected function do_action_args( $args ) {
		return array(
			'recipe_id'     => $args[0], // ...$args no. 1
			'user_id'       => $args[1], // ...$args no. 2
			'recipe_log_id' => $args[2], // ...$args no. 3
			'args'          => $args[3], // ...$args no. 4
		);
	}

	protected function validate_trigger( $args ) {
	}

	protected function prepare_to_run( $args ) {
	}
}

Next step, as the name suggests, validate_trigger(), you are going to do some basic validation before its passed back to Automator for further processing.

protected function validate_trigger( $args ) {
	$recipe_log_id = absint( $args['recipe_log_id'] ); // set in do_action_args() above
	global $wpdb;
	// get recipe actions
	$table_name = $wpdb->prefix . Automator()->db->tables->action; // @see https://docs.automatorplugin.com/reference/classes/uncanny_automator-automator_db_handler/
	$errors     = $wpdb->get_results( $wpdb->prepare( "SELECT automator_action_id FROM $table_name WHERE automator_recipe_log_id = {$recipe_log_id} AND error_message != ''" ) ); //phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared

	// There are no error messages, bail
    if ( empty( $errors ) ) {
		// bail early
		return false;
	}
	return true;
}

This trigger is only going to run if there is an error message stored in the DB for an action. validate_trigger will either return true or false back to Automator. The trigger file now will be:

<?php

use Uncanny_Automator\Recipe;

/**
 * Class UOA_RECIPENOTCOMPLETED
 */
class UOA_RECIPENOTCOMPLETED {
	use Recipe\Triggers;

    public function __construct() {
		$this->setup_trigger();
	}

	protected function setup_trigger() {

		$this->set_integration( 'UOA' ); // Display this trigger under UOA integration 

		$this->set_trigger_code( 'UOARECIPESNOTCOMPLETED' ); // Unique Trigger code

		$this->set_trigger_meta( 'UOARECIPE' ); // Reuseable meta, selectable value in blue boxes

		/* Translators: Some information for translators */
		$this->set_sentence( sprintf( esc_attr__( '{{A recipe:%1$s}} is not completed', 'uncanny-automator' ), $this->get_trigger_meta() ) ); // Sentence to appear when trigger is added. {{A recipe:%1$s}} will be presented in blue box as selectable value

		/* Translators: Some information for translators */
		$this->set_readable_sentence( esc_attr__( '{{A recipe}} is not completed', 'uncanny-automator' ) ); // Non-active state sentence to show

		$this->add_action( 'automator_recipe_completed_with_errors', 90, 4 ); // which do_action() triggers this trigger 

		$options = array(
			Automator()->helpers->recipe->uncanny_automator->options->get_recipes(), // Add your options for this trigger
		);

		$this->set_options( $options ); // Adding options so that {{A recipe:%1$s}} could display it in Recipe UI 

		$this->register_trigger(); // Registering this trigger
	}

    protected function do_action_args( $args ) {
		return array(
			'recipe_id'     => $args[0], // ...$args no. 1
			'user_id'       => $args[1], // ...$args no. 2
			'recipe_log_id' => $args[2], // ...$args no. 3
			'args'          => $args[3], // ...$args no. 4
		);
	}

	protected function validate_trigger( $args ) {
		$recipe_log_id = absint( $args['recipe_log_id'] );
		global $wpdb;
		// get recipe actions
		$table_name = $wpdb->prefix . Automator()->db->tables->action;
		$errors     = $wpdb->get_results( $wpdb->prepare( "SELECT automator_action_id FROM $table_name WHERE automator_recipe_log_id = {$recipe_log_id} AND error_message != ''" ) ); //phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		if ( empty( $errors ) ) {
			// bail early
			return false;
		}

		return true;
	}

	protected function prepare_to_run( $args ) {
	}
}

The last step is to provide Automator with post_id to process the trigger further and call other triggers/actions of the recipe. To set post_id with the recipe_id, add the following code:

protected function prepare_to_run( $args ) {
	$recipe_id = absint( $args['recipe_id'] ); // set in do_action_args() function above
	$this->set_post_id( $recipe_id ); // setting post_id with the recipe id from previous step
}

Your trigger file is now complete and will look like this:

<?php

use Uncanny_Automator\Recipe;

/**
 * Class UOA_RECIPENOTCOMPLETED
 */
class UOA_RECIPENOTCOMPLETED {
	use Recipe\Triggers;

    public function __construct() {
		$this->setup_trigger();
	}

	protected function setup_trigger() {

		$this->set_integration( 'UOA' ); // Display this trigger under UOA integration 

		$this->set_trigger_code( 'UOARECIPESNOTCOMPLETED' ); // Unique Trigger code

		$this->set_trigger_meta( 'UOARECIPE' ); // Reuseable meta, selectable value in blue boxes

		/* Translators: Some information for translators */
		$this->set_sentence( sprintf( esc_attr__( '{{A recipe:%1$s}} is not completed', 'uncanny-automator' ), $this->get_trigger_meta() ) ); // Sentence to appear when trigger is added. {{A recipe:%1$s}} will be presented in blue box as selectable value

		/* Translators: Some information for translators */
		$this->set_readable_sentence( esc_attr__( '{{A recipe}} is not completed', 'uncanny-automator' ) ); // Non-active state sentence to show

		$this->add_action( 'automator_recipe_completed_with_errors', 90, 4 ); // which do_action() triggers this trigger 

		$options = array(
			Automator()->helpers->recipe->uncanny_automator->options->get_recipes(), // Add your options for this trigger
		);

		$this->set_options( $options ); // Adding options so that {{A recipe:%1$s}} could display it in Recipe UI 

		$this->register_trigger(); // Registering this trigger
	}

    protected function do_action_args( $args ) {
		return array(
			'recipe_id'     => $args[0], // ...$args no. 1
			'user_id'       => $args[1], // ...$args no. 2
			'recipe_log_id' => $args[2], // ...$args no. 3
			'args'          => $args[3], // ...$args no. 4
		);
	}

	protected function validate_trigger( $args ) {
		$recipe_log_id = absint( $args['recipe_log_id'] );
		global $wpdb;
		// get recipe actions
		$table_name = $wpdb->prefix . Automator()->db->tables->action;
		$errors     = $wpdb->get_results( $wpdb->prepare( "SELECT automator_action_id FROM $table_name WHERE automator_recipe_log_id = {$recipe_log_id} AND error_message != ''" ) ); //phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		if ( empty( $errors ) ) {
			// bail early
			return false;
		}

		return true;
	}

    protected function prepare_to_run( $args ) {
		$recipe_id = absint( $args['recipe_id'] ); // set in do_action_args() function above
		$this->set_post_id( $recipe_id ); // setting post_id with the recipe id from previous step
    }
}

The trigger is now ready to be used in a recipe. Once an action with an error is completed, your trigger will fire and process according to the recipe that you have created.

Back To Top