Completed
Pull Request — master (#11843)
by
unknown
22:53
created

WC_Form_Handler::process_registration()   F

Complexity

Conditions 13
Paths 244

Size

Total Lines 40
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 23
c 0
b 0
f 0
nc 244
nop 0
dl 0
loc 40
rs 3.8801

How to fix   Complexity   

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
if ( ! defined( 'ABSPATH' ) ) {
4
	exit; // Exit if accessed directly
5
}
6
7
/**
8
 * Handle frontend forms.
9
 *
10
 * @class 		WC_Form_Handler
11
 * @version		2.2.0
12
 * @package		WooCommerce/Classes/
13
 * @category	Class
14
 * @author 		WooThemes
15
 */
16
class WC_Form_Handler {
17
18
	/**
19
	 * Hook in methods.
20
	 */
21
	public static function init() {
22
		add_action( 'template_redirect', array( __CLASS__, 'redirect_reset_password_link' ) );
23
		add_action( 'template_redirect', array( __CLASS__, 'save_address' ) );
24
		add_action( 'template_redirect', array( __CLASS__, 'save_account_details' ) );
25
		add_action( 'wp_loaded', array( __CLASS__, 'checkout_action' ), 20 );
26
		add_action( 'wp_loaded', array( __CLASS__, 'process_login' ), 20 );
27
		add_action( 'wp_loaded', array( __CLASS__, 'process_registration' ), 20 );
28
		add_action( 'wp_loaded', array( __CLASS__, 'process_lost_password' ), 20 );
29
		add_action( 'wp_loaded', array( __CLASS__, 'process_reset_password' ), 20 );
30
		add_action( 'wp_loaded', array( __CLASS__, 'cancel_order' ), 20 );
31
		add_action( 'wp_loaded', array( __CLASS__, 'order_again' ), 20 );
32
		add_action( 'wp_loaded', array( __CLASS__, 'update_cart_action' ), 20 );
33
		add_action( 'wp_loaded', array( __CLASS__, 'add_to_cart_action' ), 20 );
34
35
		// May need $wp global to access query vars.
36
		add_action( 'wp', array( __CLASS__, 'pay_action' ), 20 );
37
		add_action( 'wp', array( __CLASS__, 'add_payment_method_action' ), 20 );
38
		add_action( 'wp', array( __CLASS__, 'delete_payment_method_action' ), 20 );
39
		add_action( 'wp', array( __CLASS__, 'set_default_payment_method_action' ), 20 );
40
	}
41
42
	/**
43
	 * Remove key and login from querystring, set cookie, and redirect to account page to show the form.
44
	 */
45
	public static function redirect_reset_password_link() {
46
		if ( is_account_page() && ! empty( $_GET['key'] ) && ! empty( $_GET['login'] ) ) {
47
			$value = sprintf( '%s:%s', wp_unslash( $_GET['login'] ), wp_unslash( $_GET['key'] ) );
48
			WC_Shortcode_My_Account::set_reset_password_cookie( $value );
49
50
			wp_safe_redirect( add_query_arg( 'show-reset-form', 'true', wc_lostpassword_url() ) );
51
			exit;
52
		}
53
	}
54
55
	/**
56
	 * Save and and update a billing or shipping address if the
57
	 * form was submitted through the user account page.
58
	 */
59
	public static function save_address() {
60
		global $wp;
61
62
		if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
63
			return;
64
		}
65
66
		if ( empty( $_POST['action'] ) || 'edit_address' !== $_POST['action'] || empty( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'woocommerce-edit_address' ) ) {
67
			return;
68
		}
69
70
		$user_id = get_current_user_id();
71
72
		if ( $user_id <= 0 ) {
73
			return;
74
		}
75
76
		$load_address = isset( $wp->query_vars['edit-address'] ) ? wc_edit_address_i18n( sanitize_title( $wp->query_vars['edit-address'] ), true ) : 'billing';
77
78
		$address = WC()->countries->get_address_fields( esc_attr( $_POST[ $load_address . '_country' ] ), $load_address . '_' );
79
80
		foreach ( $address as $key => $field ) {
81
82
			if ( ! isset( $field['type'] ) ) {
83
				$field['type'] = 'text';
84
			}
85
86
			// Get Value.
87
			switch ( $field['type'] ) {
88
				case 'checkbox' :
89
					$_POST[ $key ] = isset( $_POST[ $key ] ) ? 1 : 0;
90
				break;
91
				default :
92
					$_POST[ $key ] = isset( $_POST[ $key ] ) ? wc_clean( $_POST[ $key ] ) : '';
93
				break;
94
			}
95
96
			// Hook to allow modification of value.
97
			$_POST[ $key ] = apply_filters( 'woocommerce_process_myaccount_field_' . $key, $_POST[ $key ] );
98
99
			// Validation: Required fields.
100
			if ( ! empty( $field['required'] ) && empty( $_POST[ $key ] ) ) {
101
				wc_add_notice( $field['label'] . ' ' . __( 'is a required field.', 'woocommerce' ), 'error' );
102
			}
103
104
			if ( ! empty( $_POST[ $key ] ) ) {
105
106
				// Validation rules
107
				if ( ! empty( $field['validate'] ) && is_array( $field['validate'] ) ) {
108
					foreach ( $field['validate'] as $rule ) {
109
						switch ( $rule ) {
110
							case 'postcode' :
111
								$_POST[ $key ] = strtoupper( str_replace( ' ', '', $_POST[ $key ] ) );
112
113
								if ( ! WC_Validation::is_postcode( $_POST[ $key ], $_POST[ $load_address . '_country' ] ) ) {
114
									wc_add_notice( __( 'Please enter a valid postcode/ZIP.', 'woocommerce' ), 'error' );
115
								} else {
116
									$_POST[ $key ] = wc_format_postcode( $_POST[ $key ], $_POST[ $load_address . '_country' ] );
117
								}
118
							break;
119
							case 'phone' :
120
								$_POST[ $key ] = wc_format_phone_number( $_POST[ $key ] );
121
122
								if ( ! WC_Validation::is_phone( $_POST[ $key ] ) ) {
123
									wc_add_notice( '<strong>' . $field['label'] . '</strong> ' . __( 'is not a valid phone number.', 'woocommerce' ), 'error' );
124
								}
125
							break;
126
							case 'email' :
127
								$_POST[ $key ] = strtolower( $_POST[ $key ] );
128
129
								if ( ! is_email( $_POST[ $key ] ) ) {
130
									wc_add_notice( '<strong>' . $field['label'] . '</strong> ' . __( 'is not a valid email address.', 'woocommerce' ), 'error' );
131
								}
132
							break;
133
						}
134
					}
135
				}
136
			}
137
		}
138
139
		if ( wc_notice_count( 'error' ) == 0 ) {
140
141
			foreach ( $address as $key => $field ) {
142
				update_user_meta( $user_id, $key, $_POST[ $key ] );
143
			}
144
145
			wc_add_notice( __( 'Address changed successfully.', 'woocommerce' ) );
146
147
			do_action( 'woocommerce_customer_save_address', $user_id, $load_address );
148
149
			wp_safe_redirect( wc_get_endpoint_url( 'edit-address', '', wc_get_page_permalink( 'myaccount' ) ) );
150
			exit;
151
		}
152
	}
153
154
	/**
155
	 * Save the password/account details and redirect back to the my account page.
156
	 */
157
	public static function save_account_details() {
158
159
		if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
160
			return;
161
		}
162
163
		if ( empty( $_POST['action'] ) || 'save_account_details' !== $_POST['action'] || empty( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'save_account_details' ) ) {
164
			return;
165
		}
166
167
		$errors       = new WP_Error();
168
		$user         = new stdClass();
169
170
		$user->ID     = (int) get_current_user_id();
171
		$current_user = get_user_by( 'id', $user->ID );
172
173
		if ( $user->ID <= 0 ) {
174
			return;
175
		}
176
177
		$account_first_name = ! empty( $_POST['account_first_name'] ) ? wc_clean( $_POST['account_first_name'] ) : '';
178
		$account_last_name  = ! empty( $_POST['account_last_name'] ) ? wc_clean( $_POST['account_last_name'] ) : '';
179
		$account_email      = ! empty( $_POST['account_email'] ) ? sanitize_email( $_POST['account_email'] ) : '';
180
		$pass_cur           = ! empty( $_POST['password_current'] ) ? $_POST['password_current'] : '';
181
		$pass1              = ! empty( $_POST['password_1'] ) ? $_POST['password_1'] : '';
182
		$pass2              = ! empty( $_POST['password_2'] ) ? $_POST['password_2'] : '';
183
		$save_pass          = true;
184
185
		$user->first_name   = $account_first_name;
186
		$user->last_name    = $account_last_name;
187
188
		// Prevent emails being displayed, or leave alone.
189
		$user->display_name = is_email( $current_user->display_name ) ? $user->first_name : $current_user->display_name;
190
191
		// Handle required fields
192
		$required_fields = apply_filters( 'woocommerce_save_account_details_required_fields', array(
193
			'account_first_name' => __( 'First Name', 'woocommerce' ),
194
			'account_last_name'  => __( 'Last Name', 'woocommerce' ),
195
			'account_email'      => __( 'Email address', 'woocommerce' ),
196
		) );
197
198
		foreach ( $required_fields as $field_key => $field_name ) {
199
			$value = wc_clean( $_POST[ $field_key ] );
200
			if ( empty( $value ) ) {
201
				wc_add_notice( '<strong>' . esc_html( $field_name ) . '</strong> ' . __( 'is a required field.', 'woocommerce' ), 'error' );
202
			}
203
		}
204
205
		if ( $account_email ) {
206
			if ( ! is_email( $account_email ) ) {
207
				wc_add_notice( __( 'Please provide a valid email address.', 'woocommerce' ), 'error' );
208
			} elseif ( email_exists( $account_email ) && $account_email !== $current_user->user_email ) {
209
				wc_add_notice( __( 'This email address is already registered.', 'woocommerce' ), 'error' );
210
			}
211
			$user->user_email = $account_email;
212
		}
213
214
		if ( ! empty( $pass_cur ) && empty( $pass1 ) && empty( $pass2 ) ) {
215
			wc_add_notice( __( 'Please fill out all password fields.', 'woocommerce' ), 'error' );
216
			$save_pass = false;
217
		} elseif ( ! empty( $pass1 ) && empty( $pass_cur ) ) {
218
			wc_add_notice( __( 'Please enter your current password.', 'woocommerce' ), 'error' );
219
			$save_pass = false;
220
		} elseif ( ! empty( $pass1 ) && empty( $pass2 ) ) {
221
			wc_add_notice( __( 'Please re-enter your password.', 'woocommerce' ), 'error' );
222
			$save_pass = false;
223
		} elseif ( ( ! empty( $pass1 ) || ! empty( $pass2 ) ) && $pass1 !== $pass2 ) {
224
			wc_add_notice( __( 'New passwords do not match.', 'woocommerce' ), 'error' );
225
			$save_pass = false;
226
		} elseif ( ! empty( $pass1 ) && ! wp_check_password( $pass_cur, $current_user->user_pass, $current_user->ID ) ) {
227
			wc_add_notice( __( 'Your current password is incorrect.', 'woocommerce' ), 'error' );
228
			$save_pass = false;
229
		}
230
231
		if ( $pass1 && $save_pass ) {
232
			$user->user_pass = $pass1;
233
		}
234
235
		// Allow plugins to return their own errors.
236
		do_action_ref_array( 'woocommerce_save_account_details_errors', array( &$errors, &$user ) );
237
238
		if ( $errors->get_error_messages() ) {
239
			foreach ( $errors->get_error_messages() as $error ) {
240
				wc_add_notice( $error, 'error' );
241
			}
242
		}
243
244
		if ( wc_notice_count( 'error' ) === 0 ) {
245
246
			wp_update_user( $user ) ;
247
248
			wc_add_notice( __( 'Account details changed successfully.', 'woocommerce' ) );
249
250
			do_action( 'woocommerce_save_account_details', $user->ID );
251
252
			wp_safe_redirect( wc_get_page_permalink( 'myaccount' ) );
253
			exit;
254
		}
255
	}
