This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | if ( ! defined( 'ABSPATH' ) ) { |
||
4 | exit; // Exit if accessed directly |
||
5 | } |
||
6 | |||
7 | /** |
||
8 | * Checkout |
||
9 | * |
||
10 | * The WooCommerce checkout class handles the checkout process, collecting user data and processing the payment. |
||
11 | * |
||
12 | * @class WC_Checkout |
||
13 | * @version 2.1.0 |
||
14 | * @package WooCommerce/Classes |
||
15 | * @category Class |
||
16 | * @author WooThemes |
||
17 | */ |
||
18 | class WC_Checkout { |
||
19 | |||
20 | /** @var array Array of posted form data. */ |
||
21 | public $posted; |
||
22 | |||
23 | /** @var array Array of fields to display on the checkout. */ |
||
24 | public $checkout_fields; |
||
25 | |||
26 | /** @var bool Whether or not the user must create an account to checkout. */ |
||
27 | public $must_create_account; |
||
28 | |||
29 | /** @var bool Whether or not signups are allowed. */ |
||
30 | public $enable_signup; |
||
31 | |||
32 | /** @var object The shipping method being used. */ |
||
33 | private $shipping_method; |
||
34 | |||
35 | /** @var WC_Payment_Gateway|string The payment gateway being used. */ |
||
36 | private $payment_method; |
||
37 | |||
38 | /** @var int ID of customer. */ |
||
39 | private $customer_id; |
||
40 | |||
41 | /** @var array Where shipping_methods are stored. */ |
||
42 | public $shipping_methods; |
||
43 | |||
44 | /** |
||
45 | * @var WC_Checkout The single instance of the class |
||
46 | * @since 2.1 |
||
47 | */ |
||
48 | protected static $_instance = null; |
||
49 | |||
50 | /** @var Bool */ |
||
51 | public $enable_guest_checkout; |
||
52 | |||
53 | /** |
||
54 | * Main WC_Checkout Instance. |
||
55 | * |
||
56 | * Ensures only one instance of WC_Checkout is loaded or can be loaded. |
||
57 | * |
||
58 | * @since 2.1 |
||
59 | * @static |
||
60 | * @return WC_Checkout Main instance |
||
61 | */ |
||
62 | public static function instance() { |
||
63 | if ( is_null( self::$_instance ) ) |
||
64 | self::$_instance = new self(); |
||
65 | return self::$_instance; |
||
66 | } |
||
67 | |||
68 | /** |
||
69 | * Cloning is forbidden. |
||
70 | * |
||
71 | * @since 2.1 |
||
72 | */ |
||
73 | public function __clone() { |
||
74 | _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?', 'woocommerce' ), '2.1' ); |
||
75 | } |
||
76 | |||
77 | /** |
||
78 | * Unserializing instances of this class is forbidden. |
||
79 | * |
||
80 | * @since 2.1 |
||
81 | */ |
||
82 | public function __wakeup() { |
||
83 | _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?', 'woocommerce' ), '2.1' ); |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Constructor for the checkout class. Hooks in methods and defines checkout fields. |
||
88 | * |
||
89 | * @access public |
||
90 | */ |
||
91 | public function __construct () { |
||
92 | add_action( 'woocommerce_checkout_billing', array( $this,'checkout_form_billing' ) ); |
||
93 | add_action( 'woocommerce_checkout_shipping', array( $this,'checkout_form_shipping' ) ); |
||
94 | |||
95 | $this->enable_signup = get_option( 'woocommerce_enable_signup_and_login_from_checkout' ) == 'yes' ? true : false; |
||
96 | $this->enable_guest_checkout = get_option( 'woocommerce_enable_guest_checkout' ) == 'yes' ? true : false; |
||
97 | $this->must_create_account = $this->enable_guest_checkout || is_user_logged_in() ? false : true; |
||
98 | |||
99 | // Define all Checkout fields |
||
100 | $this->checkout_fields['billing'] = WC()->countries->get_address_fields( $this->get_value( 'billing_country' ), 'billing_' ); |
||
101 | $this->checkout_fields['shipping'] = WC()->countries->get_address_fields( $this->get_value( 'shipping_country' ), 'shipping_' ); |
||
102 | |||
103 | View Code Duplication | if ( get_option( 'woocommerce_registration_generate_username' ) == 'no' ) { |
|
104 | $this->checkout_fields['account']['account_username'] = array( |
||
105 | 'type' => 'text', |
||
106 | 'label' => __( 'Account username', 'woocommerce' ), |
||
107 | 'required' => true, |
||
108 | 'placeholder' => _x( 'Username', 'placeholder', 'woocommerce' ) |
||
109 | ); |
||
110 | } |
||
111 | |||
112 | View Code Duplication | if ( get_option( 'woocommerce_registration_generate_password' ) == 'no' ) { |
|
113 | $this->checkout_fields['account']['account_password'] = array( |
||
114 | 'type' => 'password', |
||
115 | 'label' => __( 'Account password', 'woocommerce' ), |
||
116 | 'required' => true, |
||
117 | 'placeholder' => _x( 'Password', 'placeholder', 'woocommerce' ) |
||
118 | ); |
||
119 | } |
||
120 | |||
121 | $this->checkout_fields['order'] = array( |
||
122 | 'order_comments' => array( |
||
123 | 'type' => 'textarea', |
||
124 | 'class' => array('notes'), |
||
125 | 'label' => __( 'Order Notes', 'woocommerce' ), |
||
126 | 'placeholder' => _x('Notes about your order, e.g. special notes for delivery.', 'placeholder', 'woocommerce') |
||
127 | ) |
||
128 | ); |
||
129 | |||
130 | $this->checkout_fields = apply_filters( 'woocommerce_checkout_fields', $this->checkout_fields ); |
||
131 | |||
132 | do_action( 'woocommerce_checkout_init', $this ); |
||
133 | } |
||
134 | |||
135 | /** |
||
136 | * Checkout process. |
||
137 | */ |
||
138 | public function check_cart_items() { |
||
139 | // When we process the checkout, lets ensure cart items are rechecked to prevent checkout |
||
140 | do_action('woocommerce_check_cart_items'); |
||
141 | } |
||
142 | |||
143 | /** |
||
144 | * Output the billing information form. |
||
145 | */ |
||
146 | public function checkout_form_billing() { |
||
147 | wc_get_template( 'checkout/form-billing.php', array( 'checkout' => $this ) ); |
||
148 | } |
||
149 | |||
150 | /** |
||
151 | * Output the shipping information form. |
||
152 | */ |
||
153 | public function checkout_form_shipping() { |
||
154 | wc_get_template( 'checkout/form-shipping.php', array( 'checkout' => $this ) ); |
||
155 | } |
||
156 | |||
157 | /** |
||
158 | * Create an order. Error codes: |
||
159 | * 520 - Cannot insert order into the database. |
||
160 | * 521 - Cannot get order after creation. |
||
161 | * 522 - Cannot update order. |
||
162 | * 525 - Cannot create line item. |
||
163 | * 526 - Cannot create fee item. |
||
164 | * 527 - Cannot create shipping item. |
||
165 | * 528 - Cannot create tax item. |
||
166 | * 529 - Cannot create coupon item. |
||
167 | * @access public |
||
168 | * @throws Exception |
||
169 | * @return int|WP_ERROR |
||
170 | */ |
||
171 | public function create_order() { |
||
172 | global $wpdb; |
||
173 | |||
174 | // Give plugins the opportunity to create an order themselves |
||
175 | if ( $order_id = apply_filters( 'woocommerce_create_order', null, $this ) ) { |
||
176 | return $order_id; |
||
177 | } |
||
178 | |||
179 | try { |
||
180 | // Start transaction if available |
||
181 | wc_transaction_query( 'start' ); |
||
182 | |||
183 | $order_data = array( |
||
184 | 'status' => apply_filters( 'woocommerce_default_order_status', 'pending' ), |
||
185 | 'customer_id' => $this->customer_id, |
||
186 | 'customer_note' => isset( $this->posted['order_comments'] ) ? $this->posted['order_comments'] : '', |
||
187 | 'cart_hash' => md5( json_encode( wc_clean( WC()->cart->get_cart_for_session() ) ) . WC()->cart->total ), |
||
188 | 'created_via' => 'checkout', |
||
189 | ); |
||
190 | |||
191 | // Insert or update the post data |
||
192 | $order_id = absint( WC()->session->order_awaiting_payment ); |
||
193 | |||
194 | /** |
||
195 | * If there is an order pending payment, we can resume it here so |
||
196 | * long as it has not changed. If the order has changed, i.e. |
||
197 | * different items or cost, create a new order. We use a hash to |
||
198 | * detect changes which is based on cart items + order total. |
||
199 | */ |
||
200 | if ( $order_id && $order_data['cart_hash'] === get_post_meta( $order_id, '_cart_hash', true ) && ( $order = wc_get_order( $order_id ) ) && $order->has_status( array( 'pending', 'failed' ) ) ) { |
||
201 | |||
202 | $order_data['order_id'] = $order_id; |
||
203 | $order = wc_update_order( $order_data ); |
||
204 | |||
205 | if ( is_wp_error( $order ) ) { |
||
206 | throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce' ), 522 ) ); |
||
207 | } else { |
||
208 | $order->remove_order_items(); |
||
209 | do_action( 'woocommerce_resume_order', $order_id ); |
||
210 | } |
||
211 | |||
212 | } else { |
||
213 | |||
214 | $order = wc_create_order( $order_data ); |
||
215 | |||
216 | if ( is_wp_error( $order ) ) { |
||
217 | throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce' ), 520 ) ); |
||
218 | } elseif ( false === $order ) { |
||
219 | throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce' ), 521 ) ); |
||
220 | } else { |
||
221 | $order_id = $order->id; |
||
222 | do_action( 'woocommerce_new_order', $order_id ); |
||
223 | } |
||
224 | } |
||
225 | |||
226 | // Store the line items to the new/resumed order |
||
227 | foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) { |
||
228 | $item_id = $order->add_product( |
||
229 | $values['data'], |
||
230 | $values['quantity'], |
||
231 | array( |
||
232 | 'variation' => $values['variation'], |
||
233 | 'totals' => array( |
||
234 | 'subtotal' => $values['line_subtotal'], |
||
235 | 'subtotal_tax' => $values['line_subtotal_tax'], |
||
236 | 'total' => $values['line_total'], |
||
237 | 'tax' => $values['line_tax'], |
||
238 | 'tax_data' => $values['line_tax_data'] // Since 2.2 |
||
239 | ) |
||
240 | ) |
||
241 | ); |
||
242 | |||
243 | if ( ! $item_id ) { |
||
244 | throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce' ), 525 ) ); |
||
245 | } |
||
246 | |||
247 | // Allow plugins to add order item meta |
||
248 | do_action( 'woocommerce_add_order_item_meta', $item_id, $values, $cart_item_key ); |
||
249 | } |
||
250 | |||
251 | // Store fees |
||
252 | foreach ( WC()->cart->get_fees() as $fee_key => $fee ) { |
||
253 | $item_id = $order->add_fee( $fee ); |
||
254 | |||
255 | if ( ! $item_id ) { |
||
256 | throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce' ), 526 ) ); |
||
257 | } |
||
258 | |||
259 | // Allow plugins to add order item meta to fees |
||
260 | do_action( 'woocommerce_add_order_fee_meta', $order_id, $item_id, $fee, $fee_key ); |
||
261 | } |
||
262 | |||
263 | // Store shipping for all packages |
||
264 | foreach ( WC()->shipping->get_packages() as $package_key => $package ) { |
||
265 | if ( isset( $package['rates'][ $this->shipping_methods[ $package_key ] ] ) ) { |
||
266 | $item_id = $order->add_shipping( $package['rates'][ $this->shipping_methods[ $package_key ] ] ); |
||
267 | |||
268 | if ( ! $item_id ) { |
||
269 | throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce' ), 527 ) ); |
||
270 | } |
||
271 | |||
272 | // Allows plugins to add order item meta to shipping |
||
273 | do_action( 'woocommerce_add_shipping_order_item', $order_id, $item_id, $package_key ); |
||
274 | } |
||
275 | } |
||
276 | |||
277 | // Store tax rows |
||
278 | foreach ( array_keys( WC()->cart->taxes + WC()->cart->shipping_taxes ) as $tax_rate_id ) { |
||
279 | 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 ) { |
||
280 | throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce' ), 528 ) ); |
||
281 | } |
||
282 | } |
||
283 | |||
284 | // Store coupons |
||
285 | foreach ( WC()->cart->get_coupons() as $code => $coupon ) { |
||
286 | if ( ! $order->add_coupon( $code, WC()->cart->get_coupon_discount_amount( $code ), WC()->cart->get_coupon_discount_tax_amount( $code ) ) ) { |
||
287 | throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'woocommerce' ), 529 ) ); |
||
288 | } |
||
289 | } |
||
290 | |||
291 | // Billing address |
||
292 | $billing_address = array(); |
||
293 | View Code Duplication | if ( $this->checkout_fields['billing'] ) { |
|
294 | foreach ( array_keys( $this->checkout_fields['billing'] ) as $field ) { |
||
295 | $field_name = str_replace( 'billing_', '', $field ); |
||
296 | $billing_address[ $field_name ] = $this->get_posted_address_data( $field_name ); |
||
297 | } |
||
298 | } |
||
299 | |||
300 | // Shipping address. |
||
301 | $shipping_address = array(); |
||
302 | View Code Duplication | if ( $this->checkout_fields['shipping'] ) { |
|
303 | foreach ( array_keys( $this->checkout_fields['shipping'] ) as $field ) { |
||
304 | $field_name = str_replace( 'shipping_', '', $field ); |
||
305 | $shipping_address[ $field_name ] = $this->get_posted_address_data( $field_name, 'shipping' ); |
||
306 | } |
||
307 | } |
||
308 | |||
309 | $order->set_address( $billing_address, 'billing' ); |
||
310 | $order->set_address( $shipping_address, 'shipping' ); |
||
311 | $order->set_payment_method( $this->payment_method ); |
||
312 | $order->set_total( WC()->cart->shipping_total, 'shipping' ); |
||
313 | $order->set_total( WC()->cart->get_cart_discount_total(), 'cart_discount' ); |
||
314 | $order->set_total( WC()->cart->get_cart_discount_tax_total(), 'cart_discount_tax' ); |
||
315 | $order->set_total( WC()->cart->tax_total, 'tax' ); |
||
316 | $order->set_total( WC()->cart->shipping_tax_total, 'shipping_tax' ); |
||
317 | $order->set_total( WC()->cart->total ); |
||
318 | |||
319 | // Update user meta |
||
320 | if ( $this->customer_id ) { |
||
321 | if ( apply_filters( 'woocommerce_checkout_update_customer_data', true, $this ) ) { |
||
322 | foreach ( $billing_address as $key => $value ) { |
||
323 | update_user_meta( $this->customer_id, 'billing_' . $key, $value ); |
||
324 | } |
||
325 | if ( WC()->cart->needs_shipping() ) { |
||
326 | foreach ( $shipping_address as $key => $value ) { |
||
327 | update_user_meta( $this->customer_id, 'shipping_' . $key, $value ); |
||
328 | } |
||
329 | } |
||
330 | } |
||
331 | do_action( 'woocommerce_checkout_update_user_meta', $this->customer_id, $this->posted ); |
||
332 | } |
||
333 | |||
334 | // Let plugins add meta |
||
335 | do_action( 'woocommerce_checkout_update_order_meta', $order_id, $this->posted ); |
||
336 | |||
337 | // If we got here, the order was created without problems! |
||
338 | wc_transaction_query( 'commit' ); |
||
339 | |||
340 | } catch ( Exception $e ) { |
||
341 | // There was an error adding order data! |
||
342 | wc_transaction_query( 'rollback' ); |
||
343 | return new WP_Error( 'checkout-error', $e->getMessage() ); |
||
344 | } |
||
345 | |||
346 | return $order_id; |
||
347 | } |
||
348 | |||
349 | /** |
||
350 | * Process the checkout after the confirm order button is pressed. |
||
351 | */ |
||
352 | public function process_checkout() { |
||
353 | try { |
||
354 | if ( empty( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'woocommerce-process_checkout' ) ) { |
||
355 | WC()->session->set( 'refresh_totals', true ); |
||
356 | throw new Exception( __( 'We were unable to process your order, please try again.', 'woocommerce' ) ); |
||
357 | } |
||
358 | |||
359 | if ( ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) { |
||
360 | define( 'WOOCOMMERCE_CHECKOUT', true ); |
||
361 | } |
||
362 | |||
363 | // Prevent timeout |
||
364 | @set_time_limit(0); |
||
365 | |||
366 | do_action( 'woocommerce_before_checkout_process' ); |
||
367 | |||
368 | if ( WC()->cart->is_empty() ) { |
||
369 | throw new Exception( sprintf( __( 'Sorry, your session has expired. <a href="%s" class="wc-backward">Return to shop</a>', 'woocommerce' ), esc_url( wc_get_page_permalink( 'shop' ) ) ) ); |
||
370 | } |
||
371 | |||
372 | do_action( 'woocommerce_checkout_process' ); |
||
373 | |||
374 | // Checkout fields (not defined in checkout_fields) |
||
375 | $this->posted['terms'] = isset( $_POST['terms'] ) ? 1 : 0; |
||
376 | $this->posted['createaccount'] = isset( $_POST['createaccount'] ) && ! empty( $_POST['createaccount'] ) ? 1 : 0; |
||
377 | $this->posted['payment_method'] = isset( $_POST['payment_method'] ) ? stripslashes( $_POST['payment_method'] ) : ''; |
||
378 | $this->posted['shipping_method'] = isset( $_POST['shipping_method'] ) ? $_POST['shipping_method'] : ''; |
||
379 | $this->posted['ship_to_different_address'] = isset( $_POST['ship_to_different_address'] ) ? true : false; |
||
380 | |||
381 | if ( isset( $_POST['shiptobilling'] ) ) { |
||
382 | _deprecated_argument( 'WC_Checkout::process_checkout()', '2.1', 'The "shiptobilling" field is deprecated. The template files are out of date' ); |
||
383 | |||
384 | $this->posted['ship_to_different_address'] = $_POST['shiptobilling'] ? false : true; |
||
385 | } |
||
386 | |||
387 | // Ship to billing only option |
||
388 | if ( wc_ship_to_billing_address_only() ) { |
||
389 | $this->posted['ship_to_different_address'] = false; |
||
390 | } |
||
391 | |||
392 | // Update customer shipping and payment method to posted method |
||
393 | $chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' ); |
||
394 | |||
395 | if ( isset( $this->posted['shipping_method'] ) && is_array( $this->posted['shipping_method'] ) ) { |
||
396 | foreach ( $this->posted['shipping_method'] as $i => $value ) { |
||
397 | $chosen_shipping_methods[ $i ] = wc_clean( $value ); |
||
398 | } |
||
399 | } |
||
400 | |||
401 | WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods ); |
||
402 | WC()->session->set( 'chosen_payment_method', $this->posted['payment_method'] ); |
||
403 | |||
404 | // Note if we skip shipping |
||
405 | $skipped_shipping = false; |
||
406 | |||
407 | // Get posted checkout_fields and do validation |
||
408 | foreach ( $this->checkout_fields as $fieldset_key => $fieldset ) { |
||
409 | |||
410 | // Skip shipping if not needed |
||
411 | if ( $fieldset_key == 'shipping' && ( $this->posted['ship_to_different_address'] == false || ! WC()->cart->needs_shipping_address() ) ) { |
||
412 | $skipped_shipping = true; |
||
413 | continue; |
||
414 | } |
||
415 | |||
416 | // Skip account if not needed |
||
417 | if ( $fieldset_key == 'account' && ( is_user_logged_in() || ( $this->must_create_account == false && empty( $this->posted['createaccount'] ) ) ) ) { |
||
418 | continue; |
||
419 | } |
||
420 | |||
421 | foreach ( $fieldset as $key => $field ) { |
||
422 | |||
423 | if ( ! isset( $field['type'] ) ) { |
||
424 | $field['type'] = 'text'; |
||
425 | } |
||
426 | |||
427 | // Get Value |
||
428 | switch ( $field['type'] ) { |
||
429 | case "checkbox" : |
||
430 | $this->posted[ $key ] = isset( $_POST[ $key ] ) ? 1 : 0; |
||
431 | break; |
||
432 | case "multiselect" : |
||
433 | $this->posted[ $key ] = isset( $_POST[ $key ] ) ? implode( ', ', array_map( 'wc_clean', $_POST[ $key ] ) ) : ''; |
||
434 | break; |
||
435 | case "textarea" : |
||
436 | $this->posted[ $key ] = isset( $_POST[ $key ] ) ? wp_strip_all_tags( wp_check_invalid_utf8( stripslashes( $_POST[ $key ] ) ) ) : ''; |
||
437 | break; |
||
438 | default : |
||
439 | $this->posted[ $key ] = isset( $_POST[ $key ] ) ? ( is_array( $_POST[ $key ] ) ? array_map( 'wc_clean', $_POST[ $key ] ) : wc_clean( $_POST[ $key ] ) ) : ''; |
||
440 | break; |
||
441 | } |
||
442 | |||
443 | // Hooks to allow modification of value |
||
444 | $this->posted[ $key ] = apply_filters( 'woocommerce_process_checkout_' . sanitize_title( $field['type'] ) . '_field', $this->posted[ $key ] ); |
||
445 | $this->posted[ $key ] = apply_filters( 'woocommerce_process_checkout_field_' . $key, $this->posted[ $key ] ); |
||
446 | |||
447 | // Validation: Required fields |
||
448 | if ( isset( $field['required'] ) && $field['required'] && ( ! isset( $this->posted[ $key ] ) || "" === $this->posted[ $key ] ) ) { |
||
449 | switch ( $fieldset_key ) { |
||
450 | case 'shipping' : |
||
451 | $field_label = sprintf( _x( 'Shipping %s', 'Shipping FIELDNAME', 'woocommerce' ), $field['label'] ); |
||
452 | break; |
||
453 | case 'billing' : |
||
454 | $field_label = sprintf( _x( 'Billing %s', 'Billing FIELDNAME', 'woocommerce' ), $field['label'] ); |
||
455 | break; |
||
456 | default : |
||
457 | $field_label = $field['label']; |
||
458 | break; |
||
459 | } |
||
460 | wc_add_notice( apply_filters( 'woocommerce_checkout_required_field_notice', sprintf( _x( '%s is a required field.', 'FIELDNAME is a required field.', 'woocommerce' ), '<strong>' . $field_label . '</strong>' ), $field_label ), 'error' ); |
||
461 | } |
||
462 | |||
463 | if ( ! empty( $this->posted[ $key ] ) ) { |
||
464 | |||
465 | // Validation rules |
||
466 | if ( ! empty( $field['validate'] ) && is_array( $field['validate'] ) ) { |
||
467 | foreach ( $field['validate'] as $rule ) { |
||
468 | switch ( $rule ) { |
||
469 | case 'postcode' : |
||
470 | $this->posted[ $key ] = strtoupper( str_replace( ' ', '', $this->posted[ $key ] ) ); |
||
471 | |||
472 | if ( ! WC_Validation::is_postcode( $this->posted[ $key ], $_POST[ $fieldset_key . '_country' ] ) ) : |
||
473 | wc_add_notice( __( 'Please enter a valid postcode/ZIP.', 'woocommerce' ), 'error' ); |
||
474 | else : |
||
475 | $this->posted[ $key ] = wc_format_postcode( $this->posted[ $key ], $_POST[ $fieldset_key . '_country' ] ); |
||
476 | endif; |
||
477 | break; |
||
478 | View Code Duplication | case 'phone' : |
|
479 | $this->posted[ $key ] = wc_format_phone_number( $this->posted[ $key ] ); |
||
480 | |||
481 | if ( ! WC_Validation::is_phone( $this->posted[ $key ] ) ) |
||
482 | wc_add_notice( '<strong>' . $field['label'] . '</strong> ' . __( 'is not a valid phone number.', 'woocommerce' ), 'error' ); |
||
483 | break; |
||
484 | View Code Duplication | case 'email' : |
|
485 | $this->posted[ $key ] = strtolower( $this->posted[ $key ] ); |
||
486 | |||
487 | if ( ! is_email( $this->posted[ $key ] ) ) |
||
488 | wc_add_notice( '<strong>' . $field['label'] . '</strong> ' . __( 'is not a valid email address.', 'woocommerce' ), 'error' ); |
||
489 | break; |
||
490 | case 'state' : |
||
491 | // Get valid states |
||
492 | $valid_states = WC()->countries->get_states( isset( $_POST[ $fieldset_key . '_country' ] ) ? $_POST[ $fieldset_key . '_country' ] : ( 'billing' === $fieldset_key ? WC()->customer->get_country() : WC()->customer->get_shipping_country() ) ); |
||
493 | |||
494 | if ( ! empty( $valid_states ) && is_array( $valid_states ) ) { |
||
495 | $valid_state_values = array_flip( array_map( 'strtolower', $valid_states ) ); |
||
496 | |||
497 | // Convert value to key if set |
||
498 | if ( isset( $valid_state_values[ strtolower( $this->posted[ $key ] ) ] ) ) { |
||
499 | $this->posted[ $key ] = $valid_state_values[ strtolower( $this->posted[ $key ] ) ]; |
||
500 | } |
||
501 | } |
||
502 | |||
503 | // Only validate if the country has specific state options |
||
504 | if ( ! empty( $valid_states ) && is_array( $valid_states ) && sizeof( $valid_states ) > 0 ) { |
||
505 | if ( ! in_array( $this->posted[ $key ], array_keys( $valid_states ) ) ) { |
||
506 | wc_add_notice( '<strong>' . $field['label'] . '</strong> ' . __( 'is not valid. Please enter one of the following:', 'woocommerce' ) . ' ' . implode( ', ', $valid_states ), 'error' ); |
||
507 | } |
||
508 | } |
||
509 | break; |
||
510 | } |
||
511 | } |
||
512 | } |
||
513 | } |
||
514 | } |
||
515 | } |
||
516 | |||
517 | // Update customer location to posted location so we can correctly check available shipping methods |
||
518 | if ( isset( $this->posted['billing_country'] ) ) { |
||
519 | WC()->customer->set_country( $this->posted['billing_country'] ); |
||
520 | } |
||
521 | if ( isset( $this->posted['billing_state'] ) ) { |
||
522 | WC()->customer->set_state( $this->posted['billing_state'] ); |
||
523 | } |
||
524 | if ( isset( $this->posted['billing_postcode'] ) ) { |
||
525 | WC()->customer->set_postcode( $this->posted['billing_postcode'] ); |
||
526 | } |
||
527 | |||
528 | // Shipping Information |
||
529 | if ( ! $skipped_shipping ) { |
||
530 | |||
531 | // Update customer location to posted location so we can correctly check available shipping methods |
||
532 | if ( isset( $this->posted['shipping_country'] ) ) { |
||
533 | WC()->customer->set_shipping_country( $this->posted['shipping_country'] ); |
||
534 | } |
||
535 | if ( isset( $this->posted['shipping_state'] ) ) { |
||
536 | WC()->customer->set_shipping_state( $this->posted['shipping_state'] ); |
||
537 | } |
||
538 | if ( isset( $this->posted['shipping_postcode'] ) ) { |
||
539 | WC()->customer->set_shipping_postcode( $this->posted['shipping_postcode'] ); |
||
540 | } |
||
541 | |||
542 | } else { |
||
543 | |||
544 | // Update customer location to posted location so we can correctly check available shipping methods |
||
545 | if ( isset( $this->posted['billing_country'] ) ) { |
||
546 | WC()->customer->set_shipping_country( $this->posted['billing_country'] ); |
||
547 | } |
||
548 | if ( isset( $this->posted['billing_state'] ) ) { |
||
549 | WC()->customer->set_shipping_state( $this->posted['billing_state'] ); |
||
550 | } |
||
551 | if ( isset( $this->posted['billing_postcode'] ) ) { |
||
552 | WC()->customer->set_shipping_postcode( $this->posted['billing_postcode'] ); |
||
553 | } |
||
554 | |||
555 | } |
||
556 | |||
557 | // Update cart totals now we have customer address |
||
558 | WC()->cart->calculate_totals(); |
||
559 | |||
560 | // Terms |
||
561 | if ( ! isset( $_POST['woocommerce_checkout_update_totals'] ) && empty( $this->posted['terms'] ) && wc_get_page_id( 'terms' ) > 0 && apply_filters( 'woocommerce_checkout_show_terms', true ) ) { |
||
562 | wc_add_notice( __( 'You must accept our Terms & Conditions.', 'woocommerce' ), 'error' ); |
||
563 | } |
||
564 | |||
565 | if ( WC()->cart->needs_shipping() ) { |
||
566 | $shipping_country = WC()->customer->get_shipping_country(); |
||
567 | |||
568 | if ( empty( $shipping_country ) ) { |
||
569 | wc_add_notice( __( 'Please enter an address to continue.', 'woocommerce' ), 'error' ); |
||
570 | } elseif ( ! in_array( WC()->customer->get_shipping_country(), array_keys( WC()->countries->get_shipping_countries() ) ) ) { |
||
571 | wc_add_notice( sprintf( __( 'Unfortunately <strong>we do not ship %s</strong>. Please enter an alternative shipping address.', 'woocommerce' ), WC()->countries->shipping_to_prefix() . ' ' . WC()->customer->get_shipping_country() ), 'error' ); |
||
572 | } |
||
573 | |||
574 | // Validate Shipping Methods |
||
575 | $packages = WC()->shipping->get_packages(); |
||
576 | $this->shipping_methods = WC()->session->get( 'chosen_shipping_methods' ); |
||
577 | |||
578 | foreach ( $packages as $i => $package ) { |
||
579 | if ( ! isset( $package['rates'][ $this->shipping_methods[ $i ] ] ) ) { |
||
580 | wc_add_notice( __( 'No shipping method has been selected. Please double check your address, or contact us if you need any help.', 'woocommerce' ), 'error' ); |
||
581 | $this->shipping_methods[ $i ] = ''; |
||
582 | } |
||
583 | } |
||
584 | } |
||
585 | |||
586 | if ( WC()->cart->needs_payment() ) { |
||
587 | // Payment Method |
||
588 | $available_gateways = WC()->payment_gateways->get_available_payment_gateways(); |
||
589 | |||
590 | if ( ! isset( $available_gateways[ $this->posted['payment_method'] ] ) ) { |
||
591 | $this->payment_method = ''; |
||
592 | wc_add_notice( __( 'Invalid payment method.', 'woocommerce' ), 'error' ); |
||
593 | } else { |
||
594 | $this->payment_method = $available_gateways[ $this->posted['payment_method'] ]; |
||
595 | $this->payment_method->validate_fields(); |
||
596 | } |
||
597 | } else { |
||
598 | $available_gateways = array(); |
||
599 | } |
||
600 | |||
601 | // Action after validation |
||
602 | do_action( 'woocommerce_after_checkout_validation', $this->posted ); |
||
603 | |||
604 | if ( ! isset( $_POST['woocommerce_checkout_update_totals'] ) && wc_notice_count( 'error' ) == 0 ) { |
||
605 | |||
606 | // Customer accounts |
||
607 | $this->customer_id = apply_filters( 'woocommerce_checkout_customer_id', get_current_user_id() ); |
||
608 | |||
609 | if ( ! is_user_logged_in() && ( $this->must_create_account || ! empty( $this->posted['createaccount'] ) ) ) { |
||
610 | |||
611 | $username = ! empty( $this->posted['account_username'] ) ? $this->posted['account_username'] : ''; |
||
612 | $password = ! empty( $this->posted['account_password'] ) ? $this->posted['account_password'] : ''; |
||
613 | $new_customer = wc_create_new_customer( $this->posted['billing_email'], $username, $password ); |
||
614 | |||
615 | if ( is_wp_error( $new_customer ) ) { |
||
616 | throw new Exception( $new_customer->get_error_message() ); |
||
617 | } |
||
618 | |||
619 | $this->customer_id = $new_customer; |
||
0 ignored issues
–
show
|
|||
620 | |||
621 | wc_set_customer_auth_cookie( $this->customer_id ); |
||
622 | |||
623 | // As we are now logged in, checkout will need to refresh to show logged in data |
||
624 | WC()->session->set( 'reload_checkout', true ); |
||
625 | |||
626 | // Also, recalculate cart totals to reveal any role-based discounts that were unavailable before registering |
||
627 | WC()->cart->calculate_totals(); |
||
628 | |||
629 | // Add customer info from other billing fields |
||
630 | if ( $this->posted['billing_first_name'] && apply_filters( 'woocommerce_checkout_update_customer_data', true, $this ) ) { |
||
631 | $userdata = array( |
||
632 | 'ID' => $this->customer_id, |
||
633 | 'first_name' => $this->posted['billing_first_name'] ? $this->posted['billing_first_name'] : '', |
||
634 | 'last_name' => $this->posted['billing_last_name'] ? $this->posted['billing_last_name'] : '', |
||
635 | 'display_name' => $this->posted['billing_first_name'] ? $this->posted['billing_first_name'] : '' |
||
636 | ); |
||
637 | wp_update_user( apply_filters( 'woocommerce_checkout_customer_userdata', $userdata, $this ) ); |
||
638 | } |
||
639 | } |
||
640 | |||
641 | // Do a final stock check at this point |
||
642 | $this->check_cart_items(); |
||
643 | |||
644 | // Abort if errors are present |
||
645 | if ( wc_notice_count( 'error' ) > 0 ) |
||
646 | throw new Exception(); |
||
647 | |||
648 | $order_id = $this->create_order(); |
||
649 | |||
650 | if ( is_wp_error( $order_id ) ) { |
||
651 | throw new Exception( $order_id->get_error_message() ); |
||
652 | } |
||
653 | |||
654 | do_action( 'woocommerce_checkout_order_processed', $order_id, $this->posted ); |
||
655 | |||
656 | // Process payment |
||
657 | if ( WC()->cart->needs_payment() ) { |
||
658 | |||
659 | // Store Order ID in session so it can be re-used after payment failure |
||
660 | WC()->session->order_awaiting_payment = $order_id; |
||
661 | |||
662 | // Process Payment |
||
663 | $result = $available_gateways[ $this->posted['payment_method'] ]->process_payment( $order_id ); |
||
664 | |||
665 | // Redirect to success/confirmation/payment page |
||
666 | if ( isset( $result['result'] ) && 'success' === $result['result'] ) { |
||
667 | |||
668 | $result = apply_filters( 'woocommerce_payment_successful_result', $result, $order_id ); |
||
669 | |||
670 | if ( is_ajax() ) { |
||
671 | wp_send_json( $result ); |
||
672 | } else { |
||
673 | wp_redirect( $result['redirect'] ); |
||
674 | exit; |
||
675 | } |
||
676 | |||
677 | } |
||
678 | |||
679 | } else { |
||
680 | |||
681 | if ( empty( $order ) ) { |
||
682 | $order = wc_get_order( $order_id ); |
||
683 | } |
||
684 | |||
685 | // No payment was required for order |
||
686 | $order->payment_complete(); |
||
687 | |||
688 | // Empty the Cart |
||
689 | WC()->cart->empty_cart(); |
||
690 | |||
691 | // Get redirect |
||
692 | $return_url = $order->get_checkout_order_received_url(); |
||
693 | |||
694 | // Redirect to success/confirmation/payment page |
||
695 | if ( is_ajax() ) { |
||
696 | wp_send_json( array( |
||
697 | 'result' => 'success', |
||
698 | 'redirect' => apply_filters( 'woocommerce_checkout_no_payment_needed_redirect', $return_url, $order ) |
||
699 | ) ); |
||
700 | } else { |
||
701 | wp_safe_redirect( |
||
702 | apply_filters( 'woocommerce_checkout_no_payment_needed_redirect', $return_url, $order ) |
||
703 | ); |
||
704 | exit; |
||
705 | } |
||
706 | |||
707 | } |
||
708 | |||
709 | } |
||
710 | |||
711 | } catch ( Exception $e ) { |
||
712 | if ( ! empty( $e ) ) { |
||
713 | wc_add_notice( $e->getMessage(), 'error' ); |
||
714 | } |
||
715 | } |
||
716 | |||
717 | // If we reached this point then there were errors |
||
718 | if ( is_ajax() ) { |
||
719 | |||
720 | // only print notices if not reloading the checkout, otherwise they're lost in the page reload |
||
721 | if ( ! isset( WC()->session->reload_checkout ) ) { |
||
722 | ob_start(); |
||
723 | wc_print_notices(); |
||
724 | $messages = ob_get_clean(); |
||
725 | } |
||
726 | |||
727 | $response = array( |
||
728 | 'result' => 'failure', |
||
729 | 'messages' => isset( $messages ) ? $messages : '', |
||
730 | 'refresh' => isset( WC()->session->refresh_totals ) ? 'true' : 'false', |
||
731 | 'reload' => isset( WC()->session->reload_checkout ) ? 'true' : 'false' |
||
732 | ); |
||
733 | |||
734 | unset( WC()->session->refresh_totals, WC()->session->reload_checkout ); |
||
735 | |||
736 | wp_send_json( $response ); |
||
737 | } |
||
738 | } |
||
739 | |||
740 | /** |
||
741 | * Get a posted address field after sanitization and validation. |
||
742 | * @param string $key |
||
743 | * @param string $type billing for shipping |
||
744 | * @return string |
||
745 | */ |
||
746 | public function get_posted_address_data( $key, $type = 'billing' ) { |
||
747 | if ( 'billing' === $type || false === $this->posted['ship_to_different_address'] ) { |
||
748 | $return = isset( $this->posted[ 'billing_' . $key ] ) ? $this->posted[ 'billing_' . $key ] : ''; |
||
749 | } else { |
||
750 | $return = isset( $this->posted[ 'shipping_' . $key ] ) ? $this->posted[ 'shipping_' . $key ] : ''; |
||
751 | } |
||
752 | |||
753 | // Use logged in user's billing email if neccessary |
||
754 | if ( 'email' === $key && empty( $return ) && is_user_logged_in() ) { |
||
755 | $current_user = wp_get_current_user(); |
||
756 | $return = $current_user->user_email; |
||
757 | } |
||
758 | return $return; |
||
759 | } |
||
760 | |||
761 | /** |
||
762 | * Gets the value either from the posted data, or from the users meta data. |
||
763 | * |
||
764 | * @access public |
||
765 | * @param string $input |
||
766 | * @return string|null |
||
767 | */ |
||
768 | public function get_value( $input ) { |
||
769 | if ( ! empty( $_POST[ $input ] ) ) { |
||
770 | |||
771 | return wc_clean( $_POST[ $input ] ); |
||
772 | |||
773 | } else { |
||
774 | |||
775 | $value = apply_filters( 'woocommerce_checkout_get_value', null, $input ); |
||
776 | |||
777 | if ( $value !== null ) { |
||
778 | return $value; |
||
779 | } |
||
780 | |||
781 | // Get the billing_ and shipping_ address fields |
||
782 | if ( isset( $this->checkout_fields['shipping'] ) && isset( $this->checkout_fields['billing'] ) ) { |
||
783 | |||
784 | $address_fields = array_merge( $this->checkout_fields['billing'], $this->checkout_fields['shipping'] ); |
||
785 | |||
786 | if ( is_user_logged_in() && is_array( $address_fields ) && array_key_exists( $input, $address_fields ) ) { |
||
787 | $current_user = wp_get_current_user(); |
||
788 | |||
789 | if ( $meta = get_user_meta( $current_user->ID, $input, true ) ) { |
||
790 | return $meta; |
||
791 | } |
||
792 | |||
793 | if ( $input == 'billing_email' ) { |
||
794 | return $current_user->user_email; |
||
795 | } |
||
796 | } |
||
797 | |||
798 | } |
||
799 | |||
800 | switch ( $input ) { |
||
801 | case 'billing_country' : |
||
802 | return apply_filters( 'default_checkout_country', WC()->customer->get_country() ? WC()->customer->get_country() : '', 'billing' ); |
||
803 | case 'billing_state' : |
||
804 | return apply_filters( 'default_checkout_state', WC()->customer->get_state() ? WC()->customer->get_state() : '', 'billing' ); |
||
805 | case 'billing_postcode' : |
||
806 | return apply_filters( 'default_checkout_postcode', WC()->customer->get_postcode() ? WC()->customer->get_postcode() : '', 'billing' ); |
||
807 | case 'shipping_country' : |
||
808 | return apply_filters( 'default_checkout_country', WC()->customer->get_shipping_country() ? WC()->customer->get_shipping_country() : '', 'shipping' ); |
||
809 | case 'shipping_state' : |
||
810 | return apply_filters( 'default_checkout_state', WC()->customer->get_shipping_state() ? WC()->customer->get_shipping_state() : '', 'shipping' ); |
||
811 | case 'shipping_postcode' : |
||
812 | return apply_filters( 'default_checkout_postcode', WC()->customer->get_shipping_postcode() ? WC()->customer->get_shipping_postcode() : '', 'shipping' ); |
||
813 | default : |
||
814 | return apply_filters( 'default_checkout_' . $input, null, $input ); |
||
815 | } |
||
816 | } |
||
817 | } |
||
818 | } |
||
819 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.