Completed
Push — master ( 10354b...44551c )
by Devin
29:37 queued 13:08
created

customer-actions.php ➔ give_edit_customer()   F

Complexity

Conditions 36
Paths > 20000

Size

Total Lines 149
Code Lines 86

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 36
eloc 86
nc 92926
nop 1
dl 0
loc 149
rs 2

How to fix   Long Method    Complexity   

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 26 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 (Donors)
4
 *
5
 * @package     Give
6
 * @subpackage  Admin/Customers
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
 * Processes a customer edit
19
 *
20
 * @since  1.0
21
 *
22
 * @param  array $args The $_POST array being passeed
23
 *
24
 * @return array $output Response messages
25
 */
26
function give_edit_customer( $args ) {
27
	$customer_edit_role = apply_filters( 'give_edit_customers_role', 'edit_give_payments' );
28
29
	if ( ! is_admin() || ! current_user_can( $customer_edit_role ) ) {
30
		wp_die( __( 'You do not have permission to edit this donor.', 'give' ) );
31
	}
32
33
	if ( empty( $args ) ) {
34
		return;
35
	}
36
37
	$customer_info = $args['customerinfo'];
38
	$customer_id   = (int) $args['customerinfo']['id'];
39
	$nonce         = $args['_wpnonce'];
40
41
	if ( ! wp_verify_nonce( $nonce, 'edit-customer' ) ) {
42
		wp_die( __( 'Cheatin\' eh?!', 'give' ) );
43
	}
44
45
	$customer = new Give_Customer( $customer_id );
46
	if ( empty( $customer->id ) ) {
47
		return false;
48
	}
49
50
	$defaults = array(
51
		'name'    => '',
52
		'email'   => '',
53
		'user_id' => 0
54
	);
55
56
	$customer_info = wp_parse_args( $customer_info, $defaults );
57
58
	if ( ! is_email( $customer_info['email'] ) ) {
59
		give_set_error( 'give-invalid-email', __( 'Please enter a valid email address.', 'give' ) );
60
	}
61
62
	if ( (int) $customer_info['user_id'] != (int) $customer->user_id ) {
63
64
		// Make sure we don't already have this user attached to a customer
65
		if ( ! empty( $customer_info['user_id'] ) && false !== Give()->customers->get_customer_by( 'user_id', $customer_info['user_id'] ) ) {
0 ignored issues
show
Bug introduced by
The method get_customer_by() does not seem to exist on object<Give_Customer>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
66
			give_set_error( 'give-invalid-customer-user_id', sprintf( __( 'The User ID %d is already associated with a different donor.', 'give' ), $customer_info['user_id'] ) );
67
		}
68
69
		// Make sure it's actually a user
70
		$user = get_user_by( 'id', $customer_info['user_id'] );
71
		if ( ! empty( $customer_info['user_id'] ) && false === $user ) {
72
			give_set_error( 'give-invalid-user_id', sprintf( __( 'The User ID %d does not exist. Please assign an existing user.', 'give' ), $customer_info['user_id'] ) );
73
		}
74
75
	}
76
77
	// Record this for later
78
	$previous_user_id = $customer->user_id;
79
80
	if ( give_get_errors() ) {
81
		return;
82
	}
83
84
	// Setup the customer address, if present
85
	$address = array();
86
	if ( intval( $customer_info['user_id'] ) > 0 ) {
87
88
		$current_address = get_user_meta( $customer_info['user_id'], '_give_user_address', true );
89
90
		if ( false === $current_address ) {
91
			$address['line1']   = isset( $customer_info['line1'] ) ? $customer_info['line1'] : '';
92
			$address['line2']   = isset( $customer_info['line2'] ) ? $customer_info['line2'] : '';
93
			$address['city']    = isset( $customer_info['city'] ) ? $customer_info['city'] : '';
94
			$address['country'] = isset( $customer_info['country'] ) ? $customer_info['country'] : '';
95
			$address['zip']     = isset( $customer_info['zip'] ) ? $customer_info['zip'] : '';
96
			$address['state']   = isset( $customer_info['state'] ) ? $customer_info['state'] : '';
97
		} else {
98
			$current_address    = wp_parse_args( $current_address, array(
99
				'line1',
100
				'line2',
101
				'city',
102
				'zip',
103
				'state',
104
				'country'
105
			) );
106
			$address['line1']   = isset( $customer_info['line1'] ) ? $customer_info['line1'] : $current_address['line1'];
107
			$address['line2']   = isset( $customer_info['line2'] ) ? $customer_info['line2'] : $current_address['line2'];
108
			$address['city']    = isset( $customer_info['city'] ) ? $customer_info['city'] : $current_address['city'];
109
			$address['country'] = isset( $customer_info['country'] ) ? $customer_info['country'] : $current_address['country'];
110
			$address['zip']     = isset( $customer_info['zip'] ) ? $customer_info['zip'] : $current_address['zip'];
111
			$address['state']   = isset( $customer_info['state'] ) ? $customer_info['state'] : $current_address['state'];
112
		}
113
114
	}
115
116
	// Sanitize the inputs
117
	$customer_data            = array();
118
	$customer_data['name']    = strip_tags( stripslashes( $customer_info['name'] ) );
119
	$customer_data['email']   = $customer_info['email'];
120
	$customer_data['user_id'] = $customer_info['user_id'];
121
122
	$customer_data = apply_filters( 'give_edit_customer_info', $customer_data, $customer_id );
123
	$address       = apply_filters( 'give_edit_customer_address', $address, $customer_id );
124
125
	$customer_data = array_map( 'sanitize_text_field', $customer_data );
126
	$address       = array_map( 'sanitize_text_field', $address );
127
128
	do_action( 'give_pre_edit_customer', $customer_id, $customer_data, $address );
129
130
	$output         = array();
131
	$previous_email = $customer->email;
132
133
	if ( $customer->update( $customer_data ) ) {
134
135
		if ( ! empty( $customer->user_id ) && $customer->user_id > 0 ) {
136
			update_user_meta( $customer->user_id, '_give_user_address', $address );
137
		}
138
139
		// Update some payment meta if we need to
140
		$payments_array = explode( ',', $customer->payment_ids );
141
142
		if ( $customer->email != $previous_email ) {
143
			foreach ( $payments_array as $payment_id ) {
144
				give_update_payment_meta( $payment_id, 'email', $customer->email );
145
			}
146
		}
147
148
		if ( $customer->user_id != $previous_user_id ) {
149
			foreach ( $payments_array as $payment_id ) {
150
				give_update_payment_meta( $payment_id, '_give_payment_user_id', $customer->user_id );
151
			}
152
		}
153
154
		$output['success']       = true;
155
		$customer_data           = array_merge( $customer_data, $address );
156
		$output['customer_info'] = $customer_data;
157
158
	} else {
159
160
		$output['success'] = false;
161
162
	}
163
164
	do_action( 'give_post_edit_customer', $customer_id, $customer_data );
165
166
	if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
167
		header( 'Content-Type: application/json' );
168
		echo json_encode( $output );
169
		wp_die();
170
	}
