Completed
Push — master ( bc7ba4...ae6ee3 )
by Roy
02:07
created

WC_Stripe_Apple_Pay   C

Complexity

Total Complexity 67

Size/Duplication

Total Lines 473
Duplicated Lines 3.59 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 67
lcom 1
cbo 3
dl 17
loc 473
rs 5.7097
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A instance() 0 3 1
A init() 0 12 2
D payment_scripts() 0 34 10
A is_supported_product_type() 0 9 3
B display_apple_pay_button() 0 24 5
A generate_apple_pay_cart() 0 11 3
C process_apple_pay() 3 60 9
B generate_payment_request() 0 24 5
B build_line_items() 14 50 6
F create_order() 0 143 22

How to fix   Duplicated Code    Complexity   

Duplicated Code

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 Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like WC_Stripe_Apple_Pay 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 WC_Stripe_Apple_Pay, and based on these observations, apply Extract Interface, too.

1
<?php
2
if ( ! defined( 'ABSPATH' ) ) {
3
	exit;
4
}
5
6
/**
7
 * WC_Stripe_Apple_Pay class.
8
 *
9
 * @extends WC_Gateway_Stripe
10
 */
11
class WC_Stripe_Apple_Pay extends WC_Gateway_Stripe {
12
	/**
13
	 * This Instance.
14
	 *
15
	 * @var
16
	 */
17
	private static $_this;
18
19
	/**
20
	 * Gateway.
21
	 *
22
	 * @var
23
	 */
24
	private $_gateway;
0 ignored issues
show
Unused Code introduced by
The property $_gateway is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
25
26
	/**
27
	 * Gateway settings.
28
	 *
29
	 * @var
30
	 */
31
	private $_gateway_settings;
32
33
	/**
34
	 * Constructor.
35
	 *
36
	 * @access public
37
	 * @since 3.1.0
38
	 * @version 3.1.0
39
	 */
40
	public function __construct() {
41
		self::$_this = $this;
42
43
		$this->_gateway_settings = get_option( 'woocommerce_stripe_settings', '' );
44
45
		$this->init();
46
	}
47
48
	public function instance() {
49
		return self::$_this;
50
	}
51
52
	/**
53
	 * Initialize.
54
	 *
55
	 * @access public
56
	 * @since 3.1.0
57
	 * @version 3.1.0
58
	 */
59
	public function init() {
60
		add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
61
		add_action( 'woocommerce_proceed_to_checkout', array( $this, 'display_apple_pay_button' ), 20 );
62
		add_action( 'woocommerce_review_order_before_payment', array( $this, 'display_apple_pay_button' ) );
63
		
64
		if ( is_admin() ) {
65
			add_action( 'wp_ajax_wc_stripe_apple_pay', array( $this, 'process_apple_pay' ) );
66
			add_action( 'wp_ajax_nopriv_wc_stripe_apple_pay', array( $this, 'process_apple_pay' ) );
67
			add_action( 'wp_ajax_wc_stripe_generate_apple_pay_cart', array( $this, 'generate_apple_pay_cart' ) );
68
			add_action( 'wp_ajax_nopriv_wc_stripe_generate_apple_pay_cart', array( $this, 'generate_apple_pay_cart' ) );
69
		}
70
	}
71
72
	/**
73
	 * Enqueue JS scripts and styles.
74
	 *
75
	 * @since 3.1.0
76
	 * @version 3.1.0
77
	 */
78
	public function payment_scripts() {
79
		if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) ) {
80
			return;
81
		}
82
83
		if ( ! $this->is_supported_product_type() ) {
84
			return;
85
		}
86
		
87
		$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
88
		
89
		wp_enqueue_style( 'stripe_apple_pay', plugins_url( 'assets/css/stripe-apple-pay.css', WC_STRIPE_MAIN_FILE ), array(), WC_STRIPE_VERSION );
90
91
		wp_enqueue_script( 'stripe', 'https://js.stripe.com/v2/', '', '1.0', true );
92
		wp_enqueue_script( 'woocommerce_stripe_apple_pay', plugins_url( 'assets/js/stripe-apple-pay' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), array( 'stripe' ), WC_STRIPE_VERSION, true );
93
94
		$publishable_key = 'yes' === $this->_gateway_settings['testmode'] ? $this->_gateway_settings['test_publishable_key'] : $this->_gateway_settings['publishable_key'];
