Completed
Pull Request — master (#986)
by Rami
20:36
created

Give_Customer::create()   B

Complexity

Conditions 8
Paths 6

Size

Total Lines 58
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 8

Importance

Changes 0
Metric Value
cc 8
eloc 19
nc 6
nop 1
dl 0
loc 58
ccs 19
cts 19
cp 1
crap 8
rs 7.1977
c 0
b 0
f 0

How to fix   Long Method   

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
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 donation 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 bool|int    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
		/**
259 53
		 * Fires before creating customers.
260
		 *
261 53
		 * @since 1.0
262 53
		 *
263
		 * @param array $args Customer attributes.
264 53
		 */
265 53
		do_action( 'give_customer_pre_create', $args );
266
267 53
		$created = false;
268
269 53
		// The DB class 'add' implies an update if the customer being asked to be created already exists
270
		if ( $this->db->add( $data ) ) {
271
272
			// We've successfully added/updated the customer, reset the class vars with the new data
273
			$customer = $this->db->get_customer_by( 'email', $args['email'] );
274
275
			// Setup the customer data with the values from DB
276
			$this->setup_customer( $customer );
277
278
			$created = $this->id;
279
		}
280
281
		/**
282
		 * Fires after creating customers.
283 52
		 *
284
		 * @since 1.0
285 52
		 *
286 1
		 * @param bool|int $created False if not a valid creation,
287
		 *                          customer ID if user is found or valid creation.
288
		 * @param array    $args    Customer attributes.
289 52
		 */
290
		do_action( 'give_customer_post_create', $created, $args );
291 52
292
		return $created;
293 52
294
	}
295 7
296
	/**
297 7
	 * Update a customer record
298 1
	 *
299 1
	 * @since  1.0
300
	 * @access public
301 7
	 *
302
	 * @param  array $data Array of data attributes for a customer (checked via whitelist).
303 7
	 *
304
	 * @return bool        If the update was successful or not.
305
	 */
306
	public function update( $data = array() ) {
307 52
308
		if ( empty( $data ) ) {
309 52
			return false;
310
		}
311 52
312
		$data = $this->sanitize_columns( $data );
313 52
314
		/**
315
		 * Fires before updating customers.
316 52
		 *
317 1
		 * @since 1.0
318
		 *
319 1
		 * @param int   $customer_id Customer id.
320
		 * @param array $data        Customer attributes.
321
		 */
322
		do_action( 'give_customer_pre_update', $this->id, $data );
323 1
324 1
		$updated = false;
325
326 52
		if ( $this->db->update( $this->id, $data ) ) {
327
328 52
			$customer = $this->db->get_customer_by( 'id', $this->id );
329
			$this->setup_customer( $customer );
330 52
331
			$updated = true;
332
		}
333
334
		/**
335
		 * Fires after updating customers.
336
		 *
337
		 * @since 1.0
338
		 *
339
		 * @param bool  $updated     If the update was successful or not.
340
		 * @param int   $customer_id Customer id.
341
		 * @param array $data        Customer attributes.
342
		 */
343
		do_action( 'give_customer_post_update', $updated, $this->id, $data );
344 3
345
		return $updated;
346 3
	}
347
348
	/**
349
	 * Attach Payment
350 3
	 *
351
	 * Attach payment to the customer then triggers increasing stats.
352 3
	 *
353 3
	 * @since  1.0
354 3
	 * @access public
355
	 *
356 3
	 * @param  int  $payment_id   The payment ID to attach to the customer.
357
	 * @param  bool $update_stats For backwards compatibility, if we should increase the stats or not.
358 3
	 *
359
	 * @return bool            If the attachment was successfuly.
360 3
	 */
