first commit

This commit is contained in:
2026-03-05 13:07:40 +01:00
commit 64ba0721ee
25709 changed files with 4691006 additions and 0 deletions

View File

@@ -0,0 +1,344 @@
<?php
/**
* Abstract class for actions.
*
* @since 4.4.1
* @version 1.0
* @package Email Subscribers
*/
/**
* Abstract Class ES_Workflow_Action
*
* All workflow actions extend this class.
*
* @since 4.4.1
*/
abstract class ES_Workflow_Action {
/**
* The action's unique name/slug.
*
* @since 4.4.1
* @var string
*/
public $name;
/**
* The action's title.
*
* @since 4.4.1
* @var string
*/
public $title;
/**
* The action's description.
*
* @since 4.4.1
* @var string
*/
public $description;
/**
* The action's group.
*
* @since 4.4.1
* @var string
*/
public $group;
/**
* The action's fields objects.
*
* @since 4.4.1
* @var Field[]
*/
public $fields;
/**
* Array containing the action's option values.
*
* @since 4.4.1
* @var array
*/
public $options;
/**
* The workflow the action belongs to.
*
* This prop may not be set depending on the context.
*
* @since 4.4.1
* @var Workflow
*/
public $workflow;
/**
* The workflow trigger for which action is being added.
*
* This prop may not be set depending on the context.
*
* @since 4.4.3
*
* @var ES_Workflow_Trigger
*/
public $trigger;
/**
* Knows if admin details have been loaded.
*
* @since 4.4.1
* @var bool
*/
protected $has_loaded_admin_details = false;
/**
* Called when an action should be run.
*
* @since 4.4.1
* @throws Exception When an error occurs.
*/
abstract public function run();
/**
* Action constructor.
*
* @since 4.4.1
*/
public function __construct() {
$this->init();
}
/**
* This method no longer has an explicit purpose and is deprecated.
*
* @since 4.4.1
*
* @deprecated
*/
public function init() {}
/**
* Method to load the action's fields.
*
* @since 4.4.1
*
* @modified 4.5.3 Removed dependency to modify child action file to load extra fields.
*/
public function load_fields() {}
/**
* Method to set the action's admin props.
*
* Admin props include: title, group and description.
*
* @since 4.4.1
*/
protected function load_admin_details() {}
/**
* Loads the action's admin props.
*
* @since 4.4.1
*/
protected function maybe_load_admin_details() {
if ( ! $this->has_loaded_admin_details ) {
$this->load_admin_details();
$this->has_loaded_admin_details = true;
}
}
/**
* Get the action's title.
*
* @since 4.4.1
* @param bool $prepend_group Action group.
* @return string $title Action group title
*/
public function get_title( $prepend_group = false ) {
$this->maybe_load_admin_details();
$group = $this->get_group();
$title = $this->title ? $this->title : '';
if ( $prepend_group && __( 'Other', 'email-subscribers' ) !== $group ) {
return $group . ' - ' . $title;
}
return $title;
}
/**
* Get the action's group.
*
* @since 4.4.1
* @return string
*/
public function get_group() {
$this->maybe_load_admin_details();
return $this->group ? $this->group : __( 'Other', 'email-subscribers' );
}
/**
* Get the action's description.
*
* @since 4.4.1
* @return string
*/
public function get_description() {
$this->maybe_load_admin_details();
return $this->description ? $this->description : '';
}
/**
* Get the action's name.
*
* @since 4.4.1
* @return string
*/
public function get_name() {
return $this->name ? $this->name : '';
}
/**
* Set the action's name.
*
* @since 4.4.1
*
* @param string $name Action name.
*/
public function set_name( $name ) {
$this->name = $name;
}
/**
* Get the action's description HTML.
*
* @since 4.4.1
* @return string
*/
public function get_description_html() {
if ( ! $this->get_description() ) {
return '';
}
return '<p class="ig-es-field-description">' . $this->get_description() . '</p>';
}
/**
* Adds a field to the action.
*
* Should only be called in the load_fields() method.
*
* @since 4.4.1
* @param Field $field Action field object.
*/
public function add_field( $field ) {
$field->set_name_base( 'ig_es_workflow_data[actions]' );
$this->fields[ $field->get_name() ] = $field;
}
/**
* Gets specific field belonging to the action.
*
* @since 4.4.1
* @param string $name field name.
*
* @return ES_Field|false
*/
public function get_field( $name ) {
$this->get_fields();
if ( ! isset( $this->fields[ $name ] ) ) {
return false;
}
return $this->fields[ $name ];
}
/**
* Gets the action's fields.
*
* @return ES_Field[]
*
* @since 4.4.1
*
* @modified 4.4.3 Removed isset condition to allow latest list of fields every time when called.
*
* @modified 4.5.3 Added new action action_name_load_extra_fileds to allow loading of extra fields for action.
*/
public function get_fields() {
$this->fields = array();
$this->load_fields();
// Load extra fields for workflow action.
do_action( $this->name . '_load_extra_fields', $this );
return $this->fields;
}
/**
* Set the action's options.
*
* @since 4.4.1
* @param array $options Options array.
*/
public function set_options( $options ) {
$this->options = $options;
}
/**
* Returns an option for use when running the action.
*
* Option value will already have been sanitized by it's field ::sanitize_value() method.
*
* @since 4.4.1
* @param string $field_name Field name.
*
* @return mixed Will vary depending on the field type specified in the action's fields.
*/
public function get_option( $field_name, $process_variables = false, $allow_html = false ) {
$value = $this->get_option_raw( $field_name );
// Process the option value only if it's a string
// The value will almost always be a string but it could be a bool if the field is checkbox
if ( $value && is_string( $value ) ) {
if ( $process_variables ) {
$value = $this->workflow->variable_processor()->process_field( $value, $allow_html );
}
}
return apply_filters( 'ig_es_action_option', $value, $field_name, $this );
}
/**
* Get an option for use when editing the action.
*
* The value will be already sanitized by the field object.
* This is used to displaying an option value for editing.
*
* @since 4.4.1
*
* @param string $field_name Field name.
*
* @return mixed
*/
public function get_option_raw( $field_name ) {
if ( isset( $this->options[ $field_name ] ) ) {
return $this->options[ $field_name ];
}
return false;
}
/**
* Load preview for the action
*
* @return null
*/
public function load_preview() {
return null;
}
}