256
257
	/**
258
	 * Process the checkout form.
259
	 */
260
	public static function checkout_action() {
261
		if ( isset( $_POST['woocommerce_checkout_place_order'] ) || isset( $_POST['woocommerce_checkout_update_totals'] ) ) {
262
263
			if ( WC()->cart->is_empty() ) {
264
				wp_redirect( wc_get_page_permalink( 'cart' ) );
265
				exit;
266
			}
267
268
			if ( ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) {
269
				define( 'WOOCOMMERCE_CHECKOUT', true );
270
			}
271
272
			WC()->checkout()->process_checkout();
273
		}
274
	}
275
276
	/**
277
	 * Process the pay form.
278
	 */
279
	public static function pay_action() {
280
		global $wp;
281
282
		if ( isset( $_POST['woocommerce_pay'] ) && isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'woocommerce-pay' ) ) {
283
284
			ob_start();
285
286
			// Pay for existing order
287
			$order_key  = $_GET['key'];
288
			$order_id   = absint( $wp->query_vars['order-pay'] );
289
			$order      = wc_get_order( $order_id );
290
291
			if ( $order->get_id() == $order_id && $order->get_order_key() == $order_key && $order->needs_payment() ) {
292
293
				do_action( 'woocommerce_before_pay_action', $order );
294
295
				WC()->customer->set_props( array(
296
					'billing_country'  => $order->get_billing_country() ? $order->get_billing_country()   : null,
297
					'billing_state'    => $order->get_billing_state() ? $order->get_billing_state()       : null,
298
					'billing_postcode' => $order->get_billing_postcode() ? $order->get_billing_postcode() : null,
299
					'billing_city'     => $order->get_billing_city() ? $order->get_billing_city()         : null,
300
				) );
301
				WC()->customer->save();
302
303
				// Terms
304
				if ( ! empty( $_POST['terms-field'] ) && empty( $_POST['terms'] ) ) {
305
					wc_add_notice( __( 'You must accept our Terms &amp; Conditions.', 'woocommerce' ), 'error' );
306
					return;
307
				}
308
309
				// Update payment method
310
				if ( $order->needs_payment() ) {
311
					$payment_method     = isset( $_POST['payment_method'] ) ? wc_clean( $_POST['payment_method'] ) : false;
312
					$available_gateways = WC()->payment_gateways->get_available_payment_gateways();
313
314
					if ( ! $payment_method ) {
315
						wc_add_notice( __( 'Invalid payment method.', 'woocommerce' ), 'error' );
316
						return;
317
					}
318
319
					// Update meta
320
					update_post_meta( $order_id, '_payment_method', $payment_method );
321
322
					if ( isset( $available_gateways[ $payment_method ] ) ) {
323
						$payment_method_title = $available_gateways[ $payment_method ]->get_title();
324
					} else {
325
						$payment_method_title = '';
326
					}
327
328
					update_post_meta( $order_id, '_payment_method_title', $payment_method_title );
329
330
					// Validate
331
					$available_gateways[ $payment_method ]->validate_fields();
332
333
					// Process
334
					if ( wc_notice_count( 'error' ) == 0 ) {
335
336
						$result = $available_gateways[ $payment_method ]->process_payment( $order_id );
337
338
						// Redirect to success/confirmation/payment page
339
						if ( 'success' === $result['result'] ) {
340
							wp_redirect( $result['redirect'] );
341
							exit;
342
						}
343
					}
344
				} else {
345
					// No payment was required for order
346
					$order->payment_complete();
347
					wp_safe_redirect( $order->get_checkout_order_received_url() );
348
					exit;
349
				}
350
351
				do_action( 'woocommerce_after_pay_action', $order );
352
353
			}
354
		}