361
	public function attach_payment( $payment_id = 0, $update_stats = true ) {
362 3
363 3
		if ( empty( $payment_id ) ) {
364
			return false;
365
		}
366
367 3
		if ( empty( $this->payment_ids ) ) {
368 3
369
			$new_payment_ids = $payment_id;
370 3
371
		} else {
372 3
373
			$payment_ids = array_map( 'absint', explode( ',', $this->payment_ids ) );
374 3
375
			if ( in_array( $payment_id, $payment_ids ) ) {
376 3
				$update_stats = false;
377
			}
378 3
379
			$payment_ids[] = $payment_id;
380 3
381
			$new_payment_ids = implode( ',', array_unique( array_values( $payment_ids ) ) );
382 3
383
		}
384
385
		/**
386
		 * Fires before attaching payments to customers.
387
		 *
388
		 * @since 1.0
389
		 *
390
		 * @param int $payment_id  Payment id.
391
		 * @param int $customer_id Customer id.
392
		 */
393 3
		do_action( 'give_customer_pre_attach_payment', $payment_id, $this->id );
394
395 3
		$payment_added = $this->update( array( 'payment_ids' => $new_payment_ids ) );
396
397 3
		if ( $payment_added ) {
398
399
			$this->payment_ids = $new_payment_ids;
400
401
			// We added this payment successfully, increment the stats
402
			if ( $update_stats ) {
403
				$payment_amount = give_get_payment_amount( $payment_id );
404
405
				if ( ! empty( $payment_amount ) ) {
406
					$this->increase_value( $payment_amount );
407
				}
408
409
				$this->increase_purchase_count();
410 42
			}
411
412
		}
413 42
414 1
		/**
415
		 * Fires after attaching payments to customers.
416
		 *
417 42
		 * @since 1.0
418
		 *
419 42
		 * @param bool $payment_added If the attachment was successfuly.
420
		 * @param int  $payment_id    Payment id.
421 42
		 * @param int  $customer_id   Customer id.
422 41
		 */
423 41
		do_action( 'give_customer_post_attach_payment', $payment_added, $payment_id, $this->id );
424
425 42
		return $payment_added;
426
	}
427 42
428
	/**
429
	 * Remove Payment
430
	 *
431
	 * Remove a payment from this customer, then triggers reducing stats.
432
	 *
433
	 * @since  1.0
434
	 * @access public
435
	 *
436
	 * @param  int  $payment_id   The Payment ID to remove.
437
	 * @param  bool $update_stats For backwards compatibility, if we should increase the stats or not.
438
	 *
439 6
	 * @return boolean               If the removal was successful.
440
	 */
441
	public function remove_payment( $payment_id = 0, $update_stats = true ) {
442 6
443 1
		if ( empty( $payment_id ) ) {
444
			return false;
445
		}
446 6
447
		$payment = new Give_Payment( $payment_id );
448 6
449 1
		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...
450 1
			$update_stats = false;
451
		}
452 6
453
		$new_payment_ids = '';
454 6
455 6
		if ( ! empty( $this->payment_ids ) ) {
456 6
457
			$payment_ids = array_map( 'absint', explode( ',', $this->payment_ids ) );
458 6
459
			$pos = array_search( $payment_id, $payment_ids );
460 6
			if ( false === $pos ) {
461
				return false;
462
			}
463
464
			unset( $payment_ids[ $pos ] );
465
			$payment_ids = array_filter( $payment_ids );
466
467
			$new_payment_ids = implode( ',', array_unique( array_values( $payment_ids ) ) );
468
469
		}
470
471
		/**
472 42
		 * Fires before removing payments from customers.
473
		 *
474 42
		 * @since 1.0
475
		 *
476 42
		 * @param int $payment_id  Payment id.
477
		 * @param int $customer_id Customer id.
478 42
		 */
479 41
		do_action( 'give_customer_pre_remove_payment', $payment_id, $this->id );
480 41
481
		$payment_removed = $this->update( array( 'payment_ids' => $new_payment_ids ) );
482 42
483
		if ( $payment_removed ) {
484 42
485
			$this->payment_ids = $new_payment_ids;
486
487
			if ( $update_stats ) {
488
				// We removed this payment successfully, decrement the stats
489
				$payment_amount = give_get_payment_amount( $payment_id );
490
491
				if ( ! empty( $payment_amount ) ) {
492
					$this->decrease_value( $payment_amount );
493
				}
494
495
				$this->decrease_purchase_count();
496 7
			}
497
498 7
		}
