Issues (4335)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

includes/forms/functions.php (48 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

Code
1
<?php
2
/**
3
 * Give Form Functions
4
 *
5
 * @package     GiveWP
6
 * @subpackage  Includes/Forms
7
 * @copyright   Copyright (c) 2016, GiveWP
8
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
9
 * @since       1.1
10
 */
11
12
// Exit if accessed directly.
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * Filter: Do not show the Give shortcut button on Give Forms CPT
19
 *
20
 * @return bool
21
 */
22
function give_shortcode_button_condition() {
23
24
	global $typenow;
25
26
	if ( $typenow != 'give_forms' ) {
0 ignored issues
show
Found "!= '". Use Yoda Condition checks, you must
Loading history...
27
		return true;
28
	}
29
30
	return false;
31
}
32
33
add_filter( 'give_shortcode_button_condition', 'give_shortcode_button_condition' );
34
35
36
/**
37
 * Get the form ID from the form $args
38
 *
39
 * @param array $args
40
 *
41
 * @return int|false
42
 */
43
function get_form_id_from_args( $args ) {
44
45
	if ( isset( $args['form_id'] ) && $args['form_id'] != 0 ) {
0 ignored issues
show
Found "!= 0". Use Yoda Condition checks, you must
Loading history...
46
47
		return intval( $args['form_id'] );
48
	}
49
50
	return false;
51
}
52
53
/**
54
 * Checks whether floating labels is enabled for the form ID in $args
55
 *
56
 * @since 1.1
57
 *
58
 * @param array $args
59
 *
60
 * @return bool
61
 */
62
function give_is_float_labels_enabled( $args ) {
63
64
	$float_labels = '';
65
66
	if ( ! empty( $args['float_labels'] ) ) {
67
		$float_labels = $args['float_labels'];
68
	}
69
70
	if ( empty( $float_labels ) ) {
71
		$float_labels = give_get_meta( $args['form_id'], '_give_form_floating_labels', true );
72
	}
73
74
	if ( empty( $float_labels ) || ( 'global' === $float_labels ) ) {
75
		$float_labels = give_get_option( 'floatlabels', 'disabled' );
76
	}
77
78
	return give_is_setting_enabled( $float_labels );
79
}
80
81
/**
82
 * Determines if a user can checkout or not
83
 *
84
 * Allows themes and plugins to set donation checkout conditions
85
 *
86
 * @since 1.0
87
 *
88
 * @return bool Can user checkout?
89
 */
90
function give_can_checkout() {
91
92
	$can_checkout = true;
93
94
	return (bool) apply_filters( 'give_can_checkout', $can_checkout );
95
}
96
97
/**
98
 * Retrieve the Success page URI
99
 *
100
 * @access      public
101
 * @since       1.0
102
 *
103
 * @return      string
104
 */
105
function give_get_success_page_uri() {
106
	$give_options = give_get_settings();
107
108
	$success_page = isset( $give_options['success_page'] ) ? get_permalink( absint( $give_options['success_page'] ) ) : get_bloginfo( 'url' );
109
110
	return apply_filters( 'give_get_success_page_uri', $success_page );
111
}
112
113
/**
114
 * Determines if we're currently on the Success page.
115
 *
116
 * @since 1.0
117
 *
118
 * @return bool True if on the Success page, false otherwise.
119
 */
120 View Code Duplication
function give_is_success_page() {
0 ignored issues
show
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
121
	$give_options = give_get_settings();
122
123
	$success_page = isset( $give_options['success_page'] ) ? is_page( $give_options['success_page'] ) : false;
124
125
	return apply_filters( 'give_is_success_page', $success_page );
126
}
127
128
/**
129
 * Send To Success Page
130
 *
131
 * Sends the user to the success page.
132
 *
133
 * @param string $query_string
134
 *
135
 * @access      public
136
 * @since       1.0
137
 * @return      void
138
 */
139
function give_send_to_success_page( $query_string = null ) {
140
141
	$redirect = give_get_success_page_uri();
142
143
	if ( $query_string ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $query_string of type string|null is loosely compared to true; this is ambiguous if the string can be empty. 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 string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
144
		$redirect .= $query_string;
145
	}
146
147
	$gateway = isset( $_REQUEST['give-gateway'] ) ? $_REQUEST['give-gateway'] : '';
0 ignored issues
show
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
148
149
	wp_redirect( apply_filters( 'give_success_page_redirect', $redirect, $gateway, $query_string ) );
150
	give_die();
151
}
152
153
154
/**
155
 * Send back to donation form.
156
 *
157
 * Used to redirect a user back to the donation form if there are errors present.
158
 *
159
 * @param array|string $args
160
 *
161
 * @access public
162
 * @since  1.0
163
 * @return Void
164
 */
165
function give_send_back_to_checkout( $args = array() ) {
166
167
	$url     = isset( $_POST['give-current-url'] ) ? sanitize_text_field( $_POST['give-current-url'] ) : '';
0 ignored issues
show
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
168
	$form_id = 0;
169
170
	// Set the form_id.
171
	if ( isset( $_POST['give-form-id'] ) ) {
172
		$form_id = sanitize_text_field( $_POST['give-form-id'] );
0 ignored issues
show
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
173
	}
174
175
	// Need a URL to continue. If none, redirect back to single form.
176
	if ( empty( $url ) ) {
177
		wp_safe_redirect( get_permalink( $form_id ) );
178
		give_die();
179
	}
180
181
	$defaults = array(
182
		'form-id' => (int) $form_id,
183
	);
184
185
	// Set the $level_id.
186
	if ( isset( $_POST['give-price-id'] ) ) {
187
		$defaults['level-id'] = sanitize_text_field( $_POST['give-price-id'] );
0 ignored issues
show
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
188
	}
189
190
	// Check for backward compatibility.
191
	if ( is_string( $args ) ) {
192
		$args = str_replace( '?', '', $args );
193
	}
194
195
	$args = wp_parse_args( $args, $defaults );
196
197
	// Merge URL query with $args to maintain third-party URL parameters after redirect.
198
	$url_data = wp_parse_url( $url );
199
200
	// Check if an array to prevent notices before parsing.
201
	if ( isset( $url_data['query'] ) && ! empty( $url_data['query'] ) ) {
202
		parse_str( $url_data['query'], $query );
203
204
		// Precaution: don't allow any CC info.
205
		unset( $query['card_number'] );
206
		unset( $query['card_cvc'] );
207
208
	} else {
209
		// No $url_data so pass empty array.
210
		$query = array();
211
	}
212
213
	$new_query        = array_merge( $args, $query );
214
	$new_query_string = http_build_query( $new_query );
215
216
	// Assemble URL parts.
217
	$redirect = home_url( '/' . $url_data['path'] . '?' . $new_query_string . '#give-form-' . $form_id . '-wrap' );
218
219
	// Redirect them.
220
	wp_safe_redirect( apply_filters( 'give_send_back_to_checkout', $redirect, $args ) );
221
	give_die();
222
223
}
224
225
/**
226
 * Get Success Page URL
227
 *
228
 * Gets the success page URL.
229
 *
230
 * @param string $query_string
231
 *
232
 * @access      public
233
 * @since       1.0
234
 * @return      string
235
 */
236
function give_get_success_page_url( $query_string = null ) {
237
238
	$success_page = give_get_option( 'success_page', 0 );
239
	$success_page = get_permalink( $success_page );
240
241
	if ( $query_string ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $query_string of type string|null is loosely compared to true; this is ambiguous if the string can be empty. 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 string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
242
		$success_page .= $query_string;
243
	}
244
245
	return apply_filters( 'give_success_page_url', $success_page );
246
247
}
248
249
/**
250
 * Get the URL of the Failed Donation Page.
251
 *
252
 * @since 1.0
253
 *
254
 * @param bool $extras Extras to append to the URL.
255
 *
256
 * @return mixed Full URL to the Failed Donation Page, if present, home page if it doesn't exist.
257
 */
258
function give_get_failed_transaction_uri( $extras = false ) {
259
	$give_options = give_get_settings();
260
261
	// Remove question mark.
262
	if ( 0 === strpos( $extras, '?' ) ) {
263
		$extras = substr( $extras, 1 );
264
	}
265
266
	$extras_args = wp_parse_args( $extras );
267
268
	// Set nonce if payment id exist in extra params.
269
	if ( array_key_exists( 'payment-id', $extras_args ) ) {
270
		$extras_args['_wpnonce'] = wp_create_nonce( "give-failed-donation-{$extras_args['payment-id']}" );
271
		$extras                  = http_build_query( $extras_args );
272
	}
273
274
	$uri = ! empty( $give_options['failure_page'] ) ?
275
		trailingslashit( get_permalink( $give_options['failure_page'] ) ) :
276
		home_url();
277
0 ignored issues
show
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
278
279
	if ( $extras ) {
280
		$uri .= "?{$extras}";
281
	}
282
283
	return apply_filters( 'give_get_failed_transaction_uri', $uri );
284
}
285
286
/**
287
 * Determines if we're currently on the Failed Donation Page.
288
 *
289
 * @since 1.0
290
 * @return bool True if on the Failed Donation Page, false otherwise.
291
 */
292
function give_is_failed_transaction_page() {
293
	$give_options = give_get_settings();
294
	$ret          = isset( $give_options['failure_page'] ) ? is_page( $give_options['failure_page'] ) : false;
295
296
	return apply_filters( 'give_is_failure_page', $ret );
297
}
298
299
/**
300
 * Mark payments as Failed when returning to the Failed Donation Page
301
 *
302
 * @since  1.0
303
 * @since  1.8.16 Add security check
304
 *
305
 * @return bool
306
 */
307
function give_listen_for_failed_payments() {
308
309
	$failed_page = give_get_option( 'failure_page', 0 );
310
	$payment_id  = ! empty( $_GET['payment-id'] ) ? absint( $_GET['payment-id'] ) : 0;
0 ignored issues
show
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
311
	$nonce       = ! empty( $_GET['_wpnonce'] ) ? give_clean( $_GET['_wpnonce'] ) : false;
0 ignored issues
show
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
Detected usage of a non-sanitized input variable: $_GET
Loading history...
312
313
	// Bailout.
314
	if ( ! $failed_page || ! is_page( $failed_page ) || ! $payment_id || ! $nonce ) {
315
		return false;
316
	}
317
318
	// Security check.
319
	if ( ! wp_verify_nonce( $nonce, "give-failed-donation-{$payment_id}" ) ) {
320
		wp_die( __( 'Nonce verification failed.', 'give' ), __( 'Error', 'give' ) );
321
	}
322
323
	// Set payment status to failure
324
	give_update_payment_status( $payment_id, 'failed' );
325
}
326
327
add_action( 'template_redirect', 'give_listen_for_failed_payments' );
328
329
/**
330
 * Retrieve the Donation History page URI
331
 *
332
 * @access      public
333
 * @since       1.7
334
 *
335
 * @return      string
336
 */
337
function give_get_history_page_uri() {
338
	$give_options = give_get_settings();
339
340
	$history_page = isset( $give_options['history_page'] ) ? get_permalink( absint( $give_options['history_page'] ) ) : get_bloginfo( 'url' );
341
342
	return apply_filters( 'give_get_history_page_uri', $history_page );
343
}
344
345
/**
346
 * Determines if we're currently on the History page.
347
 *
348
 * @since 1.0
349
 *
350
 * @return bool True if on the History page, false otherwise.
351
 */
352 View Code Duplication
function give_is_history_page() {
0 ignored issues
show
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
353
	$give_options = give_get_settings();
354
355
	$history_page = isset( $give_options['history_page'] ) ? absint( $give_options['history_page'] ) : 0;
356
357
	return apply_filters( 'give_is_history_page', is_page( $history_page ) );
358
}
359
360
/**
361
 * Check if a field is required
362
 *
363
 * @param string $field
364
 * @param int    $form_id
365
 *
366
 * @access      public
367
 * @since       1.0
368
 * @return      bool
369
 */
370
function give_field_is_required( $field, $form_id ) {
371
372
	$required_fields = give_get_required_fields( $form_id );
373
374
	return array_key_exists( $field, $required_fields );
375
}
376
377
/**
378
 * Record Donation In Log
379
 *
380
 * Stores log information for a donation.
381
 *
382
 * @since 1.0
383
 *
384
 * @param int         $give_form_id  Give Form ID.
385
 * @param int         $payment_id    Payment ID.
386
 * @param bool|int    $price_id      Price ID, if any.
387
 * @param string|null $donation_date The date of the donation.
388
 *
389
 * @return void
390
 */
391
function give_record_donation_in_log( $give_form_id = 0, $payment_id, $price_id = false, $donation_date = null ) {
392
	$log_data = array(
393
		'log_parent'   => $payment_id,
394
		'log_type'     => 'sale',
395
		'log_date'     => isset( $donation_date ) ? $donation_date : null,
396
		'log_date_gmt' => isset( $donation_date ) ? $donation_date : null,
397
	);
398
399
	$log_meta = array(
400
		'form_id'  => $give_form_id,
401
		'price_id' => (int) $price_id,
402
	);
403
404
	Give()->logs->insert_log( $log_data, $log_meta );
405
}
406
407
408
/**
409
 * Increases the donation total count of a donation form.
410
 *
411
 * @since 1.0
412
 *
413
 * @param int $form_id  Give Form ID
414
 * @param int $quantity Quantity to increase donation count by
415
 *
416
 * @return bool|int
417
 */
418
function give_increase_donation_count( $form_id = 0, $quantity = 1 ) {
419
	$quantity = (int) $quantity;
420
421
	/** @var \Give_Donate_Form $form */
422
	$form = new Give_Donate_Form( $form_id );
423
424
	return $form->increase_sales( $quantity );
425
}
426
427
/**
428
 * Update the goal progress count of a donation form.
429
 *
430
 * @since 2.4.0
431
 *
432
 * @param int $form_id Give Form ID
433
 *
434
 * @return void
435
 */
436
function give_update_goal_progress( $form_id = 0 ) {
437
438
	//Get goal option meta key
439
	$is_goal_enabled = give_is_setting_enabled( give_get_meta( $form_id, '_give_goal_option', true, 'disabled' ) );
0 ignored issues
show
'disabled' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
440
441
	// Check, if the form goal is enabled.
442
	if ( $is_goal_enabled ) {
443
		$goal_stats               = give_goal_progress_stats( $form_id );
444
		$form_goal_progress_value = ! empty( $goal_stats['progress'] ) ? $goal_stats['progress'] : 0;
445
	} else {
446
		$form_goal_progress_value = -1;
447
	}
448
449
	give_update_meta( $form_id, '_give_form_goal_progress', $form_goal_progress_value );
450
}
451
452
/**
453
 * Decreases the sale count of a form. Primarily for when a donation is refunded.
454
 *
455
 * @since 1.0
456
 *
457
 * @param int $form_id  Give Form ID
458
 * @param int $quantity Quantity to increase donation count by
459
 *
460
 * @return bool|int
461
 */
462
function give_decrease_donation_count( $form_id = 0, $quantity = 1 ) {
463
	$quantity = (int) $quantity;
464
465
	/** @var \Give_Donate_Form $form */
466
	$form = new Give_Donate_Form( $form_id );
467
468
	return $form->decrease_sales( $quantity );
469
}
470
471
/**
472
 * Increases the total earnings of a form.
473
 *
474
 * @since 1.0
475
 *
476
 * @since 2.1 Pass donation id.
477
 *
478
 * @param int $give_form_id Give Form ID
479
 * @param int $amount       Earnings
480
 * @param int $payment_id   Donation ID.
481
 *
482
 * @return bool|int
483
 */
484
function give_increase_earnings( $give_form_id = 0, $amount, $payment_id = 0 ) {
485
	/** @var \Give_Donate_Form $form */
486
	$form = new Give_Donate_Form( $give_form_id );
487
488
	return $form->increase_earnings( $amount, $payment_id );
489
}
490
491
/**
492
 * Decreases the total earnings of a form.
493
 *
494
 * Primarily for when a donation is refunded.
495
 *
496
 * @since 1.0
497
 *
498
 * @since 2.1 Pass donation id.
499
 *
500
 * @param int $form_id    Give Form ID
501
 * @param int $amount     Earnings
502
 * @param int $payment_id Donation ID.
503
 *
504
 * @return bool|int
505
 */
506
function give_decrease_form_earnings( $form_id = 0, $amount, $payment_id = 0 ) {
507
	/** @var \Give_Donate_Form $form */
508
	$form = new Give_Donate_Form( $form_id );
509
510
	return $form->decrease_earnings( $amount, $payment_id );
511
}
512
513
514
/**
515
 * Returns the total earnings for a form.
516
 *
517
 * @since 1.0
518
 *
519
 * @param int $form_id Give Form ID
520
 *
521
 * @return int $earnings Earnings for a certain form
522
 */
523
function give_get_form_earnings_stats( $form_id = 0 ) {
524
	$give_form = new Give_Donate_Form( $form_id );
525
526
	/**
527
	 * Filter the form earnings
528
	 *
529
	 * @since 1.8.17
530
	 */
531
	return apply_filters( 'give_get_form_earnings_stats', $give_form->earnings, $form_id, $give_form );
532
}
533
534
535
/**
536
 * Return the sales number for a form.
537
 *
538
 * @since 1.0
539
 *
540
 * @param int $give_form_id Give Form ID
541
 *
542
 * @return int $sales Amount of sales for a certain form
543
 */
544
function give_get_form_sales_stats( $give_form_id = 0 ) {
545
	$give_form = new Give_Donate_Form( $give_form_id );
546
547
	return $give_form->sales;
548
}
549
550
551
/**
552
 * Retrieves the average monthly sales for a specific donation form
553
 *
554
 * @since 1.0
555
 *
556
 * @param int $form_id Form ID
557
 *
558
 * @return float $sales Average monthly sales
559
 */
560 View Code Duplication
function give_get_average_monthly_form_sales( $form_id = 0 ) {
0 ignored issues
show
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
561
	$sales        = give_get_form_sales_stats( $form_id );
562
	$release_date = get_post_field( 'post_date', $form_id );
563
564
	$diff = abs( current_time( 'timestamp' ) - strtotime( $release_date ) );
565
566
	$months = floor( $diff / ( 30 * 60 * 60 * 24 ) ); // Number of months since publication
567
568
	if ( $months > 0 ) {
569
		$sales = ( $sales / $months );
570
	}
571
572
	return $sales;
573
}
574
575
576
/**
577
 * Retrieves the average monthly earnings for a specific form
578
 *
579
 * @since 1.0
580
 *
581
 * @param int $form_id Form ID
582
 *
583
 * @return float $earnings Average monthly earnings
584
 */
585 View Code Duplication
function give_get_average_monthly_form_earnings( $form_id = 0 ) {
0 ignored issues
show
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
586
	$earnings     = give_get_form_earnings_stats( $form_id );
587
	$release_date = get_post_field( 'post_date', $form_id );
588
589
	$diff = abs( current_time( 'timestamp' ) - strtotime( $release_date ) );
590
591
	$months = floor( $diff / ( 30 * 60 * 60 * 24 ) ); // Number of months since publication
592
593
	if ( $months > 0 ) {
594
		$earnings = ( $earnings / $months );
595
	}
596
597
	return $earnings < 0 ? 0 : $earnings;
598
}
599
600
601
/**
602
 * Get Price Option Name (Text)
603
 *
604
 * Retrieves the name of a variable price option.
605
 *
606
 * @since       1.0
607
 *
608
 * @param int  $form_id      ID of the donation form.
609
 * @param int  $price_id     ID of the price option.
610
 * @param int  $payment_id   payment ID for use in filters ( optional ).
611
 * @param bool $use_fallback Outputs the level amount if no level text is provided.
612
 *
613
 * @return string $price_name Name of the price option
614
 */
615
function give_get_price_option_name( $form_id = 0, $price_id = 0, $payment_id = 0, $use_fallback = true ) {
616
617
	$prices     = give_get_variable_prices( $form_id );
618
	$price_name = '';
619
620
	if ( false === $prices ) {
621
		return $price_name;
622
	}
623
624
	foreach ( $prices as $price ) {
625
626
		if ( intval( $price['_give_id']['level_id'] ) === intval( $price_id ) ) {
627
628
			$price_text     = isset( $price['_give_text'] ) ? $price['_give_text'] : '';
629
			$price_fallback = $use_fallback ?
630
				give_currency_filter(
631
					give_format_amount(
632
						$price['_give_amount'],
633
						array( 'sanitize' => false )
634
					),
635
					array( 'decode_currency' => true )
636
				) : '';
637
			$price_name     = ! empty( $price_text ) ? $price_text : $price_fallback;
638
639
		}
640
	}
641
642
	return apply_filters( 'give_get_price_option_name', $price_name, $form_id, $payment_id, $price_id );
643
}
644
645
646
/**
647
 * Retrieves a price from from low to high of a variable priced form
648
 *
649
 * @since 1.0
650
 *
651
 * @param int  $form_id   ID of the form
652
 * @param bool $formatted Flag to decide which type of price range string return
653
 *
654
 * @return string $range A fully formatted price range
655
 */
656
function give_price_range( $form_id = 0, $formatted = true ) {
657
	$low        = give_get_lowest_price_option( $form_id );
658
	$high       = give_get_highest_price_option( $form_id );
659
	$order_type = ! empty( $_REQUEST['order'] ) ? $_REQUEST['order'] : 'asc';
0 ignored issues
show
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
660
661
	$range = sprintf(
662
		'<span class="give_price_range_%1$s">%2$s</span><span class="give_price_range_sep">&nbsp;&ndash;&nbsp;</span><span class="give_price_range_%3$s">%4$s</span>',
663
		'asc' === $order_type ? 'low' : 'high',
664
		'asc' === $order_type ? give_currency_filter( give_format_amount( $low, array( 'sanitize' => false ) ) ) : give_currency_filter( give_format_amount( $high, array( 'sanitize' => false ) ) ),
665
		'asc' === $order_type ? 'high' : 'low',
666
		'asc' === $order_type ? give_currency_filter( give_format_amount( $high, array( 'sanitize' => false ) ) ) : give_currency_filter( give_format_amount( $low, array( 'sanitize' => false ) ) )
667
0 ignored issues
show
There should be no empty lines in a multi-line function call.
Loading history...
668
	);
669
670
	if ( ! $formatted ) {
671
		$range = wp_strip_all_tags( $range );
672
	}
673
674
	return apply_filters( 'give_price_range', $range, $form_id, $low, $high );
675
}
676
677
678
/**
679
 * Get Lowest Price ID
680
 *
681
 * Retrieves the ID for the cheapest price option of a variable donation form
682
 *
683
 * @since 1.5
684
 *
685
 * @param int $form_id ID of the donation
686
 *
687
 * @return int ID of the lowest price
688
 */
689
function give_get_lowest_price_id( $form_id = 0 ) {
690
691
	if ( empty( $form_id ) ) {
692
		$form_id = get_the_ID();
693
	}
694
695
	if ( ! give_has_variable_prices( $form_id ) ) {
696
		return give_get_form_price( $form_id );
697
	}
698
699
	$prices = give_get_variable_prices( $form_id );
700
701
	$min = $min_id = 0;
702
703
	if ( ! empty( $prices ) ) {
704
705
		foreach ( $prices as $key => $price ) {
706
707
			if ( empty( $price['_give_amount'] ) ) {
708
				continue;
709
			}
710
711
			if ( ! isset( $min ) ) {
712
				$min = $price['_give_amount'];
713
			} else {
714
				$min = min( $min, $price['_give_amount'] );
715
			}
716
717
			if ( $price['_give_amount'] == $min ) {
718
				$min_id = $price['_give_id']['level_id'];
719
			}
720
		}
721
	}
722
723
	return (int) $min_id;
724
}
725
726
/**
727
 * Retrieves cheapest price option of a variable priced form
728
 *
729
 * @since 1.0
730
 *
731
 * @param int $form_id ID of the form
732
 *
733
 * @return float Amount of the lowest price
734
 */
735 View Code Duplication
function give_get_lowest_price_option( $form_id = 0 ) {
0 ignored issues
show
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
736
	if ( empty( $form_id ) ) {
737
		$form_id = get_the_ID();
738
	}
739
740
	if ( ! give_has_variable_prices( $form_id ) ) {
741
		return give_get_form_price( $form_id );
742
	}
743
744
	if ( ! ( $low = get_post_meta( $form_id, '_give_levels_minimum_amount', true ) ) ) {
745
		// Backward compatibility.
746
		$prices = wp_list_pluck( give_get_variable_prices( $form_id ), '_give_amount' );
747
		$low    = ! empty( $prices ) ? min( $prices ) : 0;
748
	}
749
750
	return give_maybe_sanitize_amount( $low );
751
}
752
753
/**
754
 * Retrieves most expensive price option of a variable priced form
755
 *
756
 * @since 1.0
757
 *
758
 * @param int $form_id ID of the form
759
 *
760
 * @return float Amount of the highest price
761
 */
762 View Code Duplication
function give_get_highest_price_option( $form_id = 0 ) {
0 ignored issues
show
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
763
764
	if ( empty( $form_id ) ) {
765
		$form_id = get_the_ID();
766
	}
767
768
	if ( ! give_has_variable_prices( $form_id ) ) {
769
		return give_get_form_price( $form_id );
770
	}
771
772
	if ( ! ( $high = get_post_meta( $form_id, '_give_levels_maximum_amount', true ) ) ) {
773
		// Backward compatibility.
774
		$prices = wp_list_pluck( give_get_variable_prices( $form_id ), '_give_amount' );
775
		$high   = ! empty( $prices ) ? max( $prices ) : 0;
776
	}
777
778
	return give_maybe_sanitize_amount( $high );
779
}
780
781
/**
782
 * Returns the price of a form, but only for non-variable priced forms.
783
 *
784
 * @since 1.0
785
 *
786
 * @param int $form_id ID number of the form to retrieve a price for
787
 *
788
 * @return mixed string|int Price of the form
789
 */
790
function give_get_form_price( $form_id = 0 ) {
791
792
	if ( empty( $form_id ) ) {
793
		return false;
794
	}
795
796
	$form = new Give_Donate_Form( $form_id );
797
798
	return $form->__get( 'price' );
799
}
800
801
/**
802
 * Returns the minimum price amount of a form, only enforced for the custom amount input.
803
 *
804
 * @since 1.3.6
805
 *
806
 * @param int $form_id ID number of the form to retrieve the minimum price for
807
 *
808
 * @return mixed string|int Minimum price of the form
809
 */
810
function give_get_form_minimum_price( $form_id = 0 ) {
811
812
	if ( empty( $form_id ) ) {
813
		return false;
814
	}
815
816
	$form = new Give_Donate_Form( $form_id );
817
818
	return $form->get_minimum_price();
819
820
}
821
822
/**
823
 * Return the maximum price amount of form.
824
 *
825
 * @since 2.1
826
 *
827
 * @param int $form_id Donate Form ID
828
 *
829
 * @return bool|float
830
 */
831
function give_get_form_maximum_price( $form_id = 0 ) {
832
833
	if ( empty( $form_id ) ) {
834
		return false;
835
	}
836
837
	$form = new Give_Donate_Form( $form_id );
838
839
	return $form->get_maximum_price();
840
}
841
842
/**
843
 * Displays a formatted price for a donation form
844
 *
845
 * @since 1.0
846
 *
847
 * @param int      $form_id  ID of the form price to show
848
 * @param bool     $echo     Whether to echo or return the results
849
 * @param bool|int $price_id Optional price id for variable pricing
850
 *
851
 * @return int $formatted_price
852
 */
853
function give_price( $form_id = 0, $echo = true, $price_id = false ) {
854
	$price = 0;
855
856
	if ( empty( $form_id ) ) {
857
		$form_id = get_the_ID();
858
	}
859
860
	if ( give_has_variable_prices( $form_id ) ) {
861
862
		$prices = give_get_variable_prices( $form_id );
863
864
		if ( false !== $price_id ) {
865
866
			// loop through multi-prices to see which is default
867
			foreach ( $prices as $price ) {
0 ignored issues
show
The expression $prices of type false|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
868
				// this is the default price
869
				if ( isset( $price['_give_default'] ) && $price['_give_default'] === 'default' ) {
0 ignored issues
show
Found "=== '". Use Yoda Condition checks, you must
Loading history...
870
					$price = (float) $price['_give_amount'];
871
				};
872
			}
873
		} else {
874
875
			$price = give_get_lowest_price_option( $form_id );
876
		}
877
	} else {
878
879
		$price = give_get_form_price( $form_id );
880
	}
881
882
	$price           = apply_filters( 'give_form_price', give_maybe_sanitize_amount( $price ), $form_id );
883
	$formatted_price = '<span class="give_price" id="give_price_' . $form_id . '">' . $price . '</span>';
884
	$formatted_price = apply_filters( 'give_form_price_after_html', $formatted_price, $form_id, $price );
885
886
	if ( $echo ) {
887
		echo $formatted_price;
0 ignored issues
show
Expected next thing to be a escaping function, not '$formatted_price'
Loading history...
888
	} else {
889
		return $formatted_price;
890
	}
891
}
892
893
add_filter( 'give_form_price', 'give_format_amount', 10 );
894
add_filter( 'give_form_price', 'give_currency_filter', 20 );
895
896
897
/**
898
 * Retrieves the amount of a variable price option
899
 *
900
 * @since 1.0
901
 *
902
 * @param int $form_id  ID of the form
903
 * @param int $price_id ID of the price option
904
 *
905
 * @return float $amount Amount of the price option
906
 */
907
function give_get_price_option_amount( $form_id = 0, $price_id = 0 ) {
908
	$prices = give_get_variable_prices( $form_id );
909
910
	$amount = 0.00;
911
912 View Code Duplication
	foreach ( $prices as $price ) {
0 ignored issues
show
The expression $prices of type false|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
913
		if ( isset( $price['_give_id']['level_id'] ) && $price['_give_id']['level_id'] == $price_id ) {
914
			$amount = isset( $price['_give_amount'] ) ? $price['_give_amount'] : 0.00;
915
			break;
916
		};
917
	}
918
919
	return apply_filters( 'give_get_price_option_amount', give_maybe_sanitize_amount( $amount ), $form_id, $price_id );
920
}
921
922
/**
923
 * Returns the goal of a form
924
 *
925
 * @since 1.0
926
 *
927
 * @param int $form_id ID number of the form to retrieve a goal for
928
 *
929
 * @return mixed string|int Goal of the form
930
 */
931
function give_get_form_goal( $form_id = 0 ) {
932
933
	if ( empty( $form_id ) ) {
934
		return false;
935
	}
936
937
	$form = new Give_Donate_Form( $form_id );
938
939
	return $form->goal;
940
941
}
942
943
/**
944
 * Returns the goal format of a form
945
 *
946
 * @since 2.0
947
 *
948
 * @param int $form_id ID number of the form to retrieve a goal for
949
 *
950
 * @return mixed string|int Goal of the form
951
 */
952
function give_get_form_goal_format( $form_id = 0 ) {
953
954
	if ( empty( $form_id ) ) {
955
		return false;
956
	}
957
958
	return give_get_meta( $form_id, '_give_goal_format', true );
959
960
}
961
962
/**
963
 * Display/Return a formatted goal for a donation form
964
 *
965
 * @since 1.0
966
 *
967
 * @param int  $form_id ID of the form price to show
968
 * @param bool $echo    Whether to echo or return the results
969
 *
970
 * @return string $formatted_goal
971
 */
972
function give_goal( $form_id = 0, $echo = true ) {
973
974
	if ( empty( $form_id ) ) {
975
		$form_id = get_the_ID();
976
	}
977
978
	$goal        = give_get_form_goal( $form_id );
979
	$goal_format = give_get_form_goal_format( $form_id );
980
981
	if ( 'donation' === $goal_format ) {
982
		$goal = "{$goal} donations";
983
	} else {
984
		$goal = apply_filters( 'give_form_goal', give_maybe_sanitize_amount( $goal ), $form_id );
985
	}
986
987
	$formatted_goal = sprintf(
988
		'<span class="give_price" id="give_price_%1$s">%2$s</span>',
989
		$form_id,
990
		$goal
991
	);
992
	$formatted_goal = apply_filters( 'give_form_price_after_html', $formatted_goal, $form_id, $goal );
993
994
	if ( $echo ) {
995
		echo $formatted_goal;
0 ignored issues
show
Expected next thing to be a escaping function, not '$formatted_goal'
Loading history...
996
	} else {
997
		return $formatted_goal;
998
	}
999
}
1000
1001
add_filter( 'give_form_goal', 'give_format_amount', 10 );
1002
add_filter( 'give_form_goal', 'give_currency_filter', 20 );
1003
1004
1005
/**
1006
 * Checks if users can only donate when logged in
1007
 *
1008
 * @since  1.0
1009
 *
1010
 * @param  int $form_id Give form ID
1011
 *
1012
 * @return bool  $ret Whether or not the logged_in_only setting is set
1013
 */
1014 View Code Duplication
function give_logged_in_only( $form_id ) {
0 ignored issues
show
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1015
	// If _give_logged_in_only is set to enable then guest can donate from that specific form.
1016
	// Otherwise it is member only donation form.
1017
	$val = give_get_meta( $form_id, '_give_logged_in_only', true );
1018
	$val = ! empty( $val ) ? $val : 'enabled';
1019
1020
	$ret = ! give_is_setting_enabled( $val );
1021
1022
	return (bool) apply_filters( 'give_logged_in_only', $ret, $form_id );
1023
}
1024
1025
1026
/**
1027
 * Checks the option for the "Register / Login Option"
1028
 *
1029
 * @since 1.4.1
1030
 *
1031
 * @param int $form_id
1032
 *
1033
 * @return string
1034
 */
1035
function give_show_login_register_option( $form_id ) {
1036
1037
	$show_register_form = give_get_meta( $form_id, '_give_show_register_form', true );
1038
1039
	return apply_filters( 'give_show_register_form', $show_register_form, $form_id );
1040
1041
}
1042
1043
1044
/**
1045
 * Get pre fill form field values.
1046
 *
1047
 * Note: this function will extract form field values from give_purchase session data.
1048
 *
1049
 * @since  1.8
1050
 *
1051
 * @param  int $form_id Form ID.
1052
 *
1053
 * @return array
1054
 */
1055
function _give_get_prefill_form_field_values( $form_id ) {
1056
	$logged_in_donor_info = array();
1057
1058
	if ( is_user_logged_in() ) :
1059
		$donor_data    = get_userdata( get_current_user_id() );
1060
		$donor         = new Give_Donor( get_current_user_id(), true );
1061
		$donor_address = $donor->get_donor_address();
1062
		$company_name  = $donor->get_company_name();
1063
1064
		$logged_in_donor_info = array(
1065
			// First name.
1066
			'give_first'      => $donor_data->first_name,
1067
1068
			// Last name.
1069
			'give_last'       => $donor_data->last_name,
1070
1071
			// Title Prefix.
1072
			'give_title'      => $donor->get_meta( '_give_donor_title_prefix', true ),
1073
1074
			// Company name.
1075
			'company_name'    => $company_name,
1076
1077
			// Email.
1078
			'give_email'      => $donor_data->user_email,
1079
1080
			// Street address 1.
1081
			'card_address'    => $donor_address['line1'],
1082
1083
			// Street address 2.
1084
			'card_address_2'  => $donor_address['line2'],
1085
1086
			// Country.
1087
			'billing_country' => $donor_address['country'],
1088
1089
			// State.
1090
			'card_state'      => $donor_address['state'],
1091
1092
			// City.
1093
			'card_city'       => $donor_address['city'],
1094
1095
			// Zipcode
1096
			'card_zip'        => $donor_address['zip'],
1097
		);
1098
	endif;
1099
1100
	// Bailout: Auto fill form field values only form form which donor is donating.
1101
	if (
1102
		empty( $_GET['form-id'] )
0 ignored issues
show
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
1103
		|| ! $form_id
1104
		|| ( $form_id !== absint( $_GET['form-id'] ) )
0 ignored issues
show
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
1105
	) {
1106
		return $logged_in_donor_info;
1107
	}
1108
1109
	// Get purchase data.
1110
	$give_purchase_data = Give()->session->get( 'give_purchase' );
1111
1112
	// Get donor info from form data.
1113
	$give_donor_info_in_session = empty( $give_purchase_data['post_data'] )
1114
		? array()
1115
		: $give_purchase_data['post_data'];
1116
1117
	// Output.
1118
	return wp_parse_args( $give_donor_info_in_session, $logged_in_donor_info );
1119
}
1120
1121
/**
1122
 * Get donor count of form
1123
 *
1124
 * @since 2.1.0
1125
 *
1126
 * @param int   $form_id
1127
 * @param array $args
1128
 *
1129
 * @return int
1130
 */
1131
function give_get_form_donor_count( $form_id, $args = array() ) {
1132
	global $wpdb;
1133
1134
	$cache_key   = Give_Cache::get_key( "form_donor_count_{$form_id}", $args, false );
1135
	$donor_count = absint( Give_Cache::get_db_query( $cache_key ) );
1136
1137
	if ( $form_id && ! $donor_count ) {
1138
		// Set arguments.
1139
		$args = wp_parse_args(
1140
			$args,
1141
			array(
1142
				'unique' => true,
1143
			)
1144
		);
1145
1146
		$donation_meta_table  = Give()->payment_meta->table_name;
1147
		$donation_id_col_name = Give()->payment_meta->get_meta_type() . '_id';
1148
1149
		$distinct = $args['unique'] ? 'DISTINCT meta_value' : 'meta_value';
1150
1151
		$query = $wpdb->prepare(
1152
			"
1153
			SELECT COUNT({$distinct})
1154
			FROM {$donation_meta_table}
1155
			WHERE meta_key=%s
1156
			AND {$donation_id_col_name} IN(
1157
				SELECT {$donation_id_col_name}
1158
				FROM {$donation_meta_table} as pm
1159
				INNER JOIN {$wpdb->posts} as p
1160
				ON pm.{$donation_id_col_name}=p.ID
1161
				WHERE pm.meta_key=%s
1162
				AND pm.meta_value=%s
1163
				AND p.post_status=%s
1164
			)
1165
			",
1166
			'_give_payment_donor_id',
1167
			'_give_payment_form_id',
1168
			$form_id,
1169
			'publish'
1170
		);
1171
1172
		$donor_count = absint( $wpdb->get_var( $query ) );
0 ignored issues
show
Usage of a direct database call is discouraged.
Loading history...
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
1173
	}
1174
0 ignored issues
show
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
1175
1176
	/**
1177
	 * Filter the donor count
1178
	 *
1179
	 * @since 2.1.0
1180
	 */
1181
	$donor_count = apply_filters( 'give_get_form_donor_count', $donor_count, $form_id, $args );
1182
1183
	return $donor_count;
1184
}
1185
1186
/**
1187
 * Verify the form status.
1188
 *
1189
 * @param int $form_id Donation Form ID.
1190
 *
1191
 * @since 2.1
1192
 *
1193
 * @return void
1194
 */
1195
function give_set_form_closed_status( $form_id ) {
1196
1197
	// Bailout.
1198
	if ( empty( $form_id ) ) {
1199
		return;
1200
	}
1201
1202
	$open_form       = false;
1203
	$is_goal_enabled = give_is_setting_enabled( give_get_meta( $form_id, '_give_goal_option', true, 'disabled' ) );
0 ignored issues
show
'disabled' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1204
1205
	// Proceed, if the form goal is enabled.
1206
	if ( $is_goal_enabled ) {
1207
1208
		$close_form_when_goal_achieved = give_is_setting_enabled( give_get_meta( $form_id, '_give_close_form_when_goal_achieved', true, 'disabled' ) );
0 ignored issues
show
'disabled' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1209
1210
		// Proceed, if close form when goal achieved option is enabled.
1211
		if ( $close_form_when_goal_achieved ) {
1212
1213
			$form                = new Give_Donate_Form( $form_id );
1214
			$goal_progress_stats = give_goal_progress_stats( $form );
1215
1216
			// Verify whether the form is closed or not after processing data.
1217
			$closed = $goal_progress_stats['raw_goal'] <= $goal_progress_stats['raw_actual'];
1218
1219
			// Update form meta if verified that the form is closed.
1220
			if ( $closed ) {
1221
				give_update_meta( $form_id, '_give_form_status', 'closed' );
1222
			} else {
1223
				$open_form = true;
1224
			}
1225
		} else {
1226
			$open_form = true;
1227
		}
1228
	} else {
1229
		$open_form = true;
1230
	}
1231
1232
	// If $open_form is true, then update form status to open.
1233
	if ( $open_form ) {
1234
		give_update_meta( $form_id, '_give_form_status', 'open' );
1235
	}
1236
}
1237
1238
/**
1239
 * Show Form Goal Stats in Admin ( Listing and Detail page )
1240
 *
1241
 * @param int $form_id Form ID.
1242
 *
1243
 * @since 2.1.0
1244
 *
1245
 * @return string
1246
 */
1247
function give_admin_form_goal_stats( $form_id ) {
1248
1249
	$html             = '';
1250
	$goal_stats       = give_goal_progress_stats( $form_id );
1251
	$percent_complete = round( ( $goal_stats['raw_actual'] / $goal_stats['raw_goal'] ), 3 ) * 100;
1252
1253
	$html .= sprintf(
1254
		'<div class="give-admin-progress-bar" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="%1$s">
1255
<span style="width:%1$s%%;"></span>
1256
</div>',
1257
		esc_attr( $goal_stats['progress'] )
1258
	);
1259
1260
	$html .= sprintf(
1261
		( 'percentage' !== $goal_stats['format'] ) ?
1262
			'<div class="give-goal-text"><span>%1$s</span> %2$s <a href="%3$s">%4$s</a> %5$s ' :
1263
			'<div class="give-goal-text"><a href="%3$s">%1$s </a>',
1264
		( 'percentage' !== $goal_stats['format'] ) ? $goal_stats['actual'] : $percent_complete . '%',
1265
		( 'percentage' !== $goal_stats['format'] ) ? __( 'of', 'give' ) : '',
1266
		esc_url( admin_url( "post.php?post={$form_id}&action=edit&give_tab=donation_goal_options" ) ),
1267
		$goal_stats['goal'],
1268
		( 'donors' === $goal_stats['format'] ? __( 'Donors', 'give' ) : ( 'donation' === $goal_stats['format'] ? __( 'Donations', 'give' ) : '' ) )
1269
	);
1270
1271
	if ( $goal_stats['raw_actual'] >= $goal_stats['raw_goal'] ) {
1272
		$html .= sprintf( '<span class="give-admin-goal-achieved"><span class="dashicons dashicons-star-filled"></span> %s</span>', __( 'Goal achieved', 'give' ) );
1273
	}
1274
1275
	$html .= '</div>';
1276
0 ignored issues
show
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
1277
1278
	return $html;
1279
}
1280
1281
/**
1282
 * Get the default donation form's level id.
1283
 *
1284
 * @since 2.2.0
1285
 *
1286
 * @param integer $form_id Donation Form ID.
1287
 *
1288
 * @return null | array
1289
 */
1290
function give_form_get_default_level( $form_id ) {
1291
	$default_level = null;
1292
1293
	// If donation form has variable prices.
1294
	if ( give_has_variable_prices( $form_id ) ) {
1295
		/**
1296
		 * Filter the variable pricing
1297
		 *
1298
		 *
1299
		 * @since      1.0
1300
		 * @deprecated 2.2 Use give_get_donation_levels filter instead of give_form_variable_prices.
1301
		 *                 Check Give_Donate_Form::get_prices().
1302
		 *
1303
		 * @param array $prices Array of variable prices.
1304
		 * @param int   $form   Form ID.
1305
		 */
1306
		$prices = apply_filters( 'give_form_variable_prices', give_get_variable_prices( $form_id ), $form_id );
1307
1308
		// Go through each of the level and get the default level id.
1309
		foreach ( $prices as $level ) {
1310
			if (
0 ignored issues
show
Found "=== '". Use Yoda Condition checks, you must
Loading history...
1311
				isset( $level['_give_default'] )
1312
				&& $level['_give_default'] === 'default'
1313
			) {
1314
				$default_level = $level;
1315
			}
1316
		}
1317
	}
1318
1319
	/**
1320
	 * Filter the default donation level id.
1321
	 *
1322
	 * @since 2.2.0
1323
	 *
1324
	 * @param array   $default_level Default level price data.
1325
	 * @param integer $form_id       Donation form ID.
1326
	 */
1327
	return apply_filters( 'give_form_get_default_level', $default_level, $form_id );
1328
}
1329
1330
/**
1331
 * Get the default level id.
1332
 *
1333
 * @since 2.2.0
1334
 *
1335
 * @param array|integer   $price_or_level_id Price level data.
1336
 * @param boolean|integer $form_id           Donation Form ID.
1337
 *
1338
 * @return boolean
1339
 */
1340
function give_is_default_level_id( $price_or_level_id, $form_id = 0 ) {
1341
	$is_default = false;
1342
1343
	if (
1344
		! empty( $form_id )
1345
		&& is_numeric( $price_or_level_id )
1346
	) {
1347
		// Get default level id.
1348
		$form_price_data = give_form_get_default_level( $form_id );
0 ignored issues
show
Are you sure the assignment to $form_price_data is correct as give_form_get_default_level($form_id) (which targets give_form_get_default_level()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

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

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

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

Loading history...
1349
1350
		$is_default = ! is_null( $form_price_data ) && ( $price_or_level_id === absint( $form_price_data['_give_id']['level_id'] ) );
1351
	}
1352
1353
	$is_default = false === $is_default && is_array( $price_or_level_id ) ?
1354
		( isset( $price_or_level_id['_give_default'] ) && $price_or_level_id['_give_default'] === 'default' )
1355
		: $is_default;
1356
1357
	/**
1358
	 * Allow developers to modify the default level id checks.
1359
	 *
1360
	 * @since 2.2.0
1361
	 *
1362
	 * @param bool          $is_default        True if it is default price level id otherwise false.
1363
	 * @param array|integer $price_or_level_id Price Data.
1364
	 */
1365
	return apply_filters( 'give_is_default_level_id', $is_default, $price_or_level_id );
1366
}
1367
1368
1369
/**
1370
 * Get Name Title Prefixes (a.k.a. Salutation) value.
1371
 *
1372
 * @param int $form_id Donation Form ID.
1373
 *
1374
 * @since 2.2.0
1375
 *
1376
 * @return mixed
1377
 */
1378
function give_get_name_title_prefixes( $form_id = 0 ) {
1379
1380
	$name_title_prefix = give_is_name_title_prefix_enabled( $form_id );
1381
	$title_prefixes    = give_get_option( 'title_prefixes', give_get_default_title_prefixes() );
0 ignored issues
show
give_get_default_title_prefixes() is of type array, but the function expects a string|boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1382
1383
	// If form id exists, then fetch form specific title prefixes.
1384
	if ( intval( $form_id ) > 0 && $name_title_prefix ) {
1385
1386
		$form_title_prefix = give_get_meta( $form_id, '_give_name_title_prefix', true );
1387
		if ( 'global' !== $form_title_prefix ) {
1388
			$form_title_prefixes = give_get_meta( $form_id, '_give_title_prefixes', true, give_get_default_title_prefixes() );
0 ignored issues
show
give_get_default_title_prefixes() is of type array, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1389
1390
			// Check whether the form based title prefixes exists or not.
1391
			if ( is_array( $form_title_prefixes ) && count( $form_title_prefixes ) > 0 ) {
1392
				$title_prefixes = $form_title_prefixes;
1393
			}
1394
		}
1395
	}
1396
1397
	return $title_prefixes;
1398
}
1399
1400
/**
1401
 * Check whether the name title prefix is enabled or not.
1402
 *
1403
 * @param int    $form_id Donation Form ID.
1404
 * @param string $status  Status to set status based on option value.
1405
 *
1406
 * @since 2.2.0
1407
 *
1408
 * @return bool
1409
 */
1410
function give_is_name_title_prefix_enabled( $form_id = 0, $status = '' ) {
1411
	if ( empty( $status ) ) {
1412
		$status = array( 'required', 'optional' );
1413
	} else {
1414
		$status = array( $status );
1415
	}
1416
1417
	$title_prefix_status = give_is_setting_enabled( give_get_option( 'name_title_prefix' ), $status );
0 ignored issues
show
$status is of type array<integer,string,{"0":"string"}>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1418
1419
	if ( intval( $form_id ) > 0 ) {
1420
		$form_title_prefix = give_get_meta( $form_id, '_give_name_title_prefix', true );
1421
1422
		if ( 'disabled' === $form_title_prefix ) {
1423
			$title_prefix_status = false;
1424
		} elseif ( in_array( $form_title_prefix, $status, true ) ) {
1425
			$title_prefix_status = give_is_setting_enabled( $form_title_prefix, $status );
0 ignored issues
show
$status is of type array<integer,string,{"0":"string"}>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1426
		}
1427
	}
1428
1429
	return $title_prefix_status;
1430
1431
}
1432
1433
/**
1434
 * Get Donor Name with Title Prefix
1435
 *
1436
 * @param int|Give_Donor $donor Donor Information.
1437
 *
1438
 * @since 2.2.0
1439
 *
1440
 * @return object
1441
 */
1442
function give_get_name_with_title_prefixes( $donor ) {
1443
1444
	// Prepare Give_Donor object, if $donor is numeric.
1445
	if ( is_numeric( $donor ) ) {
1446
		$donor = new Give_Donor( $donor );
1447
	}
1448
1449
	$title_prefix = Give()->donor_meta->get_meta( $donor->id, '_give_donor_title_prefix', true );
1450
1451
	// Update Donor name, if non empty title prefix.
1452
	if ( ! empty( $title_prefix ) ) {
1453
		$donor->name = give_get_donor_name_with_title_prefixes( $title_prefix, $donor->name );
1454
	}
1455
1456
	return $donor;
1457
}
1458
1459
/**
1460
 * This function will generate donor name with title prefix if it is required.
1461
 *
1462
 * @param string $title_prefix Title Prefix of Donor
1463
 * @param string $name         Donor Name.
1464
 *
1465
 * @since 2.2.0
1466
 *
1467
 * @return string
1468
 */
1469
function give_get_donor_name_with_title_prefixes( $title_prefix, $name ) {
1470
1471
	$donor_name = $name;
1472
1473
	if ( ! empty( $title_prefix ) && ! empty( $name ) ) {
1474
		$donor_name = "{$title_prefix} {$name}";
1475
	}
1476
1477
	return trim( $donor_name );
1478
}
1479
1480
/**
1481
 * This function will fetch the default list of title prefixes.
1482
 *
1483
 * @since 2.2.0
1484
 *
1485
 * @return array
1486
 */
1487
function give_get_default_title_prefixes() {
1488
	/**
1489
	 * Filter the data
1490
	 * Set default title prefixes.
1491
	 *
1492
	 * @since 2.2.0
1493
	 */
1494
	return apply_filters(
1495
		'give_get_default_title_prefixes',
1496
		array(
1497
			'Mr.'  => __( 'Mr.', 'give' ),
1498
			'Mrs.' => __( 'Mrs.', 'give' ),
1499
			'Ms.'  => __( 'Ms.', 'give' ),
1500
		)
1501
	);
1502
}
1503
1504
/**
1505
 * This function will check whether the name title prefix field is required or not.
1506
 *
1507
 * @param int $form_id Donation Form ID.
1508
 *
1509
 * @since 2.2.0
1510
 *
1511
 * @return bool
1512
 */
1513
function give_is_name_title_prefix_required( $form_id = 0 ) {
1514
1515
	// Bail out, if name title prefix is not enabled.
1516
	if ( ! give_is_name_title_prefix_enabled( $form_id ) ) {
1517
		return false;
1518
	}
1519
1520
	$status      = array( 'optional' );
1521
	$is_optional = give_is_setting_enabled( give_get_option( 'name_title_prefix' ), $status );
0 ignored issues
show
$status is of type array<integer,string,{"0":"string"}>, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1522
1523
	if ( intval( $form_id ) > 0 ) {
1524
		$form_title_prefix = give_get_meta( $form_id, '_give_name_title_prefix', true );
1525
1526
		if ( 'required' === $form_title_prefix ) {
1527
			$is_optional = false;
1528
		} elseif ( 'optional' === $form_title_prefix ) {
1529
			$is_optional = true;
1530
		}
1531
	}
1532
1533
	return ( ! $is_optional );
1534
}
1535
1536
/**
1537
 * Deletes form meta when the form is permanently deleted from the trash.
1538
 *
1539
 * @since 2.3.0
1540
 *
1541
 * @param integer $id Donation Form ID which needs to be deleted.
1542
 *
1543
 * @return void
1544
 */
1545
function give_handle_form_meta_on_delete( $id ) {
1546
1547
	global $wpdb;
1548
1549
	$form     = get_post( $id );
1550
	$get_data = give_clean( $_GET );
0 ignored issues
show
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
1551
1552
	if (
1553
		'give_forms' === $form->post_type &&
1554
		'trash' === $form->post_status &&
1555
		(
1556
			( isset( $get_data['action'] ) && 'delete' === $get_data['action'] ) ||
1557
			! empty( $get_data['delete_all'] )
1558
		)
1559
	) {
1560
		$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->formmeta} WHERE form_id = '%d'", $form->ID ) );
0 ignored issues
show
Usage of a direct database call is discouraged.
Loading history...
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
1561
	}
1562
}
1563
1564
add_action( 'before_delete_post', 'give_handle_form_meta_on_delete', 10, 1 );
1565
1566
1567
/**
1568
 * Get list of default param of form shrtcode.
1569
 *
1570
 * @since 2.4.1
1571
 * @return array
1572
 */
1573
function give_get_default_form_shortcode_args() {
1574
	$default = array(
1575
		'id'                    => '',
1576
		'show_title'            => true,
1577
		'show_goal'             => true,
1578
		'show_content'          => '',
1579
		'float_labels'          => '',
1580
		'display_style'         => '',
1581
		'continue_button_title' => '',
1582
	);
1583
1584
	/**
1585
	 * Fire the filter
1586
	 */
1587
	$default = apply_filters( 'give_get_default_form_shortcode_args', $default );
1588
1589
	return $default;
1590
}
1591