171
172
	return $output;
173
174
}
175
176
add_action( 'give_edit-customer', 'give_edit_customer', 10, 1 );
177
178
/**
179
 * Save a customer note being added
180
 *
181
 * @since  1.0
182
 *
183
 * @param  array $args The $_POST array being passeed
184
 *
185
 * @return int         The Note ID that was saved, or 0 if nothing was saved
186
 */
187
function give_customer_save_note( $args ) {
188
189
	$customer_view_role = apply_filters( 'give_view_customers_role', 'view_give_reports' );
190
191
	if ( ! is_admin() || ! current_user_can( $customer_view_role ) ) {
192
		wp_die( __( 'You do not have permission to edit this donor.', 'give' ) );
193
	}
194
195
	if ( empty( $args ) ) {
196
		return;
197
	}
198
199
	$customer_note = trim( sanitize_text_field( $args['customer_note'] ) );
200
	$customer_id   = (int) $args['customer_id'];
201
	$nonce         = $args['add_customer_note_nonce'];
202
203
	if ( ! wp_verify_nonce( $nonce, 'add-customer-note' ) ) {
204
		wp_die( __( 'Cheatin\' eh?!', 'give' ) );
205
	}
206
207
	if ( empty( $customer_note ) ) {
208
		give_set_error( 'empty-customer-note', __( 'A note is required', 'give' ) );
209
	}
210
211
	if ( give_get_errors() ) {
212
		return;
213
	}
214
215
	$customer = new Give_Customer( $customer_id );
216
	$new_note = $customer->add_note( $customer_note );
217
218
	do_action( 'give_pre_insert_customer_note', $customer_id, $new_note );
219
220
	if ( ! empty( $new_note ) && ! empty( $customer->id ) ) {
221
222
		ob_start();
223
		?>
224
		<div class="customer-note-wrapper dashboard-comment-wrap comment-item">
225
			<span class="note-content-wrap">
226
				<?php echo stripslashes( $new_note ); ?>
227
			</span>
228
		</div>
229
		<?php
230
		$output = ob_get_contents();
231
		ob_end_clean();
232
233
		if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
234
			echo $output;
235
			exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The function give_customer_save_note() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
236
		}
237
238
		return $new_note;
239
240
	}
241
242
	return false;
243
244
}
245
246
add_action( 'give_add-customer-note', 'give_customer_save_note', 10, 1 );
247
248
/**
249
 * Delete a customer
250
 *
251
 * @since  1.0
252
 *
253
 * @param  array $args The $_POST array being passed
254
 *
255
 * @return int Whether it was a successful deletion
256
 */