499
500 7
		/**
501 2
		 * Fires after removing payments from customers.
502 2
		 *
503
		 * @since 1.0
504 7
		 *
505
		 * @param bool $payment_removed If the removal was successfuly.
506 7
		 * @param int  $payment_id      Payment id.
507 6
		 * @param int  $customer_id     Customer id.
508 6
		 */
509
		do_action( 'give_customer_post_remove_payment', $payment_removed, $payment_id, $this->id );
510 7
511
		return $payment_removed;
512 7
513
	}
514
515
	/**
516
	 * Increase the donation count of a customer.
517
	 *
518
	 * @since  1.0
519
	 * @access public
520
	 *
521
	 * @param  int $count The number to increase by.
522
	 *
523
	 * @return int        The donation count.
524
	 */
525 52
	public function increase_purchase_count( $count = 1 ) {
526
527 52
		// Make sure it's numeric and not negative.
528 52
		if ( ! is_numeric( $count ) || $count != absint( $count ) ) {
529
			return false;
530 52
		}
531 52
532
		$new_total = (int) $this->purchase_count + (int) $count;
533 52
534
		/**
535 52
		 * Fires before increasing customer donation count.
536
		 *
537
		 * @since 1.0
538
		 *
539
		 * @param int $count       The number to increase by.
540
		 * @param int $customer_id Customer id.
541
		 */
542
		do_action( 'give_customer_pre_increase_purchase_count', $count, $this->id );
543
544
		if ( $this->update( array( 'purchase_count' => $new_total ) ) ) {
545 1
			$this->purchase_count = $new_total;
546
		}
547 1
548 1
		/**
549
		 * Fires after increasing customer donation count.
550 1
		 *
551
		 * @since 1.0
552
		 *
553
		 * @param int $purchase_count Customer donation count.
554
		 * @param int $count          The number increased by.
555
		 * @param int $customer_id    Customer id.
556
		 */
557
		do_action( 'give_customer_post_increase_purchase_count', $this->purchase_count, $count, $this->id );
558
559
		return $this->purchase_count;
560
	}
561
562
	/**
563 1
	 * Decrease the customer donation count.
564
	 *
565 1
	 * @since  1.0
566 1
	 * @access public
567
	 *
568
	 * @param  int $count The amount to decrease by.
569
	 *
570 1
	 * @return mixed      If successful, the new count, otherwise false.
571
	 */
572 1
	public function decrease_purchase_count( $count = 1 ) {
573 1
574 1
		// Make sure it's numeric and not negative
575
		if ( ! is_numeric( $count ) || $count != absint( $count ) ) {
576 1
			return false;
577 1
		}
578 1
579
		$new_total = (int) $this->purchase_count - (int) $count;
580 1
581
		if ( $new_total < 0 ) {
582 1
			$new_total = 0;
583
		}
584 1
585 1
		/**
586 1
		 * Fires before decreasing customer donation count.
587
		 *
588 1
		 * @since 1.0
589
		 *
590
		 * @param int $count       The number to decrease by.
591 1
		 * @param int $customer_id Customer id.
592
		 */
593
		do_action( 'give_customer_pre_decrease_purchase_count', $count, $this->id );
594
595
		if ( $this->update( array( 'purchase_count' => $new_total ) ) ) {
596
			$this->purchase_count = $new_total;
597
		}
598
599
		/**
600
		 * Fires after decreasing customer donation count.
601 52
		 *
602
		 * @since 1.0
603 52
		 *
604
		 * @param int $purchase_count Customer donation count.
605 52
		 * @param int $count          The number decreased by.
606
		 * @param int $customer_id    Customer id.
607
		 */
608
		do_action( 'give_customer_post_decrease_purchase_count', $this->purchase_count, $count, $this->id );
609
610
		return $this->purchase_count;
611
	}
612
613
	/**
614
	 * Increase the customer's lifetime value.
615
	 *
616
	 * @since  1.0
617
	 * @access public
618 52
	 *
619
	 * @param  float $value The value to increase by.
620 52
	 *
621 52
	 * @return mixed        If successful, the new value, otherwise false.
622
	 */
