Files
medicalalert-web-reloaded/wp/wp-content/plugins/woocommerce-smart-coupons/includes/class-wc-sc-url-coupon.php
2024-06-17 14:42:23 -04:00

582 lines
17 KiB
PHP

<?php
/**
* Coupons via URL
*
* @author StoreApps
* @since 3.3.0
* @version 1.9.0
*
* @package woocommerce-smart-coupons/includes/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'WC_SC_URL_Coupon' ) ) {
/**
* Class for handling coupons applied via URL
*/
class WC_SC_URL_Coupon {
/**
* Variable to hold instance of WC_SC_URL_Coupon
*
* @var $instance
*/
private static $instance = null;
/**
* Variable to hold coupon notices
*
* @var $coupon_notices
*/
private $coupon_notices = array();
/**
* Constructor
*/
private function __construct() {
add_action( 'wp_loaded', array( $this, 'apply_coupon_from_url' ), 19 );
add_action( 'wp_loaded', array( $this, 'apply_coupon_from_session' ), 20 );
add_action( 'wp_loaded', array( $this, 'move_applied_coupon_from_cookies_to_account' ) );
add_action( 'wp_head', array( $this, 'convert_sc_coupon_notices_to_wc_notices' ) );
add_filter( 'the_content', array( $this, 'show_coupon_notices' ) );
}
/**
* Get single instance of WC_SC_URL_Coupon
*
* @return WC_SC_URL_Coupon Singleton object of WC_SC_URL_Coupon
*/
public static function get_instance() {
// Check if instance is already exists.
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handle call to functions which is not available in this class
*
* @param string $function_name The function name.
* @param array $arguments Array of arguments passed while calling $function_name.
* @return result of function call
*/
public function __call( $function_name, $arguments = array() ) {
global $woocommerce_smart_coupon;
if ( ! is_callable( array( $woocommerce_smart_coupon, $function_name ) ) ) {
return;
}
if ( ! empty( $arguments ) ) {
return call_user_func_array( array( $woocommerce_smart_coupon, $function_name ), $arguments );
} else {
return call_user_func( array( $woocommerce_smart_coupon, $function_name ) );
}
}
/**
* Apply coupon code if passed in url
*/
public function apply_coupon_from_url() {
if ( empty( $_SERVER['QUERY_STRING'] ) ) {
return;
}
parse_str( wp_unslash( $_SERVER['QUERY_STRING'] ), $coupon_args ); // phpcs:ignore
$coupon_args = wc_clean( $coupon_args );
if ( ! empty( $coupon_args['coupon-code'] ) ) {
$coupons_data = array();
$coupon_args['coupon-code'] = urldecode( $coupon_args['coupon-code'] );
$coupon_codes = explode( ',', $coupon_args['coupon-code'] );
$coupon_codes = array_filter( $coupon_codes ); // Remove empty coupon codes if any.
$cart = ( is_object( WC() ) && isset( WC()->cart ) ) ? WC()->cart : null;
foreach ( $coupon_codes as $coupon_index => $coupon_code ) {
// Process only first five coupons to avoid GET request parameter limit.
if ( apply_filters( 'wc_sc_max_url_coupons_limit', 5 ) === $coupon_index ) {
break;
}
if ( empty( $coupon_code ) ) {
continue;
}
$coupons_data[] = array(
'coupon-code' => $coupon_code,
);
}
$is_cart_empty = is_a( $cart, 'WC_Cart' ) && is_callable( array( $cart, 'is_empty' ) ) && $cart->is_empty();
if ( true === $is_cart_empty ) {
$is_hold = apply_filters(
'wc_sc_hold_applied_coupons',
true,
array(
'coupons_data' => $coupons_data,
'source' => $this,
)
);
if ( true === $is_hold ) {
$this->hold_applied_coupon( $coupons_data );
}
// Set a session cookie to persist the coupon in case the cart is empty. This code will persist the coupon even if the param sc-page is not supplied.
WC()->session->set_customer_session_cookie( true ); // Thanks to: Devon Godfrey.
} else {
foreach ( $coupons_data as $coupon_data ) {
$coupon_code = $coupon_data['coupon-code'];
if ( ! WC()->cart->has_discount( $coupon_code ) ) {
WC()->cart->add_discount( trim( $coupon_code ) );
}
}
}
if ( ! empty( $coupon_args['add-to-cart'] ) ) {
add_filter( 'woocommerce_add_to_cart_redirect', array( $this, 'add_to_cart_redirect' ), 20, 2 );
return; // Redirection handed over to WooCommerce.
}
if ( empty( $coupon_args['sc-page'] ) ) {
return;
}
$redirect_url = $this->get_sc_redirect_url( $coupon_args );
wp_safe_redirect( $redirect_url );
exit;
}
}
/**
* Get Smart Coupons redirect url
*
* @param array $coupon_args Coupon args.
* @return string
*/
public function get_sc_redirect_url( $coupon_args = array() ) {
$redirect_url = '';
if ( in_array( $coupon_args['sc-page'], array( 'shop', 'cart', 'checkout', 'myaccount' ), true ) ) {
if ( $this->is_wc_gte_30() ) {
$page_id = wc_get_page_id( $coupon_args['sc-page'] );
} else {
$page_id = woocommerce_get_page_id( $coupon_args['sc-page'] );
}
$redirect_url = get_permalink( $page_id );
} elseif ( is_string( $coupon_args['sc-page'] ) ) {
if ( is_numeric( $coupon_args['sc-page'] ) && ! is_float( $coupon_args['sc-page'] ) ) {
$page = $coupon_args['sc-page'];
} else {
$page = ( function_exists( 'wpcom_vip_get_page_by_path' ) ) ? wpcom_vip_get_page_by_path( $coupon_args['sc-page'], OBJECT, get_post_types() ) : get_page_by_path( $coupon_args['sc-page'], OBJECT, get_post_types() ); // phpcs:ignore
}
$redirect_url = get_permalink( $page );
} elseif ( is_numeric( $coupon_args['sc-page'] ) && ! is_float( $coupon_args['sc-page'] ) ) {
$redirect_url = get_permalink( $coupon_args['sc-page'] );
}
if ( empty( $redirect_url ) ) {
$redirect_url = home_url();
}
return $this->get_redirect_url_after_smart_coupons_process( $redirect_url );
}
/**
* WooCommerce handles add to cart redirect.
*
* @param string $url The redirect URL.
* @param WC_Product $product Product.
* @return string
*/
public function add_to_cart_redirect( $url = '', $product = null ) {
remove_filter( 'woocommerce_add_to_cart_redirect', array( $this, 'add_to_cart_redirect' ), 20 );
if ( empty( $_SERVER['QUERY_STRING'] ) ) {
return $url;
}
parse_str( wp_unslash( $_SERVER['QUERY_STRING'] ), $coupon_args ); // phpcs:ignore
$coupon_args = wc_clean( $coupon_args );
if ( ! empty( $coupon_args['sc-page'] ) ) {
return $this->get_sc_redirect_url( $coupon_args );
}
return $url;
}
/**
* Apply coupon code from session, if any
*/
public function apply_coupon_from_session() {
$cart = ( is_object( WC() ) && isset( WC()->cart ) ) ? WC()->cart : null;
if ( empty( $cart ) || WC()->cart->is_empty() ) {
return;
}
$user_id = get_current_user_id();
if ( 0 === $user_id ) {
$unique_id = ( ! empty( $_COOKIE['sc_applied_coupon_profile_id'] ) ) ? wc_clean( wp_unslash( $_COOKIE['sc_applied_coupon_profile_id'] ) ) : ''; // phpcs:ignore
$applied_coupon_from_url = ( ! empty( $unique_id ) ) ? $this->get_applied_coupons_by_guest_user( $unique_id ) : array();
} else {
$applied_coupon_from_url = get_user_meta( $user_id, 'sc_applied_coupon_from_url', true );
}
if ( empty( $applied_coupon_from_url ) ) {
return;
}
foreach ( $applied_coupon_from_url as $index => $coupon_code ) {
$coupon = new WC_Coupon( $coupon_code );
if ( $coupon->is_valid() && ! WC()->cart->has_discount( $coupon_code ) ) {
WC()->cart->add_discount( trim( $coupon_code ) );
unset( $applied_coupon_from_url[ $index ] );
}
}
if ( 0 === $user_id ) {
$this->set_applied_coupon_for_guest_user( $unique_id, $applied_coupon_from_url );
} else {
update_user_meta( $user_id, 'sc_applied_coupon_from_url', $applied_coupon_from_url );
}
}
/**
* Apply coupon code from session, if any
*
* @param array $coupons_args The coupon arguments.
*/
public function hold_applied_coupon( $coupons_args = array() ) {
$user_id = get_current_user_id();
$saved_status = array();
if ( 0 === $user_id ) {
$saved_status = $this->save_applied_coupon_in_cookie( $coupons_args );
} else {
$saved_status = $this->save_applied_coupon_in_account( $coupons_args, $user_id );
}
if ( ! empty( $saved_status ) ) {
foreach ( $coupons_args as $coupon_args ) {
$coupon_code = $coupon_args['coupon-code'];
$save_status = isset( $saved_status[ $coupon_code ] ) ? $saved_status[ $coupon_code ] : '';
if ( 'saved' === $save_status ) {
/* translators: %s: $coupon_code coupon code */
$notice = sprintf( __( 'Coupon code "%s" applied successfully. Please add some products to the cart to see the discount.', 'woocommerce-smart-coupons' ), $coupon_code );
$this->set_coupon_notices( $notice, 'success' );
} elseif ( 'already_saved' === $save_status ) {
/* translators: %s: $coupon_code coupon code */
$notice = sprintf( __( 'Coupon code "%s" already applied! Please add some products to the cart to see the discount.', 'woocommerce-smart-coupons' ), $coupon_code );
$this->set_coupon_notices( $notice, 'error' );
}
}
}
}
/**
* Apply coupon code from session, if any
*
* @param array $coupons_args The coupon arguments.
* @return array $saved_status
*/
public function save_applied_coupon_in_cookie( $coupons_args = array() ) {
$saved_status = array(); // Variable to store whether coupons saved/already saved in cookie.
if ( ! empty( $coupons_args ) ) {
if ( empty( $_COOKIE['sc_applied_coupon_profile_id'] ) ) {
$unique_id = $this->generate_unique_id();
} else {
$unique_id = wc_clean( wp_unslash( $_COOKIE['sc_applied_coupon_profile_id'] ) ); // phpcs:ignore
}
$applied_coupons = $this->get_applied_coupons_by_guest_user( $unique_id );
foreach ( $coupons_args as $coupon_args ) {
$coupon_code = isset( $coupon_args['coupon-code'] ) ? $coupon_args['coupon-code'] : '';
if ( is_array( $applied_coupons ) && in_array( $coupon_code, $applied_coupons, true ) ) {
$saved_status[ $coupon_code ] = 'already_saved';
} else {
$applied_coupons[] = $coupon_code;
$saved_status[ $coupon_code ] = 'saved';
}
}
$this->set_applied_coupon_for_guest_user( $unique_id, $applied_coupons );
wc_setcookie( 'sc_applied_coupon_profile_id', $unique_id, $this->get_cookie_life() );
}
return $saved_status;
}
/**
* Apply coupon code from session, if any
*
* @param array $coupons_args The coupon arguments.
* @param int $user_id The user id.
* @return array $saved_status
*/
public function save_applied_coupon_in_account( $coupons_args = array(), $user_id = 0 ) {
$saved_status = array(); // Variable to store whether coupons saved/already saved in user meta.
if ( ! empty( $coupons_args ) ) {
$applied_coupons = get_user_meta( $user_id, 'sc_applied_coupon_from_url', true );
if ( empty( $applied_coupons ) ) {
$applied_coupons = array();
}
foreach ( $coupons_args as $coupon_args ) {
$coupon_code = $coupon_args['coupon-code'];
if ( ! in_array( $coupon_code, $applied_coupons, true ) ) {
$applied_coupons[] = $coupon_args['coupon-code'];
$saved_status[ $coupon_code ] = 'saved';
} else {
$saved_status[ $coupon_code ] = 'already_saved';
}
}
update_user_meta( $user_id, 'sc_applied_coupon_from_url', $applied_coupons );
}
return $saved_status;
}
/**
* Apply coupon code from session, if any
*/
public function move_applied_coupon_from_cookies_to_account() {
$user_id = get_current_user_id();
if ( $user_id > 0 && ! empty( $_COOKIE['sc_applied_coupon_profile_id'] ) ) {
$unique_id = wc_clean( wp_unslash( $_COOKIE['sc_applied_coupon_profile_id'] ) ); // phpcs:ignore
$applied_coupons = $this->get_applied_coupons_by_guest_user( $unique_id );
if ( false !== $applied_coupons && is_array( $applied_coupons ) && ! empty( $applied_coupons ) ) {
$saved_coupons = get_user_meta( $user_id, 'sc_applied_coupon_from_url', true );
if ( empty( $saved_coupons ) || ! is_array( $saved_coupons ) ) {
$saved_coupons = array();
}
$saved_coupons = array_merge( $saved_coupons, $applied_coupons );
update_user_meta( $user_id, 'sc_applied_coupon_from_url', $saved_coupons );
wc_setcookie( 'sc_applied_coupon_profile_id', '' );
$this->delete_applied_coupons_of_guest_user( $unique_id );
delete_option( 'sc_applied_coupon_profile_' . $unique_id );
}
}
}
/**
* Function to get redirect URL after processing Smart Coupons params
*
* @param string $url The URL.
* @return string $url
*/
public function get_redirect_url_after_smart_coupons_process( $url = '' ) {
if ( empty( $url ) ) {
return $url;
}
$query_string = ( ! empty( $_SERVER['QUERY_STRING'] ) ) ? wc_clean( wp_unslash( $_SERVER['QUERY_STRING'] ) ) : array(); // phpcs:ignore
parse_str( $query_string, $url_args );
$sc_params = array( 'coupon-code', 'sc-page' );
$url_params = array_diff_key( $url_args, array_flip( $sc_params ) );
if ( empty( $url_params['add-to-cart'] ) ) {
$redirect_url = apply_filters( 'wc_sc_redirect_url_after_smart_coupons_process', add_query_arg( $url_params, $url ), array( 'source' => $this ) );
} else {
$redirect_url = apply_filters( 'wc_sc_redirect_url_after_smart_coupons_process', $url, array( 'source' => $this ) );
}
return $redirect_url;
}
/**
* Function to convert sc coupon notices to wc notices
*/
public function convert_sc_coupon_notices_to_wc_notices() {
$coupon_notices = $this->get_coupon_notices();
// If we have coupon notices to be shown and we are on a woocommerce page then convert them to wc notices.
if ( count( $coupon_notices ) > 0 && ( is_woocommerce() || is_cart() || is_checkout() || is_account_page() ) ) {
foreach ( $coupon_notices as $notice_type => $notices ) {
if ( count( $notices ) > 0 ) {
foreach ( $notices as $notice ) {
wc_add_notice( $notice, $notice_type );
}
}
}
$this->remove_coupon_notices();
}
}
/**
* Function to get sc coupon notices
*/
public function get_coupon_notices() {
return apply_filters( 'wc_sc_coupon_notices', $this->coupon_notices );
}
/**
* Function to set sc coupon notices
*
* @param string $notice notice.
* @param string $type notice type.
*/
public function set_coupon_notices( $notice = '', $type = '' ) {
if ( empty( $notice ) || empty( $type ) ) {
return;
}
if ( empty( $this->coupon_notices[ $type ] ) || ! is_array( $this->coupon_notices[ $type ] ) ) {
$this->coupon_notices[ $type ] = array();
}
$this->coupon_notices[ $type ][] = $notice;
}
/**
* Function to remove sc coupon notices
*/
public function remove_coupon_notices() {
$this->coupon_notices = array();
}
/**
* Function to add coupon notices to wp content
*
* @param string $content page content.
* @return string $content page content
*/
public function show_coupon_notices( $content = '' ) {
$coupon_notices = $this->get_coupon_notices();
if ( count( $coupon_notices ) > 0 ) {
// Buffer output.
ob_start();
foreach ( $coupon_notices as $notice_type => $notices ) {
if ( count( $coupon_notices[ $notice_type ] ) > 0 ) {
wc_get_template(
"notices/{$notice_type}.php",
array(
'messages' => $coupon_notices[ $notice_type ],
)
);
}
}
$notices = wc_kses_notice( ob_get_clean() );
$content = $notices . $content;
$this->remove_coupon_notices(); // Empty out notice data.
}
return $content;
}
/**
* Function to get coupon codes by guest user's unique id.
*
* @param string $unique_id Unique id for guest user.
*
* @return array.
*/
public function get_applied_coupons_by_guest_user( $unique_id = '' ) {
$key = sprintf( 'sc_applied_coupon_profile_%s', $unique_id );
// Get coupons from `transient`.
$coupons = get_transient( $key );
if ( ! empty( $coupons ) && is_array( $coupons ) ) {
return $coupons;
}
// Get coupon from `wp_option`.
return get_option( $key, array() );
}
/**
* Function to set applied coupons for guest user.
*
* @param string $unique_id Unique id for guest user.
* @param array $coupons Array of coupon codes.
*
* @return bool.
*/
public function set_applied_coupon_for_guest_user( $unique_id = '', $coupons = array() ) {
if ( ! empty( $unique_id ) && is_array( $coupons ) ) {
$key = sprintf( 'sc_applied_coupon_profile_%s', $unique_id );
if ( empty( $coupons ) ) {
return delete_transient( $key );
} else {
return set_transient(
$key,
$coupons,
apply_filters( 'wc_sc_applied_coupon_by_url_expire_time', MONTH_IN_SECONDS )
);
}
}
return false;
}
/**
* Function to delete all applied coupons for a guest user.
*
* @param string $unique_id Unique id for guest user.
*
* @return bool.
*/
public function delete_applied_coupons_of_guest_user( $unique_id = '' ) {
if ( ! empty( $unique_id ) ) {
$key = sprintf( 'sc_applied_coupon_profile_%s', $unique_id );
return delete_transient( $key );
}
return false;
}
}
}
WC_SC_URL_Coupon::get_instance();