View File

@@ -0,0 +1,78 @@
<?php
/**
* Workflow Data Types.
*
* @since 4.4.1
* @version 1.0
* @package Email Subscribers
*/
/**
* Abstract Class ES_Workflow_Data_Type
*
* @class ES_Workflow_Data_Type
* @since 4.4.1
*/
abstract class ES_Workflow_Data_Type {
/**
* Data type id
*
* @var string
*/
public $id;
/**
* Returns id of data type
*
* @since 4.4.1
* @return string
*/
public function get_id() {
return $this->id;
}
/**
* Sets id of data type
*
* @since 4.4.1
* @param string $id ID.
*/
public function set_id( $id ) {
$this->id = $id;
}
/**
* Validate given data item
*
* @since 4.4.1
* @param mixed $item Data item object.
* @return bool
*/
abstract public function validate( $item );
/**
* Returns id of given data item object. Only validated $items should be passed to this method
*
* @since 4.4.1
* @param mixed $item Data item object.
* @return mixed
*/
abstract public function compress( $item );
/**
* Return data item object from given id.
*
* @since 4.4.1
* @param string $compressed_item Data item object ID.
* @param array $compressed_data_layer Data layer.
* @return mixed
*/
abstract public function decompress( $compressed_item, $compressed_data_layer );
}

View File

