PNG %k25u25%fgd5n!
<?php
/**
* File: Ecre_Order_Tracking.php
*
* The Ecre_Order_Tracking class is responsible for tracking referral orders when an order is completed in WooCommerce.
*
* @package ECRE
* @since 1.0.0
*/
namespace ECRE;
if ( ! class_exists( 'Ecre_Order_Tracking' ) ) {
/**
* The Ecre_Order_Tracking class handles tracking referral orders.
*
* @since 1.0.0
*/
class Ecre_Order_Tracking {
/**
* Holds the settings configuration for the ECRE order tracking system.
*
* This property stores various settings retrieved from the database,
* such as email templates, discount configurations, and tracking options.
*
* @var array
*/
public $erce_settings;
/**
* Holds the settings configuration for the ECRE order tracking system.
*
* This property stores various settings retrieved from the database,
* such as email templates, discount configurations, and tracking options.
*
* @var array
*/
public $is_pro;
/**
* The default plugin settings used for order tracking behavior.
*
* @var array
*/
public $default_settings;
private $database;
/**
* Ecre_Order_Tracking constructor.
*
* Initializes the Ecre_Order_Tracking class and hooks into the
* 'woocommerce_order_status_completed' action to track and process
* referral-related logic upon order completion.
*
* @param bool $is_pro Indicates whether the user has a professional (pro) account.
* @param array $default_settings The default plugin settings used for order tracking behavior.
*
* @since 1.0.0
*/
public function __construct( $is_pro, $default_settings ) {
$this->erce_settings = get_option( 'ecre_settings', array() );
$this->is_pro = $is_pro;
$this->default_settings = $default_settings;
if ( class_exists( '\ECRE\Ecre_Database' ) ) {
$this->database = new \ECRE\Ecre_Database();
}
add_action( 'woocommerce_order_status_changed', array( $this, 'ecre_track_referral_orders_on_status_change' ), 10, 4 );
add_action( 'ecre_reward_scheduled', array( $this, 'ecre_track_referral_orders_on_completed_scheduled' ), 10, 1 );
add_action( 'woocommerce_admin_order_data_after_order_details', array( $this, 'ecre_display_referral_details_in_order_admin' ), 10, 1 );
}
/**
* Tracks referral orders when a WooCommerce order status changes.
*
* This function checks if an order's status changes to 'completed'. If so, it processes referral
* rewards by generating coupons or reward points for referrers.
*
* @param int $order_id The unique WooCommerce order ID.
* @param string $old_status The previous status of the order.
* @param string $new_status The new status of the order.
* @param object $order The WooCommerce order object.
*
* @since 2.3.1
*
* @return void
*/
public function ecre_track_referral_orders_on_status_change( $order_id, $old_status, $new_status, $order ) {
// $order = wc_get_order( $order_id );
if ( ! $order ) {
return;
}
// CHANGE THIS: Use existing database instance.
if ( $this->database ) {
$this->database->update_referral_status( $order_id, $new_status );
}
$reward_status = ! $this->is_pro
? 'completed'
: ( isset( $this->erce_settings['rewardOrderStatus']['value'] )
? str_replace( 'wc-', '', $this->erce_settings['rewardOrderStatus']['value'] )
: 'completed'
);
$enable_reward_delay_time = isset( $this->erce_settings['enableRewardDelayTime'] ) ? $this->erce_settings['enableRewardDelayTime'] : false;
$reward_delay_day = isset( $this->erce_settings['rewardDelayTime'] ) ? $this->erce_settings['rewardDelayTime'] : 0;
if ( $new_status === $reward_status ) {
if ( $this->is_pro && $enable_reward_delay_time && $reward_delay_day > 0 ) {
$schedule_status = get_post_meta( $order_id, 'ecre_reward_schedule_status', true );
if ( 'complete' !== $schedule_status && 'cancelled' !== $schedule_status ) {
// Calculate the timestamp for the scheduled event.
$timestamp = time() + ( $reward_delay_day * DAY_IN_SECONDS );
// Create a unique hook name for the order.
$unique_hook = 'ecre_schedule_referral_order_completion_' . $order_id;
// Clear any previously scheduled event for the same order.
if ( wp_next_scheduled( $unique_hook, array( $order_id ) ) ) {
wp_clear_scheduled_hook( $unique_hook, array( $order_id ) );
}
// Schedule the event.
wp_schedule_single_event( $timestamp, 'ecre_reward_scheduled', array( $order_id ) );
}
} else {
// Run immediately if no delay is specified.
$this->ecre_track_referral_orders_on_completed( $order_id );
}
}
}
/**
* Handles scheduled referral order completion.
*
* @param int $order_id The WooCommerce order ID.
*/
public function ecre_track_referral_orders_on_completed_scheduled( $order_id ) {
update_post_meta( $order_id, 'ecre_reward_schedule_status', 'complete' );
$this->ecre_track_referral_orders_on_completed( $order_id );
}
/**
* Tracks referral orders upon order completion and generates rewards for referrers.
*
* This function checks if a completed order used a referral coupon. If so, it generates a reward
* (coupon or reward points) for the referrer, marks the order as processed for rewards, and
* optionally sends a reward notification email.
*
* @param int $order_id The ID of the completed order.
*
* @return void
*/
public function ecre_track_referral_orders_on_completed( $order_id ) {
$order = wc_get_order( $order_id );
if ( ! $order ) {
return;
}
// Check if the order already has a coupon generated.
$coupon_generated = get_post_meta( $order_id, 'ecre_reward_coupon_generated', true );
$reward_point_generated = get_post_meta( $order_id, 'ecre_reward_point_generated', true );
if ( $coupon_generated || $reward_point_generated ) {
return;
}
$user_id = absint( $order->get_user_id() );
$coupons_used = $order->get_coupon_codes();
$enable_email_notifications = isset( $this->erce_settings['enableRewardEmailInvitation'] ) ? $this->erce_settings['enableRewardEmailInvitation'] : false;
$reward_type = '';
$settings_reward_type = isset( $this->erce_settings['rewardType']['value'] ) ? $this->erce_settings['rewardType']['value'] : '';
if ( ! $this->is_pro && ( 'percent' !== $settings_reward_type && 'fixed' !== $settings_reward_type ) ) {
$reward_type = $this->default_settings['rewardType']['value'];
} else {
$reward_type = $settings_reward_type;
}
if ( ! empty( $coupons_used ) ) {
foreach ( $coupons_used as $coupon_code ) {
$coupon_id = wc_get_coupon_id_by_code( $coupon_code );
$referral_user_id = absint( get_post_meta( $coupon_id, 'referral_user_id', true ) );
// Check if user ID is available.
if ( $user_id ) {
$user_id = (int) $user_id;
}
// Check if referral user ID is available.
if ( $referral_user_id ) {
$referral_user_id = (int) $referral_user_id;
}
if ( $referral_user_id ) {
$inserted_coupon = '';
if ( $this->is_pro ) {
if ( 'reward_point' === strval( $reward_type ) ) {
echo_rewards_pro()->helpers->generate_reward_point( $referral_user_id, $order_id );
update_post_meta( $order_id, 'ecre_reward_point_generated', true );
} else {
$inserted_coupon = echo_rewards_pro()->helpers->generate_reward_coupon( $referral_user_id, $order_id );
update_post_meta( $coupon_id, 'applied_coupon_code', esc_html( $inserted_coupon ) );
update_post_meta( $order_id, 'ecre_reward_coupon_generated', true );
}
} else {
$inserted_coupon = $this->ecre_generate_reward_coupon( $referral_user_id, $coupon_id, $coupon_code, $order_id );
update_post_meta( $coupon_id, 'applied_coupon_code', esc_html( $inserted_coupon ) );
update_post_meta( $order_id, 'ecre_reward_coupon_generated', true );
}
// Update referrer reward stats (total_rewards_issued + conversion_rate).
if ( $this->database ) {
$this->database->update_referrer_rewards_on_completion( $referral_user_id );
$this->database->update_dashboard_summary_rewards_on_completion( $referral_user_id );
}
// If enable mail settings then only run.
if ( $enable_email_notifications ) {
$wc_emails = WC()->mailer();
$emails_array = $wc_emails ? $wc_emails->get_emails() : array();
if ( isset( $emails_array['Ecre_Email'] ) && is_object( $emails_array['Ecre_Email'] ) ) {
$emails_array['Ecre_Email']->trigger( $referral_user_id, esc_html( $inserted_coupon ) );
}
}
}
update_post_meta( $order_id, 'ecre_referral_order_completed', true );
}
}
}
/**
* Generates a reward coupon for a given user ID if the user does not already have one.
*
* This function creates a unique reward coupon for a user based on various settings such as discount amount,discount type
* (percent or fixed), product/category restrictions, subscription limits, and more. The coupon is created using WooCommerce's
* `shop_coupon` post type, and metadata is saved for various coupon properties like usage limit, valid products, and categories.
* After creating the coupon, the function stores coupon-related data in the database for easy retrieval, including associating
* it with the referrer and the order.
*
* @since 1.0.0
*
* @param int $referral_user_id The ID of the user for whom the reward coupon is generated.
* @param int $referral_coupon_id The referral coupon ID associated with the user.
* @param string $referral_coupon_code The referral coupon code associated with the user.
* @param int $order_id The ID of the order associated with the referral.
*
* @return string|false The generated coupon code, or `false` if the coupon could not be created.
*/
public function ecre_generate_reward_coupon( $referral_user_id, $referral_coupon_id, $referral_coupon_code, $order_id ) {
$this->erce_settings = ecre_merge_with_custom_settings( $this->erce_settings, $referral_user_id );
// Generate a new reward coupon.
$coupon_code = ecre_generate_unique_coupon_code();
$currency_symbol = ecre_custom_currency_symbol();
$amount = $this->erce_settings['rewardDiscount'];
$settings_reward_type = isset( $this->erce_settings['rewardType']['value'] ) ? $this->erce_settings['rewardType']['value'] : '';
$discount_type = '';
if ( ! $this->is_pro && ( 'percent' !== $settings_reward_type && 'fixed' !== $settings_reward_type ) ) {
$discount_type = $this->default_settings['rewardType']['value'];
} else {
$discount_type = $settings_reward_type;
}
$discount = ( 'percent' === $discount_type ) ? $amount . '%' : $amount . $currency_symbol;
$selected_product_ids = isset( $this->erce_settings['rewardIncludeProducts'] ) && is_array( $this->erce_settings['rewardIncludeProducts'] ) ? array_column( $this->erce_settings['rewardIncludeProducts'], 'value' ) : array();
$exclude_product_ids = isset( $this->erce_settings['rewardExcludeProducts'] ) && is_array( $this->erce_settings['rewardExcludeProducts'] ) ? array_column( $this->erce_settings['rewardExcludeProducts'], 'value' ) : array();
$selected_categories = isset( $this->erce_settings['rewardIncludeCategories'] ) && is_array( $this->erce_settings['rewardIncludeCategories'] ) ? array_column( $this->erce_settings['rewardIncludeCategories'], 'value' ) : array();
$exclude_categories = isset( $this->erce_settings['rewardExcludeCategories'] ) && is_array( $this->erce_settings['rewardExcludeCategories'] ) ? array_column( $this->erce_settings['rewardExcludeCategories'], 'value' ) : array();
$enable_subscription_limit = $this->erce_settings['enableRewardLimitSubscriptionCoupon'];
$subscription_limit = $this->erce_settings['rewardLimitSubscriptionCoupon'];
$coupon = array(
'post_title' => $coupon_code,
'post_content' => $discount . ' off coupon',
'post_excerpt' => $discount . ' off coupon',
'post_status' => 'publish',
'post_author' => $referral_user_id,
'post_type' => 'shop_coupon',
);
$new_coupon_id = wp_insert_post( $coupon );
// Handle Expiry Date.
$enable_expiry = isset( $this->erce_settings['enableRewardExpiry'] ) ? $this->erce_settings['enableRewardExpiry'] : 0;
$validity_days = isset( $this->erce_settings['rewardCouponValidity'] ) ? (int) $this->erce_settings['rewardCouponValidity'] : 0;
$expiry_date = null;
if ( $enable_expiry && $validity_days > 0 ) {
$expiry_date = gmdate( 'Y-m-d', strtotime( "+{$validity_days} days" ) );
update_post_meta( $new_coupon_id, 'date_expires', $expiry_date );
}
if ( $this->is_pro && ! empty( $enable_subscription_limit ) ) {
update_post_meta( $new_coupon_id, '_wcs_number_payments', $subscription_limit );
}
update_post_meta( $new_coupon_id, 'discount_type', $discount_type );
update_post_meta( $new_coupon_id, 'coupon_amount', $amount );
update_post_meta( $new_coupon_id, 'individual_use', 'yes' );
update_post_meta( $new_coupon_id, 'reward_user_id', $referral_user_id );
if ( $this->erce_settings['enableRewardCouponUsageLimit'] && $this->erce_settings['rewardCouponUsageLimit'] > 0 ) {
update_post_meta( $new_coupon_id, 'usage_limit', $this->erce_settings['rewardCouponUsageLimit'] );
}
if ( ! empty( $selected_product_ids ) ) {
update_post_meta( $new_coupon_id, 'product_ids', implode( ',', $selected_product_ids ) );
}
if ( ! empty( $exclude_product_ids ) ) {
update_post_meta( $new_coupon_id, 'exclude_product_ids', implode( ',', $exclude_product_ids ) );
}
if ( ! empty( $selected_categories ) ) {
update_post_meta( $new_coupon_id, 'product_categories', $selected_categories );
}
if ( ! empty( $exclude_categories ) ) {
update_post_meta( $new_coupon_id, 'exclude_product_categories', $exclude_categories );
}
$new_coupon = new \WC_Coupon( $new_coupon_id );
$inserted_coupon_code = $new_coupon->get_code();
update_post_meta( $order_id, 'ecre_reward_coupon_code', $inserted_coupon_code );
update_post_meta( $order_id, 'ecre_reward_coupon_id', $new_coupon_id );
update_post_meta( $new_coupon_id, 'ecre_applied_referral_user_id', $referral_user_id );
update_post_meta( $new_coupon_id, 'ecre_applied_referral_coupon_code', $referral_coupon_code );
update_post_meta( $new_coupon_id, 'ecre_applied_referral_coupon_id', $referral_coupon_id );
// Store coupon in our dedicated reward coupons table.
if ( class_exists( '\ECRE\Ecre_Database' ) ) {
$coupon_data = array(
'referrer_user_id' => $referral_user_id,
'order_id' => $order_id,
'coupon_code' => $inserted_coupon_code,
'coupon_id' => $new_coupon_id,
'discount_type' => $discount_type,
'discount_amount' => $amount,
'usage_limit' => $this->erce_settings['enableRewardCouponUsageLimit'] ? $this->erce_settings['rewardCouponUsageLimit'] : 0,
'usage_count' => 0,
'status' => 'active',
'expires_at' => ( $enable_expiry && $validity_days > 0 ) ? gmdate( 'Y-m-d H:i:s', strtotime( "+{$validity_days} days" ) ) : null,
'include_products' => ! empty( $selected_product_ids ) ? $selected_product_ids : null,
'exclude_products' => ! empty( $exclude_product_ids ) ? $exclude_product_ids : null,
'include_product_categories' => ! empty( $selected_categories ) ? $selected_categories : null,
'exclude_product_categories' => ! empty( $exclude_categories ) ? $exclude_categories : null,
);
$this->database->store_reward_coupon_data( $coupon_data );
}
return $inserted_coupon_code;
}
/**
* Display referral details in the WooCommerce admin order details page.
*
* This function checks for a '_referral_user_id' post meta in the order. If it exists,
* it fetches the corresponding user's details and displays them in the admin order details page.
*
* @param WC_Order $order The WooCommerce order object.
*/
public function ecre_display_referral_details_in_order_admin( $order ) {
$order_id = $order->get_id();
// Get the referral user ID from the order meta.
$referral_user_id = get_post_meta( $order_id, '_referral_user_id', true );
$reward_user_id = get_post_meta( $order_id, '_reward_user_id', true );
$reward_type = '';
$settings_reward_type = isset( $this->erce_settings['rewardType']['value'] ) ? $this->erce_settings['rewardType']['value'] : '';
if ( ! $this->is_pro && ( 'percent' !== $settings_reward_type && 'fixed' !== $settings_reward_type ) ) {
$reward_type = $this->default_settings['rewardType']['value'];
} else {
$reward_type = $settings_reward_type;
}
if ( ! empty( $referral_user_id ) ) {
// Get user data based on the referral user ID.
$user = get_user_by( 'id', $referral_user_id );
$coupons = $order->get_coupon_codes();
// Get the scheduled reward timestamp.
$scheduled_time = wp_next_scheduled( 'ecre_reward_scheduled', array( $order_id ) );
$schedule_status = get_post_meta( $order_id, 'ecre_reward_schedule_status', true );
$reward_coupon_code = get_post_meta( $order_id, 'ecre_reward_coupon_code', true );
$reward_coupon_id = get_post_meta( $order_id, 'ecre_reward_coupon_id', true );
$reward_point = get_post_meta( $order_id, 'ecre_reward_point', true );
if ( $user ) {
?>
<div class="ecre-referral-details" style="margin-top:20px; display:inline-block; width:100%;">
<h4>
<?php echo esc_html__( 'Referral Details', 'echo-rewards' ); ?>:
</h4>
<p>
<strong>
<?php echo esc_html__( 'Referrer', 'echo-rewards' ); ?>:
</strong>
<a href="mailto:<?php echo esc_attr( $user->user_email ); ?>">
<?php echo esc_html( $user->user_email ); ?>
</a>
<span style="margin-left:3px;">| <?php echo esc_html( $user->display_name ); ?> </span>
</p>
<p>
<strong>
<?php echo esc_html__( 'Referral coupon', 'echo-rewards' ); ?>:
</strong>
<span>
<?php
$coupons = $order->get_coupon_codes();
echo ! empty( $coupons ) ? esc_html( implode( ', ', $coupons ) ) : esc_html__( 'None', 'echo-rewards' );
?>
</span>
</p>
<p>
<?php if ( 'reward_point' !== $reward_type ) { ?>
<strong><?php echo esc_html__( 'Reward coupon', 'echo-rewards' ); ?>:</strong>
<span>
<?php
if ( $scheduled_time ) {
$time_remaining = human_time_diff( time(), $scheduled_time );
// translators: %s is the time remaining until the reward is issued.
printf( esc_html__( 'Will be issued in %s', 'echo-rewards' ), esc_html( $time_remaining ) );
} elseif ( ! empty( $reward_coupon_id ) ) {
$coupon = new \WC_Coupon( $reward_coupon_id );
if ( $coupon && $coupon->get_id() ) {
echo esc_html( $coupon->get_code() );
$coupon_edit_link = admin_url( 'post.php?post=' . absint( $reward_coupon_id ) . '&action=edit' );
echo ' <a href="' . esc_url( $coupon_edit_link ) . '" style="color:#0073aa; text-decoration:underline;">' . esc_html__( 'Manage', 'echo-rewards' ) . '</a>';
} else {
echo esc_html__( 'Not available', 'echo-rewards' );
}
} else {
echo esc_html__( 'Not available', 'echo-rewards' );
}
?>
</span>
<?php } ?>
<?php if ( 'reward_point' === $reward_type ) { ?>
<strong><?php echo esc_html__( 'Reward points', 'echo-rewards' ); ?>:</strong>
<span>
<?php
if ( $scheduled_time ) {
$time_remaining = human_time_diff( time(), $scheduled_time );
// translators: %s is the time remaining until the reward is issued.
printf( esc_html__( 'Will be issued in %s', 'echo-rewards' ), esc_html( $time_remaining ) );
} elseif ( ! empty( $reward_point ) ) {
echo esc_html( $reward_point ) . ' ' . esc_html__( 'points', 'echo-rewards' );
} else {
echo esc_html__( 'Not available', 'echo-rewards' );
}
?>
</span>
<?php } ?>
<?php if ( $scheduled_time ) : ?>
<a href="#" class="button issue-now" data-order-id="<?php echo esc_attr( $order_id ); ?>">
<?php esc_html_e( 'Issue Now', 'echo-rewards' ); ?>
</a>
<a href="#" class="button cancel-schedule" data-order-id="<?php echo esc_attr( $order_id ); ?>">
<?php esc_html_e( 'Cancel', 'echo-rewards' ); ?>
</a>
<?php endif; ?>
</p>
</div>
<?php if ( $this->is_pro ) { ?>
<div id="ecre_schedule_confirmation_popup" class="ecre-schedule-popup-overlay">
<div class="ecre-popup-box">
<button id="ecre-popup-close" class="ecre-popup-close">✖</button>
<h3 id="ecre-popup-title"><?php esc_html_e( 'Confirm Action', 'echo-rewards' ); ?></h3>
<p id="ecre-popup-message"><?php esc_html_e( 'Are you sure you want to proceed?', 'echo-rewards' ); ?></p>
<div class="ecre-popup-buttons">
<button id="ecre-popup-cancel" class="ecre-popup-btn ecre-cancel"><?php esc_html_e( 'Cancel', 'echo-rewards' ); ?></button>
<button id="ecre-popup-confirm" class="ecre-popup-btn ecre-confirm"><?php esc_html_e( 'Confirm', 'echo-rewards' ); ?></button>
</div>
</div>
</div>
<?php } ?>
<?php
}
}
}
}
}