Completed
Pull Request — master (#11613)
by Mike
11:14
created

WC_Customer::save_session_if_changed()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
1
<?php
2
include_once( 'legacy/class-wc-legacy-customer.php' );
3
4
if ( ! defined( 'ABSPATH' ) ) {
5
	exit;
6
}
7
8
/**
9
 * The WooCommerce customer class handles storage of the current customer's data, such as location.
10
 *
11
 * @class    WC_Customer
12
 * @version  2.7.0
13
 * @package  WooCommerce/Classes
14
 * @category Class
15
 * @author   WooThemes
16
 */
17
class WC_Customer extends WC_Legacy_Customer {
18
19
	/**
20
	 * Stores customer data.
21
	 * @var array
22
	 */
23
	protected $_data = array(
24
		'id'				  => 0,
25
		'email'               => '',
26
		'first_name'          => '',
27
		'last_name'           => '',
28
		'role'				  => 'customer',
29
		'last_order_id'       => null, // read only
30
		'last_order_date'     => null, // read only
31
		'orders_count'        => 0, // read only
32
		'total_spent'         => 0, // read only
33
		'username'            => '', // read only on existing users
34
		'password'            => '', // write only
35
		'date_created'        => '', // read only
36
		'date_modified'		  => '', // read only
37
		'billing_postcode'    => '',
38
		'billing_city'        => '',
39
		'billing_address_1'   => '',
40
		'billing_address_2'   => '',
41
		'billing_state'       => '',
42
		'billing_country'     => '',
43
		'shipping_postcode'   => '',
44
		'shipping_city'       => '',
45
		'shipping_address_1'  => '',
46
		'shipping_address_2'  => '',
47
		'shipping_state'      => '',
48
		'shipping_country'    => '',
49
		'is_paying_customer'  => false,
50
		'is_vat_exempt'       => false, // session only.
51
		'calculated_shipping' => false, // session only
52
	);
53
54
	/**
55
	 * Keys which are also stored in a session (so we can make sure they get updated...)
56
	 * @var array
57
	 */
58
	protected $_session_keys = array(
59
		'billing_postcode', 'billing_city', 'billing_address_1', 'billing_address', 'billing_address_2',
60
		'billing_state', 'billing_country', 'shipping_postcode', 'shipping_city', 'shipping_address_1', 'shipping_address',
61
		'shipping_address_2', 'shipping_state', 'shipping_country', 'is_vat_exempt', 'calculated_shipping',
62
	);
63
64
	/**
65
	 * Data stored in meta keys, but not considered "meta"
66
	 * @since 2.7.0
67
	 * @var array
68
	 */
69
	protected $_internal_meta_keys = array(
70
		'billing_postcode', 'billing_city', 'billing_address_1', 'billing_address_2', 'billing_state',
71
		'billing_country', 'shipping_postcode', 'shipping_city', 'shipping_address_1',
72
		'shipping_address_2', 'shipping_state', 'shipping_country', 'paying_customer',
73
		'last_update', 'first_name', 'last_name',
74
	);
75
76
	/**
77
	 *  Internal meta type used to store user data.
78
	 * @var string
79
	 */
80
	protected $_meta_type = 'user';
81
82
	/**
83
	 * Was data changed in the database for this class?
84
	 * @var boolean
85
	 */
86
	protected $_changed = false;
87
88
	/**
89
	 * If some of the customer information is loaded by session (instead of just from the DB).
90
	 * @var boolean
91
	 */
92
	protected $_from_session = false;
93
94
	/**
95
	 * WC_Customer can also return an object for a logged out user (session).
96
	 * $_is_user will be false in this case. It will be true for all other cases
97
	 * (logged in users or getting a WC_Customer for another object)
98
	 * @var boolean
99
	 */
100
	protected $_is_user = false;
101
102
	/**
103
	 * Load customer data based on how WC_Customer is called.
104
	 * @param mixed $customer WC_Customer object or customer ID is accepted.
105
	 * if $customer is 'new', you can build a new WC_Customer object. If it's empty, some
106
	 * data will be pulled from the session for the current user/customer.
107
	 */
108
	public function __construct( $customer = '' ) {
109
		if ( $customer instanceof WC_Customer ) {
110
			$this->_is_user = true;
111
			$this->read( absint( $customer->get_id() ) );
112
		} elseif ( is_numeric( $customer ) ) {
113
			$this->_is_user = true;
114
			$this->read( $customer );
115
		} elseif ( empty( $customer ) ) {
116
			$this->_is_user = true; // unless load_session gets called after.
117
		}
118
119
		if ( $this->_from_session ) {
120
			add_action( 'shutdown', array( $this, 'save_session_if_changed' ), 10 );
121
		}
122
	}
123
124
	/**
125
	 * Saves customer information to the current session if any data changed.
126
	 * @since 2.7.0
127
	 */
128
	public function save_session_if_changed() {
129
		if ( $this->_changed ) {
130
			$this->save_to_session();
131
		}
132
	}
133
134
	/**
135
	 * Loads a WC session into the customer class.
136
	 */
137
	public function load_session() {
138
		$this->_from_session = true;
139
		if ( is_user_logged_in() ) {
140
			$this->_is_user = true;
141
			$this->read( get_current_user_id() );
142
		} else {
143
			$this->_is_user = false;
144
			$this->read( WC()->session->get_customer_id() );
145
		}
146
	}
147
148
	/*
149
	 |--------------------------------------------------------------------------
150
	 | Getters
151
	 |--------------------------------------------------------------------------
152
	 | Methods for getting data from the customer object.
153
	 */
154
155
	/**
156
	 * Return a customer's user ID. If the current customer is logged out, this will be a session key.
157
	 * @since 2.7.0
158
	 * @return mixed
159
	 */
160
	public function get_id() {
161
		return $this->_data['id'];
162
	}
163
164
	/**
165
	 * Return the customer's username.
166
	 * @since 2.7.0
167
	 * @return string
168
	 */
169
	public function get_username() {
170
		return $this->_data['username'];
171
	}
172
173
	/**
174
	 * Return the customer's email.
175
	 * @since 2.7.0
176
	 * @return string
177
	 */
178
	public function get_email() {
179
		return $this->_data['email'];
180
	}
181
182
	/**
183
	 * Return customer's first name.
184
	 * @since 2.7.0
185
	 * @return string
186
	 */
187
	public function get_first_name() {
188
		return $this->_data['first_name'];
189
	}
190
191
	/**
192
	 * Return customer's last name.
193
	 * @since 2.7.0
194
	 * @return string
195
	 */
196
	public function get_last_name() {
197
		return $this->_data['last_name'];
198
	}
199
200
	/**
201
	 * Return customer's user role.
202
	 * @since 2.7.0
203
	 * @return string
204
	 */
205
	public function get_role() {
206
		return $this->_data['role'];
207
	}
208
209
	/**
210
	 * Return customer's last order ID.
211
	 * @since 2.7.0
212
	 * @return integer|null
213
	 */
214
	public function get_last_order_id() {
215
		return ( is_null( $this->_data['last_order_id'] ) ? null : intval( $this->_data['last_order_id'] ) );
216
	}
217
218
	/**
219
	 * Return the date of the customer's last order.
220
	 * @since 2.7.0
221
	 * @return integer|null
222
	 */
223
	public function get_last_order_date() {
224
		return ( is_null( $this->_data['last_order_date'] ) ? null : intval( $this->_data['last_order_date'] ) );
225
	}
226
227
	/**
228
	 * Return the number of orders this customer has.
229
	 * @since 2.7.0
230
	 * @return integer
231
	 */
232
	public function get_orders_count() {
233
		return intval( $this->_data['orders_count'] );
234
	}
235
236
	/**
237
	 * Return how much money this customer has spent.
238
	 * @since 2.7.0
239
	 * @return float
240
	 */
241
	public function get_total_spent() {
242
		return wc_format_decimal( $this->_data['total_spent'] );
243
	}
244
245
	/**
246
	 * Return this customer's avatar.
247
	 * @since 2.7.0
248
	 * @return string
249
	 */
250 View Code Duplication
	public function get_avatar_url() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
251
		$avatar_html = get_avatar( $this->get_email() );
252
253
		// Get the URL of the avatar from the provided HTML
254
		preg_match( '/src=["|\'](.+)[\&|"|\']/U', $avatar_html, $matches );
255
256
		if ( isset( $matches[1] ) && ! empty( $matches[1] ) ) {
257
			return esc_url( $matches[1] );
258
		}
259
260
		return '';
261
	}
262
263
	/**
264
	 * Return the date this customer was created.
265
	 * @since 2.7.0
266
	 * @return integer
267
	 */
268
	public function get_date_created() {
269
		return absint( $this->_data['date_created'] );
270
	}
271
272
	/**
273
	 * Return the date this customer was last updated.
274
	 * @since 2.7.0
275
	 * @return integer
276
	 */
277
	public function get_date_modified() {
278
		return absint( $this->_data['date_modified'] );
279
	}
280
281
	/**
282
	 * Gets customer postcode.
283
	 * @return string
284
	 */
285
	public function get_billing_postcode() {
286
		return wc_format_postcode( $this->_data['billing_postcode'], $this->get_billing_country() );
287
	}
288
289
	/**
290
	 * Get customer city.
291
	 * @return string
292
	 */
293
	public function get_billing_city() {
294
		return $this->_data['billing_city'];
295
	}
296
297
	/**
298
	 * Get customer address.
299
	 * @return string
300
	 */
301
	public function get_billing_address() {
302
		return $this->_data['billing_address_1'];
303
	}
304
305
	/**
306
	 * Get customer address.
307
	 * @return string
308
	 */
309
	public function get_billing_address_1() {
310
		return $this->get_billing_address();
311
	}
312
313
	/**
314
	 * Get customer's second address.
315
	 * @return string
316
	 */
317
	public function get_billing_address_2() {
318
		return $this->_data['billing_address_2'];
319
	}
320
321
	/**
322
	 * Get customer state.
323
	 * @return string
324
	 */
325
	public function get_billing_state() {
326
		return $this->_data['billing_state'];
327
	}
328
329
	/**
330
	 * Get customer country.
331
	 * @return string
332
	 */
333
	public function get_billing_country() {
334
		return $this->_data['billing_country'];
335
	}
336
337
	/**
338
	 * Get customer's shipping state.
339
	 * @return string
340
	 */
341
	public function get_shipping_state() {
342
		return $this->_data['shipping_state'];
343
	}
344
345
	/**
346
	 * Get customer's shipping country.
347
	 * @return string
348
	 */
349
	public function get_shipping_country() {
350
		return $this->_data['shipping_country'];
351
	}
352
353
	/**
354
	 * Get customer's shipping postcode.
355
	 * @return string
356
	 */
357
	public function get_shipping_postcode() {
358
		return wc_format_postcode( $this->_data['shipping_postcode'], $this->get_shipping_country() );
359
	}
360
361
	/**
362
	 * Get customer's shipping city.
363
	 * @return string
364
	 */
365
	public function get_shipping_city() {
366
		return $this->_data['shipping_city'];
367
	}
368
369
	/**
370
	 * Get customer's shipping address.
371
	 * @return string
372
	 */
373
	public function get_shipping_address() {
374
		return $this->_data['shipping_address_1'];
375
	}
376
377
	/**
378
	 * Get customer address.
379
	 * @return string
380
	 */
381
	public function get_shipping_address_1() {
382
		return $this->get_shipping_address();
383
	}
384
385
	/**
386
	 * Get customer's second shipping address.
387
	 * @return string
388
	 */
389
	public function get_shipping_address_2() {
390
		return $this->_data['shipping_address_2'];
391
	}
392
393
	/**
394
	 * Get if customer is VAT exempt?
395
	 * @since 2.7.0
396
	 * @return bool
397
	 */
398
	public function get_is_vat_exempt() {
399
		return ( ! empty( $this->_data['is_vat_exempt'] ) ) ? true : false;
400
	}
401
402
	/**
403
	 * Has customer calculated shipping?
404
	 * @return bool
405
	 */
406
	public function get_calculated_shipping() {
407
		return ! empty( $this->_data['calculated_shipping'] );
408
	}
409
410
	/**
411
	 * Get taxable address.
412
	 * @return array
413
	 */
414
	public function get_taxable_address() {
415
		$tax_based_on = get_option( 'woocommerce_tax_based_on' );
416
417
		// Check shipping method at this point to see if we need special handling
418
		if ( true === apply_filters( 'woocommerce_apply_base_tax_for_local_pickup', true ) && sizeof( array_intersect( wc_get_chosen_shipping_method_ids(), apply_filters( 'woocommerce_local_pickup_methods', array( 'legacy_local_pickup', 'local_pickup' ) ) ) ) > 0 ) {
419
			$tax_based_on = 'base';
420
		}
421
422
		if ( 'base' === $tax_based_on ) {
423
			$country  = WC()->countries->get_base_country();
424
			$state    = WC()->countries->get_base_state();
425
			$postcode = WC()->countries->get_base_postcode();
426
			$city     = WC()->countries->get_base_city();
427
		} elseif ( 'billing' === $tax_based_on ) {
428
			$country  = $this->get_billing_country();
429
			$state    = $this->get_billing_state();
430
			$postcode = $this->get_billing_postcode();
431
			$city     = $this->get_billing_city();
432
		} else {
433
			$country  = $this->get_shipping_country();
434
			$state    = $this->get_shipping_state();
435
			$postcode = $this->get_shipping_postcode();
436
			$city     = $this->get_shipping_city();
437
		}
438
439
		return apply_filters( 'woocommerce_customer_taxable_address', array( $country, $state, $postcode, $city ) );
440
	}
441
442
	/**
443
	 * Gets a customer's downloadable products.
444
	 * @return array Array of downloadable products
445
	 */
446
	public function get_downloadable_products() {
447
		$downloads = array();
448
		if ( $this->_is_user ) {
449
			$downloads = wc_get_customer_available_downloads( $this->get_id() );
450
		}
451
		return apply_filters( 'woocommerce_customer_get_downloadable_products', $downloads );
452
	}
453
454
	/**
455
	 * Is the user a paying customer?
456
	 * @since 2.7.0
457
	 * @return bool
458
	 */
459
	function get_is_paying_customer() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
460
		return (bool) $this->_data['is_paying_customer'];
461
	}
