Test Failed
Push — master ( 76928d...4654fc )
by Devin
09:23
created

misc-functions.php ➔ give_get_meta()   B

Complexity

Conditions 7
Paths 8

Size

Total Lines 31

Duplication

Lines 16
Ratio 51.61 %

Importance

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