@@ -0,0 +1,169 @@
<?php
/**
* Abstract class for workflow actions, triggers and data type related functions.
*
* @since 4.4.1
* @version 1.0
* @package Email Subscribers
*/
/**
* Abstract class for workflow actions, triggers and data type related functions.
*
* @class ES_Registry
* @since 4.4.1
*/
abstract class ES_Workflow_Registry {
/**
* Registered include classes
*
* @since 4.4.1
* @var array
*/
protected static $includes;
/**
* Loaded registered class objects
*
* @var array
*/
protected static $loaded = array();
/**
*
* Implement this method in sub classes
*
* @since 4.4.1
* @return array
*/
public static function load_includes() {
return array();
}
/**
* Optional method to implement
*
* @since 4.4.1
* @param string $name Class name.
* @param mixed $object Class object.
*/
public static function after_loaded( $name, $object ) {}
/**
* Initiate registered include classes.
*
* @since 4.4.1
* @return array
*/
public static function get_includes() {
if ( ! isset( static::$includes ) ) {
static::$includes = static::load_includes();
}
return static::$includes;
}
/**
* Get objects of all registered classes.
*
* @since 4.4.1
* @return mixed
*/
public static function get_all() {
foreach ( static::get_includes() as $name => $path ) {
static::load( $name );
}
return static::$loaded;
}
/**
* Get object of specific registered class.
*
* @since 4.4.1
* @param string $name Registered class name.
* @return bool|object
*/
public static function get( $name ) {
if ( static::load( $name ) ) {
return static::$loaded[ $name ];
}
return false;
}
/**
* Returns if class has been initiated or not
*
* @since 4.4.1
* @param string $name Registered class name.
* @return bool
*/
public static function is_loaded( $name ) {
return isset( static::$loaded[ $name ] );
}
/**
* Load an object by name.
*
* Returns true if the object has been loaded.
*
* @since 4.4.1
* @param string $name Registered class name.
*
* @return bool
*/
public static function load( $name ) {
if ( self::is_loaded( $name ) ) {
return true;
}
$includes = static::get_includes();
$object = false;
if ( empty( $includes[ $name ] ) ) {
return false;
}
$include = $includes[ $name ];
// Check if include is a file path or a class name
// NOTE: the file include method should NOT be used! It is kept for compatibility.
if ( strstr( $include, '.php' ) ) {
if ( file_exists( $include ) ) {
$object = include_once $include;
}
} else {
// If include is not a file path, assume it's a class name.
if ( class_exists( $include ) ) {
$object = new $include();
}
}
if ( ! is_object( $object ) ) {
return false;
}
static::after_loaded( $name, $object );
static::$loaded[ $name ] = $object;
return true;
}
/**
* Clear all registry cached data.
*
* @since 4.4.1
*/
public static function reset() {
static::$includes = null;
static::$loaded = array();
}
}

View File