355
	}
356
357
	/**
358
	 * Process the add payment method form.
359
	 */
360
	public static function add_payment_method_action() {
361
		if ( isset( $_POST['woocommerce_add_payment_method'], $_POST['payment_method'], $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'woocommerce-add-payment-method' ) ) {
362
363
			ob_start();
364
365
			$payment_method = wc_clean( $_POST['payment_method'] );
366
367
			$available_gateways = WC()->payment_gateways->get_available_payment_gateways();
368
			// Validate
369
			$available_gateways[ $payment_method ]->validate_fields();
370
371
			// Process
372
			if ( wc_notice_count( 'wc_errors' ) == 0 ) {
373
				$result = $available_gateways[ $payment_method ]->add_payment_method();
374
				// Redirect to success/confirmation/payment page
375
				if ( $result['result'] == 'success' ) {
376
					wc_add_notice( __( 'Payment method added.', 'woocommerce' ) );
377
					wp_redirect( $result['redirect'] );
378
					exit();
379
				}
380
			}
381
		}
382
383
	}
384
385
	/**
386
	 * Process the delete payment method form.
387
	 */
388
	public static function delete_payment_method_action() {
389
		global $wp;
390
391
		if ( isset( $wp->query_vars['delete-payment-method'] ) ) {
392
393
			$token_id = absint( $wp->query_vars['delete-payment-method'] );
394
			$token = WC_Payment_Tokens::get( $token_id );
395
			$delete = true;
396
397
			if ( is_null( $token ) ) {
398
				wc_add_notice( __( 'Invalid payment method', 'woocommerce' ), 'error' );
399
				$delete = false;
400
			}
401
402
			if ( get_current_user_id() !== $token->get_user_id() ) {
403
				wc_add_notice( __( 'Invalid payment method', 'woocommerce' ), 'error' );
404
				$delete = false;
405
			}
406
407
			if ( false === wp_verify_nonce( $_REQUEST['_wpnonce'], 'delete-payment-method-' . $token_id ) ) {
408
				wc_add_notice( __( 'Invalid payment method', 'woocommerce' ), 'error' );
409
				$delete = false;
410
			}
411
412
			if ( $delete ) {
413
				WC_Payment_Tokens::delete( $token_id );
414
				wc_add_notice( __( 'Payment method deleted.', 'woocommerce' ) );
415
			}
416
417
			wp_redirect( wc_get_account_endpoint_url( 'payment-methods' ) );
418
			exit();
419
		}
420
421
	}