95
96
		$stripe_params = array(
97
			'key'                         => $publishable_key,
98
			'currency_code'               => get_woocommerce_currency(),
99
			'country_code'                => substr( get_option( 'woocommerce_default_country' ), 0, 2 ),
100
			'label'                       => get_bloginfo( 'name', 'display' ),
101
			'ajaxurl'                     => admin_url( 'admin-ajax.php' ),
102
			'stripe_apple_pay_nonce'      => wp_create_nonce( '_wc_stripe_apple_pay_nonce' ),
103
			'stripe_apple_pay_cart_nonce' => wp_create_nonce( '_wc_stripe_apple_pay_cart_nonce' ),
104
			'needs_shipping'              => WC()->cart->needs_shipping() ? 'yes' : 'no',
105
			'needs_shipping_msg'          => __( 'Please first calculate your shipping.', 'woocommerce-gateway-stripe' ),
106
			'is_cart_page'                => is_cart() ? 'yes' : 'no',
107
			'chosen_shipping'             => wc_get_chosen_shipping_method_ids(),
108
		);
109
110
		wp_localize_script( 'woocommerce_stripe_apple_pay', 'wc_stripe_apple_pay_params', apply_filters( 'wc_stripe_apple_pay_params', $stripe_params ) );
111
	}
112
		
113
	/**
114
	 * Checks to make sure product type is supported by Apple Pay.
115
	 *
116
	 */
117
	public function is_supported_product_type() {
118
		foreach( WC()->cart->get_cart() as $cart_item_key => $values ) {
119
			if ( 'subscription' === $values['data']->product_type ) {
120
				return false;
121
			}
122
		}
123
124
		return true;
125
	}
126
127
	/**
128
	 * Display Apple Pay button on the cart page
129
	 *
130
	 * @since 3.1.0
131
	 * @version 3.1.0
132
	 */
133
	public function display_apple_pay_button() {
134
		$gateways = WC()->payment_gateways->get_available_payment_gateways();
135
136
		/**
137
		 * In order for the Apple Pay button to show on cart page,
138
		 * Apple Pay must be enabled and Stripe gateway must be enabled.
139
		 */
140
		if ( 
141
			'yes' !== $this->_gateway_settings['apple_pay']
142
			|| ! isset( $gateways['stripe'] ) 
143
		) {
144
			return;
145
		}
146
147
		if ( ! $this->is_supported_product_type() ) {
148
			return;
149
		}
150
151
		$apple_pay_button = ! empty( $this->_gateway_settings['apple_pay_button'] ) ? $this->_gateway_settings['apple_pay_button'] : 'black';
152
		$country = strtolower( substr( get_option( 'woocommerce_default_country' ), 0, 2 ) );
153
		?>
154
		<button class="apple-pay-button" lang="<?php echo esc_attr( $country ); ?>" style="-webkit-appearance: -apple-pay-button; -apple-pay-button-type: buy; -apple-pay-button-style: <?php echo esc_attr( $apple_pay_button ); ?>;"></button>
155
		<?php
156
	}
157
158
	/**
159
	 * Generates the Apple Pay cart.
160
	 *
161
	 * @since 3.1.0
162
	 * @version 3.1.0
163
	 */
164
	public function generate_apple_pay_cart() {
165
		if ( ! defined( 'DOING_AJAX' ) ) {
166
			define( 'DOING_AJAX', true );
167
		}
168
169
		if ( ! wp_verify_nonce( $_POST['nonce'], '_wc_stripe_apple_pay_cart_nonce' ) ) {
170
			wp_die( __( 'Cheatin&#8217; huh?', 'woocommerce-gateway-stripe' ) );
171
		}
172
173
		wp_send_json( array( 'line_items' => $this->build_line_items(), 'total' => WC()->cart->total, 'chosen_shipping' => wc_get_chosen_shipping_method_ids() ) );
174
	}
175
176
	/**
177
	 * Handles the Apple Pay processing via AJAX
178
	 *
179
	 * @access public
180
	 * @since 3.1.0
181
	 * @version 3.1.0
182
	 */
