PluginProbe ʕ •ᴥ•ʔ
Hostinger Reach – AI-Powered Email Marketing for WordPress / trunk
Hostinger Reach – AI-Powered Email Marketing for WordPress vtrunk
1.7.2 1.7.1 1.7.0 1.6.0 1.5.9 1.5.8 1.5.7 1.5.6 1.5.5 1.5.4 1.5.3 1.5.2 1.5.1 1.5.0 1.4.12 1.4.11 1.4.10 1.4.9 1.4.8 1.4.7 trunk 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6
hostinger-reach / src / Tracking / RestoreCart.php
hostinger-reach / src / Tracking Last commit date
AbandonedCarts.php 9 months ago RestoreCart.php 1 month ago
RestoreCart.php
103 lines
1 <?php
2
3 namespace Hostinger\Reach\Tracking;
4
5 use Exception;
6 use Hostinger\Reach\Repositories\CartRepository;
7 use WC_Product;
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 die;
11 }
12
13 class RestoreCart {
14
15 public const QUERY_VAR = 'hostinger_reach_restore_cart';
16 public const TOKEN_VAR = 'hostinger_reach_token';
17 private const TOKEN_SALT = 'hostinger_reach_restore_cart|';
18
19 private CartRepository $cart_repository;
20
21 public function __construct( CartRepository $cart_repository ) {
22 $this->cart_repository = $cart_repository;
23 }
24
25 public function init(): void {
26 add_action( 'template_redirect', array( $this, 'maybe_restore_cart' ) );
27 }
28
29 /**
30 * Build the signed URL that restores the given cart and forwards to checkout.
31 */
32 public static function get_restore_url( string $hash ): string {
33 return add_query_arg(
34 array(
35 self::QUERY_VAR => rawurlencode( $hash ),
36 self::TOKEN_VAR => self::generate_token( $hash ),
37 ),
38 home_url( '/' )
39 );
40 }
41
42 public static function generate_token( string $hash ): string {
43 return hash_hmac( 'sha256', self::TOKEN_SALT . $hash, wp_salt() );
44 }
45
46 public function maybe_restore_cart(): void {
47 if ( ! isset( $_GET[ self::QUERY_VAR ], $_GET[ self::TOKEN_VAR ] ) ) {
48 return;
49 }
50
51 $hash = sanitize_text_field( wp_unslash( $_GET[ self::QUERY_VAR ] ) );
52 $token = sanitize_text_field( wp_unslash( $_GET[ self::TOKEN_VAR ] ) );
53
54 if ( ! $hash || ! $this->is_valid_token( $hash, $token ) ) {
55 return;
56 }
57
58 if ( ! function_exists( 'WC' ) || ! WC()->cart ) {
59 return;
60 }
61
62 try {
63 $cart = $this->cart_repository->get( $hash );
64 } catch ( Exception $e ) {
65 return;
66 }
67
68 $this->restore_items( $cart['items'] ?? array() );
69
70 wp_safe_redirect( wc_get_checkout_url() );
71 exit;
72 }
73
74 private function is_valid_token( string $hash, string $token ): bool {
75 return hash_equals( self::generate_token( $hash ), $token );
76 }
77
78 private function restore_items( array $items ): void {
79 $cart = WC()->cart;
80 $cart->empty_cart();
81
82 foreach ( $items as $item ) {
83 $product_id = (int) ( $item['product_id'] ?? 0 );
84 $quantity = (int) ( $item['quantity'] ?? 0 );
85
86 if ( $product_id <= 0 || $quantity <= 0 ) {
87 continue;
88 }
89
90 $product = wc_get_product( $product_id );
91 if ( ! $product instanceof WC_Product ) {
92 continue;
93 }
94
95 if ( $product->is_type( 'variation' ) ) {
96 $cart->add_to_cart( $product->get_parent_id(), $quantity, $product_id, $product->get_variation_attributes() );
97 } else {
98 $cart->add_to_cart( $product_id, $quantity );
99 }
100 }
101 }
102 }
103