422
423
	/**
424
	 * Process the delete payment method form.
425
	 */
426
	public static function set_default_payment_method_action() {
427
		global $wp;
428
429
		if ( isset( $wp->query_vars['set-default-payment-method'] ) ) {
430
431
			$token_id = absint( $wp->query_vars['set-default-payment-method'] );
432
			$token = WC_Payment_Tokens::get( $token_id );
433
			$delete = true;
434
435
			if ( is_null( $token ) ) {
436
				wc_add_notice( __( 'Invalid payment method', 'woocommerce' ), 'error' );
437
				$delete = false;
438
			}
439
440
			if ( get_current_user_id() !== $token->get_user_id() ) {
441
				wc_add_notice( __( 'Invalid payment method', 'woocommerce' ), 'error' );
442
				$delete = false;
443
			}
444
445
			if ( false === wp_verify_nonce( $_REQUEST['_wpnonce'], 'set-default-payment-method-' . $token_id ) ) {
446
				wc_add_notice( __( 'Invalid payment method', 'woocommerce' ), 'error' );
447
				$delete = false;
448
			}
449
450
			if ( $delete ) {
451
				WC_Payment_Tokens::set_users_default( $token->get_user_id(), intval( $token_id ) );
452
				wc_add_notice( __( 'This payment method was successfully set as your default.', 'woocommerce' ) );
453
			}
454
455
			wp_redirect( wc_get_account_endpoint_url( 'payment-methods' ) );
456
			exit();
457
		}
458
459
	}
460
461
	/**
462
	 * Remove from cart/update.
463
	 */
464
	public static function update_cart_action() {
465
466
		// Add Discount
467
		if ( ! empty( $_POST['apply_coupon'] ) && ! empty( $_POST['coupon_code'] ) ) {
468
			WC()->cart->add_discount( sanitize_text_field( $_POST['coupon_code'] ) );
469
		}
470
471
		// Remove Coupon Codes
472
		elseif ( isset( $_GET['remove_coupon'] ) ) {
473
			WC()->cart->remove_coupon( wc_clean( $_GET['remove_coupon'] ) );
474
		}
475
476
		// Remove from cart
477
		elseif ( ! empty( $_GET['remove_item'] ) && isset( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'woocommerce-cart' ) ) {
478
			$cart_item_key = sanitize_text_field( $_GET['remove_item'] );
479
480
			if ( $cart_item = WC()->cart->get_cart_item( $cart_item_key ) ) {
481
				WC()->cart->remove_cart_item( $cart_item_key );
482
483
				$product = wc_get_product( $cart_item['product_id'] );
484
485
				$item_removed_title = apply_filters( 'woocommerce_cart_item_removed_title', $product ? $product->get_title() : __( 'Item', 'woocommerce' ), $cart_item );
486
487
				// Don't show undo link if removed item is out of stock.
488
				if ( $product->is_in_stock() && $product->has_enough_stock( $cart_item['quantity'] ) ) {
489
					$removed_notice  = sprintf( __( '%s removed.', 'woocommerce' ), $item_removed_title );
490
					$removed_notice .= ' <a href="' . esc_url( WC()->cart->get_undo_url( $cart_item_key ) ) . '">' . __( 'Undo?', 'woocommerce' ) . '</a>';
491
				} else {
492
					$removed_notice = sprintf( __( '%s removed.', 'woocommerce' ), $item_removed_title );
493
				}
494
495
				wc_add_notice( $removed_notice );
496
			}
497
498
			$referer  = wp_get_referer() ? remove_query_arg( array( 'remove_item', 'add-to-cart', 'added-to-cart' ), add_query_arg( 'removed_item', '1', wp_get_referer() ) ) : wc_get_cart_url();
499
			wp_safe_redirect( $referer );
500
			exit;
501
		}
502
503
		// Undo Cart Item
504
		elseif ( ! empty( $_GET['undo_item'] ) && isset( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'woocommerce-cart' ) ) {
505
			$cart_item_key = sanitize_text_field( $_GET['undo_item'] );
506
507
			WC()->cart->restore_cart_item( $cart_item_key );
508
509
			$referer  = wp_get_referer() ? remove_query_arg( array( 'undo_item', '_wpnonce' ), wp_get_referer() ) : wc_get_cart_url();
510
			wp_safe_redirect( $referer );
511
			exit;
512
		}
513
514
		// Update Cart - checks apply_coupon too because they are in the same form
515
		if ( ( ! empty( $_POST['apply_coupon'] ) || ! empty( $_POST['update_cart'] ) || ! empty( $_POST['proceed'] ) ) && isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'woocommerce-cart' ) ) {
516
517
			$cart_updated = false;
518
			$cart_totals  = isset( $_POST['cart'] ) ? $_POST['cart'] : '';
519
520
			if ( ! WC()->cart->is_empty() && is_array( $cart_totals ) ) {
521
				foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
522
523
					$_product = $values['data'];
524
525
					// Skip product if no updated quantity was posted
526
					if ( ! isset( $cart_totals[ $cart_item_key ] ) || ! isset( $cart_totals[ $cart_item_key ]['qty'] ) ) {
527
						continue;
528
					}
529
530
					// Sanitize
531
					$quantity = apply_filters( 'woocommerce_stock_amount_cart_item', wc_stock_amount( preg_replace( "/[^0-9\.]/", '', $cart_totals[ $cart_item_key ]['qty'] ) ), $cart_item_key );
532
533
					if ( '' === $quantity || $quantity == $values['quantity'] )
534
						continue;
535
536
					// Update cart validation
537
					$passed_validation 	= apply_filters( 'woocommerce_update_cart_validation', true, $cart_item_key, $values, $quantity );
538
539
					// is_sold_individually
540
					if ( $_product->is_sold_individually() && $quantity > 1 ) {
541
						wc_add_notice( sprintf( __( 'You can only have 1 %s in your cart.', 'woocommerce' ), $_product->get_title() ), 'error' );
542
						$passed_validation = false;
543
					}
544
545
					if ( $passed_validation ) {
546
						WC()->cart->set_quantity( $cart_item_key, $quantity, false );
547
						$cart_updated = true;
548
					}
549
				}
550
			}
