Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Jetpack_WooCommerce_Analytics_Universal often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Jetpack_WooCommerce_Analytics_Universal, and based on these observations, apply Extract Interface, too.
| 1 | <?php  | 
            ||
| 20 | class Jetpack_WooCommerce_Analytics_Universal { | 
            ||
| 21 | /**  | 
            ||
| 22 | * Jetpack_WooCommerce_Analytics_Universal constructor.  | 
            ||
| 23 | */  | 
            ||
| 24 | 	public function __construct() { | 
            ||
| 25 | // loading _wca  | 
            ||
| 26 | add_action( 'wp_head', array( $this, 'wp_head_top' ), 1 );  | 
            ||
| 27 | |||
| 28 | // add to carts from non-product pages or lists (search, store etc.)  | 
            ||
| 29 | add_action( 'wp_head', array( $this, 'loop_session_events' ), 2 );  | 
            ||
| 30 | |||
| 31 | // loading s.js  | 
            ||
| 32 | add_action( 'wp_head', array( $this, 'wp_head_bottom' ), 999999 );  | 
            ||
| 33 | |||
| 34 | // Capture cart events  | 
            ||
| 35 | add_action( 'woocommerce_add_to_cart', array( $this, 'capture_add_to_cart' ), 10, 6 );  | 
            ||
| 36 | |||
| 37 | // single product page view  | 
            ||
| 38 | add_action( 'woocommerce_after_single_product', array( $this, 'capture_product_view' ) );  | 
            ||
| 39 | |||
| 40 | add_action( 'woocommerce_after_cart', array( $this, 'remove_from_cart' ) );  | 
            ||
| 41 | add_action( 'woocommerce_after_mini_cart', array( $this, 'remove_from_cart' ) );  | 
            ||
| 42 | add_action( 'wcct_before_cart_widget', array( $this, 'remove_from_cart' ) );  | 
            ||
| 43 | add_filter( 'woocommerce_cart_item_remove_link', array( $this, 'remove_from_cart_attributes' ), 10, 2 );  | 
            ||
| 44 | |||
| 45 | // cart checkout  | 
            ||
| 46 | add_action( 'woocommerce_after_checkout_form', array( $this, 'checkout_process' ) );  | 
            ||
| 47 | |||
| 48 | // order confirmed  | 
            ||
| 49 | add_action( 'woocommerce_thankyou', array( $this, 'order_process' ), 10, 1 );  | 
            ||
| 50 | add_action( 'woocommerce_after_cart', array( $this, 'remove_from_cart_via_quantity' ), 10, 1 );  | 
            ||
| 51 | }  | 
            ||
| 52 | |||
| 53 | /**  | 
            ||
| 54 | * Make _wca available to queue events  | 
            ||
| 55 | */  | 
            ||
| 56 | 	public function wp_head_top() { | 
            ||
| 57 | 		if ( is_cart() || is_checkout() || is_checkout_pay_page() || is_order_received_page() || is_add_payment_method_page() ) { | 
            ||
| 58 | $prevent_referrer_code = "<script>window._wca_prevent_referrer = true;</script>";  | 
            ||
| 59 | echo "$prevent_referrer_code\r\n";  | 
            ||
| 60 | }  | 
            ||
| 61 | $wca_code = "<script>window._wca = window._wca || [];</script>";  | 
            ||
| 62 | echo "$wca_code\r\n";  | 
            ||
| 63 | }  | 
            ||
| 64 | |||
| 65 | |||
| 66 | /**  | 
            ||
| 67 | * Place script to call s.js, Store Analytics  | 
            ||
| 68 | */  | 
            ||
| 69 | 	public function wp_head_bottom() { | 
            ||
| 74 | |||
| 75 | /**  | 
            ||
| 76 | * On product lists or other non-product pages, add an event listener to "Add to Cart" button click  | 
            ||
| 77 | */  | 
            ||
| 78 | 	public function loop_session_events() { | 
            ||
| 107 | |||
| 108 | /**  | 
            ||
| 109 | * On the cart page, add an event listener for removal of product click  | 
            ||
| 110 | */  | 
            ||
| 111 | View Code Duplication | 	public function remove_from_cart() { | 
            |
| 135 | |||
| 136 | /**  | 
            ||
| 137 | * Adds the product ID to the remove product link (for use by remove_from_cart above) if not present  | 
            ||
| 138 | *  | 
            ||
| 139 | * @param string $url url.  | 
            ||
| 140 | * @param string $key key.  | 
            ||
| 141 | * @return mixed.  | 
            ||
| 142 | */  | 
            ||
| 143 | View Code Duplication | 	public function remove_from_cart_attributes( $url, $key ) { | 
            |
| 144 | 		if ( false !== strpos( $url, 'data-product_id' ) ) { | 
            ||
| 145 | return $url;  | 
            ||
| 146 | }  | 
            ||
| 147 | |||
| 148 | $item = WC()->cart->get_cart_item( $key );  | 
            ||
| 149 | $product = $item['data'];  | 
            ||
| 150 | |||
| 151 | $new_attributes = sprintf(  | 
            ||
| 152 | 'href="%s" data-product_id="%s" data-product_sku="%s"',  | 
            ||
| 153 | esc_attr( $url ),  | 
            ||
| 154 | esc_attr( $product->get_id() ),  | 
            ||
| 155 | esc_attr( $product->get_sku() )  | 
            ||
| 156 | );  | 
            ||
| 157 | $url = str_replace( 'href=', $new_attributes, $url );  | 
            ||
| 158 | return $url;  | 
            ||
| 159 | }  | 
            ||
| 160 | |||
| 161 | /**  | 
            ||
| 162 | * Gather relevant product information  | 
            ||
| 163 | *  | 
            ||
| 164 | * @param array $product product  | 
            ||
| 165 | * @return array  | 
            ||
| 166 | */  | 
            ||
| 167 | 	public function get_product_details( $product ) { | 
            ||
| 175 | |||
| 176 | /**  | 
            ||
| 177 | * Track a product page view  | 
            ||
| 178 | */  | 
            ||
| 179 | 	public function capture_product_view() { | 
            ||
| 197 | |||
| 198 | /**  | 
            ||
| 199 | * On the Checkout page, trigger an event for each product in the cart  | 
            ||
| 200 | */  | 
            ||
| 201 | 	public function checkout_process() { | 
            ||
| 233 | |||
| 234 | /**  | 
            ||
| 235 | * After the checkout process, fire an event for each item in the order  | 
            ||
| 236 | *  | 
            ||
| 237 | * @param string $order_id Order Id.  | 
            ||
| 238 | */  | 
            ||
| 239 | 	public function order_process( $order_id ) { | 
            ||
| 265 | |||
| 266 | /**  | 
            ||
| 267 | * Listen for clicks on the "Update Cart" button to know if an item has been removed by  | 
            ||
| 268 | * updating its quantity to zero  | 
            ||
| 269 | */  | 
            ||
| 270 | View Code Duplication | 	public function remove_from_cart_via_quantity() { | 
            |
| 291 | |||
| 292 | /**  | 
            ||
| 293 | * Get the current user id  | 
            ||
| 294 | *  | 
            ||
| 295 | * @return int  | 
            ||
| 296 | */  | 
            ||
| 297 | 	public function get_user_id() { | 
            ||
| 305 | |||
| 306 | /**  | 
            ||
| 307 | * @param $cart_item_key  | 
            ||
| 308 | * @param $product_id  | 
            ||
| 309 | * @param $quantity  | 
            ||
| 310 | * @param $variation_id  | 
            ||
| 311 | * @param $variation  | 
            ||
| 312 | * @param $cart_item_data  | 
            ||
| 313 | */  | 
            ||
| 314 | 	public function capture_add_to_cart( $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data ) { | 
            ||
| 324 | |||
| 325 | /**  | 
            ||
| 326 | * @param $product_id  | 
            ||
| 327 | * @param $quantity  | 
            ||
| 328 | * @param $event  | 
            ||
| 329 | */  | 
            ||
| 330 | 	public function capture_event_in_session_data( $product_id, $quantity, $event ) { | 
            ||
| 357 | |||
| 358 | /**  | 
            ||
| 359 | * Gets product categories or varation attributes as a formatted concatenated string  | 
            ||
| 360 | *  | 
            ||
| 361 | * @param object $product WC_Product.  | 
            ||
| 362 | * @return string  | 
            ||
| 363 | */  | 
            ||
| 364 | View Code Duplication | 	public function get_product_categories_concatenated( $product ) { | 
            |
| 385 | |||
| 386 | }  | 
            ||
| 387 | 
This check looks for improperly formatted assignments.
Every assignment must have exactly one space before and one space after the equals operator.
To illustrate:
will have no issues, while
will report issues in lines 1 and 2.