Completed
Push — master ( 820036...352120 )
by Roy
02:31
created

WC_Stripe_Payment_Request::compute_display_items()   B

Complexity

Conditions 7
Paths 8

Size

Total Lines 54
Code Lines 33

Duplication

Lines 18
Ratio 33.33 %

Importance

Changes 0
Metric Value
dl 18
loc 54
rs 7.8331
c 0
b 0
f 0
cc 7
eloc 33
nc 8
nop 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Stripe Payment Request API
4
 *
5
 * @package WooCommerce_Stripe/Classes/Payment_Request
6
 * @since   3.1.0
7
 * @version 3.1.0
8
 */
9
10
if ( ! defined( 'ABSPATH' ) ) {
11
	exit;
12
}
13
14
/**
15
 * WC_Stripe_Payment_Request class.
16
 */
17
class WC_Stripe_Payment_Request {
18
19
	/**
20
	 * Initialize class actions.
21
	 */
22
	public function __construct() {
23
		add_action( 'wp_enqueue_scripts', array( $this, 'scripts' ) );
24
25
		add_action( 'wc_ajax_wc_stripe_get_cart_details', array( $this, 'ajax_get_cart_details' ) );
26
		add_action( 'wc_ajax_wc_stripe_get_shipping_options', array( $this, 'ajax_get_shipping_options' ) );
27
		add_action( 'wc_ajax_wc_stripe_update_shipping_method', array( $this, 'ajax_update_shipping_method' ) );
28
		add_action( 'wc_ajax_wc_stripe_create_order', array( $this, 'ajax_create_order' ) );
29
	}
30
31
	/**
32
	 * Check if Stripe gateway is enabled.
33
	 *
34
	 * @return bool
35
	 */
36
	protected function is_activated() {
37
		$options             = get_option( 'woocommerce_stripe_settings', array() );
38
		$enabled             = isset( $options['enabled'] ) && 'yes' === $options['enabled'];
39
		$stripe_checkout     = isset( $options['stripe_checkout'] ) && 'yes' !== $options['stripe_checkout'];
40
		$request_payment_api = isset( $options['request_payment_api'] ) && 'yes' === $options['request_payment_api'];
41
42
		return $enabled && $stripe_checkout && $request_payment_api && is_ssl();
43
	}
44
45
	/**
46
	 * Get publishable key.
47
	 *
48
	 * @return string
49
	 */
50
	protected function get_publishable_key() {
51
		$options = get_option( 'woocommerce_stripe_settings', array() );
52
53
		if ( empty( $options ) ) {
54
			return '';
55
		}
56
57
		return 'yes' === $options['testmode'] ? $options['test_publishable_key'] : $options['publishable_key'];
58
	}
59
60
	/**
61
	 * Load public scripts.
62
	 */
63
	public function scripts() {
64
		// Load PaymentRequest only on cart for now.
65
		if ( ! is_cart() ) {
66
			return;
67
		}
68
69
		if ( ! $this->is_activated() ) {
70
			return;
71
		}
72
73
		$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
74
75
		wp_enqueue_script( 'stripe', 'https://js.stripe.com/v2/', '', '1.0', true );
76
		wp_enqueue_script( 'google-payment-request-shim', 'https://storage.googleapis.com/prshim/v1/payment-shim.js', '', '1.0', false );
77
		wp_enqueue_script( 'wc-stripe-payment-request', plugins_url( 'assets/js/payment-request' . $suffix . '.js', WC_STRIPE_MAIN_FILE ), array( 'jquery', 'stripe' ), WC_STRIPE_VERSION, true );
78
79
		wp_localize_script(
80
			'wc-stripe-payment-request',
81
			'wcStripePaymentRequestParams',
82
			array(
83
				'ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
84
				'stripe'   => array(
85
					'key'                => $this->get_publishable_key(),
86
					'allow_prepaid_card' => apply_filters( 'wc_stripe_allow_prepaid_card', true ) ? 'yes' : 'no',
87
				),
88
				'nonce'    => array(
89
					'payment'         => wp_create_nonce( 'wc-stripe-payment-request' ),
90
					'shipping'        => wp_create_nonce( 'wc-stripe-payment-request-shipping' ),
91
					'update_shipping' => wp_create_nonce( 'wc-stripe-update-shipping-method' ),
92
					'checkout'        => wp_create_nonce( 'woocommerce-process_checkout' ),
93
				),
94
				'i18n'     => array(
95
					'no_prepaid_card'  => __( 'Sorry, we\'re not accepting prepaid cards at this time.', 'woocommerce-gateway-stripe' ),
96
					/* translators: Do not translate the [option] placeholder */
97
					'unknown_shipping' => __( 'Unknown shipping option "[option]".', 'woocommerce-gateway-stripe' ),
98
				),
99
			)
100
		);
101
	}
102
103
	/**
104
	 * Get cart details.
105
	 */
106
	public function ajax_get_cart_details() {
107
		check_ajax_referer( 'wc-stripe-payment-request', 'security' );
108
109
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
110
			define( 'WOOCOMMERCE_CART', true );
111
		}
112
113
		WC()->cart->calculate_totals();
114
115
		$currency = get_woocommerce_currency();
116
117
		// Set mandatory payment details.
118
		$data = array(
119
			'shipping_required' => WC()->cart->needs_shipping(),
120
			'order_data'        => array(
121
				'total' => array(
122
					'label'  => __( 'Total', 'woocommerce-gateway-stripe' ),
123
					'amount' => array(
124
						'value'    => max( 0, apply_filters( 'woocommerce_calculated_total', round( WC()->cart->cart_contents_total + WC()->cart->fee_total + WC()->cart->tax_total, WC()->cart->dp ), WC()->cart ) ),
125
						'currency' => $currency,
126
					),
127
				),
128
				// Include line items such as subtotal, fees and taxes. No shipping option is provided here because it is not chosen yet.
129
				'displayItems' => $this->compute_display_items( null ),
130
			),
131
		);
132
133
		wp_send_json( $data );
134
	}