551
552
			// Trigger action - let 3rd parties update the cart if they need to and update the $cart_updated variable
553
			$cart_updated = apply_filters( 'woocommerce_update_cart_action_cart_updated', $cart_updated );
554
555
			if ( $cart_updated ) {
556
				// Recalc our totals
557
				WC()->cart->calculate_totals();
558
			}
559
560
			if ( ! empty( $_POST['proceed'] ) ) {
561
				wp_safe_redirect( wc_get_checkout_url() );
562
				exit;
563
			} elseif ( $cart_updated ) {
564
				wc_add_notice( __( 'Cart updated.', 'woocommerce' ) );
565
				$referer = remove_query_arg( 'remove_coupon', ( wp_get_referer() ? wp_get_referer() : wc_get_cart_url() ) );
566
				wp_safe_redirect( $referer );
567
				exit;
568
			}
569
		}
570
	}
571
572
	/**
573
	 * Place a previous order again.
574
	 */
575
	public static function order_again() {
576
577
		// Nothing to do
578
		if ( ! isset( $_GET['order_again'] ) || ! is_user_logged_in() || ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( $_GET['_wpnonce'], 'woocommerce-order_again' ) ) {
579
			return;
580
		}
581
582
		// Clear current cart
583
		WC()->cart->empty_cart();
584
585
		// Load the previous order - Stop if the order does not exist
586
		$order = wc_get_order( absint( $_GET['order_again'] ) );
587
588
		if ( ! $order->get_id() ) {
589
			return;
590
		}
591
592
		if ( ! $order->has_status( apply_filters( 'woocommerce_valid_order_statuses_for_order_again', array('completed') ) ) {
0 ignored issues
show
Bug introduced by
Avoid IF statements that are always true or false
Loading history...
593
			return;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_RETURN
Loading history...
594
		}
595
596
		// Make sure the user is allowed to order again. By default it check if the
597
		// previous order belonged to the current user.
598
		if ( ! current_user_can( 'order_again', $order->get_id() ) ) {
599
			return;
600
		}
601
602
		// Copy products from the order to the cart
603
		foreach ( $order->get_items() as $item ) {
604
			// Load all product info including variation data
605
			$product_id   = (int) apply_filters( 'woocommerce_add_to_cart_product_id', $item->get_product_id() );
606
			$quantity     = $item->get_quantity();
607
			$variation_id = $item->get_variation_id();
608
			$variations   = array();
609
			$cart_item_data = apply_filters( 'woocommerce_order_again_cart_item_data', array(), $item, $order );
610
611
			foreach ( $item->get_meta_data() as $meta ) {
612
				if ( taxonomy_is_product_attribute( $meta->meta_key ) ) {
613
					$variations[ $meta->meta_key ] = $meta->meta_value;
614
				} elseif ( meta_is_product_attribute( $meta->meta_key, $meta->meta_value, $product_id ) ) {
615
					$variations[ $meta->meta_key ] = $meta->meta_value;
616
				}
617
			}
618
619
			// Add to cart validation
620
			if ( ! apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity, $variation_id, $variations, $cart_item_data ) ) {
621
				continue;
622
			}
623
624
			WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variations, $cart_item_data );
625
		}
626
627
		do_action( 'woocommerce_ordered_again', $order->get_id() );
628
629
		// Redirect to cart
630
		wc_add_notice( __( 'The cart has been filled with the items from your previous order.', 'woocommerce' ) );
631
		wp_safe_redirect( wc_get_cart_url() );
632
		exit;
633
	}
634
635
	/**
636
	 * Cancel a pending order.
637
	 */
