Passed
Push — master ( 345b42...86cae5 )
by Brian
05:49
created

GetPaid_Customer::set_email()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 3
rs 10
1
<?php
2
/**
3
 * Contains the customer class
4
 *
5
 * @since   1.0.15
6
 */
7
8
defined( 'ABSPATH' ) || exit;
9
10
/**
11
 * Customer class.
12
 *
13
 * @since 1.0.15
14
 *
15
 */
16
class GetPaid_Customer extends GetPaid_Data {
17
18
	/**
19
	 * Which data store to load.
20
	 *
21
	 * @var string
22
	 */
23
    protected $data_store_name = 'customer';
24
25
    /**
26
	 * This is the name of this object type.
27
	 *
28
	 * @var string
29
	 */
30
	protected $object_type = 'customer';
31
32
	/**
33
	 * Get the customer if ID is passed, otherwise the customer is new and empty.
34
	 *
35
	 * @param int|string|GetPaid_Customer $customer customer id, object, or email.
36
	 */
37
	public function __construct( $customer = 0 ) {
38
39
        // Setup default customer data.
40
        $this->setup_default_data();
41
42
		if ( is_numeric( $customer ) ) {
43
			$this->set_id( $customer );
0 ignored issues
show
Bug introduced by
It seems like $customer can also be of type string; however, parameter $id of GetPaid_Data::set_id() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

43
			$this->set_id( /** @scrutinizer ignore-type */ $customer );
Loading history...
44
		} elseif ( $customer instanceof self ) {
45
			$this->set_id( $customer->get_id() );
46
		} elseif ( is_string( $customer ) && $customer_id = self::get_customer_id_by( $customer, 'email' ) ) {
47
			$this->set_id( $customer_id );
48
		}
49
50
        // Load the datastore.
51
		$this->data_store = GetPaid_Data_Store::load( $this->data_store_name );
52
53
		if ( $this->get_id() > 0 ) {
54
			$this->data_store->read( $this );
55
        }
56
57
        $this->set_object_read( true );
58
	}
59
60
    /**
61
	 * Sets up default customer data.
62
	 */
63
	private function setup_default_data() {
64
65
        $this->data = array(
66
			'user_id'        => 0,
67
			'email'          => '',
68
			'email_cc'       => '',
69
			'status'         => 'active',
70
			'purchase_value' => 0,
71
			'purchase_count' => 0,
72
			'date_created'   => current_time( 'mysql' ),
73
			'date_modified'  => current_time( 'mysql' ),
74
			'uuid'           => wp_generate_uuid4(),
75
		);
76
77
        // Add address fields.
78
		foreach ( array_keys( getpaid_user_address_fields() ) as $field ) {
79
80
            if ( isset( $this->data[ $field ] ) ) {
81
                continue;
82
            }
83
84
            // Country.
85
            if ( 'country' === $field ) {
86
                $this->data[ $field ] = wpinv_get_default_country();
87
                continue;
88
            }
89
90
            // State.
91
            if ( 'state' === $field ) {
92
                $this->data[ $field ] = wpinv_get_default_state();
93
                continue;
94
            }
95
96
			$this->data[ $field ] = '';
97
		}
98
99
        $this->default_data = $this->data;
100
	}
101
102
	/**
103
	 * Given a customer email or user id, it returns a customer id.
104
	 *
105
	 * @static
106
	 * @param string $value
107
	 * @since 1.0.15
108
	 * @return int
109
	 */
110
	public static function get_customer_id_by( $value, $by = 'email' ) {
111
		global $wpdb;
112
113
        // Prepare value.
114
        if ( 'email' === $by ) {
115
            $value = sanitize_email( $value );
116
        } elseif ( 'user_id' === $by ) {
117
            $value = absint( $value );
118
        } else {
119
            return 0;
120
        }
121
122
        if ( empty( $value ) ) {
123
            return 0;
124
        }
125
126
		// Maybe retrieve from the cache.
127
        $cache_key   = 'getpaid_customer_ids_by_' . $by;
128
		$customer_id = wp_cache_get( $value, $cache_key );
129
		if ( false !== $customer_id ) {
130
			return $customer_id;
131
		}
132
133
        if ( 'email' === $by ) {
134
            $customer_id = (int) $wpdb->get_var(
135
                $wpdb->prepare( "SELECT id FROM {$wpdb->prefix}getpaid_customers WHERE email=%s LIMIT 1", $value )
136
            );
137
        } elseif ( 'user_id' === $by ) {
138
            $customer_id = (int) $wpdb->get_var(
139
                $wpdb->prepare( "SELECT id FROM {$wpdb->prefix}getpaid_customers WHERE user_id=%d LIMIT 1", $value )
140
            );
141
        }
142
143
		// Update the cache with our data
144
		wp_cache_set( $value, $customer_id, $cache_key );
145
146
		return $customer_id;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $customer_id could also return false which is incompatible with the documented return type integer. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
147
148
	}
149
150
	/**
151
     * Clears the customer's cache.
152
     */
153
    public function clear_cache() {
154
        wp_cache_delete( $this->get( 'email' ), 'getpaid_customer_ids_by_email' );
155
        wp_cache_delete( $this->get( 'user_id' ), 'getpaid_customer_ids_by_user_id' );
156
		wp_cache_delete( $this->get_id(), 'getpaid_customers' );
157
	}
158
159
	/*
160
	|--------------------------------------------------------------------------
161
	| CRUD methods
162
	|--------------------------------------------------------------------------
163
	|
164
	| Methods which create, read, update and delete discounts from the database.
165
	|
166
    */
167
168
    /*
169
	|--------------------------------------------------------------------------
170
	| Getters
171
	|--------------------------------------------------------------------------
172
	*/
173
174
    /**
175
     * Margic method for retrieving a property.
176
     *
177
     * @param  string $key The key to fetch.
178
     * @param  string $context View or edit context.
179
     */
180
    public function get( $key, $context = 'view' ) {
181
182
        // Maybe strip _wpinv_ prefix from key.
183
        $key = str_replace( '_wpinv_', '', $key );
184
185
        // Check if we have a helper method for that.
186
        if ( method_exists( $this, 'get_' . $key ) ) {
187
            return call_user_func( array( $this, 'get_' . $key ), $context );
188
        }
189
190
		return $this->get_prop( $key, $context );
191
192
    }
193
194
	/*
195
	|--------------------------------------------------------------------------
196
	| Setters
197
	|--------------------------------------------------------------------------
198
	|
199
	| Functions for setting customer data. These should not update anything in the
200
	| database itself and should only change what is stored in the class
201
	| object.
202
	*/
203
204
    /**
205
     * Margic method for setting a property.
206
     *
207
     * @param string $key The key to fetch.
208
     * @param mixed $value The new value.
209
     */
210
    public function set( $key, $value ) {
211
212
        // Check if we have a helper method for that.
213
        if ( method_exists( $this, 'set_' . $key ) ) {
214
            return call_user_func( array( $this, 'set_' . $key ), $value );
215
        }
216
217
		return $this->set_prop( $key, $value );
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->set_prop($key, $value) targeting GetPaid_Data::set_prop() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
218
219
    }
220
221
	/**
222
	 * Sets customer status.
223
	 *
224
	 * @since 1.0.0
225
	 * @param  string $status New status.
226
	 */
227
	public function set_status( $status ) {
228
229
		if ( in_array( $status, array( 'active', 'inactive', 'blocked' ), true ) ) {
230
			return $this->set_prop( 'status', $status );
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->set_prop('status', $status) targeting GetPaid_Data::set_prop() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
231
		}
232
233
		$this->set_prop( 'status', 'inactive' );
234
	}
235
236
	/**
237
	 * Sets the purchase value.
238
	 *
239
	 * @since 1.0.0
240
	 * @param float $purchase_value.
241
	 */
242
	public function set_purchase_value( $purchase_value ) {
243
		$this->set_prop( 'purchase_value', (float) $purchase_value );
244
	}
245
246
    /**
247
	 * Sets the purchase count.
248
	 *
249
	 * @since 1.0.0
250
	 * @param int $purchase_count.
251
	 */
252
	public function set_purchase_count( $purchase_count ) {
253
		$this->set_prop( 'purchase_count', absint( $purchase_count ) );
254
	}
255
256
    /**
257
	 * Sets the user id.
258
	 *
259
	 * @since 1.0.0
260
	 * @param int $user_id.
261
	 */
262
	public function set_user_id( $user_id ) {
263
		$this->set_prop( 'user_id', absint( $user_id ) );
264
	}
265
266
    /**
267
	 * Sets the email.
268
	 *
269
	 * @since 1.0.0
270
	 * @param string $email.
271
	 */
272
	public function set_email( $email ) {
273
        $email = is_string( $email ) ? sanitize_email( $email ) : '';
274
		$this->set_prop( 'email', $email );
275
	}
276
277
    /**
278
	 * Sets the email cc.
279
	 *
280
	 * @since 1.0.0
281
	 * @param string $email_cc.
282
	 */
283
	public function set_email_cc( $email_cc ) {
284
        $email_cc = implode( ', ', wp_parse_list( $email_cc ) );
285
		$this->set_prop( 'email_cc', $email_cc );
286
	}
287
288
    /**
289
	 * Sets the created date.
290
	 *
291
	 * @since 1.0.0
292
	 * @param  string $date_created date created.
293
	 */
294
	public function set_date_created( $date_created ) {
295
296
		$date = strtotime( $date_created );
297
298
        if ( $date && $date_created !== '0000-00-00 00:00:00'  && $date_created !== '0000-00-00 00:00' ) {
299
            $this->set_prop( 'date_created', gmdate( 'Y-m-d H:i:s', $date ) );
300
            return;
301
		}
302
303
		$this->set_prop( 'date_created', null );
304
	}
305
306
    /**
307
	 * Sets the created date.
308
	 *
309
	 * @since 1.0.0
310
	 * @param  string $date_modified date created.
311
	 */
312
	public function set_date_modified( $date_modified ) {
313
314
		$date = strtotime( $date_modified );
315
316
        if ( $date && $date_modified !== '0000-00-00 00:00:00'  && $date_modified !== '0000-00-00 00:00' ) {
317
            $this->set_prop( 'date_modified', gmdate( 'Y-m-d H:i:s', $date ) );
318
            return;
319
		}
320
321
		$this->set_prop( 'date_modified', null );
322
	}
323
324
	/*
325
	|--------------------------------------------------------------------------
326
	| Additional methods
327
	|--------------------------------------------------------------------------
328
	|
329
	| This method help you manipulate a customer.
330
	|
331
	*/
332
333
	/**
334
	 * Saves the customer.
335
	 *
336
	 * @since 1.0.0
337
	 */
338
	public function save() {
339
340
        $maybe_set = array(
341
            'uuid'         => wp_generate_uuid4(),
342
            'date_created' => current_time( 'mysql' ),
343
        );
344
345
        foreach ( $maybe_set as $key => $value ) {
346
            $current_value = $this->get( $key );
347
348
            if ( empty( $current_value ) ) {
349
                $this->set( $key, $value );
350
            }
351
        }
352
353
        $this->set( 'date_modified', current_time( 'mysql' ) );
354
355
		return parent::save();
356
	}
357
358
    /**
359
	 * Helper method to clone a customer from a user ID.
360
	 *
361
	 * @since 1.0.0
362
	 * @param int $user_id.
363
	 */
364
	public function clone_user( $user_id ) {
365
        $user = get_userdata( $user_id );
366
367
        if ( empty( $user ) ) {
368
            return;
369
        }
370
371
		$this->set_user_id( $user->ID );
372
        $this->set_email( $user->user_email );
373
        $this->set_purchase_value( getpaid_get_user_total_spend( $user->ID ) );
374
        $this->set_purchase_count( getpaid_count_user_invoices( $user->ID ) );
375
        $this->set( 'first_name', $user->first_name );
376
        $this->set( 'last_name', $user->last_name );
377
378
        // Fetch extra data from WC or old GetPaid.
379
        $prefixes = array(
380
            '_wpinv_',
381
            'billing_',
382
            '',
383
        );
384
385
        foreach ( array_keys( getpaid_user_address_fields() ) as $field ) {
386
387
            foreach ( $prefixes as $prefix ) {
388
389
                // Meta table.
390
                $value = get_user_meta( $user_id, $prefix . $field, true );
391
392
                // UWP table.
393
                $value = ( empty( $value ) && function_exists( 'uwp_get_usermeta' ) ) ? uwp_get_usermeta( $user_id, $prefix . $field ) : $value;
394
395
                if ( ! empty( $value ) ) {
396
                    $this->set( $field, $value );
397
                    continue;
398
                }
399
            }
400
		}
401
	}
402
403
    /**
404
	 * Helper method to migrate an existing user ID to the new customers table.
405
	 *
406
	 * @since 1.0.0
407
	 * @param int $user_id.
408
	 */
409
	public function migrate_from_user( $user_id ) {
410
        $this->clone_user( $user_id );
411
        do_action( 'getpaid_customer_migrated_from_user', $this, $user_id );
412
        $this->save();
413
	}
414
}
415