Completed
Push — release/2.0 ( 4d845f...d9fa8a )
by Ravinder
18:24
created

includes/admin/payments/actions.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Admin Payment Actions
4
 *
5
 * @package     Give
6
 * @subpackage  Admin/Payments
7
 * @copyright   Copyright (c) 2016, WordImpress
8
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
9
 * @since       1.0
10
 */
11
12
// Exit if accessed directly.
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 *
19
 * Process the payment details edit
20
 *
21
 * @since  1.0
22
 * @access private
23
 *
24
 * @param array $data Donation data.
25
 *
26
 * @return      void
27
 */
28
function give_update_payment_details( $data ) {
29
30
	if ( ! current_user_can( 'edit_give_payments', $data['give_payment_id'] ) ) {
31
		wp_die( esc_html__( 'You do not have permission to edit payments.', 'give' ), esc_html__( 'Error', 'give' ), array( 'response' => 403 ) );
32
	}
33
34
	check_admin_referer( 'give_update_payment_details_nonce' );
35
36
	// Retrieve the payment ID.
37
	$payment_id = absint( $data['give_payment_id'] );
38
39
	/* @var Give_Payment $payment */
40
	$payment = new Give_Payment( $payment_id );
41
42
	// Retrieve existing payment meta.
43
	$meta      = $payment->get_meta();
44
	$user_info = $payment->user_info;
45
46
	$status = $data['give-payment-status'];
47
	$date   = sanitize_text_field( $data['give-payment-date'] );
48
	$hour   = sanitize_text_field( $data['give-payment-time-hour'] );
49
50
	// Restrict to our high and low.
51
	if ( $hour > 23 ) {
52
		$hour = 23;
53
	} elseif ( $hour < 0 ) {
54
		$hour = 00;
55
	}
56
57
	$minute = sanitize_text_field( $data['give-payment-time-min'] );
58
59
	// Restrict to our high and low.
60
	if ( $minute > 59 ) {
61
		$minute = 59;
62
	} elseif ( $minute < 0 ) {
63
		$minute = 00;
64
	}
65
66
	$address = array_map( 'trim', $data['give-payment-address'][0] );
67
68
	$curr_total = give_sanitize_amount( $payment->total );
69
	$new_total  = give_sanitize_amount( $data['give-payment-total'] );
70
	$date       = date( 'Y-m-d', strtotime( $date ) ) . ' ' . $hour . ':' . $minute . ':00';
71
72
	$curr_donor_id = sanitize_text_field( $data['give-current-donor'] );
73
	$new_donor_id  = sanitize_text_field( $data['donor-id'] );
74
75
	/**
76
	 * Fires before updating edited donation.
77
	 *
78
	 * @since 1.0
79
	 *
80
	 * @param int $payment_id The ID of the payment.
81
	 */
82
	do_action( 'give_update_edited_donation', $payment_id );
83
84
	$payment->date = $date;
85
	$updated       = $payment->save();
86
87
	if ( 0 === $updated ) {
88
		wp_die( esc_html__( 'Error Updating Donation.', 'give' ), esc_html__( 'Error', 'give' ), array( 'response' => 400 ) );
89
	}
90
91
	$donor_changed = false;
92
93
	if ( isset( $data['give-new-donor'] ) && $data['give-new-donor'] == '1' ) {
94
95
		$email = isset( $data['give-new-donor-email'] ) ? sanitize_text_field( $data['give-new-donor-email'] ) : '';
96
		$names = isset( $data['give-new-donor-name'] ) ? sanitize_text_field( $data['give-new-donor-name'] ) : '';
97
98
		if ( empty( $email ) || empty( $names ) ) {
99
			wp_die( esc_html__( 'New donors require a name and email address.', 'give' ), esc_html__( 'Error', 'give' ), array( 'response' => 400 ) );
100
		}
101
102
		$donor = new Give_Donor( $email );
103
		if ( empty( $donor->id ) ) {
104
			$donor_data = array( 'name' => $names, 'email' => $email );
105
			$user_id       = email_exists( $email );
106
			if ( false !== $user_id ) {
107
				$donor_data['user_id'] = $user_id;
108
			}
109
110
			if ( ! $donor->create( $donor_data ) ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $donor->create($donor_data) of type false|integer is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
111
				// Failed to crete the new donor, assume the previous donor.
112
				$donor_changed = false;
113
				$donor         = new Give_Donor( $curr_donor_id );
114
				give_set_error( 'give-payment-new-donor-fail', __( 'Error creating new donor.', 'give' ) );
115
			}
116
		}
117
118
		$new_donor_id = $donor->id;
119
120
		$previous_donor = new Give_Donor( $curr_donor_id );
121
122
		$donor_changed = true;
123
124
	} elseif ( $curr_donor_id !== $new_donor_id ) {
125
126
		$donor = new Give_Donor( $new_donor_id );
127
		$email    = $donor->email;
128
		$names    = $donor->name;
129
130
		$previous_donor = new Give_Donor( $curr_donor_id );
131
132
		$donor_changed = true;
133
134
	} else {
135
136
		$donor = new Give_Donor( $curr_donor_id );
137
		$email    = $donor->email;
138
		$names    = $donor->name;
139
140
	}
141
142
	// Setup first and last name from input values.
143
	$names      = explode( ' ', $names );
144
	$first_name = ! empty( $names[0] ) ? $names[0] : '';
145
	$last_name  = '';
146
	if ( ! empty( $names[1] ) ) {
147
		unset( $names[0] );
148
		$last_name = implode( ' ', $names );
149
	}
150
151
	if ( $donor_changed ) {
152
153
		// Remove the stats and payment from the previous donor and attach it to the new donor.
154
		$previous_donor->remove_payment( $payment_id, false );
0 ignored issues
show
The variable $previous_donor does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
155
		$donor->attach_payment( $payment_id, false );
156
157
		if ( 'publish' == $status ) {
158
159
			// Reduce previous user donation count and amount.
160
			$previous_donor->decrease_donation_count();
161
			$previous_donor->decrease_value( $curr_total );
162
163
			// If donation was completed adjust stats of new donors.
164
			$donor->increase_purchase_count();
165
			$donor->increase_value( $new_total );
166
		}
167
168
		$payment->customer_id = $donor->id;
169
	} else {
170
171
		if ( 'publish' === $status ) {
172
			// Update user donation stat.
173
			$donor->update_donation_value( $curr_total, $new_total );
174
		}
175
	}
176
177
	// Set new meta values.
178
	$payment->user_id    = $donor->user_id;
179
	$payment->email      = $donor->email;
180
	$payment->first_name = $first_name;
181
	$payment->last_name  = $last_name;
182
	$payment->address    = $address;
183
	$payment->total      = $new_total;
184
185
	// Check for payment notes.
186
	if ( ! empty( $data['give-payment-note'] ) ) {
187
188
		$note = wp_kses( $data['give-payment-note'], array() );
189
		give_insert_payment_note( $payment_id, $note );
190
191
	}
192
193
	// Set new status.
194
	$payment->status = $status;
195
196
	// Adjust total store earnings if the payment total has been changed.
197
	if ( $new_total !== $curr_total && 'publish' == $status ) {
198
199
		if ( $new_total > $curr_total ) {
200
			// Increase if our new total is higher.
201
			$difference = $new_total - $curr_total;
202
			give_increase_total_earnings( $difference );
203
204
		} elseif ( $curr_total > $new_total ) {
205
			// Decrease if our new total is lower.
206
			$difference = $curr_total - $new_total;
207
			give_decrease_total_earnings( $difference );
208
209
		}
210
	}
211
212
	$payment->save();
213
214
	// Get new give form ID.
215
	$new_form_id     = absint( $data['give-payment-form-select'] );
216
	$current_form_id = absint( $payment->get_meta( '_give_payment_form_id' ) );
217
218
	// We are adding payment transfer code in last to remove any conflict with above functionality.
219
	// For example: above code will automatically handle form stat (increase/decrease) when payment status changes.
220
	// Check if user want to transfer current payment to new give form id.
221
	if ( $new_form_id != $current_form_id ) {
222
223
		// Get new give form title.
224
		$new_form_title = get_the_title( $new_form_id );
225
226
		// Update new give form data in payment data.
227
		$payment_meta               = $payment->get_meta();
228
		$payment_meta['form_title'] = $new_form_title;
229
		$payment_meta['form_id']    = $new_form_id;
230
231
		// Update price id post meta data for set donation form.
232
		if ( ! give_has_variable_prices( $new_form_id ) ) {
233
			$payment_meta['price_id'] = '';
234
		}
235
236
		// Update payment give form meta data.
237
		$payment->update_meta( '_give_payment_form_id', $new_form_id );
238
		$payment->update_meta( '_give_payment_form_title', $new_form_title );
239
		$payment->update_meta( '_give_payment_meta', $payment_meta );
240
241
		// Update price id payment metadata.
242
		if ( ! give_has_variable_prices( $new_form_id ) ) {
243
			$payment->update_meta( '_give_payment_price_id', '' );
244
		}
245
246
		// If donation was completed, adjust stats of forms.
247
		if ( 'publish' == $status ) {
248
249
			// Decrease sale of old give form. For other payment status.
250
			$current_form = new Give_Donate_Form( $current_form_id );
251
			$current_form->decrease_sales();
252
			$current_form->decrease_earnings( $curr_total );
253
254
			// Increase sale of new give form.
255
			$new_form = new Give_Donate_Form( $new_form_id );
256
			$new_form->increase_sales();
257
			$new_form->increase_earnings( $new_total );
258
		}
259
260
		// Re setup payment to update new meta value in object.
261
		$payment->update_payment_setup( $payment->ID );
262
	}
263
264
	// Update price id if current form is variable form.
265
	if ( ! empty( $data['give-variable-price'] ) && give_has_variable_prices( $payment->form_id ) ) {
266
267
		// Get payment meta data.
268
		$payment_meta = $payment->get_meta();
269
270
		// Set payment id to empty string if variable price id is negative ( i.e. custom amount feature enabled ).
271
		$data['give-variable-price'] = ( 'custom' === $data['give-variable-price'] ) ? 'custom' : ( 0 < $data['give-variable-price'] ) ? $data['give-variable-price'] : '';
272
273
		// Update payment meta data.
274
		$payment_meta['price_id'] = $data['give-variable-price'];
275
276
		// Update payment give form meta data.
277
		$payment->update_meta( '_give_payment_price_id', $data['give-variable-price'] );
278
		$payment->update_meta( '_give_payment_meta', $payment_meta );
279
280
		// Re setup payment to update new meta value in object.
281
		$payment->update_payment_setup( $payment->ID );
282
	}
283
284
	/**
285
	 * Fires after updating edited donation.
286
	 *
287
	 * @since 1.0
288
	 *
289
	 * @param int $payment_id The ID of the payment.
290
	 */
291
	do_action( 'give_update_edited_donation', $payment_id );
292
293
	wp_safe_redirect( admin_url( 'edit.php?post_type=give_forms&page=give-payment-history&view=view-payment-details&give-message=payment-updated&id=' . $payment_id ) );
294
	exit;
295
}
296
297
add_action( 'give_update_payment_details', 'give_update_payment_details' );
298
299
/**
300
 * Trigger a Donation Deletion.
301
 *
302
 * @since 1.0
303
 *
304
 * @param array $data Arguments passed.
305
 *
306
 * @return void
307
 */