183
	public function process_apple_pay() {
184
		if ( ! defined( 'DOING_AJAX' ) ) {
185
			define( 'DOING_AJAX', true );
186
		}
187
188
		if ( ! wp_verify_nonce( $_POST['nonce'], '_wc_stripe_apple_pay_nonce' ) ) {
189
			wp_die( __( 'Cheatin&#8217; huh?', 'woocommerce-gateway-stripe' ) );
190
		}
191
192
		try {
193
			$result = array_map( 'wc_clean', $_POST['result'] );
194
195
			$order = $this->create_order( $result );
196
197
			// Handle payment.
198
			if ( $order->get_total() > 0 ) {
199
200 View Code Duplication
				if ( $order->get_total() * 100 < WC_Stripe::get_minimum_amount() ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
201
					return new WP_Error( 'stripe_error', sprintf( __( 'Sorry, the minimum allowed order total is %1$s to use this payment method.', 'woocommerce-gateway-stripe' ), wc_price( WC_Stripe::get_minimum_amount() / 100 ) ) );
202
				}
203
204
				WC_Stripe::log( "Info: Begin processing payment for order $order->id for the amount of {$order->get_total()}" );
205
206
				// Make the request.
207
				$response = WC_Stripe_API::request( $this->generate_payment_request( $order, $result['token']['id'] ) );
208
209
				if ( is_wp_error( $response ) ) {
210
					$localized_messages = $this->get_localized_messages();
211
212
					throw new Exception( ( isset( $localized_messages[ $response->get_error_code() ] ) ? $localized_messages[ $response->get_error_code() ] : $response->get_error_message() ) );
213
				}
214
215
				// Process valid response.
216
				$this->process_response( $response, $order );
217
			} else {
218
				$order->payment_complete();
219
			}
220
221
			// Remove cart.
222
			WC()->cart->empty_cart();
223
224
			update_post_meta( $order->id, '_customer_user', get_current_user_id() );
225
226
			// Return thank you page redirect.
227
			wp_send_json( array(
228
				'success'  => 'true',
229
				'redirect' => $this->get_return_url( $order ),
230
			) );
231
232
		} catch ( Exception $e ) {
233
			WC()->session->set( 'refresh_totals', true );
234
			WC_Stripe::log( sprintf( __( 'Error: %s', 'woocommerce-gateway-stripe' ), $e->getMessage() ) );
235
236
			if ( $order->has_status( array( 'pending', 'failed' ) ) ) {
237
				$this->send_failed_order_email( $order->id );
0 ignored issues
show
Bug introduced by
The variable $order does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
238
			}
239
240
			wp_send_json( array( 'success' => 'false', 'msg' => $e->getMessage() ) );
241
		}
242
	}
243
244
	/**
245
	 * Generate the request for the payment.
246
	 * @param  WC_Order $order
247
	 * @param string $source token
248
	 * @return array()
0 ignored issues
show
Documentation introduced by
The doc-type array() could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
249
	 */
250
	protected function generate_payment_request( $order, $source ) {
251
		$post_data                = array();
252
		$post_data['currency']    = strtolower( $order->get_order_currency() ? $order->get_order_currency() : get_woocommerce_currency() );
253
		$post_data['amount']      = $this->get_stripe_amount( $order->get_total(), $post_data['currency'] );
254
		$post_data['description'] = sprintf( __( '%s - Order %s', 'woocommerce-gateway-stripe' ), wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ), $order->get_order_number() );
255
		$post_data['capture']     = 'yes' === $this->_gateway_settings['capture'] ? 'true' : 'false';
256
257
		if ( ! empty( $order->billing_email ) && apply_filters( 'wc_stripe_send_stripe_receipt', false ) ) {
258
			$post_data['receipt_email'] = $order->billing_email;
259
		}
260
261
		$post_data['expand[]']    = 'balance_transaction';
262
		$post_data['source']      = $source;
263
264
		/**
265
		 * Filter the return value of the WC_Payment_Gateway_CC::generate_payment_request.
266
		 *
267
		 * @since 3.1.0
268
		 * @param array $post_data
269
		 * @param WC_Order $order
270
		 * @param object $source
271
		 */
272
		return apply_filters( 'wc_stripe_generate_payment_request', $post_data, $order );
273
	}
274
275
	/**
276
	 * Builds the line items to pass to Apple Pay
277
	 *
278
	 * @since 3.1.0
279
	 * @version 3.1.0
280
	 */	
281
	public function build_line_items() {
282
		$decimals = apply_filters( 'wc_stripe_apple_pay_decimals', 2 );
283
284
		$items = array();
285
286
		foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
287
			$amount         = wc_format_decimal( $values['line_subtotal'], $decimals );
288
			$quantity_label = 1 < $values['quantity'] ? ' (x' . $values['quantity'] . ')' : '';
289
290
			$item = array(
291
				'type'   => 'final',
292
				'label'  => $values['data']->post->post_title . $quantity_label,
293
				'amount' => wc_format_decimal( $amount, $decimals ),
294
			);
295
296
			$items[] = $item;
297
		}
298
299
		$discounts   = wc_format_decimal( WC()->cart->get_cart_discount_total(), $decimals );
300
		$tax         = wc_format_decimal( WC()->cart->tax_total + WC()->cart->shipping_tax_total, $decimals );
301
		$shipping    = wc_format_decimal( WC()->cart->shipping_total, $decimals );
302
		$item_total  = wc_format_decimal( WC()->cart->cart_contents_total, $decimals ) + $discounts;
303
		$order_total = wc_format_decimal( $item_total + $tax + $shipping, $decimals );
0 ignored issues
show
Unused Code introduced by
$order_total is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
304
305
		if ( wc_tax_enabled() ) {
306
			$items[] = array(
307
				'type'   => 'final',
308
				'label'  => __( 'Tax', 'woocommerce-gateway-stripe' ),
309
				'amount' => $tax,
310
			);
311
		}
312
313 View Code Duplication
		if ( WC()->cart->needs_shipping() ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
314
			$items[] = array(
315
				'type'   => 'final',
316
				'label'  => __( 'Shipping', 'woocommerce-gateway-stripe' ),
317
				'amount' => $shipping,
318
			);
319
		}
320
321 View Code Duplication
		if ( WC()->cart->has_discount() ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
322
			$items[] = array(
323
				'type'   => 'final',
324
				'label'  => __( 'Discount', 'woocommerce-gateway-stripe' ),
325
				'amount' => $discounts,
326
			);
327
		}
328
329
		return $items;
330
	}
331
332
	/**
333
	 * Create order programatically.
334
	 *
335
	 * @since 3.1.0
336
	 * @version 3.1.0
337
	 * @param array $data
338
	 * @return object $order
339
	 */
340
	public function create_order( $data = array() ) {
341
		if ( empty( $data ) ) {
342
			throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 520 ) );
343
		}
344
345
		$order = wc_create_order();
346
347
		if ( is_wp_error( $order ) ) {
348
			throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 520 ) );
349
		} elseif ( false === $order ) {
350
			throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 521 ) );
351
		} else {
352
			$order_id = $order->id;
353
			do_action( 'woocommerce_new_order', $order_id );
354
		}
355
356
		// Store the line items to the new/resumed order
357
		foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
358
			$item_id = $order->add_product(
359
				$values['data'],
360
				$values['quantity'],
361
				array(
362
					'variation' => $values['variation'],
363
					'totals'    => array(
364
						'subtotal'     => $values['line_subtotal'],
365
						'subtotal_tax' => $values['line_subtotal_tax'],
366
						'total'        => $values['line_total'],
367
						'tax'          => $values['line_tax'],
368
						'tax_data'     => $values['line_tax_data'] // Since 2.2
369
					)
370
				)
371
			);
372
373
			if ( ! $item_id ) {
374
				throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 525 ) );
375
			}
376
377
			// Allow plugins to add order item meta
378
			do_action( 'woocommerce_add_order_item_meta', $item_id, $values, $cart_item_key );
379
		}
380
381
		// Store fees
382
		foreach ( WC()->cart->get_fees() as $fee_key => $fee ) {
383
			$item_id = $order->add_fee( $fee );
384
385
			if ( ! $item_id ) {
386
				throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 526 ) );
387
			}
388
389
			// Allow plugins to add order item meta to fees
390
			do_action( 'woocommerce_add_order_fee_meta', $order_id, $item_id, $fee, $fee_key );
391
		}
392
393
		// Store tax rows
394
		foreach ( array_keys( WC()->cart->taxes + WC()->cart->shipping_taxes ) as $tax_rate_id ) {
395
			if ( $tax_rate_id && ! $order->add_tax( $tax_rate_id, WC()->cart->get_tax_amount( $tax_rate_id ), WC()->cart->get_shipping_tax_amount( $tax_rate_id ) ) && apply_filters( 'woocommerce_cart_remove_taxes_zero_rate_id', 'zero-rated' ) !== $tax_rate_id ) {
396
				throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 528 ) );
397
			}
398
		}
399
400
		// Store coupons
401
		foreach ( WC()->cart->get_coupons() as $code => $coupon ) {
402
			if ( ! $order->add_coupon( $code, WC()->cart->get_coupon_discount_amount( $code ), WC()->cart->get_coupon_discount_tax_amount( $code ) ) ) {
403
				throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce-gateway-stripe' ), 529 ) );
404
			}
405
		}
406
407
		// Billing address
408
		$billing_address = array();
409
		if ( ! empty( $data['token']['card'] ) ) {
410
			// Name from Stripe is a full name string.
411
			$name                          = explode( ' ', $data['token']['card']['name'] );
412
			$lastname                      = array_pop( $name );
413
			$firstname                     = implode( ' ', $name );
414
			$billing_address['first_name'] = $firstname;
415
			$billing_address['last_name']  = $lastname;
416
			$billing_address['email']      = $data['shippingContact']['emailAddress'];
417
			$billing_address['phone']      = $data['shippingContact']['phoneNumber'];
418
			$billing_address['country']    = $data['token']['card']['country'];
419
			$billing_address['address_1']  = $data['token']['card']['address_line1'];
420
			$billing_address['address_2']  = $data['token']['card']['address_line2'];
421
			$billing_address['city']       = $data['token']['card']['address_city'];
422
			$billing_address['state']      = $data['token']['card']['address_state'];
423
			$billing_address['postcode']   = $data['token']['card']['address_zip'];
424
		}
425
426
		// Shipping address.
427
		$shipping_address = array();
428
		if ( WC()->cart->needs_shipping() && ! empty( $data['shippingContact'] ) ) {
429
			$shipping_address['first_name'] = $data['shippingContact']['givenName'];
430
			$shipping_address['last_name']  = $data['shippingContact']['familyName'];
431
			$shipping_address['email']      = $data['shippingContact']['emailAddress'];
432
			$shipping_address['phone']      = $data['shippingContact']['phoneNumber'];
433
			$shipping_address['country']    = $data['shippingContact']['countryCode'];
434
			$shipping_address['address_1']  = $data['shippingContact']['addressLines'][0];
435
			$shipping_address['address_2']  = $data['shippingContact']['addressLines'][1];
436
			$shipping_address['city']       = $data['shippingContact']['locality'];
437
			$shipping_address['state']      = $data['shippingContact']['administrativeArea'];
438
			$shipping_address['postcode']   = $data['shippingContact']['postalCode'];
439
		} elseif ( ! empty( $data['shippingContact'] ) ) {
440
			$shipping_address['first_name'] = $firstname;
0 ignored issues
show
Bug introduced by
The variable $firstname does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
441
			$shipping_address['last_name']  = $lastname;
0 ignored issues
show
Bug introduced by
The variable $lastname does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
442
			$shipping_address['email']      = $data['shippingContact']['emailAddress'];
443
			$shipping_address['phone']      = $data['shippingContact']['phoneNumber'];
444
			$shipping_address['country']    = $data['token']['card']['country'];
445
			$shipping_address['address_1']  = $data['token']['card']['address_line1'];
446
			$shipping_address['address_2']  = $data['token']['card']['address_line2'];
447
			$shipping_address['city']       = $data['token']['card']['address_city'];
448
			$shipping_address['state']      = $data['token']['card']['address_state'];
449
			$shipping_address['postcode']   = $data['token']['card']['address_zip'];
450
		}
451
452
		$order->set_address( $billing_address, 'billing' );
453
		$order->set_address( $shipping_address, 'shipping' );
454
455
		WC()->shipping->calculate_shipping( WC()->cart->get_shipping_packages() );
456
		
457
		// Get the rate object selected by user.
458
		foreach ( WC()->shipping->get_packages() as $package_key => $package ) {
459
			foreach ( $package['rates'] as $key => $rate ) {
460
				// Loop through user chosen shipping methods.
461
				foreach( WC()->session->get( 'chosen_shipping_methods' ) as $method ) {
462
					if ( $method === $key ) {
463
						$order->add_shipping( $rate );
464
					}
465
				}
466
			}
467
		}
468
469
		$available_gateways = WC()->payment_gateways->get_available_payment_gateways();
470
		$order->set_payment_method( $available_gateways['stripe'] );
471
		$order->set_total( WC()->cart->shipping_total, 'shipping' );
472
		$order->set_total( WC()->cart->get_cart_discount_total(), 'cart_discount' );
473
		$order->set_total( WC()->cart->get_cart_discount_tax_total(), 'cart_discount_tax' );
474
		$order->set_total( WC()->cart->tax_total, 'tax' );
475
		$order->set_total( WC()->cart->shipping_tax_total, 'shipping_tax' );
476
		$order->set_total( WC()->cart->total );
477
478
		// If we got here, the order was created without problems!
479
		wc_transaction_query( 'commit' );
480
481
		return $order;
482
	}
483
}
484
485
new WC_Stripe_Apple_Pay();
486
487