623 52
	public function increase_value( $value = 0.00 ) {
624
625
		$new_value = floatval( $this->purchase_value ) + $value;
626 52
627 52
		/**
628
		 * Fires before increasing customer lifetime value.
629
		 *
630
		 * @since 1.0
631
		 *
632 52
		 * @param float $value       The value to increase by.
633 52
		 * @param int   $customer_id Customer id.
634 52
		 */
635 52
		do_action( 'give_customer_pre_increase_value', $value, $this->id );
636 1
637 1
		if ( $this->update( array( 'purchase_value' => $new_value ) ) ) {
638 52
			$this->purchase_value = $new_value;
639
		}
640 52
641
		/**
642 52
		 * Fires after increasing customer lifetime value.
643 52
		 *
644
		 * @since 1.0
645
		 *
646 52
		 * @param float $purchase_value Customer lifetime value.
647
		 * @param float $value          The value increased by.
648 52
		 * @param int   $customer_id    Customer id.
649
		 */
650 42
		do_action( 'give_customer_post_increase_value', $this->purchase_value, $value, $this->id );
651
652 42
		return $this->purchase_value;
653
	}
654 42
655
	/**
656
	 * Decrease a customer's lifetime value.
657 42
	 *
658
	 * @since  1.0
659 42
	 * @access public
660
	 *
661
	 * @param  float $value The value to decrease by.
662
	 *
663
	 * @return mixed        If successful, the new value, otherwise false.
664
	 */
665
	public function decrease_value( $value = 0.00 ) {
666
667 52
		$new_value = floatval( $this->purchase_value ) - $value;
668
669 52
		if ( $new_value < 0 ) {
670
			$new_value = 0.00;
671
		}
672
673
		/**
674
		 * Fires before decreaseing customer lifetime value.
675
		 *
676
		 * @since 1.0
677
		 *
678
		 * @param float $value       The value to decrease by.
679
		 * @param int   $customer_id Customer id.
680
		 */
681
		do_action( 'give_customer_pre_decrease_value', $value, $this->id );
682
683
		if ( $this->update( array( 'purchase_value' => $new_value ) ) ) {
684
			$this->purchase_value = $new_value;
685
		}
686
687
		/**
688
		 * Fires after decreaseing customer lifetime value.
689
		 *
690
		 * @since 1.0
691
		 *
692
		 * @param float $purchase_value Customer lifetime value.
693
		 * @param float $value          The value decreased by.
694
		 * @param int   $customer_id    Customer id.
695
		 */
696
		do_action( 'give_customer_post_decrease_value', $this->purchase_value, $value, $this->id );
697
698
		return $this->purchase_value;
699
	}
700
701
	/**
702
	 * Decrease/Increase a customer's lifetime value.
703
     *
704
     * This function will update donation stat on basis of current amount and new amount donation difference.
705
     * Difference value can positive or negative. Negative value will decrease user donation stat while positive value increase donation stat.
706
     *
707
	 * @since  1.0
708
     * @access public
709
	 *
710
	 * @param  float $curr_amount Current Donation amount.
711
	 * @param  float $new_amount  New (changed) Donation amount.
712
	 *
713
	 * @return mixed              If successful, the new donation stat value, otherwise false.
714
	 */
715
	public function update_donation_value( $curr_amount, $new_amount ) {
716
        /**
717
         * Payment total difference value can be:
718
         *  zero   (in case amount not change)
719
         *  or -ve (in case amount decrease)
720
         *  or +ve (in case amount increase)
721
         */
722
        $payment_total_diff = $new_amount - $curr_amount;
723
724
        // We do not need to update donation stat if donation did not change.
725
        if( ! $payment_total_diff ) {
726
            return false;
727
        }
728
729
730
        if( $payment_total_diff > 0 ) {
731
            $this->increase_value( $payment_total_diff );
732
        }else{
733
            // Pass payment total difference as +ve value to decrease amount from user lifetime stat.
734
            $this->decrease_value( -$payment_total_diff );
735
        }
736
737
        return $this->purchase_value;
738
	}
