- WordPress core y plugins - Tema Twenty Twenty-Four configurado - Plugin allow-unfiltered-html.php simplificado - .gitignore configurado para excluir wp-config.php y uploads 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1011 lines
29 KiB
PHP
Executable File
1011 lines
29 KiB
PHP
Executable File
<?php
|
|
|
|
#[AllowDynamicProperties]
|
|
class BWFAN_Automation_Controller {
|
|
/** Step Statuses */
|
|
public static $STATUS_ACTIVE = 1;
|
|
public static $STATUS_FAILED = 2;
|
|
public static $STATUS_PAUSED = 3;
|
|
public static $STATUS_WAITING = 4;
|
|
public static $STATUS_TERMINATE = 5;
|
|
public static $STATUS_RETRY = 6;
|
|
/** Step types */
|
|
public static $TYPE_WAIT = 1;
|
|
public static $TYPE_ACTION = 2;
|
|
public static $TYPE_GOAL = 3;
|
|
public static $TYPE_CONDITIONAL = 4;
|
|
public static $TYPE_EXIT = 5;
|
|
public static $TYPE_JUMP = 6;
|
|
public static $TYPE_SPLIT = 7;
|
|
/** Automation DB Row */
|
|
public $automation = array();
|
|
/** Automation Contact DB Row */
|
|
public $automation_contact = array();
|
|
public $automation_contact_data = array();
|
|
public $trail_id = '';
|
|
public $automation_id = 0;
|
|
public $contact_id = 0;
|
|
public $attempts = 0;
|
|
public $event_slug = '';
|
|
/** Step */
|
|
public $step_id = 0;
|
|
public $last_step_id = 0;
|
|
public $current_step = array();
|
|
public $type = 0;
|
|
public $status = 1;
|
|
/** Time Properties of Automation Contact */
|
|
public $e_time = 0;
|
|
public $c_date = '';
|
|
|
|
/** Start Time */
|
|
public $start_time = 0;
|
|
public $run_duration = 15;
|
|
|
|
/** Traversal Controller */
|
|
/** @var BWFAN_Traversal_Controller traverse_ins */
|
|
public $traverse_ins = null;
|
|
|
|
/** Execution stop action props */
|
|
public $should_end_automation = false;
|
|
public $end_current_process = false;
|
|
|
|
/** Caching vars */
|
|
protected $cached_automation_data = array();
|
|
protected $cached_automation_step_data = array();
|
|
|
|
public $skip_step_id = 0;
|
|
|
|
public $end_reason = '';
|
|
|
|
/** @var int Type of end automation */
|
|
public static $MANUAL_END = 1;
|
|
public static $ACTION_END = 2;
|
|
public static $BULK_ACTION_END = 3;
|
|
public static $LINK_TRIGGER_END = 4;
|
|
public static $GOAL_UPDATE_WITH_END = 5;
|
|
public static $GOAL_END = 6;
|
|
public static $CART_RECOVERED_END = 7;
|
|
public static $BEFORE_START_VALIDATION = 8;
|
|
public static $AUTOMATION_DATA_NOT_FOUND = 9;
|
|
|
|
public function __construct() {
|
|
$this->run_duration = apply_filters( 'bwfan_automation_v2_run_duration', $this->run_duration );
|
|
}
|
|
|
|
/**
|
|
* Set automation contact DB row
|
|
*
|
|
* @param $aContact
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function set_automation_data( $aContact ) {
|
|
$this->automation_contact = $aContact;
|
|
if ( ! is_array( $aContact ) || ! isset( $aContact['data'] ) ) {
|
|
return false;
|
|
}
|
|
|
|
$this->automation_contact_data = ! empty( $aContact['data'] ) ? json_decode( $aContact['data'], true ) : array();
|
|
|
|
$this->attempts = absint( $aContact['attempts'] );
|
|
$this->last_step_id = absint( $aContact['last'] );
|
|
$this->contact_id = absint( $aContact['cid'] );
|
|
$this->automation_id = absint( $aContact['aid'] );
|
|
$this->status = absint( $aContact['status'] );
|
|
$this->e_time = absint( $aContact['e_time'] );
|
|
$this->c_date = $aContact['c_date'];
|
|
$this->event_slug = $aContact['event'];
|
|
|
|
/** @todo check automation status is active or not */
|
|
|
|
$this->trail_id = ! empty( $aContact['trail'] ) ? $aContact['trail'] : md5( $aContact['ID'] . $aContact['cid'] . $aContact['c_date'] );
|
|
|
|
/** Validate event before start */
|
|
$event = BWFAN_Core()->sources->get_event( $this->event_slug );
|
|
if ( $event instanceof BWFAN_Event && false === $event->validate_v2_before_start( $aContact ) ) {
|
|
if ( empty( $aContact['trail'] ) ) {
|
|
BWFAN_Model_Automation_Contact::delete( $aContact['ID'] );
|
|
} else {
|
|
$this->end_reason = [
|
|
'type' => self::$BEFORE_START_VALIDATION
|
|
];
|
|
$this->move_to_completed();
|
|
}
|
|
|
|
$this->end_current_process = true;
|
|
|
|
return false;
|
|
}
|
|
|
|
if ( empty( $aContact['trail'] ) ) {
|
|
$this->automation_contact['trail'] = $this->trail_id;
|
|
|
|
/** First time update trail when empty */
|
|
BWFAN_Model_Automation_Contact::update( array(
|
|
'trail' => $this->trail_id,
|
|
), array(
|
|
'ID' => $aContact['ID'],
|
|
) );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Start automation contact execution
|
|
*
|
|
* @return void
|
|
*/
|
|
public function start() {
|
|
if ( true === $this->end_current_process ) {
|
|
return;
|
|
}
|
|
|
|
$this->setup_automation();
|
|
|
|
/** If current node is end node */
|
|
if ( $this->traverse_ins->is_end() ) {
|
|
$this->end_current_process = true;
|
|
$this->move_to_completed();
|
|
|
|
return;
|
|
}
|
|
|
|
/** If no next id then return */
|
|
if ( 0 === absint( $this->step_id ) ) {
|
|
$this->traverse_ins->log( $this->automation_contact['trail'] . ' - No next step id for automation id: ' . $this->automation_id . ' and contact id: ' . $this->contact_id );
|
|
|
|
return;
|
|
}
|
|
|
|
while ( ( ( time() - $this->start_time ) < $this->run_duration ) && ( false === $this->end_current_process ) ) {
|
|
$this->setup_current_step();
|
|
|
|
/** If current process needs to END */
|
|
if ( true === $this->end_current_process ) {
|
|
return;
|
|
}
|
|
|
|
$this->process_current_step();
|
|
|
|
/** If current process needs to END */
|
|
if ( true === $this->end_current_process ) {
|
|
return;
|
|
}
|
|
|
|
$this->setup_next_step();
|
|
|
|
/** If current node is end node */
|
|
if ( $this->traverse_ins->is_end() ) {
|
|
$this->end_current_process = true;
|
|
$this->move_to_completed();
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Setup automation and step
|
|
* Update old step status if required
|
|
*
|
|
* @return void
|
|
*/
|
|
public function setup_automation() {
|
|
$this->start_time = time();
|
|
|
|
/** Fetch Automation DB Row */
|
|
$this->automation = $this->get_automation_data( $this->automation_id );
|
|
|
|
/** Setup Traverse Controller */
|
|
$this->setup_traverser();
|
|
|
|
if ( ! is_array( $this->automation ) || ! isset( $this->automation['ID'] ) ) {
|
|
$automation_id = $this->automation_contact['aid'] ?? $this->automation_id;
|
|
$this->traverse_ins->log( 'Unable to get automation data for ID: ' . $automation_id );
|
|
|
|
return;
|
|
}
|
|
|
|
/** Set current step id. If last 0 then pick the start node */
|
|
$this->step_id = ( 0 === absint( $this->automation_contact['last'] ) ) ? $this->automation['start'] : $this->automation_contact['last'];
|
|
$this->traverse_ins->log( $this->automation_contact['trail'] . ' - automation last run step id: ' . $this->automation_contact['last'] . ' and step id: ' . $this->step_id );
|
|
|
|
/** Setup automation contact instance */
|
|
$this->traverse_ins->automation_contact_ins = $this;
|
|
|
|
/** Set current node id */
|
|
$valid = $this->traverse_ins->set_node_id_from_step_id( $this->step_id );
|
|
|
|
/** If node not exists i.e. deleted or draft then traverse back to active executed step */
|
|
if ( false === $valid ) {
|
|
$this->traverse_ins->maybe_traverse_back();
|
|
}
|
|
|
|
/** maybe update current step trail status */
|
|
$this->maybe_update_trail_status();
|
|
|
|
/** Set to next step if last step run found */
|
|
if ( absint( $this->automation_contact['last'] ) > 0 && ( self::$STATUS_ACTIVE === absint( $this->automation_contact['status'] ) ) ) {
|
|
$this->traverse_ins->traverse_to_next_step();
|
|
}
|
|
|
|
/** Set next step id for execution */
|
|
$step_id = $this->traverse_ins->get_current_step_id();
|
|
if ( ! empty( $step_id ) ) {
|
|
$this->step_id = $step_id;
|
|
$this->traverse_ins->log( $this->automation_contact['trail'] . ' - current step to process, id: ' . $this->step_id . '. setup_automation func end.' );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get automation data by automation id
|
|
*
|
|
* @param $aid
|
|
*
|
|
* @return array|mixed|object|void|null
|
|
*/
|
|
public function get_automation_data( $aid ) {
|
|
/** If data cached once, return */
|
|
if ( isset( $this->cached_automation_data[ $aid ] ) ) {
|
|
return $this->cached_automation_data[ $aid ];
|
|
}
|
|
|
|
$this->cached_automation_data[ $aid ] = BWFAN_Model_Automations::get_automation_with_data( $aid );
|
|
|
|
return $this->cached_automation_data[ $aid ];
|
|
}
|
|
|
|
/**
|
|
* Initialize traverse controller and set data
|
|
*
|
|
* @return void
|
|
*/
|
|
public function setup_traverser() {
|
|
$this->traverse_ins = new BWFAN_Traversal_Controller();
|
|
if ( ! is_array( $this->automation ) || empty( $this->automation ) ) {
|
|
$this->traverse_ins->current_node_id = 'end';
|
|
$this->end_reason = [
|
|
'type' => self::$AUTOMATION_DATA_NOT_FOUND,
|
|
'data' => [
|
|
'event_slug' => $this->automation_contact['event']
|
|
],
|
|
];
|
|
|
|
return;
|
|
}
|
|
$this->traverse_ins->set_steps( $this->automation['meta']['steps'] );
|
|
$this->traverse_ins->set_links( $this->automation['meta']['links'] );
|
|
|
|
$this->traverse_ins->automation_id = $this->automation_id;
|
|
$this->traverse_ins->contact_id = $this->contact_id;
|
|
$this->traverse_ins->trail_id = $this->trail_id;
|
|
}
|
|
|
|
/**
|
|
* Update step trail status to success
|
|
* For wait and goal type
|
|
*
|
|
* @return void
|
|
*/
|
|
public function maybe_update_trail_status() {
|
|
if ( false === ( 0 < absint( $this->automation_contact['last'] ) ) ) {
|
|
return;
|
|
}
|
|
BWFAN_Model_Automation_Contact_Trail::update_all_step_trail_status_complete( $this->trail_id );
|
|
}
|
|
|
|
/**
|
|
* Setup current step data
|
|
*
|
|
* @return void
|
|
*/
|
|
public function setup_current_step() {
|
|
$this->traverse_ins->log( $this->automation_contact['trail'] . ' - ' . __FUNCTION__ . ': step id: ' . $this->step_id );
|
|
|
|
$this->current_step = $this->get_automation_step_data( $this->step_id );
|
|
|
|
/** If step data doesn't exists i.e. deleted from the DB somehow then traverse to next step */
|
|
if ( empty( $this->current_step ) ) {
|
|
/** Step exists in the automation but data not present in the step table */
|
|
$this->setup_next_step();
|
|
$this->current_step = $this->get_automation_step_data( $this->step_id );
|
|
}
|
|
|
|
if ( ! is_array( $this->current_step ) || ! isset( $this->current_step['ID'] ) ) {
|
|
$this->end_current_process = true;
|
|
|
|
return;
|
|
}
|
|
|
|
$this->type = absint( $this->current_step['type'] );
|
|
}
|
|
|
|
/**
|
|
* Get automation step data by step id
|
|
*
|
|
* @param $step_id
|
|
*
|
|
* @return array|mixed|object|void|null
|
|
*/
|
|
public function get_automation_step_data( $step_id ) {
|
|
/** If data cached once, return */
|
|
if ( isset( $this->cached_automation_step_data[ $step_id ] ) ) {
|
|
return $this->cached_automation_step_data[ $step_id ];
|
|
}
|
|
|
|
$this->cached_automation_step_data[ $step_id ] = BWFAN_Model_Automation_Step::get_step_data_by_id( $step_id );
|
|
|
|
return $this->cached_automation_step_data[ $step_id ];
|
|
}
|
|
|
|
/**
|
|
* Process current step and set trail
|
|
*
|
|
* @return void
|
|
*/
|
|
public function process_current_step() {
|
|
if ( $this->e_time > time() + 5 ) {
|
|
return;
|
|
}
|
|
|
|
/** @todo Status check */
|
|
|
|
/** End automation for a contact if current step is the END */
|
|
if ( true === $this->traverse_ins->is_end() ) {
|
|
$this->end_current_process = true;
|
|
$this->move_to_completed();
|
|
|
|
return;
|
|
}
|
|
|
|
if ( empty( $this->type ) ) {
|
|
$this->end_current_process = true;
|
|
|
|
return;
|
|
}
|
|
|
|
/** Execute Steps */
|
|
switch ( $this->type ) {
|
|
case self::$TYPE_ACTION:
|
|
$this->process_action();
|
|
break;
|
|
case self::$TYPE_WAIT:
|
|
$this->process_wait();
|
|
break;
|
|
case self::$TYPE_CONDITIONAL:
|
|
$this->process_conditional();
|
|
break;
|
|
case self::$TYPE_GOAL:
|
|
$this->process_goal();
|
|
break;
|
|
case self::$TYPE_JUMP:
|
|
$this->process_jump();
|
|
break;
|
|
case self::$TYPE_SPLIT:
|
|
$this->process_split_path();
|
|
break;
|
|
case self::$TYPE_EXIT:
|
|
$this->process_exit();
|
|
break;
|
|
}
|
|
|
|
/** Special handling */
|
|
if ( true === BWFAN_Common::$end_v2_current_contact_automation ) {
|
|
$this->end_current_process = true;
|
|
|
|
BWFAN_Common::$end_v2_current_contact_automation = false;
|
|
}
|
|
|
|
/** Check if automation needs to END for a contact */
|
|
if ( true === $this->should_end_automation ) {
|
|
$this->end_current_process = true;
|
|
$this->move_to_completed();
|
|
|
|
return;
|
|
}
|
|
|
|
$this->last_step_id = $this->step_id;
|
|
|
|
/**
|
|
* For `wait` and `jump` step only
|
|
* If skip_step_id found then set it as last_step_id
|
|
* Set status to retry so that it can re-run on the same last executed step which will be skip_step_id i.e. jump step
|
|
*/
|
|
if ( in_array( $this->type, [ self::$TYPE_WAIT, self::$TYPE_JUMP ], true ) && intval( $this->skip_step_id ) > 0 ) {
|
|
$this->last_step_id = $this->skip_step_id;
|
|
$this->status = self::$STATUS_RETRY;
|
|
}
|
|
|
|
/** Update automation contact DB row */
|
|
$this->update_automation_contact();
|
|
}
|
|
|
|
/**
|
|
* Move automation contact row to complete table
|
|
*
|
|
* @return void
|
|
*/
|
|
public function move_to_completed() {
|
|
/** Unset if conditional result node id present */
|
|
if ( isset( $this->automation_contact_data['node_id'] ) ) {
|
|
unset( $this->automation_contact_data['node_id'] );
|
|
}
|
|
|
|
if ( ! empty( $this->end_reason ) ) {
|
|
$this->automation_contact_data['end_reason'] = $this->end_reason;
|
|
}
|
|
|
|
$data = array(
|
|
'cid' => empty( $this->contact_id ) && isset( $this->automation_contact['cid'] ) ? $this->automation_contact['cid'] : $this->contact_id,
|
|
'aid' => empty( $this->automation_id ) && isset( $this->automation_contact['aid'] ) ? $this->automation_contact['aid'] : $this->automation_id,
|
|
'event' => empty( $this->event_slug ) && isset( $this->automation_contact['event'] ) ? $this->automation_contact['event'] : $this->event_slug,
|
|
's_date' => empty( $this->c_date ) && isset( $this->automation_contact['c_date'] ) ? $this->automation_contact['c_date'] : $this->c_date,
|
|
'c_date' => current_time( 'mysql', 1 ),
|
|
'data' => json_encode( $this->automation_contact_data ),
|
|
'trail' => empty( $this->trail_id ) && isset( $this->automation_contact['trail'] ) ? $this->automation_contact['trail'] : $this->trail_id,
|
|
);
|
|
BWFAN_Model_Automation_Complete_Contact::insert_ignore( $data, [
|
|
'%d',// cid
|
|
'%d',// aid
|
|
'%s',// event
|
|
'%s',// s_date
|
|
'%s',// c_date
|
|
'%s',// data
|
|
'%s',// trail
|
|
] );
|
|
|
|
/** Delete the row from automation contact table */
|
|
BWFAN_Model_Automation_Contact::delete( $this->automation_contact['ID'] );
|
|
|
|
/** Update status as success for any step trail where status was waiting */
|
|
BWFAN_Model_Automation_Contact_Trail::update_all_step_trail_status_complete( $this->trail_id );
|
|
|
|
/**Update automation contact fields */
|
|
BWFAN_Common::update_automation_contact_fields( $this->contact_id, $this->automation_id );
|
|
}
|
|
|
|
/**
|
|
* Process action step
|
|
*
|
|
* @return void
|
|
*/
|
|
public function process_action() {
|
|
$ins = new BWFAN_Action_Controller();
|
|
$ins->populate_automation_contact_data( $this->automation_contact );
|
|
$ins->populate_step_data( $this->current_step );
|
|
|
|
if ( 'wp_sendemail' !== $ins->action_data['action'] && ! BWFAN_Common::check_for_lks() ) {
|
|
$this->set_trail_item( [ 'error_msg' => __( 'License Expired. Renew Now.', 'wp-marketing-automations' ) ], 3 );
|
|
|
|
$this->status = self::$STATUS_FAILED;
|
|
$this->e_time = current_time( 'timestamp', 1 );
|
|
|
|
$this->end_current_process = true;
|
|
|
|
return;
|
|
}
|
|
|
|
$result = $ins->execute_action();
|
|
if ( $result instanceof WP_Error ) {
|
|
$message = $result->get_error_message();
|
|
$result = array(
|
|
'message' => $message,
|
|
'status' => BWFAN_Action::$RESPONSE_FAILED,
|
|
);
|
|
}
|
|
|
|
$this->status = BWFAN_Automation_Controller::$STATUS_ACTIVE;
|
|
|
|
if ( ! is_array( $result ) || ! isset( $result['status'] ) ) {
|
|
$this->traverse_ins->log( $this->automation_contact['trail'] . ' - Unable to process action for step ID: ' . $this->step_id . ', contact: ' . $this->contact_id . ', automation: ' . $this->automation_id );
|
|
|
|
$this->e_time = current_time( 'timestamp', 1 ) + ( 5 * MINUTE_IN_SECONDS );
|
|
$this->attempts = 0;
|
|
|
|
$this->end_current_process = true;
|
|
|
|
return;
|
|
}
|
|
|
|
/** Action skipped */
|
|
if ( $result['status'] === BWFAN_Action::$RESPONSE_SKIPPED ) {
|
|
$this->set_trail_item( [ 'msg' => $result['message'] ], 4 );
|
|
|
|
$this->attempts = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
/** Action successfully executed */
|
|
if ( $result['status'] === BWFAN_Action::$RESPONSE_SUCCESS ) {
|
|
$this->set_trail_item();
|
|
|
|
$this->attempts = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
/** Action failed, reattempt possible */
|
|
if ( $result['status'] === BWFAN_Action::$RESPONSE_REATTEMPT ) {
|
|
$this->set_trail_item( [ 'error_msg' => $result['message'] ], 3 );
|
|
|
|
$this->e_time = time() + ( 5 * MINUTE_IN_SECONDS );
|
|
if ( isset( $result['e_time'] ) && absint( $result['e_time'] ) > time() ) {
|
|
$this->e_time = absint( $result['e_time'] );
|
|
}
|
|
|
|
$this->attempts ++;
|
|
$this->status = self::$STATUS_RETRY;
|
|
|
|
$this->end_current_process = true;
|
|
|
|
return;
|
|
}
|
|
|
|
$this->set_trail_item( [ 'error_msg' => $result['message'] ], 3 );
|
|
|
|
/** Action permanently failed to execute */
|
|
$this->status = self::$STATUS_FAILED;
|
|
$this->e_time = current_time( 'timestamp', 1 );
|
|
|
|
$this->end_current_process = true;
|
|
}
|
|
|
|
/**
|
|
* Insert row in contact step trail table
|
|
*
|
|
* @param $message
|
|
* @param $status
|
|
*
|
|
* @return void
|
|
*/
|
|
public function set_trail_item( $message = '', $status = 1 ) {
|
|
$arr = array(
|
|
'tid' => $this->trail_id,
|
|
'cid' => $this->contact_id,
|
|
'aid' => $this->automation_id,
|
|
'sid' => $this->step_id,
|
|
'c_time' => time(),
|
|
'status' => $status,
|
|
);
|
|
|
|
if ( isset( $message['msg'] ) && is_string( $message['msg'] ) && strlen( $message['msg'] ) > 220 ) {
|
|
$message['msg'] = substr( $message['msg'], 0, 220 );
|
|
}
|
|
|
|
if ( isset( $message['error_msg'] ) && is_string( $message['error_msg'] ) && strlen( $message['error_msg'] ) > 220 ) {
|
|
$message['error_msg'] = substr( $message['error_msg'], 0, 220 );
|
|
}
|
|
|
|
if ( ! empty( $message ) ) {
|
|
$arr['data'] = json_encode( $message );
|
|
}
|
|
|
|
BWFAN_Model_Automation_Contact_Trail::insert( $arr );
|
|
}
|
|
|
|
/**
|
|
* Process wait step
|
|
*
|
|
* @return void
|
|
*/
|
|
public function process_wait() {
|
|
$ins = new BWFAN_Delay_Controller();
|
|
$ins->populate_automation_contact_data( $this->automation_contact );
|
|
$ins->populate_step_data( $this->current_step );
|
|
|
|
$this->attempts = 0;
|
|
|
|
$time = $ins->get_time();
|
|
if ( empty( $time ) ) {
|
|
BWFAN_Common::log_test_data( 'Wait Step: Unable to get the wait time, step ID: ' . $this->step_id . ', automation ID: ' . $this->automation_id, 'process-wait-error' );
|
|
$this->set_trail_item( [ 'error_msg' => __( 'Unable to get the delayed time', 'wp-marketing-automations' ) ], 3 );
|
|
$this->status = self::$STATUS_FAILED;
|
|
$this->e_time = current_time( 'timestamp', 1 );
|
|
$this->end_current_process = true;
|
|
|
|
return;
|
|
}
|
|
|
|
/** If execution time has passed skip to the step */
|
|
$step_data = $ins->step_data;
|
|
$enable_step_skip = isset( $step_data['sidebarData']['data']['enable_step_skip'] ) ? $step_data['sidebarData']['data']['enable_step_skip'] : 0;
|
|
if ( current_time( 'timestamp', 1 ) > $time && ! empty( $enable_step_skip ) ) {
|
|
$this->skip_step_id = isset( $step_data['sidebarData']['data']['skip_to_step']['step'] ) ? $step_data['sidebarData']['data']['skip_to_step']['step'] : 0;
|
|
$is_step_active = BWFAN_Model_Automation_Step::is_step_active( intval( $this->skip_step_id ) );
|
|
if ( empty( $is_step_active ) && 'end' !== $this->skip_step_id ) {
|
|
$this->end_current_process = true;
|
|
$this->skip_step_id = 0;
|
|
$this->set_trail_item( [ 'error_msg' => __( 'Jump step deleted', 'wp-marketing-automations' ) ], 3 );
|
|
|
|
$this->status = BWFAN_Automation_Controller::$STATUS_FAILED;
|
|
$this->attempts = 0;
|
|
|
|
return;
|
|
}
|
|
BWFAN_Common::log_test_data( 'Wait Step: Skipped as time passed, step ID: ' . $this->step_id . ', automation ID: ' . $this->automation_id . '. Next Step ID: ' . $this->skip_step_id, 'process-wait-skipped' );
|
|
if ( 'end' === $this->skip_step_id ) {
|
|
$this->should_end_automation = true;
|
|
}
|
|
|
|
$this->set_trail_item( [ 'msg' => __( 'Skipped as time passed', 'wp-marketing-automations' ) ], 2 );
|
|
} else {
|
|
$this->set_trail_item( '', 2 );
|
|
}
|
|
|
|
$this->e_time = $time;
|
|
$this->status = BWFAN_Automation_Controller::$STATUS_ACTIVE;
|
|
|
|
$this->end_current_process = true;
|
|
}
|
|
|
|
/**
|
|
* Process conditional step
|
|
*
|
|
* @return void
|
|
*/
|
|
public function process_conditional() {
|
|
/** If pro is not active */
|
|
if ( false === bwfan_is_autonami_pro_active() ) {
|
|
$this->set_trail_item( [ 'msg' => 'This is a pro feature' ], 3 );
|
|
|
|
return;
|
|
}
|
|
|
|
$current_step = $this->traverse_ins->get_current_step();
|
|
|
|
BWFAN_Core()->rules->load_rules_classes();
|
|
|
|
$ins = new BWFAN_Conditional_Controller();
|
|
$ins->contact_id = $this->automation_contact['cid'];
|
|
$ins->automation_id = $this->automation_contact['aid'];
|
|
$ins->step_id = absint( $current_step['stepId'] );
|
|
|
|
$ins->populate_step_data( $this->current_step );
|
|
$ins->populate_automation_contact_data( $this->automation_contact );
|
|
|
|
try {
|
|
$result = $ins->is_match();
|
|
$this->traverse_ins->conditional_result_node_id = $current_step['id'] . ( ( true === $result ) ? 'yes' : 'no' );
|
|
|
|
$this->update_conditional_step_result( $this->traverse_ins->conditional_result_node_id );
|
|
$result = ( true === $result ) ? '1' : '0';
|
|
$this->set_trail_item( [ 'msg' => $result ] );
|
|
|
|
$this->status = BWFAN_Automation_Controller::$STATUS_ACTIVE;;
|
|
$this->attempts = 0;
|
|
|
|
return;
|
|
} catch ( Error $e ) {
|
|
$result = $e->getMessage();
|
|
$trail_status = BWFAN_Action::$RESPONSE_REATTEMPT;
|
|
}
|
|
|
|
$attempt_limit = $ins->get_retry_data();
|
|
/** If attempt limit exceed then mark failed */
|
|
if ( ! is_array( $attempt_limit ) || ( count( $attempt_limit ) <= $this->attempts ) ) {
|
|
$trail_status = BWFAN_Action::$RESPONSE_FAILED;
|
|
}
|
|
|
|
/** Condition failed, reattempt possible */
|
|
if ( $trail_status === BWFAN_Action::$RESPONSE_REATTEMPT ) {
|
|
$this->set_trail_item( [ 'msg' => $result ], $trail_status );
|
|
$this->attempts ++;
|
|
$time = isset( $attempt_limit[ $this->attempts - 1 ] ) ? $attempt_limit[ $this->attempts - 1 ] : 5 * MINUTE_IN_SECONDS;
|
|
$this->e_time = time() + $time;
|
|
$this->status = self::$STATUS_RETRY;
|
|
$this->end_current_process = true;
|
|
|
|
return;
|
|
}
|
|
|
|
$this->set_trail_item( [ 'msg' => $result ], 3 );
|
|
|
|
/** Action permanently failed to execute */
|
|
$this->status = self::$STATUS_FAILED;
|
|
$this->e_time = current_time( 'timestamp', 1 );
|
|
|
|
$this->end_current_process = true;
|
|
}
|
|
|
|
/**
|
|
* Process goal step
|
|
*
|
|
* @return void
|
|
*/
|
|
public function process_goal() {
|
|
/** Pro is not active */
|
|
if ( false === bwfan_is_autonami_pro_active() ) {
|
|
$this->set_trail_item( [ 'msg' => __( 'This is a pro feature', 'wp-marketing-automations' ) ] );
|
|
|
|
return;
|
|
}
|
|
|
|
$current_step = $this->traverse_ins->get_current_step();
|
|
|
|
$ins = new BWFAN_Goal_Controller();
|
|
$ins->step_id = absint( $current_step['stepId'] );
|
|
|
|
$set_data = $ins->populate_step_data( $this->current_step );
|
|
|
|
if ( ! $set_data ) {
|
|
$this->set_trail_item( [ 'error_msg' => __( 'Goal step is not configured', 'wp-marketing-automations' ) ], 3 );
|
|
$this->status = self::$STATUS_FAILED;
|
|
$this->e_time = current_time( 'timestamp', 1 );
|
|
$this->end_current_process = true;
|
|
|
|
return;
|
|
}
|
|
|
|
$result = $ins->traverse_setting;
|
|
$this->traverse_ins->log( $this->automation_contact['trail'] . ' - process_goal result: ' . $result );
|
|
|
|
/** Check if goal already met */
|
|
$event = isset( $ins->action_data['benchmark'] ) ? BWFAN_Core()->sources->get_event( $ins->action_data['benchmark'] ) : '';
|
|
if ( $event instanceof BWFAN_Event && method_exists( $event, 'pre_validate_goal' ) && $event->pre_validate_goal( $ins->step_data, $this->contact_id ) ) {
|
|
$this->set_trail_item( [ 'msg' => $result ] );
|
|
$this->status = BWFAN_Automation_Controller::$STATUS_ACTIVE;
|
|
$this->attempts = 0;
|
|
|
|
$this->traverse_ins->log( $this->automation_contact['trail'] . ' - Goal is already met for event: ' . $event->get_name() );
|
|
|
|
return;
|
|
}
|
|
|
|
/** Traverse End */
|
|
if ( $result === BWFAN_Goal_Controller::$TRAVERSE_SETTING_END ) {
|
|
$this->set_trail_item( [ 'msg' => $result ] );
|
|
$this->should_end_automation = true;
|
|
$this->end_reason = [
|
|
'type' => self::$GOAL_END,
|
|
'data' => [
|
|
'sid' => $this->step_id
|
|
]
|
|
];
|
|
|
|
return;
|
|
}
|
|
|
|
/** Traverse Wait */
|
|
if ( $result === BWFAN_Goal_Controller::$TRAVERSE_SETTING_WAIT ) {
|
|
$this->set_trail_item( [ 'msg' => $result ], 2 );
|
|
$this->status = self::$STATUS_WAITING;
|
|
$this->attempts = 0;
|
|
|
|
$this->end_current_process = true;
|
|
|
|
return;
|
|
}
|
|
|
|
/** Traverse Continue */
|
|
$this->set_trail_item( [ 'msg' => $result ] );
|
|
|
|
$this->status = BWFAN_Automation_Controller::$STATUS_ACTIVE;
|
|
$this->attempts = 0;
|
|
}
|
|
|
|
/**
|
|
* Process jump step
|
|
*
|
|
* @return void
|
|
*/
|
|
public function process_jump() {
|
|
/** Pro is not active */
|
|
if ( false === bwfan_is_autonami_pro_active() ) {
|
|
$this->set_trail_item( [ 'msg' => 'This is a pro feature' ] );
|
|
|
|
return;
|
|
}
|
|
|
|
$current_step = $this->traverse_ins->get_current_step();
|
|
|
|
$ins = new BWFAN_Jump_Controller();
|
|
$ins->step_id = absint( $current_step['stepId'] );
|
|
|
|
$ins->populate_step_data( $this->current_step );
|
|
$this->skip_step_id = $ins->get_jump_step_id();
|
|
|
|
/** If jump step deleted then end automation */
|
|
$skip_step_data = BWFAN_Model_Automation_Step::is_step_active( $this->skip_step_id );
|
|
if ( empty( $skip_step_data ) && 'end' !== $this->skip_step_id ) {
|
|
$this->end_current_process = true;
|
|
$this->set_trail_item( [ 'msg' => 'Jump step deleted' ], 3 );
|
|
|
|
$this->status = BWFAN_Automation_Controller::$STATUS_FAILED;
|
|
$this->attempts = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
if ( 'end' === $this->skip_step_id ) {
|
|
$this->should_end_automation = true;
|
|
}
|
|
$jump_step_name = $ins->get_jump_step_name();
|
|
|
|
/** Traverse Continue */
|
|
$this->set_trail_item( [ 'msg' => 'Jumped to ' . $jump_step_name ] );
|
|
|
|
$this->status = BWFAN_Automation_Controller::$STATUS_ACTIVE;
|
|
$this->attempts = 0;
|
|
|
|
$this->end_current_process = true;
|
|
}
|
|
|
|
/**
|
|
* Process split path step
|
|
*
|
|
* @return void
|
|
*/
|
|
public function process_split_path() {
|
|
/** If pro is not active */
|
|
if ( false === bwfan_is_autonami_pro_active() ) {
|
|
$this->set_trail_item( [ 'msg' => 'This is a pro feature' ], 3 );
|
|
|
|
return;
|
|
}
|
|
$current_step = $this->traverse_ins->get_current_step();
|
|
|
|
$ins = new BWFAN_Split_Test_Controller();
|
|
$ins->automation = $this->automation;
|
|
$ins->current_node_id = $this->traverse_ins->current_node_id;
|
|
$ins->automation_id = $this->automation_contact['aid'];
|
|
$ins->step_id = absint( $current_step['stepId'] );
|
|
|
|
$ins->populate_step_data( $this->current_step );
|
|
$ins->populate_automation_contact_data( $this->automation_contact );
|
|
$path = $ins->get_next_path();
|
|
|
|
$this->traverse_ins->split_result_node_id = $current_step['id'] . '-path-' . $path;
|
|
$this->update_split_result( $this->traverse_ins->split_result_node_id, $ins );
|
|
$this->set_trail_item( [ 'path' => "$path" ] );
|
|
|
|
$this->status = BWFAN_Automation_Controller::$STATUS_ACTIVE;
|
|
}
|
|
|
|
/**
|
|
* Process exit step
|
|
*
|
|
* @return void
|
|
*/
|
|
public function process_exit() {
|
|
/** Pro is not active */
|
|
if ( false === bwfan_is_autonami_pro_active() ) {
|
|
$this->set_trail_item( [ 'msg' => 'This is a pro feature' ], 3 );
|
|
|
|
return;
|
|
}
|
|
|
|
$this->should_end_automation = true;
|
|
|
|
$this->set_trail_item();
|
|
}
|
|
|
|
/**
|
|
* Update automation contact row
|
|
*
|
|
* @return void
|
|
*/
|
|
public function update_automation_contact() {
|
|
if ( absint( $this->attempts ) > 0 && self::$STATUS_RETRY !== $this->status ) {
|
|
$this->attempts = 0;
|
|
}
|
|
|
|
BWFAN_Model_Automation_Contact::update( array(
|
|
'last' => $this->last_step_id,
|
|
'attempts' => $this->attempts,
|
|
'status' => $this->status,
|
|
'e_time' => $this->e_time,
|
|
'last_time' => current_time( 'timestamp', 1 ),
|
|
), array(
|
|
'ID' => $this->automation_contact['ID'],
|
|
) );
|
|
}
|
|
|
|
/**
|
|
* Update conditional step result data in the database
|
|
*
|
|
* @param $node_id
|
|
*
|
|
* @return void
|
|
*/
|
|
public function update_conditional_step_result( $node_id = '' ) {
|
|
$data = $this->automation_contact_data;
|
|
|
|
if ( empty( $node_id ) ) {
|
|
if ( isset( $data['node_id'] ) ) {
|
|
unset( $data['node_id'] );
|
|
}
|
|
} else {
|
|
$data['node_id'] = $node_id;
|
|
}
|
|
/** Set automation contact data back */
|
|
$this->automation_contact_data = $data;
|
|
|
|
BWFAN_Model_Automation_Contact::update( array(
|
|
'data' => wp_json_encode( $data )
|
|
), array(
|
|
'ID' => $this->automation_contact['ID'],
|
|
) );
|
|
}
|
|
|
|
/**
|
|
* Update the split path result
|
|
*
|
|
* @param $node_id
|
|
* @param $split_ins BWFAN_Split_Test_Controller
|
|
*
|
|
* @return void
|
|
*/
|
|
public function update_split_result( $node_id, $split_ins ) {
|
|
$step = $this->current_step;
|
|
|
|
$data = isset( $step['data'] ) ? json_decode( $step['data'], true ) : [];
|
|
$sidebarData = isset( $data['sidebarData'] ) ? $data['sidebarData'] : [];
|
|
$path_no = str_replace( $split_ins->current_node_id . '-path-', '', $node_id );
|
|
$sidebarData['last_run'] = $path_no;
|
|
$updated_data = [
|
|
'sidebarData' => $sidebarData
|
|
];
|
|
|
|
BWFAN_Model_Automation_Step::update( array(
|
|
'data' => wp_json_encode( $updated_data )
|
|
), array(
|
|
'ID' => $step['ID'],
|
|
) );
|
|
}
|
|
|
|
/**
|
|
* Traverse to next step
|
|
*
|
|
* @return void
|
|
*/
|
|
public function setup_next_step() {
|
|
$next = $this->traverse_ins->traverse_to_next_step();
|
|
|
|
/** If current node is end node */
|
|
if ( $this->traverse_ins->is_end() ) {
|
|
return;
|
|
}
|
|
|
|
if ( false === $next ) {
|
|
$this->end_current_process = true;
|
|
$this->update_execution_time();
|
|
BWFAN_Common::log_test_data( __FUNCTION__ . ' - Unable to traverse to next step, step ID: ' . $this->step_id . ', automation ID: ' . $this->automation_id, 'traverse-error' );
|
|
|
|
return;
|
|
}
|
|
|
|
$next_step_id = $this->traverse_ins->get_current_step_id();
|
|
if ( empty( $next_step_id ) ) {
|
|
$this->end_current_process = true;
|
|
$this->update_execution_time();
|
|
BWFAN_Common::log_test_data( __FUNCTION__ . ' - No current step id found', 'traverse-error' );
|
|
|
|
return;
|
|
}
|
|
|
|
$this->step_id = $next_step_id;
|
|
}
|
|
|
|
/**
|
|
* Update execution time of automation contact by 1 min default
|
|
*
|
|
* @param $time
|
|
*
|
|
* @return void
|
|
*/
|
|
protected function update_execution_time( $time = 60 ) {
|
|
if ( empty( $this->automation_contact['ID'] ) ) {
|
|
return;
|
|
}
|
|
$time = current_time( 'timestamp', 1 ) + absint( $time );
|
|
BWFAN_Model_Automation_Contact::update( array(
|
|
'e_time' => $time,
|
|
), array(
|
|
'ID' => $this->automation_contact['ID'],
|
|
) );
|
|
|
|
}
|
|
}
|