PluginProbe ʕ •ᴥ•ʔ
Hostinger Reach – AI-Powered Email Marketing for WordPress / 1.7.0
Hostinger Reach – AI-Powered Email Marketing for WordPress v1.7.0
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 week 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