739
740
	/**
741
	 * Get the parsed notes for a customer as an array.
742
	 *
743
	 * @since  1.0
744
     * @access public
745
	 *
746
	 * @param  int $length The number of notes to get.
747
	 * @param  int $paged  What note to start at.
748
	 *
749
	 * @return array       The notes requested.
750
	 */
751
	public function get_notes( $length = 20, $paged = 1 ) {
752
753
		$length = is_numeric( $length ) ? $length : 20;
754
		$offset = is_numeric( $paged ) && $paged != 1 ? ( ( absint( $paged ) - 1 ) * $length ) : 0;
755
756
		$all_notes   = $this->get_raw_notes();
757
		$notes_array = array_reverse( array_filter( explode( "\n\n", $all_notes ) ) );
758
759
		$desired_notes = array_slice( $notes_array, $offset, $length );
760
761
		return $desired_notes;
762
763
	}
764
765
	/**
766
	 * Get the total number of notes we have after parsing.
767
	 *
768
	 * @since  1.0
769
     * @access public
770
	 *
771
	 * @return int The number of notes for the customer.
772
	 */
773
	public function get_notes_count() {
774
775
		$all_notes   = $this->get_raw_notes();
776
		$notes_array = array_reverse( array_filter( explode( "\n\n", $all_notes ) ) );
777
778
		return count( $notes_array );
779
780
	}
781
782
	/**
783
	 * Add a note for the customer.
784
	 *
785
	 * @since  1.0
786
     * @access public
787
	 *
788
	 * @param  string $note   The note to add. Default is empty.
789
	 *
790
	 * @return string|boolean The new note if added successfully, false otherwise.
791
	 */
792
	public function add_note( $note = '' ) {
793
794
		$note = trim( $note );
795
		if ( empty( $note ) ) {
796
			return false;
797
		}
798
799
		$notes = $this->get_raw_notes();
800
801
		if ( empty( $notes ) ) {
802
			$notes = '';
803
		}
804
805
		$note_string = date_i18n( 'F j, Y H:i:s', current_time( 'timestamp' ) ) . ' - ' . $note;
806
		$new_note    = apply_filters( 'give_customer_add_note_string', $note_string );
807
		$notes .= "\n\n" . $new_note;
808
809
		/**
810
		 * Fires before customer note added.
811
		 *
812
		 * @since 1.0
813
		 *
814
		 * @param string $new_note    New note to add.
815
		 * @param int    $customer_id Customer id.
816
		 */
817
		do_action( 'give_customer_pre_add_note', $new_note, $this->id );
818
819
		$updated = $this->update( array( 'notes' => $notes ) );
820
821
		if ( $updated ) {
822
			$this->notes = $this->get_notes();
823
		}
824
825
		/**
826
		 * Fires after customer note added.
827
		 *
828
		 * @since 1.0
829
		 *
830
		 * @param array  $customer_notes Customer notes.
831
		 * @param string $new_note       New note added.
832
		 * @param int    $customer_id    Customer id.
833
		 */
834
		do_action( 'give_customer_post_add_note', $this->notes, $new_note, $this->id );
835
836
		// Return the formatted note, so we can test, as well as update any displays
837
		return $new_note;
838
839
	}
840
841
	/**
842
	 * Get the notes column for the customer
843
	 *
844
	 * @since  1.0
845
     * @access private
846
	 *
847
	 * @return string The Notes for the customer, non-parsed.
848
	 */
849
	private function get_raw_notes() {
850
851
		$all_notes = $this->db->get_column( 'notes', $this->id );
852
853
		return $all_notes;
854
855
	}
856
857
	/**
858
	 * Retrieve customer meta field for a customer.
859
	 *
860
	 * @since  1.6
861
	 * @access public
862
	 *
863
	 * @param  string $meta_key The meta key to retrieve. Default is empty.
864
	 * @param  bool   $single   Whether to return a single value. Default is true.
865
	 *
866
	 * @return mixed            Will be an array if $single is false. Will be value of meta data field if $single is true.
867
	 */