462
463
	/*
464
	|--------------------------------------------------------------------------
465
	| Setters
466
	|--------------------------------------------------------------------------
467
	| Functions for setting customer data. These should not update anything in the
468
	| database itself and should only change what is stored in the class
469
	| object.
470
	*/
471
472
	/**
473
	 * Set customer's username.
474
	 * @since 2.7.0
475
	 * @param string $username
476
	 */
477
	public function set_username( $username ) {
478
		$this->_data['username'] = $username;
479
	}
480
481
	/**
482
	 * Set customer's email.
483
	 * @since 2.7.0
484
	 * @param string $email
485
	 */
486
	public function set_email( $email ) {
487
		$this->_data['email'] = sanitize_email( $email );
488
	}
489
490
	/**
491
	 * Set customer's first name.
492
	 * @since 2.7.0
493
	 * @param string $first_name
494
	 */
495
	public function set_first_name( $first_name ) {
496
		$this->_data['first_name'] = $first_name;
497
	}
498
499
	/**
500
	 * Set customer's last name.
501
	 * @since 2.7.0
502
	 * @param string $last_name
503
	 */
504
	public function set_last_name( $last_name ) {
505
		$this->_data['last_name'] = $last_name;
506
	}
507
508
	/**
509
	 * Set customer's user role(s).
510
	 * @since 2.7.0
511
	 * @param mixed $role
512
	 */
