Test Failed
Push — master ( 9f3342...e85998 )
by Devin
08:35
created

misc-functions.php ➔ give_is_host()   D

Complexity

Conditions 25
Paths 26

Size

Total Lines 71

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 25
nc 26
nop 1
dl 0
loc 71
rs 4.1666
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A misc-functions.php ➔ _give_deprecated_function() 0 30 4
A misc-functions.php ➔ give_get_admin_post_id() 0 9 6

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
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
introduced by
Found "== 1". Use Yoda Condition checks, you must
Loading history...
86
		$ret = true;
87
	} elseif ( count( $gateways ) == 1 ) {
0 ignored issues
show
introduced by
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
introduced by
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
introduced by
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
introduced by
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
introduced by
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
161
	} elseif ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) {
0 ignored issues
show
introduced by
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
introduced by
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
introduced by
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
Duplication introduced by
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
Duplication introduced by
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
	$find_host = gethostname();
341
342
	if ( strpos( $find_host, 'sgvps.net' ) ) {
343
		$host = 'Siteground';
344
	} elseif ( defined( 'WPE_APIKEY' ) ) {
345
		$host = 'WP Engine';
346
	} elseif ( defined( 'PAGELYBIN' ) || strpos( $find_host, 'pagelyhosting.com' ) ) {
347
		$host = 'Pagely';
348
	} elseif ( strpos( $find_host, 'secureserver.net') ) {
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
349
		$host = "GoDaddy/Media Temple";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal GoDaddy/Media Temple does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
350
	} elseif ( DB_HOST == 'localhost:/tmp/mysql5.sock' ) {
0 ignored issues
show
introduced by
Found "== '". Use Yoda Condition checks, you must
Loading history...
351
		$host = 'ICDSoft';
352
	} elseif ( DB_HOST == 'mysqlv5' ) {
0 ignored issues
show
introduced by
Found "== '". Use Yoda Condition checks, you must
Loading history...
353
		$host = 'NetworkSolutions';
354
	} elseif ( strpos( $find_host, preg_match('wp', $find_host) ) ) {
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
355
		$host = "Bluehost";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal Bluehost does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
356
	} elseif ( strpos( DB_HOST, 'ipagemysql.com' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
357
		$host = 'iPage';
358
	} elseif ( strpos( DB_HOST, 'ipowermysql.com' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
359
		$host = 'IPower';
360
	} elseif ( strpos( DB_HOST, '.gridserver.com' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
361
		$host = 'MediaTemple Grid';
362
	} elseif ( strpos( DB_HOST, '.pair.com' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
363
		$host = 'pair Networks';
364
	} elseif ( strpos( DB_HOST, '.stabletransit.com' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
365
		$host = 'Rackspace Cloud';
366
	} elseif ( strpos( DB_HOST, '.sysfix.eu' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
367
		$host = 'SysFix.eu Power Hosting';
368
	} elseif ( strpos( $_SERVER['SERVER_NAME'], 'Flywheel' ) !== false || strpos( $find_host, 'fw' ) ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
369
		$host = 'Flywheel';
370
	} else {
371
		// Adding a general fallback for data gathering
372
		$host = 'DBH: ' . DB_HOST . ', SRV: ' . $_SERVER['SERVER_NAME'];
0 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
373
	}
374
375
	return $host;
376
}
377
378
/**
379
 * Marks a function as deprecated and informs when it has been used.
380
 *
381
 * There is a hook give_deprecated_function_run that will be called that can be used
382
 * to get the backtrace up to what file and function called the deprecated
383
 * function.
384
 *
385
 * The current behavior is to trigger a user error if WP_DEBUG is true.
386
 *
387
 * This function is to be used in every function that is deprecated.
388
 *
389
 * @uses do_action() Calls 'give_deprecated_function_run' and passes the function name, what to use instead,
390
 *   and the version the function was deprecated in.
391
 * @uses apply_filters() Calls 'give_deprecated_function_trigger_error' and expects boolean value of true to do
392
 *   trigger or false to not trigger error.
393
 *
394
 * @param string $function    The function that was called.
395
 * @param string $version     The plugin version that deprecated the function.
396
 * @param string $replacement Optional. The function that should have been called.
397
 * @param array  $backtrace   Optional. Contains stack backtrace of deprecated function.
398
 */
399
function _give_deprecated_function( $function, $version, $replacement = null, $backtrace = null ) {
400
401
	/**
402
	 * Fires while give deprecated function call occurs.
403
	 *
404
	 * Allow you to hook to deprecated function call.
405
	 *
406
	 * @since 1.0
407
	 *
408
	 * @param string $function    The function that was called.
409
	 * @param string $replacement Optional. The function that should have been called.
410
	 * @param string $version     The plugin version that deprecated the function.
411
	 */
412
	do_action( 'give_deprecated_function_run', $function, $replacement, $version );
413
414
	$show_errors = current_user_can( 'manage_options' );
415
416
	// Allow plugin to filter the output error trigger.
417
	if ( WP_DEBUG && apply_filters( 'give_deprecated_function_trigger_error', $show_errors ) ) {
418
		if ( ! is_null( $replacement ) ) {
419
			trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since Give version %2$s! Use %3$s instead.', 'give' ), $function, $version, $replacement ) );
420
			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
introduced by
The use of function print_r() is discouraged
Loading history...
421
			// Alternatively we could dump this to a file.
422
		} else {
423
			trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since Give version %2$s with no alternative available.', 'give' ), $function, $version ) );
424
			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
introduced by
The use of function print_r() is discouraged
Loading history...
425
			// Alternatively we could dump this to a file.
426
		}
427
	}
428
}
429
430
/**
431
 * Give Get Admin ID
432
 *
433
 * Helper function to return the ID of the post for admin usage
434
 *
435
 * @return string $post_id
436
 */
437
function give_get_admin_post_id() {
438
	$post_id = isset( $_REQUEST['post'] ) ? absint( $_REQUEST['post'] ) : null;
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
439
440
	$post_id = ! empty( $post_id ) ? $post_id : ( isset( $_REQUEST['post_id'] ) ? absint( $_REQUEST['post_id'] ) : null );
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
441
442
	$post_id = ! empty( $post_id ) ? $post_id : ( isset( $_REQUEST['post_ID'] ) ? absint( $_REQUEST['post_ID'] ) : null );
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
443
444
	return $post_id;
445
}
446
447
/**
448
 * Get PHP Arg Separator Output
449
 *
450
 * @since 1.0
451
 * @return string Arg separator output
452
 */
453
function give_get_php_arg_separator_output() {
454
	return ini_get( 'arg_separator.output' );
455
}
456
457
458
/**
459
 * Month Num To Name
460
 *
461
 * Takes a month number and returns the name three letter name of it.
462
 *
463
 * @since 1.0
464
 *
465
 * @param int $n
466
 *
467
 * @return string Short month name
468
 */
469
function give_month_num_to_name( $n ) {
470
	$timestamp = mktime( 0, 0, 0, $n, 1, 2005 );
471
472
	return date_i18n( 'M', $timestamp );
473
}
474
475
476
/**
477
 * Checks whether function is disabled.
478
 *
479
 * @since 1.0
480
 *
481
 * @param string $function Name of the function.
482
 *
483
 * @return bool Whether or not function is disabled.
484
 */
485
function give_is_func_disabled( $function ) {
486
	$disabled = explode( ',', ini_get( 'disable_functions' ) );
487
488
	return in_array( $function, $disabled );
489
}
490
491
/**
492
 * Give Newsletter
493
 *
494
 * Returns the main Give newsletter form
495
 */
496
function give_get_newsletter() {
497
	?>
498
499
	<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>
500
501
	<div class="give-newsletter-form-wrap">
502
503
		<form action="//givewp.us3.list-manage.com/subscribe/post?u=3ccb75d68bda4381e2f45794c&amp;id=12a081aa13"
504
			  method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate"
505
			  target="_blank">
506
			<div class="give-newsletter-confirmation">
507
				<p><?php esc_html_e( 'To complete your subscription, click the confirmation link in your email. Thank you!', 'give' ); ?></p>
508
			</div>
509
510
			<table class="form-table give-newsletter-form">
511
				<tr valign="middle">
512
					<td>
513
						<label for="mce-EMAIL"
514
							   class="screen-reader-text"><?php esc_html_e( 'Email Address (required)', 'give' ); ?></label>
515
						<input type="email" name="EMAIL" id="mce-EMAIL"
516
							   placeholder="<?php esc_attr_e( 'Email Address (required)', 'give' ); ?>"
517
							   class="required email" value="" required>
518
					</td>
519
					<td>
520
						<label for="mce-FNAME"
521
							   class="screen-reader-text"><?php esc_html_e( 'First Name', 'give' ); ?></label>
522
						<input type="text" name="FNAME" id="mce-FNAME"
523
							   placeholder="<?php esc_attr_e( 'First Name', 'give' ); ?>" class="" value="" required>
524
					</td>
525
					<td>
526
						<label for="mce-LNAME"
527
							   class="screen-reader-text"><?php esc_html_e( 'Last Name', 'give' ); ?></label>
528
						<input type="text" name="LNAME" id="mce-LNAME"
529
							   placeholder="<?php esc_attr_e( 'Last Name', 'give' ); ?>" class="" value="">
530
					</td>
531
					<td>
532
						<input type="submit" name="subscribe" id="mc-embedded-subscribe" class="button"
533
							   value="<?php esc_attr_e( 'Subscribe', 'give' ); ?>">
534
					</td>
535
				</tr>
536
			</table>
537
		</form>
538
539
		<div style="position: absolute; left: -5000px;">
540
			<input type="text" name="b_3ccb75d68bda4381e2f45794c_12a081aa13" tabindex="-1" value="">
541
		</div>
542
543
	</div>
544
545
	<script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'></script>
0 ignored issues
show
introduced by
Scripts must be registered/enqueued via wp_enqueue_script
Loading history...
546
	<script type='text/javascript'>(
547
			function( $ ) {
548
				window.fnames = new Array();
549
				window.ftypes = new Array();
550
				fnames[ 0 ] = 'EMAIL';
551
				ftypes[ 0 ] = 'email';
552
				fnames[ 1 ] = 'FNAME';
553
				ftypes[ 1 ] = 'text';
554
				fnames[ 2 ] = 'LNAME';
555
				ftypes[ 2 ] = 'text';
556
557
				$( 'form[name="mc-embedded-subscribe-form"]' ).removeAttr( 'novalidate' );
558
559
				//Successful submission
560
				$( 'form[name="mc-embedded-subscribe-form"]' ).on( 'submit', function() {
561
562
					var email_field = $( this ).find( '#mce-EMAIL' ).val();
563
					if ( ! email_field ) {
564
						return false;
565
					}
566
					$( this ).find( '.give-newsletter-confirmation' ).show().delay( 5000 ).slideUp();
567
					$( this ).find( '.give-newsletter-form' ).hide();
568
569
				} );
570
571
			}( jQuery )
572
		);
573
		var $mcj = jQuery.noConflict( true );
574
575
576
	</script>
577
	<!--End mc_embed_signup-->
578
579
	<?php
580
}
581
582
583
/**
584
 * Create SVG library function
585
 *
586
 * @param string $icon
587
 *
588
 * @return string
589
 */
590
function give_svg_icons( $icon ) {
591
592
	// Store your SVGs in an associative array
593
	$svgs = array(
594
		'microphone'    => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE2LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgd2lkdGg9IjY0cHgiIGhlaWdodD0iMTAwcHgiIHZpZXdCb3g9IjAgLTIwIDY0IDEyMCIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNjQgMTAwOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8Zz4NCgk8Zz4NCgkJPHBhdGggZD0iTTYyLDM2LjIxNWgtM2MtMS4xLDAtMiwwLjktMiwyVjUyYzAsNi42ODYtNS4yNjYsMTgtMjUsMThTNyw1OC42ODYsNyw1MlYzOC4yMTVjMC0xLjEtMC45LTItMi0ySDJjLTEuMSwwLTIsMC45LTIsMlY1Mg0KCQkJYzAsMTEuMTg0LDguMjE1LDIzLjE1MiwyNywyNC44MDFWOTBIMTRjLTEuMSwwLTIsMC44OTgtMiwydjZjMCwxLjEsMC45LDIsMiwyaDM2YzEuMSwwLDItMC45LDItMnYtNmMwLTEuMTAyLTAuOS0yLTItMkgzN1Y3Ni44MDENCgkJCUM1NS43ODUsNzUuMTUyLDY0LDYzLjE4NCw2NCw1MlYzOC4yMTVDNjQsMzcuMTE1LDYzLjEsMzYuMjE1LDYyLDM2LjIxNXoiLz4NCgkJPHBhdGggZD0iTTMyLDYwYzExLjczMiwwLDE1LTQuODE4LDE1LThWMzYuMjE1SDE3VjUyQzE3LDU1LjE4MiwyMC4yNjYsNjAsMzIsNjB6Ii8+DQoJCTxwYXRoIGQ9Ik00Nyw4YzAtMy4xODQtMy4yNjgtOC0xNS04QzIwLjI2NiwwLDE3LDQuODE2LDE3LDh2MjEuMjE1aDMwVjh6Ii8+DQoJPC9nPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPC9zdmc+DQo=',
595
		'alert'         => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE2LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgd2lkdGg9IjI4LjkzOHB4IiBoZWlnaHQ9IjI1LjAwNXB4IiB2aWV3Qm94PSIwIDAgMjguOTM4IDI1LjAwNSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMjguOTM4IDI1LjAwNTsiDQoJIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPHBhdGggc3R5bGU9ImZpbGw6IzAwMDAwMDsiIGQ9Ik0yOC44NTksMjQuMTU4TDE0Ljk1NywwLjI3OUMxNC44NTYsMC4xMDYsMTQuNjcsMCwxNC40NjgsMGMtMC4xOTgsMC0wLjM4MywwLjEwNi0wLjQ4MSwwLjI3OQ0KCUwwLjA3OSwyNC4xNThjLTAuMTAyLDAuMTc1LTAuMTA2LDAuMzg5LTAuMDA2LDAuNTY1YzAuMTAzLDAuMTc0LDAuMjg3LDAuMjgyLDAuNDg4LDAuMjgyaDI3LjgxNGMwLjIwMSwwLDAuMzg5LTAuMTA4LDAuNDg4LTAuMjgyDQoJYzAuMDQ3LTAuMDg4LDAuMDc0LTAuMTg2LDAuMDc0LTAuMjgxQzI4LjkzOCwyNC4zNDMsMjguOTExLDI0LjI0NSwyOC44NTksMjQuMTU4eiBNMTYuMzY5LDguNDc1bC0wLjQ2Miw5LjQ5M2gtMi4zODlsLTAuNDYxLTkuNDkzDQoJSDE2LjM2OXogTTE0LjcxMSwyMi44MjhoLTAuMDQyYy0xLjA4OSwwLTEuODQzLTAuODE3LTEuODQzLTEuOTA3YzAtMS4xMzEsMC43NzQtMS45MDcsMS44ODUtMS45MDdzMS44NDYsMC43NzUsMS44NjcsMS45MDcNCglDMTYuNTc5LDIyLjAxMSwxNS44NDQsMjIuODI4LDE0LjcxMSwyMi44Mjh6Ii8+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8L3N2Zz4NCg==',
596
		'placemark'     => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxNi4wLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB3aWR0aD0iMTAwcHgiIGhlaWdodD0iMTAwcHgiIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMDAgMTAwIiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxnPg0KCTxwYXRoIGQ9Ik01MC40MzQsMjAuMjcxYy0xMi40OTksMC0yMi42NjgsMTAuMTY5LTIyLjY2OCwyMi42NjhjMCwxMS44MTQsMTguODE1LDMyLjE1NSwyMC45NiwzNC40MzdsMS43MDgsMS44MTZsMS43MDgtMS44MTYNCgkJYzIuMTQ1LTIuMjgxLDIwLjk2LTIyLjYyMywyMC45Ni0zNC40MzdDNzMuMTAzLDMwLjQ0LDYyLjkzNCwyMC4yNzEsNTAuNDM0LDIwLjI3MXogTTUwLjQzNCw1Mi4zMmMtNS4xNzIsMC05LjM4LTQuMjA4LTkuMzgtOS4zOA0KCQlzNC4yMDgtOS4zOCw5LjM4LTkuMzhjNS4xNzMsMCw5LjM4LDQuMjA4LDkuMzgsOS4zOFM1NS42MDcsNTIuMzIsNTAuNDM0LDUyLjMyeiIvPg0KPC9nPg0KPC9zdmc+DQo=',
597
		'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==',
598
		'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',
599
	);
600
601
	// Return the chosen icon's SVG string
602
	return $svgs[ $icon ];
603
}
604
605
/**
606
 * Modify Admin Nav Menu Label
607
 *
608
 * @since 1.3
609
 *
610
 * @param object $post_type The current object to add a menu items meta box for.
611
 *
612
 * @return mixed
613
 */
614
function modify_nav_menu_meta_box_object( $post_type ) {
615
	if ( isset( $post_type->name ) && $post_type->name == 'give_forms' ) {
0 ignored issues
show
introduced by
Found "== '". Use Yoda Condition checks, you must
Loading history...
616
		$post_type->labels->name = esc_html__( 'Donation Forms', 'give' );
617
	}
618
619
	return $post_type;
620
}
621
622
add_filter( 'nav_menu_meta_box_object', 'modify_nav_menu_meta_box_object' );
623
624
/**
625
 * Show Donation Forms Post Type in Appearance > Menus by default on fresh install.
626
 *
627
 * @since 1.8.14
628
 *
629
 * @todo  Remove this, when WordPress Core ticket is resolved (https://core.trac.wordpress.org/ticket/16828).
630
 *
631
 * @return bool
632
 */
633
function give_donation_metabox_menu() {
634
635
	// Get Current Screen.
636
	$screen = get_current_screen();
637
638
	// Proceed, if current screen is navigation menus.
639
	if ( 'nav-menus' === $screen->id && give_is_setting_enabled( give_get_option( 'forms_singular' ) ) && ! get_user_option( 'give_is_donation_forms_menu_updated' ) ) {
640
641
		// Return false, if it fails to retrieve hidden meta box list and is not admin.
642
		if ( ! is_admin() || ( ! $hidden_meta_boxes = get_user_option( 'metaboxhidden_nav-menus' ) ) ) {
643
			return false;
644
		}
645
646
		// Return false, In case, we don't find 'Donation Form' in hidden meta box list.
647
		if ( ! in_array( 'add-post-type-give_forms', $hidden_meta_boxes, true ) ) {
648
			return false;
649
		}
650
651
		// Exclude 'Donation Form' value from hidden meta box's list.
652
		$hidden_meta_boxes = array_diff( $hidden_meta_boxes, array( 'add-post-type-give_forms' ) );
653
654
		// Get current user ID.
655
		$user = wp_get_current_user();
656
657
		update_user_option( $user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true );
658
		update_user_option( $user->ID, 'give_is_donation_forms_menu_updated', true, true );
659
	}
660
}
661
662
add_action( 'current_screen', 'give_donation_metabox_menu' );
663
664
/**
665
 * Array_column backup usage
666
 *
667
 * This file is part of the array_column library.
668
 *
669
 * @since      : 1.3.0.1
670
 *
671
 * @copyright  Copyright (c) Ben Ramsey (http://benramsey.com)
672
 * @license    https://opensource.org/licenses/MIT MIT
673
 */
674
675
if ( ! function_exists( 'array_column' ) ) {
676
	/**
677
	 * Returns the values from a single column of the input array, identified by
678
	 * the $columnKey.
679
	 *
680
	 * Optionally, you may provide an $indexKey to index the values in the returned
681
	 * array by the values from the $indexKey column in the input array.
682
	 *
683
	 * @param array      $input     A multi-dimensional array (record set) from which to pull
684
	 *                              a column of values.
685
	 * @param int|string $columnKey The column of values to return. This value may be the
686
	 *                              integer key of the column you wish to retrieve, or it
687
	 *                              may be the string key name for an associative array.
688
	 * @param mixed      $indexKey  (Optional.) The column to use as the index/keys for
689
	 *                              the returned array. This value may be the integer key
690
	 *                              of the column, or it may be the string key name.
691
	 *
692
	 * @return array
693
	 */
694
	function array_column( $input = null, $columnKey = null, $indexKey = null ) {
0 ignored issues
show
Unused Code introduced by
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...
Unused Code introduced by
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...
Unused Code introduced by
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...
695
		// Using func_get_args() in order to check for proper number of
696
		// parameters and trigger errors exactly as the built-in array_column()
697
		// does in PHP 5.5.
698
		$argc   = func_num_args();
699
		$params = func_get_args();
700
701
		if ( $argc < 2 ) {
702
			trigger_error( sprintf( esc_html__( 'array_column() expects at least 2 parameters, %s given.', 'give' ), $argc ), E_USER_WARNING );
703
704
			return null;
705
		}
706
707
		if ( ! is_array( $params[0] ) ) {
708
			trigger_error( sprintf( esc_html__( 'array_column() expects parameter 1 to be array, %s given.', 'give' ), gettype( $params[0] ) ), E_USER_WARNING );
709
710
			return null;
711
		}
712
713 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
Duplication introduced by
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...
714
			trigger_error( esc_html__( 'array_column(): The column key should be either a string or an integer.', 'give' ), E_USER_WARNING );
715
716
			return false;
717
		}
718
719 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
Duplication introduced by
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...
720
			trigger_error( esc_html__( 'array_column(): The index key should be either a string or an integer.', 'give' ), E_USER_WARNING );
721
722
			return false;
723
		}
724
725
		$paramsInput     = $params[0];
726
		$paramsColumnKey = ( $params[1] !== null ) ? (string) $params[1] : null;
727
728
		$paramsIndexKey = null;
729
		if ( isset( $params[2] ) ) {
730
			if ( is_float( $params[2] ) || is_int( $params[2] ) ) {
731
				$paramsIndexKey = (int) $params[2];
732
			} else {
733
				$paramsIndexKey = (string) $params[2];
734
			}
735
		}
736
737
		$resultArray = array();
738
739
		foreach ( $paramsInput as $row ) {
740
			$key    = $value = null;
741
			$keySet = $valueSet = false;
742
743
			if ( $paramsIndexKey !== null && array_key_exists( $paramsIndexKey, $row ) ) {
744
				$keySet = true;
745
				$key    = (string) $row[ $paramsIndexKey ];
746
			}
747
748
			if ( $paramsColumnKey === null ) {
749
				$valueSet = true;
750
				$value    = $row;
751
			} elseif ( is_array( $row ) && array_key_exists( $paramsColumnKey, $row ) ) {
752
				$valueSet = true;
753
				$value    = $row[ $paramsColumnKey ];
754
			}
755
756
			if ( $valueSet ) {
757
				if ( $keySet ) {
758
					$resultArray[ $key ] = $value;
759
				} else {
760
					$resultArray[] = $value;
761
				}
762
			}
763
		}
764
765
		return $resultArray;
766
	}
767
}// End if().
768
769
/**
770
 * Determines the receipt visibility status.
771
 *
772
 * @since 1.3.2
773
 *
774
 * @param int $donation_id Donation ID.
775
 *
776
 * @return bool Whether the receipt is visible or not.
777
 */
778
function give_can_view_receipt( $donation_id ) {
779
780
	global $give_receipt_args;
781
782
	$donor            = false;
783
	$can_view_receipt = false;
784
785
	// Bail out, if donation id doesn't exist.
786
	if ( empty( $donation_id ) ) {
787
		return $can_view_receipt;
788
	}
789
790
	$give_receipt_args['id'] = $donation_id;
791
792
	// Add backward compatibility.
793
	if ( ! is_numeric( $donation_id ) ) {
794
		$give_receipt_args['id'] = give_get_donation_id_by_key( $donation_id );
795
	}
796
797
	// Return to download receipts from admin panel.
798
	if ( current_user_can( 'export_give_reports' ) ) {
799
800
		/**
801
		 * This filter will be used to modify can view receipt response when accessed from admin.
802
		 *
803
		 * @since 2.3.1
804
		 */
805
		return apply_filters( 'give_can_admin_view_receipt', true );
806
	}
807
808
	if ( is_user_logged_in() || current_user_can( 'view_give_sensitive_data' ) ) {
809
810
		// Proceed only, if user is logged in or can view sensitive Give data.
811
		$donor = Give()->donors->get_donor_by( 'user_id', get_current_user_id() );
812
813
	} elseif ( ! is_user_logged_in() ) {
814
815
		// Check whether it is purchase session?
816
		// This condition is to show receipt to donor after donation.
817
		$purchase_session = give_get_purchase_session();
818
819
		if (
820
			! empty( $purchase_session )
821
			&& absint( $purchase_session['donation_id'] ) === absint( $donation_id )
822
		) {
823
			$donor = Give()->donors->get_donor_by( 'email', $purchase_session['user_email'] );
824
		}
825
826
		// Check whether it is receipt access session?
827
		$receipt_session    = give_get_receipt_session();
828
		$email_access_token = ! empty( $_COOKIE['give_nl'] ) ? give_clean( $_COOKIE['give_nl'] ) : false;
0 ignored issues
show
introduced by
Due to using Batcache, server side based client related logic will not work, use JS instead.
Loading history...
829
830
		if (
831
			! empty( $receipt_session ) ||
832
			(
833
				give_is_setting_enabled( give_get_option( 'email_access' ) ) &&
834
				! empty( $email_access_token )
835
			)
836
		) {
837
			$donor = ! empty( $email_access_token )
838
				? Give()->donors->get_donor_by_token( $email_access_token )
0 ignored issues
show
Documentation introduced by
$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...
839
				: false;
840
		}
841
	}
842
843
	// If donor object exists, compare the donation ids of donor with the donation receipt donor tries to access.
844
	if ( is_object( $donor ) ) {
845
		$is_donor_donated = in_array( (int) $donation_id, array_map( 'absint', explode( ',', $donor->payment_ids ) ), true );
846
		$can_view_receipt = $is_donor_donated ? true : $can_view_receipt;
847
848
		if ( ! $is_donor_donated ) {
849
			Give()->session->set( 'donor_donation_mismatch', true );
850
		}
851
	}
852
853
	return (bool) apply_filters( 'give_can_view_receipt', $can_view_receipt, $donation_id );
854
855
}
856
857
/**
858
 * Fallback for cal_days_in_month
859
 *
860
 * Fallback in case the calendar extension is not loaded in PHP; Only supports Gregorian calendar
861
 */
862
if ( ! function_exists( 'cal_days_in_month' ) ) {
863
	/**
864
	 * cal_days_in_month
865
	 *
866
	 * @param int $calendar
867
	 * @param int $month
868
	 * @param int $year
869
	 *
870
	 * @return bool|string
871
	 */
872
	function cal_days_in_month( $calendar, $month, $year ) {
0 ignored issues
show
Unused Code introduced by
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...
873
		return date( 't', mktime( 0, 0, 0, $month, 1, $year ) );
874
	}
875
}
876
877
/**
878
 * Get plugin info including status, type, and license validation.
879
 *
880
 * This is an enhanced version of get_plugins() that returns the status
881
 * (`active` or `inactive`) of all plugins, type of plugin (`add-on` or `other`
882
 * and license validation for Give add-ons (`true` or `false`). Does not include
883
 * MU plugins.
884
 *
885
 * @since 1.8.0
886
 *
887
 * @return array Plugin info plus status, type, and license validation if
888
 *               available.
889
 */
890
function give_get_plugins() {
891
	$plugins             = get_plugins();
892
	$active_plugin_paths = (array) get_option( 'active_plugins', array() );
893
894 View Code Duplication
	if ( is_multisite() ) {
0 ignored issues
show
Duplication introduced by
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...
895
		$network_activated_plugin_paths = array_keys( get_site_option( 'active_sitewide_plugins', array() ) );
896
		$active_plugin_paths            = array_merge( $active_plugin_paths, $network_activated_plugin_paths );
897
	}
898
899
	foreach ( $plugins as $plugin_path => $plugin_data ) {
900
		// Is plugin active?
901
		if ( in_array( $plugin_path, $active_plugin_paths ) ) {
902
			$plugins[ $plugin_path ]['Status'] = 'active';
903
		} else {
904
			$plugins[ $plugin_path ]['Status'] = 'inactive';
905
		}
906
907
		$dirname = strtolower( dirname( $plugin_path ) );
908
909
		// Is the plugin a Give add-on?
910
		if (
911
			false !== strpos( $dirname, 'give-' )
912
			&& in_array( $plugin_data['Author'], array( 'WordImpress', 'GiveWP' ) )
913
		) {
914
			// Plugin is a Give-addon.
915
			$plugins[ $plugin_path ]['Type'] = 'add-on';
916
917
			/* @var stdClass $license_active */
918
			$license_active = __give_get_active_license_info( Give_License::get_short_name( $plugin_data['Name'] ) );
919
920
			// Does a valid license exist?
921
			if ( ! empty( $license_active ) && 'valid' === $license_active->license ) {
922
				$plugins[ $plugin_path ]['License'] = true;
923
			} else {
924
				$plugins[ $plugin_path ]['License'] = false;
925
			}
926
		} else {
927
			// Plugin is not a Give add-on.
928
			$plugins[ $plugin_path ]['Type'] = 'other';
929
		}
930
	}
931
932
	return $plugins;
933
}
934
935
/**
936
 * Check if terms enabled or not for form.
937
 *
938
 * @since 1.8
939
 *
940
 * @param $form_id
941
 *
942
 * @return bool
943
 */
944
function give_is_terms_enabled( $form_id ) {
945
	$form_option = give_get_meta( $form_id, '_give_terms_option', true );
946
947
	if ( give_is_setting_enabled( $form_option, 'global' ) && give_is_setting_enabled( give_get_option( 'terms' ) ) ) {
948
		return true;
949
950
	} elseif ( give_is_setting_enabled( $form_option ) ) {
951
		return true;
952
953
	} else {
954
		return false;
955
	}
956
}
957
958
/**
959
 * Delete donation stats cache.
960
 *
961
 * @todo  Resolve stats cache key naming issue. Currently it is difficult to regenerate cache key.
962
 *
963
 * @since 1.8.7
964
 *
965
 * @param string|array $date_range Date for stats.
966
 *                                 Date value should be in today, yesterday, this_week, last_week, this_month,
967
 *                                 last_month, this_quarter, last_quarter, this_year, last_year. For date value other,
968
 *                                 all cache will be removed.
969
 *
970
 * @param array        $args
971
 *
972
 * @return WP_Error|bool
973
 */
974
function give_delete_donation_stats( $date_range = '', $args = array() ) {
975
976
	// Delete all cache.
977
	$status = Give_Cache::delete( Give_Cache::get_options_like( 'give_stats' ) );
978
979
	/**
980
	 * Fire the action when donation stats delete.
981
	 *
982
	 * @since 1.8.7
983
	 *
984
	 * @param string|array $date_range
985
	 * @param array        $args
986
	 */
987
	do_action( 'give_delete_donation_stats', $status, $date_range, $args );
988
989
	return $status;
990
}
991
992
/**
993
 * Check if admin creating new donation form or not.
994
 *
995
 * @since 2.0
996
 * @return bool
997
 */
998
function give_is_add_new_form_page() {
999
	$status = false;
1000
1001
	if ( false !== strpos( $_SERVER['REQUEST_URI'], '/wp-admin/post-new.php?post_type=give_forms' ) ) {
1002
		$status = true;
1003
	}
1004
1005
	return $status;
1006
}
1007
1008
/**
1009
 * Get Form/Payment meta.
1010
 *
1011
 * Note: This function will help you to get meta for payment and form.
1012
 *       If you want to get meta for donors then use get_meta of Give_Donor and
1013
 *       If you want to get meta for logs then use get_meta of Give_Logging->logmeta_db.
1014
 *
1015
 * @since 1.8.8
1016
 *
1017
 * @param int    $id
1018
 * @param string $meta_key
1019
 * @param bool   $single
1020
 * @param bool   $default
1021
 *
1022
 * @return mixed
1023
 */
1024
function give_get_meta( $id, $meta_key = '', $single = false, $default = false ) {
1025
	/**
1026
	 * Filter the meta value
1027
	 *
1028
	 * @since 1.8.8
1029
	 */
1030
	$meta_value = apply_filters( 'give_get_meta', get_post_meta( $id, $meta_key, $single ), $id, $meta_key, $default );
1031
1032
	if ( ( empty( $meta_key ) || empty( $meta_value ) ) && $default ) {
1033
		$meta_value = $default;
1034
	}
1035
1036
	return $meta_value;
1037
}
1038
1039
/**
1040
 * Update Form/Payment meta.
1041
 *
1042
 * @since 1.8.8
1043
 *
1044
 * @param int    $id
1045
 * @param string $meta_key
1046
 * @param mixed  $meta_value
1047
 * @param mixed  $prev_value
1048
 *
1049
 * @return mixed
1050
 */
1051
function give_update_meta( $id, $meta_key, $meta_value, $prev_value = '' ) {
1052
	$status = update_post_meta( $id, $meta_key, $meta_value, $prev_value );
1053
1054
	/**
1055
	 * Filter the meta value update status
1056
	 *
1057
	 * @since 1.8.8
1058
	 */
1059
	return apply_filters( 'give_update_meta', $status, $id, $meta_key, $meta_value );
1060
}
1061
1062
/**
1063
 * Delete Form/Payment meta.
1064
 *
1065
 * @since 1.8.8
1066
 *
1067
 * @param int    $id
1068
 * @param string $meta_key
1069
 * @param string $meta_value
1070
 *
1071
 * @return mixed
1072
 */
1073
function give_delete_meta( $id, $meta_key, $meta_value = '' ) {
1074
	$status = delete_post_meta( $id, $meta_key, $meta_value );
1075
1076
	/**
1077
	 * Filter the meta value delete status
1078
	 *
1079
	 * @since 1.8.8
1080
	 */
1081
	return apply_filters( 'give_delete_meta', $status, $id, $meta_key, $meta_value );
1082
}
1083
1084
/**
1085
 * Check if the upgrade routine has been run for a specific action
1086
 *
1087
 * @since  1.0
1088
 *
1089
 * @param  string $upgrade_action The upgrade action to check completion for
1090
 *
1091
 * @return bool                   If the action has been added to the completed actions array
1092
 */
1093
function give_has_upgrade_completed( $upgrade_action = '' ) {
1094
	// Bailout.
1095
	if ( empty( $upgrade_action ) ) {
1096
		return false;
1097
	}
1098
1099
	// Fresh install?
1100
	// If fresh install then all upgrades will be consider as completed.
1101
	$is_fresh_install = ! Give_Cache_Setting::get_option( 'give_version' );
1102
	if ( $is_fresh_install ) {
1103
		return true;
1104
	}
1105
1106
	$completed_upgrades = give_get_completed_upgrades();
1107
1108
	return in_array( $upgrade_action, $completed_upgrades );
1109
1110
}
1111
1112
/**
1113
 * For use when doing 'stepped' upgrade routines, to see if we need to start somewhere in the middle
1114
 *
1115
 * @since 1.8
1116
 *
1117
 * @return mixed   When nothing to resume returns false, otherwise starts the upgrade where it left off
1118
 */
1119
function give_maybe_resume_upgrade() {
1120
	$doing_upgrade = get_option( 'give_doing_upgrade', false );
1121
	if ( empty( $doing_upgrade ) ) {
1122
		return false;
1123
	}
1124
1125
	return $doing_upgrade;
1126
}
1127
1128
/**
1129
 * Adds an upgrade action to the completed upgrades array
1130
 *
1131
 * @since  1.0
1132
 *
1133
 * @param  string $upgrade_action The action to add to the completed upgrades array
1134
 *
1135
 * @return bool                   If the function was successfully added
1136
 */
1137
function give_set_upgrade_complete( $upgrade_action = '' ) {
1138
1139
	if ( empty( $upgrade_action ) ) {
1140
		return false;
1141
	}
1142
1143
	$completed_upgrades   = give_get_completed_upgrades();
1144
	$completed_upgrades[] = $upgrade_action;
1145
1146
	// Remove any blanks, and only show uniques.
1147
	$completed_upgrades = array_unique( array_values( $completed_upgrades ) );
1148
1149
	/**
1150
	 * Fire the action when any upgrade set to complete.
1151
	 *
1152
	 * @since 1.8.12
1153
	 */
1154
	do_action( 'give_set_upgrade_completed', $upgrade_action, $completed_upgrades );
1155
1156
	return update_option( 'give_completed_upgrades', $completed_upgrades, false );
1157
}
1158
1159
/**
1160
 * Get's the array of completed upgrade actions
1161
 *
1162
 * @since  1.0
1163
 * @return array The array of completed upgrades
1164
 */
1165
function give_get_completed_upgrades() {
1166
	return (array) Give_Cache_Setting::get_option( 'give_completed_upgrades' );
1167
}
1168
1169
/**
1170
 * In 2.0 we updated table for log, payment and form.
1171
 *
1172
 * Note: internal purpose only.
1173
 *
1174
 * @since 2.0
1175
 * @global wpdb  $wpdb
1176
 *
1177
 * @param string $type Context for table
1178
 *
1179
 * @return null|array
1180
 */
1181
function __give_v20_bc_table_details( $type ) {
1182
	global $wpdb;
1183
	$table = array();
1184
1185
	// Bailout.
1186
	if ( empty( $type ) ) {
1187
		return null;
1188
	}
1189
1190
	switch ( $type ) {
1191
		case 'form':
1192
			$table['name']         = $wpdb->formmeta;
1193
			$table['column']['id'] = 'form_id';
1194
1195
			break;
1196
1197
		case 'payment':
1198
			$table['name']         = $wpdb->donationmeta;
1199
			$table['column']['id'] = Give()->payment_meta->get_meta_type() . '_id';
1200
	}
1201
1202
	// Backward compatibility.
1203
	if ( ! give_has_upgrade_completed( 'v20_move_metadata_into_new_table' ) ) {
1204
		$table['name']         = $wpdb->postmeta;
1205
		$table['column']['id'] = 'post_id';
1206
	}
1207
1208
	return $table;
1209
}
1210
1211
/**
1212
 * Remove the Give transaction pages from WP search results.
1213
 *
1214
 * @since 1.8.13
1215
 *
1216
 * @param WP_Query $query
1217
 */
1218
function give_remove_pages_from_search( $query ) {
1219
1220
	if ( ! $query->is_admin && $query->is_search && $query->is_main_query() ) {
1221
1222
		$transaction_failed = give_get_option( 'failure_page', 0 );
1223
		$success_page       = give_get_option( 'success_page', 0 );
1224
1225
		$args = apply_filters(
1226
			'give_remove_pages_from_search', array(
1227
				$transaction_failed,
1228
				$success_page,
1229
			), $query
1230
		);
1231
		$query->set( 'post__not_in', $args );
1232
	}
1233
}
1234
1235
add_action( 'pre_get_posts', 'give_remove_pages_from_search', 10, 1 );
1236
1237
/**
1238
 * Inserts a new key/value before a key in the array.
1239
 *
1240
 * @since 1.8.13
1241
 *
1242
 * @param string       $key       The key to insert before.
1243
 * @param array        $array     An array to insert in to.
1244
 * @param string       $new_key   The key to insert.
1245
 * @param array|string $new_value An value to insert.
1246
 *
1247
 * @return array The new array if the key exists, the passed array otherwise.
1248
 *
1249
 * @see   array_insert_before()
1250
 */
1251 View Code Duplication
function give_array_insert_before( $key, array &$array, $new_key, $new_value ) {
0 ignored issues
show
Duplication introduced by
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...
1252
	if ( array_key_exists( $key, $array ) ) {
1253
		$new = array();
1254
		foreach ( $array as $k => $value ) {
1255
			if ( $k === $key ) {
1256
				$new[ $new_key ] = $new_value;
1257
			}
1258
			$new[ $k ] = $value;
1259
		}
1260
1261
		return $new;
1262
	}
1263
1264
	return $array;
1265
}
1266
1267
/**
1268
 * Inserts a new key/value after a key in the array.
1269
 *
1270
 * @since 1.8.13
1271
 *
1272
 * @param string       $key       The key to insert after.
1273
 * @param array        $array     An array to insert in to.
1274
 * @param string       $new_key   The key to insert.
1275
 * @param array|string $new_value An value to insert.
1276
 *
1277
 * @return array The new array if the key exists, the passed array otherwise.
1278
 *
1279
 * @see   array_insert_before()
1280
 */
1281 View Code Duplication
function give_array_insert_after( $key, array &$array, $new_key, $new_value ) {
0 ignored issues
show
Duplication introduced by
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...
1282
	if ( array_key_exists( $key, $array ) ) {
1283
		$new = array();
1284
		foreach ( $array as $k => $value ) {
1285
			$new[ $k ] = $value;
1286
			if ( $k === $key ) {
1287
				$new[ $new_key ] = $new_value;
1288
			}
1289
		}
1290
1291
		return $new;
1292
	}
1293
1294
	return $array;
1295
}
1296
1297
/**
1298
 * Pluck a certain field out of each object in a list.
1299
 *
1300
 * This has the same functionality and prototype of
1301
 * array_column() (PHP 5.5) but also supports objects.
1302
 *
1303
 * @since 1.8.13
1304
 *
1305
 * @param array      $list      List of objects or arrays
1306
 * @param int|string $field     Field from the object to place instead of the entire object
1307
 * @param int|string $index_key Optional. Field from the object to use as keys for the new array.
1308
 *                              Default null.
1309
 *
1310
 * @return array Array of found values. If `$index_key` is set, an array of found values with keys
1311
 *               corresponding to `$index_key`. If `$index_key` is null, array keys from the original
1312
 *               `$list` will be preserved in the results.
1313
 */
1314
function give_list_pluck( $list, $field, $index_key = null ) {
1315
1316
	if ( ! $index_key ) {
1317
		/**
1318
		 * This is simple. Could at some point wrap array_column()
1319
		 * if we knew we had an array of arrays.
1320
		 */
1321
		foreach ( $list as $key => $value ) {
1322
			if ( is_object( $value ) ) {
1323
				if ( isset( $value->$field ) ) {
1324
					$list[ $key ] = $value->$field;
1325
				}
1326
			} else {
1327
				if ( isset( $value[ $field ] ) ) {
1328
					$list[ $key ] = $value[ $field ];
1329
				}
1330
			}
1331
		}
1332
1333
		return $list;
1334
	}
1335
1336
	/*
1337
	 * When index_key is not set for a particular item, push the value
1338
	 * to the end of the stack. This is how array_column() behaves.
1339
	 */
1340
	$newlist = array();
1341
	foreach ( $list as $value ) {
1342
		if ( is_object( $value ) ) {
1343
			if ( isset( $value->$index_key ) ) {
1344
				$newlist[ $value->$index_key ] = $value->$field;
1345
			} else {
1346
				$newlist[] = $value->$field;
1347
			}
1348
		} else {
1349
			if ( isset( $value[ $index_key ] ) ) {
1350
				$newlist[ $value[ $index_key ] ] = $value[ $field ];
1351
			} else {
1352
				$newlist[] = $value[ $field ];
1353
			}
1354
		}
1355
	}
1356
1357
	$list = $newlist;
1358
1359
	return $list;
1360
}
1361
1362
/**
1363
 * Add meta data field to a donor.
1364
 *
1365
 * @since 1.8.13
1366
 *
1367
 * @param int    $donor_id   Donor ID.
1368
 * @param string $meta_key   Metadata name.
1369
 * @param mixed  $meta_value Metadata value. Must be serializable if non-scalar.
1370
 * @param bool   $unique     Optional. Whether the same key should not be added.
1371
 *                           Default false.
1372
 *
1373
 * @return int|false Meta ID on success, false on failure.
1374
 */
1375
function add_donor_meta( $donor_id, $meta_key, $meta_value, $unique = false ) {
1376
	return add_metadata( 'give_customer', $donor_id, $meta_key, $meta_value, $unique );
1377
}
1378
1379
/**
1380
 * Remove metadata matching criteria from a Donor meta.
1381
 *
1382
 * You can match based on the key, or key and value. Removing based on key and
1383
 * value, will keep from removing duplicate metadata with the same key. It also
1384
 * allows removing all metadata matching key, if needed.
1385
 *
1386
 * @since 1.8.13
1387
 *
1388
 * @param int    $donor_id   Donor ID
1389
 * @param string $meta_key   Metadata name.
1390
 * @param mixed  $meta_value Optional. Metadata value.
1391
 *
1392
 * @return bool True on success, false on failure.
1393
 */
1394
function delete_donor_meta( $donor_id, $meta_key, $meta_value = '' ) {
1395
	return delete_metadata( 'give_customer', $donor_id, $meta_key, $meta_value );
1396
}
1397
1398
/**
1399
 * Retrieve donor meta field for a donor meta table.
1400
 *
1401
 * @since 1.8.13
1402
 *
1403
 * @param int    $donor_id Donor ID.
1404
 * @param string $key      Optional. The meta key to retrieve. By default, returns data for all keys.
1405
 * @param bool   $single   Whether to return a single value.
1406
 *
1407
 * @return mixed Will be an array if $single is false. Will be value of meta data field if $single
1408
 *  is true.
1409
 */
1410
function get_donor_meta( $donor_id, $key = '', $single = false ) {
1411
	return get_metadata( 'give_customer', $donor_id, $key, $single );
1412
}
1413
1414
/**
1415
 * Update customer meta field based on Donor ID.
1416
 *
1417
 * If the meta field for the donor does not exist, it will be added.
1418
 *
1419
 * @since 1.8.13
1420
 *
1421
 * @param int    $donor_id   Donor ID.
1422
 * @param string $meta_key   Metadata key.
1423
 * @param mixed  $meta_value Metadata value.
1424
 * @param mixed  $prev_value Optional. Previous value to check before removing.
1425
 *
1426
 * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.
1427
 */
1428
function update_donor_meta( $donor_id, $meta_key, $meta_value, $prev_value = '' ) {
1429
	return update_metadata( 'give_customer', $donor_id, $meta_key, $meta_value, $prev_value );
1430
}
1431
1432
1433
/**
1434
 * Give recalculate income and donation of the donation from ID
1435
 *
1436
 * @since 1.8.13
1437
 *
1438
 * @param int $form_id Form id of which recalculation needs to be done.
1439
 *
1440
 * @return void
1441
 */
1442
function give_recount_form_income_donation( $form_id = 0 ) {
1443
	// Check if form id is not empty.
1444
	if ( ! empty( $form_id ) ) {
1445
		/**
1446
		 * Filter to modify payment status.
1447
		 *
1448
		 * @since 1.8.13
1449
		 */
1450
		$accepted_statuses = apply_filters( 'give_recount_accepted_statuses', array( 'publish' ) );
1451
1452
		/**
1453
		 * Filter to modify args of payment query before recalculating the form total
1454
		 *
1455
		 * @since 1.8.13
1456
		 */
1457
		$args = apply_filters(
1458
			'give_recount_form_stats_args', array(
1459
				'give_forms' => $form_id,
1460
				'status'     => $accepted_statuses,
1461
				'number'     => - 1,
1462
				'fields'     => 'ids',
1463
			)
1464
		);
1465
1466
		$totals = array(
1467
			'sales'    => 0,
1468
			'earnings' => 0,
1469
		);
1470
1471
		$payments = new Give_Payments_Query( $args );
1472
		$payments = $payments->get_payments();
1473
1474
		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...
1475
			foreach ( $payments as $payment ) {
1476
				// Ensure acceptable status only.
1477
				if ( ! in_array( $payment->post_status, $accepted_statuses ) ) {
1478
					continue;
1479
				}
1480
1481
				// Ensure only payments for this form are counted.
1482
				if ( $payment->form_id != $form_id ) {
1483
					continue;
1484
				}
1485
1486
				$totals['sales'] ++;
1487
				$totals['earnings'] += $payment->total;
1488
1489
			}
1490
		}
1491
		give_update_meta( $form_id, '_give_form_sales', $totals['sales'] );
1492
		give_update_meta( $form_id, '_give_form_earnings', give_sanitize_amount_for_db( $totals['earnings'] ) );
1493
	}// End if().
1494
}
1495
1496
1497
/**
1498
 * Get attribute string
1499
 *
1500
 * @since 1.8.17
1501
 *
1502
 * @param array $attributes
1503
 * @param array $default_attributes
1504
 *
1505
 * @return string
1506
 */
1507
function give_get_attribute_str( $attributes, $default_attributes = array() ) {
1508
	$attribute_str = '';
1509
1510
	if ( isset( $attributes['attributes'] ) ) {
1511
		$attributes = $attributes['attributes'];
1512
	}
1513
1514
	if ( ! empty( $default_attributes ) ) {
1515
		$attributes = wp_parse_args( $attributes, $default_attributes );
1516
	}
1517
1518
	if ( empty( $attributes ) ) {
1519
		return $attribute_str;
1520
	}
1521
1522
	foreach ( $attributes as $tag => $value ) {
1523
		if ( 'value' == $tag ) {
1524
			$value = esc_attr( $value );
1525
		}
1526
1527
		$attribute_str .= " {$tag}=\"{$value}\"";
1528
	}
1529
1530
	return trim( $attribute_str );
1531
}
1532
1533
/**
1534
 * Get the upload dir path
1535
 *
1536
 * @since 1.8.17
1537
 *
1538
 * @return string $wp_upload_dir;
1539
 */
1540
function give_get_wp_upload_dir() {
1541
	$wp_upload_dir = wp_upload_dir();
1542
1543
	return ( ! empty( $wp_upload_dir['path'] ) ? $wp_upload_dir['path'] : false );
1544
}
1545
1546
/**
1547
 * Get the data from uploaded JSON file
1548
 *
1549
 * @since 1.8.17
1550
 *
1551
 * @param string $file_name filename of the json file that is being uploaded
1552
 *
1553
 * @return string|bool $file_contents File content
1554
 */
1555
function give_get_core_settings_json( $file_name ) {
1556
	$upload_dir = give_get_wp_upload_dir();
1557
	$file_path  = $upload_dir . '/' . $file_name;
1558
1559
	if ( is_wp_error( $file_path ) || empty( $file_path ) ) {
1560
		Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide a valid JSON file.', 'give' ) );
1561
	}
1562
1563
	$file_contents = file_get_contents( $file_path );
0 ignored issues
show
introduced by
file_get_contents is highly discouraged, please use wpcom_vip_file_get_contents() instead.
Loading history...
1564
1565
	return $file_contents;
1566
}
1567
1568
/**
1569
 * Get number of donation to show when user is not login.
1570
 *
1571
 * @since 1.8.17
1572
 *
1573
 * @return int $country The two letter country code for the site's base country
1574
 */
1575
function give_get_limit_display_donations() {
1576
	return give_get_option( 'limit_display_donations', 1 );
1577
}
1578
1579
/**
1580
 * Add footer to the table when donor is view the donation history page with out login
1581
 *
1582
 * @since 1.8.17
1583
 */
1584
function give_donation_history_table_end() {
1585
	$email = Give()->session->get( 'give_email' );
1586
	?>
1587
	<tfoot>
1588
	<tr>
1589
		<td colspan="9999">
1590
			<div class="give-security-wrap">
1591
				<div class="give-security-column give-security-description-wrap">
1592
					<?php
1593
					echo sprintf( __( 'For security reasons, please confirm your email address (%s) to view your complete donation history.', 'give' ), $email );
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'sprintf'
Loading history...
1594
					?>
1595
				</div>
1596
				<div class="give-security-column give-security-button-wrap">
1597
					<a href="#" data-email="<?php echo $email; ?>" id="give-confirm-email-btn"
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$email'
Loading history...
1598
					   class="give-confirm-email-btn give-btn">
1599
						<?php _e( 'Confirm Email', 'give' ); ?>
1600
					</a>
1601
					<span><?php _e( 'Email Sent!', 'give' ); ?></span>
1602
				</div>
1603
			</div>
1604
		</td>
1605
	</tr>
1606
	</tfoot>
1607
	<?php
1608
}
1609
1610
1611
/**
1612
 * Wrapper for _doing_it_wrong.
1613
 *
1614
 * @since  1.8.18
1615
 *
1616
 * @param  string $function
1617
 * @param  string $message
1618
 * @param  string $version
1619
 *
1620
 * @return void
1621
 */
1622
function give_doing_it_wrong( $function, $message, $version ) {
1623
	$message .= "\nBacktrace:" . wp_debug_backtrace_summary();
1624
1625
	_doing_it_wrong( $function, $message, $version );
1626
}
1627
1628
1629
/**
1630
 * Remove limit from running php script complete.
1631
 *
1632
 * @since 1.8.18
1633
 */
1634
function give_ignore_user_abort() {
1635
	ignore_user_abort( true );
1636
1637
	if ( ! give_is_func_disabled( 'set_time_limit' ) && ! ini_get( 'safe_mode' ) ) {
1638
		set_time_limit( 0 );
1639
	}
1640
}
1641
1642
/**
1643
 * Get post type count.
1644
 *
1645
 * @since 2.0.2
1646
 *
1647
 * @param string $post_type
1648
 * @param array  $args
1649
 *
1650
 * @return int
1651
 */
1652
function give_get_total_post_type_count( $post_type = '', $args = array() ) {
0 ignored issues
show
Unused Code introduced by
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...
1653
	global $wpdb;
1654
	$where = '';
1655
1656
	if ( ! $post_type ) {
1657
		return 0;
1658
	}
1659
1660
	// Bulit where query
1661
	if ( ! empty( $post_type ) ) {
1662
		$where .= ' WHERE';
1663
1664
		if ( is_array( $post_type ) ) {
1665
			$where .= " post_type='" . implode( "' OR post_type='", $post_type ) . "'";
1666
		} else {
1667
			$where .= " post_type='{$post_type}'";
1668
		}
1669
	}
1670
1671
	$result = $wpdb->get_var( "SELECT count(ID) FROM {$wpdb->posts}{$where}" );
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
1672
1673
	return absint( $result );
1674
}
1675
1676
/**
1677
 * Define a constant if it is not already defined.
1678
 *
1679
 * @since  2.0.5
1680
 *
1681
 * @param string $name  Constant name.
1682
 * @param string $value Value.
1683
 *
1684
 * @credit WooCommerce
1685
 */
1686
function give_maybe_define_constant( $name, $value ) {
1687
	if ( ! defined( $name ) ) {
1688
		define( $name, $value );
1689
	}
1690
}
1691
1692
/**
1693
 * Decode time short tag in string
1694
 *
1695
 * @since 2.1.0
1696
 *
1697
 * @param string $string
1698
 * @param int    $timestamp
1699
 *
1700
 * @return string
1701
 */
1702
function give_time_do_tags( $string, $timestamp = 0 ) {
1703
	$current_time = ! empty( $timestamp ) ? $timestamp : current_time( 'timestamp' );
1704
1705
	$formatted_string = str_replace(
1706
		array(
1707
			'{D}',
1708
			'{DD}',
1709
			'{M}',
1710
			'{MM}',
1711
			'{YY}',
1712
			'{YYYY}',
1713
			'{H}',
1714
			'{HH}',
1715
			'{N}',
1716
			'{S}',
1717
		), array(
1718
			date( 'j', $current_time ),
1719
			date( 'd', $current_time ),
1720
			date( 'n', $current_time ),
1721
			date( 'm', $current_time ),
1722
			date( 'Y', $current_time ),
1723
			date( 'Y', $current_time ),
1724
			date( 'G', $current_time ),
1725
			date( 'H', $current_time ),
1726
			date( 's', $current_time ),
1727
		), $string
1728
	);
1729
1730
	/**
1731
	 * Filter the parsed string.
1732
	 *
1733
	 * @since 2.1.0
1734
	 */
1735
	return apply_filters( 'give_time_do_tags', $formatted_string, $string, $timestamp );
1736
}
1737
1738
1739
/**
1740
 * Check if Company field enabled or not for form or globally.
1741
 *
1742
 * @since 2.1
1743
 *
1744
 * @param $form_id
1745
 *
1746
 * @return bool
1747
 */
1748
function give_is_company_field_enabled( $form_id ) {
1749
	$form_setting_val   = give_get_meta( $form_id, '_give_company_field', true );
1750
	$global_setting_val = give_get_option( 'company_field' );
1751
1752
	if ( ! empty( $form_setting_val ) ) {
1753
		if ( give_is_setting_enabled( $form_setting_val, array( 'required', 'optional' ) ) ) {
0 ignored issues
show
Documentation introduced by
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...
1754
			return true;
1755
		} elseif ( 'global' === $form_setting_val && give_is_setting_enabled(
1756
			$global_setting_val, array(
0 ignored issues
show
Documentation introduced by
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...
1757
				'required',
1758
				'optional',
1759
			)
1760
		) ) {
1761
			return true;
1762
		} else {
1763
			return false;
1764
		}
1765
	} elseif ( give_is_setting_enabled( $global_setting_val, array( 'required', 'optional' ) ) ) {
0 ignored issues
show
Documentation introduced by
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...
1766
		return true;
1767
1768
	} else {
1769
		return false;
1770
	}
1771
}
1772
1773
/**
1774
 * Check if anonymous donation field enabled or not for form or globally.
1775
 *
1776
 * @since 2.1
1777
 *
1778
 * @param $form_id
1779
 *
1780
 * @return bool
1781
 */
1782 View Code Duplication
function give_is_anonymous_donation_field_enabled( $form_id ) {
0 ignored issues
show
Duplication introduced by
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...
1783
	$form_setting_val   = give_get_meta( $form_id, '_give_anonymous_donation', true, 'global' );
0 ignored issues
show
Documentation introduced by
'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...
1784
	$global_setting_val = give_get_option( 'anonymous_donation', 'disabled' );
1785
1786
	if ( ! empty( $form_setting_val ) ) {
1787
		if ( give_is_setting_enabled( $form_setting_val ) ) {
1788
			return true;
1789
		} elseif ( 'global' === $form_setting_val && give_is_setting_enabled( $global_setting_val ) ) {
1790
			return true;
1791
		} else {
1792
			return false;
1793
		}
1794
	} elseif ( give_is_setting_enabled( $global_setting_val ) ) {
1795
		return true;
1796
	}
1797
1798
	return false;
1799
}
1800
1801
/**
1802
 * Check if donor comment field enabled or not for form or globally.
1803
 *
1804
 * @since 2.1
1805
 *
1806
 * @param $form_id
1807
 *
1808
 * @return bool
1809
 */
1810 View Code Duplication
function give_is_donor_comment_field_enabled( $form_id ) {
0 ignored issues
show
Duplication introduced by
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...
1811
	$form_setting_val   = give_get_meta( $form_id, '_give_donor_comment', true, 'global' );
0 ignored issues
show
Documentation introduced by
'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...
1812
	$global_setting_val = give_get_option( 'donor_comment', 'disabled' );
1813
1814
	if ( ! empty( $form_setting_val ) ) {
1815
		if ( give_is_setting_enabled( $form_setting_val ) ) {
1816
			return true;
1817
		} elseif ( 'global' === $form_setting_val && give_is_setting_enabled( $global_setting_val ) ) {
1818
			return true;
1819
		} else {
1820
			return false;
1821
		}
1822
	} elseif ( give_is_setting_enabled( $global_setting_val ) ) {
1823
		return true;
1824
	}
1825
1826
	return false;
1827
1828
}
1829
1830
/**
1831
 * Get add-on user meta value information
1832
 * Note: only for internal use.
1833
 *
1834
 * @since 2.1.0
1835
 *
1836
 * @param string $license_id
1837
 *
1838
 * @return array
1839
 */
1840
function __give_get_active_license_info( $license_id ) {
1841
	global $wpdb;
1842
	$option_name = "{$license_id}_license_active";
1843
	$data        = array();
1844
1845
	if ( ! isset( $GLOBALS['give_active_licenses_info'] ) ) {
1846
		$GLOBALS['give_active_licenses_info'] = array();
1847
1848
		$licenses_info = $wpdb->get_results(
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
1849
			"
1850
			SELECT option_name, option_value
1851
			FROM {$wpdb->options}
1852
			WHERE option_name LIKE '%_license_active%'
1853
			AND option_name LIKE '%give_%'
1854
			",
1855
			ARRAY_A
1856
		);
1857
1858 View Code Duplication
		if ( ! empty( $licenses_info ) ) {
0 ignored issues
show
Duplication introduced by
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...
1859
			$GLOBALS['give_active_licenses_info'] = array_combine(
1860
				wp_list_pluck( $licenses_info, 'option_name' ),
1861
				wp_list_pluck( $licenses_info, 'option_value' )
1862
			);
1863
		}
1864
	}
1865
1866 View Code Duplication
	if ( in_array( $option_name, array_keys( $GLOBALS['give_active_licenses_info'] ) ) ) {
0 ignored issues
show
Duplication introduced by
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...
1867
		$data = maybe_unserialize( $GLOBALS['give_active_licenses_info'][ $option_name ] );
1868
	}
1869
1870
	return $data;
1871
}
1872
1873
/**
1874
 * Get add-on user meta value information
1875
 * Note: only for internal use.
1876
 *
1877
 * @since 2.1.0
1878
 *
1879
 * @param string $banner_addon_name Give add-on name.
1880
 *
1881
 * @return array
1882
 */
1883
function __give_get_active_by_user_meta( $banner_addon_name ) {
1884
	global $wpdb;
1885
1886
	// Get the option key.
1887
	$option_name = Give_Addon_Activation_Banner::get_banner_user_meta_key( $banner_addon_name );
1888
	$data        = array();
1889
1890
	if (
1891
		! isset( $GLOBALS['give_addon_activated_by_user'][ $banner_addon_name ] )
1892
		|| empty( $GLOBALS['give_addon_activated_by_user'][ $banner_addon_name ] )
1893
	) {
1894
		$GLOBALS['give_addon_activated_by_user'][ $banner_addon_name ] = array();
1895
1896
		// Get the meta of activation banner by user.
1897
		$activation_banners = $wpdb->get_results(
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
1898
			"
1899
					SELECT option_name, option_value
1900
					FROM {$wpdb->options}
1901
					WHERE option_name LIKE '%_active_by_user%'
1902
					AND option_name LIKE '%give_addon%'
1903
					",
1904
			ARRAY_A
1905
		);
1906
1907 View Code Duplication
		if ( ! empty( $activation_banners ) ) {
0 ignored issues
show
Duplication introduced by
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...
1908
			$GLOBALS['give_addon_activated_by_user'] = array_combine(
1909
				wp_list_pluck( $activation_banners, 'option_name' ),
1910
				wp_list_pluck( $activation_banners, 'option_value' )
1911
			);
1912
		}
1913
	}
1914
1915 View Code Duplication
	if ( in_array( $option_name, array_keys( $GLOBALS['give_addon_activated_by_user'] ) ) ) {
0 ignored issues
show
Duplication introduced by
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...
1916
		$data = maybe_unserialize( $GLOBALS['give_addon_activated_by_user'][ $option_name ] );
1917
	}
1918
1919
	return $data;
1920
}
1921
1922
/**
1923
 * Get time interval for which nonce is valid
1924
 *
1925
 * @since 2.1.3
1926
 *
1927
 * @return int
1928
 */
1929
function give_get_nonce_life() {
1930
	/**
1931
	 * Filters the lifespan of nonces in seconds.
1932
	 *
1933
	 * @see wp-inlucdes/pluggable.php:wp_nonce_tick
1934
	 */
1935
	return (int) apply_filters( 'nonce_life', DAY_IN_SECONDS );
1936
}
1937
1938
/**
1939
 * Get nonce field without id
1940
 *
1941
 * @since 2.1.3
1942
 *
1943
 * @param  string $action
1944
 * @param  string $name
1945
 * @param bool   $referer
1946
 *
1947
 * @return string
1948
 */
1949
function give_get_nonce_field( $action, $name, $referer = false ) {
1950
	return str_replace(
1951
		"id=\"{$name}\"",
1952
		'',
1953
		wp_nonce_field( $action, $name, $referer, false )
1954
	);
1955
}
1956
1957
/**
1958
 * Display/Return a formatted goal for a donation form
1959
 *
1960
 * @param int|Give_Donate_Form $form Form ID or Form Object.
1961
 *
1962
 * @since 2.1
1963
 *
1964
 * @return array
1965
 */
1966
function give_goal_progress_stats( $form ) {
1967
1968
	if ( ! $form instanceof Give_Donate_Form ) {
1969
		$form = new Give_Donate_Form( $form );
1970
	}
1971
1972
	$donors = '';
0 ignored issues
show
Unused Code introduced by
$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...
1973
1974
	$goal_format = give_get_form_goal_format( $form->ID );
1975
1976
	/**
1977
	 * Filter the form.
1978
	 *
1979
	 * @since 1.8.8
1980
	 */
1981
	$total_goal = apply_filters( 'give_goal_amount_target_output', round( give_maybe_sanitize_amount( $form->goal ), 2 ), $form->ID, $form );
1982
1983
	switch ( $goal_format ) {
1984
		case 'donation':
1985
			/**
1986
			 * Filter the form donations.
1987
			 *
1988
			 * @since 2.1
1989
			 */
1990
			$actual = $donations = apply_filters( 'give_goal_donations_raised_output', $form->sales, $form->ID, $form );
0 ignored issues
show
Unused Code introduced by
$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...
1991
			break;
1992
		case 'donors':
1993
			/**
1994
			 * Filter to modify total number if donor for the donation form.
1995
			 *
1996
			 * @since 2.1.3
1997
			 *
1998
			 * @param int              $donors  Total number of donors that donated to the form.
1999
			 * @param int              $form_id Donation Form ID.
2000
			 * @param Give_Donate_Form $form    instances of Give_Donate_Form.
2001
			 *
2002
			 * @return int $donors Total number of donors that donated to the form.
2003
			 */
2004
			$actual = $donors = apply_filters( 'give_goal_donors_target_output', give_get_form_donor_count( $form->ID ), $form->ID, $form );
0 ignored issues
show
Unused Code introduced by
$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...
2005
			break;
2006
		default:
2007
			/**
2008
			 * Filter the form income.
2009
			 *
2010
			 * @since 1.8.8
2011
			 */
2012
			$actual = $income = apply_filters( 'give_goal_amount_raised_output', $form->earnings, $form->ID, $form );
0 ignored issues
show
Unused Code introduced by
$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...
2013
			break;
2014
	}
2015
2016
	$progress = $total_goal ? round( ( $actual / $total_goal ) * 100, 2 ) : 0;
2017
2018
	$stats_array = array(
2019
		'raw_actual' => $actual,
2020
		'raw_goal'   => $total_goal,
2021
	);
2022
2023
	/**
2024
	 * Filter the goal progress output
2025
	 *
2026
	 * @since 1.8.8
2027
	 */
2028
	$progress = apply_filters( 'give_goal_amount_funded_percentage_output', $progress, $form->ID, $form );
2029
2030
	// Define Actual Goal based on the goal format.
2031 View Code Duplication
	if ( 'percentage' === $goal_format ) {
0 ignored issues
show
Duplication introduced by
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...
2032
		$actual = "{$actual}%";
2033
	} elseif ( 'amount' === $goal_format ) {
2034
		$actual = give_currency_filter( give_format_amount( $actual ) );
2035
	}
2036
2037
	// Define Total Goal based on the goal format.
2038 View Code Duplication
	if ( 'percentage' === $goal_format ) {
0 ignored issues
show
Duplication introduced by
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...
2039
		$total_goal = '';
2040
	} elseif ( 'amount' === $goal_format ) {
2041
		$total_goal = give_currency_filter( give_format_amount( $total_goal ) );
2042
	}
2043
2044
	$stats_array = array_merge(
2045
		array(
2046
			'progress' => $progress,
2047
			'actual'   => $actual,
2048
			'goal'     => $total_goal,
2049
			'format'   => $goal_format,
2050
		),
2051
		$stats_array
2052
	);
2053
2054
	/**
2055
	 * Filter the goal stats
2056
	 *
2057
	 * @since 2.1
2058
	 */
2059
	return apply_filters( 'give_goal_progress_stats', $stats_array );
2060
}
2061
2062
/**
2063
 * Get the admin messages key to show the notices.
2064
 *
2065
 * @since 2.1.4
2066
 *
2067
 * @return array $message admin message key.
2068
 */
2069
function give_get_admin_messages_key() {
2070
	$messages = empty( $_GET['give-messages'] ) ? array() : give_clean( $_GET['give-messages'] );
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
2071
2072
	// backward compatibility.
2073
	if ( ! empty( $_GET['give-message'] ) ) {
2074
		$messages[] = give_clean( $_GET['give-message'] );
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
2075
	}
2076
2077
	/**
2078
	 * Filter to modify the admin messages key.
2079
	 *
2080
	 * @since 2.1.4
2081
	 *
2082
	 * @param array $message admin message key.
2083
	 *
2084
	 * @return array $message admin message key.
2085
	 */
2086
	return (array) apply_filters( 'give_get_admin_messages_key', $messages );
2087
}
2088
2089
/**
2090
 * Get User Agent String.
2091
 *
2092
 * @since 2.1.4
2093
 *
2094
 * @return array|string
2095
 */
2096
function give_get_user_agent() {
2097
2098
	// Get User Agent.
2099
	$user_agent = ! empty( $_SERVER['HTTP_USER_AGENT'] ) ? give_clean( $_SERVER['HTTP_USER_AGENT'] ) : ''; // WPCS: input var ok.
0 ignored issues
show
introduced by
Due to using Batcache, server side based client related logic will not work, use JS instead.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
2100
2101
	return $user_agent;
2102
}
2103
2104
/**
2105
 * Set a cookie - wrapper for setcookie using WP constants.
2106
 *
2107
 * @since 2.2.0
2108
 *
2109
 * @param  string  $name   Name of the cookie being set.
2110
 * @param  string  $value  Value of the cookie.
2111
 * @param  integer $expire Expiry of the cookie.
2112
 * @param  bool    $secure Whether the cookie should be served only over https.
2113
 */
2114
function give_setcookie( $name, $value, $expire = 0, $secure = false ) {
2115
	if ( ! headers_sent() ) {
2116
		setcookie(
0 ignored issues
show
introduced by
Due to using Batcache, server side based client related logic will not work, use JS instead.
Loading history...
2117
			$name, $value, $expire, COOKIEPATH ? COOKIEPATH : '/', COOKIE_DOMAIN, $secure,
2118
			apply_filters( 'give_cookie_httponly', false, $name, $value, $expire, $secure )
2119
		);
2120
	}
2121
}
2122
2123
/**
2124
 * Get formatted billing address.
2125
 *
2126
 * @since 2.2.0
2127
 *
2128
 * @param array $address
2129
 *
2130
 * @return string Formatted address.
2131
 */
2132
function give_get_formatted_address( $address = array() ) {
2133
	$formatted_address = '';
2134
2135
	/**
2136
	 * Address format.
2137
	 *
2138
	 * @since 2.2.0
2139
	 */
2140
	$address_format = apply_filters( 'give_address_format_template', "{street_address}\n{city}, {state} {postal_code}\n{country}" );
2141
	preg_match_all( '/{([A-z0-9\-\_\ ]+)}/s', $address_format, $matches );
2142
2143
	if ( ! empty( $matches ) && ! empty( $address ) ) {
2144
		$address_values = array();
2145
2146
		foreach ( $matches[1] as $address_tag ) {
2147
			$address_values[ $address_tag ] = '';
2148
2149
			if ( isset( $address[ $address_tag ] ) ) {
2150
				$address_values[ $address_tag ] = $address[ $address_tag ];
2151
			}
2152
		}
2153
2154
		$formatted_address = str_ireplace( $matches[0], $address_values, $address_format );
2155
	}
2156
2157
	/**
2158
	 * Give get formatted address.
2159
	 *
2160
	 * @since 2.2.0
2161
	 *
2162
	 * @param string $formatted_address Formatted address.
2163
	 * @param string $address_format    Format of the address.
2164
	 */
2165
	$formatted_address = apply_filters( 'give_get_formatted_address', $formatted_address, $address_format, $address );
2166
2167
	return $formatted_address;
2168
}
2169
2170
/**
2171
 * Get safe url for assets
2172
 * Note: this function will return url without http protocol
2173
 *
2174
 * @since 2.2.0
2175
 *
2176
 * @param string $url URL
2177
 *
2178
 * @return string
2179
 */
2180
function give_get_safe_asset_url( $url ) {
2181
2182
	// Bailout, if empty URL passed.
2183
	if ( empty( $url ) ) {
2184
		return $url;
2185
	}
2186
2187
	$schema        = parse_url( $url, PHP_URL_SCHEME );
2188
	$schema_length = strlen( $schema ) + 1;
2189
	$url           = substr( $url, $schema_length );
2190
2191
	/**
2192
	 * Fire the filter
2193
	 *
2194
	 * @since 2.2.0
2195
	 */
2196
	return apply_filters( 'give_get_safe_asset_url', $url );
2197
}
2198
2199
/**
2200
 * Give get formatted date.
2201
 *
2202
 * @since 2.3.0
2203
 *
2204
 * @param string $date           Date.
2205
 * @param string $format         Date Format.
2206
 * @param string $current_format Current date Format.
2207
 *
2208
 * @return string
2209
 */
2210
function give_get_formatted_date( $date, $format = 'Y-m-d', $current_format = '' ) {
2211
	$current_format = empty( $current_format ) ? give_date_format() : $current_format;
2212
	$date_obj       = DateTime::createFromFormat( $current_format, $date );
2213
2214
	$formatted_date = $date_obj instanceof DateTime ? $date_obj->format( $format ) : '';
2215
2216
	/**
2217
	 * Give get formatted date.
2218
	 *
2219
	 * @since 2.3.0
2220
	 *
2221
	 * @param string $formatted_date Formatted date.
2222
	 * @param array
2223
	 */
2224
	return apply_filters( 'give_get_formatted_date', $formatted_date, array( $date, $format, $current_format ) );
2225
}
2226
2227
/**
2228
 * This function will be used to fetch the donation receipt link.
2229
 *
2230
 * @param int $donation_id Donation ID.
2231
 *
2232
 * @since 2.3.1
2233
 *
2234
 * @return string
2235
 */
2236
function give_get_receipt_link( $donation_id ) {
2237
2238
	return sprintf(
2239
		'<a href="%1$s">%2$s</a>',
2240
		esc_url( give_get_receipt_url( $donation_id ) ),
2241
		esc_html__( 'View the receipt in your browser &raquo;', 'give' )
2242
	);
2243
2244
}
2245
2246
/**
2247
 * Get receipt_url
2248
 *
2249
 * @since 2.0
2250
 *
2251
 * @param int $donation_id Donation ID.
2252
 *
2253
 * @return string
2254
 */
2255
function give_get_receipt_url( $donation_id ) {
2256
2257
	$receipt_url = esc_url(
2258
		add_query_arg(
2259
			array(
2260
				'donation_id' => $donation_id,
2261
			), give_get_history_page_uri()
2262
		)
2263
	);
2264
2265
	return $receipt_url;
2266
}
2267
2268
/**
2269
 * Get "View in browser" Receipt Link for email.
2270
 *
2271
 * @param int $donation_id Donation ID.
2272
 *
2273
 * @since 2.4.1
2274
 *
2275
 * @return string
2276
 */
2277
function give_get_view_receipt_link( $donation_id ) {
2278
2279
	return sprintf(
2280
		'<a href="%1$s">%2$s</a>',
2281
		esc_url( give_get_view_receipt_url( $donation_id ) ),
2282
		esc_html__( 'View the receipt in your browser &raquo;', 'give' )
2283
	);
2284
2285
}
2286
2287
/**
2288
 * Get "View in browser" Receipt URL for email.
2289
 *
2290
 * @since 2.4.1
2291
 *
2292
 * @param int $donation_id Donation ID.
2293
 *
2294
 * @return string
2295
 */
2296
function give_get_view_receipt_url( $donation_id ) {
2297
2298
	$receipt_url = esc_url(
2299
		add_query_arg(
2300
			array(
2301
				'action'     => 'view_in_browser',
2302
				'_give_hash' => give_get_payment_key( $donation_id ),
2303
			), give_get_history_page_uri()
2304
		)
2305
	);
2306
2307
	return $receipt_url;
2308
}
2309
2310
/**
2311
 * This function is used to display donation receipt content based on the parameters.
2312
 *
2313
 * @param $args
2314
 *
2315
 * @since 2.4.1
2316
 *
2317
 * @return bool|mixed
2318
 */
2319
function give_display_donation_receipt( $args ) {
2320
2321
	global $give_receipt_args;
2322
2323
	$give_receipt_args = $args;
2324
2325
	ob_start();
2326
2327
	$get_data     = give_clean( filter_input_array( INPUT_GET ) );
2328
	$donation_id  = ! empty( $get_data['donation_id'] ) ? $get_data['donation_id'] : false;
2329
	$receipt_type = ! empty( $get_data['receipt_type'] ) ? $get_data['receipt_type'] : false;
2330
2331
	$give_receipt_args['id'] = $donation_id;
2332
2333
	if ( 'view_in_browser' !== $receipt_type ) {
2334
2335
		$email_access    = give_get_option( 'email_access' );
2336
		$is_email_access = give_is_setting_enabled( $email_access ) && ! Give()->email_access->token_exists;
2337
2338
		// No donation id found & Email Access is Turned on.
2339
		if ( ! $donation_id ) {
2340
2341
			if ( $is_email_access ) {
2342
				give_get_template_part( 'email-login-form' );
2343
			} else {
2344
				echo Give()->notices->print_frontend_notice( $args['error'], false, 'error' );
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'Give'
Loading history...
2345
			}
2346
2347
			return ob_get_clean();
2348
		}
2349
2350
		// Donation id provided, but user is logged out. Offer them the ability to login and view the receipt.
2351
		if ( ! ( $user_can_view = give_can_view_receipt( $donation_id ) ) ) {
2352
2353
			if ( true === Give()->session->get( 'donor_donation_mismatch' ) ) {
2354
2355
				/**
2356
				 * This filter will be used to modify the donor mismatch text for front end error notice.
2357
				 *
2358
				 * @since 2.3.1
2359
				 */
2360
				$donor_mismatch_text = apply_filters( 'give_receipt_donor_mismatch_notice_text', __( 'You are trying to access invalid donation receipt. Please try again.', 'give' ) );
2361
2362
				echo Give()->notices->print_frontend_notice(
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'Give'
Loading history...
2363
					$donor_mismatch_text,
2364
					false,
2365
					'error'
2366
				);
2367
2368
			} elseif ( $is_email_access ) {
2369
2370
				give_get_template_part( 'email-login-form' );
2371
2372
			} else {
2373
2374
				global $give_login_redirect;
2375
2376
				$give_login_redirect = give_get_current_page_url();
2377
2378
				Give()->notices->print_frontend_notice(
2379
					apply_filters(
2380
						'give_must_be_logged_in_error_message',
2381
						__( 'You must be logged in to view this donation receipt.', 'give' )
2382
					)
2383
				);
2384
2385
				give_get_template_part( 'shortcode', 'login' );
2386
			}
2387
2388
			return ob_get_clean();
2389
		}
2390
2391
		/**
2392
		 * Check if the user has permission to view the receipt.
2393
		 *
2394
		 * If user is logged in, user ID is compared to user ID of ID stored in payment meta
2395
		 * or if user is logged out and donation was made as a guest, the donation session is checked for
2396
		 * or if user is logged in and the user can view sensitive shop data.
2397
		 */
2398
		if ( ! apply_filters( 'give_user_can_view_receipt', $user_can_view, $args ) ) {
2399
			return Give()->notices->print_frontend_notice( $args['error'], false, 'error' );
2400
		}
2401
	}
2402
2403
	give_get_template_part( 'shortcode', 'receipt' );
2404
2405
	return ob_get_clean();
2406
}
2407