638
	public static function cancel_order() {
639
		if ( isset( $_GET['cancel_order'] ) && isset( $_GET['order'] ) && isset( $_GET['order_id'] ) ) {
640
641
			$order_key        = $_GET['order'];
642
			$order_id         = absint( $_GET['order_id'] );
643
			$order            = wc_get_order( $order_id );
644
			$user_can_cancel  = current_user_can( 'cancel_order', $order_id );
645
			$order_can_cancel = $order->has_status( apply_filters( 'woocommerce_valid_order_statuses_for_cancel', array( 'pending', 'failed' ) ) );
646
			$redirect         = $_GET['redirect'];
647
648
			if ( $order->has_status( 'cancelled' ) ) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
649
				// Already cancelled - take no action
650
			} elseif ( $user_can_cancel && $order_can_cancel && $order->get_id() === $order_id && $order->get_order_key() === $order_key ) {
651
652
				// Cancel the order + restore stock
653
				WC()->session->set( 'order_awaiting_payment', false );
654
				$order->update_status( 'cancelled', __( 'Order cancelled by customer.', 'woocommerce' ) );
655
656
				// Message
657
				wc_add_notice( apply_filters( 'woocommerce_order_cancelled_notice', __( 'Your order was cancelled.', 'woocommerce' ) ), apply_filters( 'woocommerce_order_cancelled_notice_type', 'notice' ) );
658
659
				do_action( 'woocommerce_cancelled_order', $order->get_id() );
660
661
			} elseif ( $user_can_cancel && ! $order_can_cancel ) {
662
				wc_add_notice( __( 'Your order can no longer be cancelled. Please contact us if you need assistance.', 'woocommerce' ), 'error' );
663
			} else {
664
				wc_add_notice( __( 'Invalid order.', 'woocommerce' ), 'error' );
665
			}
666
667
			if ( $redirect ) {
668
				wp_safe_redirect( $redirect );
669
				exit;
670
			}
671
		}
672
	}
673
674
	/**
675
	 * Add to cart action.
676
	 *
677
	 * Checks for a valid request, does validation (via hooks) and then redirects if valid.
678
	 *
679
	 * @param bool $url (default: false)
680
	 */
681
	public static function add_to_cart_action( $url = false ) {
682
		if ( empty( $_REQUEST['add-to-cart'] ) || ! is_numeric( $_REQUEST['add-to-cart'] ) ) {
683
			return;
684
		}
685
686
		$product_id          = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $_REQUEST['add-to-cart'] ) );
687
		$was_added_to_cart   = false;
688
		$adding_to_cart      = wc_get_product( $product_id );
689
690
		if ( ! $adding_to_cart ) {
691
			return;
692
		}
693
694
		$add_to_cart_handler = apply_filters( 'woocommerce_add_to_cart_handler', $adding_to_cart->product_type, $adding_to_cart );
695
696
		// Variable product handling
697
		if ( 'variable' === $add_to_cart_handler ) {
698
			$was_added_to_cart = self::add_to_cart_handler_variable( $product_id );
699
700
		// Grouped Products
701
		} elseif ( 'grouped' === $add_to_cart_handler ) {
702
			$was_added_to_cart = self::add_to_cart_handler_grouped( $product_id );
703
704
		// Custom Handler
705
		} elseif ( has_action( 'woocommerce_add_to_cart_handler_' . $add_to_cart_handler ) ) {
706
			do_action( 'woocommerce_add_to_cart_handler_' . $add_to_cart_handler, $url );
707
708
		// Simple Products
709
		} else {
710
			$was_added_to_cart = self::add_to_cart_handler_simple( $product_id );
711
		}
712
713
		// If we added the product to the cart we can now optionally do a redirect.
714
		if ( $was_added_to_cart && wc_notice_count( 'error' ) === 0 ) {
715
			// If has custom URL redirect there
716
			if ( $url = apply_filters( 'woocommerce_add_to_cart_redirect', $url ) ) {
717
				wp_safe_redirect( $url );
718
				exit;
719
			} elseif ( get_option( 'woocommerce_cart_redirect_after_add' ) === 'yes' ) {
720
				wp_safe_redirect( wc_get_cart_url() );
721
				exit;
722
			}
723
		}
724
	}
725
726
	/**
727
	 * Handle adding simple products to the cart.
728
	 * @since 2.4.6 Split from add_to_cart_action
729
	 * @param int $product_id
730
	 * @return bool success or not
731
	 */
732
	private static function add_to_cart_handler_simple( $product_id ) {
733
		$quantity 			= empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( $_REQUEST['quantity'] );
734
		$passed_validation 	= apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity );
735
736
		if ( $passed_validation && WC()->cart->add_to_cart( $product_id, $quantity ) !== false ) {
737
			wc_add_to_cart_message( array( $product_id => $quantity ), true );
738
			return true;
739
		}
740
		return false;
741
	}
742
743
	/**
744
	 * Handle adding grouped products to the cart.
745
	 * @since 2.4.6 Split from add_to_cart_action
746
	 * @param int $product_id
747
	 * @return bool success or not
748
	 */
749
	private static function add_to_cart_handler_grouped( $product_id ) {
750
		$was_added_to_cart = false;
751
		$added_to_cart     = array();
752
753
		if ( ! empty( $_REQUEST['quantity'] ) && is_array( $_REQUEST['quantity'] ) ) {
754
			$quantity_set = false;
755
756
			foreach ( $_REQUEST['quantity'] as $item => $quantity ) {
757
				if ( $quantity <= 0 ) {
758
					continue;
759
				}
760
				$quantity_set = true;
761
762
				// Add to cart validation
763
				$passed_validation 	= apply_filters( 'woocommerce_add_to_cart_validation', true, $item, $quantity );
764
765
				if ( $passed_validation && WC()->cart->add_to_cart( $item, $quantity ) !== false ) {
766
					$was_added_to_cart = true;
767
					$added_to_cart[ $item ] = $quantity;
768
				}
769
			}
770
771
			if ( ! $was_added_to_cart && ! $quantity_set ) {
772
				wc_add_notice( __( 'Please choose the quantity of items you wish to add to your cart&hellip;', 'woocommerce' ), 'error' );
773
			} elseif ( $was_added_to_cart ) {
774
				wc_add_to_cart_message( $added_to_cart );
775
				return true;
776
			}
777
		} elseif ( $product_id ) {
778
			/* Link on product archives */
779
			wc_add_notice( __( 'Please choose a product to add to your cart&hellip;', 'woocommerce' ), 'error' );
780
		}
781
		return false;
782
	}