257
function give_customer_delete( $args ) {
258
259
	$customer_edit_role = apply_filters( 'give_edit_customers_role', 'edit_give_payments' );
260
261
	if ( ! is_admin() || ! current_user_can( $customer_edit_role ) ) {
262
		wp_die( __( 'You do not have permission to delete this donor.', 'give' ) );
263
	}
264
265
	if ( empty( $args ) ) {
266
		return;
267
	}
268
269
	$customer_id = (int) $args['customer_id'];
270
	$confirm     = ! empty( $args['give-customer-delete-confirm'] ) ? true : false;
271
	$remove_data = ! empty( $args['give-customer-delete-records'] ) ? true : false;
272
	$nonce       = $args['_wpnonce'];
273
274
	if ( ! wp_verify_nonce( $nonce, 'delete-customer' ) ) {
275
		wp_die( __( 'Cheatin\' eh?!', 'give' ) );
276
	}
277
278
	if ( ! $confirm ) {
279
		give_set_error( 'customer-delete-no-confirm', __( 'Please confirm you want to delete this donor', 'give' ) );
280
	}
281
282
	if ( give_get_errors() ) {
283
		wp_redirect( admin_url( 'edit.php?post_type=give_forms&page=give-donors&view=overview&id=' . $customer_id ) );
284
		exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The function give_customer_delete() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
285
	}
286
287
	$customer = new Give_Customer( $customer_id );
288
289
	do_action( 'give_pre_delete_customer', $customer_id, $confirm, $remove_data );
290
291
	$success = false;
292
293
	if ( $customer->id > 0 ) {
294
295
		$payments_array = explode( ',', $customer->payment_ids );
296
		$success        = Give()->customers->delete( $customer->id );
0 ignored issues
show
Bug introduced by
The method delete() does not seem to exist on object<Give_Customer>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
297
298
		if ( $success ) {
299
300
			if ( $remove_data ) {
301
302
				// Remove all payments, logs, etc
303
				foreach ( $payments_array as $payment_id ) {
304
					give_delete_purchase( $payment_id );
305
				}
306
307
			} else {
308
309
				// Just set the payments to customer_id of 0
310
				foreach ( $payments_array as $payment_id ) {
311
					give_update_payment_meta( $payment_id, '_give_payment_customer_id', 0 );
312
				}
313
314
			}
315
316
			$redirect = admin_url( 'edit.php?post_type=give_forms&page=give-donors&give-message=customer-deleted' );
317
318
		} else {
319
320
			give_set_error( 'give-donor-delete-failed', __( 'Error deleting donor', 'give' ) );
321
			$redirect = admin_url( 'edit.php?post_type=give_forms&page=give-donors&view=delete&id=' . $customer_id );
322
323
		}
324
325
	} else {
326
327
		give_set_error( 'give-customer-delete-invalid-id', __( 'Invalid Donor ID', 'give' ) );
328
		$redirect = admin_url( 'edit.php?post_type=give_forms&page=give-donors' );
329
330
	}
331
332
	wp_redirect( $redirect );
333
	exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The function give_customer_delete() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
334
335
}
336
337
add_action( 'give_delete-customer', 'give_customer_delete', 10, 1 );
338
339
/**
340
 * Disconnect a user ID from a donor
341
 *
342
 * @since  1.0
343
 *
344
 * @param  array $args Array of arguements
345
 *
346
 * @return bool        If the disconnect was sucessful
347
 */
348
function give_disconnect_customer_user_id( $args ) {
349
350
	$customer_edit_role = apply_filters( 'give_edit_customers_role', 'edit_give_payments' );
351
352
	if ( ! is_admin() || ! current_user_can( $customer_edit_role ) ) {
353
		wp_die( __( 'You do not have permission to edit this donor.', 'give' ) );
354
	}
355
356
	if ( empty( $args ) ) {
357
		return;
358
	}
359
360
	$customer_id = (int) $args['customer_id'];
361
	$nonce       = $args['_wpnonce'];
362
363
	if ( ! wp_verify_nonce( $nonce, 'edit-customer' ) ) {
364
		wp_die( __( 'Cheatin\' eh?!', 'give' ) );
365
	}
366
367
	$customer = new Give_Customer( $customer_id );
368
	if ( empty( $customer->id ) ) {
369
		return false;
370
	}
371
372
	do_action( 'give_pre_customer_disconnect_user_id', $customer_id, $customer->user_id );
373
374
	$customer_args = array( 'user_id' => 0 );
375
376
	if ( $customer->update( $customer_args ) ) {
377
		global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
378
379
		if ( ! empty( $customer->payment_ids ) ) {
380
			$wpdb->query( "UPDATE $wpdb->postmeta SET meta_value = 0 WHERE meta_key = '_give_payment_user_id' AND post_id IN ( $customer->payment_ids )" );
381
		}
382
383
		$output['success'] = true;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$output was never initialized. Although not strictly required by PHP, it is generally a good practice to add $output = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
384
385
	} else {
386
387
		$output['success'] = false;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$output was never initialized. Although not strictly required by PHP, it is generally a good practice to add $output = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
388
		give_set_error( 'give-disconnect-user-fail', __( 'Failed to disconnect user from donor', 'give' ) );
389
	}
390
391
	do_action( 'give_post_customer_disconnect_user_id', $customer_id );
392
393
	if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
394
		header( 'Content-Type: application/json' );
395
		echo json_encode( $output );
396
		wp_die();
397
	}
398
399
	return $output;
400
401
}
402
403
add_action( 'give_disconnect-userid', 'give_disconnect_customer_user_id', 10, 1 );
404