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/misc-functions.php (102 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
 * Misc Functions
4
 *
5
 * @package     Give
6
 * @subpackage  Functions
7
 * @copyright   Copyright (c) 2016, GiveWP
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
 * Is Test Mode Enabled.
19
 *
20
 * @since 1.0
21
 *
22
 * @return bool $ret True if return mode is enabled, false otherwise
23
 */
24
function give_is_test_mode() {
25
26
	$ret = give_is_setting_enabled( give_get_option( 'test_mode' ) );
27
28
	return (bool) apply_filters( 'give_is_test_mode', $ret );
29
30
}
31
32
/**
33
 * Get the current page URL.
34
 *
35
 * @since 1.0
36
 * @return string $current_url Current page URL.
37
 */
38
function give_get_current_page_url() {
39
40
	global $wp;
41
42
	if ( get_option( 'permalink_structure' ) ) {
43
		$base = trailingslashit( home_url( $wp->request ) );
44
	} else {
45
		$base = add_query_arg( $wp->query_string, '', trailingslashit( home_url( $wp->request ) ) );
46
		$base = remove_query_arg( array( 'post_type', 'name' ), $base );
47
	}
48
49
	$scheme      = is_ssl() ? 'https' : 'http';
50
	$current_uri = set_url_scheme( $base, $scheme );
51
52
	if ( is_front_page() ) {
53
		$current_uri = home_url( '/' );
54
	}
55
56
	/**
57
	 * Filter the current page url
58
	 *
59
	 * @since 1.0
60
	 *
61
	 * @param string $current_uri
62
	 */
63
	return apply_filters( 'give_get_current_page_url', $current_uri );
64
65
}
66
67
68
/**
69
 * Verify credit card numbers live?
70
 *
71
 * @since 1.0
72
 *
73
 * @return bool $ret True is verify credit cards is live
74
 */
75
function give_is_cc_verify_enabled() {
76
77
	$ret = true;
78
79
	/**
80
	 * Enable if use a single gateway other than PayPal or Manual. We have to assume it accepts credit cards.
81
	 * Enable if using more than one gateway if they are not both PayPal and manual, again assuming credit card usage.
82
	 */
83
	$gateways = give_get_enabled_payment_gateways();
84
85
	if ( count( $gateways ) == 1 && ! isset( $gateways['paypal'] ) && ! isset( $gateways['manual'] ) ) {
0 ignored issues
show
Found "== 1". Use Yoda Condition checks, you must
Loading history...
86
		$ret = true;
87
	} elseif ( count( $gateways ) == 1 ) {
0 ignored issues
show
Found "== 1". Use Yoda Condition checks, you must
Loading history...
88
		$ret = false;
89
	} elseif ( count( $gateways ) == 2 && isset( $gateways['paypal'] ) && isset( $gateways['manual'] ) ) {
0 ignored issues
show
Found "== 2". Use Yoda Condition checks, you must
Loading history...
90
		$ret = false;
91
	}
92
93
	/**
94
	 * Fire the filter
95
	 *
96
	 * @since 1.0
97
	 *
98
	 * @param bool $ret
99
	 */
100
	return (bool) apply_filters( 'give_is_cc_verify_enabled', $ret );
101
}
102
103
/**
104
 * Retrieve timezone.
105
 *
106
 * @since 1.0
107
 * @return string $timezone The timezone ID.
108
 */
109
function give_get_timezone_id() {
110
111
	// if site timezone string exists, return it.
112
	if ( $timezone = get_option( 'timezone_string' ) ) {
113
		return $timezone;
114
	}
115
116
	// get UTC offset, if it isn't set return UTC.
117
	if ( ! ( $utc_offset = 3600 * get_option( 'gmt_offset', 0 ) ) ) {
118
		return 'UTC';
119
	}
120
121
	// attempt to guess the timezone string from the UTC offset.
122
	$timezone = timezone_name_from_abbr( '', $utc_offset );
123
124
	// last try, guess timezone string manually.
125
	if ( $timezone === false ) {
0 ignored issues
show
Found "=== false". Use Yoda Condition checks, you must
Loading history...
126
127
		$is_dst = date( 'I' );
128
129
		foreach ( timezone_abbreviations_list() as $abbr ) {
130
			foreach ( $abbr as $city ) {
131
				if ( $city['dst'] == $is_dst && $city['offset'] == $utc_offset ) {
132
					return $city['timezone_id'];
133
				}
134
			}
135
		}
136
	}
137
138
	// Fallback.
139
	return 'UTC';
140
}
141
142
143
/**
144
 * Get User IP
145
 *
146
 * Returns the IP address of the current visitor
147
 *
148
 * @since 1.0
149
 * @return string $ip User's IP address
150
 */
151
function give_get_ip() {
152
153
	$ip = '127.0.0.1';
154
155
	if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
156
		// check ip from share internet
157
		$ip = $_SERVER['HTTP_CLIENT_IP'];
0 ignored issues
show
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
158
	} elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
159
		// to check ip is pass from proxy
160
		$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
0 ignored issues
show
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
161
	} elseif ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) {
0 ignored issues
show
Due to using Batcache, server side based client related logic will not work, use JS instead.
Loading history...
162
		$ip = $_SERVER['REMOTE_ADDR'];
0 ignored issues
show
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
Due to using Batcache, server side based client related logic will not work, use JS instead.
Loading history...
163
	}
164
165
	/**
166
	 * Filter the IP
167
	 *
168
	 * @since 1.0
169
	 */
170
	$ip = apply_filters( 'give_get_ip', $ip );
171
172
	// Filter empty values.
173
	if ( false !== strpos( $ip, ',' ) ) {
174
		$ip = give_clean( explode( ',', $ip ) );
175
		$ip = array_filter( $ip );
176
		$ip = implode( ',', $ip );
177
	} else {
178
		$ip = give_clean( $ip );
179
	}
180
181
	return $ip;
182
}
183
184
185
/**
186
 * Store Donation Data in Sessions
187
 *
188
 * Used for storing info about donation
189
 *
190
 * @since 1.0
191
 *
192
 * @param $purchase_data
193
 *
194
 * @uses  Give()->session->set()
195
 */
196
function give_set_purchase_session( $purchase_data = array() ) {
197
	Give()->session->set( 'give_purchase', $purchase_data );
198
	Give()->session->set( 'give_email', $purchase_data['user_email'] );
199
}
200
201
/**
202
 * Retrieve Donation Data from Session
203
 *
204
 * Used for retrieving info about donation
205
 * after completing a donation
206
 *
207
 * @since 1.0
208
 * @uses  Give()->session->get()
209
 * @return mixed array | false
210
 */
211
function give_get_purchase_session() {
212
	return Give()->session->get( 'give_purchase' );
213
}
214
215
/**
216
 * Retrieve Payment Key of the Receipt Access Session.
217
 *
218
 * @since 1.8.17
219
 *
220
 * @return array|string
221
 */
222
function give_get_receipt_session() {
223
	return Give()->session->get( 'receipt_access' );
224
}
225
226
/**
227
 * Retrieve Payment Key of the History Access Session.
228
 *
229
 * @since 1.8.17
230
 *
231
 * @return array|string
232
 */
233
function give_get_history_session() {
234
	return (bool) Give()->session->get( 'history_access' );
235
}
236
237
/**
238
 * Generate Item Title for Payment Gateway.
239
 *
240
 * @param array $payment_data Payment Data.
241
 *
242
 * @since 1.8.14
243
 *
244
 * @return string By default, the name of the form. Then the price level text if any is found.
245
 */
246
function give_payment_gateway_item_title( $payment_data ) {
247
248
	$form_id   = intval( $payment_data['post_data']['give-form-id'] );
249
	$item_name = isset( $payment_data['post_data']['give-form-title'] ) ? $payment_data['post_data']['give-form-title'] : '';
250
	$price_id  = isset( $payment_data['post_data']['give-price-id'] ) ? $payment_data['post_data']['give-price-id'] : '';
251
252
	// Verify has variable prices.
253
	if ( give_has_variable_prices( $form_id ) && ! empty( $price_id ) ) {
254
255
		$item_price_level_text = give_get_price_option_name( $form_id, $price_id, 0, false );
256
257
		/**
258
		 * Output donation level text if:
259
		 *
260
		 * 1. It's not a custom amount
261
		 * 2. The level field has actual text and isn't the amount (which is already displayed on the receipt).
262
		 */
263
		if ( 'custom' !== $price_id && ! empty( $item_price_level_text ) ) {
264
			// Matches a donation level - append level text.
265
			$item_name .= ' - ' . $item_price_level_text;
266
		}
267
	}
268
269
	/**
270
	 * Filter the Item Title of Payment Gateway.
271
	 *
272
	 * @param string $item_name    Item Title of Payment Gateway.
273
	 * @param int    $form_id      Donation Form ID.
274
	 * @param array  $payment_data Payment Data.
275
	 *
276
	 * @since 1.8.14
277
	 *
278
	 * @return string
279
	 */
280
	return apply_filters( 'give_payment_gateway_item_title', $item_name, $form_id, $payment_data );
281
}
282
283
/**
284
 * Get Donation Summary
285
 *
286
 * Creates a donation summary for payment gateways from the donation data before the payment is created in the database.
287
 *
288
 * @since       1.8.12
289
 *
290
 * @param array $donation_data
291
 * @param bool  $name_and_email
292
 * @param int   $length
293
 *
294
 * @return string
295
 */
296
function give_payment_gateway_donation_summary( $donation_data, $name_and_email = true, $length = 255 ) {
297
298
	$form_id  = isset( $donation_data['post_data']['give-form-id'] ) ? $donation_data['post_data']['give-form-id'] : '';
299
	$price_id = isset( $donation_data['post_data']['give-price-id'] ) ? $donation_data['post_data']['give-price-id'] : '';
300
301
	// Form title.
302
	$summary = ( ! empty( $donation_data['post_data']['give-form-title'] ) ? $donation_data['post_data']['give-form-title'] : ( ! empty( $form_id ) ? wp_sprintf( __( 'Donation Form ID: %d', 'give' ), $form_id ) : __( 'Untitled donation form', 'give' ) ) );
303
304
	// Form multilevel if applicable.
305
	if ( ! empty( $price_id ) && 'custom' !== $price_id ) {
306
		$summary .= ': ' . give_get_price_option_name( $form_id, $donation_data['post_data']['give-price-id'] );
307
	}
308
309
	// Add Donor's name + email if requested.
310
	if ( $name_and_email ) {
311
312
		// First name
313 View Code Duplication
		if ( isset( $donation_data['user_info']['first_name'] ) && ! empty( $donation_data['user_info']['first_name'] ) ) {
0 ignored issues
show
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...
314
			$summary .= ' - ' . $donation_data['user_info']['first_name'];
315
		}
316
317 View Code Duplication
		if ( isset( $donation_data['user_info']['last_name'] ) && ! empty( $donation_data['user_info']['last_name'] ) ) {
0 ignored issues
show
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...
318
			$summary .= ' ' . $donation_data['user_info']['last_name'];
319
		}
320
321
		$summary .= ' (' . $donation_data['user_email'] . ')';
322
	}
323
324
	// Cut the length
325
	$summary = substr( $summary, 0, $length );
326
327
	return apply_filters( 'give_payment_gateway_donation_summary', $summary );
328
}
329
330
331
/**
332
 * Get user host
333
 *
334
 * Returns the webhost this site is using if possible
335
 *
336
 * @since 1.0
337
 * @return string $host if detected, false otherwise
338
 */
339
function give_get_host() {
340
	$host = false;
0 ignored issues
show
$host is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
341
342
	if ( defined( 'WPE_APIKEY' ) ) {
343
		$host = 'WP Engine';
344
	} elseif ( defined( 'PAGELYBIN' ) ) {
345
		$host = 'Pagely';
346
	} elseif ( DB_HOST == 'localhost:/tmp/mysql5.sock' ) {
0 ignored issues
show
Found "== '". Use Yoda Condition checks, you must
Loading history...
347
		$host = 'ICDSoft';
348
	} elseif ( DB_HOST == 'mysqlv5' ) {
0 ignored issues
show
Found "== '". Use Yoda Condition checks, you must
Loading history...
349
		$host = 'NetworkSolutions';
350
	} elseif ( strpos( DB_HOST, 'ipagemysql.com' ) !== false ) {
0 ignored issues
show
Found "!== false". Use Yoda Condition checks, you must
Loading history...
351
		$host = 'iPage';
352
	} elseif ( strpos( DB_HOST, 'ipowermysql.com' ) !== false ) {
0 ignored issues
show
Found "!== false". Use Yoda Condition checks, you must
Loading history...
353
		$host = 'IPower';
354
	} elseif ( strpos( DB_HOST, '.gridserver.com' ) !== false ) {
0 ignored issues
show
Found "!== false". Use Yoda Condition checks, you must
Loading history...
355
		$host = 'MediaTemple Grid';
356
	} elseif ( strpos( DB_HOST, '.pair.com' ) !== false ) {
0 ignored issues
show
Found "!== false". Use Yoda Condition checks, you must
Loading history...
357
		$host = 'pair Networks';
358
	} elseif ( strpos( DB_HOST, '.stabletransit.com' ) !== false ) {
0 ignored issues
show
Found "!== false". Use Yoda Condition checks, you must
Loading history...
359
		$host = 'Rackspace Cloud';
360
	} elseif ( strpos( DB_HOST, '.sysfix.eu' ) !== false ) {
0 ignored issues
show
Found "!== false". Use Yoda Condition checks, you must
Loading history...
361
		$host = 'SysFix.eu Power Hosting';
362
	} elseif ( strpos( $_SERVER['SERVER_NAME'], 'Flywheel' ) !== false ) {
0 ignored issues
show
Found "!== false". Use Yoda Condition checks, you must
Loading history...
363
		$host = 'Flywheel';
364
	} else {
365
		// Adding a general fallback for data gathering
366
		$host = 'DBH: ' . DB_HOST . ', SRV: ' . $_SERVER['SERVER_NAME'];
0 ignored issues
show
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
367
	}
368
369
	return $host;
370
}
371
372
373
/**
374
 * Check site host
375
 *
376
 * @since 1.0
377
 *
378
 * @param bool /string $host The host to check
379
 *
380
 * @return bool true if host matches, false if not
381
 */
382
function give_is_host( $host = false ) {
383
384
	$return = false;
385
386
	if ( $host ) {
387
		$host = str_replace( ' ', '', strtolower( $host ) );
388
389
		switch ( $host ) {
390
			case 'wpengine':
391
				if ( defined( 'WPE_APIKEY' ) ) {
392
					$return = true;
393
				}
394
				break;
395
			case 'pagely':
396
				if ( defined( 'PAGELYBIN' ) ) {
397
					$return = true;
398
				}
399
				break;
400
			case 'icdsoft':
401
				if ( DB_HOST == 'localhost:/tmp/mysql5.sock' ) {
0 ignored issues
show
Found "== '". Use Yoda Condition checks, you must
Loading history...
402
					$return = true;
403
				}
404
				break;
405
			case 'networksolutions':
406
				if ( DB_HOST == 'mysqlv5' ) {
0 ignored issues
show
Found "== '". Use Yoda Condition checks, you must
Loading history...
407
					$return = true;
408
				}
409
				break;
410
			case 'ipage':
411
				if ( strpos( DB_HOST, 'ipagemysql.com' ) !== false ) {
0 ignored issues
show
Found "!== false". Use Yoda Condition checks, you must
Loading history...
412
					$return = true;
413
				}
414
				break;
415
			case 'ipower':
416
				if ( strpos( DB_HOST, 'ipowermysql.com' ) !== false ) {
0 ignored issues
show
Found "!== false". Use Yoda Condition checks, you must
Loading history...
417
					$return = true;
418
				}
419
				break;
420
			case 'mediatemplegrid':
421
				if ( strpos( DB_HOST, '.gridserver.com' ) !== false ) {
0 ignored issues
show
Found "!== false". Use Yoda Condition checks, you must
Loading history...
422
					$return = true;
423
				}
424
				break;
425
			case 'pairnetworks':
426
				if ( strpos( DB_HOST, '.pair.com' ) !== false ) {
0 ignored issues
show
Found "!== false". Use Yoda Condition checks, you must
Loading history...
427
					$return = true;
428
				}
429
				break;
430
			case 'rackspacecloud':
431
				if ( strpos( DB_HOST, '.stabletransit.com' ) !== false ) {
0 ignored issues
show
Found "!== false". Use Yoda Condition checks, you must
Loading history...
432
					$return = true;
433
				}
434
				break;
435
			case 'sysfix.eu':
436
			case 'sysfix.eupowerhosting':
437
				if ( strpos( DB_HOST, '.sysfix.eu' ) !== false ) {
0 ignored issues
show
Found "!== false". Use Yoda Condition checks, you must
Loading history...
438
					$return = true;
439
				}
440
				break;
441
			case 'flywheel':
442
				if ( strpos( $_SERVER['SERVER_NAME'], 'Flywheel' ) !== false ) {
0 ignored issues
show
Found "!== false". Use Yoda Condition checks, you must
Loading history...
443
					$return = true;
444
				}
445
				break;
446
			default:
447
				$return = false;
448
		}// End switch().
449
	}// End if().
450
451
	return $return;
452
}
453
454
/**
455
 * Marks a function as deprecated and informs when it has been used.
456
 *
457
 * There is a hook give_deprecated_function_run that will be called that can be used
458
 * to get the backtrace up to what file and function called the deprecated
459
 * function.
460
 *
461
 * The current behavior is to trigger a user error if WP_DEBUG is true.
462
 *
463
 * This function is to be used in every function that is deprecated.
464
 *
465
 * @uses do_action() Calls 'give_deprecated_function_run' and passes the function name, what to use instead,
466
 *   and the version the function was deprecated in.
467
 * @uses apply_filters() Calls 'give_deprecated_function_trigger_error' and expects boolean value of true to do
468
 *   trigger or false to not trigger error.
469
 *
470
 * @param string $function    The function that was called.
471
 * @param string $version     The plugin version that deprecated the function.
472
 * @param string $replacement Optional. The function that should have been called.
473
 * @param array  $backtrace   Optional. Contains stack backtrace of deprecated function.
474
 */
475
function _give_deprecated_function( $function, $version, $replacement = null, $backtrace = null ) {
476
477
	/**
478
	 * Fires while give deprecated function call occurs.
479
	 *
480
	 * Allow you to hook to deprecated function call.
481
	 *
482
	 * @since 1.0
483
	 *
484
	 * @param string $function    The function that was called.
485
	 * @param string $replacement Optional. The function that should have been called.
486
	 * @param string $version     The plugin version that deprecated the function.
487
	 */
488
	do_action( 'give_deprecated_function_run', $function, $replacement, $version );
489
490
	$show_errors = current_user_can( 'manage_options' );
491
492
	// Allow plugin to filter the output error trigger.
493
	if ( WP_DEBUG && apply_filters( 'give_deprecated_function_trigger_error', $show_errors ) ) {
494
		if ( ! is_null( $replacement ) ) {
495
			trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since Give version %2$s! Use %3$s instead.', 'give' ), $function, $version, $replacement ) );
496
			trigger_error( print_r( $backtrace, 1 ) ); // Limited to previous 1028 characters, but since we only need to move back 1 in stack that should be fine.
0 ignored issues
show
The use of function print_r() is discouraged
Loading history...
497
			// Alternatively we could dump this to a file.
498
		} else {
499
			trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since Give version %2$s with no alternative available.', 'give' ), $function, $version ) );
500
			trigger_error( print_r( $backtrace, 1 ) );// Limited to previous 1028 characters, but since we only need to move back 1 in stack that should be fine.
0 ignored issues
show
The use of function print_r() is discouraged
Loading history...
501
			// Alternatively we could dump this to a file.
502
		}
503
	}
504
}
505
506
/**
507
 * Give Get Admin ID
508
 *
509
 * Helper function to return the ID of the post for admin usage
510
 *
511
 * @return string $post_id
512
 */
513
function give_get_admin_post_id() {
514
	$post_id = isset( $_REQUEST['post'] ) ? absint( $_REQUEST['post'] ) : null;
0 ignored issues
show
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
515
516
	$post_id = ! empty( $post_id ) ? $post_id : ( isset( $_REQUEST['post_id'] ) ? absint( $_REQUEST['post_id'] ) : null );
0 ignored issues
show
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
517
518
	$post_id = ! empty( $post_id ) ? $post_id : ( isset( $_REQUEST['post_ID'] ) ? absint( $_REQUEST['post_ID'] ) : null );
0 ignored issues
show
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
519
520
	return $post_id;
521
}
522
523
/**
524
 * Get PHP Arg Separator Output
525
 *
526
 * @since 1.0
527
 * @return string Arg separator output
528
 */
529
function give_get_php_arg_separator_output() {
530
	return ini_get( 'arg_separator.output' );
531
}
532
533
534
/**
535
 * Month Num To Name
536
 *
537
 * Takes a month number and returns the name three letter name of it.
538
 *
539
 * @since 1.0
540
 *
541
 * @param int $n
542
 *
543
 * @return string Short month name
544
 */
545
function give_month_num_to_name( $n ) {
546
	$timestamp = mktime( 0, 0, 0, $n, 1, 2005 );
547
548
	return date_i18n( 'M', $timestamp );
549
}
550
551
552
/**
553
 * Checks whether function is disabled.
554
 *
555
 * @since 1.0
556
 *
557
 * @param string $function Name of the function.
558
 *
559
 * @return bool Whether or not function is disabled.
560
 */
561
function give_is_func_disabled( $function ) {
562
	$disabled = explode( ',', ini_get( 'disable_functions' ) );
563
564
	return in_array( $function, $disabled );
565
}
566
567
/**
568
 * Give Newsletter
569
 *
570
 * Returns the main Give newsletter form
571
 */