783
784
	/**
785
	 * Handle adding variable products to the cart.
786
	 * @since 2.4.6 Split from add_to_cart_action
787
	 * @param int $product_id
788
	 * @return bool success or not
789
	 */
790
	private static function add_to_cart_handler_variable( $product_id ) {
791
		$adding_to_cart     = wc_get_product( $product_id );
792
		$variation_id       = empty( $_REQUEST['variation_id'] ) ? '' : absint( $_REQUEST['variation_id'] );
793
		$quantity           = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( $_REQUEST['quantity'] );
794
		$missing_attributes = array();
795
		$variations         = array();
796
		$attributes         = $adding_to_cart->get_attributes();
797
798
		// If no variation ID is set, attempt to get a variation ID from posted attributes.
799
		if ( empty( $variation_id ) ) {
800
			$variation_id = $adding_to_cart->get_matching_variation( wp_unslash( $_POST ) );
801
		}
802
803
		$variation = wc_get_product( $variation_id );
804
805
		// Verify all attributes
806
		foreach ( $attributes as $attribute ) {
807
			if ( ! $attribute['is_variation'] ) {
808
				continue;
809
			}
810
811
			$taxonomy = 'attribute_' . sanitize_title( $attribute['name'] );
812
813
			if ( isset( $_REQUEST[ $taxonomy ] ) ) {
814
815
				// Get value from post data
816
				if ( $attribute['is_taxonomy'] ) {
817
					// Don't use wc_clean as it destroys sanitized characters
818
					$value = sanitize_title( stripslashes( $_REQUEST[ $taxonomy ] ) );
819
				} else {
820
					$value = wc_clean( stripslashes( $_REQUEST[ $taxonomy ] ) );
821
				}
822
823
				// Get valid value from variation
824
				$valid_value = isset( $variation->variation_data[ $taxonomy ] ) ? $variation->variation_data[ $taxonomy ] : '';
825
826
				// Allow if valid
827
				if ( '' === $valid_value || $valid_value === $value ) {
828
					$variations[ $taxonomy ] = $value;
829
					continue;
830
				}
831
			} else {
832
				$missing_attributes[] = wc_attribute_label( $attribute['name'] );
833
			}
834
		}
835
836
		if ( ! empty( $missing_attributes ) ) {
837
			wc_add_notice( sprintf( _n( '%s is a required field', '%s are required fields', sizeof( $missing_attributes ), 'woocommerce' ), wc_format_list_of_items( $missing_attributes ) ), 'error' );
838
		} elseif ( empty( $variation_id ) ) {
839
			wc_add_notice( __( 'Please choose product options&hellip;', 'woocommerce' ), 'error' );
840
		} else {
841
			// Add to cart validation
842
			$passed_validation 	= apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity, $variation_id, $variations );
843
844
			if ( $passed_validation && WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variations ) !== false ) {
845
				wc_add_to_cart_message( array( $product_id => $quantity ), true );
846
				return true;
847
			}
848
		}
849
		return false;
850
	}
851
852
	/**
853
	 * Process the login form.
854
	 */
855
	public static function process_login() {
856
		$nonce_value = isset( $_POST['_wpnonce'] ) ? $_POST['_wpnonce'] : '';
857
		$nonce_value = isset( $_POST['woocommerce-login-nonce'] ) ? $_POST['woocommerce-login-nonce'] : $nonce_value;
858
859
		if ( ! empty( $_POST['login'] ) && wp_verify_nonce( $nonce_value, 'woocommerce-login' ) ) {
860
861
			try {
862
				$creds = array(
863
					'user_password' => $_POST['password'],
864
					'remember'      => isset( $_POST['rememberme'] ),
865
				);
866
867
				$username         = trim( $_POST['username'] );
868
				$validation_error = new WP_Error();
869
				$validation_error = apply_filters( 'woocommerce_process_login_errors', $validation_error, $_POST['username'], $_POST['password'] );
870
871
				if ( $validation_error->get_error_code() ) {
872
					throw new Exception( '<strong>' . __( 'Error', 'woocommerce' ) . ':</strong> ' . $validation_error->get_error_message() );
873
				}
874
875
				if ( empty( $username ) ) {
876
					throw new Exception( '<strong>' . __( 'Error', 'woocommerce' ) . ':</strong> ' . __( 'Username is required.', 'woocommerce' ) );
877
				}
878
879
				if ( empty( $_POST['password'] ) ) {
880
					throw new Exception( '<strong>' . __( 'Error', 'woocommerce' ) . ':</strong> ' . __( 'Password is required.', 'woocommerce' ) );
881
				}
882
883
				if ( is_email( $username ) && apply_filters( 'woocommerce_get_username_from_email', true ) ) {
884
					$user = get_user_by( 'email', $username );
885
886
					if ( isset( $user->user_login ) ) {
887
						$creds['user_login'] = $user->user_login;
888
					} else {
889
						throw new Exception( '<strong>' . __( 'Error', 'woocommerce' ) . ':</strong> ' . __( 'A user could not be found with this email address.', 'woocommerce' ) );
890
					}
891
				} else {
892
					$creds['user_login'] = $username;
893
				}
894
895
				// On multisite, ensure user exists on current site, if not add them before allowing login.
896
				if ( is_multisite() ) {
897
					$user_data = get_user_by( 'login', $username );
898
899
					if ( $user_data && ! is_user_member_of_blog( $user_data->ID, get_current_blog_id() ) ) {
900
						add_user_to_blog( get_current_blog_id(), $user_data->ID, 'customer' );
901
					}
902
				}
903
904
				// Perform the login
905
				$user = wp_signon( apply_filters( 'woocommerce_login_credentials', $creds ), is_ssl() );
906
907
				if ( is_wp_error( $user ) ) {
908
					$message = $user->get_error_message();
909
					$message = str_replace( '<strong>' . esc_html( $creds['user_login'] ) . '</strong>', '<strong>' . esc_html( $username ) . '</strong>', $message );
910
					throw new Exception( $message );
911
				} else {
912
913
					if ( ! empty( $_POST['redirect'] ) ) {
914
						$redirect = $_POST['redirect'];
915
					} elseif ( wp_get_referer() ) {
916
						$redirect = wp_get_referer();
917
					} else {
918
						$redirect = wc_get_page_permalink( 'myaccount' );
919
					}
920
921
					wp_redirect( apply_filters( 'woocommerce_login_redirect', $redirect, $user ) );
922
					exit;
923
				}
924
			} catch ( Exception $e ) {
925
				wc_add_notice( apply_filters('login_errors', $e->getMessage() ), 'error' );
926
			}
927
		}
928
	}
