context = 'woocommerce';
add_action( 'woocommerce_before_checkout_form', array( $this, 'action_add_checkout_notice' ) );
add_action( 'woocommerce_cart_loaded_from_session', array( $this, 'checkout_actions' ) );
add_action( 'woocommerce_checkout_order_processed', array( $this, 'validate_coupon_usage' ), 10, 2 );
}
/**
* Add a payment to a referrer
*
* @access protected
* @since 0.1
* @param int $referral_id The referral ID
* @return bool false if adding failed, object otherwise
*/
protected function add_payment( $referral_id ) {
// Return if the referral ID isn't valid
if( ! is_numeric( $referral_id ) ) {
return;
}
// Get the referral object
$referral = affwp_get_referral( $referral_id );
// Get the user id
$user_id = affwp_get_affiliate_user_id( $referral->affiliate_id );
// Get the user's current woocommerce credit balance
$current_balance = get_user_meta( $user_id, 'affwp_wc_credit_balance', true );
$new_balance = floatval( $current_balance + $referral->amount );
return update_user_meta( $user_id, 'affwp_wc_credit_balance', $new_balance );
}
/**
* Remove a payment from a referrer
*
* @access protected
* @since 0.1
* @param int $referral_id The referral ID
* @return bool false if removing failed, object otherwise
*/
protected function remove_payment( $referral_id ) {
// Return if the referral ID isn't valid
if( ! is_numeric( $referral_id ) ) {
return;
}
// Get the referral object
$referral = affwp_get_referral( $referral_id );
// Get the user id
$user_id = affwp_get_affiliate_user_id( $referral->affiliate_id );
// Get the user's current woocommerce credit balance
$current_balance = get_user_meta( $user_id, 'affwp_wc_credit_balance', true );
$new_balance = floatval( $current_balance - $referral->amount );
return update_user_meta( $user_id, 'affwp_wc_credit_balance', $new_balance );
}
/**
* Add notice on checkout if user can checkout with coupon
*
* @access public
* @since 0.1
* @return void
*/
public function action_add_checkout_notice() {
$balance = (float) get_user_meta( get_current_user_id(), 'affwp_wc_credit_balance', true );
$cart_coupons = WC()->cart->get_applied_coupons();
$coupon_applied = $this->check_for_coupon( $cart_coupons );
// If the user has a credit balance and haven't already generated and applied a coupon code
if( $balance && ! $coupon_applied ) {
wc_print_notice( sprintf( __( 'You have an account balance of %1$s. Would you like to use it now? Apply', 'affiliatewp-store-credit' ), wc_price( $balance ), add_query_arg( 'affwp_wc_apply_credit', 'true', WC()->cart->get_checkout_url() ) ), 'notice' );
}
}
/**
* Process checkout actions
*
* @access public
* @since 0.1
* @return void
*/
public function checkout_actions() {
if( isset( $_GET['affwp_wc_apply_credit'] ) && $_GET['affwp_wc_apply_credit'] ) {
$user_id = get_current_user_id();
// Get the credit balance and cart total
$credit_balance = (float) get_user_meta( $user_id, 'affwp_wc_credit_balance', true );
$cart_total = (float) $this->calculate_cart_subtotal();
// Determine the max possible coupon value
$coupon_total = $this->calculate_coupon_amount( $credit_balance, $cart_total );
// Bail if the coupon value was 0
if( $coupon_total <= 0 ) {
return;
}
// Attempt to generate a coupon code
$coupon_code = $this->generate_coupon( $user_id, $coupon_total );
// If a coupon code was successfully generated, apply it
if( $coupon_code ) {
WC()->cart->add_discount( $coupon_code );
wp_redirect( remove_query_arg( 'affwp_wc_apply_credit' ) ); exit;
}
}
}
/**
* Calculate the cart subtotal
*
* @access protected
* @since 0.1
* @return float $cart_subtotal The subtotal
*/
protected function calculate_cart_subtotal() {
$cart_subtotal = ( 'excl' == WC()->cart->tax_display_cart ) ? WC()->cart->subtotal_ex_tax : WC()->cart->subtotal;
return $cart_subtotal;
}
/**
* Calculate the amount of a coupon
*
* @access protected
* @since 0.1
* @param float $credit_balance The balance of a users account
* @param float $cart_total The value of the current cart
* @return float $coupon_amount The coupon amount
*/
protected function calculate_coupon_amount( $credit_balance, $cart_total ) {
// If either of these are empty, return 0
if( ! $credit_balance || ! $cart_total ) {
return 0;
}
if( $credit_balance > $cart_total ) {
$coupon_amount = $cart_total;
} else {
$coupon_amount = $credit_balance;
}
return $coupon_amount;
}
/**
* Generate a coupon
*
* @access protected
* @since 0.1
* @param int $user_id The ID of a given user
* @param float $amount The amount of the coupon
* @return mixed string $coupon_code The coupon code if successful, false otherwise
*/
protected function generate_coupon( $user_id = 0, $amount = 0 ){
$amount = floatval( $amount );
if( $amount <= 0 ) {
return false;
}
$user_id = ( $user_id ) ? $user_id : get_current_user_id();
$date = current_time( 'Ymd' );
$coupon_code = 'AFFILIATE-CREDIT-' . $date . '-' . $user_id;
$expires = date( 'Y-m-d', strtotime( '+2 days', current_time( 'timestamp' ) ) );
$coupon = array(
'post_title' => $coupon_code,
'post_content' => '',
'post_status' => 'publish',
'post_author' => 1,
'post_type' => 'shop_coupon'
);
$new_coupon_id = wp_insert_post( $coupon );
if( $new_coupon_id ) {
update_post_meta( $new_coupon_id, 'discount_type', 'fixed_cart' );
update_post_meta( $new_coupon_id, 'coupon_amount', $amount );
update_post_meta( $new_coupon_id, 'individual_use', 'yes' );
update_post_meta( $new_coupon_id, 'usage_limit', '1' );
update_post_meta( $new_coupon_id, 'expiry_date', $expires );
update_post_meta( $new_coupon_id, 'apply_before_tax', 'yes' );
update_post_meta( $new_coupon_id, 'free_shipping', 'no' );
return $coupon_code;
}
return false;
}
/**
* Validate a coupon
*
* @access public
* @since 0.1
* @param int $order_id The ID of an order
* @param object $data
* @return void
*/
public function validate_coupon_usage( $order_id, $data ) {
// Get the order object
$order = new WC_Order( $order_id );
// Get the user ID associated with the order
$user_id = $order->get_user_id();
// Grab an array of coupons used
$coupons = $order->get_used_coupons();
// If the order has coupons
if( $coupon_code = $this->check_for_coupon( $coupons ) ) {
// Process the coupon usage and remove the amount from the user's credit balance
$this->process_used_coupon( $user_id, $coupon_code );
}
}
/**
* Check for a coupon
*
* @access protected
* @since 0.1
* @param array $coupons Coupons to check
* @return mixed $coupon_code if found, false otherwise
*/
protected function check_for_coupon( $coupons = array() ) {
if( ! empty( $coupons ) ) {
foreach ( $coupons as $coupon_code ) {
// Return coupon code if an affiliate credit coupon is found
if ( false !== stripos( $coupon_code, 'AFFILIATE-CREDIT-' ) ) {
return $coupon_code;
}
}
}
return false;
}
/**
* Process a used coupon
*
* @access protected
* @since 0.1
* @param int $user_id The ID of a given user
* @param string $coupon_code The coupon to process
* @return mixed object if successful, false otherwise
*/
protected function process_used_coupon( $user_id = 0, $coupon_code = '' ) {
if( ! $user_id || ! $coupon_code ) {
return;
}
$coupon = new WC_Coupon( $coupon_code );
$coupon_amount = $coupon->amount;
if( ! $coupon_amount ) {
return;
}
// Get the user's current woocommerce credit balance
$current_balance = get_user_meta( $user_id, 'affwp_wc_credit_balance', true );
$new_balance = floatval( $current_balance - $coupon_amount );
return update_user_meta( $user_id, 'affwp_wc_credit_balance', $new_balance );
}
}
new AffiliateWP_Store_Credit_WooCommerce;