513
	public function set_role( $role ) {
514
		$this->_data['role'] = $role;
515
	}
516
517
	/**
518
	 * Set customer's last order ID.
519
	 * @since 2.7.0
520
	 * @param integer|null $last_order_id
521
	 */
522
	public function set_last_order_id( $last_order_id ) {
523
		$this->_data['last_order_id'] = $last_order_id;
524
	}
525
526
	/**
527
	 * Set the date of the customer's last order.
528
	 * @since 2.7.0
529
	 * @param string|null $last_order_date
530
	 */
531
	public function set_last_order_date( $last_order_date ) {
532
		$this->_data['last_order_date'] = $last_order_date;
533
 	}
534
535
	/**
536
	 * Set the number of orders this customer has.
537
	 * @since 2.7.0
538
	 * @param integer $order_count
0 ignored issues
show
Documentation introduced by
There is no parameter named $order_count. Did you maybe mean $orders_count?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
539
	 */
540
	public function set_orders_count( $orders_count ) {
541
		$this->_data['orders_count'] = $orders_count;
542
	}
543
544
	/**
545
	 * Return how much money this customer has spent.
546
	 * @since 2.7.0
547
	 * @param float $total_spent
548
	 */
549
	public function set_total_spent( $total_spent ) {
550
		$this->_data['total_spent'] = $total_spent;
551
	}