308
function give_trigger_donation_delete( $data ) {
309
	if ( wp_verify_nonce( $data['_wpnonce'], 'give_donation_nonce' ) ) {
310
311
		$payment_id = absint( $data['purchase_id'] );
312
313
		if ( ! current_user_can( 'edit_give_payments', $payment_id ) ) {
314
			wp_die( __( 'You do not have permission to edit payments.', 'give' ), __( 'Error', 'give' ), array( 'response' => 403 ) );
315
		}
316
317
		give_delete_donation( $payment_id );
318
		wp_redirect( admin_url( 'edit.php?post_type=give_forms&page=give-payment-history&give-message=donation_deleted' ) );
319
		give_die();
320
	}
321
}
322
323
add_action( 'give_delete_payment', 'give_trigger_donation_delete' );
324
325
/**
326
 * AJAX Store Donation Note
327
 */
328
function give_ajax_store_payment_note() {
329
330
	$payment_id = absint( $_POST['payment_id'] );
331
	$note       = wp_kses( $_POST['note'], array() );
332
333
	if ( ! current_user_can( 'edit_give_payments', $payment_id ) ) {
334
		wp_die( __( 'You do not have permission to edit payments.', 'give' ), __( 'Error', 'give' ), array( 'response' => 403 ) );
335
	}
336
337
	if ( empty( $payment_id ) ) {
338
		die( '-1' );
339
	}
340
341
	if ( empty( $note ) ) {
342
		die( '-1' );
343
	}
344
345
	$note_id = give_insert_payment_note( $payment_id, $note );
346
	die( give_get_payment_note_html( $note_id ) );
347
}
348
349
add_action( 'wp_ajax_give_insert_payment_note', 'give_ajax_store_payment_note' );
350
351
/**
352
 * Triggers a donation note deletion without ajax
353
 *
354
 * @since 1.0
355
 *
356
 * @param array $data Arguments passed
357
 *
358
 * @return void
359
 */
