Completed
Push — master ( 859ed4...a97791 )
by Justin
05:09
created

WPSC_Controller_Checkout::get_purchase_log()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 28
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 16
nc 4
nop 0
dl 0
loc 28
rs 8.8571
c 0
b 0
f 0
1
<?php
2
require_once( WPSC_TE_V2_CLASSES_PATH . '/checkout-wizard.php' );
3
4
class WPSC_Controller_Checkout extends WPSC_Controller {
5
	protected $current_step  = '';
6
	protected $wizard;
7
	protected $shipping_calculator;
8
9
	public function __construct() {
10
		parent::__construct();
11
12
		$this->check_cart_items();
13
		$this->title = wpsc_get_checkout_title();
14
		$this->init_checkout_wizard();
15
	}
16
17
	private function check_cart_items() {
18
		global $wpsc_cart;
19
20
		if ( count( $wpsc_cart->cart_items ) > 0 ) {
21
			return;
22
		}
23
24
		wp_redirect( wpsc_get_cart_url() );
25
		exit;
26
	}
27
28
	public function index() {
29
		if ( ! is_user_logged_in() ) {
30
			wpsc_update_customer_meta( 'checkout_after_login', true );
31
			if ( get_option( 'require_register' ) ) {
32
				$this->view = 'checkout-login-required';
33
			} else {
34
				$this->view = 'checkout-login-prompt';
35
			}
36
		} else {
37
			wp_redirect( wpsc_get_checkout_url( 'shipping-and-billing' ) );
38
			exit;
39
		}
40
	}
41
42
	/**
43
	 * Review Order method
44
	 *
45
	 * @return void
46
	 */
47
	public function review_order() {
48
		// Initialize Shipping Calculator
49
		$this->init_shipping_calculator();
50
51
		// View Settings
52
		$this->title .= ' → Review Order';
53
		$this->view = 'checkout-review-order';
54
55
		// If no shipping is available, show an error message.
56
		if ( wpsc_uses_shipping() && ! $this->shipping_calculator->has_quotes ) {
0 ignored issues
show
Bug introduced by
The property has_quotes does not seem to exist. Did you mean quotes?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
57
			$this->message_collection->add(
58
				__( 'Sorry, but we cannot ship products to your submitted address. Please either provide another shipping address or contact the store administrator about product availability to your location.', 'wp-e-commerce' ),
59
				'error'
60
			);
61
			return;
62
		}
63
64
		// Alert the user that the payment process is not complete.
65
		$this->message_collection->add(
66
			__( 'Your payment is not completed, please review your order details, select a Shipping method and press "Place Order" to complete your order', 'wp-e-commerce' ),
67
			'info'
68
		);
69
70
		// Shipping Selector Scripts and Filters
71
		add_action( 'wp_enqueue_scripts',
72
			array( $this, '_action_shipping_method_scripts' )
73
		);
74
		add_filter( 'wpsc_checkout_shipping_method_form_button_title', array( &$this, 'review_order_button_title' ), 1, 100 );
75
76
		// Handle POST request
77
		if ( isset( $_POST['action'] ) && $_POST['action'] == 'submit_shipping_method' ) {
78
			$this->submit_review_order();
79
		}
80
	}
81
82
	/**
83
	 * Modify the Submit Order button title
84
	 *
85
	 * @return string
86
	 */
87
	public function review_order_button_title() {
88
		return __( 'Place Order', 'wp-e-commerce' );
89
	}
90
91
	/**
92
	 * Validates cart submission.
93
	 *
94
	 * @since  4.0
95
	 * @return bool Whether or not there are validation errors.
96
	 */
97
	private function validate_cart() {
98
		$validation = wpsc_validate_form( wpsc_get_checkout_shipping_form_args() );
99
100
		if ( is_wp_error( $validation ) ) {
101
			wpsc_set_validation_errors( $validation );
102
			return false;
103
		}
104
105
		return true;
106
107
	}
108
109
	/**
110
	 * Confirms the existence of the submitted shipping method and option.
111
	 *
112
	 * @param  string $submitted_value POSTed value for shipping method.
113
	 *
114
	 * @return boolean                 Whether or not shipping method was found.
115
	 */
116
	private function check_shipping_method( $submitted_value ) {
117
		global $wpsc_cart;
118
119
		$found = false;
120
121
		foreach ( $this->shipping_calculator->quotes as $module_name => $quotes ) {
122
			foreach ( $quotes as $option => $cost ) {
123
				$id = $this->shipping_calculator->ids[ $module_name ][ $option ];
124
125
				if ( $id == $submitted_value ) {
126
					$found = true;
127
					$wpsc_cart->update_shipping( $module_name, $option );
128
					break 2;
129
				}
130
			}
131
		}
132
133
		// Set the Shipping method
134
		if ( isset( $module_name ) && isset( $option ) ) {
135
			$this->shipping_calculator->set_active_method( $module_name, $option );
136
		}
137
138
		return $found;
139
	}
140
141
	/**
142
	 * Handle the Review Order page POST request.
143
	 *
144
	 * @return null|void
145
	 */
146
	private function submit_review_order() {
147
		global $wpsc_cart;
148
149
		if ( ! $this->verify_nonce( 'wpsc-checkout-form-shipping-method' ) ) {
150
			return null;
151
		}
152
153
		if ( ! $this->validate_cart() ) {
154
			return null;
155
		}
156
157
		// Checks shipping method
158
		if ( ! $this->check_shipping_method( $_POST['wpsc_shipping_option'] ) ) {
159
			return null;
160
		}
161
162
		// Update the Purchase Log
163
		$purchase_log_id = wpsc_get_customer_meta( 'current_purchase_log_id' );
164
		$purchase_log    = new WPSC_Purchase_Log( $purchase_log_id );
165
		$purchase_log->set( 'base_shipping', $wpsc_cart->calculate_base_shipping() );
166
		$purchase_log->set( 'totalprice', $wpsc_cart->calculate_total_price() );
167
		$purchase_log->save();
168
169
		// Build the Redirection URL
170
		$url = add_query_arg( array_merge( $_GET, array( 'payment_gateway_callback' => 'confirm_transaction' ) ), wpsc_get_checkout_url( 'results' ) );
171
172
		// Redirect to Results Page
173
		wp_redirect( $url );
174
		exit;
175
	}
176
177
	public function shipping_and_billing() {
178
		$this->view = 'checkout-shipping-and-billing';
179
		_wpsc_enqueue_shipping_billing_scripts();
180
181
		$this->maybe_add_guest_account();
182
183
		if ( isset( $_POST['action'] ) && $_POST['action'] == 'submit_checkout_form' ) {
184
			$this->submit_shipping_and_billing();
185
		}
186
	}
187
188
	/**
189
	 * Maybe add UI for creating a guest account.
190
	 *
191
	 * By default, it will automatically generate a password and use the billing email as the username.
192
	 * This way, the customer has no other fields to fill out.
193
	 *
194
	 * @since  4.0
195
	 *
196
	 * @return bool Whether or not to add a UI for account creation on checkout.
197
	 */
198
	private function maybe_add_guest_account() {
199
200
		$email = wpsc_get_customer_meta( 'billingemail' );
201
202
		return apply_filters( 'wpsc_checkout_maybe_add_guest_account', ( ! is_user_logged_in() ) && get_option( 'users_can_register' ) && ! empty( $email ) && ! username_exists( $email ) );
203
	}
204
205
	private function submit_shipping_and_billing() {
206
		if ( ! $this->verify_nonce( 'wpsc-checkout-form' ) ) {
207
			return;
208
		}
209
210
		// wipe out completed steps because we're starting from scratch
211
		$this->wizard->reset();
212
213
		$form_args  = wpsc_get_checkout_form_args();
214
		$validation = wpsc_validate_form( $form_args );
215
216
		if ( is_wp_error( $validation ) ) {
217
			$this->message_collection->add(
218
				__( 'Sorry, but it looks like there are some errors with your submitted information.', 'wp-e-commerce' ),
219
				'error'
220
			);
221
			wpsc_set_validation_errors( $validation, 'inline' );
222
			return;
223
		}
224
225
		if ( ! empty( $_POST['wpsc_copy_billing_details'] ) ) {
226
			_wpsc_copy_billing_details();
227
		} else {
228
			wpsc_update_customer_meta( 'wpsc_copy_billing_details', 'false' );
229
		}
230
231
		$this->save_shipping_and_billing_info();
232
	}
233
234
	public function get_purchase_log() {
235
236
		// see if an existing purchase log has been set for this user
237
		// otherwise create one
238
		$purchase_log_id = (int) wpsc_get_customer_meta( 'current_purchase_log_id' );
239
240
		$create = true;
241
242
		if ( $purchase_log_id ) {
243
			$purchase_log = new WPSC_Purchase_Log( $purchase_log_id );
244
			$create       = ! $purchase_log->exists();
245
		}
246
247
		if ( $create ) {
248
			wpsc_delete_customer_meta( 'current_purchase_log_id' );
249
250
			$purchase_log = new WPSC_Purchase_Log();
251
252
			$purchase_log->set( array(
253
				'user_ID'        => get_current_user_id(),
254
				'date'           => time(),
255
				'plugin_version' => WPSC_VERSION,
256
				'statusno'       => '0',
257
			) )->save();
258
		}
259
260
		return $purchase_log;
0 ignored issues
show
Bug introduced by
The variable $purchase_log does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
261
	}
262
263
	public function save_shipping_and_billing_info() {
264
		global $wpsc_cart;
265
266
		$purchase_log = $this->get_purchase_log();
267
268
		$sessionid = ( mt_rand( 100, 999 ) . time() );
269
		wpsc_update_customer_meta( 'checkout_session_id', $sessionid );
270
271
		$purchase_log->set( array(
272
			'sessionid'      => $sessionid,
273
			'discount_value' => $wpsc_cart->coupons_amount,
274
			'discount_data'  => $wpsc_cart->coupons_name,
275
		) );
276
277
		$form   = WPSC_Checkout_Form::get();
278
		$fields = $form->get_fields();
279
280
		foreach ( $fields as $field ) {
281
			if ( ! array_key_exists( $field->id, $_POST['wpsc_checkout_details'] ) ) {
282
				continue;
283
			}
284
285
			$value = $_POST['wpsc_checkout_details'][ $field->id ];
286
287
			switch ( $field->unique_name ) {
288
				case 'billingstate':
289
					wpsc_update_customer_meta( 'billing_region', $value );
290
					$purchase_log->set( 'billing_region', $value );
291
					break;
292
				case 'shippingstate':
293
					wpsc_update_customer_meta( 'shipping_region', $value );
294
					$purchase_log->set( 'shipping_region', $value );
295
					break;
296
				case 'billingcountry':
297
					wpsc_update_customer_meta( 'billing_country', $value );
298
					$purchase_log->set( 'billing_country', $value );
299
					break;
300
				case 'shippingcountry':
301
					wpsc_update_customer_meta( 'shipping_country', $value );
302
					$purchase_log->set( 'shipping_region', $value );
303
					break;
304
				case 'shippingpostcode':
305
					wpsc_update_customer_meta( 'shipping_zip', $value );
306
					break;
307
			}
308
		}
309
310
		_wpsc_update_location();
311
312
		//keep track of tax if taxes are exclusive
313
		$wpec_taxes_controller = new wpec_taxes_controller();
314
		if ( ! $wpec_taxes_controller->wpec_taxes_isincluded() ) {
315
			$tax = $wpsc_cart->calculate_total_tax();
316
			$tax_percentage = $wpsc_cart->tax_percentage;
317
		} else {
318
			$tax = 0.00;
319
			$tax_percentage = 0.00;
320
		}
321
322
		$purchase_log->set( array(
323
			'wpec_taxes_total' => $tax,
324
			'wpec_taxes_rate'  => $tax_percentage,
325
		) );
326
327
		$purchase_log->save();
328
329
		//Check to ensure purchase log row was inserted successfully
330
		if ( is_null( $purchase_log->get( 'id' ) ) ) {
331
			$this->message_collection->add(
332
				__( 'A database error occurred while processing your request.', 'wp-e-commerce' ),
333
				'error'
334
			);
335
			return;
336
		}
337
338
		$wpsc_cart->log_id = $purchase_log->get( 'id' );
339
340
		wpsc_update_customer_meta( 'current_purchase_log_id', $purchase_log->get( 'id' ) );
341
342
		WPSC_Checkout_Form_Data::save_form( $purchase_log, $fields );
343
344
		$this->init_shipping_calculator();
345
346
		if ( wpsc_uses_shipping() && ! $this->shipping_calculator->has_quotes ) {
0 ignored issues
show
Bug introduced by
The property has_quotes does not seem to exist. Did you mean quotes?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
347
			$this->message_collection->add(
348
				__( 'Sorry, but we cannot ship products to your submitted address. Please either provide another shipping address or contact the store administrator about product availability to your location.', 'wp-e-commerce' ),
349
				'error'
350
			);
351
352
			return;
353
		}
354
355
		$this->wizard->completed_step( 'shipping-and-billing' );
356
357
		$url = add_query_arg( $_GET, wpsc_get_checkout_url( $this->wizard->pending_step ) );
358
359
		wp_redirect( $url );
360
		exit;
361
	}
362
363
	public function shipping_method() {
364
		$this->init_shipping_calculator();
365
		$this->view = 'checkout-shipping-method';
366
367
		add_action( 'wp_enqueue_scripts', array( $this, '_action_shipping_method_scripts' ) );
368
369
		if ( isset( $_POST['action'] ) && $_POST['action'] == 'submit_shipping_method' ) {
370
			$this->submit_shipping_method();
371
		}
372
	}
373
374
	private function submit_shipping_method() {
375
		global $wpsc_cart;
376
377
		if ( ! $this->verify_nonce( 'wpsc-checkout-form-shipping-method' ) ) {
378
			return;
379
		}
380
381
		$form_args  = wpsc_get_checkout_shipping_form_args();
382
		$validation = wpsc_validate_form( $form_args );
383
384
		if ( is_wp_error( $validation ) ) {
385
			wpsc_set_validation_errors( $validation );
386
			return;
387
		}
388
389
		$submitted_value = $_POST['wpsc_shipping_option'];
390
		$found           = false;
391
		$module_name     = '';
392
		$option          = '';
393
394
		foreach ( $this->shipping_calculator->quotes as $module_name => $quotes ) {
395
			foreach ( $quotes as $option => $cost ) {
396
				$id = $this->shipping_calculator->ids[ $module_name ][ $option ];
397
398
				if ( $id == $submitted_value ) {
399
					$found = true;
400
					$wpsc_cart->update_shipping( $module_name, $option );
401
					break 2;
402
				}
403
			}
404
		}
405
406
		if ( ! $found ) {
407
			return;
408
		}
409
410
		$this->wizard->completed_step( 'shipping-method' );
411
412
		$this->shipping_calculator->set_active_method( $module_name, $option );
413
414
		$url = add_query_arg( $_GET, wpsc_get_checkout_url( $this->wizard->pending_step ) );
415
		wp_redirect( $url );
416
		exit;
417
	}
418
419
	public function payment() {
420
		$this->view = 'checkout-payment';
421
422
		add_action( 'wp_enqueue_scripts', array( $this, '_action_payment_scripts' ) );
423
424
		if ( $this->maybe_add_guest_account() ) {
425
			add_filter( 'wpsc_get_checkout_payment_method_form_args', 'wpsc_create_account_checkbox' );
426
		}
427
428
		if ( isset( $_POST['action'] ) && $_POST['action'] == 'submit_payment_method' ) {
429
			$this->submit_payment_method();
430
		}
431
	}
432
433
	private function submit_payment_method() {
434
		global $wpsc_cart;
435
436
		if ( ! $this->verify_nonce( 'wpsc-checkout-form-payment-method' ) ) {
437
			return;
438
		}
439
440
		if ( empty( $_POST['wpsc_payment_method'] ) && ! wpsc_is_free_cart() ) {
441
			$this->message_collection->add(
442
				__( 'Please select a payment method', 'wp-e-commerce' ),
443
				'validation'
444
			);
445
		}
446
447
		$valid = apply_filters( '_wpsc_merchant_v2_validate_payment_method', true, $this );
448
449
		if ( ! $valid ) {
450
			return;
451
		}
452
453
		$purchase_log_id   = wpsc_get_customer_meta( 'current_purchase_log_id' );
454
		$purchase_log      = new WPSC_Purchase_Log( $purchase_log_id );
455
		$submitted_gateway = $_POST['wpsc_payment_method'];
456
457
		$purchase_log->set( array(
458
			'gateway'       => $submitted_gateway,
459
			'base_shipping' => $wpsc_cart->calculate_base_shipping(),
460
			'totalprice'    => $wpsc_cart->calculate_total_price(),
461
		) );
462
463
		if ( $this->maybe_add_guest_account() && isset( $_POST['wpsc_create_account'] ) ) {
464
465
			$email   = wpsc_get_customer_meta( 'billingemail' );
466
			$user_id = wpsc_register_customer( $email, $email, false );
467
			$purchase_log->set( 'user_ID', $user_id );
468
469
			wpsc_update_customer_meta( 'checkout_details', wpsc_get_customer_meta( 'checkout_details' ), $user_id );
470
471
			update_user_meta( $user_id, '_wpsc_visitor_id', wpsc_get_current_customer_id() );
0 ignored issues
show
introduced by
update_user_meta() usage is highly discouraged, check VIP documentation on "Working with wp_users"
Loading history...
472
		}
473
474
		$purchase_log->save();
475
476
		$wpsc_cart->empty_db( $purchase_log_id );
477
		$wpsc_cart->save_to_db( $purchase_log_id );
478
		$wpsc_cart->submit_stock_claims( $purchase_log_id );
479
		$wpsc_cart->log_id = $purchase_log_id;
480
481
		$this->wizard->completed_step( 'payment' );
482
483
		do_action( 'wpsc_submit_checkout', array(
484
			'purchase_log_id' => $purchase_log_id,
485
			'our_user_id'     => isset( $user_id ) ? $user_id : get_current_user_id(),
486
		) );
487
488
		do_action( 'wpsc_submit_checkout_gateway', $submitted_gateway, $purchase_log );
489
	}
490
491
	public function results() {
492
		$this->view = 'checkout-results';
493
		$this->wizard->completed_step( 'results' );
494
		require_once( WPSC_TE_V2_HELPERS_PATH . '/checkout-results.php' );
495
496
		add_action( 'shutdown', array( $this, '_action_shutdown' ) );
497
	}
498
499
	private function init_checkout_wizard() {
500
		$this->wizard = WPSC_Checkout_Wizard::get_instance();
501
		$this->wizard->steps = array(
502
			'shipping-and-billing' => __( 'Details', 'wp-e-commerce' ),
503
			'shipping-method'      => __( 'Delivery', 'wp-e-commerce' ),
504
			'payment'              => __( 'Place Order', 'wp-e-commerce' ),
505
			'results'              => __( 'Complete', 'wp-e-commerce' ),
506
		);
507
508
		if ( ! wpsc_uses_shipping() ) {
509
			unset( $this->wizard->steps['shipping-method'] );
510
		}
511
512
		if ( is_user_logged_in() && (
513
		   		! array_key_exists( $this->wizard->active_step, $this->wizard->steps )
514
				|| in_array( $this->wizard->active_step, $this->wizard->disabled )
515
			)
516
		) {
517
			wp_redirect( wpsc_get_checkout_url( $this->wizard->pending_step ) );
518
			exit;
519
		}
520
	}
521
522
	private function init_shipping_calculator() {
523
524
		if ( ! wpsc_uses_shipping() ) {
525
			return;
526
		}
527
528
		$current_log_id = $this->get_purchase_log();
529
530
		require_once( WPSC_TE_V2_CLASSES_PATH . '/shipping-calculator.php' );
531
		$this->shipping_calculator = new WPSC_Shipping_Calculator( $current_log_id );
532
	}
533
534
	private function get_shipping_method_js_vars() {
535
		global $wpsc_cart;
536
		$js_var = array(
537
			'subtotal' => (float) $wpsc_cart->calculate_subtotal(),
538
			'shipping' => array(),
539
			'tax' =>
540
				  ( wpsc_is_tax_enabled() && ! wpsc_is_tax_included() )
541
				? (float) wpsc_cart_tax( false )
542
				: 0,
543
			'discount' => wpsc_coupon_amount( false ) > 0 ? wpsc_coupon_amount( false ) : 0
544
		);
545
546
		foreach ( $this->shipping_calculator->sorted_quotes as $module_name => $quotes ) {
547
			foreach ( $quotes as $option => $cost ) {
548
				$id = $this->shipping_calculator->ids[ $module_name ][ $option ];
549
				$js_var['shipping'][ $id ] = $cost;
550
			}
551
		}
552
553
		$currency          = new WPSC_Country( get_option( 'currency_type' ) );
554
		$currency_code     = $currency->get_currency_code();
555
		$isocode           = $currency->get_isocode();
556
		$without_fractions = in_array( $currency_code, WPSC_Payment_Gateways::currencies_without_fractions() );
557
558
		$decimals = $without_fractions ? 0 : 2;
559
		$decimals            = apply_filters( 'wpsc_modify_decimals'                 , $decimals, $isocode );
560
		$decimal_separator   = apply_filters( 'wpsc_format_currency_decimal_separator'  , wpsc_get_option( 'decimal_separator' ), $isocode );
561
		$thousands_separator = apply_filters( 'wpsc_format_currency_thousands_separator', wpsc_get_option( 'thousands_separator' ), $isocode );
562
		$symbol = apply_filters( 'wpsc_format_currency_currency_symbol', $currency->get_currency_symbol() );
563
		$sign_location = get_option( 'currency_sign_location' );
564
565
		$js_var['formatter'] = array(
566
			'currency_code'       => $currency_code,
567
			'without_fractions'   => $without_fractions,
568
			'decimals'            => $decimals,
569
			'decimal_separator'   => $decimal_separator,
570
			'thousands_separator' => $thousands_separator,
571
			'symbol'              => $symbol,
572
			'sign_location'       => $sign_location,
573
		);
574
575
		return $js_var;
576
	}
577
578
	public function _action_shipping_method_scripts() {
579
		wp_enqueue_script( 'wpsc-shipping-price-simulator' );
580
		wp_localize_script(
581
			'wpsc-shipping-price-simulator',
582
			'WPSC_Price_Table',
583
			$this->get_shipping_method_js_vars()
584
		);
585
	}
586
587
	public function _action_payment_scripts() {
588
		wp_enqueue_script( 'wpsc-checkout-payment' );
589
	}
590
591
	public function _action_shutdown() {
592
		$this->wizard->reset();
593
		wpsc_delete_customer_meta( 'current_purchase_log_id' );
594
	}
595
}
596