552
553
	/**
554
	 * Set customer's password.
555
	 * @since 2.7.0
556
	 * @param string $password
557
	 */
558
	public function set_password( $password ) {
559
		$this->_data['password'] = wc_clean( $password );
560
	}
561
562
	/**
563
	 * Set the date this customer was last updated.
564
	 * @since 2.7.0
565
	 * @param integer $timestamp
566
	 */
567
	public function set_date_modified( $timestamp ) {
568
		$this->_data['date_modified'] = is_numeric( $timestamp ) ? $timestamp : strtotime( $timestamp );
569
	}
570
571
	/**
572
	 * Set the date this customer was last updated.
573
	 * @since 2.7.0
574
	 * @param integer $timestamp
575
	 */
576
	public function set_date_created( $timestamp ) {
577
		$this->_data['date_created'] = is_numeric( $timestamp ) ? $timestamp : strtotime( $timestamp );
578
	}
579
580
	/**
581
	 * Set customer address to match shop base address.
582
	 * @since 2.7.0
583
	 */
584 View Code Duplication
	public function set_billing_address_to_base() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
585
		$base = wc_get_customer_default_location();
586
		$this->_data['billing_country']  = $base['country'];
587
		$this->_data['billing_state']    = $base['state'];
588
		$this->_data['billing_postcode'] = '';
589
		$this->_data['billing_city']     = '';
590
	}
591
592
	/**
593
	 * Set customer shipping address to base address.
594
	 * @since 2.7.0
595
	 */
596 View Code Duplication
	public function set_shipping_address_to_base() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
597
		$base = wc_get_customer_default_location();
598
		$this->_data['shipping_country']  = $base['country'];
599
		$this->_data['shipping_state']    = $base['state'];
600
		$this->_data['shipping_postcode'] = '';
601
		$this->_data['shipping_city']     = '';
602
	}
603
604
	/**
605
	 * Sets all shipping info at once.
606
	 * @param string $country
607
	 * @param string $state
608
	 * @param string $postcode
609
	 * @param string $city
610
	 */
611
	public function set_shipping_location( $country, $state = '', $postcode = '', $city = '' ) {
612
		$this->_data['shipping_country']  = $country;
613
		$this->_data['shipping_state']    = $state;
614
		$this->_data['shipping_postcode'] = $postcode;
615
		$this->_data['shipping_city']     = $city;
616
	}
617
618
	/**
619
	 * Sets all address info at once.
620
	 * @param string $country
621
	 * @param string $state
622
	 * @param string $postcode
623
	 * @param string $city
624
	 */
625
	public function set_billing_location( $country, $state, $postcode = '', $city = '' ) {
626
		$this->_data['billing_country']  = $country;
627
		$this->_data['billing_state']    = $state;
628
		$this->_data['billing_postcode'] = $postcode;
629
		$this->_data['billing_city']     = $city;
630
	}
631
632
	/**
633
	 * Set customer country.
634
	 * @param mixed $country
635
	 */
636
	public function set_billing_country( $country ) {
637
		$this->_data['billing_country'] = $country;
638
	}
639
640
	/**
641
	 * Set customer state.
642
	 * @param mixed $state
643
	 */
644
	public function set_billing_state( $state ) {
645
		$this->_data['billing_state'] = $state;
646
	}
647
648
	/**
649
	 * Sets customer postcode.
650
	 * @param mixed $postcode
651
	 */
652
	public function set_billing_postcode( $postcode ) {
653
		$this->_data['billing_postcode'] = $postcode;
654
	}
655
656
	/**
657
	 * Sets customer city.
658
	 * @param mixed $city
659
	 */
660
	public function set_billing_city( $city ) {
661
		$this->_data['billing_city'] = $city;
662
	}
663
664
	/**
665
	 * Set customer address.
666
	 * @param mixed $address
667
	 */
668
	public function set_billing_address( $address ) {
669
		$this->_data['billing_address_1'] = $address;
670
	}
671
672
	/**
673
	 * Set customer address.
674
	 * @param mixed $address
675
	 */
676
	public function set_billing_address_1( $address ) {
677
		$this->set_billing_address( $address );
678
	}
679
680
	/**
681
	 * Set customer's second address.
682
	 * @param mixed $address
683
	 */
684
	public function set_billing_address_2( $address ) {
685
		$this->_data['billing_address_2'] = $address;
686
	}
687
688
	/**
689
	 * Set shipping country.
690
	 * @param string $country
691
	 */
692
	public function set_shipping_country( $country ) {
693
		$this->_data['shipping_country'] = $country;
694
	}
695
696
	/**
697
	 * Set shipping state.
698
	 * @param string $state
699
	 */
700
	public function set_shipping_state( $state ) {
701
		$this->_data['shipping_state'] = $state;
702
	}
703
704
	/**
705
	 * Set shipping postcode.
706
	 * @param string $postcode
707
	 */
708
	public function set_shipping_postcode( $postcode ) {
709
		$this->_data['shipping_postcode'] = $postcode;
710
	}
711
712
	/**
713
	 * Sets shipping city.
714
	 * @param string $city
715
	 */
716
	public function set_shipping_city( $city ) {
717
		$this->_data['shipping_city'] = $city;
718
	}
719
720
	/**
721
	 * Set shipping address.
722
	 * @param string $address
723
	 */
724
	public function set_shipping_address( $address ) {
725
		$this->_data['shipping_address_1'] = $address;
726
	}
727
728
	/**
729
	 * Set customer shipping address.
730
	 * @param mixed $address
731
	 */
732
	public function set_shipping_address_1( $address ) {
733
		$this->set_shipping_address( $address );
734
	}
735
736
	/**
737
	 * Set second shipping address.
738
	 * @param string $address
739
	 */
740
	public function set_shipping_address_2( $address ) {
741
		$this->_data['shipping_address_2'] = $address;
742
	}
743
744
	/**
745
	 * Set if customer has tax exemption.
746
	 * @param bool $is_vat_exempt
747
	 */
748
	public function set_is_vat_exempt( $is_vat_exempt ) {
749
		$this->_data['is_vat_exempt'] = $is_vat_exempt;
750
	}
751
752
	/**
753
	 * Calculated shipping?
754
	 * @param boolean $calculated
755
	 */
756
	public function set_calculated_shipping( $calculated = true ) {
757
		$this->_data['calculated_shipping'] = $calculated;
758
	}
759
760
	/**
761
	 * Set if the user a paying customer.
762
	 * @since 2.7.0
763
	 * @param boolean $is_paying_customer
764
	 */
765
	function set_is_paying_customer( $is_paying_customer ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
766
		$this->_data['is_paying_customer'] = (bool) $is_paying_customer;
767
	}
768
769
	/*
770
	|--------------------------------------------------------------------------
771
	| Other methods
772
	|--------------------------------------------------------------------------
773
	| Other functions for interacting with customers.
774
	*/
775
776
	/**
777
	 * Is customer outside base country (for tax purposes)?
778
	 * @return bool
779
	 */
780
	public function is_customer_outside_base() {
781
		list( $country, $state ) = $this->get_taxable_address();
782
		if ( $country ) {
783
			$default = wc_get_base_location();
784
			if ( $default['country'] !== $country ) {
785
				return true;
786
			}
787
			if ( $default['state'] && $default['state'] !== $state ) {
788
				return true;
789
			}
790
		}
791
		return false;
792
	}
793
794
	/*
795
	 |--------------------------------------------------------------------------
796
	 | CRUD methods
797
	 |--------------------------------------------------------------------------
798
	 | Methods which create, read, update and delete from the database.
799
	 |
800
	 | A save method is included for convenience (chooses update or create based
801
	 | on if the order exists yet).
802
	 */
803
804
	 /**
805
	  * Create a customer.
806
	  * @since 2.7.0.
807
	  */
808
	public function create() {
809
		$customer_id = wc_create_new_customer( $this->get_email(), $this->get_username(), $this->_data['password'] );
810
		unset( $this->_data['password'] );
811
		if ( $customer_id ) {
812
			$this->_data['id'] = $customer_id;
813
			update_user_meta( $this->get_id(), 'billing_postcode', $this->get_billing_postcode() );
814
			update_user_meta( $this->get_id(), 'billing_city', $this->get_billing_city() );
815
			update_user_meta( $this->get_id(), 'billing_address_1', $this->get_billing_address() );
816
			update_user_meta( $this->get_id(), 'billing_address_2', $this->get_billing_address_2() );
817
			update_user_meta( $this->get_id(), 'billing_state', $this->get_billing_state() );
818
			update_user_meta( $this->get_id(), 'billing_country', $this->get_billing_country() );
819
			update_user_meta( $this->get_id(), 'shipping_postcode', $this->get_shipping_postcode() );
820
			update_user_meta( $this->get_id(), 'shipping_city', $this->get_shipping_city() );
821
			update_user_meta( $this->get_id(), 'shipping_address_1', $this->get_shipping_address() );
822
			update_user_meta( $this->get_id(), 'shipping_address_2', $this->get_shipping_address_2() );
823
			update_user_meta( $this->get_id(), 'shipping_state', $this->get_shipping_state() );
824
			update_user_meta( $this->get_id(), 'shipping_country', $this->get_shipping_country() );
825
			update_user_meta( $this->get_id(), 'paying_customer', $this->get_is_paying_customer() );
826
			$this->set_date_modified( time() );
827
			update_user_meta( $this->get_id(), 'last_update',  $this->get_date_modified() );
828
			update_user_meta( $this->get_id(), 'first_name', $this->get_first_name() );
829
			update_user_meta( $this->get_id(), 'last_name', $this->get_last_name() );
830
			wp_update_user( array( 'ID' => $this->get_id(), 'role' => $this->get_role() ) );
831
			$wp_user = new WP_User( $this->get_id() );
832
			$this->set_date_created( strtotime( $wp_user->user_registered ) );
833
			$this->save_meta_data();
834
		}
835
	}
836
837
	/**
838
	 * Read a customer from the database.
839
	 * @since 2.7.0
840
	 * @param integer $id
841
	 */
842
	public function read( $id ) {
843
		global $wpdb;
844
		$pull_from_db = true;
845
		$data         = array();
846
		if ( $this->_from_session ) {
847
			$data = (array) WC()->session->get( 'customer' );
848
			if ( ! empty( $data ) ) {
849
				$pull_from_db  = false;
850
				foreach ( $this->_session_keys as $session_key ) {
851
					$function_key = $session_key;
852
					if ( 'billing_' === substr( $session_key, 0, 8 ) ) {
853
						$session_key = str_replace( 'billing_', '', $session_key );
854
					}
855
					if ( ! empty( $data[ $session_key ] ) && is_callable( array( $this, "set_{$function_key}" ) ) ) {
856
						$this->{"set_{$function_key}"}( $data[ $session_key ] );
857
					}
858
				}
859
			}
860
		}
861
862
		if ( $this->_is_user ) {
863
864
			// Only continue reading if the customer exists.
865
			$user_object = get_userdata( $id );
866
			if ( empty( $user_object ) || empty ( $user_object->ID ) ) {
867
				$this->_data['id'] = 0;
868
				return;
869
			}
870
871
			foreach ( array_keys( $this->_data ) as $key ) {
872
				if ( 'billing_' === substr( $key, 0, 8 ) ) {
873
					$session_key = str_replace( 'billing_', '', $key );
874
				}
875
				if ( ! $pull_from_db && ! empty( $data[ $session_key ] ) ) {
876
					continue;
877
				}
878
879
				$meta_value = get_user_meta( $id, $key, true );
880
				if ( $meta_value && is_callable( array( $this, "set_{$key}" ) ) ) {
881
					$this->{"set_{$key}"}( $meta_value );
882
				}
883
			}
884
885
			$this->set_is_paying_customer( get_user_meta( $id, 'paying_customer', true ) );
886
			$wp_user = new WP_User( $id );
887
			$this->set_email( $wp_user->user_email );
888
			$this->set_username( $wp_user->user_login );
889
			$this->set_date_created( strtotime( $wp_user->user_registered ) );
890
			$this->set_date_modified( get_user_meta( $id, 'last_update', true ) );
891
			$this->set_role( ( ! empty ( $wp_user->roles[0] ) ? $wp_user->roles[0] : 'customer' ) );
892
893
			// Get info about user's last order
894
			$last_order = $wpdb->get_row( "SELECT id, post_date_gmt
895
				FROM $wpdb->posts AS posts
896
				LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id
897
				WHERE meta.meta_key = '_customer_user'
898
				AND   meta.meta_value = {$id}
899
				AND   posts.post_type = 'shop_order'
900
				AND   posts.post_status IN ( '" . implode( "','", array_keys( wc_get_order_statuses() ) ) . "' )
901
				ORDER BY posts.ID DESC
902
			" );
903
904
			$this->set_last_order_id( is_object( $last_order ) ? $last_order->id : null );
905
			$this->set_last_order_date( is_object( $last_order ) ? strtotime( $last_order->post_date_gmt ) : null );
906
907
			// WC_Customer can't use wc_get_customer_order_count because get_order_types might not be loaded by the time a customer/session is
908
909
			$count = $wpdb->get_var( "SELECT COUNT(*)
910
				FROM $wpdb->posts as posts
911
912
				LEFT JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
913
914
				WHERE   meta.meta_key       = '_customer_user'
915
				AND     posts.post_type = 'shop_order'
916
				AND     posts.post_status   IN ('" . implode( "','", array_keys( wc_get_order_statuses() ) )  . "')
917
				AND     meta_value          = $id
918
			" );
919
920
			$spent = $wpdb->get_var( "SELECT SUM(meta2.meta_value)
921
				FROM $wpdb->posts as posts
922
923
				LEFT JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
924
				LEFT JOIN {$wpdb->postmeta} AS meta2 ON posts.ID = meta2.post_id
925
926
				WHERE   meta.meta_key       = '_customer_user'
927
				AND     meta.meta_value     = $id
928
				AND     posts.post_type     = 'shop_order'
929
				AND     posts.post_status   IN ( 'wc-completed', 'wc-processing' )
930
				AND     meta2.meta_key      = '_order_total'
931
			" );
932
			if ( ! $spent ) {
933
				$spent = 0;
934
			}
935
936
			$this->set_orders_count( $count );
937
			$this->set_total_spent( $spent );
938
939
			$this->read_meta_data();
940
		}
941
942
		$this->_data['id'] = $id;
943
944
		$default = wc_get_customer_default_location();
945
946
		// Set some defaults if some of our values are still not set.
947
		if ( empty( $this->get_billing_country() ) ) {
948
			$this->set_billing_country( $default['country'] );
949
		}
950
951
		if ( empty( $this->get_shipping_country() ) ) {
952
			$this->set_shipping_country( $this->get_billing_country() );
953
		}
954
955
		if ( empty( $this->get_billing_state() ) ) {
956
			$this->set_billing_state( $default['state'] );
957
		}
958
959
		if ( empty( $this->get_shipping_state() ) ) {
960
			$this->set_shipping_state( $this->get_billing_state() );
961
		}
962
963
		unset( $this->_data['password'] ); // password is write only, never ever read it
964
	}
965
966
	/**
967
	 * Update a customer.
968
	 * @since 2.7.0
969
	 */
970
	public function update() {
971
		$customer_ID = $this->get_id();
972
973
		wp_update_user( array( 'ID' => $customer_ID, 'user_email' => $this->get_email() ) );
974
		// Only update password if a new one was set with set_password
975
		if ( isset( $this->_data['password'] ) ) {
976
			wp_update_user( array( 'ID' => $customer_ID, 'user_pass' => $this->_data['password'] ) );
977
			unset( $this->_data['password'] );
978
		}
979
980
		update_user_meta( $this->get_id(), 'billing_postcode', $this->get_billing_postcode() );
981
		update_user_meta( $this->get_id(), 'billing_city', $this->get_billing_city() );
982
		update_user_meta( $this->get_id(), 'billing_address_1', $this->get_billing_address() );
983
		update_user_meta( $this->get_id(), 'billing_address_2', $this->get_billing_address_2() );
984
		update_user_meta( $this->get_id(), 'billing_state', $this->get_billing_state() );
985
		update_user_meta( $this->get_id(), 'billing_country', $this->get_billing_country() );
986
		update_user_meta( $this->get_id(), 'shipping_postcode', $this->get_shipping_postcode() );
987
		update_user_meta( $this->get_id(), 'shipping_city', $this->get_shipping_city() );
988
		update_user_meta( $this->get_id(), 'shipping_address_1', $this->get_shipping_address() );
989
		update_user_meta( $this->get_id(), 'shipping_address_2', $this->get_shipping_address_2() );
990
		update_user_meta( $this->get_id(), 'shipping_state', $this->get_shipping_state() );
991
		update_user_meta( $this->get_id(), 'shipping_country', $this->get_shipping_country() );
992
		update_user_meta( $this->get_id(), 'paying_customer', $this->get_is_paying_customer() );
993
		$this->set_date_modified( time() );
994
		update_user_meta( $this->get_id(), 'last_update',  $this->get_date_modified() );
995
		update_user_meta( $this->get_id(), 'first_name', $this->get_first_name() );
996
		update_user_meta( $this->get_id(), 'last_name', $this->get_last_name() );
997
		wp_update_user( array( 'ID' => $this->get_id(), 'role' => $this->get_role() ) );
998
		$this->save_meta_data();
999
	}
1000
1001
	/**
1002
	 * Delete a customer.
1003
	 * @since 2.7.0
1004
	 */
1005
	public function delete() {
1006
		if ( ! $this->get_id() ) {
1007
			return;
1008
		}
1009
		wp_delete_user( $this->get_id() );
1010
	}
1011
1012
	/**
1013
	 * Save data. Create when creating a new user/class, update when editing
1014
	 * an existing user, and save session when working on a logged out guest
1015
	 * session.
1016
	 * @since 2.7.0
1017
	 */
1018
	public function save() {
1019
		if ( $this->_from_session && ! $this->_is_user ) {
1020
			$this->save_session_if_changed();
1021
			return;
1022
		}
1023
		if ( ! $this->_is_user ) {
1024
			$this->create();
1025
		} else {
1026
			if ( ! $this->get_id() ) {
1027
				$this->create();
1028
			} else {
1029
				$this->update();
1030
			}
1031
		}
1032
	}
1033
1034
	/**
1035
	 * Saves data to the session only (does not overwrite DB values).
1036
	 * @since 2.7.0
1037
	 */
1038
	public function save_to_session() {
1039
		if ( ! $this->_from_session ) {
1040
			return;
1041
		}
1042
		$data = array();
1043
		foreach ( $this->_session_keys as $session_key ) {
1044
			$function_key = $session_key;
1045
			if ( 'billing_' === substr( $session_key, 0, 8 ) ) {
1046
				$session_key = str_replace( 'billing_', '', $session_key );
1047
			}
1048
			$data[ $session_key ] = $this->{"get_$function_key"}();
1049
		}
1050
		WC()->session->set( 'customer', $data );
1051
	}
1052
1053
}
1054