is_goal; } public function get_goal_name() { if ( ! empty( $this->goal_name ) ) { return $this->goal_name; } return $this->event_name; } public function get_goal_desc() { if ( ! empty( $this->goal_desc ) ) { return $this->goal_desc; } return $this->event_desc; } public function validate_event( $task_details ) { $result = array(); $result['status'] = 1; $result['message'] = ''; return $result; } public function validate_event_data_before_executing_task( $data ) { return true; } public function load_hooks() { } public function get_automation_event_validation() { return array( 'status' => 1, 'message' => '', ); } public function get_automation_event_status() { return array( 'status' => 4, 'message' => __( 'Event has been changed in the automation', 'wp-marketing-automations' ), ); } public function get_automation_event_success() { return array( 'status' => 1, 'message' => '', ); } /** * show the validate checkbox in event meta fields * contains text related to wc order only. * Is overridable in the child event class * * @param $unique_slug * @param $section_label * @param $field_label */ public function get_validation_html( $unique_slug, $section_label, $field_label ) { ?>
verify time-delayed Actions. For instance, you can create a follow-up Action that runs after 30 days of placing an order. That Action won\'t trigger if the above selected Order Statuses are not matched to the order.', 'wp-marketing-automations' ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
public->load_active_automations( $this->get_slug() ); if ( ! is_array( $this->automations_arr ) || count( $this->automations_arr ) === 0 ) { BWFAN_Core()->logger->log( 'Async callback: No active automations found. Event - ' . $this->get_slug(), $this->log_type ); return false; } /** Extra checking for certain event like form events */ $this->automations_arr = $this->validate_event_data_before_creating_task( $this->automations_arr ); if ( ! is_array( $this->automations_arr ) || count( $this->automations_arr ) === 0 ) { return false; } $automation_actions = []; foreach ( $this->automations_arr as $automation_id => $automation_data ) { if ( $this->get_slug() !== $automation_data['event'] || 0 !== intval( $automation_data['requires_update'] ) ) { continue; } $ran_actions = $this->handle_single_automation_run( $automation_data, $automation_id ); $automation_actions[ $automation_id ] = $ran_actions; } return $automation_actions; } public function get_slug() { return str_replace( array( 'bwfan_' ), '', sanitize_title( get_class( $this ) ) ); } public function validate_event_data_before_creating_task( $automations_arr ) { return $automations_arr; } /** * Handle execution of each automation to get all the executable tasks for the automation. * Also responsible to run pre executable action function to instruct events to setup required data before execution. * * @param $automation_data * @param $automation_id * * @return bool|int */ public function handle_single_automation_run( $automation_data, $automation_id ) { $this->event_automation_id = $automation_id; /** Setup the rules data */ $this->pre_executable_actions( $automation_data ); /** get all the actions which have passed the rules */ $actions = $this->get_executable_actions( $automation_data ); if ( ! isset( $actions['actions'] ) || ! is_array( $actions['actions'] ) || count( $actions['actions'] ) === 0 ) { BWFAN_Core()->logger->log( 'No task eligible for Automation ID - ' . $automation_id . '. Event - ' . $this->get_slug(), $this->log_type ); return false; } $event_data = $this->get_automation_event_data( $automation_data ); /** This only occurs when sync process is going on */ if ( ! empty( $this->user_selected_actions ) ) { $final_actions = $this->filter_executable_actions( $actions['actions'] ); try { $final_actions['actions'] = $this->recalculate_actions_time( $final_actions['actions'] ); } catch ( Exception $exception ) { BWFAN_Core()->logger->log( 'Register task function not overrided by child class ->' . get_class( $this ), $this->log_type ); } $actions['actions'] = $final_actions['actions']; } try { /** Register all those tasks which passed through rules or which are direct actions. The following function is present in every event class. */ $this->register_tasks( $automation_id, $actions['actions'], $event_data ); } catch ( Exception $exception ) { BWFAN_Core()->logger->log( 'Register task function not overrided by child class' . get_class( $this ), $this->log_type ); } return count( $actions['actions'] ); } /** * Make rules data for every event. * * @param $automation_data */ public function pre_executable_actions( $automation_data ) { } /** * Get the actions which are actually going to run. * * @param $automation_meta * * @return array */ public function get_executable_actions( $automation_meta ) { $this->event_actions = []; $ui_data = isset( $automation_meta['uiData'] ) ? $automation_meta['uiData'] : []; foreach ( $ui_data as $details ) { $return_data = $this->get_actions_data( $details, $automation_meta ); if ( is_array( $return_data ) && count( $return_data ) > 0 ) { $this->event_actions[] = $return_data; } if ( $this->validation_passed ) { $this->validation_passed = false; break; } } $executable_actions = $this->combine_actions(); return $executable_actions; } /** * Get those actions which satisfies the rules. * * @param $details * @param $automation_meta * * @return array */ public function get_actions_data( $details, $automation_meta ) { $return_data = []; switch ( $details['id'] ) { case 'condition': $group_id = $details['group_id']; $group_conditions = $automation_meta['condition'][ $group_id ]; $is_passed = BWFAN_Core()->rules->match_groups( $group_conditions ); if ( $is_passed ) { $return_data['actions'] = $automation_meta['actions'][ $group_id ]; $return_data['group_id'] = $group_id; $this->validation_passed = true; } break; case 'action': $group_id = $details['group_id']; $return_data['actions'] = $automation_meta['actions'][ $group_id ]; $return_data['group_id'] = $group_id; break; default: break; } return $return_data; } /** * Combines all the actions of all groups whose tasks will be made. * @return array */ public function combine_actions() { if ( ! is_array( $this->event_actions ) || 0 === count( $this->event_actions ) ) { return $this->event_actions; } $result = []; $all_actions = []; foreach ( $this->event_actions as $details ) { $actions = $details['actions']; $group_id = $details['group_id']; if ( ! is_array( $actions ) || empty( $actions ) ) { continue; } foreach ( $actions as $key1 => $action_detail ) { if ( empty( $action_detail['action_slug'] ) || empty( $action_detail['integration_slug'] ) ) { continue; } $action_detail['group_id'] = $group_id; $action_detail['action_id'] = $key1; $all_actions[] = $action_detail; } } $this->event_actions = []; $result['actions'] = $all_actions; return $result; } /** * Returns the current event settings set in the automation at the time of task creation. * * @param $value * * @return array */ public function get_automation_event_data( $value ) { return [ 'event_source' => $value['source'], 'event_slug' => $value['event'], 'validate_event' => ( isset( $value['event_meta']['validate_event'] ) ) ? 1 : 0, ]; } public function filter_executable_actions( $actions ) { $final_actions = []; $user_selected_actions = $this->user_selected_actions; foreach ( $user_selected_actions as $group_actions ) { foreach ( $group_actions as $action_details ) { $action_slug = $action_details['action_slug']; foreach ( $actions as $act_ind => $act_det ) { $act_sl = $act_det['action_slug']; $unique_key = $act_sl . '_' . $act_ind; if ( $action_slug === $act_sl ) { if ( ! isset( $final_actions[ $unique_key ] ) ) { $final_actions[ $unique_key ] = $act_det; } } } } } sort( $final_actions ); return array( 'actions' => $final_actions, ); } /** * @param $actions * * Recalculate action's execution time with respect to order date. * * @return mixed * @throws Exception */ public function recalculate_actions_time( $actions ) { throw new ErrorException( 'This function `' . __FUNCTION__ . '` Must be override in child class' ); } public function register_tasks( $automation_id, $actions, $event_data ) { throw new ErrorException( 'This function `' . __FUNCTION__ . '` Must be override in child class' ); } /** * @param $automation - automation with data * * @return false|void */ public function run_v2( $automation, $event_slug ) { $aid = $automation['ID']; $event = BWFAN_Core()->sources->get_event( $event_slug ); $global_data = apply_filters( 'bwfan_modify_event_data', $event->get_event_data() ); $global_data = BWFAN_Common::get_global_data( $global_data ); $event_data = $this->get_automation_event_data( $automation ); $global_data['event_data'] = $event_data; $global_data['global']['automation_id'] = $aid; if ( empty( $global_data['global']['cid'] ) ) { return false; } /** Validate automation common settings like run count */ if ( false === BWFAN_Model_Automations_V2::validation_automation_run_count( $aid, $global_data['global']['cid'], $automation ) ) { BWFAN_Common::log_test_data( 'Automation ID ' . $aid . ' already run on a contact ' . $global_data['global']['cid'] . '. Event - ' . $event_slug, 'contact-exist-automation', true ); return false; } $data = [ 'cid' => intval( $global_data['global']['cid'] ), 'aid' => $aid, 'event' => $event_slug, 'c_date' => current_time( 'mysql', 1 ), 'e_time' => current_time( 'timestamp', 1 ), 'last_time' => current_time( 'timestamp', 1 ), 'data' => json_encode( $global_data ) ]; /** In case of duplicate run, when hook runs twice. */ $already_exists = BWFAN_Model_Automation_Contact::check_duplicate_automation_contact( $data ); if ( $already_exists ) { BWFAN_Common::log_test_data( 'Automation ID ' . $data['aid'] . ' already exists with same data for contact ' . $data['cid'] . '. Event - ' . $data['event'], 'contact-duplicate-automation', true ); BWFAN_Common::log_test_data( $global_data, 'contact-duplicate-automation', true ); return false; } BWFAN_Model_Automation_Contact::insert( $data ); } public function get_automations_data( $v = 1 ) { return ( 2 === $v ) ? $this->automations_v2_arr : $this->automations_arr; } public function check_if_bulk_process_executing( $should_logs_made ) { if ( is_array( $this->user_selected_actions ) && count( $this->user_selected_actions ) > 0 ) { return false; } return $should_logs_made; } /** * Create tasks of the actions. * * @param $automation_id * @param $actions * @param $event_data * @param $data */ public function create_tasks( $automation_id, $actions, $event_data, $data ) { /** Check if Autonami is in sandbox mode */ if ( true === BWFAN_Common::is_sandbox_mode_active() ) { return; } $a_track_id = $this->automations_arr[ $automation_id ]['a_track_id']; $total_tasks_made = []; /** For modify data */ $data = apply_filters( 'bwfan_modify_event_data', $data ); /** Get global data */ $data = BWFAN_Common::get_global_data( $data ); do_action( 'bwfan_before_creating_tasks', $automation_id, $actions, $event_data, $data ); $immediate_actions = []; foreach ( $actions as $index => $action ) { $should_task_create = $this->should_task_create( $action, $data ); if ( false === $should_task_create ) { continue; } // Task data can be modified before making a task $action = apply_filters( 'bwfan_pre_insert_task', $action, $automation_id, $this ); $task_id = BWFAN_Core()->tasks->insert_task( $automation_id, $action, $this ); if ( isset( $action['data_meta'] ) ) { $data['data_meta'] = $action['data_meta']; } $data['event_data'] = $event_data; $data['data'] = ( isset( $action['data'] ) ) ? $action['data'] : array(); $data['group_id'] = $action['group_id']; $data['action_id'] = $action['action_id']; $data = apply_filters( 'bwfan_alter_taskdata', $data ); $data = apply_filters( 'bwfan_alter_taskdata_' . $this->get_slug(), $data ); BWFAN_Core()->tasks->insert_taskmeta( $task_id, 'integration_data', $data ); // Unique task tracking id $t_track_id = $a_track_id . '_' . $action['group_id'] . '_' . $action['action_id']; BWFAN_Core()->tasks->insert_taskmeta( $task_id, 't_track_id', $t_track_id ); // Actions can be performed after task in inserted into db do_action( 'bwfan_task_created', $index, $task_id ); do_action( 'bwfan_task_created_' . $this->get_slug(), $index, $task_id ); $total_tasks_made[] = $task_id; /** Checking immediately executable actions */ if ( ! isset( $action['time']['delay_type'] ) || 'immediately' === $action['time']['delay_type'] ) { $immediate_actions[] = $task_id; } } do_action( 'bwfan_after_creating_tasks', $automation_id, $actions, $event_data, $data, $total_tasks_made ); /** Executing immediately executable actions */ $this->execute_immediate_tasks( $immediate_actions ); // Increase the automation run count and fire contact creation async call only when async process in not running if ( empty( $this->user_selected_actions ) ) { BWFAN_Core()->automations->update_automation_run_count( $automation_id ); if ( $this->track_automation_run ) { // Send an async call for updating contact meta $this->send_async_contact_call( $automation_id ); } } if ( count( $total_tasks_made ) > 0 ) { BWFAN_Core()->logger->log( 'Total ' . count( $total_tasks_made ) . ' tasks created. Event - ' . $this->get_slug() . ', Task IDs -' . implode( ', ', $total_tasks_made ), $this->log_type ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions } else { BWFAN_Core()->logger->log( '0 Tasks created. Event - ' . $this->get_slug(), $this->log_type ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions } } /** * Check if task for an action should be created or not. * * @param $action_data * * @return bool */ public function should_task_create( $action_data, $data ) { if ( ! isset( $action_data['integration_slug'] ) ) { return false; } $action_instance = BWFAN_Core()->integration->get_action( $action_data['action_slug'] ); /** If action not found then load connector classes */ if ( empty( $action_instance ) ) { WFCO_Load_Connectors::load_connectors_direct(); BWFAN_Load_Connectors::get_instance()->run_connectors(); $action_instance = BWFAN_Core()->integration->get_action( $action_data['action_slug'] ); } if ( ! $action_instance instanceof BWFAN_Action ) { return false; } $check_action_data = $action_instance->check_required_data( $data ); if ( false === $check_action_data ) { return false; } $check_language_support = $this->check_language_support( $action_data, $data ); if ( false === $check_language_support ) { return false; } return true; } public function check_language_support( $action_data, $data ) { /** checking for language support **/ if ( BWFAN_Common::should_skip_language_support() ) { return true; } if ( false === $this->support_lang || ! isset( $action_data['language'] ) || ! isset( $action_data['language']['enable_lang'] ) || 1 !== absint( $action_data['language']['enable_lang'] ) && ! isset( $action_data['language']['lang'] ) || empty( $action_data['language']['lang'] ) ) { return true; } $selected_lang = $action_data['language']['lang']; $lang = $this->get_language_from_event( $data ); if ( $lang === $selected_lang ) { return true; } return false; } public function get_language_from_event( $data ) { $lang = ''; $order = isset( $data['global']['wc_order'] ) ? $data['global']['wc_order'] : ''; if ( ! $order instanceof WC_Order && isset( $data['global']['order_id'] ) ) { $order = wc_get_order( $data['global']['order_id'] ); } if ( ! $order instanceof WC_Order && isset( $data['global']['wc_order_id'] ) ) { $order = wc_get_order( $data['global']['wc_order_id'] ); } if ( $order instanceof WC_Order ) { if ( isset( $data['global']['language'] ) && ! empty( $data['global']['language'] ) ) { $lang = $data['global']['language']; } } elseif ( isset( $data['global']['cart_abandoned_id'] ) ) { $cart_details = BWFAN_Model_Abandonedcarts::get( $data['global']['cart_abandoned_id'] ); $checkout_data = json_decode( $cart_details['checkout_data'], true ); if ( isset( $checkout_data['lang'] ) ) { $lang = $checkout_data['lang']; } } return $lang; } public function execute_immediate_tasks( $task_ids ) { if ( empty( $task_ids ) ) { return; } /** set claim_id to 1 for the immediate tasks so it will not run by the action scheduler */ global $wpdb; $placeholders = array_fill( 0, count( $task_ids ), '%d' ); $placeholders = implode( ', ', $placeholders ); $query = $wpdb->prepare( "UPDATE `{$wpdb->prefix}bwfan_tasks` SET `claim_id` = 1 WHERE `ID` IN ($placeholders)", $task_ids ); $wpdb->query( $query ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching /** @var BWFAN_Tasks $task_ins */ $task_ins = BWFAN_Tasks::get_instance(); foreach ( $task_ids as $id ) { $task_ins->bwfan_ac_execute_task( $id ); } } /** * Send async call for updating the contact automation details * * @param $automation_id */ public function send_async_contact_call( $automation_id ) { $email = $this->get_email_event(); if ( false === $email ) { BWFAN_Core()->logger->log( $this->error_message . '. Automation ID - ' . $automation_id . '. Event - ' . $this->get_slug(), $this->log_type ); return; } $user_id = $this->get_user_id_event(); $url = rest_url( '/autonami/v1/update-contact-automation' ); $body_data = array( 'automation_id' => $automation_id, 'email' => $email, 'user_id' => $user_id, 'unique_key' => get_option( 'bwfan_u_key', false ), ); $args = bwf_get_remote_rest_args( $body_data ); wp_remote_post( $url, $args ); } /** * If any event has email and it does not contain order object, then following method must be overridden by child event class. * Return email * @return bool */ public function get_email_event() { $order = $this->order; if ( $order instanceof WC_Order ) { return $order->get_billing_email(); } $this->error_message = __( 'Not a valid WC order object', 'wp-marketing-automations' ); $email = false; return $email; } /** * If any event has user id and it does not contain order object, then following method must be overridden by child event class. * Return user id * @return bool */ public function get_user_id_event() { $order = $this->order; if ( $order instanceof WC_Order ) { return $order->get_user_id(); } $this->error_message = __( 'Not a valid WC order object', 'wp-marketing-automations' ); $user_id = false; return $user_id; } /** * Calculate actions time based on record date. * * @param $actions * @param $record_date DateTime * * @return mixed * @throws Exception */ public function calculate_actions_time( $actions, $record_date ) { BWFAN_Common::convert_from_gmt( $record_date ); // convert to site time BWFAN_Common::convert_to_gmt( $record_date ); $record_date_timestamp = $record_date->getTimestamp(); $current_timestamp = current_time( 'timestamp', 1 ); $datetime1 = new DateTime( date( 'Y-m-d H:i:s', $record_date_timestamp ) );//start time $datetime2 = new DateTime( date( 'Y-m-d H:i:s', $current_timestamp ) );//end time $interval = $datetime1->diff( $datetime2 ); $days_difference = intval( $interval->format( '%a' ) ); $hours_difference = intval( $interval->format( '%h' ) ); $minutes_difference = intval( $interval->format( '%i' ) ); foreach ( $actions as $action_index => $action_details ) { $delay_type = $action_details['time']['delay_type']; if ( 'fixed' === $delay_type && isset( $action_details['time']['fixed_date'] ) && ! empty( $action_details['time']['fixed_date'] ) ) { $fixed_date = $action_details['time']['fixed_date']; $fixed_date_timestamp = strtotime( $fixed_date ); $fixed_time = $action_details['time']['fixed_time']; $fixed_time_seconds = BWFAN_Common::get_seconds_from_time_format( $fixed_time ); $task_actual_timestamp = intval( $fixed_date_timestamp ) + intval( $fixed_time_seconds ); if ( $task_actual_timestamp < $current_timestamp ) { $actions[ $action_index ]['time']['delay_type'] = 'immediately'; } } if ( 'after_delay' === $delay_type ) { $time_type = $action_details['time']['time_type']; $time_number = intval( $action_details['time']['time_number'] ); $new_time_number = $time_number; $time_increament_string = ''; if ( 'days' === $time_type ) { if ( $time_number > $days_difference ) { $new_time_number = $time_number - $days_difference; } $time_increament_string = '+' . $new_time_number . ' days'; } elseif ( 'hours' === $time_type ) { if ( $time_number > $hours_difference ) { $new_time_number = $time_number - $hours_difference; } $time_increament_string = '+' . $new_time_number . ' hours'; } elseif ( 'minutes' === $time_type ) { if ( $time_number > $minutes_difference ) { $new_time_number = $time_number - $minutes_difference; } $time_increament_string = '+' . $new_time_number . ' minutes'; } $timestamp = strtotime( $time_increament_string, $record_date_timestamp ); if ( $timestamp > $current_timestamp ) { $actions[ $action_index ]['time']['time_number'] = $new_time_number; } else { $actions[ $action_index ]['time']['delay_type'] = 'immediately'; } } } return $actions; } public function get_view( $db_eventmeta_saved_value ) { } public function get_default_data() { //Use in every event $source = $this->source_type; $data = array( 'source' => $source, 'event' => $this->get_slug(), ); return $data; } /** * Send the event data to endpoint for processing * * @param $data * * @return array|void|WP_Error */ public function send_async_call( $data ) { $should_fire_call = ( $this->get_current_event_automations() || $this->get_current_goal_automations() ); /** In case of Form Submission, Proceed the send_async_call, to trigger the CRM's Form feed */ $form_submit_events = BWFAN_Common::get_form_submit_events(); $is_form_submission = is_array( $form_submit_events ) && in_array( get_class( $this ), $form_submit_events ); if ( false === $should_fire_call && false === $is_form_submission ) { BWFAN_Core()->logger->log( 'No automations found for event ' . $this->get_slug(), $this->log_type ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions return; } if ( true === $is_form_submission ) { $data['is_form_submission'] = 1; } $data['unique_key'] = get_option( 'bwfan_u_key', false ); $url = rest_url( '/autonami/v1/events' ); $data = apply_filters( 'bwfan_send_async_call_data', $data ); try { $a_e_id = BWFAN_Model_Automation_Events::insert_data( $data ); } catch ( Error $e ) { BWFAN_Common::log_test_data( 'Automation Event Insert Row Error: ' . $e->getMessage(), 'db-creation-errors', true ); $table_instance = new BWFAN_DB_Table_Automation_Events(); $table_instance->create_table(); $a_e_id = BWFAN_Model_Automation_Events::insert_data( $data ); } if ( ! empty( $a_e_id ) && intval( $a_e_id ) > 0 ) { $data['a_e_id'] = $a_e_id; } $args = bwf_get_remote_rest_args( $data ); BWFAN_Common::event_advanced_logs( 'Sending data for event: ' . $this->get_slug() ); BWFAN_Common::event_advanced_logs( 'URL: ' . $url ); BWFAN_Common::event_advanced_logs( $args ); if ( 1 === BWFAN_Common::$stop_async_call && false === $this->is_force_asyc() ) { return; } $flag_saved_val = get_transient( 'bwfan_stop_async_call' ); if ( 1 === intval( $flag_saved_val ) && false === $this->is_force_asyc() ) { return; } $start_time = microtime( true ); $response = wp_remote_post( $url, $args ); $end_time = microtime( true ); if ( ( $end_time - $start_time ) > 0.2 ) { /** Curl took minimum 0.2 secs */ set_transient( 'bwfan_stop_async_call', 1, WEEK_IN_SECONDS ); BWFAN_Common::$stop_async_call = 1; } BWFAN_Common::event_advanced_logs( 'Event endpoint response' ); if ( is_wp_error( $response ) ) { BWFAN_Common::event_advanced_logs( $response->get_error_message() ); } elseif ( isset( $response['body'] ) ) { BWFAN_Common::event_advanced_logs( $response['body'] ); BWFAN_Common::event_advanced_logs( $response['response'] ); } return $response; } /** * Check if any active automation for current event is present * * @return array|bool */ public function get_current_event_automations() { BWFAN_Core()->public->load_active_automations( $this->get_slug() ); BWFAN_Core()->public->load_active_v2_automations( $this->get_slug() ); if ( ( ! is_array( $this->automations_arr ) || count( $this->automations_arr ) === 0 ) && ( ! is_array( $this->automations_v2_arr ) || count( $this->automations_v2_arr ) === 0 ) ) { return false; } return true; } /** * Get all active automations by the goal * * @return array|false */ public function get_current_goal_automations() { if ( ! $this->is_goal() ) { return false; } $goal_automations = BWFAN_Model_Automations_V2::get_goal_automations( $this->get_slug() ); return empty( $goal_automations ) ? false : $goal_automations; } public function get_contact_id_for_goal( $capture_args ) { if ( isset( $capture_args['contact_id'] ) && absint( $capture_args['contact_id'] ) > 0 ) { return absint( $capture_args['contact_id'] ); } return 0; } public function get_task_view( $global_data ) { return ''; } /** * Set global data for all the merge tags which are supported by this event. * * @param $task_meta */ public function set_merge_tags_data( $task_meta ) { $wc_order_id = BWFAN_Merge_Tag_Loader::get_data( 'wc_order_id' ); if ( empty( $wc_order_id ) || $wc_order_id !== $task_meta['global']['order_id'] ) { $set_data = array( 'wc_order_id' => $task_meta['global']['order_id'], 'email' => $task_meta['global']['email'], 'wc_order' => wc_get_order( $task_meta['global']['order_id'] ), ); BWFAN_Merge_Tag_Loader::set_data( $set_data ); } } public function get_source() { return $this->source_type; } public function get_optgroup_label() { return $this->optgroup_label; } public function get_name() { return $this->event_name; } public function get_desc() { return $this->event_desc; } public function get_priority() { return $this->priority; } public function get_included_actions() { return $this->included_actions; } public function get_excluded_actions() { return $this->excluded_actions; } public function set_event_saved_data( $data ) { $this->event_saved_data = $data; } public function is_time_independent() { return $this->is_time_independent; } /** * Return localize data of event for frontend UI * @return array */ public function get_localize_data() { $this->localize_data = [ 'source_type' => $this->source_type, 'source_type_label' => $this->optgroup_label, 'event_name' => $this->event_name, 'event_desc' => $this->event_desc, 'slug' => $this->get_slug(), 'is_time_independent' => $this->is_time_independent, 'included_actions' => $this->included_actions, 'excluded_actions' => $this->excluded_actions, 'event_saved_data' => $this->event_saved_data, 'support_lang' => $this->support_lang, 'support_v1' => $this->support_v1, 'customer_email_tag' => $this->customer_email_tag, 'available' => 'yes', 'need_unique_key' => $this->need_unique_key, 'supported_blocks' => $this->supported_blocks, ]; return apply_filters( 'bwfan_event_' . $this->get_slug() . '_localize_data', $this->localize_data, $this ); } /** * Returns event data * * @param string $selected_event * * @return mixed */ public function get_event_data_for_api( $selected_event = '' ) { if ( ! $this->is_v2() ) { return []; } $data = $this->localize_data; $default_event_field = [ [ 'id' => 'bwfan_automation_run', 'type' => 'radio', 'label' => __( 'Runs On Contact', 'wp-marketing-automations' ), 'options' => [ [ 'label' => __( 'Once', 'wp-marketing-automations' ), 'value' => 'once' ], [ 'label' => __( 'Multiple Times', 'wp-marketing-automations' ), 'value' => 'multiple' ] ], 'tip' => "", "required" => false, ], [ 'id' => 'enter_automation_on_active_contact', 'label' => __( "Allow currently active contacts in this automation to re-enter again", 'wp-marketing-automations' ), 'className' => 'bwf-tooglecontrol-advance', 'type' => 'toggle', 'toggler' => [ 'fields' => [ [ 'id' => 'bwfan_automation_run', 'value' => 'multiple', ] ], 'relation' => 'OR', ], ] ]; $default_run_value = [ 'bwfan_automation_run' => 'once' ]; $is_selected_event = $selected_event === $this->get_slug(); $fields = $is_selected_event && method_exists( $this, 'get_fields_schema' ) ? $this->get_fields_schema() : []; $default_values = $is_selected_event && method_exists( $this, 'get_default_values' ) ? $this->get_default_values() : []; $data['fields'] = ! $is_selected_event || $this->disable_default_fields ? $fields : array_merge( $fields, $default_event_field ); $data['default_values'] = ! $is_selected_event || $this->disable_default_fields ? $default_values : array_merge( $default_values, $default_run_value ); return $data; } public function is_v2() { return $this->v2; } public function get_fields_schema() { return array(); } public function is_support_v1() { return $this->support_v1; } /** * Get Goal schema data * * @return array */ public function get_goal_data_for_api() { if ( ! $this->is_v2() ) { return []; } $data = $this->localize_data; $default_goal_field = [ [ 'id' => 'bwfan_goal_run', 'type' => 'radio', 'label' => __( 'If the contact doesn\'t meet the specified goal', 'wp-marketing-automations' ), 'options' => [ [ 'label' => __( 'Wait until the goal is met', 'wp-marketing-automations' ), 'value' => 'wait' ], [ 'label' => __( 'Continue anyway', 'wp-marketing-automations' ), 'value' => 'continue' ], [ 'label' => __( 'End this automation', 'wp-marketing-automations' ), 'value' => 'end' ] ], 'tip' => "", "required" => false, ] ]; $default_run_value = [ 'bwfan_goal_run' => 'wait' ]; $schema = $this->get_goal_fields_schema(); $schema = empty( $schema ) ? $this->get_fields_schema() : $schema; $default_values = method_exists( $this, 'get_default_goal_values' ) ? $this->get_default_goal_values() : []; $data['fields'] = array_merge( $schema, $default_goal_field ); $data['default_values'] = array_merge( $default_values, $default_run_value ); return $data; } public function get_goal_fields_schema() { return array(); } public function get_default_goal_values() { return array(); } /** * Return Available event rule group * @return array */ public function get_rule_group() { $rule_groups = $this->event_rule_groups; $rule_groups = array_merge( $rule_groups, [ 'bwf_automation', 'languages', 'bwf_date_time', 'bwf_pushengage' ] ); return apply_filters( 'bwfan_event_' . $this->get_slug() . '_rules_group', $rule_groups, $this ); } /** * Return Available event Merge tag group * @return array */ public function get_merge_tag_groups() { if ( true === $this->support_lang ) { $this->event_merge_tag_groups[] = 'language'; } $this->event_merge_tag_groups[] = 'bwfan_default'; /** Added Advanced Coupon merge tags group */ if ( function_exists( 'bwfan_is_advanced_coupon_for_woocommerce_active' ) && bwfan_is_advanced_coupon_for_woocommerce_active() && defined( 'BWFAN_PRO_VERSION' ) && version_compare( BWFAN_PRO_VERSION, '3.5.3', '>=' ) ) { $this->event_merge_tag_groups[] = 'bwfan_adv_coupon'; } return apply_filters( 'bwfan_event_' . $this->get_slug() . '_merge_tag_group', $this->event_merge_tag_groups, $this ); } /** * Return user selected actions against this event * @return null */ public function get_user_selected_actions() { return $this->user_selected_actions; } public function set_automations_data( $data, $v = 1 ) { if ( empty( $data ) ) { return; } if ( 2 === $v ) { $this->automations_v2_arr = $data; return; } $this->automations_arr = $data; } public function make_task_data( $automation_id, $automation_data ) { } public function set_source_type( $type ) { $this->source_type = $type; } /** v2 Methods: START */ public function capture_async_data() { throw new ErrorException( 'This function `' . __FUNCTION__ . '` Must be override in child class' ); } /** * Validate single v2 automation if passed to run * * @param $automation_data * * @return bool */ public function validate_v2_event_settings( $automation_data ) { return true; } /** * Validate v2 automation before start * * @param $automation_contact_row * * @return bool */ public function validate_v2_before_start( $automation_contact_row ) { return true; } /** * Validate automation goal settings * * @param $automation_data * * @return bool */ public function validate_goal_settings( $automation_settings, $automation_data ) { return false; } /** * Validate automation goal settings * * @param $entity * @param $automation_data * @param $version * * @return bool */ public function validate_bulk_action_event_settings( $entity, $automation_data, $version ) { return true; } /** * Run v2 automation for a contact * Validate and save in the automation contact table * * @param $automation_id * @param $automation_data * * @return false|int * @throws Exception */ public function handle_automation_run_v2( $automation_id, $automation_data ) { /** If no start node found */ if ( ! isset( $automation_data['start'] ) || 0 === intval( $automation_data['start'] ) ) { return false; } /** Global data */ $global_data = $this->global_data; $global_data = ! is_array( $global_data ) ? [] : $global_data; $global_data = BWFAN_Common::get_global_data( $global_data ); /** Event data */ $event_data = $this->event_data; $event_data = ! is_array( $event_data ) ? [] : $event_data; $global_data['event_data'] = $event_data; /** If no contact ID found, log and return */ if ( ! isset( $global_data['global'] ) || ! isset( $global_data['global']['cid'] ) || 0 === intval( $global_data['global']['cid'] ) ) { BWFAN_Common::log_test_data( 'No cid found for Automation ID - ' . $automation_id . '. Event - ' . $this->get_slug(), 'no-contact-id', true ); BWFAN_Common::log_test_data( $global_data, 'no-contact-id', true ); return false; } /** If contact is active in automation */ $exclude_check = false; if ( isset( $automation_data['event_meta'] ) && isset( $automation_data['event_meta']['enter_automation_on_active_contact'] ) && 1 === absint( $automation_data['event_meta']['enter_automation_on_active_contact'] ) ) { $exclude_check = true; } if ( false === $exclude_check && BWFAN_Model_Automation_Contact::maybe_contact_in_automation( $global_data['global']['cid'], $automation_id ) ) { BWFAN_Common::log_test_data( 'Contact ' . $global_data['global']['cid'] . ' is active in the automation - ' . $automation_id . '. Event - ' . $this->get_slug(), 'contact-exist-automation', true ); return false; } /** Validate automation common settings like run count */ if ( false === BWFAN_Model_Automations_V2::validation_automation_run_count( $automation_id, $global_data['global']['cid'], $automation_data, $exclude_check ) ) { BWFAN_Common::log_test_data( 'Automation ID ' . $automation_id . ' already run on a contact ' . $global_data['global']['cid'] . '. Event - ' . $this->get_slug(), 'contact-exist-automation', true ); return false; } /** set automation id in event global data */ $global_data['global']['automation_id'] = $automation_id; $contact_id = intval( $global_data['global']['cid'] ); $data = [ 'cid' => $contact_id, 'aid' => $automation_id, 'event' => $this->get_slug(), 'c_date' => current_time( 'mysql', 1 ), 'e_time' => current_time( 'timestamp', 1 ), 'last_time' => current_time( 'timestamp', 1 ), 'data' => json_encode( $global_data ) ]; /** In case of duplicate run, when hook runs twice. */ $already_exists = BWFAN_Model_Automation_Contact::check_duplicate_automation_contact( $data ); if ( $already_exists ) { BWFAN_Common::log_test_data( 'Automation ID ' . $data['aid'] . ' already exists with same data for contact ' . $data['cid'] . '. Event - ' . $data['event'], 'contact-duplicate-automation', true ); BWFAN_Common::log_test_data( $global_data, 'contact-duplicate-automation', true ); return false; } $run_immediately = apply_filters( 'bwfan_run_v2_automation_immediately', true, $automation_id, $data ); if ( true === $run_immediately ) { $data['e_time'] = $data['e_time'] + 5; } BWFAN_Model_Automation_Contact::insert( $data ); $p_key = BWFAN_Model_Automation_Contact::insert_id(); BWFAN_Common::event_advanced_logs( 'Automation started on contact ID: ' . $contact_id ); $this->update_automation_contact_field( $contact_id, $automation_id ); /** Check if automation needs to run immediately */ if ( true === $run_immediately ) { $ins = BWFAN_Automation_V2_Contact::get_instance(); $ins->bwfan_ac_execute_action( $p_key ); } return $p_key; } public function update_automation_contact_field( $contact_id, $automation_id ) { if ( ! class_exists( 'BWFCRM_Contact' ) ) { return; } /** CRM contact object */ $contact = new BWFCRM_Contact( $contact_id ); if ( ! $contact->is_contact_exists() ) { return; } /** Get Automation ids from automation active field */ $active_automations = $contact->get_field_by_slug( 'automation-active' ); $active_aids = json_decode( $active_automations, true ); $active_aids = ( ! empty( $active_aids ) && is_array( $active_aids ) ) ? $active_aids : array(); $active_aids[] = (string) $automation_id; $active_aids = array_unique( $active_aids ); sort( $active_aids ); $active_aids = wp_json_encode( $active_aids ); /** Get automation ids from automation entered field */ $entered_automations = $contact->get_field_by_slug( 'automation-entered' ); $entered_aids = json_decode( $entered_automations, true ); $entered_aids = ( ! empty( $entered_aids ) && is_array( $entered_aids ) ) ? $entered_aids : array(); $entered_aids[] = (string) $automation_id; $entered_aids = array_unique( $entered_aids ); sort( $entered_aids ); $entered_aids = wp_json_encode( $entered_aids ); /** Set updated automation active and automation entered value */ $contact->set_field_by_slug( 'automation-active', $active_aids ); $contact->set_field_by_slug( 'automation-entered', $entered_aids ); $contact->save_fields(); } public function capture_v2_data( $automation_data ) { return $automation_data; } /** * to avoid unserialize of the current class */ public function __wakeup() { throw new ErrorException( 'BWFAN_Core can`t converted to string' ); } /** * to avoid serialize of the current class */ public function __sleep() { throw new ErrorException( 'BWFAN_Core can`t converted to string' ); } /** v2 Methods: END */ /** * Returns optgroup priority */ public function get_optgroup_priority() { return $this->optgroup_priority; } protected function validate_order( $data ) { if ( ! isset( $data['order_id'] ) ) { return false; } $order = wc_get_order( $data['order_id'] ); if ( $order instanceof WC_Order ) { return true; } return false; } protected function validate_subscription( $data ) { if ( ! isset( $data['wc_subscription_id'] ) || ! function_exists( 'wcs_get_subscription' ) ) { return false; } $subscription = wcs_get_subscription( $data['wc_subscription_id'] ); if ( $subscription instanceof WC_Subscription ) { return true; } return false; } public function is_db_normalize() { return false; } public function is_contact_add_to_automation_allowed() { return $this->automation_add; } /** * need to extend by child class * * @param $cid * * @return array */ public function get_manually_added_contact_automation_data( $automation_data, $cid ) { return array_merge( $automation_data, [ 'cid' => $cid ] ); } protected function is_force_asyc() { return apply_filters( 'bwfan_force_async', $this->force_async ); } /** * To avoid cloning of current class */ protected function __clone() { } /** * Get supported blocks * * @return bool|mixed */ public function get_supported_blocks() { return $this->supported_blocks; } }