Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 44
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
Checkout
0.00% covered (danger)
0.00%
0 / 44
0.00% covered (danger)
0.00%
0 / 2
72
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 prefill_checkout_fields
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 1
56
1<?php
2/**
3 * If we have the identity of someone through a Klaviyo/MailPoet/etc. email link but
4 * they do not have a user account, we can still prefill their information at checkout.
5 *
6 * @package brianhenryie/bh-wp-autologin-urls
7 */
8
9namespace BrianHenryIE\WP_Autologin_URLs\WooCommerce;
10
11use Psr\Log\LoggerAwareTrait;
12use Psr\Log\LoggerInterface;
13use WC_Order;
14
15/**
16 * Uses WC()->customer (the global WC_Customer object) methods to set the values.
17 */
18class Checkout {
19    use LoggerAwareTrait;
20
21    /**
22     * Constructor
23     *
24     * @param LoggerInterface $logger A PSR logger.
25     */
26    public function __construct( LoggerInterface $logger ) {
27        $this->setLogger( $logger );
28    }
29
30    /**
31     * If WooCommerce is installed, when there is no WP_User, attempt to populate the user checkout
32     * fields using data from Newsletter/MailPoet and from past orders by that email address.
33     *
34     * If we're here, it means there is no WP_User object for this email address.
35     *
36     * TODO: Prefill additional fields returned by Klaviyo.
37     *
38     * @see WC_Customer_Data_Store_Session::$session_keys
39     *
40     * @param array{email:string, first_name:string, last_name:string} $user_info Information e.g. first name, last name that might be available from MailPoet/Newsletter/Klaviyo.
41     */
42    public function prefill_checkout_fields( array $user_info ): void {
43        $this->logger->debug( 'Prefilling WooCommerce checkout.', $user_info );
44
45        WC()->session->set_customer_session_cookie( true );
46
47        if ( ! empty( $user_info['email'] ) && is_email( $user_info['email'] ) ) {
48            WC()->session->set( 'billing_email', $user_info['email'] );
49            WC()->customer->set_billing_email( $user_info['email'] );
50        }
51
52        if ( ! empty( $user_info['first_name'] ) ) {
53            WC()->customer->set_first_name( $user_info['first_name'] );
54            WC()->customer->set_billing_first_name( $user_info['first_name'] );
55            WC()->customer->set_shipping_first_name( $user_info['first_name'] );
56        }
57
58        if ( ! empty( $user_info['last_name'] ) ) {
59            WC()->customer->set_last_name( $user_info['last_name'] );
60            WC()->customer->set_billing_last_name( $user_info['last_name'] );
61            WC()->customer->set_shipping_last_name( $user_info['last_name'] );
62        }
63
64        if ( ! isset( $user_info['email'] ) ) {
65            return;
66        }
67
68        // Hook after `woocommerce_after_register_post_type` otherwise "wc_get_order was called incorrectly" warning is shown.
69        add_action(
70            'woocommerce_after_register_post_type',
71            function () use ( $user_info ) {
72
73                /**
74                 * Try to get one past order placed by this email address.
75                 *
76                 * @var WC_Order[] $customer_orders
77                 */
78                $customer_orders = wc_get_orders(
79                    array(
80                        'customer' => $user_info['email'],
81                        'limit'    => 1,
82                        'order'    => 'DESC',
83                        'orderby'  => 'id',
84                        'paginate' => false,
85                    )
86                );
87
88                if ( count( $customer_orders ) > 0 ) {
89
90                    $order = $customer_orders[0];
91
92                    WC()->customer->set_billing_country( $order->get_billing_country() );
93                    WC()->customer->set_billing_postcode( $order->get_billing_postcode() );
94                    WC()->customer->set_billing_state( $order->get_billing_state() );
95                    WC()->customer->set_billing_last_name( $order->get_billing_last_name() );
96                    WC()->customer->set_billing_first_name( $order->get_billing_first_name() );
97                    WC()->customer->set_billing_address_1( $order->get_billing_address_1() );
98                    WC()->customer->set_billing_address_2( $order->get_billing_address_2() );
99                    WC()->customer->set_billing_city( $order->get_billing_city() );
100                    WC()->customer->set_billing_company( $order->get_billing_company() );
101                    WC()->customer->set_billing_phone( $order->get_billing_phone() );
102
103                    $this->logger->info( "Set customer checkout details from past order wc_order:{$order->get_id()}" );
104                } else {
105                    $this->logger->debug( 'No past orders found for user.' );
106                }
107            }
108        );
109    }
110}