360
function give_trigger_payment_note_deletion( $data ) {
361
362
	if ( ! wp_verify_nonce( $data['_wpnonce'], 'give_delete_payment_note_' . $data['note_id'] ) ) {
363
		return;
364
	}
365
366
	if ( ! current_user_can( 'edit_give_payments', $data['payment_id'] ) ) {
367
		wp_die( esc_html__( 'You do not have permission to edit payments.', 'give' ), esc_html__( 'Error', 'give' ), array( 'response' => 403 ) );
368
	}
369
370
	$edit_order_url = admin_url( 'edit.php?post_type=give_forms&page=give-payment-history&view=view-payment-details&give-message=donation-note-deleted&id=' . absint( $data['payment_id'] ) );
371
372
	give_delete_payment_note( $data['note_id'], $data['payment_id'] );
373
374
	wp_redirect( $edit_order_url );
375
}
376
377
add_action( 'give_delete_payment_note', 'give_trigger_payment_note_deletion' );
378
379
/**
380
 * Delete a payment note deletion with ajax
381
 *
382
 * @since 1.0
383
 *
384
 * @return void
385
 */
386
function give_ajax_delete_payment_note() {
387
388
	if ( ! current_user_can( 'edit_give_payments', $_POST['payment_id'] ) ) {
389
		wp_die( esc_html__( 'You do not have permission to edit payments.', 'give' ), esc_html__( 'Error', 'give' ), array( 'response' => 403 ) );
390
	}
391
392
	if ( give_delete_payment_note( $_POST['note_id'], $_POST['payment_id'] ) ) {
393
		die( '1' );
394
	} else {
395
		die( '-1' );
396
	}
397
398
}
399
400
add_action( 'wp_ajax_give_delete_payment_note', 'give_ajax_delete_payment_note' );
401