Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 2
n/a
0 / 0
CRAP
n/a
0 / 0
Jetpack_WooCommerce_Analytics_My_Account
n/a
0 / 0
n/a
0 / 0
53
n/a
0 / 0
 __construct
n/a
0 / 0
n/a
0 / 0
1
 track_tabs
n/a
0 / 0
n/a
0 / 0
25
 track_save_address
n/a
0 / 0
n/a
0 / 0
1
 track_add_payment_method
n/a
0 / 0
n/a
0 / 0
4
 track_delete_payment_method
n/a
0 / 0
n/a
0 / 0
2
 track_order_cancel_event
n/a
0 / 0
n/a
0 / 0
4
 track_order_pay_event
n/a
0 / 0
n/a
0 / 0
2
 track_save_account_details
n/a
0 / 0
n/a
0 / 0
1
 track_logouts
n/a
0 / 0
n/a
0 / 0
1
 add_initiator_prop_to_my_account_action_links
n/a
0 / 0
n/a
0 / 0
4
 add_initiator_prop_to_order_urls
n/a
0 / 0
n/a
0 / 0
2
 add_initiator_param_to_query_vars
n/a
0 / 0
n/a
0 / 0
1
 trigger_queued_events
n/a
0 / 0
n/a
0 / 0
3
 queue_event