@@ -0,0 +1,537 @@
<?php
/**
* Abstract rule class.
*
* @since 5.5.0
* @version 1.0
* @package Email Subscribers
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'Es_Workflow_Rule' ) ) {
/**
* Abstract class for workflow rules
*
* @class Es_Rule_Abstract
*
* @since 5.5.0
*/
abstract class Es_Workflow_Rule {
/**
* Name of the rule
*
* @var string
*/
public $name;
/**
* Title of the rule
*
* @var string
*/
public $title;
/**
* Group that rules belongs to
*
* @var string
*/
public $group;
/**
* Type of the rule
*
* @var string string|number|object|select
*/
public $type;
/**
* Define the data type used by the rule.
*
* @var string
*/
public $data_item;
/**
* Comparison type that the rule has used
*
* @var array
*/
public $compare_types = [];
/**
* Workflow that the rule belongs to
*
* @var ES_Workflow
*/
private $workflow;
/**
* Is that rule has multiple input value fields?
*
* @var bool - e.g meta rules have 2 value fields so their value data is an stored as an array
*/
public $has_multiple_value_fields = false;
/**
* Some triggers excluded for particular rule
*
* @var array
*/
public $excluded_triggers = array();
/**
* Constructor
*/
public function __construct() {
$this->init();
$this->determine_rule_group();
}
/**
* Init the rule.
*/
abstract public function init();
/**
* Validates that a given workflow data item passed the rule validation
* based on the supplied $compare_type and $value.
*
* @param mixed $data_item A valid workflow data item e.g. an instance of `\WC_Order` for an order based rule.
* @param string $compare_type The user selected compare type for the rule.
* @param mixed $value The user entered value for the rule. This value is validated by the validate_value() method beforehand.
*
* @return bool
*/
abstract public function validate( $data_item, $compare_type, $value );
/**
* Validate the rule's user entered value.
*
* @param mixed $value
*
* @throws UnexpectedValueException When the value is not valid.
*/
public function validate_value( $value ) {
// Override this method in child classes.
}
/**
* Get rule group
*
* @return string
*/
public function get_group() {
return $this->group;
}
/**
* Get rule name
*
* @return string
*/
public function get_name() {
return $this->name;
}
/**
* Get rule title
*
* @return string
*/
public function get_title() {
return $this->title;
}
/**
* Set workflow
*
* @param $workflow
*/
public function set_workflow( $workflow ) {
$this->workflow = $workflow;
}
/**
* Determine the rule group based on it's title.
*
* If the group prop is already set that will be used.
*
* @return void
*/
public function determine_rule_group() {
if ( isset( $this->group ) ) {
return;
}
// extract the hyphenated part of the title and use as group
if ( isset( $this->title ) && strstr( $this->title, '-' ) ) {
list( $this->group ) = explode( ' - ', $this->title, 2 );
}
if ( empty( $this->group ) ) {
$this->group = __( 'Other', 'email-subscribers' );
}
}
/**
* Get is/is not compare types.
*
* @return array
*/
public function get_is_or_not_compare_types() {
return [
'is' => __( 'is', 'email-subscribers' ),
'is_not' => __( 'is not', 'email-subscribers' ),
];
}
/**
* Get the string comparison types
*
* @return array
*/
public function get_string_compare_types() {
return [
'contains' => __( 'contains', 'email-subscribers' ),
'not_contains' => __( 'does not contain', 'email-subscribers' ),
'is' => __( 'is', 'email-subscribers' ),
'is_not' => __( 'is not', 'email-subscribers' ),
'starts_with' => __( 'starts with', 'email-subscribers' ),
'ends_with' => __( 'ends with', 'email-subscribers' ),
'blank' => __( 'is blank', 'email-subscribers' ),
'not_blank' => __( 'is not blank', 'email-subscribers' ),
'regex' => __( 'matches regex', 'email-subscribers' ),
];
}
/**
* Get the multiple string comparison types
*
* @return array
*/
public function get_multi_string_compare_types() {
return [
'contains' => __( 'any contains', 'email-subscribers' ),
'is' => __( 'any matches exactly', 'email-subscribers' ),
'starts_with' => __( 'any starts with', 'email-subscribers' ),
'ends_with' => __( 'any ends with', 'email-subscribers' ),
];
}
/**
* Get the Float value comparison types
*
* @return array
*/
public function get_float_compare_types() {
return $this->get_is_or_not_compare_types() + [
'greater_than' => __( 'is greater than', 'email-subscribers' ),
'less_than' => __( 'is less than', 'email-subscribers' ),
];
}
/**
* Get the integer comparison types
*
* @return array
*/
public function get_integer_compare_types() {
return $this->get_float_compare_types() + [
'multiple_of' => __( 'is a multiple of', 'email-subscribers' ),
'not_multiple_of' => __( 'is not a multiple of', 'email-subscribers' )
];
}
/**
* Get multi-select match compare types.
*
* @return array
*/
public function get_multi_select_compare_types() {
return [
'matches_all' => __( 'matches all', 'email-subscribers' ),
'matches_any' => __( 'matches any', 'email-subscribers' ),
'matches_none' => __( 'matches none', 'email-subscribers' ),
];
}
/**
* Get numeric compare types.
*/
public function get_numeric_select_compare_types() {
return [
'exactly_equal_to' => __( 'exactly equal to', 'email-subscribers' ),
'less_than_or_equal_to' => __( 'less than or equal to', 'email-subscribers' ),
'more_than_or_equal_to' => __( 'more than or equal to', 'email-subscribers' ),
];
}
/**
* Get includes or not includes compare types.
*
* @return array
*/
public function get_includes_or_not_compare_types() {
return [
'includes' => __( 'includes', 'email-subscribers' ),
'not_includes' => __( 'does not include', 'email-subscribers' ),
];
}
/**
* Check the comparison type
*
* @param $compare_type
*
* @return bool
*/
public function is_string_compare_type( $compare_type ) {
return array_key_exists( $compare_type, $this->get_string_compare_types() );
}
/**
* Check the comparison type
*
* @param $compare_type
*
* @return bool
*/
public function is_integer_compare_type( $compare_type ) {
return array_key_exists( $compare_type, $this->get_integer_compare_types() );
}
/**
* Check the comparison type
*
* @param $compare_type
*
* @return bool
*/
public function is_float_compare_type( $compare_type ) {
return array_key_exists( $compare_type, $this->get_float_compare_types() );
}
/**
* Get the is/is not comparison type
*
* @param $compare_type
*
* @return bool
*/
public function is_is_or_is_not_compare_type( $compare_type ) {
return array_key_exists( $compare_type, $this->get_is_or_not_compare_types() );
}
/**
* Validate a string based rule value.
*
* @param string $actual_value
* @param string $compare_type
* @param string $expected_value
*
* @return bool
*/
public function validate_string( $actual_value, $compare_type, $expected_value ) {
$actual_value = (string) $actual_value;
$expected_value = (string) $expected_value;
// most comparisons are case in-sensitive
$actual_value_lowercase = strtolower( $actual_value );
$expected_value_lowercase = strtolower( $expected_value );
switch ( $compare_type ) {
case 'is':
return $actual_value_lowercase == $expected_value_lowercase;
case 'is_not':
return $actual_value_lowercase != $expected_value_lowercase;
case 'contains':
return strstr( $actual_value_lowercase, $expected_value_lowercase ) !== false;
case 'not_contains':
return strstr( $actual_value_lowercase, $expected_value_lowercase ) === false;
case 'starts_with':
return str_starts_with( $actual_value_lowercase, $expected_value_lowercase );
case 'ends_with':
return str_ends_with( $actual_value_lowercase, $expected_value_lowercase );
case 'blank':
return empty( $actual_value );
case 'not_blank':
return ! empty( $actual_value );
case 'regex':
// Regex validation must not use case insensitive values
return $this->validate_string_regex( $actual_value, $expected_value );
}
return false;
}
/**
* Remove the global regex modifier as it is not supported by PHP.
*
* @param string $regex
*
* @return string
*/
protected function remove_global_regex_modifier( $regex ) {
return preg_replace_callback( '/(\/[a-z]+)$/', function ( $modifiers ) {
return str_replace( 'g', '', $modifiers[0] );
}, $regex );
}
/**
* Validates string regex rule.
*
* @param string $string
* @param string $regex
*
* @return bool
*/
protected function validate_string_regex( $string, $regex ) {
$regex = $this->remove_global_regex_modifier( trim( $regex ) );
// Add '/' delimiters if none are provided in the regex.
if ( ! preg_match( '#^/(.+)/[gi]*$#', $regex ) ) {
// Escape any unescaped delimiters in the regex first.
if ( preg_match( '#[^\\\\]/#', $regex ) ) {
$regex = str_replace( '/', '\\/', $regex );
}
$regex = '/' . $regex . '/';
}
return (bool) @preg_match( $regex, $string );
}
/**
* Only supports 'contains', 'is', 'starts_with', 'ends_with'
*
* @param array $actual_values
* @param string $compare_type
* @param string $expected_value
*
* @return bool
*/
public function validate_string_multi( $actual_values, $compare_type, $expected_value ) {
if ( empty( $expected_value ) ) {
return false;
}
// look for at least one item that validates the text match
foreach ( $actual_values as $coupon_code ) {
if ( $this->validate_string( $coupon_code, $compare_type, $expected_value ) ) {
return true;
}
}
return false;
}
/**
* Check the given two numbers against the operator
*
* @param $actual_value
* @param $compare_type
* @param $expected_value
*
* @return bool
*/
public function validate_number( $actual_value, $compare_type, $expected_value ) {
$actual_value = (float) $actual_value;
$expected_value = (float) $expected_value;
switch ( $compare_type ) {
case 'is':
return $actual_value == $expected_value;
break;
case 'is_not':
return $actual_value != $expected_value;
break;
case 'greater_than':
return $actual_value > $expected_value;
break;
case 'less_than':
return $actual_value < $expected_value;
break;
}
// validate 'multiple of' compares, only accept integers
if ( ! $this->is_whole_number( $actual_value ) || ! $this->is_whole_number( $expected_value ) ) {
return false;
}
$actual_value = (int) $actual_value;
$expected_value = (int) $expected_value;
switch ( $compare_type ) {
case 'multiple_of':
return 0 == $actual_value % $expected_value;
case 'not_multiple_of':
return 0!= $actual_value % $expected_value;
}
return false;
}
/**
* Check the given input is whole number or not
*
* @param $number
*
* @return bool
*/
public function is_whole_number( $number ) {
$number = (float) $number;
return floor( $number ) == $number;
}
/**
* Format the given value
*
* @param $value
*
* @return mixed
*/
public function format_value( $value ) {
return $value;
}
}
}