868
	public function get_meta( $meta_key = '', $single = true ) {
869
		return Give()->customer_meta->get_meta( $this->id, $meta_key, $single );
870
	}
871
872
	/**
873
	 * Add meta data field to a customer.
874
	 *
875
	 * @since  1.6
876
	 * @access public
877
	 *
878
	 * @param  string $meta_key   Metadata name. Default is empty.
879
	 * @param  mixed  $meta_value Metadata value.
880
	 * @param  bool   $unique     Optional. Whether the same key should not be added. Default is false.
881
	 *
882
	 * @return bool               False for failure. True for success.
883
	 */
884
	public function add_meta( $meta_key = '', $meta_value, $unique = false ) {
885
		return Give()->customer_meta->add_meta( $this->id, $meta_key, $meta_value, $unique );
886
	}
887
888
	/**
889
	 * Update customer meta field based on customer ID.
890
	 *
891
	 * @since  1.6
892
	 * @access public
893
	 *
894
	 * @param  string $meta_key   Metadata key. Default is empty.
895
	 * @param  mixed  $meta_value Metadata value.
896
	 * @param  mixed  $prev_value Optional. Previous value to check before removing. Default is empty.
897
	 *
898
	 * @return bool               False on failure, true if success.
899
	 */
900
	public function update_meta( $meta_key = '', $meta_value, $prev_value = '' ) {
901
		return Give()->customer_meta->update_meta( $this->id, $meta_key, $meta_value, $prev_value );
902
	}
903
904
	/**
905
	 * Remove metadata matching criteria from a customer.
906
	 *
907
	 * @since  1.6
908
	 * @access public
909
	 *
910
	 * @param  string $meta_key   Metadata name. Default is empty.
911
	 * @param  mixed  $meta_value Optional. Metadata value. Default is empty.
912
	 *
913
	 * @return bool               False for failure. True for success.
914
	 */
915
	public function delete_meta( $meta_key = '', $meta_value = '' ) {
916
		return Give()->customer_meta->delete_meta( $this->id, $meta_key, $meta_value );
917
	}
918
919
	/**
920
	 * Sanitize the data for update/create
921
	 *
922
	 * @since  1.0
923
     * @access private
924
	 *
925
	 * @param  array $data The data to sanitize.
926
	 *
927
	 * @return array       The sanitized data, based off column defaults.
928
	 */
929
	private function sanitize_columns( $data ) {
930
931
		$columns        = $this->db->get_columns();
932
		$default_values = $this->db->get_column_defaults();
933
934
		foreach ( $columns as $key => $type ) {
935
936
			// Only sanitize data that we were provided
937
			if ( ! array_key_exists( $key, $data ) ) {
938
				continue;
939
			}
940
941
			switch ( $type ) {
942
943
				case '%s':
944
					if ( 'email' == $key ) {
945
						$data[ $key ] = sanitize_email( $data[ $key ] );
946
					} elseif ( 'notes' == $key ) {
947
						$data[ $key ] = strip_tags( $data[ $key ] );
948
					} else {
949
						$data[ $key ] = sanitize_text_field( $data[ $key ] );
950
					}
951
					break;
952
953
				case '%d':
954
					if ( ! is_numeric( $data[ $key ] ) || (int) $data[ $key ] !== absint( $data[ $key ] ) ) {
955
						$data[ $key ] = $default_values[ $key ];
956
					} else {
957
						$data[ $key ] = absint( $data[ $key ] );
958
					}
959
					break;
960
961
				case '%f':
962
					// Convert what was given to a float
963
					$value = floatval( $data[ $key ] );
964
965
					if ( ! is_float( $value ) ) {
966
						$data[ $key ] = $default_values[ $key ];
967
					} else {
968
						$data[ $key ] = $value;
969
					}
970
					break;
971
972
				default:
973
					$data[ $key ] = sanitize_text_field( $data[ $key ] );
974
					break;
975
976
			}
977
978
		}
979
980
		return $data;
981
	}
982
983
}
984