135
136
	/**
137
	 * Calculate and set shipping method.
138
	 *
139
	 * @since 3.1.0
140
	 * @version 3.1.0
141
	 * @param array $address
142
	 */
143
	public function calculate_shipping( $address = array() ) {
144
		$country   = $address['country'];
145
		$state     = $address['state'];
146
		$postcode  = $address['postcode'];
147
		$city      = $address['city'];
148
		$address_1 = $address['address'];
149
		$address_2 = $address['address_2'];
150
151
		WC()->shipping->reset_shipping();
152
153
		if ( $postcode && WC_Validation::is_postcode( $postcode, $country ) ) {
154
			$postcode = wc_format_postcode( $postcode, $country );
155
		}
156
157 View Code Duplication
		if ( $country ) {
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...
158
			WC()->customer->set_location( $country, $state, $postcode, $city );
159
			WC()->customer->set_shipping_location( $country, $state, $postcode, $city );
160
		} else {
161
			WC()->customer->set_to_base();
162
			WC()->customer->set_shipping_to_base();
163
		}
164
165
		WC()->customer->calculated_shipping( true );
166
167
		$packages = array();
168
169
		$packages[0]['contents']                 = WC()->cart->get_cart();
170
		$packages[0]['contents_cost']            = 0;
171
		$packages[0]['applied_coupons']          = WC()->cart->applied_coupons;
172
		$packages[0]['user']['ID']               = get_current_user_id();
173
		$packages[0]['destination']['country']   = $country;
174
		$packages[0]['destination']['state']     = $state;
175
		$packages[0]['destination']['postcode']  = $postcode;
176
		$packages[0]['destination']['city']      = $city;
177
		$packages[0]['destination']['address']   = $address_1;
178
		$packages[0]['destination']['address_2'] = $address_2;
179
180 View Code Duplication
		foreach ( WC()->cart->get_cart() as $item ) {
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...
181
			if ( $item['data']->needs_shipping() ) {
182
				if ( isset( $item['line_total'] ) ) {
183
					$packages[0]['contents_cost'] += $item['line_total'];
184
				}
185
			}
186
		}
187
188
		$packages = apply_filters( 'woocommerce_cart_shipping_packages', $packages );
189
190
		WC()->shipping->calculate_shipping( $packages );
191
	}
192
193
	/**
194
	 * Get shipping options.
195
	 *
196
	 * @see WC_Cart::get_shipping_packages().
197
	 * @see WC_Shipping::calculate_shipping().
198
	 * @see WC_Shipping::get_packages().
199
	 */
200
	public function ajax_get_shipping_options() {
201
		check_ajax_referer( 'wc-stripe-payment-request-shipping', 'security' );
202
203
		// Set the shipping package.
204
		$posted   = filter_input_array( INPUT_POST, array(
205
			'country'   => FILTER_SANITIZE_STRING,
206
			'state'     => FILTER_SANITIZE_STRING,
207
			'postcode'  => FILTER_SANITIZE_STRING,
208
			'city'      => FILTER_SANITIZE_STRING,
209
			'address'   => FILTER_SANITIZE_STRING,
210
			'address_2' => FILTER_SANITIZE_STRING,
211
		) );
212
213
		$this->calculate_shipping( $posted );
214
215
		// Set the shipping options.
216
		$currency = get_woocommerce_currency();
217
		$data     = array();
218
219
		$packages = WC()->shipping->get_packages();
220
221
		if ( ! empty( $packages ) && WC()->customer->has_calculated_shipping() ) {
222
			foreach ( $packages as $package_key => $package ) {
223
				if ( empty( $package['rates'] ) ) {
224
					break;
225
				}
226
227
				foreach ( $package['rates'] as $key => $rate ) {
228
					$data[] = array(
229
						'id'       => $rate->id,
230
						'label'    => $rate->label,
231
						'amount'   => array(
232
							'currency' => $currency,
233
							'value'    => $rate->cost,
234
						),
235
						'selected' => false,
236
					);
237
				}
238
			}
239
		}
240
241
		// Auto select when have only one shipping method available.
242
		if ( 1 === count( $data ) ) {
243
			$data[0]['selected'] = true;
244
		}
245
246
		wp_send_json( $data );
247
	}