929
930
	/**
931
	 * Handle lost password form.
932
	 */
933
	public static function process_lost_password() {
934
		if ( isset( $_POST['wc_reset_password'] ) && isset( $_POST['user_login'] ) && isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'lost_password' ) ) {
935
			$success = WC_Shortcode_My_Account::retrieve_password();
936
937
			// If successful, redirect to my account with query arg set
938
			if ( $success ) {
939
				wp_redirect( add_query_arg( 'reset-link-sent', 'true', remove_query_arg( array( 'key', 'login', 'reset' ) ) ) );
940
				exit;
941
			}
942
		}
943
	}
944
945
	/**
946
	 * Handle reset password form.
947
	 */
948
	public static function process_reset_password() {
949
		$posted_fields = array( 'wc_reset_password', 'password_1', 'password_2', 'reset_key', 'reset_login', '_wpnonce' );
950
951
		foreach ( $posted_fields as $field ) {
952
			if ( ! isset( $_POST[ $field ] ) ) {
953
				return;
954
			}
955
			$posted_fields[ $field ] = $_POST[ $field ];
956
		}
957
958
		if ( ! wp_verify_nonce( $posted_fields['_wpnonce'], 'reset_password' ) ) {
959
			return;
960
		}
961
962
		$user = WC_Shortcode_My_Account::check_password_reset_key( $posted_fields['reset_key'], $posted_fields['reset_login'] );
963
964
		if ( $user instanceof WP_User ) {
965
			if ( empty( $posted_fields['password_1'] ) ) {
966
				wc_add_notice( __( 'Please enter your password.', 'woocommerce' ), 'error' );
967
			}
968
969
			if ( $posted_fields['password_1'] !== $posted_fields['password_2'] ) {
970
				wc_add_notice( __( 'Passwords do not match.', 'woocommerce' ), 'error' );
971
			}
972
973
			$errors = new WP_Error();
974
975
			do_action( 'validate_password_reset', $errors, $user );
976
977
			wc_add_wp_error_notices( $errors );
978
979
			if ( 0 === wc_notice_count( 'error' ) ) {
980
				WC_Shortcode_My_Account::reset_password( $user, $posted_fields['password_1'] );
981
982
				do_action( 'woocommerce_customer_reset_password', $user );
983
984
				wp_redirect( add_query_arg( 'password-reset', 'true', wc_get_page_permalink( 'myaccount' ) ) );
985
				exit;
986
			}
987
		}
988
	}
989
990
	/**
991
	 * Process the registration form.
992
	 */
993
	public static function process_registration() {
994
		$nonce_value = isset( $_POST['_wpnonce'] ) ? $_POST['_wpnonce'] : '';
995
		$nonce_value = isset( $_POST['woocommerce-register-nonce'] ) ? $_POST['woocommerce-register-nonce'] : $nonce_value;
996
997
		if ( ! empty( $_POST['register'] ) && wp_verify_nonce( $nonce_value, 'woocommerce-register' ) ) {
998
			$username = 'no' === get_option( 'woocommerce_registration_generate_username' ) ? $_POST['username'] : '';
999
			$password = 'no' === get_option( 'woocommerce_registration_generate_password' ) ? $_POST['password'] : '';
1000
			$email    = $_POST['email'];
1001
1002
			try {
1003
				$validation_error = new WP_Error();
1004
				$validation_error = apply_filters( 'woocommerce_process_registration_errors', $validation_error, $username, $password, $email );
1005
1006
				if ( $validation_error->get_error_code() ) {
1007
					throw new Exception( $validation_error->get_error_message() );
1008
				}
1009
1010
				// Anti-spam trap
1011
				if ( ! empty( $_POST['email_2'] ) ) {
1012
					throw new Exception( __( 'Anti-spam field was filled in.', 'woocommerce' ) );
1013
				}
1014
1015
				$new_customer = wc_create_new_customer( sanitize_email( $email ), wc_clean( $username ), $password );
1016
1017
				if ( is_wp_error( $new_customer ) ) {
1018
					throw new Exception( $new_customer->get_error_message() );
1019
				}
1020
1021
				if ( apply_filters( 'woocommerce_registration_auth_new_customer', true, $new_customer ) ) {
1022
					wc_set_customer_auth_cookie( $new_customer );
1023
				}
1024
1025
				wp_safe_redirect( apply_filters( 'woocommerce_registration_redirect', wp_get_referer() ? wp_get_referer() : wc_get_page_permalink( 'myaccount' ) ) );
1026
				exit;
1027
1028
			} catch ( Exception $e ) {
1029
				wc_add_notice( '<strong>' . __( 'Error', 'woocommerce' ) . ':</strong> ' . $e->getMessage(), 'error' );
1030
			}
1031
		}
1032
	}
1033
}
1034
1035
WC_Form_Handler::init();
1036