n/a
0 / 0
n/a
0 / 0
2
1<?php
2/**
3 * Jetpack_WooCommerce_Analytics_My_Account
4 *
5 * @deprecated 13.3
6 *
7 * @package automattic/jetpack
8 * @author  Automattic
9 */
10
11/**
12 * Bail if accessed directly
13 */
14if ( ! defined( 'ABSPATH' ) ) {
15    exit( 0 );
16}
17
18/**
19 * Class Jetpack_WooCommerce_Analytics_My_Account
20 * Filters and Actions added to My Account pages to perform analytics
21 *
22 * @deprecated 13.3
23 */
24class Jetpack_WooCommerce_Analytics_My_Account {
25
26    use Jetpack_WooCommerce_Analytics_Trait;
27
28    /**
29     * Jetpack_WooCommerce_Analytics_My_Account constructor.
30     *
31     * @deprecated 13.3
32     */
33    public function __construct() {
34
35        add_action( 'woocommerce_account_content', array( $this, 'track_tabs' ) );
36        add_action( 'woocommerce_account_content', array( $this, 'track_logouts' ) );
37        add_action( 'woocommerce_customer_save_address', array( $this, 'track_save_address' ), 10, 2 );
38        add_action( 'wp_head', array( $this, 'trigger_queued_events' ) );
39        add_action( 'wp', array( $this, 'track_add_payment_method' ) );
40        add_action( 'wp', array( $this, 'track_delete_payment_method' ) );
41        add_action( 'woocommerce_save_account_details', array( $this, 'track_save_account_details' ) );
42        add_filter( 'woocommerce_my_account_my_orders_actions', array( $this, 'add_initiator_prop_to_my_account_action_links' ) );
43        add_action( 'woocommerce_cancelled_order', array( $this, 'track_order_cancel_event' ), 10, 0 );
44        add_action( 'before_woocommerce_pay', array( $this, 'track_order_pay_event' ) );
45        add_action( 'woocommerce_before_account_orders', array( $this, 'add_initiator_prop_to_order_urls' ), 9 );
46        add_filter( 'query_vars', array( $this, 'add_initiator_param_to_query_vars' ) );
47    }
48
49    /**
50     * Track my account tabs, we only trigger an event if a tab is viewed.
51     *
52     * We also track other events here, like order number clicks, order action clicks,
53     * address clicks, payment method add and delete.
54     *
55     * @deprecated 13.3
56     */
57    public function track_tabs() {
58        global $wp;
59
60        // WooCommerce keeps a map of my-account endpoints keys and their custom permalinks.
61        $core_endpoints = WC()->query->get_query_vars();
62
63        if ( ! empty( $wp->query_vars ) ) {
64
65            foreach ( $wp->query_vars as $key => $value ) {
66                // we skip pagename.
67                if ( 'pagename' === $key ) {
68                    continue;
69                }
70
71                // When no permalink is set, the first page is page_id, so we skip it.
72                if ( 'page_id' === $key ) {
73                    continue;
74                }
75
76                // We don't want to track our own analytics params.
77                if ( '_wca_initiator' === $key ) {
78                    continue;
79                }
80
81                if ( isset( $core_endpoints['view-order'] ) && $core_endpoints['view-order'] === $key && is_numeric( $value ) ) {
82                    $initiator = get_query_var( '_wca_initiator' );
83                    if ( 'number' === $initiator ) {
84                        $this->record_event( 'woocommerceanalytics_my_account_order_number_click' );
85                        continue;
86                    }
87                    if ( 'action' === $initiator ) {
88                        $this->record_event( 'woocommerceanalytics_my_account_order_action_click', array( 'action' => 'view' ) );
89                        continue;
90                    }
91                }
92
93                if ( isset( $core_endpoints['edit-address'] ) && $core_endpoints['edit-address'] === $key && in_array( $value, array( 'billing', 'shipping' ), true ) ) {
94                    $refer = wp_get_referer();
95                    if ( $refer === wc_get_endpoint_url( 'edit-address', $value ) ) {
96                        // It means we're likely coming from the same page after a failed save and don't want to retrigger the address click event.
97                        continue;
98                    }
99
100                    $this->record_event( 'woocommerceanalytics_my_account_address_click', array( 'address' => $value ) );
101                    continue;
102                }
103
104                if ( isset( $core_endpoints['add-payment-method'] ) && $core_endpoints['add-payment-method'] === $key ) {
105                    $this->record_event( 'woocommerceanalytics_my_account_payment_add' );
106                    continue;
107                }
108
109                if ( isset( $core_endpoints['edit-address'] ) && $core_endpoints['edit-address'] ) {
110                    $refer = wp_get_referer();
111                    if ( $refer === wc_get_endpoint_url( 'edit-address', 'billing' ) || $refer === wc_get_endpoint_url( 'edit-address', 'shipping' ) ) {
112                        // It means we're likely coming from the edit page save and don't want to retrigger the page view event.
113                        continue;
114                    }
115                }
116                /**
117                 * The main dashboard view has page as key, so we rename it.
118                 */
119                if ( 'page' === $key ) {
120                    $key = 'dashboard';
121                }
122
123                /**
124                 * If a custom permalink is used for one of the pages, query_vars will have 2 keys, the custom permalink and the core endpoint key.
125                 * To avoid triggering the event twice, we skip the core one and only track the custom one.
126                 * Tracking the custom endpoint is safer than hoping the duplicated, redundant core endpoint is always present.
127                 */
128                if ( isset( $core_endpoints[ $key ] ) && $core_endpoints[ $key ] !== $key ) {
129                    continue;
130                }
131
132                /**
133                 * $core_endpoints is an array of core_permalink => custom_permalink,
134                 * query_vars gives us the custom_permalink, but we want to track it as core_permalink.
135                 */
136                if ( array_search( $key, $core_endpoints, true ) ) {
137                    $key = array_search( $key, $core_endpoints, true );
138                }
139
140                $this->record_event( 'woocommerceanalytics_my_account_page_view', array( 'tab' => $key ) );
141            }
142        }
143    }
144
145    /**
146     * Track address save events, this can only come from the my account page.
147     *
148     * @deprecated 13.3
149     *
150     * @param int    $customer_id The customer id.
151     * @param string $load_address The address type (billing, shipping).
152     */
153    public function track_save_address( $customer_id, $load_address ) {
154        $this->queue_event( 'woocommerceanalytics_my_account_address_save', array( 'address' => $load_address ) );
155    }
156
157    /**
158     * Track payment method add events, this can only come from the my account page.
159     *
160     * @deprecated 13.3
161     */
162    public function track_add_payment_method() {
163        if ( isset( $_POST['woocommerce_add_payment_method'] ) && isset( $_POST['payment_method'] ) ) {
164
165            $nonce_value = wc_get_var( $_REQUEST['woocommerce-add-payment-method-nonce'], wc_get_var( $_REQUEST['_wpnonce'], '' ) ); // @codingStandardsIgnoreLine.
166
167            if ( ! wp_verify_nonce( $nonce_value, 'woocommerce-add-payment-method' ) ) {
168                return;
169            }
170
171            $this->queue_event( 'woocommerceanalytics_my_account_payment_save' );
172            return;
173        }
174    }
175
176    /**
177     * Track payment method delete events.
178     *
179     * @deprecated 13.3
180     */
181    public function track_delete_payment_method() {
182        global $wp;
183        if ( isset( $wp->query_vars['delete-payment-method'] ) ) {
184            $this->queue_event( 'woocommerceanalytics_my_account_payment_delete' );
185            return;
186        }
187    }
188
189    /**
190     * Track order cancel events.
191     *
192     * @deprecated 13.3
193     */
194    public function track_order_cancel_event() {
195        if ( isset( $_GET['_wca_initiator'] ) && ( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), 'woocommerce-cancel_order' ) ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
196            $this->queue_event( 'woocommerceanalytics_my_account_order_action_click', array( 'action' => 'cancel' ) );
197        }
198    }
199
200    /**
201     * Track order pay events.
202     *
203     * @deprecated 13.3
204     */
205    public function track_order_pay_event() {
206        if ( isset( $_GET['_wca_initiator'] ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.NonceVerification.Recommended
207            $this->record_event( 'woocommerceanalytics_my_account_order_action_click', array( 'action' => 'pay' ) );
208        }
209    }
210
211    /**
212     * Track account details save events, this can only come from the my account page.
213     *
214     * @deprecated 13.3
215     */
216    public function track_save_account_details() {
217        $this->queue_event( 'woocommerceanalytics_my_account_details_save' );
218    }
219
220    /**
221     * Track logout events.
222     *
223     * @deprecated 13.3
224     */
225    public function track_logouts() {
226        $common_props = wp_json_encode(
227            array_merge(
228                array(
229                    '_en' => 'woocommerceanalytics_my_account_tab_click',
230                    'tab' => 'logout',
231                ),
232                $this->get_common_properties()
233            ),
234            JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP
235        );
236
237        wc_enqueue_js(
238            "
239            jQuery(document).ready(function($) {
240                    // Attach event listener to the logout link
241                jQuery('.woocommerce-MyAccount-navigation-link--customer-logout').on('click', function() {
242                    _wca.push($common_props);
243                });
244            });
245            "
246        );
247    }
248
249    /**
250     * Add referrer prop to my account action links
251     *
252     * @deprecated 13.3
253     *
254     * @param array $actions My account action links.
255     * @return array
256     */
257    public function add_initiator_prop_to_my_account_action_links( $actions ) {
258        foreach ( $actions as $key => $action ) {
259            if ( ! isset( $action['url'] ) ) {
260                continue;
261            }
262
263            // Check if the action key is view, pay, or cancel.
264            if ( ! in_array( $key, array( 'view', 'pay', 'cancel' ), true ) ) {
265                continue;
266            }
267
268            $url                    = add_query_arg( array( '_wca_initiator' => 'action' ), $action['url'] );
269            $actions[ $key ]['url'] = $url;
270        }
271
272        return $actions;
273    }
274
275    /**
276     * Add an initiator prop to the order url.
277     *
278     * The get_view_order_url is used in a lot of places,
279     * so we want to limit it just to my account page.
280     *
281     * @deprecated 13.3
282     */
283    public function add_initiator_prop_to_order_urls() {
284        add_filter(
285            'woocommerce_get_view_order_url',
286            function ( $url ) {
287                return add_query_arg( array( '_wca_initiator' => 'number' ), $url );
288            },
289            10,
290            1
291        );
292
293        add_filter(
294            'woocommerce_get_endpoint_url',
295            function ( $url, $endpoint ) {
296                if ( 'edit-address' === $endpoint ) {
297                    return add_query_arg( array( '_wca_initiator' => 'action' ), $url );
298                }
299                return $url;
300            },
301            10,
302            2
303        );
304    }
305
306    /**
307     * Add initiator to query vars
308     *
309     * @deprecated 13.3
310     *
311     * @param array $query_vars Query vars.
312     * @return array
313     */
314    public function add_initiator_param_to_query_vars( $query_vars ) {
315        $query_vars[] = '_wca_initiator';
316        return $query_vars;
317    }
318
319    /**
320     * Record all queued up events in session.
321     *
322     * This is called on every page load, and will record all events that were queued up in session.
323     *
324     * @deprecated 13.3
325     */
326    public function trigger_queued_events() {
327        if ( is_object( WC()->session ) ) {
328            $events = WC()->session->get( 'wca_queued_events', array() );
329
330            foreach ( $events as $event ) {
331                $this->record_event(
332                    $event['event_name'],
333                    $event['event_props']
334                );
335            }
336
337            // Clear data, now that these events have been recorded.
338            WC()->session->set( 'wca_queued_events', array() );
339
340        }
341    }
342
343    /**
344     * Queue an event in session to be recorded later on next page load.
345     *
346     * @deprecated 13.3
347     *
348     * @param string $event_name The event name.
349     * @param array  $event_props The event properties.
350     */
351    protected function queue_event( $event_name, $event_props = array() ) {
352        if ( is_object( WC()->session ) ) {
353            $events   = WC()->session->get( 'wca_queued_events', array() );
354            $events[] = array(
355                'event_name'  => $event_name,
356                'event_props' => $event_props,
357            );
358            WC()->session->set( 'wca_queued_events', $events );
359        }
360    }
361}