248
249
	/**
250
	 * Update shipping method.
251
	 */
252
	public function ajax_update_shipping_method() {
253
		check_ajax_referer( 'wc-stripe-update-shipping-method', 'security' );
254
255
		if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
256
			define( 'WOOCOMMERCE_CART', true );
257
		}
258
259
		$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );
260
		$shipping_method         = filter_input( INPUT_POST, 'shipping_method', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
261
262
		if ( is_array( $shipping_method ) ) {
263
			foreach ( $shipping_method as $i => $value ) {
264
				$chosen_shipping_methods[ $i ] = wc_clean( $value );
265
			}
266
		}
267
268
		WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods );
269
270
		WC()->cart->calculate_totals();
271
272
		// Send back the new cart total and line items to be displayed, such as subtotal, shipping rate(s), fees and taxes.
273
		$data      = array(
274
			'total' => WC()->cart->total,
275
			'items' => $this->compute_display_items( $shipping_method[0] ),
276
		);
277
278
		wp_send_json( $data );
279
	}
280
281
	/**
282
	 * Create order.
283
	 */
284
	public function ajax_create_order() {
285
		if ( WC()->cart->is_empty() ) {
286
			wp_send_json_error( __( 'Empty cart', 'woocommerce-gateway-stripe' ) );
287
		}
288
289
		if ( ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) {
290
			define( 'WOOCOMMERCE_CHECKOUT', true );
291
		}
292
293
		WC()->checkout()->process_checkout();
294
295
		die( 0 );
296
	}
297
298
	/**
299
	 * Compute display items to be included in the 'displayItems' key of the PaymentDetails.
300
	 *
301
	 * @param string shipping_method_id If shipping method ID is provided, will include display items about shipping.
302
	 */
303
	protected function compute_display_items( $shipping_method_id ) {
304
		$currency = get_woocommerce_currency();
305
		$items = array(
306
			// Subtotal excluding tax, because taxes is a separate item, below.
307
			array(
308
				'label' => __( 'Subtotal', 'woocommerce-gateway-stripe' ),
309
				'amount' => array(
310
					'value'    => max( 0, round( WC()->cart->subtotal_ex_tax, WC()->cart->dp ) ),
311
					'currency' => $currency,
312
				),
313
			),
314
		);
315
		// If a chosen shipping option was provided, add line item(s) for it and include the shipping tax.
316
		$tax_total = max( 0, round( WC()->cart->tax_total, WC()->cart->dp ) );
317
		if ( $shipping_method_id ) {
318
			$tax_total = max( 0, round( WC()->cart->tax_total + WC()->cart->shipping_tax_total, WC()->cart->dp ) );
319
			// Look through the package rates for $shipping_method_id, and when found, add a line item.
320
			foreach ( WC()->shipping->get_packages() as $package_key => $package ) {
321
				foreach ( $package['rates'] as $key => $rate ) {
322
					if ( $rate->id  == $shipping_method_id ) {
323
						$items[] = array(
324
							'label' => $rate->label,
325
							'amount' => array(
326
								'value' => $rate->cost,
327
								'currency' => $currency,
328
							),
329
						);
330
						break;
331
					}
332
				}
333
			}
334
		}
335
		// Include fees and taxes as display items.
336 View Code Duplication
		foreach ( WC()->cart->fees as $key => $fee ) {
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...
337
			$items[] = array(
338
				'label'  => $fee->name,
339
				'amount' => array(
340
					'currency' => $currency,
341
					'value'    => $fee->amount,
342
				),
343
			);
344
		}
345
		// The tax total may include the shipping taxes if a shipping option is provided.
346 View Code Duplication
		if ( 0 < $tax_total ) {
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...
347
			$items[] = array(
348
				'label'  => __( 'Tax', 'woocommerce-gateway-stripe' ),
349
				'amount' => array(
350
					'currency' => $currency,
351
					'value'    => $tax_total,
352
				),
353
			);
354
		}
355
		return $items;
356
	}
357
}
358
359
new WC_Stripe_Payment_Request();
360