View File

@@ -0,0 +1,414 @@
<?php
/**
* Abstract class for triggers.
*
* @since 4.4.1
* @version 1.0
* @package Email Subscribers
*/
/**
* Triggers abstract class. All workflow triggers should extend this class.
*
* @class ES_Workflow_Trigger
*
* @since 4.4.1
*/
abstract class ES_Workflow_Trigger {
/**
* Trigger title
*
* @since 4.4.1
* @var string
*/
public $title;
/**
* Trigger name
*
* @since 4.4.1
* @var string
*/
public $name;
/**
* Trigger description
*
* @since 4.4.1
* @var string
*/
public $description;
/**
* Trigger group
*
* @since 4.4.1
* @var string
*/
public $group;
/**
* Supplied data by the trigger class
*
* @since 4.4.1
* @var array
*/
public $supplied_data_items = array();
/**
* Trigger fields
*
* @since 4.4.1
* @var array
*/
public $fields = array();
/**
* Trigger options
*
* @since 4.4.1
* @var array
*/
public $options;
/**
* Trigger rules
*
* @since 4.4.1
* @var array
*/
protected $rules;
/**
* Flag for trigger fields
*
* @since 4.4.1
* @var boolean
*/
protected $has_loaded_fields = false;
/**
* Flag for trigger admin fields
*
* @since 4.4.1
* @var boolean
*/
public $has_loaded_admin_details = false;
/**
* Method to register event(user registerd, comment added) to trigger class
*/
abstract public function register_hooks();
/**
* Construct
*
* @since 4.4.1
*/
public function __construct() {
$this->init();
$this->supplied_data_items = array_unique( $this->supplied_data_items );
add_action( 'ig_es_init_workflow_triggers', array( $this, 'register_hooks' ) );
}
/**
* Init
*
* @since 4.4.1
*/
public function init() {}
/**
* Method to set title, group, description and other admin props
*
* @since 4.4.1
*/
public function load_admin_details() {}
/**
* Registers any fields used on for a trigger
*
* @since 4.4.1
*/
public function load_fields() {}
/**
* Admin info loader
*
* @since 4.4.1
*/
public function maybe_load_admin_details() {
if ( ! $this->has_loaded_admin_details ) {
$this->load_admin_details();
$this->has_loaded_admin_details = true;
}
}
/**
* Field loader
*
* @since 4.4.1
*
* @modified 4.5.3 Added new action trigger_name_load_extra_fields to allow loading of extra fields for given trigger.
*/
public function maybe_load_fields() {
if ( ! $this->has_loaded_fields ) {
// Load fields defined in trigger.
$this->load_fields();
// Load extra fields for given trigger.
do_action( $this->name . '_load_extra_fields', $this );
$this->has_loaded_fields = true;
}
}
/**
* Validate a workflow against trigger
*
* @since 4.4.1
* @param ES_Workflow $workflow workflow object.
* @return bool
*/
public function validate_workflow( $workflow ) {
return true;
}
/**
* Add trigger option field
*
* @param object $option Option object.
*
* @since 4.4.6
*/
public function add_field( $option ) {
$option->set_name_base( 'ig_es_workflow_data[trigger_options]' );
$this->fields[ $option->get_name() ] = $option;
}
/**
* Get supplied data item from trigger
*
* @since 4.4.1
* @return array
*/
public function get_supplied_data_items() {
return $this->supplied_data_items;
}
/**
* Method to get trigger option field
*
* @param string $name Field name.
*
* @return ES_Field|false
*
* @since 4.4.6
*/
public function get_field( $name ) {
$this->maybe_load_fields();
if ( ! isset( $this->fields[ $name ] ) ) {
return false;
}
return $this->fields[ $name ];
}
/**
* Method to get trigger option fields
*
* @return ES_Field[]
*/
public function get_fields() {
$this->maybe_load_fields();
return $this->fields;
}
/**
* Check if there are active workflow for this trigger
*
* @return bool
*
* @since 4.6.10
*/
public function has_workflows() {
$workflow_query = new ES_Workflow_Query();
$workflow_query->set_triggers( $this->get_name() );
$workflows = $workflow_query->get_results();
if ( ! empty( $workflows ) ) {
return true;
}
return false;
}
/**
* Get workflow ids registered to use this trigger
*
* @since 4.4.1
* @return array
*/
public function get_workflow_ids() {
// Get all workflows that using this trigger.
$query = new ES_Workflow_Query();
$query->set_return( 'ids' );
$query->set_trigger( $this->get_name() );
$workflows = $query->get_results();
$workflow_ids = array();
if ( ! empty( $workflows ) ) {
foreach ( $workflows as $workflow ) {
$workflow_ids[] = $workflow['id'];
}
}
return $workflow_ids;
}
/**
* Get workflow registered to use this trigger
*
* @since 4.4.1
* @return ES_Workflow[]
*/
public function get_workflows() {
$workflows = array();
foreach ( $this->get_workflow_ids() as $workflow_id ) {
$workflow = ES_Workflow_Factory::get( $workflow_id );
if ( $workflow ) {
$workflows[] = $workflow;
}
}
return apply_filters( 'ig_es_trigger_workflows', $workflows, $this );
}
/**
* Every data item registered with the trigger should be supplied to this method in its object form.
* E.g. a 'user' should be passed as a WP_User object, and an 'order' should be passed as a WC_Order object
*
* @since 4.4.1
* @param ES_Workflow_Data_Layer|array $data_layer Workflow data layer.
*/
public function maybe_run( $data_layer = array() ) {
// Get all workflows that are registered to use this trigger.
$workflows = $this->get_workflows();
if ( ! $workflows ) {
return;
}
// Flag to check if we should start the workflow processing immediately.
$process_immediately = false;
foreach ( $workflows as $workflow ) {
// First we need to schedule all the workflows.
$workflow->schedule( $data_layer );
$timing_type = $workflow->get_timing_type();
// Check if there are any workflows which needs to run immediately.
if ( 'immediately' === $timing_type ) {
$process_immediately = true;
}
}
if ( $process_immediately ) {
$request_args = array(
'action' => 'ig_es_trigger_workflow_queue_processing',
);
IG_ES_Background_Process_Helper::send_async_ajax_request( $request_args );
}
}
/**
* Get trigger name
*
* @since 4.4.1
* @return string
*/
public function get_name() {
return $this->name;
}
/**
* Set trigger name
*
* @since 4.4.1
* @param string $name trigger name.
*/
public function set_name( $name ) {
$this->name = $name;
}
/**
* Get trigger title
*
* @since 4.4.1
* @return string
*/
public function get_title() {
$this->maybe_load_admin_details();
return $this->title;
}
/**
* Get trigger group
*
* @since 4.4.1
* @return string
*/
public function get_group() {
$this->maybe_load_admin_details();
return $this->group ? $this->group : __( 'Other', 'email-subscribers' );
}
/**
* Get trigger description
*
* @since 4.4.1
* @return string|null
*/
public function get_description() {
$this->maybe_load_admin_details();
return $this->description;
}
/**
* Get trigger description html
*
* @since 4.4.1
* @return string
*/
public function get_description_html() {
if ( ! $this->get_description() ) {
return '';
}
return '<p class="ig-es-field-description">' . $this->get_description() . '</p>';
}
}