572
function give_get_newsletter() {
573
	?>
574
575
	<p class="newsletter-intro"><?php esc_html_e( 'Be sure to sign up for the Give newsletter below to stay informed of important updates and news.', 'give' ); ?></p>
576
577
	<div class="give-newsletter-form-wrap">
578
579
		<form action="//givewp.us3.list-manage.com/subscribe/post?u=3ccb75d68bda4381e2f45794c&amp;id=12a081aa13"
580
			  method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate"
581
			  target="_blank">
582
			<div class="give-newsletter-confirmation">
583
				<p><?php esc_html_e( 'To complete your subscription, click the confirmation link in your email. Thank you!', 'give' ); ?></p>
584
			</div>
585
586
			<table class="form-table give-newsletter-form">
587
				<tr valign="middle">
588
					<td>
589
						<label for="mce-EMAIL"
590
							   class="screen-reader-text"><?php esc_html_e( 'Email Address (required)', 'give' ); ?></label>
591
						<input type="email" name="EMAIL" id="mce-EMAIL"
592
							   placeholder="<?php esc_attr_e( 'Email Address (required)', 'give' ); ?>"
593
							   class="required email" value="" required>
594
					</td>
595
					<td>
596
						<label for="mce-FNAME"
597
							   class="screen-reader-text"><?php esc_html_e( 'First Name', 'give' ); ?></label>
598
						<input type="text" name="FNAME" id="mce-FNAME"
599
							   placeholder="<?php esc_attr_e( 'First Name', 'give' ); ?>" class="" value="" required>
600
					</td>
601
					<td>
602
						<label for="mce-LNAME"
603
							   class="screen-reader-text"><?php esc_html_e( 'Last Name', 'give' ); ?></label>
604
						<input type="text" name="LNAME" id="mce-LNAME"
605
							   placeholder="<?php esc_attr_e( 'Last Name', 'give' ); ?>" class="" value="">
606
					</td>
607
					<td>
608
						<input type="submit" name="subscribe" id="mc-embedded-subscribe" class="button"
609
							   value="<?php esc_attr_e( 'Subscribe', 'give' ); ?>">
610
					</td>
611
				</tr>
612
			</table>
613
		</form>
614
615
		<div style="position: absolute; left: -5000px;">
616
			<input type="text" name="b_3ccb75d68bda4381e2f45794c_12a081aa13" tabindex="-1" value="">
617
		</div>
618
619
	</div>
620
621
	<script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'></script>
0 ignored issues
show
Scripts must be registered/enqueued via wp_enqueue_script
Loading history...
622
	<script type='text/javascript'>(
623
			function ( $ ) {
624
				window.fnames = new Array();
625
				window.ftypes = new Array();
626
				fnames[0] = 'EMAIL';
627
				ftypes[0] = 'email';
628
				fnames[1] = 'FNAME';
629
				ftypes[1] = 'text';
630
				fnames[2] = 'LNAME';
631
				ftypes[2] = 'text';
632
633
				$( 'form[name="mc-embedded-subscribe-form"]' ).removeAttr( 'novalidate' );
634
635
				//Successful submission
636
				$( 'form[name="mc-embedded-subscribe-form"]' ).on( 'submit', function () {
637
638
					var email_field = $( this ).find( '#mce-EMAIL' ).val();
639
					if ( ! email_field ) {
640
						return false;
641
					}
642
					$( this ).find( '.give-newsletter-confirmation' ).show().delay( 5000 ).slideUp();
643
					$( this ).find( '.give-newsletter-form' ).hide();
644
645
				} );
646
647
			}( jQuery )
648
		);
649
		var $mcj = jQuery.noConflict( true );
650
651
652
	</script>
653
	<!--End mc_embed_signup-->
654
655
	<?php
656
}
657
658
659
/**
660
 * Create SVG library function
661
 *
662
 * @param string $icon
663
 *
664
 * @return string
665
 */
666
function give_svg_icons( $icon ) {
667
668
	// Store your SVGs in an associative array
669
	$svgs = array(
670
		'microphone'    => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE2LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgd2lkdGg9IjY0cHgiIGhlaWdodD0iMTAwcHgiIHZpZXdCb3g9IjAgLTIwIDY0IDEyMCIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNjQgMTAwOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8Zz4NCgk8Zz4NCgkJPHBhdGggZD0iTTYyLDM2LjIxNWgtM2MtMS4xLDAtMiwwLjktMiwyVjUyYzAsNi42ODYtNS4yNjYsMTgtMjUsMThTNyw1OC42ODYsNyw1MlYzOC4yMTVjMC0xLjEtMC45LTItMi0ySDJjLTEuMSwwLTIsMC45LTIsMlY1Mg0KCQkJYzAsMTEuMTg0LDguMjE1LDIzLjE1MiwyNywyNC44MDFWOTBIMTRjLTEuMSwwLTIsMC44OTgtMiwydjZjMCwxLjEsMC45LDIsMiwyaDM2YzEuMSwwLDItMC45LDItMnYtNmMwLTEuMTAyLTAuOS0yLTItMkgzN1Y3Ni44MDENCgkJCUM1NS43ODUsNzUuMTUyLDY0LDYzLjE4NCw2NCw1MlYzOC4yMTVDNjQsMzcuMTE1LDYzLjEsMzYuMjE1LDYyLDM2LjIxNXoiLz4NCgkJPHBhdGggZD0iTTMyLDYwYzExLjczMiwwLDE1LTQuODE4LDE1LThWMzYuMjE1SDE3VjUyQzE3LDU1LjE4MiwyMC4yNjYsNjAsMzIsNjB6Ii8+DQoJCTxwYXRoIGQ9Ik00Nyw4YzAtMy4xODQtMy4yNjgtOC0xNS04QzIwLjI2NiwwLDE3LDQuODE2LDE3LDh2MjEuMjE1aDMwVjh6Ii8+DQoJPC9nPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPC9zdmc+DQo=',
671
		'alert'         => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE2LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgd2lkdGg9IjI4LjkzOHB4IiBoZWlnaHQ9IjI1LjAwNXB4IiB2aWV3Qm94PSIwIDAgMjguOTM4IDI1LjAwNSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMjguOTM4IDI1LjAwNTsiDQoJIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPHBhdGggc3R5bGU9ImZpbGw6IzAwMDAwMDsiIGQ9Ik0yOC44NTksMjQuMTU4TDE0Ljk1NywwLjI3OUMxNC44NTYsMC4xMDYsMTQuNjcsMCwxNC40NjgsMGMtMC4xOTgsMC0wLjM4MywwLjEwNi0wLjQ4MSwwLjI3OQ0KCUwwLjA3OSwyNC4xNThjLTAuMTAyLDAuMTc1LTAuMTA2LDAuMzg5LTAuMDA2LDAuNTY1YzAuMTAzLDAuMTc0LDAuMjg3LDAuMjgyLDAuNDg4LDAuMjgyaDI3LjgxNGMwLjIwMSwwLDAuMzg5LTAuMTA4LDAuNDg4LTAuMjgyDQoJYzAuMDQ3LTAuMDg4LDAuMDc0LTAuMTg2LDAuMDc0LTAuMjgxQzI4LjkzOCwyNC4zNDMsMjguOTExLDI0LjI0NSwyOC44NTksMjQuMTU4eiBNMTYuMzY5LDguNDc1bC0wLjQ2Miw5LjQ5M2gtMi4zODlsLTAuNDYxLTkuNDkzDQoJSDE2LjM2OXogTTE0LjcxMSwyMi44MjhoLTAuMDQyYy0xLjA4OSwwLTEuODQzLTAuODE3LTEuODQzLTEuOTA3YzAtMS4xMzEsMC43NzQtMS45MDcsMS44ODUtMS45MDdzMS44NDYsMC43NzUsMS44NjcsMS45MDcNCglDMTYuNTc5LDIyLjAxMSwxNS44NDQsMjIuODI4LDE0LjcxMSwyMi44Mjh6Ii8+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8L3N2Zz4NCg==',
672
		'placemark'     => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxNi4wLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB3aWR0aD0iMTAwcHgiIGhlaWdodD0iMTAwcHgiIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMDAgMTAwIiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxnPg0KCTxwYXRoIGQ9Ik01MC40MzQsMjAuMjcxYy0xMi40OTksMC0yMi42NjgsMTAuMTY5LTIyLjY2OCwyMi42NjhjMCwxMS44MTQsMTguODE1LDMyLjE1NSwyMC45NiwzNC40MzdsMS43MDgsMS44MTZsMS43MDgtMS44MTYNCgkJYzIuMTQ1LTIuMjgxLDIwLjk2LTIyLjYyMywyMC45Ni0zNC40MzdDNzMuMTAzLDMwLjQ0LDYyLjkzNCwyMC4yNzEsNTAuNDM0LDIwLjI3MXogTTUwLjQzNCw1Mi4zMmMtNS4xNzIsMC05LjM4LTQuMjA4LTkuMzgtOS4zOA0KCQlzNC4yMDgtOS4zOCw5LjM4LTkuMzhjNS4xNzMsMCw5LjM4LDQuMjA4LDkuMzgsOS4zOFM1NS42MDcsNTIuMzIsNTAuNDM0LDUyLjMyeiIvPg0KPC9nPg0KPC9zdmc+DQo=',
673
		'give_grey'     => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiIHZpZXdCb3g9IjEwMC4xIDAgNDAwIDQwMCIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAxMDAuMSAwIDQwMCA0MDAiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxnIGlkPSJMYXllcl8xXzFfIj48Y2lyY2xlIGZpbGw9IiM2NkJCNkEiIGN4PSItNDA3LjMiIGN5PSIzNDYuMyIgcj0iNDIuMiIvPjxnPjxnPjxwYXRoIGZpbGw9IiM1NDZFN0EiIGQ9Ik0tNzg2LjQsMTMzLjh2LTEyLjVoNC44YzMuOCwwLDYuNiwyLjUsNi42LDYuNHMtMi44LDYuNC02LjYsNi40aC00LjhWMTMzLjh6IE0tNzc3LjUsMTI3LjVjMC0yLjMtMS4zLTMuOC0zLjgtMy44aC0yLjN2Ny45aDIuM0MtNzc5LDEzMS42LTc3Ny41LDEyOS44LTc3Ny41LDEyNy41eiIvPjxwYXRoIGZpbGw9IiM1NDZFN0EiIGQ9Ik0tNzcxLjYsMTMzLjh2LTEyLjVoOC45djIuM2gtNi4xdjIuNWg2LjF2Mi4zaC02LjF2Mi44aDYuMXYyLjNoLTguOVYxMzMuOHoiLz48cGF0aCBmaWxsPSIjNTQ2RTdBIiBkPSJNLTc0OC41LDEzMy44di04LjdsLTMuNiw4LjdoLTEuM2wtMy42LTguN3Y4LjdoLTIuNXYtMTIuNWgzLjhsMy4xLDcuNmwzLjEtNy42aDMuOHYxMi41SC03NDguNXoiLz48cGF0aCBmaWxsPSIjNTQ2RTdBIiBkPSJNLTc0Mi40LDEyNy41YzAtMy44LDIuOC02LjQsNi42LTYuNHM2LjYsMi44LDYuNiw2LjRjMCwzLjgtMi44LDYuNC02LjYsNi40Qy03MzkuOCwxMzQuMS03NDIuNCwxMzEuMy03NDIuNCwxMjcuNXogTS03MzIuMiwxMjcuNWMwLTIuMy0xLjUtNC4xLTMuOC00LjFjLTIuMywwLTMuOCwxLjgtMy44LDQuMWMwLDIuMywxLjUsNC4xLDMuOCw0LjFDLTczMy43LDEzMS42LTczMi4yLDEyOS44LTczMi4yLDEyNy41eiIvPjxwYXRoIGZpbGw9IiM1NDZFN0EiIGQ9Ik0tNzI2LjgsMTI3LjVjMC0zLjgsMi44LTYuNCw2LjYtNi40YzIuOCwwLDQuMywxLjUsNS4zLDMuMWwtMi4zLDFjLTAuNS0xLTEuNS0xLjgtMy4xLTEuOGMtMi4zLDAtMy44LDEuOC0zLjgsNC4xYzAsMi4zLDEuNSw0LjEsMy44LDQuMWMxLjMsMCwyLjMtMC44LDMuMS0xLjhsMi4zLDFjLTEsMS41LTIuNSwzLjEtNS4zLDMuMUMtNzIzLjgsMTM0LjEtNzI2LjgsMTMxLjMtNzI2LjgsMTI3LjV6Ii8+PHBhdGggZmlsbD0iIzU0NkU3QSIgZD0iTS03MDQuNywxMzMuOGwtMi41LTQuM2gtMnY0LjNoLTIuNXYtMTIuNWg1LjljMi41LDAsNC4xLDEuOCw0LjEsNC4xYzAsMi4zLTEuMywzLjMtMi44LDMuOGwyLjgsNC44aC0yLjhWMTMzLjh6IE0tNzA0LjUsMTI1LjJjMC0xLTAuOC0xLjgtMS44LTEuOGgtMi44djMuM2gyLjhDLTcwNS41LDEyNy03MDQuNSwxMjYuNS03MDQuNSwxMjUuMnoiLz48cGF0aCBmaWxsPSIjNTQ2RTdBIiBkPSJNLTY4OS43LDEzMy44bC0wLjgtMmgtNS4zbC0wLjgsMmgtMy4xbDQuOC0xMi41aDMuM2w0LjgsMTIuNUgtNjg5Ljd6IE0tNjkzLjMsMTIzLjlsLTIsNS4zaDMuOEwtNjkzLjMsMTIzLjl6Ii8+PHBhdGggZmlsbD0iIzU0NkU3QSIgZD0iTS02ODIuNiwxMzMuOHYtMTAuMmgtMy42di0yLjNoOS45djIuM2gtMy42djEwLjJILTY4Mi42eiIvPjxwYXRoIGZpbGw9IiM1NDZFN0EiIGQ9Ik0tNjczLjIsMTMzLjh2LTEyLjVoMi41djEyLjVILTY3My4yeiIvPjxwYXRoIGZpbGw9IiM1NDZFN0EiIGQ9Ik0tNjY3LDEzMy44di0ybDUuOS03LjloLTUuOXYtMi4zaDkuNHYybC01LjksOC4xaDYuMXYyLjNoLTkuN1YxMzMuOHoiLz48cGF0aCBmaWxsPSIjNTQ2RTdBIiBkPSJNLTY1NC4xLDEzMy44di0xMi41aDIuNXYxMi41SC02NTQuMXoiLz48cGF0aCBmaWxsPSIjNTQ2RTdBIiBkPSJNLTYzOS4xLDEzMy44bC01LjktOC4xdjguMWgtMi41di0xMi41aDIuOGw1LjksNy45di03LjloMi41djEyLjVILTYzOS4xeiIvPjxwYXRoIGZpbGw9IiM1NDZFN0EiIGQ9Ik0tNjMzLjIsMTI3LjVjMC00LjEsMy4xLTYuNCw2LjYtNi40YzIuNSwwLDQuMywxLjMsNS4xLDIuOGwtMi4zLDEuM2MtMC41LTAuOC0xLjUtMS41LTMuMS0xLjVjLTIuMywwLTMuOCwxLjgtMy44LDQuMWMwLDIuMywxLjUsNC4xLDMuOCw0LjFjMSwwLDItMC41LDIuNS0xdi0xLjVoLTMuM1YxMjdoNS45djQuOGMtMS4zLDEuNS0zLjEsMi4zLTUuMywyLjNDLTYzMC4yLDEzNC4xLTYzMy4yLDEzMS42LTYzMy4yLDEyNy41eiIvPjxwYXRoIGZpbGw9IiM1NDZFN0EiIGQ9Ik0tNjEyLjEsMTI3LjVjMC00LjEsMy4xLTYuNCw2LjYtNi40YzIuNSwwLDQuMywxLjMsNS4xLDIuOGwtMi4zLDEuM2MtMC41LTAuOC0xLjUtMS41LTMuMS0xLjVjLTIuMywwLTMuOCwxLjgtMy44LDQuMWMwLDIuMywxLjUsNC4xLDMuOCw0LjFjMSwwLDItMC41LDIuNS0xdi0xLjVoLTMuM1YxMjdoNS45djQuOGMtMS4zLDEuNS0zLjEsMi4zLTUuMywyLjNDLTYwOSwxMzQuMS02MTIuMSwxMzEuNi02MTIuMSwxMjcuNXoiLz48cGF0aCBmaWxsPSIjNTQ2RTdBIiBkPSJNLTU5Ni42LDEzMy44di0xMi41aDguOXYyLjNoLTYuMXYyLjVoNi4xdjIuM2gtNi4xdjIuOGg2LjF2Mi4zaC04LjlWMTMzLjh6Ii8+PHBhdGggZmlsbD0iIzU0NkU3QSIgZD0iTS01NzUuNywxMzMuOGwtNS45LTguMXY4LjFoLTIuNXYtMTIuNWgyLjhsNS45LDcuOXYtNy45aDIuNXYxMi41SC01NzUuN3oiLz48cGF0aCBmaWxsPSIjNTQ2RTdBIiBkPSJNLTU2OS4xLDEzMy44di0xMi41aDguOXYyLjNoLTYuMXYyLjVoNi4xdjIuM2gtNi4xdjIuOGg2LjF2Mi4zaC04LjlWMTMzLjh6Ii8+PHBhdGggZmlsbD0iIzU0NkU3QSIgZD0iTS01NDkuNywxMzMuOGwtMi41LTQuM2gtMnY0LjNoLTIuNXYtMTIuNWg1LjljMi41LDAsNC4xLDEuOCw0LjEsNC4xYzAsMi4zLTEuMywzLjMtMi44LDMuOGwyLjgsNC44aC0yLjhWMTMzLjh6IE0tNTQ5LjUsMTI1LjJjMC0xLTAuOC0xLjgtMS44LTEuOGgtMi44djMuM2gyLjhDLTU1MC4zLDEyNy01NDkuNSwxMjYuNS01NDkuNSwxMjUuMnoiLz48cGF0aCBmaWxsPSIjNTQ2RTdBIiBkPSJNLTU0My45LDEyNy41YzAtMy44LDIuOC02LjQsNi42LTYuNHM2LjYsMi44LDYuNiw2LjRjMCwzLjgtMi44LDYuNC02LjYsNi40Qy01NDEuMywxMzQuMS01NDMuOSwxMzEuMy01NDMuOSwxMjcuNXogTS01MzMuNywxMjcuNWMwLTIuMy0xLjUtNC4xLTMuOC00LjFzLTMuOCwxLjgtMy44LDQuMWMwLDIuMywxLjUsNC4xLDMuOCw0LjFDLTUzNS4yLDEzMS42LTUzMy43LDEyOS44LTUzMy43LDEyNy41eiIvPjxwYXRoIGZpbGw9IiM1NDZFN0EiIGQ9Ik0tNTI4LjYsMTMyLjFsMS41LTJjMC44LDEsMi4zLDEuOCw0LjEsMS44YzEuNSwwLDIuMy0wLjgsMi4zLTEuM2MwLTIuMy03LjEtMC44LTcuMS01LjNjMC0yLDEuOC0zLjgsNC44LTMuOGMyLDAsMy42LDAuNSw0LjgsMS44bC0xLjUsMmMtMS0xLTIuMy0xLjMtMy42LTEuM2MtMSwwLTEuOCwwLjUtMS44LDEuM2MwLDIsNy4xLDAuOCw3LjEsNS4zYzAsMi4zLTEuNSw0LjEtNS4xLDQuMUMtNTI1LjYsMTM0LjEtNTI3LjQsMTMzLjEtNTI4LjYsMTMyLjF6Ii8+PHBhdGggZmlsbD0iIzU0NkU3QSIgZD0iTS01MTUuMSwxMzMuOHYtMTIuNWgyLjV2MTIuNUgtNTE1LjF6Ii8+PHBhdGggZmlsbD0iIzU0NkU3QSIgZD0iTS01MDUuNywxMzMuOHYtMTAuMmgtMy42di0yLjNoOS45djIuM2gtMy42djEwLjJILTUwNS43eiIvPjxwYXRoIGZpbGw9IiM1NDZFN0EiIGQ9Ik0tNDkyLjcsMTMzLjh2LTUuMWwtNC44LTcuNGgzLjFsMy4xLDUuMWwzLjEtNS4xaDMuMWwtNC44LDcuNHY1LjFILTQ5Mi43eiIvPjwvZz48Zz48Zz48cGF0aCBmaWxsPSIjNjZCQjZBIiBkPSJNLTQ4NS45LDQ0LjNoLTEuM2wwLjMsMS4zYzIsOS45LDAuMywyNC43LTcuNCwzMy44Yy00LjMsNS4zLTkuOSw4LjEtMTYuOCw4LjFjLTEwLjksMC0xNS0xMy0xNS41LTI3LjdjMTcuOC00LjMsMjkuOC0xNS41LDI5LjgtMjguNWMwLTkuNC0yLjgtMjQuOS0yMS40LTI0LjljLTE3LjYsMC0yNi41LDI2LjItMjguMiw0NC41Yy04LjktMC4zLTE1LjUtNC4zLTE5LjYtOC4xYzEuNS02LjQsMi4zLTEyLjIsMi4zLTE3LjZjMC03LjQtNS4xLTEwLjctOS45LTEwLjdjLTYuOSwwLTE0LDYuNi0xNCwxOS4zYzAsNy42LDIuOCwxNCw4LjcsMTguNmMtNS4xLDEyLTEzLjcsMjIuMS0xNi41LDI1LjRjLTIuMy00LjgtOS43LTIyLjQtMTItNDEuNWMyLjgtNy42LDQuMy0xNCw0LjMtMTdjMC00LjgtMy4xLTcuNi04LjEtNy42Yy02LjksMC0xNy44LDQuMy0xOC4xLDQuNmwtMC41LDAuM3YwLjhjMCwwLjMsMy4zLDE1LjUsNi42LDMyLjNjLTYuNCwxMC40LTE3LjYsMjcuNy0yMy4yLDI3LjdjLTEwLjIsMCw2LjYtNTIuMi0wLjgtNTMuOWMtMC4zLDAtMC41LDAtMC44LDAuM2MtMy42LDIuMy00My41LDI0LjQtOTYuNywyNC40YzAsMCwwLDEsMC41LDJjMC4zLDAuOCwxLDEuNSwxLDEuNWMxNSwxLjgsMzYuNC0wLjMsNTIuNy0yLjVjLTkuNCwyMC4xLTI2LDMzLjMtNDEuMiwzMy4zYy0yOC44LDAtNTAuOS0zNC45LTUwLjktMzQuOWM4LjktNy45LDIzLjQtMzMuMyw0NC44LTMzLjNjMjEuMSwwLDMwLjMsMTEuNywzMC4zLDExLjdsMi4zLTMuOGMwLDAtOS45LTM0LjYtMzcuOS0zNC42cy01Ny44LDQ1LjgtNzUuMSw1Ni41YzAsMCwyMy45LDU2LjUsNzYuMSw1Ni41YzQzLjgsMCw1NS00Miw1Ny01Mi4yYzEwLjctMS41LDE4LjEtMy4xLDE4LjEtMy4xcy0yLjgsMjEuNC0yLjgsMzAuM3M5LjksMTguMywxOC4xLDE4LjNjNi45LDAsMjAuOS0xNC4yLDMxLTMxLjZsMC41LDJjNS4zLDE5LjYsMTIsMjkuOCwxOS44LDI5LjhjNy45LDAsMjAuOS0xNi4zLDI5LjMtMzYuOWM4LjQsMy42LDE4LjMsNC42LDI0LjIsNC44YzIuMywzNS40LDMxLjgsMzYuNCwzNS40LDM2LjRjMjEuOSwwLDQwLjUtMTUuOCw0MC41LTM0LjRDLTQ3MC42LDQ0LjUtNDg1LjYsNDQuMy00ODUuOSw0NC4zeiBNLTUxMi42LDI5LjVjMCwwLTAuMywxMS43LTEzLjUsMTcuNmMxLjMtMTUuNSw1LjEtMjkuNSw3LjYtMjkuNUMtNTE1LjYsMTcuOC01MTIuNiwyMi4xLTUxMi42LDI5LjV6Ii8+PHBhdGggZmlsbD0iIzY2QkI2QSIgZD0iTS02NjUsMTUuNWMwLDAuNSwwLjMsMC44LDAuOCwxYzEwLjQsMS41LDE3LjMtMS44LDE3LjMtMTguNmMwLTE1LjgtMTYuMy0zLjMtMTkuMy0xYy0wLjMsMC4zLTAuMywwLjUtMC4zLDFDLTY2My43LDQuMS02NjQuOCwxMy02NjUsMTUuNXoiLz48L2c+PGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8xXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMjg5LjU4NjQiIHkxPSIzNzMuMjM3OSIgeDI9Ii0yODIuODg0MiIgeTI9IjM3NS40NzE5IiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDIuNTQ0NSAwIDAgLTIuNTQ0NSAxMDAuMTI3MiAxMDE3LjgxMTcpIj48c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+PHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzM3OEY0MyIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCNTVkdJRF8xXykiIGQ9Ik0tNjIzLDQ5LjRjLTQuMSw2LjktMTAuMiwxNi4zLTE1LjUsMjIuMWMxLjMsMy4xLDIuOCw2LjksNC4zLDkuOWM0LjgtNS4zLDkuNy0xMi4yLDE0LTE5LjNMLTYyMyw0OS40eiIvPjxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfMl8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTI2OS4wNTc3IiB5MT0iMzcxLjU0NDEiIHgyPSItMjY1LjE3MDUiIHkyPSIzNzguMzgwMiIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgyLjU0NDUgMCAwIC0yLjU0NDUgMTAwLjEyNzIgMTAxNy44MTE3KSI+PHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPjxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz48L2xpbmVhckdyYWRpZW50PjxwYXRoIGZpbGw9InVybCgjU1ZHSURfMl8pIiBkPSJNLTU3NC43LDU0LjdjLTItMS0zLjgtMi41LTMuOC0yLjVjLTMuNiw3LjktOC40LDE1LjMtMTIuMiwyMC4xYzEuOCwyLjUsNC44LDUuOSw3LjEsOC40YzQuNi02LjQsOS40LTE0LjgsMTMtMjMuN0MtNTcwLjQsNTYuNy01NzIuNiw1Ni01NzQuNyw1NC43eiIvPjxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfM18iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTI0OC42NDE2IiB5MT0iMzY4LjM4MzUiIHgyPSItMjQ5LjQ0NTkiIHkyPSIzNzUuNTMyMyIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgyLjU0NDUgMCAwIC0yLjU0NDUgMTAwLjEyNzIgMTAxNy44MTE3KSI+PHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPjxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz48L2xpbmVhckdyYWRpZW50PjxwYXRoIGZpbGw9InVybCgjU1ZHSURfM18pIiBkPSJNLTUyNi4zLDU5LjhjMCwwLTUuMSwxLTEwLjIsMS41cy05LjksMC4zLTkuOSwwLjNjMC44LDEwLjIsMy42LDE3LjMsNy40LDIyLjZsMTguNi0xLjVDLTUyNC4zLDc3LjYtNTI2LjEsNjktNTI2LjMsNTkuOHoiLz48bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzRfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ii0yNDkuOCIgeTE9IjM4My41ODEiIHgyPSItMjQ5LjgiIHkyPSIzNzYuMzc2MyIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgyLjU0NDUgMCAwIC0yLjU0NDUgMTAwLjEyNzIgMTAxNy44MTE3KSI+PHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPjxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz48L2xpbmVhckdyYWRpZW50PjxwYXRoIGZpbGw9InVybCgjU1ZHSURfNF8pIiBkPSJNLTU0MS4xLDI4LjhMLTU0MS4xLDI4LjhjLTAuNSwxLjUtMS4zLDMuMy0xLjgsNS4xYzAsMC41LTAuMywwLjgtMC4zLDEuM2MtMSwzLjMtMS44LDYuNi0yLjMsOS45YzAsMC41LTAuMywwLjgtMC4zLDEuM2MtMC4zLDEuNS0wLjUsMy4xLTAuNSw0LjZjMTIsMCwyMC4xLTMuNiwyMC4xLTMuNmMwLTEuMywwLjMtMi4zLDAuMy0zLjZjMC0wLjMsMC0wLjUsMC0wLjhjMC0xLDAuMy0xLjgsMC4zLTIuOGMwLTAuMywwLTAuNSwwLTAuOGMwLjMtMi4zLDAuOC00LjYsMS02LjZMLTU0MS4xLDI4Ljh6IE0tNTQ2LjQsNTAuNkwtNTQ2LjQsNTAuNkwtNTQ2LjQsNTAuNkwtNTQ2LjQsNTAuNnoiLz48bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzVfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ii0zMTMiIHkxPSIzNzEuNzcyMiIgeDI9Ii0zMTMiIHkyPSIzODAuNzA4MyIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgyLjU0NDUgMCAwIC0yLjU0NDUgMTAwLjEyNzIgMTAxNy44MTE3KSI+PHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPjxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz48L2xpbmVhckdyYWRpZW50PjxwYXRoIGZpbGw9InVybCgjU1ZHSURfNV8pIiBkPSJNLTcwOC4zLDcyLjhsMTEuMiw0LjhjNS4zLTcuNiw4LjctMTUuNSwxMC43LTIxLjZsMi04LjFsLTUuMywwLjhDLTY5NC41LDU4LjgtNzAxLjEsNjYuOS03MDguMyw3Mi44eiIvPjxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfNl8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTI3Ny41MjU1IiB5MT0iMzkwLjIxMyIgeDI9Ii0yNzguNjQ3OSIgeTI9IjM4OC40MjU0IiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDIuNTQ0NSAwIDAgLTIuNTQ0NSAxMDAuMTI3MiAxMDE3LjgxMTcpIj48c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+PHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzM3OEY0MyIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCNTVkdJRF82XykiIGQ9Ik0tNjA3LDM2LjFjMi44LTcuNiw0LjMtMTQsNC4zLTE3YzAtMC4zLDAtMC41LDAtMC44bC02LjYsMkMtNjA5LjMsMjAuNC02MDksMjQuNy02MDcsMzYuMXoiLz48bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzdfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ii0yNjIuNTgxMyIgeTE9IjM4Ni40ODI3IiB4Mj0iLTI2My4yMTUiIHkyPSIzODQuMDc0OSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgyLjU0NDUgMCAwIC0yLjU0NDUgMTAwLjEyNzIgMTAxNy44MTE3KSI+PHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPjxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz48L2xpbmVhckdyYWRpZW50PjxwYXRoIGZpbGw9InVybCgjU1ZHSURfN18pIiBkPSJNLTU3MS40LDMwLjVjMCwwLTEuOCw1LjMsNS42LDEyYzEuMy01LjMsMi0xMC43LDIuMy0xNS4zTC01NzEuNCwzMC41eiIvPjwvZz48L2c+PGc+PGc+PHBhdGggZmlsbD0iIzY2QkI2QSIgZD0iTS04MDcuOCwzNDYuNmgtMC41djAuNWMwLjgsNC4zLDAsMTAuNC0zLjEsMTQuNWMtMS44LDIuMy00LjMsMy42LTcuMSwzLjZjLTQuNiwwLTYuNC01LjYtNi42LTExLjdjNy42LTEuOCwxMi43LTYuNiwxMi43LTEyLjJjMC00LjEtMS4zLTEwLjctOS4yLTEwLjdjLTcuNCwwLTExLjIsMTEuMi0xMiwxOC44Yy0zLjgsMC02LjYtMS44LTguNC0zLjZjMC44LTIuOCwxLTUuMSwxLTcuNGMwLTMuMS0yLjMtNC42LTQuMS00LjZjLTMuMSwwLTUuOSwyLjgtNS45LDguMWMwLDMuMywxLjMsNS45LDMuOCw3LjljLTIuMyw1LjEtNS45LDkuNC03LjEsMTAuN2MtMS0yLTQuMS05LjctNS4xLTE3LjZjMS4zLTMuMywxLjgtNS45LDEuOC03LjFjMC0yLTEuMy0zLjMtMy42LTMuM2MtMy4xLDAtNy42LDEuOC03LjYsMmwtMC4zLDAuM3YwLjNjMCwwLDEuMyw2LjYsMi44LDEzLjdjLTIuOCw0LjMtNy40LDExLjctOS45LDExLjdjLTQuMywwLDIuOC0yMi4xLTAuMy0yMi45aC0wLjNjLTEuNSwxLTE4LjYsMTAuNC00MSwxMC40YzAsMCwwLDAuNSwwLjMsMC44YzAuMywwLjMsMC41LDAuNSwwLjUsMC41YzYuNCwwLjgsMTUuNSwwLDIyLjQtMWMtNC4xLDguNC0xMC45LDE0LjItMTcuNiwxNC4yYy0xMi4yLDAtMjEuNi0xNC44LTIxLjYtMTQuOGMzLjgtMy4zLDkuOS0xNC4yLDE5LjEtMTQuMmM4LjksMCwxMyw0LjgsMTMsNC44bDEtMS41YzAsMC00LjMtMTQuOC0xNi0xNC44cy0yNC40LDE5LjYtMzEuOCwyMy45YzAsMCwxMC4yLDI0LjIsMzIuMywyNC4yYzE4LjYsMCwyMy40LTE3LjgsMjQuMi0yMi4xYzQuNi0wLjgsNy42LTEuMyw3LjYtMS4zcy0xLDkuMi0xLDEzYzAsMy44LDQuMSw3LjksNy42LDcuOWMzLjEsMCw4LjktNi4xLDEzLjItMTMuNWwwLjMsMC44YzIuMyw4LjQsNS4xLDEyLjcsOC40LDEyLjdzOC45LTYuOSwxMi41LTE1LjVjMy42LDEuNSw3LjksMiwxMC4yLDJjMSwxNSwxMy41LDE1LjUsMTUsMTUuNWM5LjQsMCwxNy4zLTYuNiwxNy4zLTE0LjVDLTgwMS40LDM0Ni44LTgwNy44LDM0Ni42LTgwNy44LDM0Ni42eiBNLTgxOSwzNDAuMmMwLDAsMCw1LjEtNS45LDcuNmMwLjUtNi42LDItMTIuNSwzLjMtMTIuNUMtODIwLjUsMzM1LjQtODE5LDMzNy4yLTgxOSwzNDAuMnoiLz48cGF0aCBmaWxsPSIjNjZCQjZBIiBkPSJNLTg4My44LDMzNC40YzAsMC4zLDAsMC4zLDAuMywwLjVjNC4zLDAuNSw3LjQtMC44LDcuNC03LjljMC02LjYtNi45LTEuNS04LjEtMC41YzAsMC0wLjMsMC4zLDAsMC41Qy04ODMuMywzMjkuNS04ODMuOCwzMzMuMS04ODMuOCwzMzQuNHoiLz48L2c+PGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF84XyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMzgyLjAwNzQiIHkxPSIyNTkuODQ3NSIgeDI9Ii0zNzkuMTU4NSIgeTI9IjI2MC43OTcyIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDIuNTQ0NSAwIDAgLTIuNTQ0NSAxMDAuMTI3MiAxMDE3LjgxMTcpIj48c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+PHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzM3OEY0MyIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCNTVkdJRF84XykiIGQ9Ik0tODY2LDM0OC42Yy0xLjgsMi44LTQuMyw2LjktNi42LDkuNGMwLjUsMS4zLDEuMywyLjgsMS44LDQuM2MyLTIuMyw0LjEtNS4xLDYuMS04LjFMLTg2NiwzNDguNnoiLz48bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzlfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ii0zNzMuMTYyNiIgeTE9IjI1OS4wNDIzIiB4Mj0iLTM3MS41MTAyIiB5Mj0iMjYxLjk0ODIiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMi41NDQ1IDAgMCAtMi41NDQ1IDEwMC4xMjcyIDEwMTcuODExNykiPjxzdG9wICBvZmZzZXQ9IjAiIHN0eWxlPSJzdG9wLWNvbG9yOiM2NkJCNkEiLz48c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojMzc4RjQzIi8+PC9saW5lYXJHcmFkaWVudD48cGF0aCBmaWxsPSJ1cmwoI1NWR0lEXzlfKSIgZD0iTS04NDUuNCwzNTAuOWMtMC44LTAuNS0xLjUtMS0xLjUtMWMtMS41LDMuMy0zLjYsNi40LTUuMSw4LjdjMC44LDEsMiwyLjUsMy4xLDMuNmMyLTIuOCw0LjEtNi4xLDUuNi0xMC4yQy04NDMuNiwzNTEuOS04NDQuNywzNTEuNC04NDUuNCwzNTAuOXoiLz48bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzEwXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMzY0LjY5OTYiIHkxPSIyNTcuNzUwMyIgeDI9Ii0zNjUuMDQxNCIgeTI9IjI2MC43ODkyIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDIuNTQ0NSAwIDAgLTIuNTQ0NSAxMDAuMTI3MiAxMDE3LjgxMTcpIj48c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+PHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzM3OEY0MyIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCNTVkdJRF8xMF8pIiBkPSJNLTgyNS4xLDM1My4yYzAsMC0yLDAuNS00LjMsMC44Yy0yLDAuMy00LjMsMC00LjMsMGMwLjMsNC4zLDEuNSw3LjQsMy4xLDkuN2w3LjktMC44Qy04MjQsMzYwLjgtODI0LjgsMzU3LTgyNS4xLDM1My4yeiIvPjxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfMTFfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ii0zNjUiIHkxPSIyNjQuMjIyMyIgeDI9Ii0zNjUiIHkyPSIyNjEuMTU5NyIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgyLjU0NDUgMCAwIC0yLjU0NDUgMTAwLjEyNzIgMTAxNy44MTE3KSI+PHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPjxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz48L2xpbmVhckdyYWRpZW50PjxwYXRoIGZpbGw9InVybCgjU1ZHSURfMTFfKSIgZD0iTS04MzEuMiwzMzkuOUwtODMxLjIsMzM5LjljLTAuMywwLjgtMC41LDEuNS0wLjgsMmMwLDAuMywwLDAuMy0wLjMsMC41Yy0wLjUsMS41LTAuOCwyLjgtMSw0LjNjMCwwLjMsMCwwLjMsMCwwLjVjMCwwLjgtMC4zLDEuMy0wLjMsMmM1LjEsMCw4LjctMS41LDguNy0xLjVjMC0wLjUsMC0xLDAuMy0xLjV2LTAuM2MwLTAuNSwwLTAuOCwwLjMtMXYtMC4zYzAuMy0xLDAuMy0yLDAuNS0yLjhMLTgzMS4yLDMzOS45eiBNLTgzMy41LDM0OS40TC04MzMuNSwzNDkuNEwtODMzLjUsMzQ5LjRMLTgzMy41LDM0OS40eiIvPjxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfMTJfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ii0zOTIiIHkxPSIyNTkuMjAyNSIgeDI9Ii0zOTIiIHkyPSIyNjMuMDAxMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgyLjU0NDUgMCAwIC0yLjU0NDUgMTAwLjEyNzIgMTAxNy44MTE3KSI+PHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPjxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz48L2xpbmVhckdyYWRpZW50PjxwYXRoIGZpbGw9InVybCgjU1ZHSURfMTJfKSIgZD0iTS05MDIuNCwzNTguOGw0LjgsMmMyLjMtMy4zLDMuNi02LjYsNC42LTkuMmwwLjgtMy42bC0yLjMsMC4zQy04OTYuNiwzNTIuNy04OTkuMSwzNTYuMi05MDIuNCwzNTguOHoiLz48bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzEzXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMzc2Ljg2MzciIHkxPSIyNjcuMDM1NSIgeDI9Ii0zNzcuMzQwOSIgeTI9IjI2Ni4yNzU1IiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDIuNTQ0NSAwIDAgLTIuNTQ0NSAxMDAuMTI3MiAxMDE3LjgxMTcpIj48c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+PHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzM3OEY0MyIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCNTVkdJRF8xM18pIiBkPSJNLTg1OS4yLDM0M2MxLjMtMy4zLDEuOC01LjksMS44LTcuMXYtMC4zbC0yLjgsMC44Qy04NjAuMiwzMzYuNC04NjAuMiwzMzguMi04NTkuMiwzNDN6Ii8+PGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8xNF8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTM3MC41NTQzIiB5MT0iMjY1LjQ2NDUiIHgyPSItMzcwLjgyMzYiIHkyPSIyNjQuNDQxIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDIuNTQ0NSAwIDAgLTIuNTQ0NSAxMDAuMTI3MiAxMDE3LjgxMTcpIj48c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+PHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzM3OEY0MyIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCNTVkdJRF8xNF8pIiBkPSJNLTg0NC4xLDM0MC43YzAsMC0wLjgsMi4zLDIuMyw1LjFjMC41LTIuMywxLTQuNiwxLTYuNkwtODQ0LjEsMzQwLjd6Ii8+PC9nPjxnPjxyZWN0IHg9Ii02OTcuMyIgeT0iMjkyLjkiIGZpbGw9IiNGRkZGRkYiIHdpZHRoPSIxMDYuOSIgaGVpZ2h0PSIxMDYuOSIvPjxnPjxwYXRoIGZpbGw9IiM2NkJCNkEiIGQ9Ik0tNjQ0LjQsMzQ5LjljMC4zLDAuNSwwLjUsMC44LDAuNSwwLjhjOC43LDEsMjEuMSwwLDMwLjUtMS41Yy01LjMsMTEuNy0xNSwxOS4zLTIzLjksMTkuM2MtMTYuNSwwLTI5LjUtMjAuMS0yOS41LTIwLjFjNS4xLTQuNiwxMy43LTE5LjMsMjYtMTkuM2MxMi4yLDAsMTcuNiw2LjYsMTcuNiw2LjZsMS4zLTIuM2MwLDAtNS45LTIwLjEtMjEuOS0yMC4xYy0xNi4zLDAtMzMuMywyNi41LTQzLjUsMzIuNmMwLDAsMTMuNywzMi44LDQ0LDMyLjhjMjUuNCwwLDMxLjgtMjQuMiwzMy4xLTMwLjNjMy4zLTAuNSw2LjEtMSw4LjEtMS4zYzAuNS0xLjMsMS4zLTMuOCwwLjgtNy4xYy0xMC4yLDMuOC0yNS40LDguNC00My41LDguNEMtNjQ0LjcsMzQ4LjYtNjQ0LjcsMzQ5LjEtNjQ0LjQsMzQ5Ljl6Ii8+PGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8xNV8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTI4MS44NSIgeTE9IjI1Ny41MTg3IiB4Mj0iLTI4MS44NSIgeTI9IjI2Mi42NTExIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDIuNTQ0NSAwIDAgLTIuNTQ0NSAxMDAuMTI3MiAxMDE3LjgxMTcpIj48c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+PHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzM3OEY0MyIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCNTVkdJRF8xNV8pIiBkPSJNLTYxMC4xLDM0OC45bC0zLjEsMC4zYzAsMC4zLTAuMywwLjUtMC41LDAuOGMtMC41LDEtMSwxLjgtMS41LDIuOGMtMC4zLDAuNS0wLjUsMC44LTAuOCwxLjNjLTAuNSwxLTEuMywyLTIsMi44Yy0wLjMsMC4zLTAuMywwLjMtMC41LDAuNWMtMS44LDIuMy0zLjYsNC4zLTUuNiw1LjlsNi40LDIuOEMtNjEyLjYsMzU5LjMtNjEwLjYsMzUxLjctNjEwLjEsMzQ4Ljl6Ii8+PC9nPjwvZz48Zz48Zz48ZGVmcz48Y2lyY2xlIGlkPSJTVkdJRF8xNl8iIGN4PSItNDA3LjMiIGN5PSIzNDYuMyIgcj0iNDIuMiIvPjwvZGVmcz48Y2xpcFBhdGggaWQ9IlNWR0lEXzE3XyI+PHVzZSB4bGluazpocmVmPSIjU1ZHSURfMTZfIiAgb3ZlcmZsb3c9InZpc2libGUiLz48L2NsaXBQYXRoPjxwYXRoIGNsaXAtcGF0aD0idXJsKCNTVkdJRF8xN18pIiBmaWxsPSIjRkZGRkZGIiBkPSJNLTQwMS4xLDM0OS40YzAuMywwLjMsMC41LDAuOCwwLjUsMC44YzcuNCwxLDE4LjEsMCwyNi4yLTEuM2MtNC42LDkuOS0xMywxNi41LTIwLjQsMTYuNWMtMTQuMiwwLTI1LjItMTcuMy0yNS4yLTE3LjNjNC4zLTMuOCwxMS43LTE2LjUsMjIuMS0xNi41czE1LDUuOSwxNSw1LjlsMS4zLTEuOGMwLDAtNC44LTE3LTE4LjgtMTdzLTI4LjUsMjIuNi0zNy4yLDI4YzAsMCwxMiwyOCwzNy43LDI4YzIxLjYsMCwyNy4yLTIwLjksMjguMi0yNmMyLjgtMC41LDUuMy0wLjgsNi45LTFjMC41LTEuMywxLTMuMywwLjgtNi4xYy04LjcsMy4zLTIxLjYsNy4xLTM3LjIsNy4xQy00MDEuNCwzNDguMy00MDEuNCwzNDguOS00MDEuMSwzNDkuNHoiLz48L2c+PC9nPjwvZz48ZyBpZD0iTGF5ZXJfMiI+PHBhdGggZmlsbD0iIzg4ODg4OCIgZD0iTTQ2Ny4zLDIwOS45Yy00LjgsMjQuNC0zMC44LDEyMi42LTEzMy42LDEyMi42Yy0xMjIuNiwwLTE3OC42LTEzMi44LTE3OC42LTEzMi44YzQxLTI0LjksMTEwLjQtMTMyLjMsMTc2LjEtMTMyLjNzODguOCw4MS4yLDg4LjgsODEuMmwtNS42LDguOWMwLDAtMjEuNi0yNy4yLTcxLjItMjcuMnMtODMuNyw1OS44LTEwNC42LDc4LjRjMCwwLDUyLjIsODEuNywxMTkuMyw4MS43YzM2LjEsMCw3NS4xLTMxLjMsOTYuOS03OC40Yy0zOC4yLDUuMy04OC4zLDEwLjItMTIzLjcsNS42YzAsMC0xLjgtMS41LTIuNS0zLjNjLTEtMi4zLTEuMy00LjYtMS4zLTQuNmM3MC4yLDAsMTMwLjUtMTYuNSwxNzEuNS0zMS44QzQ4Ny43LDc3LjYsNDAyLjksMCwzMDAuMSwwYy0xMTAuNCwwLTIwMCw4OS42LTIwMCwyMDBzODkuNiwyMDAsMjAwLDIwMGMxMDguOSwwLDE5Ny41LTg3LDIwMC0xOTUuNEM0OTIuNSwyMDUuOSw0ODEsMjA3LjksNDY3LjMsMjA5Ljl6Ii8+PC9nPjwvc3ZnPg==',
674
		'give_cpt_icon' => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxOC4wLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCAxNTcuMSAxNTcuMiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMTU3LjEgMTU3LjI7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoJLnN0MHtmaWxsOiM2NkJCNkE7fQ0KCS5zdDF7ZmlsbDojNTQ2RTdBO30NCgkuc3Qye2ZpbGw6dXJsKCNTVkdJRF8xXyk7fQ0KCS5zdDN7ZmlsbDp1cmwoI1NWR0lEXzJfKTt9DQoJLnN0NHtmaWxsOnVybCgjU1ZHSURfM18pO30NCgkuc3Q1e2ZpbGw6dXJsKCNTVkdJRF80Xyk7fQ0KCS5zdDZ7ZmlsbDp1cmwoI1NWR0lEXzVfKTt9DQoJLnN0N3tmaWxsOnVybCgjU1ZHSURfNl8pO30NCgkuc3Q4e2ZpbGw6dXJsKCNTVkdJRF83Xyk7fQ0KCS5zdDl7ZmlsbDp1cmwoI1NWR0lEXzhfKTt9DQoJLnN0MTB7ZmlsbDp1cmwoI1NWR0lEXzlfKTt9DQoJLnN0MTF7ZmlsbDp1cmwoI1NWR0lEXzEwXyk7fQ0KCS5zdDEye2ZpbGw6dXJsKCNTVkdJRF8xMV8pO30NCgkuc3QxM3tmaWxsOnVybCgjU1ZHSURfMTJfKTt9DQoJLnN0MTR7ZmlsbDp1cmwoI1NWR0lEXzEzXyk7fQ0KCS5zdDE1e2ZpbGw6dXJsKCNTVkdJRF8xNF8pO30NCgkuc3QxNntmaWxsOiNGRkZGRkY7fQ0KCS5zdDE3e2ZpbGw6dXJsKCNTVkdJRF8xNV8pO30NCgkuc3QxOHtjbGlwLXBhdGg6dXJsKCNTVkdJRF8xN18pO2ZpbGw6I0ZGRkZGRjt9DQoJLnN0MTl7ZmlsbDojRjFGMkYyO30NCjwvc3R5bGU+DQo8ZyBpZD0iTGF5ZXJfMSI+DQoJPGNpcmNsZSBjbGFzcz0ic3QwIiBjeD0iLTE5OS40IiBjeT0iMTM2LjEiIHI9IjE2LjYiLz4NCgk8Zz4NCgkJPGc+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTM0OC40LDUyLjZ2LTQuOWgxLjljMS41LDAsMi42LDEsMi42LDIuNWMwLDEuNS0xLjEsMi41LTIuNiwyLjVILTM0OC40eiBNLTM0NC45LDUwLjENCgkJCQljMC0wLjktMC41LTEuNS0xLjUtMS41aC0wLjl2My4xaDAuOUMtMzQ1LjUsNTEuNy0zNDQuOSw1MS0zNDQuOSw1MC4xeiIvPg0KCQkJPHBhdGggY2xhc3M9InN0MSIgZD0iTS0zNDIuNiw1Mi42di00LjloMy41djAuOWgtMi40djFoMi40djAuOWgtMi40djEuMWgyLjR2MC45SC0zNDIuNnoiLz4NCgkJCTxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0tMzMzLjUsNTIuNnYtMy40bC0xLjQsMy40aC0wLjVsLTEuNC0zLjR2My40aC0xdi00LjloMS41bDEuMiwzbDEuMi0zaDEuNXY0LjlILTMzMy41eiIvPg0KCQkJPHBhdGggY2xhc3M9InN0MSIgZD0iTS0zMzEuMSw1MC4xYzAtMS41LDEuMS0yLjUsMi42LTIuNWMxLjUsMCwyLjYsMS4xLDIuNiwyLjVjMCwxLjUtMS4xLDIuNS0yLjYsMi41DQoJCQkJQy0zMzAuMSw1Mi43LTMzMS4xLDUxLjYtMzMxLjEsNTAuMXogTS0zMjcuMSw1MC4xYzAtMC45LTAuNi0xLjYtMS41LTEuNnMtMS41LDAuNy0xLjUsMS42YzAsMC45LDAuNiwxLjYsMS41LDEuNg0KCQkJCVMtMzI3LjEsNTEtMzI3LjEsNTAuMXoiLz4NCgkJCTxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0tMzI1LDUwLjFjMC0xLjUsMS4xLTIuNSwyLjYtMi41YzEuMSwwLDEuNywwLjYsMi4xLDEuMmwtMC45LDAuNGMtMC4yLTAuNC0wLjYtMC43LTEuMi0wLjcNCgkJCQljLTAuOSwwLTEuNSwwLjctMS41LDEuNmMwLDAuOSwwLjYsMS42LDEuNSwxLjZjMC41LDAsMC45LTAuMywxLjItMC43bDAuOSwwLjRjLTAuNCwwLjYtMSwxLjItMi4xLDEuMg0KCQkJCUMtMzIzLjgsNTIuNy0zMjUsNTEuNi0zMjUsNTAuMXoiLz4NCgkJCTxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0tMzE2LjMsNTIuNmwtMS0xLjdoLTAuOHYxLjdoLTF2LTQuOWgyLjNjMSwwLDEuNiwwLjcsMS42LDEuNmMwLDAuOS0wLjUsMS4zLTEuMSwxLjVsMS4xLDEuOUgtMzE2LjN6DQoJCQkJIE0tMzE2LjIsNDkuMmMwLTAuNC0wLjMtMC43LTAuNy0wLjdoLTEuMXYxLjNoMS4xQy0zMTYuNiw0OS45LTMxNi4yLDQ5LjctMzE2LjIsNDkuMnoiLz4NCgkJCTxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0tMzEwLjQsNTIuNmwtMC4zLTAuOGgtMi4xbC0wLjMsMC44aC0xLjJsMS45LTQuOWgxLjNsMS45LDQuOUgtMzEwLjR6IE0tMzExLjgsNDguN2wtMC44LDIuMWgxLjUNCgkJCQlMLTMxMS44LDQ4Ljd6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTMwNy42LDUyLjZ2LTRoLTEuNHYtMC45aDMuOXYwLjloLTEuNHY0SC0zMDcuNnoiLz4NCgkJCTxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0tMzAzLjksNTIuNnYtNC45aDF2NC45SC0zMDMuOXoiLz4NCgkJCTxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0tMzAxLjUsNTIuNnYtMC44bDIuMy0zLjFoLTIuM3YtMC45aDMuN3YwLjhsLTIuMywzLjJoMi40djAuOUgtMzAxLjV6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTI5Ni40LDUyLjZ2LTQuOWgxdjQuOUgtMjk2LjR6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTI5MC41LDUyLjZsLTIuMy0zLjJ2My4yaC0xdi00LjloMS4xbDIuMywzLjF2LTMuMWgxdjQuOUgtMjkwLjV6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTI4OC4yLDUwLjFjMC0xLjYsMS4yLTIuNSwyLjYtMi41YzEsMCwxLjcsMC41LDIsMS4xbC0wLjksMC41Yy0wLjItMC4zLTAuNi0wLjYtMS4yLTAuNg0KCQkJCWMtMC45LDAtMS41LDAuNy0xLjUsMS42YzAsMC45LDAuNiwxLjYsMS41LDEuNmMwLjQsMCwwLjgtMC4yLDEtMC40di0wLjZoLTEuM3YtMC45aDIuM3YxLjljLTAuNSwwLjYtMS4yLDAuOS0yLjEsMC45DQoJCQkJQy0yODcsNTIuNy0yODguMiw1MS43LTI4OC4yLDUwLjF6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTI3OS45LDUwLjFjMC0xLjYsMS4yLTIuNSwyLjYtMi41YzEsMCwxLjcsMC41LDIsMS4xbC0wLjksMC41Yy0wLjItMC4zLTAuNi0wLjYtMS4yLTAuNg0KCQkJCWMtMC45LDAtMS41LDAuNy0xLjUsMS42YzAsMC45LDAuNiwxLjYsMS41LDEuNmMwLjQsMCwwLjgtMC4yLDEtMC40di0wLjZoLTEuM3YtMC45aDIuM3YxLjljLTAuNSwwLjYtMS4yLDAuOS0yLjEsMC45DQoJCQkJQy0yNzguNyw1Mi43LTI3OS45LDUxLjctMjc5LjksNTAuMXoiLz4NCgkJCTxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0tMjczLjgsNTIuNnYtNC45aDMuNXYwLjloLTIuNHYxaDIuNHYwLjloLTIuNHYxLjFoMi40djAuOUgtMjczLjh6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTI2NS42LDUyLjZsLTIuMy0zLjJ2My4yaC0xdi00LjloMS4xbDIuMywzLjF2LTMuMWgxdjQuOUgtMjY1LjZ6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTI2Myw1Mi42di00LjloMy41djAuOWgtMi40djFoMi40djAuOWgtMi40djEuMWgyLjR2MC45SC0yNjN6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTI1NS40LDUyLjZsLTEtMS43aC0wLjh2MS43aC0xdi00LjloMi4zYzEsMCwxLjYsMC43LDEuNiwxLjZjMCwwLjktMC41LDEuMy0xLjEsMS41bDEuMSwxLjlILTI1NS40eg0KCQkJCSBNLTI1NS4zLDQ5LjJjMC0wLjQtMC4zLTAuNy0wLjctMC43aC0xLjF2MS4zaDEuMUMtMjU1LjYsNDkuOS0yNTUuMyw0OS43LTI1NS4zLDQ5LjJ6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTI1My4xLDUwLjFjMC0xLjUsMS4xLTIuNSwyLjYtMi41YzEuNSwwLDIuNiwxLjEsMi42LDIuNWMwLDEuNS0xLjEsMi41LTIuNiwyLjUNCgkJCQlDLTI1Mi4xLDUyLjctMjUzLjEsNTEuNi0yNTMuMSw1MC4xeiBNLTI0OS4xLDUwLjFjMC0wLjktMC42LTEuNi0xLjUtMS42Yy0wLjksMC0xLjUsMC43LTEuNSwxLjZjMCwwLjksMC42LDEuNiwxLjUsMS42DQoJCQkJQy0yNDkuNyw1MS43LTI0OS4xLDUxLTI0OS4xLDUwLjF6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTI0Ny4xLDUxLjlsMC42LTAuOGMwLjMsMC40LDAuOSwwLjcsMS42LDAuN2MwLjYsMCwwLjktMC4zLDAuOS0wLjVjMC0wLjktMi44LTAuMy0yLjgtMi4xDQoJCQkJYzAtMC44LDAuNy0xLjUsMS45LTEuNWMwLjgsMCwxLjQsMC4yLDEuOSwwLjdsLTAuNiwwLjhjLTAuNC0wLjQtMC45LTAuNS0xLjQtMC41Yy0wLjQsMC0wLjcsMC4yLTAuNywwLjVjMCwwLjgsMi44LDAuMywyLjgsMi4xDQoJCQkJYzAsMC45LTAuNiwxLjYtMiwxLjZDLTI0NS45LDUyLjctMjQ2LjYsNTIuMy0yNDcuMSw1MS45eiIvPg0KCQkJPHBhdGggY2xhc3M9InN0MSIgZD0iTS0yNDEuOCw1Mi42di00LjloMXY0LjlILTI0MS44eiIvPg0KCQkJPHBhdGggY2xhc3M9InN0MSIgZD0iTS0yMzguMSw1Mi42di00aC0xLjR2LTAuOWgzLjl2MC45aC0xLjR2NEgtMjM4LjF6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTIzMyw1Mi42di0ybC0xLjktMi45aDEuMmwxLjIsMmwxLjItMmgxLjJsLTEuOSwyLjl2MkgtMjMzeiIvPg0KCQk8L2c+DQoJCTxnPg0KCQkJPGc+DQoJCQkJPHBhdGggY2xhc3M9InN0MCIgZD0iTS0yMzAuMywxNy40bC0wLjUsMGwwLjEsMC41YzAuOCwzLjksMC4xLDkuNy0yLjksMTMuM2MtMS43LDIuMS0zLjksMy4yLTYuNiwzLjJjLTQuMywwLTUuOS01LjEtNi4xLTEwLjkNCgkJCQkJYzctMS43LDExLjctNi4xLDExLjctMTEuMmMwLTMuNy0xLjEtOS44LTguNC05LjhjLTYuOSwwLTEwLjQsMTAuMy0xMS4xLDE3LjVjLTMuNS0wLjEtNi4xLTEuNy03LjctMy4yYzAuNi0yLjUsMC45LTQuOCwwLjktNi45DQoJCQkJCWMwLTIuOS0yLTQuMi0zLjktNC4yYy0yLjcsMC01LjUsMi42LTUuNSw3LjZjMCwzLDEuMSw1LjUsMy40LDcuM2MtMiw0LjctNS40LDguNy02LjUsMTBjLTAuOS0xLjktMy44LTguOC00LjctMTYuMw0KCQkJCQljMS4xLTMsMS43LTUuNSwxLjctNi43YzAtMS45LTEuMi0zLTMuMi0zYy0yLjcsMC03LDEuNy03LjEsMS44bC0wLjIsMC4xbDAsMC4zYzAsMC4xLDEuMyw2LjEsMi42LDEyLjcNCgkJCQkJYy0yLjUsNC4xLTYuOSwxMC45LTkuMSwxMC45Yy00LDAsMi42LTIwLjUtMC4zLTIxLjJjLTAuMSwwLTAuMiwwLTAuMywwLjFjLTEuNCwwLjktMTcuMSw5LjYtMzgsOS42YzAsMCwwLDAuNCwwLjIsMC44DQoJCQkJCWMwLjEsMC4zLDAuNCwwLjYsMC40LDAuNmM1LjksMC43LDE0LjMtMC4xLDIwLjctMWMtMy43LDcuOS0xMC4yLDEzLjEtMTYuMiwxMy4xYy0xMS4zLDAtMjAtMTMuNy0yMC0xMy43DQoJCQkJCWMzLjUtMy4xLDkuMi0xMy4xLDE3LjYtMTMuMWM4LjMsMCwxMS45LDQuNiwxMS45LDQuNmwwLjktMS41YzAsMC0zLjktMTMuNi0xNC45LTEzLjZjLTExLDAtMjIuNywxOC0yOS41LDIyLjINCgkJCQkJYzAsMCw5LjQsMjIuMiwyOS45LDIyLjJjMTcuMiwwLDIxLjYtMTYuNSwyMi40LTIwLjVjNC4yLTAuNiw3LjEtMS4yLDcuMS0xLjJzLTEuMSw4LjQtMS4xLDExLjljMCwzLjUsMy45LDcuMiw3LjEsNy4yDQoJCQkJCWMyLjcsMCw4LjItNS42LDEyLjItMTIuNGwwLjIsMC44YzIuMSw3LjcsNC43LDExLjcsNy44LDExLjdjMy4xLDAsOC4yLTYuNCwxMS41LTE0LjVjMy4zLDEuNCw3LjIsMS44LDkuNSwxLjkNCgkJCQkJYzAuOSwxMy45LDEyLjUsMTQuMywxMy45LDE0LjNjOC42LDAsMTUuOS02LjIsMTUuOS0xMy41Qy0yMjQuMywxNy41LTIzMC4yLDE3LjQtMjMwLjMsMTcuNHogTS0yNDAuOCwxMS42YzAsMC0wLjEsNC42LTUuMyw2LjkNCgkJCQkJYzAuNS02LjEsMi0xMS42LDMtMTEuNkMtMjQyLDctMjQwLjgsOC43LTI0MC44LDExLjZ6Ii8+DQoJCQkJPHBhdGggY2xhc3M9InN0MCIgZD0iTS0zMDAuNyw2LjFjMCwwLjIsMC4xLDAuMywwLjMsMC40YzQuMSwwLjYsNi44LTAuNyw2LjgtNy4zYzAtNi4yLTYuNC0xLjMtNy42LTAuNA0KCQkJCQljLTAuMSwwLjEtMC4xLDAuMi0wLjEsMC40Qy0zMDAuMiwxLjYtMzAwLjYsNS4xLTMwMC43LDYuMXoiLz4NCgkJCTwvZz4NCgkJCTxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfMV8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTI4OS41ODQ0IiB5MT0iMjYuNzY4IiB4Mj0iLTI4Mi44ODIzIiB5Mj0iMjQuNTM0Ij4NCgkJCQk8c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+DQoJCQkJPHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzM3OEY0MyIvPg0KCQkJPC9saW5lYXJHcmFkaWVudD4NCgkJCTxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0tMjg0LjIsMTkuNGMtMS42LDIuNy00LDYuNC02LjEsOC43YzAuNSwxLjIsMS4xLDIuNywxLjcsMy45YzEuOS0yLjEsMy44LTQuOCw1LjUtNy42TC0yODQuMiwxOS40eiIvPg0KCQkJPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8yXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMjY5LjAxOTQiIHkxPSIyOC40Nzc3IiB4Mj0iLTI2NS4xMzIyIiB5Mj0iMjEuNjQxNiI+DQoJCQkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPg0KCQkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz4NCgkJCTwvbGluZWFyR3JhZGllbnQ+DQoJCQk8cGF0aCBjbGFzcz0ic3QzIiBkPSJNLTI2NS4yLDIxLjVjLTAuOC0wLjQtMS41LTEtMS41LTFjLTEuNCwzLjEtMy4zLDYtNC44LDcuOWMwLjcsMSwxLjksMi4zLDIuOCwzLjNjMS44LTIuNSwzLjctNS44LDUuMS05LjMNCgkJCQlDLTI2My41LDIyLjMtMjY0LjQsMjItMjY1LjIsMjEuNXoiLz4NCgkJCTxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfM18iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTI0OC42MjU0IiB5MT0iMzEuNjE0NyIgeDI9Ii0yNDkuNDI5NyIgeTI9IjI0LjQ2NTkiPg0KCQkJCTxzdG9wICBvZmZzZXQ9IjAiIHN0eWxlPSJzdG9wLWNvbG9yOiM2NkJCNkEiLz4NCgkJCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojMzc4RjQzIi8+DQoJCQk8L2xpbmVhckdyYWRpZW50Pg0KCQkJPHBhdGggY2xhc3M9InN0NCIgZD0iTS0yNDYuMiwyMy41YzAsMC0yLDAuNC00LDAuNmMtMiwwLjItMy45LDAuMS0zLjksMC4xYzAuMyw0LDEuNCw2LjgsMi45LDguOWw3LjMtMC42DQoJCQkJQy0yNDUuNCwzMC41LTI0Ni4xLDI3LjEtMjQ2LjIsMjMuNXoiLz4NCgkJCTxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfNF8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTI0OS43MjY3IiB5MT0iMTYuNDE5IiB4Mj0iLTI0OS43MjY3IiB5Mj0iMjMuNjIzNyI+DQoJCQkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPg0KCQkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz4NCgkJCTwvbGluZWFyR3JhZGllbnQ+DQoJCQk8cGF0aCBjbGFzcz0ic3Q1IiBkPSJNLTI1MiwxMS4zTC0yNTIsMTEuM2MtMC4yLDAuNi0wLjUsMS4zLTAuNywyYzAsMC4yLTAuMSwwLjMtMC4xLDAuNWMtMC40LDEuMy0wLjcsMi42LTAuOSwzLjkNCgkJCQljMCwwLjItMC4xLDAuMy0wLjEsMC41Yy0wLjEsMC42LTAuMiwxLjItMC4yLDEuOGM0LjcsMCw3LjktMS40LDcuOS0xLjRjMC0wLjUsMC4xLTAuOSwwLjEtMS40YzAtMC4xLDAtMC4yLDAtMC4zDQoJCQkJYzAtMC40LDAuMS0wLjcsMC4xLTEuMWMwLTAuMSwwLTAuMiwwLTAuM2MwLjEtMC45LDAuMy0xLjgsMC40LTIuNkwtMjUyLDExLjN6IE0tMjU0LjEsMTkuOUMtMjU0LjEsMTkuOS0yNTQuMSwxOS45LTI1NC4xLDE5LjkNCgkJCQlMLTI1NC4xLDE5LjlDLTI1NC4xLDE5LjktMjU0LjEsMTkuOS0yNTQuMSwxOS45eiIvPg0KCQkJPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF81XyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMzEzLjAyNzIiIHkxPSIyOC4yMjc4IiB4Mj0iLTMxMy4wMjcyIiB5Mj0iMTkuMjkxNyI+DQoJCQkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPg0KCQkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz4NCgkJCTwvbGluZWFyR3JhZGllbnQ+DQoJCQk8cGF0aCBjbGFzcz0ic3Q2IiBkPSJNLTMxNy43LDI4LjZsNC40LDEuOWMyLjEtMywzLjQtNi4xLDQuMi04LjVsMC44LTMuMmwtMi4xLDAuM0MtMzEyLjMsMjMuMS0zMTQuOSwyNi4zLTMxNy43LDI4LjZ6Ii8+DQoJCQk8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzZfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ii0yNzcuNTIzOSIgeTE9IjkuNzg4IiB4Mj0iLTI3OC42NDYzIiB5Mj0iMTEuNTc1NiI+DQoJCQkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPg0KCQkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz4NCgkJCTwvbGluZWFyR3JhZGllbnQ+DQoJCQk8cGF0aCBjbGFzcz0ic3Q3IiBkPSJNLTI3Ny45LDE0LjJjMS4xLTMsMS43LTUuNSwxLjctNi43YzAtMC4xLDAtMC4yLDAtMC4zbC0yLjYsMC44Qy0yNzguOCw4LTI3OC43LDkuNy0yNzcuOSwxNC4yeiIvPg0KCQkJPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF83XyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMjYyLjU1MjkiIHkxPSIxMy41MjQ4IiB4Mj0iLTI2My4xODY2IiB5Mj0iMTUuOTMyNiI+DQoJCQkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPg0KCQkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz4NCgkJCTwvbGluZWFyR3JhZGllbnQ+DQoJCQk8cGF0aCBjbGFzcz0ic3Q4IiBkPSJNLTI2My45LDEyYzAsMC0wLjcsMi4xLDIuMiw0LjdjMC41LTIuMSwwLjgtNC4yLDAuOS02TC0yNjMuOSwxMnoiLz4NCgkJPC9nPg0KCTwvZz4NCgk8Zz4NCgkJPGc+DQoJCQk8cGF0aCBjbGFzcz0ic3QwIiBkPSJNLTM1Ni44LDEzNi4ybC0wLjIsMGwwLDAuMmMwLjMsMS43LDAsNC4xLTEuMiw1LjdjLTAuNywwLjktMS43LDEuNC0yLjgsMS40Yy0xLjgsMC0yLjUtMi4yLTIuNi00LjYNCgkJCQljMy0wLjcsNS0yLjYsNS00LjhjMC0xLjYtMC41LTQuMi0zLjYtNC4yYy0yLjksMC00LjQsNC40LTQuNyw3LjRjLTEuNSwwLTIuNi0wLjctMy4zLTEuNGMwLjMtMS4xLDAuNC0yLDAuNC0yLjkNCgkJCQljMC0xLjItMC45LTEuOC0xLjYtMS44Yy0xLjIsMC0yLjMsMS4xLTIuMywzLjJjMCwxLjMsMC41LDIuMywxLjUsMy4xYy0wLjksMi0yLjMsMy43LTIuOCw0LjJjLTAuNC0wLjgtMS42LTMuOC0yLTYuOQ0KCQkJCWMwLjUtMS4zLDAuNy0yLjMsMC43LTIuOGMwLTAuOC0wLjUtMS4zLTEuNC0xLjNjLTEuMiwwLTMsMC43LTMsMC44bC0wLjEsMC4xbDAsMC4xYzAsMCwwLjUsMi42LDEuMSw1LjQNCgkJCQljLTEuMSwxLjctMi45LDQuNi0zLjksNC42Yy0xLjcsMCwxLjEtOC43LTAuMS05YzAsMC0wLjEsMC0wLjEsMGMtMC42LDAuNC03LjMsNC4xLTE2LjEsNC4xYzAsMCwwLDAuMiwwLjEsMC4zDQoJCQkJYzAuMSwwLjEsMC4yLDAuMiwwLjIsMC4yYzIuNSwwLjMsNi4xLDAsOC44LTAuNGMtMS42LDMuMy00LjMsNS42LTYuOSw1LjZjLTQuOCwwLTguNS01LjgtOC41LTUuOGMxLjUtMS4zLDMuOS01LjYsNy41LTUuNg0KCQkJCWMzLjUsMCw1LjEsMS45LDUuMSwxLjlsMC40LTAuNmMwLDAtMS43LTUuOC02LjMtNS44cy05LjYsNy43LTEyLjUsOS40YzAsMCw0LDkuNSwxMi43LDkuNWM3LjMsMCw5LjItNyw5LjUtOC43DQoJCQkJYzEuOC0wLjMsMy0wLjUsMy0wLjVzLTAuNCwzLjYtMC40LDUuMXMxLjYsMy4xLDMsMy4xYzEuMiwwLDMuNS0yLjQsNS4yLTUuM2wwLjEsMC4zYzAuOSwzLjMsMiw1LDMuMyw1YzEuMywwLDMuNS0yLjcsNC45LTYuMQ0KCQkJCWMxLjQsMC42LDMuMSwwLjgsNCwwLjhjMC40LDUuOSw1LjMsNi4xLDUuOSw2LjFjMy43LDAsNi44LTIuNiw2LjgtNS43Qy0zNTQuMywxMzYuMy0zNTYuOCwxMzYuMi0zNTYuOCwxMzYuMnogTS0zNjEuMiwxMzMuNw0KCQkJCWMwLDAsMCwyLTIuMywzYzAuMi0yLjYsMC44LTQuOSwxLjMtNC45Qy0zNjEuOCwxMzEuOC0zNjEuMiwxMzIuNS0zNjEuMiwxMzMuN3oiLz4NCgkJCTxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0tMzg2LjcsMTMxLjRjMCwwLjEsMCwwLjEsMC4xLDAuMmMxLjcsMC4yLDIuOS0wLjMsMi45LTMuMWMwLTIuNi0yLjctMC42LTMuMi0wLjJjMCwwLTAuMSwwLjEsMCwwLjINCgkJCQlDLTM4Ni41LDEyOS41LTM4Ni43LDEzMC45LTM4Ni43LDEzMS40eiIvPg0KCQk8L2c+DQoJCTxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfOF8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTM4MS45OTkzIiB5MT0iMTQwLjE3NjkiIHgyPSItMzc5LjE1MDQiIHkyPSIxMzkuMjI3MiI+DQoJCQk8c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+DQoJCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojMzc4RjQzIi8+DQoJCTwvbGluZWFyR3JhZGllbnQ+DQoJCTxwYXRoIGNsYXNzPSJzdDkiIGQ9Ik0tMzc5LjcsMTM3Yy0wLjcsMS4xLTEuNywyLjctMi42LDMuN2MwLjIsMC41LDAuNSwxLjEsMC43LDEuN2MwLjgtMC45LDEuNi0yLDIuNC0zLjJMLTM3OS43LDEzN3oiLz4NCgkJPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF85XyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMzczLjI1NzUiIHkxPSIxNDAuOTAzNyIgeDI9Ii0zNzEuNjA1MSIgeTI9IjEzNy45OTc4Ij4NCgkJCTxzdG9wICBvZmZzZXQ9IjAiIHN0eWxlPSJzdG9wLWNvbG9yOiM2NkJCNkEiLz4NCgkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz4NCgkJPC9saW5lYXJHcmFkaWVudD4NCgkJPHBhdGggY2xhc3M9InN0MTAiIGQ9Ik0tMzcxLjYsMTM3LjljLTAuMy0wLjItMC42LTAuNC0wLjYtMC40Yy0wLjYsMS4zLTEuNCwyLjUtMiwzLjRjMC4zLDAuNCwwLjgsMSwxLjIsMS40DQoJCQljMC44LTEuMSwxLjYtMi40LDIuMi00Qy0zNzAuOSwxMzguMy0zNzEuMywxMzguMS0zNzEuNiwxMzcuOXoiLz4NCgkJPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8xMF8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTM2NC41ODg0IiB5MT0iMTQyLjIzNzIiIHgyPSItMzY0LjkzMDMiIHkyPSIxMzkuMTk4MyI+DQoJCQk8c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+DQoJCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojMzc4RjQzIi8+DQoJCTwvbGluZWFyR3JhZGllbnQ+DQoJCTxwYXRoIGNsYXNzPSJzdDExIiBkPSJNLTM2My42LDEzOC44YzAsMC0wLjgsMC4yLTEuNywwLjNjLTAuOCwwLjEtMS43LDAtMS43LDBjMC4xLDEuNywwLjYsMi45LDEuMiwzLjhsMy4xLTAuMw0KCQkJQy0zNjMuMiwxNDEuOC0zNjMuNSwxNDAuMy0zNjMuNiwxMzguOHoiLz4NCgkJPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8xMV8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTM2NS4wNTY2IiB5MT0iMTM1Ljc3NzciIHgyPSItMzY1LjA1NjYiIHkyPSIxMzguODQwMyI+DQoJCQk8c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+DQoJCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojMzc4RjQzIi8+DQoJCTwvbGluZWFyR3JhZGllbnQ+DQoJCTxwYXRoIGNsYXNzPSJzdDEyIiBkPSJNLTM2NiwxMzMuNkwtMzY2LDEzMy42Yy0wLjEsMC4zLTAuMiwwLjYtMC4zLDAuOGMwLDAuMSwwLDAuMS0wLjEsMC4yYy0wLjIsMC42LTAuMywxLjEtMC40LDEuNw0KCQkJYzAsMC4xLDAsMC4xLDAsMC4yYzAsMC4zLTAuMSwwLjUtMC4xLDAuOGMyLDAsMy40LTAuNiwzLjQtMC42YzAtMC4yLDAtMC40LDAuMS0wLjZjMCwwLDAtMC4xLDAtMC4xYzAtMC4yLDAtMC4zLDAuMS0wLjQNCgkJCWMwLDAsMC0wLjEsMC0wLjFjMC4xLTAuNCwwLjEtMC44LDAuMi0xLjFMLTM2NiwxMzMuNnogTS0zNjYuOSwxMzcuM0MtMzY2LjksMTM3LjMtMzY2LjksMTM3LjMtMzY2LjksMTM3LjNMLTM2Ni45LDEzNy4zDQoJCQlDLTM2Ni45LDEzNy4zLTM2Ni45LDEzNy4zLTM2Ni45LDEzNy4zeiIvPg0KCQk8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzEyXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMzkxLjk2NDQiIHkxPSIxNDAuNzk3NSIgeDI9Ii0zOTEuOTY0NCIgeTI9IjEzNi45OTg5Ij4NCgkJCTxzdG9wICBvZmZzZXQ9IjAiIHN0eWxlPSJzdG9wLWNvbG9yOiM2NkJCNkEiLz4NCgkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz4NCgkJPC9saW5lYXJHcmFkaWVudD4NCgkJPHBhdGggY2xhc3M9InN0MTMiIGQ9Ik0tMzk0LDE0MWwxLjksMC44YzAuOS0xLjMsMS40LTIuNiwxLjgtMy42bDAuMy0xLjRsLTAuOSwwLjFDLTM5MS43LDEzOC42LTM5Mi43LDE0MC0zOTQsMTQxeiIvPg0KCQk8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzEzXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMzc2Ljg3MjYiIHkxPSIxMzIuOTU5IiB4Mj0iLTM3Ny4zNDk4IiB5Mj0iMTMzLjcxODkiPg0KCQkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPg0KCQkJPHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzM3OEY0MyIvPg0KCQk8L2xpbmVhckdyYWRpZW50Pg0KCQk8cGF0aCBjbGFzcz0ic3QxNCIgZD0iTS0zNzcsMTM0LjhjMC41LTEuMywwLjctMi4zLDAuNy0yLjhjMCwwLDAtMC4xLDAtMC4xbC0xLjEsMC4zQy0zNzcuNCwxMzIuMi0zNzcuNCwxMzIuOS0zNzcsMTM0Ljh6Ii8+DQoJCTxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfMTRfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ii0zNzAuNTA4OCIgeTE9IjEzNC41NDc1IiB4Mj0iLTM3MC43NzgxIiB5Mj0iMTM1LjU3MSI+DQoJCQk8c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+DQoJCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojMzc4RjQzIi8+DQoJCTwvbGluZWFyR3JhZGllbnQ+DQoJCTxwYXRoIGNsYXNzPSJzdDE1IiBkPSJNLTM3MS4xLDEzMy45YzAsMC0wLjMsMC45LDAuOSwyYzAuMi0wLjksMC40LTEuOCwwLjQtMi42TC0zNzEuMSwxMzMuOXoiLz4NCgk8L2c+DQoJPGc+DQoJCTxyZWN0IHg9Ii0zMTMuNCIgeT0iMTE1LjEiIGNsYXNzPSJzdDE2IiB3aWR0aD0iNDIiIGhlaWdodD0iNDIiLz4NCgkJPGc+DQoJCQk8cGF0aCBjbGFzcz0ic3QwIiBkPSJNLTI5Mi42LDEzNy41YzAuMSwwLjIsMC4yLDAuMywwLjIsMC4zYzMuNCwwLjQsOC4zLDAsMTItMC42Yy0yLjEsNC42LTUuOSw3LjYtOS40LDcuNg0KCQkJCWMtNi41LDAtMTEuNi03LjktMTEuNi03LjljMi0xLjgsNS40LTcuNiwxMC4yLTcuNnM2LjksMi42LDYuOSwyLjZsMC41LTAuOWMwLDAtMi4zLTcuOS04LjYtNy45Yy02LjQsMC0xMy4xLDEwLjQtMTcuMSwxMi44DQoJCQkJYzAsMCw1LjQsMTIuOSwxNy4zLDEyLjljMTAsMCwxMi41LTkuNSwxMy0xMS45YzEuMy0wLjIsMi40LTAuNCwzLjItMC41YzAuMi0wLjUsMC41LTEuNSwwLjMtMi44Yy00LDEuNS0xMCwzLjMtMTcuMSwzLjMNCgkJCQlDLTI5Mi43LDEzNy0yOTIuNywxMzcuMi0yOTIuNiwxMzcuNXoiLz4NCgkJCTxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfMTVfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ii0yODEuNzk2MiIgeTE9IjE0Mi40ODEzIiB4Mj0iLTI4MS43OTYyIiB5Mj0iMTM3LjM0ODkiPg0KCQkJCTxzdG9wICBvZmZzZXQ9IjAiIHN0eWxlPSJzdG9wLWNvbG9yOiM2NkJCNkEiLz4NCgkJCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojMzc4RjQzIi8+DQoJCQk8L2xpbmVhckdyYWRpZW50Pg0KCQkJPHBhdGggY2xhc3M9InN0MTciIGQ9Ik0tMjc5LjEsMTM3LjFsLTEuMiwwLjFjMCwwLjEtMC4xLDAuMi0wLjIsMC4zYy0wLjIsMC40LTAuNCwwLjctMC42LDEuMWMtMC4xLDAuMi0wLjIsMC4zLTAuMywwLjUNCgkJCQljLTAuMiwwLjQtMC41LDAuOC0wLjgsMS4xYy0wLjEsMC4xLTAuMSwwLjEtMC4yLDAuMmMtMC43LDAuOS0xLjQsMS43LTIuMiwyLjNsMi41LDEuMUMtMjgwLjEsMTQxLjItMjc5LjMsMTM4LjItMjc5LjEsMTM3LjF6Ii8+DQoJCTwvZz4NCgk8L2c+DQoJPGc+DQoJCTxkZWZzPg0KCQkJPGNpcmNsZSBpZD0iU1ZHSURfMTZfIiBjeD0iLTE5OS40IiBjeT0iMTM2LjEiIHI9IjE2LjYiLz4NCgkJPC9kZWZzPg0KCQk8Y2xpcFBhdGggaWQ9IlNWR0lEXzE3XyI+DQoJCQk8dXNlIHhsaW5rOmhyZWY9IiNTVkdJRF8xNl8iICBzdHlsZT0ib3ZlcmZsb3c6dmlzaWJsZTsiLz4NCgkJPC9jbGlwUGF0aD4NCgkJPHBhdGggY2xhc3M9InN0MTgiIGQ9Ik0tMTk3LDEzNy4zYzAuMSwwLjEsMC4yLDAuMywwLjIsMC4zYzIuOSwwLjQsNy4xLDAsMTAuMy0wLjVjLTEuOCwzLjktNS4xLDYuNS04LDYuNWMtNS42LDAtOS45LTYuOC05LjktNi44DQoJCQljMS43LTEuNSw0LjYtNi41LDguNy02LjVzNS45LDIuMyw1LjksMi4zbDAuNS0wLjdjMCwwLTEuOS02LjctNy40LTYuN3MtMTEuMiw4LjktMTQuNiwxMWMwLDAsNC43LDExLDE0LjgsMTENCgkJCWM4LjUsMCwxMC43LTguMiwxMS4xLTEwLjJjMS4xLTAuMiwyLjEtMC4zLDIuNy0wLjRjMC4yLTAuNSwwLjQtMS4zLDAuMy0yLjRjLTMuNCwxLjMtOC41LDIuOC0xNC42LDIuOA0KCQkJQy0xOTcuMSwxMzYuOS0xOTcuMSwxMzcuMS0xOTcsMTM3LjN6Ii8+DQoJPC9nPg0KPC9nPg0KPGcgaWQ9IkxheWVyXzIiPg0KCTxwYXRoIGNsYXNzPSJzdDE5IiBkPSJNMTQ0LjMsODIuNWMtMS45LDkuNi0xMi4xLDQ4LjItNTIuNSw0OC4yYy00OC4yLDAtNzAuMi01Mi4yLTcwLjItNTIuMmMxNi4xLTkuOCw0My40LTUyLDY5LjItNTINCgkJczM0LjksMzEuOSwzNC45LDMxLjlsLTIuMiwzLjVjMCwwLTguNS0xMC43LTI4LTEwLjdTNjIuNiw3NC43LDU0LjQsODJjMCwwLDIwLjUsMzIuMSw0Ni45LDMyLjFjMTQuMiwwLDI5LjUtMTIuMywzOC4xLTMwLjgNCgkJYy0xNSwyLjEtMzQuNyw0LTQ4LjYsMi4yYzAsMC0wLjctMC42LTEtMS4zYy0wLjQtMC45LTAuNS0xLjgtMC41LTEuOGMyNy42LDAsNTEuMy02LjUsNjcuNC0xMi41QzE1Mi4zLDMwLjUsMTE5LDAsNzguNiwwDQoJCUMzNS4yLDAsMCwzNS4yLDAsNzguNmMwLDQzLjQsMzUuMiw3OC42LDc4LjYsNzguNmM0Mi44LDAsNzcuNi0zNC4yLDc4LjYtNzYuOEMxNTQuMiw4MC45LDE0OS43LDgxLjcsMTQ0LjMsODIuNXoiLz4NCjwvZz4NCjwvc3ZnPg0K',
675
	);
676
677
	// Return the chosen icon's SVG string
678
	return $svgs[ $icon ];
679
}
680
681
/**
682
 * Modify Admin Nav Menu Label
683
 *
684
 * @since 1.3
685
 *
686
 * @param object $post_type The current object to add a menu items meta box for.
687
 *
688
 * @return mixed
689
 */
690
function modify_nav_menu_meta_box_object( $post_type ) {
691
	if ( isset( $post_type->name ) && $post_type->name == 'give_forms' ) {
0 ignored issues
show
Found "== '". Use Yoda Condition checks, you must
Loading history...
692
		$post_type->labels->name = esc_html__( 'Donation Forms', 'give' );
693
	}
694
695
	return $post_type;
696
}
697
698
add_filter( 'nav_menu_meta_box_object', 'modify_nav_menu_meta_box_object' );
699
700
/**
701
 * Show Donation Forms Post Type in Appearance > Menus by default on fresh install.
702
 *
703
 * @since 1.8.14
704
 *
705
 * @todo  Remove this, when WordPress Core ticket is resolved (https://core.trac.wordpress.org/ticket/16828).
706
 *
707
 * @return bool
708
 */
709
function give_donation_metabox_menu() {
710
711
	// Get Current Screen.
712
	$screen = get_current_screen();
713
714
	// Proceed, if current screen is navigation menus.
715
	if ( 'nav-menus' === $screen->id && give_is_setting_enabled( give_get_option( 'forms_singular' ) ) && ! get_user_option( 'give_is_donation_forms_menu_updated' ) ) {
716
717
		// Return false, if it fails to retrieve hidden meta box list and is not admin.
718
		if ( ! is_admin() || ( ! $hidden_meta_boxes = get_user_option( 'metaboxhidden_nav-menus' ) ) ) {
719
			return false;
720
		}
721
722
		// Return false, In case, we don't find 'Donation Form' in hidden meta box list.
723
		if ( ! in_array( 'add-post-type-give_forms', $hidden_meta_boxes, true ) ) {
724
			return false;
725
		}
726
727
		// Exclude 'Donation Form' value from hidden meta box's list.
728
		$hidden_meta_boxes = array_diff( $hidden_meta_boxes, array( 'add-post-type-give_forms' ) );
729
730
		// Get current user ID.
731
		$user = wp_get_current_user();
732
733
		update_user_option( $user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true );
734
		update_user_option( $user->ID, 'give_is_donation_forms_menu_updated', true, true );
735
	}
736
}
737
738
add_action( 'current_screen', 'give_donation_metabox_menu' );
739
740
/**
741
 * Array_column backup usage
742
 *
743
 * This file is part of the array_column library.
744
 *
745
 * @since      : 1.3.0.1
746
 *
747
 * @copyright  Copyright (c) Ben Ramsey (http://benramsey.com)
748
 * @license    https://opensource.org/licenses/MIT MIT
749
 */
750
751
if ( ! function_exists( 'array_column' ) ) {
752
	/**
753
	 * Returns the values from a single column of the input array, identified by
754
	 * the $columnKey.
755
	 *
756
	 * Optionally, you may provide an $indexKey to index the values in the returned
757
	 * array by the values from the $indexKey column in the input array.
758
	 *
759
	 * @param array      $input     A multi-dimensional array (record set) from which to pull
760
	 *                              a column of values.
761
	 * @param int|string $columnKey The column of values to return. This value may be the
762
	 *                              integer key of the column you wish to retrieve, or it
763
	 *                              may be the string key name for an associative array.
764
	 * @param mixed      $indexKey  (Optional.) The column to use as the index/keys for
765
	 *                              the returned array. This value may be the integer key
766
	 *                              of the column, or it may be the string key name.
767
	 *
768
	 * @return array
769
	 */
770
	function array_column( $input = null, $columnKey = null, $indexKey = null ) {
0 ignored issues
show
The parameter $input is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $columnKey is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $indexKey is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
771
		// Using func_get_args() in order to check for proper number of
772
		// parameters and trigger errors exactly as the built-in array_column()
773
		// does in PHP 5.5.
774
		$argc   = func_num_args();
775
		$params = func_get_args();
776
777
		if ( $argc < 2 ) {
778
			trigger_error( sprintf( esc_html__( 'array_column() expects at least 2 parameters, %s given.', 'give' ), $argc ), E_USER_WARNING );
779
780
			return null;
781
		}
782
783
		if ( ! is_array( $params[0] ) ) {
784
			trigger_error( sprintf( esc_html__( 'array_column() expects parameter 1 to be array, %s given.', 'give' ), gettype( $params[0] ) ), E_USER_WARNING );
785
786
			return null;
787
		}
788
789 View Code Duplication
		if ( ! is_int( $params[1] ) && ! is_float( $params[1] ) && ! is_string( $params[1] ) && $params[1] !== null && ! ( is_object( $params[1] ) && method_exists( $params[1], '__toString' ) ) ) {
0 ignored issues
show
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...
790
			trigger_error( esc_html__( 'array_column(): The column key should be either a string or an integer.', 'give' ), E_USER_WARNING );
791
792
			return false;
793
		}
794
795 View Code Duplication
		if ( isset( $params[2] ) && ! is_int( $params[2] ) && ! is_float( $params[2] ) && ! is_string( $params[2] ) && ! ( is_object( $params[2] ) && method_exists( $params[2], '__toString' ) ) ) {
0 ignored issues
show
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...
796
			trigger_error( esc_html__( 'array_column(): The index key should be either a string or an integer.', 'give' ), E_USER_WARNING );
797
798
			return false;
799
		}
800
801
		$paramsInput     = $params[0];
802
		$paramsColumnKey = ( $params[1] !== null ) ? (string) $params[1] : null;
803
804
		$paramsIndexKey = null;
805
		if ( isset( $params[2] ) ) {
806
			if ( is_float( $params[2] ) || is_int( $params[2] ) ) {
807
				$paramsIndexKey = (int) $params[2];
808
			} else {
809
				$paramsIndexKey = (string) $params[2];
810
			}
811
		}
812
813
		$resultArray = array();
814
815
		foreach ( $paramsInput as $row ) {
816
			$key    = $value = null;
817
			$keySet = $valueSet = false;
818
819
			if ( $paramsIndexKey !== null && array_key_exists( $paramsIndexKey, $row ) ) {
820
				$keySet = true;
821
				$key    = (string) $row[ $paramsIndexKey ];
822
			}
823
824
			if ( $paramsColumnKey === null ) {
825
				$valueSet = true;
826
				$value    = $row;
827
			} elseif ( is_array( $row ) && array_key_exists( $paramsColumnKey, $row ) ) {
828
				$valueSet = true;
829
				$value    = $row[ $paramsColumnKey ];
830
			}
831
832
			if ( $valueSet ) {
833
				if ( $keySet ) {
834
					$resultArray[ $key ] = $value;
835
				} else {
836
					$resultArray[] = $value;
837
				}
838
			}
839
		}
840
841
		return $resultArray;
842
	}
843
}// End if().
844
845
/**
846
 * Determines the receipt visibility status.
847
 *
848
 * @since 1.3.2
849
 *
850
 * @param int $donation_id Donation ID.
851
 *
852
 * @return bool Whether the receipt is visible or not.
853
 */
854
function give_can_view_receipt( $donation_id ) {
855
856
	global $give_receipt_args;
857
858
	$donor            = false;
859
	$can_view_receipt = false;
860
861
	// Bail out, if donation id doesn't exist.
862
	if ( empty( $donation_id ) ) {
863
		return $can_view_receipt;
864
	}
865
866
	$give_receipt_args['id'] = $donation_id;
867
868
	// Add backward compatibility.
869
	if ( ! is_numeric( $donation_id ) ) {
870
		$give_receipt_args['id'] = give_get_donation_id_by_key( $donation_id );
871
	}
872
873
	// Return to download receipts from admin panel.
874
	if ( current_user_can( 'export_give_reports' ) ) {
875
876
	    /**
877
	     * This filter will be used to modify can view receipt response when accessed from admin.
878
         *
879
         * @since 2.3.1
880
	     */
881
		return apply_filters( 'give_can_admin_view_receipt', true );
882
	}
883
884
	if ( is_user_logged_in() || current_user_can( 'view_give_sensitive_data' ) ) {
885
886
		// Proceed only, if user is logged in or can view sensitive Give data.
887
		$donor = Give()->donors->get_donor_by( 'user_id', get_current_user_id() );
888
889
	} elseif ( ! is_user_logged_in() ) {
890
891
		// Check whether it is purchase session?
892
		// This condition is to show receipt to donor after donation.
893
		$purchase_session = give_get_purchase_session();
894
895
		if (
896
			! empty( $purchase_session )
897
			&& absint( $purchase_session['donation_id'] ) === absint( $donation_id )
898
		) {
899
			$donor = Give()->donors->get_donor_by( 'email', $purchase_session['user_email'] );
900
		}
901
902
		// Check whether it is receipt access session?
903
		$receipt_session    = give_get_receipt_session();
904
		$email_access_token = ! empty( $_COOKIE['give_nl'] ) ? give_clean( $_COOKIE['give_nl'] ) : false;
0 ignored issues
show
Due to using Batcache, server side based client related logic will not work, use JS instead.
Loading history...
905
906
		if (
907
			! empty( $receipt_session ) ||
908
			(
909
				give_is_setting_enabled( give_get_option( 'email_access' ) ) &&
910
				! empty( $email_access_token )
911
			)
912
		) {
913
			$donor              = ! empty( $email_access_token )
914
				? Give()->donors->get_donor_by_token( $email_access_token )
0 ignored issues
show
$email_access_token is of type string|array, but the function expects a integer.

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...
915
				: false ;
916
		}
917
	}
918
919
	// If donor object exists, compare the donation ids of donor with the donation receipt donor tries to access.
920
	if ( is_object( $donor ) ) {
921
		$is_donor_donated = in_array( (int) $donation_id, array_map( 'absint', explode( ',', $donor->payment_ids ) ), true );
922
		$can_view_receipt = $is_donor_donated ? true : $can_view_receipt;
923
924
		if( ! $is_donor_donated ) {
0 ignored issues
show
Space after opening control structure is required
Loading history...
No space before opening parenthesis is prohibited
Loading history...
925
			Give()->session->set( 'donor_donation_mismatch', true );
926
		}
927
	}
928
929
	return (bool) apply_filters( 'give_can_view_receipt', $can_view_receipt, $donation_id );
930
931
}
932
933
/**
934
 * Fallback for cal_days_in_month
935
 *
936
 * Fallback in case the calendar extension is not loaded in PHP; Only supports Gregorian calendar
937
 */
938
if ( ! function_exists( 'cal_days_in_month' ) ) {
939
	/**
940
	 * cal_days_in_month
941
	 *
942
	 * @param int $calendar
943
	 * @param int $month
944
	 * @param int $year
945
	 *
946
	 * @return bool|string
947
	 */
948
	function cal_days_in_month( $calendar, $month, $year ) {
0 ignored issues
show
The parameter $calendar is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
949
		return date( 't', mktime( 0, 0, 0, $month, 1, $year ) );
950
	}
951
}
952
953
/**
954
 * Get plugin info including status, type, and license validation.
955
 *
956
 * This is an enhanced version of get_plugins() that returns the status
957
 * (`active` or `inactive`) of all plugins, type of plugin (`add-on` or `other`
958
 * and license validation for Give add-ons (`true` or `false`). Does not include
959
 * MU plugins.
960
 *
961
 * @since 1.8.0
962
 *
963
 * @return array Plugin info plus status, type, and license validation if
964
 *               available.
965
 */
966
function give_get_plugins() {
967
	$plugins             = get_plugins();
968
	$active_plugin_paths = (array) get_option( 'active_plugins', array() );
969
970 View Code Duplication
	if ( is_multisite() ) {
0 ignored issues
show
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...
971
		$network_activated_plugin_paths = array_keys( get_site_option( 'active_sitewide_plugins', array() ) );
972
		$active_plugin_paths            = array_merge( $active_plugin_paths, $network_activated_plugin_paths );
973
	}
974
975
	foreach ( $plugins as $plugin_path => $plugin_data ) {
976
		// Is plugin active?
977
		if ( in_array( $plugin_path, $active_plugin_paths ) ) {
978
			$plugins[ $plugin_path ]['Status'] = 'active';
979
		} else {
980
			$plugins[ $plugin_path ]['Status'] = 'inactive';
981
		}
982
983
		$dirname = strtolower( dirname( $plugin_path ) );
984
985
		// Is the plugin a Give add-on?
986
		if ( strstr( $dirname, 'give-' ) && strstr( $plugin_data['AuthorURI'], 'wordimpress.com' ) ) {
987
			// Plugin is a Give-addon.
988
			$plugins[ $plugin_path ]['Type'] = 'add-on';
989
990
			/* @var stdClass $license_active */
991
			$license_active = __give_get_active_license_info( Give_License::get_short_name( $plugin_data['Name'] ) );
992
993
			// Does a valid license exist?
994
			if ( ! empty( $license_active ) && 'valid' === $license_active->license ) {
995
				$plugins[ $plugin_path ]['License'] = true;
996
			} else {
997
				$plugins[ $plugin_path ]['License'] = false;
998
			}
999
		} else {
1000
			// Plugin is not a Give add-on.
1001
			$plugins[ $plugin_path ]['Type'] = 'other';
1002
		}
1003
	}
1004
1005
	return $plugins;
1006
}
1007
1008
/**
1009
 * Check if terms enabled or not for form.
1010
 *
1011
 * @since 1.8
1012
 *
1013
 * @param $form_id
1014
 *
1015
 * @return bool
1016
 */
1017
function give_is_terms_enabled( $form_id ) {
1018
	$form_option = give_get_meta( $form_id, '_give_terms_option', true );
1019
1020
	if ( give_is_setting_enabled( $form_option, 'global' ) && give_is_setting_enabled( give_get_option( 'terms' ) ) ) {
1021
		return true;
1022
1023
	} elseif ( give_is_setting_enabled( $form_option ) ) {
1024
		return true;
1025
1026
	} else {
1027
		return false;
1028
	}
1029
}
1030
1031
/**
1032
 * Delete donation stats cache.
1033
 *
1034
 * @todo  Resolve stats cache key naming issue. Currently it is difficult to regenerate cache key.
1035
 *
1036
 * @since 1.8.7
1037
 *
1038
 * @param string|array $date_range Date for stats.
1039
 *                                 Date value should be in today, yesterday, this_week, last_week, this_month,
1040
 *                                 last_month, this_quarter, last_quarter, this_year, last_year. For date value other,
1041
 *                                 all cache will be removed.
1042
 *
1043
 * @param array        $args
1044
 *
1045
 * @return WP_Error|bool
1046
 */
1047
function give_delete_donation_stats( $date_range = '', $args = array() ) {
1048
1049
	// Delete all cache.
1050
	$status = Give_Cache::delete( Give_Cache::get_options_like( 'give_stats' ) );
1051
1052
	/**
1053
	 * Fire the action when donation stats delete.
1054
	 *
1055
	 * @since 1.8.7
1056
	 *
1057
	 * @param string|array $date_range
1058
	 * @param array        $args
1059
	 */
1060
	do_action( 'give_delete_donation_stats', $status, $date_range, $args );
1061
1062
	return $status;
1063
}
1064
1065
/**
1066
 * Check if admin creating new donation form or not.
1067
 *
1068
 * @since 2.0
1069
 * @return bool
1070
 */
1071
function give_is_add_new_form_page() {
1072
	$status = false;
1073
1074
	if ( false !== strpos( $_SERVER['REQUEST_URI'], '/wp-admin/post-new.php?post_type=give_forms' ) ) {
1075
		$status = true;
1076
	}
1077
1078
	return $status;
1079
}
1080
1081
/**
1082
 * Get Form/Payment meta.
1083
 *
1084
 * Note: This function will help you to get meta for payment and form.
1085
 *       If you want to get meta for donors then use get_meta of Give_Donor and
1086
 *       If you want to get meta for logs then use get_meta of Give_Logging->logmeta_db.
1087
 *
1088
 * @since 1.8.8
1089
 *
1090
 * @param int    $id
1091
 * @param string $meta_key
1092
 * @param bool   $single
1093
 * @param bool   $default
1094
 *
1095
 * @return mixed
1096
 */
1097
function give_get_meta( $id, $meta_key = '', $single = false, $default = false ) {
1098
	/**
1099
	 * Filter the meta value
1100
	 *
1101
	 * @since 1.8.8
1102
	 */
1103
	$meta_value = apply_filters( 'give_get_meta', get_post_meta( $id, $meta_key, $single ), $id, $meta_key, $default );
1104
1105
	if ( ( empty( $meta_key ) || empty( $meta_value ) ) && $default ) {
1106
		$meta_value = $default;
1107
	}
1108
1109
	return $meta_value;
1110
}
1111
1112
/**
1113
 * Update Form/Payment meta.
1114
 *
1115
 * @since 1.8.8
1116
 *
1117
 * @param int    $id
1118
 * @param string $meta_key
1119
 * @param mixed  $meta_value
1120
 * @param mixed  $prev_value
1121
 *
1122
 * @return mixed
1123
 */
1124
function give_update_meta( $id, $meta_key, $meta_value, $prev_value = '' ) {
1125
	$status = update_post_meta( $id, $meta_key, $meta_value, $prev_value );
1126
1127
	/**
1128
	 * Filter the meta value update status
1129
	 *
1130
	 * @since 1.8.8
1131
	 */
1132
	return apply_filters( 'give_update_meta', $status, $id, $meta_key, $meta_value );
1133
}
1134
1135
/**
1136
 * Delete Form/Payment meta.
1137
 *
1138
 * @since 1.8.8
1139
 *
1140
 * @param int    $id
1141
 * @param string $meta_key
1142
 * @param string $meta_value
1143
 *
1144
 * @return mixed
1145
 */
1146
function give_delete_meta( $id, $meta_key, $meta_value = '' ) {
1147
	$status = delete_post_meta( $id, $meta_key, $meta_value );
1148
1149
	/**
1150
	 * Filter the meta value delete status
1151
	 *
1152
	 * @since 1.8.8
1153
	 */
1154
	return apply_filters( 'give_delete_meta', $status, $id, $meta_key, $meta_value );
1155
}
1156
1157
/**
1158
 * Check if the upgrade routine has been run for a specific action
1159
 *
1160
 * @since  1.0
1161
 *
1162
 * @param  string $upgrade_action The upgrade action to check completion for
1163
 *
1164
 * @return bool                   If the action has been added to the completed actions array
1165
 */
1166
function give_has_upgrade_completed( $upgrade_action = '' ) {
1167
	// Bailout.
1168
	if ( empty( $upgrade_action ) ) {
1169
		return false;
1170
	}
1171
1172
	// Fresh install?
1173
	// If fresh install then all upgrades will be consider as completed.
1174
	$is_fresh_install = ! Give_Cache_Setting::get_option( 'give_version' );
1175
	if ( $is_fresh_install ) {
1176
		return true;
1177
	}
1178
1179
	$completed_upgrades = give_get_completed_upgrades();
1180
1181
	return in_array( $upgrade_action, $completed_upgrades );
1182
1183
}
1184
1185
/**
1186
 * For use when doing 'stepped' upgrade routines, to see if we need to start somewhere in the middle
1187
 *
1188
 * @since 1.8
1189
 *
1190
 * @return mixed   When nothing to resume returns false, otherwise starts the upgrade where it left off
1191
 */
1192
function give_maybe_resume_upgrade() {
1193
	$doing_upgrade = get_option( 'give_doing_upgrade', false );
1194
	if ( empty( $doing_upgrade ) ) {
1195
		return false;
1196
	}
1197
1198
	return $doing_upgrade;
1199
}
1200
1201
/**
1202
 * Adds an upgrade action to the completed upgrades array
1203
 *
1204
 * @since  1.0
1205
 *
1206
 * @param  string $upgrade_action The action to add to the completed upgrades array
1207
 *
1208
 * @return bool                   If the function was successfully added
1209
 */
1210
function give_set_upgrade_complete( $upgrade_action = '' ) {
1211
1212
	if ( empty( $upgrade_action ) ) {
1213
		return false;
1214
	}
1215
1216
	$completed_upgrades   = give_get_completed_upgrades();
1217
	$completed_upgrades[] = $upgrade_action;
1218
1219
	// Remove any blanks, and only show uniques.
1220
	$completed_upgrades = array_unique( array_values( $completed_upgrades ) );
1221
1222
	/**
1223
	 * Fire the action when any upgrade set to complete.
1224
	 *
1225
	 * @since 1.8.12
1226
	 */
1227
	do_action( 'give_set_upgrade_completed', $upgrade_action, $completed_upgrades );
1228
1229
	return update_option( 'give_completed_upgrades', $completed_upgrades, false );
1230
}
1231
1232
/**
1233
 * Get's the array of completed upgrade actions
1234
 *
1235
 * @since  1.0
1236
 * @return array The array of completed upgrades
1237
 */
1238
function give_get_completed_upgrades() {
1239
	return (array) Give_Cache_Setting::get_option( 'give_completed_upgrades' );
1240
}
1241
1242
/**
1243
 * In 2.0 we updated table for log, payment and form.
1244
 *
1245
 * Note: internal purpose only.
1246
 *
1247
 * @since 2.0
1248
 * @global wpdb  $wpdb
1249
 *
1250
 * @param string $type Context for table
1251
 *
1252
 * @return null|array
1253
 */
1254
function __give_v20_bc_table_details( $type ) {
1255
	global $wpdb;
1256
	$table = array();
1257
1258
	// Bailout.
1259
	if ( empty( $type ) ) {
1260
		return null;
1261
	}
1262
1263
	switch ( $type ) {
1264
		case 'form':
1265
			$table['name']         = $wpdb->formmeta;
1266
			$table['column']['id'] = 'form_id';
1267
1268
			break;
1269
1270
		case 'payment':
1271
			$table['name']         = $wpdb->donationmeta;
1272
			$table['column']['id'] = Give()->payment_meta->get_meta_type() . '_id';
1273
	}
1274
1275
	// Backward compatibility.
1276
	if ( ! give_has_upgrade_completed( 'v20_move_metadata_into_new_table' ) ) {
1277
		$table['name']         = $wpdb->postmeta;
1278
		$table['column']['id'] = 'post_id';
1279
	}
1280
1281
	return $table;
1282
}
1283
1284
/**
1285
 * Remove the Give transaction pages from WP search results.
1286
 *
1287
 * @since 1.8.13
1288
 *
1289
 * @param WP_Query $query
1290
 */
1291
function give_remove_pages_from_search( $query ) {
1292
1293
	if ( ! $query->is_admin && $query->is_search && $query->is_main_query() ) {
1294
1295
		$transaction_failed = give_get_option( 'failure_page', 0 );
1296
		$success_page       = give_get_option( 'success_page', 0 );
1297
1298
		$args = apply_filters(
1299
			'give_remove_pages_from_search', array(
1300
				$transaction_failed,
1301
				$success_page,
1302
			), $query
1303
		);
1304
		$query->set( 'post__not_in', $args );
1305
	}
1306
}
1307
1308
add_action( 'pre_get_posts', 'give_remove_pages_from_search', 10, 1 );
1309
1310
/**
1311
 * Inserts a new key/value before a key in the array.
1312
 *
1313
 * @since 1.8.13
1314
 *
1315
 * @param string       $key       The key to insert before.
1316
 * @param array        $array     An array to insert in to.
1317
 * @param string       $new_key   The key to insert.
1318
 * @param array|string $new_value An value to insert.
1319
 *
1320
 * @return array The new array if the key exists, the passed array otherwise.
1321
 *
1322
 * @see   array_insert_before()
1323
 */
1324 View Code Duplication
function give_array_insert_before( $key, array &$array, $new_key, $new_value ) {
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...
1325
	if ( array_key_exists( $key, $array ) ) {
1326
		$new = array();
1327
		foreach ( $array as $k => $value ) {
1328
			if ( $k === $key ) {
1329
				$new[ $new_key ] = $new_value;
1330
			}
1331
			$new[ $k ] = $value;
1332
		}
1333
1334
		return $new;
1335
	}
1336
1337
	return $array;
1338
}
1339
1340
/**
1341
 * Inserts a new key/value after a key in the array.
1342
 *
1343
 * @since 1.8.13
1344
 *
1345
 * @param string       $key       The key to insert after.
1346
 * @param array        $array     An array to insert in to.
1347
 * @param string       $new_key   The key to insert.
1348
 * @param array|string $new_value An value to insert.
1349
 *
1350
 * @return array The new array if the key exists, the passed array otherwise.
1351
 *
1352
 * @see   array_insert_before()
1353
 */
1354 View Code Duplication
function give_array_insert_after( $key, array &$array, $new_key, $new_value ) {
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...
1355
	if ( array_key_exists( $key, $array ) ) {
1356
		$new = array();
1357
		foreach ( $array as $k => $value ) {
1358
			$new[ $k ] = $value;
1359
			if ( $k === $key ) {
1360
				$new[ $new_key ] = $new_value;
1361
			}
1362
		}
1363
1364
		return $new;
1365
	}
1366
1367
	return $array;
1368
}
1369
1370
/**
1371
 * Pluck a certain field out of each object in a list.
1372
 *
1373
 * This has the same functionality and prototype of
1374
 * array_column() (PHP 5.5) but also supports objects.
1375
 *
1376
 * @since 1.8.13
1377
 *
1378
 * @param array      $list      List of objects or arrays
1379
 * @param int|string $field     Field from the object to place instead of the entire object
1380
 * @param int|string $index_key Optional. Field from the object to use as keys for the new array.
1381
 *                              Default null.
1382
 *
1383
 * @return array Array of found values. If `$index_key` is set, an array of found values with keys
1384
 *               corresponding to `$index_key`. If `$index_key` is null, array keys from the original
1385
 *               `$list` will be preserved in the results.
1386
 */
1387
function give_list_pluck( $list, $field, $index_key = null ) {
1388
1389
	if ( ! $index_key ) {
1390
		/**
1391
		 * This is simple. Could at some point wrap array_column()
1392
		 * if we knew we had an array of arrays.
1393
		 */
1394
		foreach ( $list as $key => $value ) {
1395
			if ( is_object( $value ) ) {
1396
				if ( isset( $value->$field ) ) {
1397
					$list[ $key ] = $value->$field;
1398
				}
1399
			} else {
1400
				if ( isset( $value[ $field ] ) ) {
1401
					$list[ $key ] = $value[ $field ];
1402
				}
1403
			}
1404
		}
1405
1406
		return $list;
1407
	}
1408
1409
	/*
1410
	 * When index_key is not set for a particular item, push the value
1411
	 * to the end of the stack. This is how array_column() behaves.
1412
	 */
1413
	$newlist = array();
1414
	foreach ( $list as $value ) {
1415
		if ( is_object( $value ) ) {
1416
			if ( isset( $value->$index_key ) ) {
1417
				$newlist[ $value->$index_key ] = $value->$field;
1418
			} else {
1419
				$newlist[] = $value->$field;
1420
			}
1421
		} else {
1422
			if ( isset( $value[ $index_key ] ) ) {
1423
				$newlist[ $value[ $index_key ] ] = $value[ $field ];
1424
			} else {
1425
				$newlist[] = $value[ $field ];
1426
			}
1427
		}
1428
	}
1429
1430
	$list = $newlist;
1431
1432
	return $list;
1433
}
1434
1435
/**
1436
 * Add meta data field to a donor.
1437
 *
1438
 * @since 1.8.13
1439
 *
1440
 * @param int    $donor_id   Donor ID.
1441
 * @param string $meta_key   Metadata name.
1442
 * @param mixed  $meta_value Metadata value. Must be serializable if non-scalar.
1443
 * @param bool   $unique     Optional. Whether the same key should not be added.
1444
 *                           Default false.
1445
 *
1446
 * @return int|false Meta ID on success, false on failure.
1447
 */
1448
function add_donor_meta( $donor_id, $meta_key, $meta_value, $unique = false ) {
1449
	return add_metadata( 'give_customer', $donor_id, $meta_key, $meta_value, $unique );
1450
}
1451
1452
/**
1453
 * Remove metadata matching criteria from a Donor meta.
1454
 *
1455
 * You can match based on the key, or key and value. Removing based on key and
1456
 * value, will keep from removing duplicate metadata with the same key. It also
1457
 * allows removing all metadata matching key, if needed.
1458
 *
1459
 * @since 1.8.13
1460
 *
1461
 * @param int    $donor_id   Donor ID
1462
 * @param string $meta_key   Metadata name.
1463
 * @param mixed  $meta_value Optional. Metadata value.
1464
 *
1465
 * @return bool True on success, false on failure.
1466
 */
1467
function delete_donor_meta( $donor_id, $meta_key, $meta_value = '' ) {
1468
	return delete_metadata( 'give_customer', $donor_id, $meta_key, $meta_value );
1469
}
1470
1471
/**
1472
 * Retrieve donor meta field for a donor meta table.
1473
 *
1474
 * @since 1.8.13
1475
 *
1476
 * @param int    $donor_id Donor ID.
1477
 * @param string $key      Optional. The meta key to retrieve. By default, returns data for all keys.
1478
 * @param bool   $single   Whether to return a single value.
1479
 *
1480
 * @return mixed Will be an array if $single is false. Will be value of meta data field if $single
1481
 *  is true.
1482
 */
1483
function get_donor_meta( $donor_id, $key = '', $single = false ) {
1484
	return get_metadata( 'give_customer', $donor_id, $key, $single );
1485
}
1486
1487
/**
1488
 * Update customer meta field based on Donor ID.
1489
 *
1490
 * If the meta field for the donor does not exist, it will be added.
1491
 *
1492
 * @since 1.8.13
1493
 *
1494
 * @param int    $donor_id   Donor ID.
1495
 * @param string $meta_key   Metadata key.
1496
 * @param mixed  $meta_value Metadata value.
1497
 * @param mixed  $prev_value Optional. Previous value to check before removing.
1498
 *
1499
 * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.
1500
 */
1501
function update_donor_meta( $donor_id, $meta_key, $meta_value, $prev_value = '' ) {
1502
	return update_metadata( 'give_customer', $donor_id, $meta_key, $meta_value, $prev_value );
1503
}
1504
1505
1506
/**
1507
 * Give recalculate income and donation of the donation from ID
1508
 *
1509
 * @since 1.8.13
1510
 *
1511
 * @param int $form_id Form id of which recalculation needs to be done.
1512
 *
1513
 * @return void
1514
 */
1515
function give_recount_form_income_donation( $form_id = 0 ) {
1516
	// Check if form id is not empty.
1517
	if ( ! empty( $form_id ) ) {
1518
		/**
1519
		 * Filter to modify payment status.
1520
		 *
1521
		 * @since 1.8.13
1522
		 */
1523
		$accepted_statuses = apply_filters( 'give_recount_accepted_statuses', array( 'publish' ) );
1524
1525
		/**
1526
		 * Filter to modify args of payment query before recalculating the form total
1527
		 *
1528
		 * @since 1.8.13
1529
		 */
1530
		$args = apply_filters(
1531
			'give_recount_form_stats_args', array(
1532
				'give_forms'     => $form_id,
1533
				'status'         => $accepted_statuses,
1534
				'number'         => - 1,
1535
				'fields'         => 'ids',
1536
			)
1537
		);
1538
1539
		$totals = array(
1540
			'sales'    => 0,
1541
			'earnings' => 0,
1542
		);
1543
1544
		$payments = new Give_Payments_Query( $args );
1545
		$payments = $payments->get_payments();
1546
1547
		if ( $payments ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $payments of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1548
			foreach ( $payments as $payment ) {
1549
				// Ensure acceptable status only.
1550
				if ( ! in_array( $payment->post_status, $accepted_statuses ) ) {
1551
					continue;
1552
				}
1553
1554
				// Ensure only payments for this form are counted.
1555
				if ( $payment->form_id != $form_id ) {
1556
					continue;
1557
				}
1558
1559
				$totals['sales'] ++;
1560
				$totals['earnings'] += $payment->total;
1561
1562
			}
1563
		}
1564
		give_update_meta( $form_id, '_give_form_sales', $totals['sales'] );
1565
		give_update_meta( $form_id, '_give_form_earnings', give_sanitize_amount_for_db( $totals['earnings'] ) );
1566
	}// End if().
1567
}
1568
1569
1570
/**
1571
 * Get attribute string
1572
 *
1573
 * @since 1.8.17
1574
 *
1575
 * @param array $attributes
1576
 * @param array $default_attributes
1577
 *
1578
 * @return string
1579
 */
1580
function give_get_attribute_str( $attributes, $default_attributes = array() ) {
1581
	$attribute_str = '';
1582
1583
	if ( isset( $attributes['attributes'] ) ) {
1584
		$attributes = $attributes['attributes'];
1585
	}
1586
1587
	if ( ! empty( $default_attributes ) ) {
1588
		$attributes = wp_parse_args( $attributes, $default_attributes );
1589
	}
1590
1591
	if ( empty( $attributes ) ) {
1592
		return $attribute_str;
1593
	}
1594
1595
	foreach ( $attributes as $tag => $value ) {
1596
		if( 'value' == $tag ){
0 ignored issues
show
Space after opening control structure is required
Loading history...
No space before opening parenthesis is prohibited
Loading history...
1597
			$value = esc_attr( $value );
1598
		}
1599
1600
		$attribute_str .= " {$tag}=\"{$value}\"";
1601
	}
1602
1603
	return trim( $attribute_str );
1604
}
1605
1606
/**
1607
 * Get the upload dir path
1608
 *
1609
 * @since 1.8.17
1610
 *
1611
 * @return string $wp_upload_dir;
1612
 */
1613
function give_get_wp_upload_dir() {
1614
	$wp_upload_dir = wp_upload_dir();
1615
1616
	return ( ! empty( $wp_upload_dir['path'] ) ? $wp_upload_dir['path'] : false );
1617
}
1618
1619
/**
1620
 * Get the data from uploaded JSON file
1621
 *
1622
 * @since 1.8.17
1623
 *
1624
 * @param string $file_name filename of the json file that is being uploaded
1625
 *
1626
 * @return string|bool $file_contents File content
1627
 */
1628
function give_get_core_settings_json( $file_name ) {
1629
	$upload_dir = give_get_wp_upload_dir();
1630
	$file_path  = $upload_dir . '/' . $file_name;
1631
1632
	if ( is_wp_error( $file_path ) || empty( $file_path ) ) {
1633
		Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide a valid JSON file.', 'give' ) );
1634
	}
1635
1636
	$file_contents = file_get_contents( $file_path );
0 ignored issues
show
file_get_contents is highly discouraged, please use wpcom_vip_file_get_contents() instead.
Loading history...
1637
1638
	return $file_contents;
1639
}
1640
1641
/**
1642
 * Get number of donation to show when user is not login.
1643
 *
1644
 * @since 1.8.17
1645
 *
1646
 * @return int $country The two letter country code for the site's base country
1647
 */
1648
function give_get_limit_display_donations() {
1649
	return give_get_option( 'limit_display_donations', 1 );
1650
}
1651
1652
/**
1653
 * Add footer to the table when donor is view the donation history page with out login
1654
 *
1655
 * @since 1.8.17
1656
 */
1657
function give_donation_history_table_end() {
1658
	$email = Give()->session->get( 'give_email' );
1659
	?>
1660
	<tfoot>
1661
	<tr>
1662
		<td colspan="9999">
1663
			<div class="give-security-wrap">
1664
				<div class="give-security-column give-security-description-wrap">
1665
					<?php
1666
					echo sprintf( __( 'For security reasons, please confirm your email address (%s) to view your complete donation history.', 'give' ), $email );
0 ignored issues
show
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'sprintf'
Loading history...
1667
					?>
1668
				</div>
1669
				<div class="give-security-column give-security-button-wrap">
1670
					<a href="#" data-email="<?php echo $email; ?>" id="give-confirm-email-btn"
0 ignored issues
show
Expected next thing to be a escaping function, not '$email'
Loading history...
1671
					   class="give-confirm-email-btn give-btn">
1672
						<?php _e( 'Confirm Email', 'give' ); ?>
1673
					</a>
1674
					<span><?php _e( 'Email Sent!', 'give' ); ?></span>
1675
				</div>
1676
			</div>
1677
		</td>
1678
	</tr>
1679
	</tfoot>
1680
	<?php
1681
}
1682
1683
1684
/**
1685
 * Wrapper for _doing_it_wrong.
1686
 *
1687
 * @since  1.8.18
1688
 *
1689
 * @param  string $function
1690
 * @param  string $message
1691
 * @param  string $version
1692
 *
1693
 * @return void
1694
 */
1695
function give_doing_it_wrong( $function, $message, $version ) {
1696
	$message .= "\nBacktrace:" . wp_debug_backtrace_summary();
1697
1698
	_doing_it_wrong( $function, $message, $version );
1699
}
1700
1701
1702
/**
1703
 * Remove limit from running php script complete.
1704
 *
1705
 * @since 1.8.18
1706
 */
1707
function give_ignore_user_abort() {
1708
	ignore_user_abort( true );
1709
1710
	if ( ! give_is_func_disabled( 'set_time_limit' ) && ! ini_get( 'safe_mode' ) ) {
1711
		set_time_limit( 0 );
1712
	}
1713
}
1714
1715
/**
1716
 * Get post type count.
1717
 *
1718
 * @since 2.0.2
1719
 *
1720
 * @param string $post_type
1721
 * @param array  $args
1722
 *
1723
 * @return int
1724
 */
1725
function give_get_total_post_type_count( $post_type = '', $args = array() ) {
0 ignored issues
show
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1726
	global $wpdb;
1727
	$where = '';
1728
1729
	if ( ! $post_type ) {
1730
		return 0;
1731
	}
1732
1733
	// Bulit where query
1734
	if ( ! empty( $post_type ) ) {
1735
		$where .= ' WHERE';
1736
1737
		if ( is_array( $post_type ) ) {
1738
			$where .= " post_type='" . implode( "' OR post_type='", $post_type ) . "'";
1739
		} else {
1740
			$where .= " post_type='{$post_type}'";
1741
		}
1742
	}
1743
1744
	$result = $wpdb->get_var( "SELECT count(ID) FROM {$wpdb->posts}{$where}" );
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...
1745
1746
	return absint( $result );
1747
}
1748
1749
/**
1750
 * Define a constant if it is not already defined.
1751
 *
1752
 * @since  2.0.5
1753
 *
1754
 * @param string $name  Constant name.
1755
 * @param string $value Value.
1756
 *
1757
 * @credit WooCommerce
1758
 */
1759
function give_maybe_define_constant( $name, $value ) {
1760
	if ( ! defined( $name ) ) {
1761
		define( $name, $value );
1762
	}
1763
}
1764
1765
/**
1766
 * Decode time short tag in string
1767
 *
1768
 * @since 2.1.0
1769
 *
1770
 * @param string $string
1771
 * @param int    $timestamp
1772
 *
1773
 * @return string
1774
 */
1775
function give_time_do_tags( $string, $timestamp = 0 ) {
1776
	$current_time = ! empty( $timestamp ) ? $timestamp : current_time( 'timestamp' );
1777
1778
	$formatted_string = str_replace(
1779
		array(
1780
			'{D}',
1781
			'{DD}',
1782
			'{M}',
1783
			'{MM}',
1784
			'{YY}',
1785
			'{YYYY}',
1786
			'{H}',
1787
			'{HH}',
1788
			'{N}',
1789
			'{S}',
1790
		), array(
1791
			date( 'j', $current_time ),
1792
			date( 'd', $current_time ),
1793
			date( 'n', $current_time ),
1794
			date( 'm', $current_time ),
1795
			date( 'Y', $current_time ),
1796
			date( 'Y', $current_time ),
1797
			date( 'G', $current_time ),
1798
			date( 'H', $current_time ),
1799
			date( 's', $current_time ),
1800
		), $string
1801
	);
1802
1803
	/**
1804
	 * Filter the parsed string.
1805
	 *
1806
	 * @since 2.1.0
1807
	 */
1808
	return apply_filters( 'give_time_do_tags', $formatted_string, $string, $timestamp );
1809
}
1810
1811
1812
/**
1813
 * Check if Company field enabled or not for form or globally.
1814
 *
1815
 * @since 2.1
1816
 *
1817
 * @param $form_id
1818
 *
1819
 * @return bool
1820
 */
1821
function give_is_company_field_enabled( $form_id ) {
1822
	$form_setting_val   = give_get_meta( $form_id, '_give_company_field', true );
1823
	$global_setting_val = give_get_option( 'company_field' );
1824
1825
	if ( ! empty( $form_setting_val ) ) {
1826
		if ( give_is_setting_enabled( $form_setting_val, array( 'required', 'optional' ) ) ) {
0 ignored issues
show
array('required', 'optional') is of type array<integer,string,{"0":"string","1":"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...
1827
			return true;
1828
		} elseif ( 'global' === $form_setting_val && give_is_setting_enabled(
1829
			$global_setting_val, array(
0 ignored issues
show
array('required', 'optional') is of type array<integer,string,{"0":"string","1":"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...
1830
				'required',
1831
				'optional',
1832
			)
1833
		) ) {
1834
			return true;
1835
		} else {
1836
			return false;
1837
		}
1838
	} elseif ( give_is_setting_enabled( $global_setting_val, array( 'required', 'optional' ) ) ) {
0 ignored issues
show
array('required', 'optional') is of type array<integer,string,{"0":"string","1":"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...
1839
		return true;
1840
1841
	} else {
1842
		return false;
1843
	}
1844
}
1845
1846
/**
1847
 * Check if anonymous donation field enabled or not for form or globally.
1848
 *
1849
 * @since 2.1
1850
 *
1851
 * @param $form_id
1852
 *
1853
 * @return bool
1854
 */
1855 View Code Duplication
function give_is_anonymous_donation_field_enabled( $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...
1856
	$form_setting_val   = give_get_meta( $form_id, '_give_anonymous_donation', true, 'global' );
0 ignored issues
show
'global' 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...
1857
	$global_setting_val = give_get_option( 'anonymous_donation', 'disabled' );
1858
1859
	if ( ! empty( $form_setting_val ) ) {
1860
		if ( give_is_setting_enabled( $form_setting_val ) ) {
1861
			return true;
1862
		} elseif ( 'global' === $form_setting_val && give_is_setting_enabled( $global_setting_val ) ) {
1863
			return true;
1864
		} else {
1865
			return false;
1866
		}
1867
	} elseif ( give_is_setting_enabled( $global_setting_val ) ) {
1868
		return true;
1869
	}
1870
1871
	return false;
1872
}
1873
1874
/**
1875
 * Check if donor comment field enabled or not for form or globally.
1876
 *
1877
 * @since 2.1
1878
 *
1879
 * @param $form_id
1880
 *
1881
 * @return bool
1882
 */
1883 View Code Duplication
function give_is_donor_comment_field_enabled( $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...
1884
	$form_setting_val   = give_get_meta( $form_id, '_give_donor_comment', true, 'global' );
0 ignored issues
show
'global' 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...
1885
	$global_setting_val = give_get_option( 'donor_comment', 'disabled' );
1886
1887
	if ( ! empty( $form_setting_val ) ) {
1888
		if ( give_is_setting_enabled( $form_setting_val ) ) {
1889
			return true;
1890
		} elseif ( 'global' === $form_setting_val && give_is_setting_enabled( $global_setting_val ) ) {
1891
			return true;
1892
		} else {
1893
			return false;
1894
		}
1895
	} elseif ( give_is_setting_enabled( $global_setting_val ) ) {
1896
		return true;
1897
	}
1898
1899
	return false;
1900
1901
}
1902
1903
/**
1904
 * Get add-on user meta value information
1905
 * Note: only for internal use.
1906
 *
1907
 * @since 2.1.0
1908
 *
1909
 * @param string $license_id
1910
 *
1911
 * @return array
1912
 */
1913
function __give_get_active_license_info( $license_id ) {
1914
	global $wpdb;
1915
	$option_name = "{$license_id}_license_active";
1916
	$data        = array();
1917
1918
	if ( ! isset( $GLOBALS['give_active_licenses_info'] ) ) {
1919
		$GLOBALS['give_active_licenses_info'] = array();
1920
1921
		$licenses_info = $wpdb->get_results(
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...
1922
			"
1923
			SELECT option_name, option_value
1924
			FROM {$wpdb->options}
1925
			WHERE option_name LIKE '%_license_active%'
1926
			AND option_name LIKE '%give_%'
1927
			",
1928
			ARRAY_A
1929
		);
1930
1931 View Code Duplication
		if ( ! empty( $licenses_info ) ) {
0 ignored issues
show
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...
1932
			$GLOBALS['give_active_licenses_info'] = array_combine(
1933
				wp_list_pluck( $licenses_info, 'option_name' ),
1934
				wp_list_pluck( $licenses_info, 'option_value' )
1935
			);
1936
		}
1937
	}
1938
1939 View Code Duplication
	if ( in_array( $option_name, array_keys( $GLOBALS['give_active_licenses_info'] ) ) ) {
0 ignored issues
show
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...
1940
		$data = maybe_unserialize( $GLOBALS['give_active_licenses_info'][ $option_name ] );
1941
	}
1942
1943
	return $data;
1944
}
1945
1946
/**
1947
 * Get add-on user meta value information
1948
 * Note: only for internal use.
1949
 *
1950
 * @since 2.1.0
1951
 *
1952
 * @param string $banner_addon_name Give add-on name.
1953
 *
1954
 * @return array
1955
 */
1956
function __give_get_active_by_user_meta( $banner_addon_name ) {
1957
	global $wpdb;
1958
1959
	// Get the option key.
1960
	$option_name = Give_Addon_Activation_Banner::get_banner_user_meta_key( $banner_addon_name );
1961
	$data        = array();
1962
1963
	if (
1964
		! isset( $GLOBALS['give_addon_activated_by_user'][ $banner_addon_name ] )
1965
		|| empty( $GLOBALS['give_addon_activated_by_user'][ $banner_addon_name ] )
1966
	) {
1967
		$GLOBALS['give_addon_activated_by_user'][ $banner_addon_name ] = array();
1968
1969
		// Get the meta of activation banner by user.
1970
		$activation_banners = $wpdb->get_results(
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...
1971
			"
1972
					SELECT option_name, option_value
1973
					FROM {$wpdb->options}
1974
					WHERE option_name LIKE '%_active_by_user%'
1975
					AND option_name LIKE '%give_addon%'
1976
					",
1977
			ARRAY_A
1978
		);
1979
1980 View Code Duplication
		if ( ! empty( $activation_banners ) ) {
0 ignored issues
show
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...
1981
			$GLOBALS['give_addon_activated_by_user'] = array_combine(
1982
				wp_list_pluck( $activation_banners, 'option_name' ),
1983
				wp_list_pluck( $activation_banners, 'option_value' )
1984
			);
1985
		}
1986
	}
1987
1988 View Code Duplication
	if ( in_array( $option_name, array_keys( $GLOBALS['give_addon_activated_by_user'] ) ) ) {
0 ignored issues
show
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...
1989
		$data = maybe_unserialize( $GLOBALS['give_addon_activated_by_user'][ $option_name ] );
1990
	}
1991
1992
	return $data;
1993
}
1994
1995
/**
1996
 * Get time interval for which nonce is valid
1997
 *
1998
 * @since 2.1.3
1999
 *
2000
 * @return int
2001
 */
2002
function give_get_nonce_life() {
2003
	/**
2004
	 * Filters the lifespan of nonces in seconds.
2005
	 *
2006
	 * @see wp-inlucdes/pluggable.php:wp_nonce_tick
2007
	 */
2008
	return (int) apply_filters( 'nonce_life', DAY_IN_SECONDS );
2009
}
2010
2011
/**
2012
 * Get nonce field without id
2013
 *
2014
 * @since 2.1.3
2015
 *
2016
 * @param  string $action
2017
 * @param  string $name
2018
 * @param bool   $referer
2019
 *
2020
 * @return string
2021
 */
2022
function give_get_nonce_field( $action, $name, $referer = false ) {
2023
	return str_replace(
2024
		"id=\"{$name}\"",
2025
		'',
2026
		wp_nonce_field( $action, $name, $referer, false )
2027
	);
2028
}
2029
2030
/**
2031
 * Display/Return a formatted goal for a donation form
2032
 *
2033
 * @param int|Give_Donate_Form $form Form ID or Form Object.
2034
 *
2035
 * @since 2.1
2036
 *
2037
 * @return array
2038
 */
2039
function give_goal_progress_stats( $form ) {
2040
2041
	if ( ! $form instanceof Give_Donate_Form ) {
2042
		$form = new Give_Donate_Form( $form );
2043
	}
2044
2045
	$donors = '';
0 ignored issues
show
$donors is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2046
2047
	$goal_format = give_get_form_goal_format( $form->ID );
2048
2049
	/**
2050
	 * Filter the form.
2051
	 *
2052
	 * @since 1.8.8
2053
	 */
2054
	$total_goal = apply_filters( 'give_goal_amount_target_output', round( give_maybe_sanitize_amount( $form->goal ), 2 ), $form->ID, $form );
2055
2056
	switch ( $goal_format ) {
2057
		case 'donation':
2058
			/**
2059
			 * Filter the form donations.
2060
			 *
2061
			 * @since 2.1
2062
			 */
2063
			$actual = $donations = apply_filters( 'give_goal_donations_raised_output', $form->sales, $form->ID, $form );
0 ignored issues
show
$donations is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2064
			break;
2065
		case 'donors':
2066
			/**
2067
			 * Filter to modify total number if donor for the donation form.
2068
			 *
2069
			 * @since 2.1.3
2070
			 *
2071
			 * @param int $donors Total number of donors that donated to the form.
2072
			 * @param int $form_id Donation Form ID.
2073
			 * @param Give_Donate_Form $form instances of Give_Donate_Form.
2074
			 *
2075
			 * @return int $donors Total number of donors that donated to the form.
2076
			 */
2077
			$actual = $donors = apply_filters( 'give_goal_donors_target_output', give_get_form_donor_count( $form->ID ), $form->ID, $form );
0 ignored issues
show
$donors is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2078
			break;
2079
		default:
2080
			/**
2081
			 * Filter the form income.
2082
			 *
2083
			 * @since 1.8.8
2084
			 */
2085
			$actual = $income = apply_filters( 'give_goal_amount_raised_output', $form->earnings, $form->ID, $form );
0 ignored issues
show
$income is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2086
			break;
2087
	}
2088
2089
	$progress = $total_goal ? round( ( $actual / $total_goal ) * 100, 2 ) : 0;
2090
2091
	$stats_array = array(
2092
		'raw_actual' => $actual,
2093
		'raw_goal'   => $total_goal,
2094
	);
2095
2096
	/**
2097
	 * Filter the goal progress output
2098
	 *
2099
	 * @since 1.8.8
2100
	 */
2101
	$progress = apply_filters( 'give_goal_amount_funded_percentage_output', $progress, $form->ID, $form );
2102
2103
	// Define Actual Goal based on the goal format.
2104 View Code Duplication
	if ( 'percentage' === $goal_format ) {
0 ignored issues
show
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...
2105
		$actual = "{$actual}%";
2106
	} elseif ( 'amount' === $goal_format ) {
2107
		$actual = give_currency_filter( give_format_amount( $actual ) );
2108
	}
2109
2110
	// Define Total Goal based on the goal format.
2111 View Code Duplication
	if ( 'percentage' === $goal_format ) {
0 ignored issues
show
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...
2112
		$total_goal = '';
2113
	} elseif ( 'amount' === $goal_format ) {
2114
		$total_goal = give_currency_filter( give_format_amount( $total_goal ) );
2115
	}
2116
2117
	$stats_array = array_merge(
2118
		array(
2119
			'progress' => $progress,
2120
			'actual'   => $actual,
2121
			'goal'     => $total_goal,
2122
			'format'   => $goal_format,
2123
		),
2124
		$stats_array
2125
	);
2126
2127
	/**
2128
	 * Filter the goal stats
2129
	 *
2130
	 * @since 2.1
2131
	 */
2132
	return apply_filters( 'give_goal_progress_stats', $stats_array );
2133
}
2134
2135
/**
2136
 * Get the admin messages key to show the notices.
2137
 *
2138
 * @since 2.1.4
2139
 *
2140
 * @return array $message admin message key.
2141
 */
2142
function give_get_admin_messages_key() {
2143
	$messages = empty( $_GET['give-messages'] ) ? array() : give_clean( $_GET['give-messages'] );
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...
2144
2145
	// backward compatibility.
2146
	if ( ! empty( $_GET['give-message'] ) ) {
2147
		$messages[] = give_clean( $_GET['give-message'] );
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...
2148
	}
2149
2150
	/**
2151
	 * Filter to modify the admin messages key.
2152
	 *
2153
	 * @since 2.1.4
2154
	 *
2155
	 * @param array $message admin message key.
2156
	 *
2157
	 * @return array $message admin message key.
2158
	 */
2159
	return (array) apply_filters( 'give_get_admin_messages_key', $messages );
2160
}
2161
2162
/**
2163
 * Get User Agent String.
2164
 *
2165
 * @since 2.1.4
2166
 *
2167
 * @return array|string
2168
 */
2169
function give_get_user_agent() {
2170
2171
	// Get User Agent.
2172
	$user_agent = ! empty( $_SERVER['HTTP_USER_AGENT'] ) ? give_clean( $_SERVER['HTTP_USER_AGENT'] ) : ''; // WPCS: input var ok.
0 ignored issues
show
Due to using Batcache, server side based client related logic will not work, use JS instead.
Loading history...
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
2173
2174
	return $user_agent;
2175
}
2176
2177
/**
2178
 * Set a cookie - wrapper for setcookie using WP constants.
2179
 *
2180
 * @since 2.2.0
2181
 *
2182
 * @param  string  $name   Name of the cookie being set.
2183
 * @param  string  $value  Value of the cookie.
2184
 * @param  integer $expire Expiry of the cookie.
2185
 * @param  bool    $secure Whether the cookie should be served only over https.
2186
 */
2187
function give_setcookie( $name, $value, $expire = 0, $secure = false ) {
2188
	if ( ! headers_sent() ) {
2189
		setcookie(
0 ignored issues
show
Due to using Batcache, server side based client related logic will not work, use JS instead.
Loading history...
2190
			$name, $value, $expire, COOKIEPATH ? COOKIEPATH : '/', COOKIE_DOMAIN, $secure,
2191
			apply_filters( 'give_cookie_httponly', false, $name, $value, $expire, $secure )
2192
		);
2193
	}
2194
}
2195
2196
/**
2197
 * Get formatted billing address.
2198
 *
2199
 * @since 2.2.0
2200
 *
2201
 * @param array $address
2202
 *
2203
 * @return string Formatted address.
2204
 */
2205
function give_get_formatted_address( $address = array() ) {
2206
	$formatted_address = '';
2207
2208
	/**
2209
	 * Address format.
2210
	 *
2211
	 * @since 2.2.0
2212
	 */
2213
	$address_format = apply_filters( 'give_address_format_template', "{street_address}\n{city}, {state} {postal_code}\n{country}" );
2214
	preg_match_all( '/{([A-z0-9\-\_\ ]+)}/s', $address_format, $matches );
2215
2216
	if ( ! empty( $matches ) && ! empty( $address ) ) {
2217
		$address_values = array();
2218
2219
		foreach ( $matches[1] as $address_tag ) {
2220
			$address_values[ $address_tag ] = '';
2221
2222
			if ( isset( $address[ $address_tag ] ) ) {
2223
				$address_values[ $address_tag ] = $address[ $address_tag ];
2224
			}
2225
		}
2226
2227
		$formatted_address = str_ireplace( $matches[0], $address_values, $address_format );
2228
	}
2229
2230
	/**
2231
	 * Give get formatted address.
2232
	 *
2233
	 * @since 2.2.0
2234
	 *
2235
	 * @param string $formatted_address Formatted address.
2236
	 * @param string $address_format    Format of the address.
2237
	 */
2238
	$formatted_address = apply_filters( 'give_get_formatted_address', $formatted_address, $address_format, $address );
2239
2240
	return $formatted_address;
2241
}
2242
2243
/**
2244
 * Get safe url for assets
2245
 * Note: this function will return url without http protocol
2246
 *
2247
 * @since 2.2.0
2248
 *
2249
 * @param string $url URL
2250
 *
2251
 * @return string
2252
 */
2253
function give_get_safe_asset_url( $url ) {
2254
2255
	// Bailout, if empty URL passed.
2256
	if ( empty( $url ) ) {
2257
		return $url;
2258
	}
2259
2260
	$schema        = parse_url( $url, PHP_URL_SCHEME );
2261
	$schema_length = strlen( $schema ) + 1;
2262
	$url           = substr( $url, $schema_length );
2263
2264
	/**
2265
	 * Fire the filter
2266
	 *
2267
	 * @since 2.2.0
2268
	 */
2269
	return apply_filters( 'give_get_safe_asset_url', $url );
2270
}
2271
2272
/**
2273
 * Give get formatted date.
2274
 *
2275
 * @since 2.3.0
2276
 *
2277
 * @param string $date           Date.
2278
 * @param string $format         Date Format.
2279
 * @param string $current_format Current date Format.
2280
 *
2281
 * @return string
2282
 */
2283
function give_get_formatted_date( $date, $format = 'Y-m-d', $current_format = '' ) {
2284
	$current_format = empty( $current_format ) ? give_date_format() : $current_format;
2285
	$date_obj       = DateTime::createFromFormat( $current_format, $date );
2286
2287
	$formatted_date = $date_obj instanceof DateTime ? $date_obj->format( $format ) : '';
2288
2289
	/**
2290
	 * Give get formatted date.
2291
	 *
2292
	 * @since 2.3.0
2293
	 *
2294
	 * @param string $formatted_date Formatted date.
2295
	 * @param array
2296
	 */
2297
	return apply_filters( 'give_get_formatted_date', $formatted_date, array( $date, $format, $current_format ) );
2298
}
2299
2300
/**
2301
 * This function will be used to fetch the donation receipt link.
2302
 *
2303
 * @param int $donation_id Donation ID.
2304
 *
2305
 * @since 2.3.1
2306
 *
2307
 * @return string
2308
 */
2309
function give_get_receipt_link( $donation_id ) {
2310
2311
	return sprintf(
2312
		'<a href="%1$s">%2$s</a>',
2313
		esc_url( give_get_receipt_url( $donation_id ) ),
2314
		esc_html__( 'View the receipt in your browser &raquo;', 'give' )
2315
	);
2316
2317
}
2318
2319
/**
2320
 * Get receipt_url
2321
 *
2322
 * @since 2.0
2323
 *
2324
 * @param int $donation_id Donation ID.
2325
 *
2326
 * @return string
2327
 */
2328
function give_get_receipt_url( $donation_id ) {
2329
	
2330
	$receipt_url = esc_url(
2331
		add_query_arg(
2332
			array(
2333
				'donation_id' => $donation_id,
2334
			), give_get_history_page_uri()
2335
		)
2336
	);
2337
	
2338
	return $receipt_url;
2339
}
2340
2341
/**
2342
 * Get "View in browser" Receipt Link for email.
2343
 *
2344
 * @param int $donation_id Donation ID.
2345
 *
2346
 * @since 2.4.1
2347
 *
2348
 * @return string
2349
 */
2350
function give_get_view_receipt_link( $donation_id ) {
2351
	
2352
	return sprintf(
2353
		'<a href="%1$s">%2$s</a>',
2354
		esc_url( give_get_view_receipt_url( $donation_id ) ),
2355
		esc_html__( 'View the receipt in your browser &raquo;', 'give' )
2356
	);
2357
	
2358
}
2359
2360
/**
2361
 * Get "View in browser" Receipt URL for email.
2362
 *
2363
 * @since 2.4.1
2364
 *
2365
 * @param int $donation_id Donation ID.
2366
 *
2367
 * @return string
2368
 */
2369
function give_get_view_receipt_url( $donation_id ) {
2370
	
2371
	$receipt_url = esc_url(
2372
		add_query_arg(
2373
			array(
2374
                'action'     => 'view_in_browser',
2375
				'_give_hash' => give_get_payment_key( $donation_id ),
2376
			), give_get_history_page_uri()
2377
		)
2378
	);
2379
	
2380
	return $receipt_url;
2381
}
2382
2383
/**
2384
 * This function is used to display donation receipt content based on the parameters.
2385
 *
2386
 * @param $args
2387
 *
2388
 * @since 2.4.1
2389
 *
2390
 * @return bool|mixed
2391
 */
2392
function give_display_donation_receipt( $args ) {
2393
	
2394
	global $give_receipt_args;
2395
	
2396
	$give_receipt_args = $args;
2397
	
2398
	ob_start();
2399
	
2400
	$get_data     = give_clean( filter_input_array( INPUT_GET ) );
2401
	$donation_id  = ! empty( $get_data['donation_id'] ) ? $get_data['donation_id'] : false;
2402
	$receipt_type = ! empty( $get_data['receipt_type'] ) ? $get_data['receipt_type'] : false;
2403
	
2404
	$give_receipt_args['id'] = $donation_id;
2405
	
2406
	if ( 'view_in_browser' !== $receipt_type ) {
2407
	 
2408
		$email_access = give_get_option( 'email_access' );
2409
		$is_email_access = give_is_setting_enabled( $email_access ) && ! Give()->email_access->token_exists;
2410
		
0 ignored issues
show
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
2411
		
2412
		// No donation id found & Email Access is Turned on.
2413
		if ( ! $donation_id ) {
2414
			
2415
			if( $is_email_access ){
0 ignored issues
show
Space after opening control structure is required
Loading history...
No space before opening parenthesis is prohibited
Loading history...
2416
				give_get_template_part( 'email-login-form' );
2417
			} else{
0 ignored issues
show
Space after opening control structure is required
Loading history...
No space before opening parenthesis is prohibited
Loading history...
2418
				echo Give()->notices->print_frontend_notice( $args['error'], false, 'error' );
0 ignored issues
show
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'Give'
Loading history...
2419
			}
2420
			
2421
			return ob_get_clean();
2422
		}
2423
		
2424
		// Donation id provided, but user is logged out. Offer them the ability to login and view the receipt.
2425
		if ( ! ( $user_can_view = give_can_view_receipt( $donation_id ) ) ) {
2426
			
2427
			if( true === Give()->session->get( 'donor_donation_mismatch' ) ) {
0 ignored issues
show
Space after opening control structure is required
Loading history...
No space before opening parenthesis is prohibited
Loading history...
2428
				
2429
				/**
2430
				 * This filter will be used to modify the donor mismatch text for front end error notice.
2431
				 *
2432
				 * @since 2.3.1
2433
				 */
2434
				$donor_mismatch_text = apply_filters( 'give_receipt_donor_mismatch_notice_text', __( 'You are trying to access invalid donation receipt. Please try again.', 'give' ) );
2435
				
2436
				echo Give()->notices->print_frontend_notice(
0 ignored issues
show
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'Give'
Loading history...
2437
					$donor_mismatch_text,
2438
					false,
2439
					'error'
2440
				);
2441
				
2442
			} elseif( $is_email_access ) {
0 ignored issues
show
Space after opening control structure is required
Loading history...
No space before opening parenthesis is prohibited
Loading history...
2443
				
2444
				give_get_template_part( 'email-login-form' );
2445
				
2446
			}else{
0 ignored issues
show
Space after opening control structure is required
Loading history...
No space before opening parenthesis is prohibited
Loading history...
2447
				
2448
				global $give_login_redirect;
2449
				
2450
				$give_login_redirect = give_get_current_page_url();
2451
				
2452
				Give()->notices->print_frontend_notice(
2453
					apply_filters( 'give_must_be_logged_in_error_message',
2454
						__( 'You must be logged in to view this donation receipt.', 'give' )
2455
					)
2456
				);
2457
				
2458
				give_get_template_part( 'shortcode', 'login' );
2459
			}
2460
			
2461
			return ob_get_clean();
2462
		}
2463
		
2464
		/**
2465
		 * Check if the user has permission to view the receipt.
2466
		 *
2467
		 * If user is logged in, user ID is compared to user ID of ID stored in payment meta
2468
		 * or if user is logged out and donation was made as a guest, the donation session is checked for
2469
		 * or if user is logged in and the user can view sensitive shop data.
2470
		 */
2471
		if ( ! apply_filters( 'give_user_can_view_receipt', $user_can_view, $args ) ) {
2472
			return Give()->notices->print_frontend_notice( $args['error'], false, 'error' );
2473
		}
0 ignored issues
show
Blank line found after control structure
Loading history...
2474
		
2475
	}
2476
	
2477
	give_get_template_part( 'shortcode', 'receipt' );
2478
	
2479
	return ob_get_clean();
2480
}