- 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>
326 lines
11 KiB
PHP
Executable File
326 lines
11 KiB
PHP
Executable File
<?php
|
|
|
|
if ( ! BWFAN_PRO_Common::is_lite_3_0() && ! class_exists( 'BWFAN_Conversions' ) ) {
|
|
|
|
class BWFAN_Conversions {
|
|
private static $ins = null;
|
|
|
|
public static function get_instance() {
|
|
if ( null === self::$ins ) {
|
|
self::$ins = new self();
|
|
}
|
|
|
|
return self::$ins;
|
|
}
|
|
|
|
public function __construct() {
|
|
add_action( 'woocommerce_order_refunded', array( $this, 'remove_conversion' ) );
|
|
add_action( 'woocommerce_order_status_cancelled', array( $this, 'remove_conversion' ) );
|
|
add_action( 'before_delete_post', array( $this, 'remove_conversion_on_deletion' ), 10, 2 );
|
|
add_filter( 'bwfan_get_global_settings', array( $this, 'modify_conversion_def_value_global' ), 10, 1 );
|
|
add_action( 'bwfan_external_event_settings', array( $this, 'bwfan_event_global_tracking_enable' ) );
|
|
|
|
add_action( 'bwf_normalize_contact_meta_after_save', array( $this, 'process_order_for_conversion' ), 5, 3 );
|
|
}
|
|
|
|
/**
|
|
* Helper function
|
|
*
|
|
* Runs on bwf_normalize_contact_meta_after_save
|
|
*
|
|
* @param $bwf_contact WooFunnels_Contact
|
|
* @param $order_id
|
|
* @param $order WC_Order
|
|
*/
|
|
public function process_order_for_conversion( $bwf_contact, $order_id, $order ) {
|
|
/** Don't process orders for conversion during the WC Import (Indexing) */
|
|
if ( true === WooFunnels_DB_Updater::$indexing ) {
|
|
return;
|
|
}
|
|
|
|
/** If renewal order, don't mark conversion */
|
|
if ( function_exists( 'wcs_order_contains_renewal' ) && wcs_order_contains_renewal( $order ) ) {
|
|
return;
|
|
}
|
|
|
|
/** Check if the Conversion already exists: */
|
|
$existing_conversion = BWFAN_Model_Conversions::get_specific_rows( 'wcid', absint( $order_id ) );
|
|
if ( ! empty( $existing_conversion ) ) {
|
|
return;
|
|
}
|
|
|
|
$order_id = absint( $order_id );
|
|
if ( ! $order instanceof WC_Order ) {
|
|
$order = wc_get_order( absint( $order_id ) );
|
|
}
|
|
|
|
if ( ! $order instanceof WC_Order || 'shop_order' !== $order->get_type() ) {
|
|
return;
|
|
}
|
|
|
|
$contact_id = $bwf_contact->get_id();
|
|
if ( empty( $contact_id ) ) {
|
|
return;
|
|
}
|
|
|
|
/** checking if there is any used $coupons of autonami generated */
|
|
$coupons = $order->get_coupon_codes();
|
|
if ( is_array( $coupons ) && count( $coupons ) > 0 ) {
|
|
$is_conversion = $this->check_coupon_for_conversion( $contact_id, $order_id, $order, $coupons );
|
|
if ( true === $is_conversion ) {
|
|
/** Found used coupon created by automation or broadcast */
|
|
return;
|
|
}
|
|
}
|
|
|
|
global $wpdb;
|
|
$global_settings = BWFAN_Common::get_global_settings();
|
|
$email_order_conversion_days = $global_settings['bwfan_order_tracking_conversion'];
|
|
$email_order_strtotime = $email_order_conversion_days * DAY_IN_SECONDS;
|
|
$order_creation_date = $order->get_date_created();
|
|
$order_from = ( strtotime( $order_creation_date ) - $email_order_strtotime );
|
|
$order_from = date( 'Y-m-d', $order_from );
|
|
$order_to = date( 'Y-m-d', strtotime( $order_creation_date ) );
|
|
|
|
/** Get automation ids in which don't need to mark conversion */
|
|
$skip_aids = BWFAN_PRO_Common::get_skip_conversion_automations();
|
|
$skip_aids = implode( ', ', $skip_aids );
|
|
|
|
/** If empty then use single quotes to avoid the sql error */
|
|
if ( empty( $skip_aids ) ) {
|
|
$skip_aids = "''";
|
|
}
|
|
|
|
$email_open = '(`mode` = 1 && `open` > 0)';
|
|
if ( false === apply_filters( 'bwfan_conversion_on_email_open', true ) ) {
|
|
$email_open = '(`mode` = 1 && `click` > 0)';
|
|
}
|
|
|
|
/**
|
|
* Fetching conversations where email opened or sms clicked of automation or broadcast within given date range
|
|
*/
|
|
$query = $wpdb->prepare( "SELECT `ID`, `cid`, `oid`, `type` FROM `{$wpdb->prefix}bwfan_engagement_tracking` WHERE DATE(`created_at`) >= %s AND DATE(`created_at`) <= %s AND ($email_open OR ((`mode` = 2 || `mode` = 3) && `click` > 0)) AND `hash_code` != '' AND `cid` = %d AND `oid` > 0 AND `type` IN (1,2) AND ( `oid` NOT IN ($skip_aids) ) ORDER BY `updated_at` DESC LIMIT 0,1", $order_from, $order_to, $contact_id );
|
|
$results = $wpdb->get_results( $query, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
|
|
|
|
/** No conversations found */
|
|
if ( ! is_array( $results ) || 0 === count( $results ) ) {
|
|
return;
|
|
}
|
|
|
|
foreach ( $results as $conversation_data ) {
|
|
$this->add_new( $order_id, $conversation_data['ID'], $contact_id, $conversation_data['oid'], $conversation_data['type'] );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param int $order_id
|
|
* @param int $conversation_id
|
|
* @param int $contact_id
|
|
* @param int $source_id
|
|
* @param int $source_type
|
|
*
|
|
* @return false|int
|
|
*/
|
|
public function add_new( $order_id, $conversation_id, $contact_id, $source_id, $source_type = 1 ) {
|
|
if ( ! class_exists( 'WooCommerce' ) ) {
|
|
return false;
|
|
}
|
|
|
|
if ( ! absint( $order_id ) > 0 || ! absint( $conversation_id ) > 0 || ! absint( $contact_id ) > 0 || ! absint( $source_id ) > 0 ) {
|
|
return false;
|
|
}
|
|
|
|
/** checking if conversion enable for automation event */
|
|
if ( 1 === absint( $source_type ) ) {
|
|
$is_conversion_enable = self::is_automation_conversion_track( $source_id );
|
|
|
|
if ( ! $is_conversion_enable ) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
$order = wc_get_order( absint( $order_id ) );
|
|
if ( ! $order instanceof WC_Order || in_array( $order->get_status(), array( 'failed', 'pending', 'cancelled', 'refunded' ) ) ) {
|
|
return false;
|
|
}
|
|
|
|
$order_base_total = $order->get_meta( '_bwfan_order_total_base' );
|
|
$order_total = ! empty( $order_base_total ) ? $order_base_total : $order->get_total();
|
|
/** @todo order base total needs to calculate and add like we did in abandonment */
|
|
$order_date = $order->get_date_paid();
|
|
$order_date = ! $order_date instanceof WC_DateTime ? $order->get_date_created() : $order_date;
|
|
if ( ! $order_date instanceof WC_DateTime ) {
|
|
$order_date = current_time( 'mysql', 1 );
|
|
} else {
|
|
$order_date->setTimezone( new DateTimeZone( 'UTC' ) );
|
|
$order_date = $order_date->format( 'Y-m-d H:i:s' );
|
|
}
|
|
$data = array(
|
|
'wcid' => absint( $order_id ),
|
|
'cid' => absint( $contact_id ),
|
|
'trackid' => absint( $conversation_id ),
|
|
'oid' => absint( $source_id ),
|
|
'otype' => absint( $source_type ),
|
|
'wctotal' => $order_total,
|
|
'date' => $order_date
|
|
);
|
|
|
|
BWFAN_Model_Conversions::insert( $data );
|
|
|
|
return BWFAN_Model_Conversions::insert_id();
|
|
}
|
|
|
|
/** checking if settings is on in automations
|
|
*
|
|
* @param $automation_id
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function is_automation_conversion_track( $automation_id ) {
|
|
$automation_meta = BWFAN_Core()->automations->get_automation_data_meta( $automation_id );
|
|
$automation_event_data = isset( $automation_meta['event_meta'] ) && ! empty( $automation_meta['event_meta'] ) ? $automation_meta['event_meta'] : array();
|
|
|
|
/** if automation version 2 then create conversion */
|
|
if ( isset( $automation_meta['v'] ) && 2 === absint( $automation_meta['v'] ) ) {
|
|
return true;
|
|
}
|
|
|
|
/** when email_open_click not set don't create conversations */
|
|
if ( ! isset( $automation_event_data['conversion_track'] ) || 1 !== absint( $automation_event_data['conversion_track'] ) ) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @param int $order_id
|
|
*/
|
|
public function remove_conversion( $order_id ) {
|
|
if ( empty( $order_id ) ) {
|
|
return;
|
|
}
|
|
$conversions = BWFAN_Model_Conversions::get_specific_rows( 'wcid', $order_id );
|
|
if ( empty( $conversions ) ) {
|
|
return;
|
|
}
|
|
|
|
foreach ( $conversions as $conversion ) {
|
|
BWFAN_Model_Conversions::delete( $conversion['ID'] );
|
|
}
|
|
}
|
|
|
|
public function modify_conversion_def_value_global( $settings ) {
|
|
if ( ! isset( $settings['bwfan_order_tracking_conversion'] ) || empty( $settings['bwfan_order_tracking_conversion'] ) ) {
|
|
$settings['bwfan_order_tracking_conversion'] = 15;
|
|
}
|
|
|
|
return $settings;
|
|
}
|
|
|
|
/**
|
|
* check coupon for conversions
|
|
*
|
|
* @param $contact_id
|
|
* @param $order_id
|
|
* @param $order
|
|
* @param $coupons
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function check_coupon_for_conversion( $contact_id, $order_id, $order, $coupons ) {
|
|
$order_email = $order->get_billing_email();
|
|
$order_phone = $order->get_billing_phone();
|
|
|
|
if ( ! is_array( $coupons ) || 0 === count( $coupons ) ) {
|
|
return false;
|
|
}
|
|
|
|
foreach ( $coupons as $coupon ) {
|
|
$coupon_id = wc_get_coupon_id_by_code( $coupon );
|
|
$coupon_automation_id = absint( get_post_meta( $coupon_id, '_bwfan_automation_id', true ) );
|
|
/** checking if coupon created with automation */
|
|
if ( $coupon_automation_id > 0 ) {
|
|
/** @todo should check tracking id by automation id, if not then any tracking id */
|
|
$track_id = $this->get_tracking_id( $order_email, $order_phone );
|
|
$this->add_new( $order_id, $track_id, $contact_id, $coupon_automation_id, 1 );
|
|
|
|
return true;
|
|
}
|
|
|
|
/** checking if coupon created using broadcast */
|
|
$coupon_broadcast_id = absint( get_post_meta( $coupon_id, '_bwfan_broadcast_id', true ) );
|
|
if ( $coupon_broadcast_id > 0 ) {
|
|
$track_id = $this->get_tracking_id( $order_email, $order_phone );
|
|
$this->add_new( $order_id, $track_id, $contact_id, $coupon_broadcast_id, 2 );
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public function bwfan_event_global_tracking_enable() {
|
|
?>
|
|
<div class="bwfan-events-email-tracking bwfan-col-sm-12 bwfan-p-0 bwfan-mt-15">
|
|
<#
|
|
conversion_tracking = '';
|
|
if(_.has(bwfan_automation_ui_data_detail.trigger.event_meta, 'conversion_track') ){
|
|
conversion_tracking = 'checked' ;
|
|
}
|
|
#>
|
|
<label class="bwfan-label-title">Conversion Tracking</label>
|
|
<div class="bwfan_email_tracking bwfan-mb-15">
|
|
<label for="bwfan_email_open">
|
|
<input type="checkbox" name="event_meta[conversion_track]" id="bwfan_conversion_track" value="1" {{conversion_tracking}}/>
|
|
<?php
|
|
esc_html_e( 'Track Conversions', 'wp-marketing-automations-pro' );
|
|
?>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Get track id using email, phone and automation id
|
|
*
|
|
* @param $order_email
|
|
* @param $order_phone
|
|
*
|
|
* @return int|mixed
|
|
*/
|
|
public static function get_tracking_id( $order_email, $order_phone ) {
|
|
global $wpdb;
|
|
$track_query = "select ID,oid,type from {$wpdb->prefix}bwfan_engagement_tracking where ((mode=1 && open>0) OR (mode=2 && click>0)) and hash_code !='' and send_to IN ('" . $order_email . "','" . $order_phone . "') order by created_at desc limit 0,1 ";
|
|
$track_results = $wpdb->get_results( $track_query, ARRAY_A ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
|
|
$track_id = ! empty( $track_results[0]['ID'] ) ? $track_results[0]['ID'] : 0;
|
|
|
|
return $track_id;
|
|
}
|
|
|
|
/**
|
|
* Delete conversion on deletion of order
|
|
*
|
|
* @param $order_id
|
|
* @param $post
|
|
*/
|
|
public function remove_conversion_on_deletion( $order_id, $post ) {
|
|
if ( empty( $order_id ) ) {
|
|
return;
|
|
}
|
|
|
|
if ( 'shop_order' !== $post->post_type ) {
|
|
return;
|
|
}
|
|
|
|
global $wpdb;
|
|
|
|
$query = $wpdb->prepare( "DELETE FROM {table_name} WHERE `wcid` = %d", $order_id );
|
|
BWFAN_Model_Conversions::query( $query );
|
|
}
|
|
}
|
|
|
|
BWFAN_Core::register( 'conversions', 'BWFAN_Conversions' );
|
|
}
|