Before we dive into developing a custom integration for Automator, let's explain some of the…
Adding a Trigger to Uncanny Automator
2.
Adding a Trigger to Uncanny Automator
Now that we have an integration, let’s add the first Trigger to it. This trigger will fire every time a post is published on the site. We will also add a post types dropdown to it so that users can narrow it down to a specific post type:

The trigger file and class
You can view the complete code of this file here, or you can download the whole sample plugin from our GitHub repository.
Let’s create the triggers
folder inside our integration and create the post-created-sample.php
file in it. In that file, define the new Post_Created_Sample_Trigger
class that extends the \Uncanny_Automator\Recipe\Trigger
class:
<?php
class Post_Created_Sample_Trigger extends \Uncanny_Automator\Recipe\Trigger {
protected function setup_trigger() {
// Define the Trigger's info
$this->set_integration( 'SAMPLE_INTEGRATION' );
$this->set_trigger_code( 'POST_CREATED_SAMPLE' );
$this->set_trigger_meta( 'POST_TYPE' );
// Trigger sentence
$this->set_sentence( sprintf( esc_attr__( '{{A post type:%1$s}} is created sample trigger', 'automator-sample' ), 'POST_TYPE' ) );
$this->set_readable_sentence( esc_attr__( '{{A post type}} is created sample trigger', 'automator-sample' ) );
// Trigger wp hook
$this->add_action( 'wp_after_insert_post', 90, 4 );
}
}
In the setup_trigger method, define the integration’s code using the set_integration function. The code can be any existing integration code. In our case it would be SAMPLE_INTEGRATION as we defined earlier in the sample-integration.php
file.
The set_trigger_code method defines the unique name of this particular trigger. You have to come up with one that is unique to this integration. It’s okay to have same trigger codes in different integrations though.
The set_trigger_meta value would be the unique ID for the post types dropdown. Later it will be used to retrieve the selected post type and also to form the trigger’s sentence.
The next two methods define the Trigger’s sentence. If we want our POST_TYPE dropdown in the middle of the sentence, we need to add it in the value we pass to the set_sentence method. The POST_TYPE string will be automatically replaced with the selected value and stored in the logs. We have to do some string juggling with sprintf here because we want to keep the variables out of the translation strings.
The string from the set_readable_sentence will be used when the trigger is listed in dropdowns.
Probably the most important attribute of a trigger is set with the add_action method – here you can define what WordPress hook should fire the trigger, define its priority and the number of accepted arguments same as you would using the add_action function, but without a callback.
Note: by default, all Automator triggers are for logged-in recipes only (more about recipe types here). If you want to set the trigger to support everyone recipes, you can set its type to anonymous:
$this->set_trigger_type( 'anonymous' );
Adding Trigger options to the recipe UI
Your trigger may have no options at all and fire whenever something happens unconditionally, but if you need to provide users with a way to narrow down the cases when your trigger fires, you can add custom fields to the UI.
We want this trigger to fire whenever a post is created, but what if users want to limit its action to only a specific type of post?
Let’s add the dropdown that will allows users do that, while still leaving an option to run it for all post types.
Override the options method that returns an array of arrays. Each array represents a field.
public function options() {
$post_types_dropdown = array(
'input_type' => 'select',
'option_code' => 'POST_TYPE',
'label' => __( 'Post type', 'automator-sample' ),
'required' => true,
'options' => array(),
'placeholder' => __( 'Please select a post type', 'automator-sample' ),
);
return array(
$post_types_dropdown
);
}
Here we create an array with the select field. It sets the input code POST_TYPE that matches the trigger_meta, makes the field required as well as sets the label, placeholder and an empty options array for now.
Note that at least one field should use the trigger_meta as the option_code, otherwise the trigger sentence won’t work.
You can find the full list of supported fields and helper methods to quickly use them in the src\core\lib\helpers\class-automator-recipe-helpers-field.php
file. To use any of the helper methods, call them anywhere like so:
Automator()->helpers->recipe->field->select( $args );
To complete the dropdown, we will need to feed it with the list of available WordPress post types in the following format:
array(
array(
'text' => 'Any post type',
'value' => '-1'
),
array(
'text' => 'Post type 1',
'value' => 'post_type_1'
),
array(
'text' => 'Post type 2',
'value' => 'post_type_2'
),
);
Including the file and injecting dependencies
Generating such a list of WordPress post types is out of the scope of this tutorial, so let’s just download this file and place into the uncanny-automator-sample/helpers/helpers.php
It has several functions that we may want to reuse in several triggers or actions, so it makes sense to keep them in a separate class.
Let’s go back to the main plugin file and let’s require the helpers and the trigger files there:
<?php
/**
* Plugin Name: Uncanny Automator Sample Integration
*/
add_action( 'automator_add_integration', 'sample_integration_load_files' );
function sample_integration_load_files() {
// If this class doesn't exist Uncanny Automator plugin is not enabled or needs to be updated.
if ( ! class_exists( '\Uncanny_Automator\Integration' ) ) {
return;
}
require_once 'helpers/helpers.php';
$helpers = new Helpers();
require_once 'sample-integration.php';
new Sample_Integration( $helpers );
require_once 'triggers/post-created-sample.php';
new Post_Created_Sample_Trigger( $helpers );
}
Note that we created the helpers object before the integration so we can pass those helpers to all of the objects. You can pass unlimited number of variables to all framework objects this way. All such variables will be collected and stored in the $this->dependecies class attribute. So to reach our helpers back in the Trigger object, we can use this line right at the top of the setup method:
$this->helpers = array_shift( $this->dependencies );
Now we can use our helpers to load the post type options:
public function options() {
$post_types_dropdown = array(
'input_type' => 'select',
'option_code' => 'POST_TYPE',
'label' => __( 'Post type', 'automator-sample' ),
'required' => true,
'options' => $this->helpers->get_post_types(), // Load the options from the helpers file
'placeholder' => __( 'Please select a post type', 'automator-sample' ),
);
return array(
$post_types_dropdown
);
}
Evaluating trigger execution
The code above is sufficient to display your integration and the trigger in the recipe UI, so let’s go ahead and create a test recipe.
We will use our trigger as the trigger and we need to select some action so that we can test the recipe. On development sites you can use the “Create a Post” action and on production sites it’s better to use the “Send an Email” action.
Now with your trigger active in at least one recipe, Automator will hook into the action and wait until it fires. Once it does, your trigger will automatically fire and run the whole recipe. This is useful for non-conditional triggers, but our trigger has a post type selector, so we need to validate that the created post matches the post type that we selected. Also note, that the wp_after_insert_post WP hook fires when posts are drafted or when drafts are created, so will need to rule out those events as well by adding a validation function to our trigger. To do that, extend the validate method:
public function validate( $trigger, $hook_args ) {
// Make sure the trigger has some value selected in the options
if ( ! isset( $trigger['meta']['POST_TYPE'] ) ) {
//Something is wrong, the trigger doesn't have the required option value.
return false;
}
// Get the dropdown value
$selected_post_type = $trigger['meta']['POST_TYPE'];
// Parse the args from the wp_after_insert_post hook
list( $post_id, $post, $update, $post_before ) = $hook_args;
// If the post type selected in the trigger options doesn't match the post type being inserted, bail.
if ( '-1' != $selected_post_type && $selected_post_type !== $post->post_type ) {
return false;
}
// Make sure the post is being published and not updated or drafted
if ( ! $this->helpers->post_is_being_published( $post, $post_before ) ) {
return false;
}
// If all conditions were met, return true
return true;
}
Note that this function will run once for each active trigger instance in each active recipe and it will pass two arrays:
- $trigger – contains all the trigger information that we have, along with the values that were selected in the trigger fields
- $hook_args – contains all the variables that were passed to the action that fired (in this case the wp_after_insert_post)
The validate method should return either true or false. If false is returned, the trigger run is ignored, if true is returned, a record of the trigger run will be created and the recipe will continue its run.
The code above demonstrates how we got the dropdown value from trigger meta and how we got the hook arguments to check if the correct post type is being updated and that it’s actually being created and not drafted.
Note that we also covered the ‘-1’ value that corresponds to ‘All post types’ value. In that case we bail out and do not check the post type at all.
You can now run the recipe a couple of times and check if it’s completing as expected.
Passing data via tokens
We are now able to trigger any of hundreds Automator actions using our custom trigger, which is amazing, but not that useful unless we pass some data from the trigger for later use such as the post type that was selected, the post title, and the URL of the created post. To do that, we can define the trigger tokens:
public function define_tokens( $trigger, $tokens ) {
$tokens[] = array(
'tokenId' => 'POST_TITLE',
'tokenName' => __( 'Post Title', 'automator-sample' ),
'tokenType' => 'text',
);
$tokens[] = array(
'tokenId' => 'POST_URL',
'tokenName' => __( 'Post URL', 'automator-sample' ),
'tokenType' => 'text',
);
return $tokens;
}
The POST_TYPE token will be defined automatically along with other UI fields.
Note that the define_tokens method will run for each recipe page load, so it passes the $trigger variable that has all the trigger field values in case you want to generate some dynamic tokens that are based on a prior selection. For example, if your trigger has a “Forms” dropdown, you may want to fetch all that form’s fields as tokens so Actions can use those values.
To populate the tokens with actual values when a trigger runs, override the following method:
public function hydrate_tokens( $trigger, $hook_args ) {
list( $post_id, $post ) = $hook_args;
$token_values = array(
'POST_TYPE' => $post->post_type,
'POST_TITLE' => $post->post_title,
'POST_URL' => get_permalink( $post->ID )
);
return $token_values;
}
Same as almost all trigger methods, this one accepts the $trigger array that has all the values from the dropdowns and the $hook_args that has all the data from the WP hook.
In the code above we extracted the needed values and returned an array of token IDs along with the values that they will pass further.
Passing values between methods
Sometimes you may want to run some resource intensive queries or requests when you validate a trigger and then reuse that information in the hydrate tokens method. For that, we recommend using custom class attributes.
If you want to alter the $trigger or $hook_args array at some point and make sure that those array remain altered in the subsequent methods, you can alter the $this->trigger and $this->hook_args attributes respectively.
Checkout other articles from this series: