Completed
Pull Request — master (#859)
by Devin
19:40
created

Give_Customer::decrease_purchase_count()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 23
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 11
c 1
b 0
f 0
nc 5
nop 1
dl 0
loc 23
ccs 10
cts 10
cp 1
crap 5
rs 8.5906
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 24 and the first side effect is on line 14.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * Customer (Donor)
4
 *
5
 * @package     Give
6
 * @subpackage  Classes/Give_Customer
7
 * @copyright   Copyright (c) 2016, WordImpress
8
 * @license     http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
 * @since       1.0
10
 */
11
12
// Exit if accessed directly
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * Give_Customer Class
19
 *
20
 * This class handles customers.
21
 *
22
 * @since 1.0
23
 */
24
class Give_Customer {
25
26
	/**
27
	 * The customer ID
28
	 *
29
	 * @since  1.0
30
	 * @access public
31
	 *
32
	 * @var    int
33
	 */
34
	public $id = 0;
35
36
	/**
37
	 * The customer's purchase count
38
	 *
39
	 * @since  1.0
40
	 * @access public
41
	 *
42
	 * @var    int
43
	 */
44
	public $purchase_count = 0;
45
46
	/**
47
	 * The customer's lifetime value
48
	 *
49
	 * @since  1.0
50
	 * @access public
51
	 *
52
	 * @var    int
53
	 */
54
	public $purchase_value = 0;
55
56
	/**
57
	 * The customer's email
58
	 *
59
	 * @since  1.0
60
	 * @access public
61
	 *
62
	 * @var    string
63
	 */
64
	public $email;
65
66
	/**
67
	 * The customer's name
68
	 *
69
	 * @since  1.0
70
	 * @access public
71
	 *
72
	 * @var    string
73
	 */
74
	public $name;
75
76
	/**
77
	 * The customer's creation date
78
	 *
79
	 * @since  1.0
80
	 * @access public
81
	 *
82
	 * @var    string
83
	 */
84
	public $date_created;
85
86
	/**
87
	 * The payment IDs associated with the customer
88
	 *
89
	 * @since  1.0
90
	 * @access public
91
	 *
92
	 * @var    array
93
	 */
94
	public $payment_ids;
95
96
	/**
97
	 * The user ID associated with the customer
98
	 *
99
	 * @since  1.0
100 52
	 * @access public
101
	 *
102 52
	 * @var    int
103
	 */
104 52
	public $user_id;
105
106
	/**
107
	 * Customer Notes
108 52
	 *
109
	 * @since  1.0
110 52
	 * @access public
111 52
	 *
112 52
	 * @var    string
113 52
	 */
114
	public $notes;
115
116 52
	/**
117
	 * The Database Abstraction
118 52
	 *
119 52
	 * @since  1.0
120
	 * @access protected
121
	 *
122 52
	 * @var    Give_DB_Customers
123
	 */
124 52
	protected $db;
125
126
	/**
127
	 * Class Constructor
128
	 *
129
	 * Set up the Give Customer Class.
130
	 *
131
	 * @since  1.0
132
	 * @access public
133
	 *
134
	 * @param  bool $_id_or_email 
135 52
	 * @param  bool $by_user_id
136
	 */
137 52
	public function __construct( $_id_or_email = false, $by_user_id = false ) {
138
139
		$this->db = new Give_DB_Customers;
140
141 52
		if ( false === $_id_or_email || ( is_numeric( $_id_or_email ) && (int) $_id_or_email !== absint( $_id_or_email ) ) ) {
142
			return false;
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
143
		}
144
145 52
		$by_user_id = is_bool( $by_user_id ) ? $by_user_id : false;
146 52
147 52
		if ( is_numeric( $_id_or_email ) ) {
148
			$field = $by_user_id ? 'user_id' : 'id';
149 52
		} else {
150 52
			$field = 'email';
151 52
		}
152
153 52
		$customer = $this->db->get_customer_by( $field, $_id_or_email );
154
155 52
		if ( empty( $customer ) || ! is_object( $customer ) ) {
156
			return false;
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
157
		}
158 52
159 52
		$this->setup_customer( $customer );
160
161
	}
162
163
	/**
164
	 * Setup Customer
165
	 *
166
	 * Given the customer data, let's set the variables.
167
	 *
168
	 * @since  1.0
169
	 * @access private
170
	 *
171 1
	 * @param  object $customer The Customer Object.
172
	 *
173 1
	 * @return bool             If the setup was successful or not.
174
	 */
175
	private function setup_customer( $customer ) {
176
177
		if ( ! is_object( $customer ) ) {
178
			return false;
179
		}
180 1
181
		foreach ( $customer as $key => $value ) {
182
183
			switch ( $key ) {
184
185
				case 'notes':
186
					$this->$key = $this->get_notes();
187
					break;
188
189
				default:
190
					$this->$key = $value;
191
					break;
192
193
			}
194
195 53
		}
196
197 53
		// Customer ID and email are the only things that are necessary, make sure they exist
198
		if ( ! empty( $this->id ) && ! empty( $this->email ) ) {
199
			return true;
200
		}
201
202
		return false;
203 53
204
	}
205 53
206 53
	/**
207
	 * Magic __get function to dispatch a call to retrieve a private property.
208 53
	 *
209 1
	 * @since  1.0
210
	 * @access public
211
	 */
212 53
	public function __get( $key ) {
213
214
		if ( method_exists( $this, 'get_' . $key ) ) {
215
216 53
			return call_user_func( array( $this, 'get_' . $key ) );
217
218 53
		} else {
219
220
			/* translators: %s: property key */
221 53
			return new WP_Error( 'give-customer-invalid-property', sprintf( esc_html__( 'Can\'t get property %s.', 'give' ), $key ) );
222
223
		}
224 53
225
	}
226
227 53
	/**
228
	 * Creates a customer
229 53
	 *
230 53
	 * @since  1.0
231
	 * @access public
232 53
	 *
233
	 * @param  array $data Array of attributes for a customer.
234 53
	 *
235
	 * @return mixed       False if not a valid creation, Customer ID if user is found or valid creation.
236
	 */
237
	public function create( $data = array() ) {
238
239
		if ( $this->id != 0 || empty( $data ) ) {
240
			return false;
241
		}
242
243
		$defaults = array(
244
			'payment_ids' => ''
245
		);
246
247 53
		$args = wp_parse_args( $data, $defaults );
248
		$args = $this->sanitize_columns( $args );
249 53
250 1
		if ( empty( $args['email'] ) || ! is_email( $args['email'] ) ) {
251
			return false;
252
		}
253 53
254
		if ( ! empty( $args['payment_ids'] ) && is_array( $args['payment_ids'] ) ) {
255 53
			$args['payment_ids'] = implode( ',', array_unique( array_values( $args['payment_ids'] ) ) );
256
		}
257 53
258
		do_action( 'give_customer_pre_create', $args );
259 53
260
		$created = false;
261 53
262 53
		// The DB class 'add' implies an update if the customer being asked to be created already exists
263
		if ( $this->db->add( $data ) ) {
264 53
265 53
			// We've successfully added/updated the customer, reset the class vars with the new data
266
			$customer = $this->db->get_customer_by( 'email', $args['email'] );
267 53
268
			// Setup the customer data with the values from DB
269 53
			$this->setup_customer( $customer );
270
271
			$created = $this->id;
272
		}
273
274
		do_action( 'give_customer_post_create', $created, $args );
275
276
		return $created;
277
278
	}
279
280
	/**
281
	 * Update a customer record
282
	 *
283 52
	 * @since  1.0
284
	 * @access public
285 52
	 *
286 1
	 * @param  array $data Array of data attributes for a customer (checked via whitelist).
287
	 *
288
	 * @return bool        If the update was successful or not.
289 52
	 */
290
	public function update( $data = array() ) {
291 52
292
		if ( empty( $data ) ) {
293 52
			return false;
294
		}
295 7
296
		$data = $this->sanitize_columns( $data );
297 7
298 1
		do_action( 'give_customer_pre_update', $this->id, $data );
299 1
300
		$updated = false;
301 7
302
		if ( $this->db->update( $this->id, $data ) ) {
303 7
304
			$customer = $this->db->get_customer_by( 'id', $this->id );
305
			$this->setup_customer( $customer );
306
307 52
			$updated = true;
308
		}
309 52
310
		do_action( 'give_customer_post_update', $updated, $this->id, $data );
311 52
312
		return $updated;
313 52
	}
314
315
	/**
316 52
	 * Attach Payment
317 1
	 *
318
	 * Attach payment to the customer then triggers increasing stats.
319 1
	 *
320
	 * @since  1.0
321
	 * @access public
322
	 *
323 1
	 * @param  int  $payment_id   The payment ID to attach to the customer.
324 1
	 * @param  bool $update_stats For backwards compatibility, if we should increase the stats or not.
325
	 *
326 52
	 * @return bool            If the attachment was successfuly.
327
	 */
328 52
	public function attach_payment( $payment_id = 0, $update_stats = true ) {
329
330 52
		if ( empty( $payment_id ) ) {
331
			return false;
332
		}
333
334
		if ( empty( $this->payment_ids ) ) {
335
336
			$new_payment_ids = $payment_id;
337
338
		} else {
339
340
			$payment_ids = array_map( 'absint', explode( ',', $this->payment_ids ) );
341
342
			if ( in_array( $payment_id, $payment_ids ) ) {
343
				$update_stats = false;
344 3
			}
345
346 3
			$payment_ids[] = $payment_id;
347
348
			$new_payment_ids = implode( ',', array_unique( array_values( $payment_ids ) ) );
349
350 3
		}
351
352 3
		do_action( 'give_customer_pre_attach_payment', $payment_id, $this->id );
353 3
354 3
		$payment_added = $this->update( array( 'payment_ids' => $new_payment_ids ) );
355
356 3
		if ( $payment_added ) {
357
358 3
			$this->payment_ids = $new_payment_ids;
359
360 3
			// We added this payment successfully, increment the stats
361
			if ( $update_stats ) {
362 3
				$payment_amount = give_get_payment_amount( $payment_id );
363 3
364
				if ( ! empty( $payment_amount ) ) {
365
					$this->increase_value( $payment_amount );
366
				}
367 3
368 3
				$this->increase_purchase_count();
369
			}
370 3
371
		}
372 3
373
		do_action( 'give_customer_post_attach_payment', $payment_added, $payment_id, $this->id );
374 3
375
		return $payment_added;
376 3
	}
377
378 3
	/**
379
	 * Remove Payment
380 3
	 *
381
	 * Remove a payment from this customer, then triggers reducing stats.
382 3
	 *
383
	 * @since  1.0
384
	 * @access public
385
	 *
386
	 * @param  integer $payment_id   The Payment ID to remove.
387
	 * @param  bool    $update_stats For backwards compatibility, if we should increase the stats or not.
388
	 *
389
	 * @return boolean               If the removal was successful.
390
	 */
391
	public function remove_payment( $payment_id = 0, $update_stats = true ) {
392
393 3
		if ( empty( $payment_id ) ) {
394
			return false;
395 3
		}
396
397 3
		$payment = new Give_Payment( $payment_id );
398
399
		if ( 'publish' !== $payment->status && 'revoked' !== $payment->status ) {
0 ignored issues
show
Documentation introduced by
The property $status is declared protected in Give_Payment. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
400
			$update_stats = false;
401
		}
402
403
		$new_payment_ids = '';
404
405
		if ( ! empty( $this->payment_ids ) ) {
406
407
			$payment_ids = array_map( 'absint', explode( ',', $this->payment_ids ) );
408
409
			$pos = array_search( $payment_id, $payment_ids );
410 42
			if ( false === $pos ) {
411
				return false;
412
			}
413 42
414 1
			unset( $payment_ids[ $pos ] );
415
			$payment_ids = array_filter( $payment_ids );
416
417 42
			$new_payment_ids = implode( ',', array_unique( array_values( $payment_ids ) ) );
418
419 42
		}
420
421 42
		do_action( 'give_customer_pre_remove_payment', $payment_id, $this->id );
422 41
423 41
		$payment_removed = $this->update( array( 'payment_ids' => $new_payment_ids ) );
424
425 42
		if ( $payment_removed ) {
426
427 42
			$this->payment_ids = $new_payment_ids;
428
429
			if ( $update_stats ) {
430
				// We removed this payment successfully, decrement the stats
431
				$payment_amount = give_get_payment_amount( $payment_id );
432
433
				if ( ! empty( $payment_amount ) ) {
434
					$this->decrease_value( $payment_amount );
435
				}
436
437
				$this->decrease_purchase_count();
438
			}
439 6
440
		}
441
442 6
		do_action( 'give_customer_post_remove_payment', $payment_removed, $payment_id, $this->id );
443 1
444
		return $payment_removed;
445
446 6
	}
447
448 6
	/**
449 1
	 * Increase the purchase count of a customer.
450 1
	 *
451
	 * @since  1.0
452 6
	 * @access public
453
	 *
454 6
	 * @param  integer $count The number to increment by.
455 6
	 *
456 6
	 * @return int            The purchase count.
457
	 */
458 6
	public function increase_purchase_count( $count = 1 ) {
459
460 6
		// Make sure it's numeric and not negative.
461
		if ( ! is_numeric( $count ) || $count != absint( $count ) ) {
462
			return false;
463
		}
464
465
		$new_total = (int) $this->purchase_count + (int) $count;
466
467
		do_action( 'give_customer_pre_increase_purchase_count', $count, $this->id );
468
469
		if ( $this->update( array( 'purchase_count' => $new_total ) ) ) {
470
			$this->purchase_count = $new_total;
471
		}
472 42
473
		do_action( 'give_customer_post_increase_purchase_count', $this->purchase_count, $count, $this->id );
474 42
475
		return $this->purchase_count;
476 42
	}
477
478 42
	/**
479 41
	 * Decrease the customer purchase count.
480 41
	 *
481
	 * @since  1.0
482 42
	 * @access public
483
	 *
484 42
	 * @param  integer $count The amount to decrease by.
485
	 *
486
	 * @return mixed          If successful, the new count, otherwise false.
487
	 */
488
	public function decrease_purchase_count( $count = 1 ) {
489
490
		// Make sure it's numeric and not negative
491
		if ( ! is_numeric( $count ) || $count != absint( $count ) ) {
492
			return false;
493
		}
494
495
		$new_total = (int) $this->purchase_count - (int) $count;
496 7
497
		if ( $new_total < 0 ) {
498 7
			$new_total = 0;
499
		}
500 7
501 2
		do_action( 'give_customer_pre_decrease_purchase_count', $count, $this->id );
502 2
503
		if ( $this->update( array( 'purchase_count' => $new_total ) ) ) {
504 7
			$this->purchase_count = $new_total;
505
		}
506 7
507 6
		do_action( 'give_customer_post_decrease_purchase_count', $this->purchase_count, $count, $this->id );
508 6
509
		return $this->purchase_count;
510 7
	}
511
512 7
	/**
513
	 * Increase the customer's lifetime value.
514
	 *
515
	 * @since  1.0
516
	 * @access public
517
	 *
518
	 * @param  float $value The value to increase by.
519
	 *
520
	 * @return mixed        If successful, the new value, otherwise false.
521
	 */
522
	public function increase_value( $value = 0.00 ) {
523
524
		$new_value = floatval( $this->purchase_value ) + $value;
525 52
526
		do_action( 'give_customer_pre_increase_value', $value, $this->id );
527 52
528 52
		if ( $this->update( array( 'purchase_value' => $new_value ) ) ) {
529
			$this->purchase_value = $new_value;
530 52
		}
531 52
532
		do_action( 'give_customer_post_increase_value', $this->purchase_value, $value, $this->id );
533 52
534
		return $this->purchase_value;
535 52
	}
536
537
	/**
538
	 * Decrease a customer's lifetime value.
539
	 *
540
	 * @since  1.0
541
	 * @access public
542
	 *
543
	 * @param  float $value The value to decrease by.
544
	 *
545 1
	 * @return mixed        If successful, the new value, otherwise false.
546
	 */
547 1
	public function decrease_value( $value = 0.00 ) {
548 1
549
		$new_value = floatval( $this->purchase_value ) - $value;
550 1
551
		if ( $new_value < 0 ) {
552
			$new_value = 0.00;
553
		}
554
555
		do_action( 'give_customer_pre_decrease_value', $value, $this->id );
556
557
		if ( $this->update( array( 'purchase_value' => $new_value ) ) ) {
558
			$this->purchase_value = $new_value;
559
		}
560
561
		do_action( 'give_customer_post_decrease_value', $this->purchase_value, $value, $this->id );
562
563 1
		return $this->purchase_value;
564
	}
565 1
566 1
	/**
567
	 * Decrease/Increase a customer's lifetime value.
568
     *
569
     * This function will update donation stat on basis of current amount and new amount donation difference.
570 1
     * Difference value can positive or negative. Negative value will decrease user donation stat while positive value increase donation stat.
571
     *
572 1
	 * @since  1.0
573 1
     * @access public
574 1
	 *
575
	 * @param  float $curr_amount Current Donation amount.
576 1
	 * @param  float $new_amount  New (changed) Donation amount.
577 1
	 *
578 1
	 * @return mixed              If successful, the new donation stat value, otherwise false.
579
	 */
580 1
	public function update_donation_value( $curr_amount, $new_amount ) {
581
        /**
582 1
         * Payment total difference value can be:
583
         *  zero   (in case amount not change)
584 1
         *  or -ve (in case amount decrease)
585 1
         *  or +ve (in case amount increase)
586 1
         */
587
        $payment_total_diff = $new_amount - $curr_amount;
588 1
589
        // We do not need to update donation stat if donation did not change.
590
        if( ! $payment_total_diff ) {
591 1
            return false;
592
        }
593
594
595
        if( $payment_total_diff > 0 ) {
596
            $this->increase_value( $payment_total_diff );
597
        }else{
598
            // Pass payment total difference as +ve value to decrease amount from user lifetime stat.
599
            $this->decrease_value( -$payment_total_diff );
600
        }
601 52
602
        return $this->purchase_value;
603 52
	}
604
605 52
	/**
606
	 * Get the parsed notes for a customer as an array.
607
	 *
608
	 * @since  1.0
609
     * @access public
610
	 *
611
	 * @param  integer $length The number of notes to get.
612
	 * @param  integer $paged  What note to start at.
613
	 *
614
	 * @return array           The notes requested.
615
	 */
616
	public function get_notes( $length = 20, $paged = 1 ) {
617
618 52
		$length = is_numeric( $length ) ? $length : 20;
619
		$offset = is_numeric( $paged ) && $paged != 1 ? ( ( absint( $paged ) - 1 ) * $length ) : 0;
620 52
621 52
		$all_notes   = $this->get_raw_notes();
622
		$notes_array = array_reverse( array_filter( explode( "\n\n", $all_notes ) ) );
623 52
624
		$desired_notes = array_slice( $notes_array, $offset, $length );
625
626 52
		return $desired_notes;
627 52
628
	}
629
630
	/**
631
	 * Get the total number of notes we have after parsing.
632 52
	 *
633 52
	 * @since  1.0
634 52
     * @access public
635 52
	 *
636 1
	 * @return int The number of notes for the customer.
637 1
	 */
638 52
	public function get_notes_count() {
639
640 52
		$all_notes   = $this->get_raw_notes();
641
		$notes_array = array_reverse( array_filter( explode( "\n\n", $all_notes ) ) );
642 52
643 52
		return count( $notes_array );
644
645
	}
646 52
647
	/**
648 52
	 * Add a note for the customer.
649
	 *
650 42
	 * @since  1.0
651
     * @access public
652 42
	 *
653
	 * @param  string $note   The note to add. Default is empty.
654 42
	 *
655
	 * @return string|boolean The new note if added successfully, false otherwise.
656
	 */
657 42
	public function add_note( $note = '' ) {
658
659 42
		$note = trim( $note );
660
		if ( empty( $note ) ) {
661
			return false;
662
		}
663
664
		$notes = $this->get_raw_notes();
665
666
		if ( empty( $notes ) ) {
667 52
			$notes = '';
668
		}
669 52
670
		$note_string = date_i18n( 'F j, Y H:i:s', current_time( 'timestamp' ) ) . ' - ' . $note;
671
		$new_note    = apply_filters( 'give_customer_add_note_string', $note_string );
672
		$notes .= "\n\n" . $new_note;
673
674
		do_action( 'give_customer_pre_add_note', $new_note, $this->id );
675
676
		$updated = $this->update( array( 'notes' => $notes ) );
677
678
		if ( $updated ) {
679
			$this->notes = $this->get_notes();
680
		}
681
682
		do_action( 'give_customer_post_add_note', $this->notes, $new_note, $this->id );
683
684
		// Return the formatted note, so we can test, as well as update any displays
685
		return $new_note;
686
687
	}
688
689
	/**
690
	 * Get the notes column for the customer
691
	 *
692
	 * @since  1.0
693
     * @access private
694
	 *
695
	 * @return string The Notes for the customer, non-parsed.
696
	 */
697
	private function get_raw_notes() {
698
699
		$all_notes = $this->db->get_column( 'notes', $this->id );
700
701
		return $all_notes;
702
703
	}
704
705
	/**
706
	 * Retrieve customer meta field for a customer.
707
	 *
708
	 * @since  1.6
709
	 * @access public
710
	 *
711
	 * @param  string $meta_key The meta key to retrieve. Default is empty.
712
	 * @param  bool   $single   Whether to return a single value. Default is true.
713
	 *
714
	 * @return mixed            Will be an array if $single is false. Will be value of meta data field if $single is true.
715
	 */
716
	public function get_meta( $meta_key = '', $single = true ) {
717
		return Give()->customer_meta->get_meta( $this->id, $meta_key, $single );
718
	}
719
720
	/**
721
	 * Add meta data field to a customer.
722
	 *
723
	 * @since  1.6
724
	 * @access public
725
	 *
726
	 * @param  string $meta_key   Metadata name. Default is empty.
727
	 * @param  mixed  $meta_value Metadata value.
728
	 * @param  bool   $unique     Optional. Whether the same key should not be added. Default is false.
729
	 *
730
	 * @return bool               False for failure. True for success.
731
	 */
732
	public function add_meta( $meta_key = '', $meta_value, $unique = false ) {
733
		return Give()->customer_meta->add_meta( $this->id, $meta_key, $meta_value, $unique );
734
	}
735
736
	/**
737
	 * Update customer meta field based on customer ID.
738
	 *
739
	 * @since  1.6
740
	 * @access public
741
	 *
742
	 * @param  string $meta_key   Metadata key. Default is empty.
743
	 * @param  mixed  $meta_value Metadata value.
744
	 * @param  mixed  $prev_value Optional. Previous value to check before removing. Default is empty.
745
	 *
746
	 * @return bool               False on failure, true if success.
747
	 */
748
	public function update_meta( $meta_key = '', $meta_value, $prev_value = '' ) {
749
		return Give()->customer_meta->update_meta( $this->id, $meta_key, $meta_value, $prev_value );
750
	}
751
752
	/**
753
	 * Remove metadata matching criteria from a customer.
754
	 *
755
	 * @since  1.6
756
	 * @access public
757
	 *
758
	 * @param  string $meta_key   Metadata name. Default is empty.
759
	 * @param  mixed  $meta_value Optional. Metadata value. Default is empty.
760
	 *
761
	 * @return bool               False for failure. True for success.
762
	 */
763
	public function delete_meta( $meta_key = '', $meta_value = '' ) {
764
		return Give()->customer_meta->delete_meta( $this->id, $meta_key, $meta_value );
765
	}
766
767
	/**
768
	 * Sanitize the data for update/create
769
	 *
770
	 * @since  1.0
771
     * @access private
772
	 *
773
	 * @param  array $data The data to sanitize.
774
	 *
775
	 * @return array       The sanitized data, based off column defaults.
776
	 */
777
	private function sanitize_columns( $data ) {
778
779
		$columns        = $this->db->get_columns();
780
		$default_values = $this->db->get_column_defaults();
781
782
		foreach ( $columns as $key => $type ) {
783
784
			// Only sanitize data that we were provided
785
			if ( ! array_key_exists( $key, $data ) ) {
786
				continue;
787
			}
788
789
			switch ( $type ) {
790
791
				case '%s':
792
					if ( 'email' == $key ) {
793
						$data[ $key ] = sanitize_email( $data[ $key ] );
794
					} elseif ( 'notes' == $key ) {
795
						$data[ $key ] = strip_tags( $data[ $key ] );
796
					} else {
797
						$data[ $key ] = sanitize_text_field( $data[ $key ] );
798
					}
799
					break;
800
801
				case '%d':
802
					if ( ! is_numeric( $data[ $key ] ) || (int) $data[ $key ] !== absint( $data[ $key ] ) ) {
803
						$data[ $key ] = $default_values[ $key ];
804
					} else {
805
						$data[ $key ] = absint( $data[ $key ] );
806
					}
807
					break;
808
809
				case '%f':
810
					// Convert what was given to a float
811
					$value = floatval( $data[ $key ] );
812
813
					if ( ! is_float( $value ) ) {
814
						$data[ $key ] = $default_values[ $key ];
815
					} else {
816
						$data[ $key ] = $value;
817
					}
818
					break;
819
820
				default:
821
					$data[ $key ] = sanitize_text_field( $data[ $key ] );
822
					break;
823
824
			}
825
826
		}
827
828
		return $data;
829
	}
830
831
}
832