View File

@@ -0,0 +1,235 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Base class for workflow placeholder variables
*/
abstract class IG_ES_Workflow_Variable {
/**
* Variable name
* wc_order.id, cart.link, user.first_name etc
*
* @var string
*/
protected $name;
/**
* Variable description
*
* @var string
*/
protected $description;
/**
* Stores parameter field objects.
*
* @var ES_Field[]
*/
protected $parameter_fields = array();
/**
* Variable data type
* e.g. wc_order in wc_order.id, cart in cart.link, user in user.first_name etc
*
* @var string
*/
protected $data_type;
/**
* Variable data field
* e.g. id in wc_order.id, link in cart.link, first_name in user.first_name etc
*
* @var string
*/
protected $data_field;
/**
* Does variable support fallback value in case no value is found
*
* @var bool
*/
public $use_fallback = true;
/**
* Knows if admin details have been loaded.
*
* @var bool
*/
public $has_loaded_admin_details = false;
/**
* Optional method
*/
public function init() {}
/**
* Method to set description and other admin props
*/
public function load_admin_details() {}
public function maybe_load_admin_details() {
if ( ! $this->has_loaded_admin_details ) {
$this->load_admin_details();
$this->has_loaded_admin_details = true;
}
}
/**
* Constructor
*/
public function __construct() {
$this->init();
}
/**
* Sets the name, data_type and data_field props
*
* @param $name
*/
public function setup( $name ) {
$this->name = $name;
list( $this->data_type, $this->data_field ) = explode( '.', $this->name );
}
/**
* Get variable description
*
* @return string
*/
public function get_description() {
$this->maybe_load_admin_details();
return $this->description;
}
/**
* Get the parameter fields for the variable.
*
* @return ES_Field[]
*/
public function get_parameter_fields() {
$this->maybe_load_admin_details();
return $this->parameter_fields;
}
/**
* Get variable name
*
* @return string
*/
public function get_name() {
return $this->name;
}
/**
* Get variable data type
*
* @return string
*/
public function get_data_type() {
return $this->data_type;
}
/**
* Get variable data field
*
* @return string
*/
public function get_data_field() {
return $this->data_field;
}
/**
* Add a parameter field to the variable.
*
* @param ES_Field $field
*/
protected function add_parameter_field( ES_Field $field ) {
$this->parameter_fields[ $field->get_name() ] = $field;
}
/**
* Add a text parameter field to the variable.
*
* @param string $name
* @param string $description
* @param bool $required
* @param string $placeholder
* @param array $extra
*/
protected function add_parameter_text_field( $name, $description, $required = false, $placeholder = '', $extra = array() ) {
$field = new ES_Text();
$field->set_name( $name );
$field->set_description( $description );
$field->set_required( $required );
$field->set_placeholder( $placeholder );
$field->meta = $extra;
if ( $required ) {
$field->add_extra_attr( 'data-required', 'yes' );
}
$this->add_parameter_field( $field );
}
/**
* Add a select parameter field to the variable.
*
* @param string $name
* @param string $description
* @param array $options
* @param bool $required
* @param array $extra
*/
protected function add_parameter_select_field( $name, $description, $options = array(), $required = false, $extra = array() ) {
$field = new ES_Select( false );
$field->set_name( $name );
$field->set_description( $description );
$field->set_required( $required );
$field->set_options( $options );
$field->meta = $extra;
if ( $required ) {
$field->add_extra_attr( 'data-required', 'yes' );
}
$this->add_parameter_field( $field );
}
/**
* Add a number parameter field to the variable.
*
* @param string $name
* @param string $description
* @param bool $required
* @param string $placeholder
* @param array $extra
*
* @since 5.3.4
*/
public function add_parameter_number_field( $name, $description, $required = false, $placeholder = '', $extra = array()) {
$field = new ES_Number();
$field->set_name( $name );
$field->set_description( $description );
$field->set_required( $required );
$field->set_placeholder( $placeholder );
$field->meta = $extra;
if ( $required ) {
$field->add_extra_attr( 'data-required', 'yes' );
}
$this->add_parameter_field( $field );
}
}