Test Failed
Push — issues/2296 ( 5e68bb )
by Ravinder
04:16
created

misc-functions.php ➔ give_get_attribute_str()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 3
nop 1
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Misc Functions
4
 *
5
 * @package     Give
6
 * @subpackage  Functions
7
 * @copyright   Copyright (c) 2016, WordImpress
8
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
9
 * @since       1.0
10
 */
11
12
// Exit if accessed directly.
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * 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 set currency
34
 *
35
 * @since 1.0
36
 * @since 1.8.15 Upgrade function to handle dynamic currency
37
 *
38
 * @param int          $donation_or_form_id Donation or Form ID
39
 * @param array|object $args                Additional data
40
 *
41
 * @return string The currency code
42
 */
43
function give_get_currency( $donation_or_form_id = null, $args = array() ) {
44
45
	// Get currency from donation
46
	if ( is_numeric( $donation_or_form_id ) && 'give_payment' === get_post_type( $donation_or_form_id ) ) {
47
		$donation_meta = give_get_meta( $donation_or_form_id, '_give_payment_meta', true );
48
49
		if ( ! empty( $donation_meta['currency'] ) ) {
50
			$currency = $donation_meta['currency'];
51
		} else {
52
			$currency = give_get_option( 'currency', 'USD' );
53
		}
54
	} else {
55
		$currency = give_get_option( 'currency', 'USD' );
56
	}
57
58
	/**
59
	 * Filter the currency on basis of donation or form id or addtional data.
60
	 *
61
	 * @since 1.0
62
	 */
63
	return apply_filters( 'give_currency', $currency, $donation_or_form_id, $args );
64
}
65
66
/**
67
 * Get the set currency position
68
 *
69
 * @since 1.3.6
70
 *
71
 * @return string The currency code
72
 */
73
function give_get_currency_position() {
74
75
	$currency_pos = give_get_option( 'currency_position', 'before' );
76
77
	return apply_filters( 'give_currency_position', $currency_pos );
78
}
79
80
81
/**
82
 * Get Currencies
83
 *
84
 * @since 1.0
85
 *
86
 * @param string $info Specify currency info
87
 *
88
 * @return array $currencies A list of the available currencies
89
 */
90
function give_get_currencies( $info = 'admin_label' ) {
91
	$currencies = array(
92
		'USD'  => array(
93
			'admin_label' => __( 'US Dollars ($)', 'give' ),
94
			'symbol'      => '&#36;',
95
			'setting'     => array(
96
				'currency_position'   => 'before',
97
				'thousands_separator' => ',',
98
				'decimal_separator'   => '.',
99
				'number_decimals'     => 2,
100
			),
101
		),
102
		'EUR'  => array(
103
			'admin_label' => __( 'Euros (€)', 'give' ),
104
			'symbol'      => '&euro;',
105
			'setting'     => array(
106
				'currency_position'   => 'before',
107
				'thousands_separator' => '.',
108
				'decimal_separator'   => ',',
109
				'number_decimals'     => 2,
110
			),
111
		),
112
		'GBP'  => array(
113
			'admin_label' => __( 'Pounds Sterling (£)', 'give' ),
114
			'symbol'      => '&pound;',
115
			'setting'     => array(
116
				'currency_position'   => 'before',
117
				'thousands_separator' => ',',
118
				'decimal_separator'   => '.',
119
				'number_decimals'     => 2,
120
			),
121
		),
122
		'AUD'  => array(
123
			'admin_label' => __( 'Australian Dollars ($)', 'give' ),
124
			'symbol'      => '&#36;',
125
			'setting'     => array(
126
				'currency_position'   => 'before',
127
				'thousands_separator' => ',',
128
				'decimal_separator'   => '.',
129
				'number_decimals'     => 2,
130
			),
131
		),
132
		'BRL'  => array(
133
			'admin_label' => __( 'Brazilian Real (R$)', 'give' ),
134
			'symbol'      => '&#82;&#36;',
135
			'setting'     => array(
136
				'currency_position'   => 'before',
137
				'thousands_separator' => ',',
138
				'decimal_separator'   => '.',
139
				'number_decimals'     => 2,
140
			),
141
		),
142
		'CAD'  => array(
143
			'admin_label' => __( 'Canadian Dollars ($)', 'give' ),
144
			'symbol'      => '&#36;',
145
			'setting'     => array(
146
				'currency_position'   => 'before',
147
				'thousands_separator' => ',',
148
				'decimal_separator'   => '.',
149
				'number_decimals'     => 2,
150
			),
151
		),
152
		'CZK'  => array(
153
			'admin_label' => __( 'Czech Koruna (Kč)', 'give' ),
154
			'symbol'      => '&#75;&#269;',
155
			'setting'     => array(
156
				'currency_position'   => 'before',
157
				'thousands_separator' => ',',
158
				'decimal_separator'   => '.',
159
				'number_decimals'     => 2,
160
			),
161
		),
162
		'DKK'  => array(
163
			'admin_label' => __( 'Danish Krone (kr.)', 'give' ),
164
			'symbol'      => '&nbsp;kr.&nbsp;',
165
			'setting'     => array(
166
				'currency_position'   => 'before',
167
				'thousands_separator' => ',',
168
				'decimal_separator'   => '.',
169
				'number_decimals'     => 2,
170
			),
171
		),
172
		'HKD'  => array(
173
			'admin_label' => __( 'Hong Kong Dollar ($)', 'give' ),
174
			'symbol'      => '&#36;',
175
			'setting'     => array(
176
				'currency_position'   => 'before',
177
				'thousands_separator' => ',',
178
				'decimal_separator'   => '.',
179
				'number_decimals'     => 2,
180
			),
181
		),
182
		'HUF'  => array(
183
			'admin_label' => __( 'Hungarian Forint (Ft)', 'give' ),
184
			'symbol'      => '&#70;&#116;',
185
			'setting'     => array(
186
				'currency_position'   => 'before',
187
				'thousands_separator' => ',',
188
				'decimal_separator'   => '.',
189
				'number_decimals'     => 2,
190
			),
191
		),
192
		'ILS'  => array(
193
			'admin_label' => __( 'Israeli Shekel (₪)', 'give' ),
194
			'symbol'      => '&#8362;',
195
			'setting'     => array(
196
				'currency_position'   => 'before',
197
				'thousands_separator' => ',',
198
				'decimal_separator'   => '.',
199
				'number_decimals'     => 2,
200
			),
201
		),
202
		'JPY'  => array(
203
			'admin_label' => __( 'Japanese Yen (¥)', 'give' ),
204
			'symbol'      => '&yen;',
205
			'setting'     => array(
206
				'currency_position'   => 'before',
207
				'thousands_separator' => ',',
208
				'decimal_separator'   => '.',
209
				'number_decimals'     => 0,
210
			),
211
		),
212
		'MYR'  => array(
213
			'admin_label' => __( 'Malaysian Ringgits (RM)', 'give' ),
214
			'symbol'      => '&#82;&#77;',
215
			'setting'     => array(
216
				'currency_position'   => 'before',
217
				'thousands_separator' => ',',
218
				'decimal_separator'   => '.',
219
				'number_decimals'     => 2,
220
			),
221
		),
222
		'MXN'  => array(
223
			'admin_label' => __( 'Mexican Peso ($)', 'give' ),
224
			'symbol'      => '&#36;',
225
			'setting'     => array(
226
				'currency_position'   => 'before',
227
				'thousands_separator' => ',',
228
				'decimal_separator'   => '.',
229
				'number_decimals'     => 2,
230
			),
231
		),
232
		'MAD'  => array(
233
			'admin_label' => __( 'Moroccan Dirham (&#x2e;&#x62f;&#x2e;&#x645;)', 'give' ),
234
			'symbol'      => '&#x2e;&#x62f;&#x2e;&#x645;',
235
			'setting'     => array(
236
				'currency_position'   => 'before',
237
				'thousands_separator' => ',',
238
				'decimal_separator'   => '.',
239
				'number_decimals'     => 2,
240
			),
241
		),
242
		'NZD'  => array(
243
			'admin_label' => __( 'New Zealand Dollar ($)', 'give' ),
244
			'symbol'      => '&#36;',
245
			'setting'     => array(
246
				'currency_position'   => 'before',
247
				'thousands_separator' => ',',
248
				'decimal_separator'   => '.',
249
				'number_decimals'     => 2,
250
			),
251
		),
252
		'NOK'  => array(
253
			'admin_label' => __( 'Norwegian Krone (Kr.)', 'give' ),
254
			'symbol'      => '&#107;&#114;.',
255
			'setting'     => array(
256
				'currency_position'   => 'before',
257
				'thousands_separator' => '.',
258
				'decimal_separator'   => ',',
259
				'number_decimals'     => 2,
260
			),
261
		),
262
		'PHP'  => array(
263
			'admin_label' => __( 'Philippine Pesos (₱)', 'give' ),
264
			'symbol'      => '&#8369;',
265
			'setting'     => array(
266
				'currency_position'   => 'before',
267
				'thousands_separator' => ',',
268
				'decimal_separator'   => '.',
269
				'number_decimals'     => 2,
270
			),
271
		),
272
		'PLN'  => array(
273
			'admin_label' => __( 'Polish Zloty (zł)', 'give' ),
274
			'symbol'      => '&#122;&#322;',
275
			'setting'     => array(
276
				'currency_position'   => 'before',
277
				'thousands_separator' => ' ',
278
				'decimal_separator'   => ',',
279
				'number_decimals'     => 2,
280
			),
281
		),
282
		'SGD'  => array(
283
			'admin_label' => __( 'Singapore Dollar ($)', 'give' ),
284
			'symbol'      => '&#36;',
285
			'setting'     => array(
286
				'currency_position'   => 'before',
287
				'thousands_separator' => ',',
288
				'decimal_separator'   => '.',
289
				'number_decimals'     => 2,
290
			),
291
		),
292
		'KRW'  => array(
293
			'admin_label' => __( 'South Korean Won (₩)', 'give' ),
294
			'symbol'      => '&#8361;',
295
			'setting'     => array(
296
				'currency_position'   => 'before',
297
				'thousands_separator' => ',',
298
				'decimal_separator'   => '.',
299
				'number_decimals'     => 0,
300
			),
301
		),
302
		'ZAR'  => array(
303
			'admin_label' => __( 'South African Rand (R)', 'give' ),
304
			'symbol'      => '&#82;',
305
			'setting'     => array(
306
				'currency_position'   => 'before',
307
				'thousands_separator' => ' ',
308
				'decimal_separator'   => '.',
309
				'number_decimals'     => 2,
310
			),
311
		),
312
		'SEK'  => array(
313
			'admin_label' => __( 'Swedish Krona (kr)', 'give' ),
314
			'symbol'      => '&nbsp;kr.&nbsp;',
315
			'setting'     => array(
316
				'currency_position'   => 'before',
317
				'thousands_separator' => ' ',
318
				'decimal_separator'   => ',',
319
				'number_decimals'     => 2,
320
			),
321
		),
322
		'CHF'  => array(
323
			'admin_label' => __( 'Swiss Franc (CHF)', 'give' ),
324
			'symbol'      => 'CHF',
325
			'setting'     => array(
326
				'currency_position'   => 'before',
327
				'thousands_separator' => ',',
328
				'decimal_separator'   => '.',
329
				'number_decimals'     => 2,
330
			),
331
		),
332
		'TWD'  => array(
333
			'admin_label' => __( 'Taiwan New Dollars (NT$)', 'give' ),
334
			'symbol'      => '&#78;&#84;&#36;',
335
			'setting'     => array(
336
				'currency_position'   => 'before',
337
				'thousands_separator' => '\'',
338
				'decimal_separator'   => '.',
339
				'number_decimals'     => 2,
340
			),
341
		),
342
		'THB'  => array(
343
			'admin_label' => __( 'Thai Baht (฿)', 'give' ),
344
			'symbol'      => '&#3647;',
345
			'setting'     => array(
346
				'currency_position'   => 'before',
347
				'thousands_separator' => ',',
348
				'decimal_separator'   => '.',
349
				'number_decimals'     => 2,
350
			),
351
		),
352
		'INR'  => array(
353
			'admin_label' => __( 'Indian Rupee (₹)', 'give' ),
354
			'symbol'      => '&#8377;',
355
			'setting'     => array(
356
				'currency_position'   => 'before',
357
				'thousands_separator' => ',',
358
				'decimal_separator'   => '.',
359
				'number_decimals'     => 2,
360
			),
361
		),
362
		'TRY'  => array(
363
			'admin_label' => __( 'Turkish Lira (₺)', 'give' ),
364
			'symbol'      => '&#8378;',
365
			'setting'     => array(
366
				'currency_position'   => 'before',
367
				'thousands_separator' => ',',
368
				'decimal_separator'   => '.',
369
				'number_decimals'     => 2,
370
			),
371
		),
372
		'RIAL' => array(
373
			'admin_label' => __( 'Iranian Rial (﷼)', 'give' ),
374
			'symbol'      => '&#xfdfc;',
375
			'setting'     => array(
376
				'currency_position'   => 'after',
377
				'thousands_separator' => ',',
378
				'decimal_separator'   => '.',
379
				'number_decimals'     => 2,
380
			),
381
		),
382
		'RUB'  => array(
383
			'admin_label' => __( 'Russian Rubles (руб)', 'give' ),
384
			'symbol'      => '&#8381;',
385
			'setting'     => array(
386
				'currency_position'   => 'before',
387
				'thousands_separator' => '.',
388
				'decimal_separator'   => ',',
389
				'number_decimals'     => 2,
390
			),
391
		),
392
	);
393
394
	/**
395
	 * Filter the currencies
396
	 * Note: you can register new currency by using this filter
397
	 * array(
398
	 *     'admin_label' => '',  // required
399
	 *     'symbol'      => '',  // required
400
	 *     'setting'     => ''   // required
401
	 *     ....
402
	 * )
403
	 *
404
	 * @since 1.8.15
405
	 *
406
	 * @param array $currencies
407
	 */
408
	$currencies = apply_filters( 'give_currencies', $currencies );
409
410
	// Backward compatibility: handle old way of currency registration.
411
	// Backward compatibility: Return desired result.
412
	if ( ! empty( $currencies ) ) {
413
		foreach ( $currencies as $currency_code => $currency_setting ) {
414
			if ( is_string( $currency_setting ) ) {
415
				$currencies[ $currency_code ] = array(
416
					'admin_label' => $currency_setting,
417
				);
418
			}
419
420
			$currencies[ $currency_code ] = wp_parse_args(
421
				$currencies[ $currency_code ],
422
				array(
423
					'admin_label' => '',
424
					'symbol'      => $currency_code,
425
					'setting'     => array(),
426
				)
427
			);
428
		}
429
430
		if ( ! empty( $info ) && is_string( $info ) && 'all' !== $info ) {
431
			$currencies = wp_list_pluck( $currencies, $info );
432
		}
433
	}
434
435
	return $currencies;
436
}
437
438
439
/**
440
 * Get all currency symbols
441
 *
442
 * @since 1.8.14
443
 *
444
 * @param bool $decode_currencies
445
 *
446
 * @return array
447
 */
448
function give_currency_symbols( $decode_currencies = false ) {
449
	$currencies = give_get_currencies( 'symbol' );
450
451
	if ( $decode_currencies ) {
452
		$currencies = array_map( 'html_entity_decode', $currencies );
453
	}
454
455
	/**
456
	 * Filter the currency symbols
457
	 *
458
	 * @since 1.8.14
459
	 *
460
	 * @param array $currencies
461
	 */
462
	return apply_filters( 'give_currency_symbols', $currencies );
463
}
464
465
466
/**
467
 * Give Currency Symbol
468
 *
469
 * Given a currency determine the symbol to use. If no currency given, site default is used. If no symbol is determine,
470
 * the currency string is returned.
471
 *
472
 * @since      1.0
473
 *
474
 * @param  string $currency        The currency string.
475
 * @param  bool   $decode_currency Option to HTML decode the currency symbol.
476
 *
477
 * @return string           The symbol to use for the currency
478
 */
479 View Code Duplication
function give_currency_symbol( $currency = '', $decode_currency = false ) {
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...
480
481
	if ( empty( $currency ) ) {
482
		$currency = give_get_currency();
483
	}
484
485
	$currencies = give_currency_symbols( $decode_currency );
486
	$symbol     = array_key_exists( $currency, $currencies ) ? $currencies[ $currency ] : $currency;
487
488
	/**
489
	 * Filter the currency symbol
490
	 *
491
	 * @since 1.0
492
	 *
493
	 * @param string $symbol
494
	 * @param string $currency
495
	 */
496
	return apply_filters( 'give_currency_symbol', $symbol, $currency );
497
}
498
499
500
/**
501
 * Get currency name.
502
 *
503
 * @since 1.8.8
504
 *
505
 * @param string $currency_code
506
 *
507
 * @return string
508
 */
509
function give_get_currency_name( $currency_code ) {
510
	$currency_name  = '';
511
	$currency_names = give_get_currencies();
512
513
	if ( $currency_code && array_key_exists( $currency_code, $currency_names ) ) {
514
		$currency_name = explode( '(', $currency_names[ $currency_code ] );
515
		$currency_name = trim( current( $currency_name ) );
516
	}
517
518
	/**
519
	 * Filter the currency name
520
	 *
521
	 * @since 1.8.8
522
	 *
523
	 * @param string $currency_name
524
	 * @param string $currency_code
525
	 */
526
	return apply_filters( 'give_currency_name', $currency_name, $currency_code );
527
}
528
529
530
/**
531
 * Get the current page URL.
532
 *
533
 * @since 1.0
534
 * @return string $current_url Current page URL.
535
 */
536
function give_get_current_page_url() {
537
538
	global $wp;
539
540
	if ( get_option( 'permalink_structure' ) ) {
541
		$base = trailingslashit( home_url( $wp->request ) );
542
	} else {
543
		$base = add_query_arg( $wp->query_string, '', trailingslashit( home_url( $wp->request ) ) );
544
		$base = remove_query_arg( array( 'post_type', 'name' ), $base );
545
	}
546
547
	$scheme      = is_ssl() ? 'https' : 'http';
548
	$current_uri = set_url_scheme( $base, $scheme );
549
550
	if ( is_front_page() ) {
551
		$current_uri = home_url( '/' );
552
	}
553
554
	/**
555
	 * Filter the current page url
556
	 *
557
	 * @since 1.0
558
	 *
559
	 * @param string $current_uri
560
	 */
561
	return apply_filters( 'give_get_current_page_url', $current_uri );
562
563
}
564
565
566
/**
567
 * Verify credit card numbers live?
568
 *
569
 * @since 1.0
570
 *
571
 * @return bool $ret True is verify credit cards is live
572
 */
573
function give_is_cc_verify_enabled() {
574
575
	$ret = true;
576
577
	/**
578
	 * Enable if use a single gateway other than PayPal or Manual. We have to assume it accepts credit cards.
579
	 * Enable if using more than one gateway if they are not both PayPal and manual, again assuming credit card usage.
580
	 */
581
	$gateways = give_get_enabled_payment_gateways();
582
583
	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...
584
		$ret = true;
585
	} elseif ( count( $gateways ) == 1 ) {
0 ignored issues
show
introduced by
Found "== 1". Use Yoda Condition checks, you must
Loading history...
586
		$ret = false;
587
	} 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...
588
		$ret = false;
589
	}
590
591
	/**
592
	 * Fire the filter
593
	 *
594
	 * @since 1.0
595
	 *
596
	 * @param bool $ret
597
	 */
598
	return (bool) apply_filters( 'give_is_cc_verify_enabled', $ret );
599
}
600
601
/**
602
 * Retrieve timezone.
603
 *
604
 * @since 1.0
605
 * @return string $timezone The timezone ID.
606
 */
607
function give_get_timezone_id() {
608
609
	// if site timezone string exists, return it.
610
	if ( $timezone = get_option( 'timezone_string' ) ) {
611
		return $timezone;
612
	}
613
614
	// get UTC offset, if it isn't set return UTC.
615
	if ( ! ( $utc_offset = 3600 * get_option( 'gmt_offset', 0 ) ) ) {
616
		return 'UTC';
617
	}
618
619
	// attempt to guess the timezone string from the UTC offset.
620
	$timezone = timezone_name_from_abbr( '', $utc_offset );
621
622
	// last try, guess timezone string manually.
623
	if ( $timezone === false ) {
0 ignored issues
show
introduced by
Found "=== false". Use Yoda Condition checks, you must
Loading history...
624
625
		$is_dst = date( 'I' );
626
627
		foreach ( timezone_abbreviations_list() as $abbr ) {
628
			foreach ( $abbr as $city ) {
629
				if ( $city['dst'] == $is_dst && $city['offset'] == $utc_offset ) {
630
					return $city['timezone_id'];
631
				}
632
			}
633
		}
634
	}
635
636
	// Fallback.
637
	return 'UTC';
638
}
639
640
641
/**
642
 * Get User IP
643
 *
644
 * Returns the IP address of the current visitor
645
 *
646
 * @since 1.0
647
 * @return string $ip User's IP address
648
 */
649
function give_get_ip() {
650
651
	$ip = '127.0.0.1';
652
653
	if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
654
		// check ip from share internet
655
		$ip = $_SERVER['HTTP_CLIENT_IP'];
0 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
656
	} elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
657
		// to check ip is pass from proxy
658
		$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
0 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
659
	} 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...
660
		$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...
661
	}
662
663
	return apply_filters( 'give_get_ip', $ip );
664
}
665
666
667
/**
668
 * Store Donation Data in Sessions
669
 *
670
 * Used for storing info about donation
671
 *
672
 * @since 1.0
673
 *
674
 * @param $purchase_data
675
 *
676
 * @uses  Give()->session->set()
677
 */
678
function give_set_purchase_session( $purchase_data = array() ) {
679
	Give()->session->set( 'give_purchase', $purchase_data );
680
	Give()->session->set( 'give_email', $purchase_data['user_email'] );
681
}
682
683
/**
684
 * Retrieve Donation Data from Session
685
 *
686
 * Used for retrieving info about donation
687
 * after completing a donation
688
 *
689
 * @since 1.0
690
 * @uses  Give()->session->get()
691
 * @return mixed array | false
692
 */
693
function give_get_purchase_session() {
694
	return Give()->session->get( 'give_purchase' );
695
}
696
697
/**
698
 * Generate Item Title for Payment Gateway.
699
 *
700
 * @param array $payment_data Payment Data.
701
 *
702
 * @since 1.8.14
703
 *
704
 * @return string
705
 */
706
function give_payment_gateway_item_title( $payment_data ) {
707
	$form_id          = intval( $payment_data['post_data']['give-form-id'] );
708
	$item_name        = $payment_data['post_data']['give-form-title'];
709
	$is_custom_amount = give_is_setting_enabled( give_get_meta( $form_id, '_give_custom_amount', true ) );
710
711
	// Verify has variable prices.
712
	if ( give_has_variable_prices( $form_id ) && isset( $payment_data['post_data']['give-price-id'] ) ) {
713
714
		$item_price_level_text = give_get_price_option_name( $form_id, $payment_data['post_data']['give-price-id'] );
715
		$price_level_amount    = give_get_price_option_amount( $form_id, $payment_data['post_data']['give-price-id'] );
716
717
		// Donation given doesn't match selected level (must be a custom amount).
718
		if ( $price_level_amount !== give_maybe_sanitize_amount( $payment_data['post_data']['give-amount'] ) ) {
719
			$custom_amount_text = give_get_meta( $form_id, '_give_custom_amount_text', true );
720
721
			// user custom amount text if any, fallback to default if not.
722
			$item_name .= ' - ' . give_check_variable( $custom_amount_text, 'empty', __( 'Custom Amount', 'give' ) );
723
724
		} elseif ( ! empty( $item_price_level_text ) ) {
725
			// Matches a donation level - append level text.
726
			$item_name .= ' - ' . $item_price_level_text;
727
		}
728
	} // End if().
729
	elseif ( $is_custom_amount && give_get_form_price( $form_id ) !== give_maybe_sanitize_amount( $payment_data['post_data']['give-amount'] ) ) {
730
		$custom_amount_text = give_get_meta( $form_id, '_give_custom_amount_text', true );
731
		// user custom amount text if any, fallback to default if not.
732
		$item_name .= ' - ' . give_check_variable( $custom_amount_text, 'empty', __( 'Custom Amount', 'give' ) );
733
	}
734
735
	/**
736
	 * Filter the Item Title of Payment Gateway.
737
	 *
738
	 * @param string $item_name    Item Title of Payment Gateway.
739
	 * @param int    $form_id      Donation Form ID.
740
	 * @param array  $payment_data Payment Data.
741
	 *
742
	 * @since 1.8.14
743
	 *
744
	 * @return string
745
	 */
746
	return apply_filters( 'give_payment_gateway_item_title', $item_name, $form_id, $payment_data );
747
}
748
749
/**
750
 * Get Donation Summary
751
 *
752
 * Creates a donation summary for payment gateways from the donation data before the payment is created in the database.
753
 *
754
 * @since       1.8.12
755
 *
756
 * @param array $donation_data
757
 * @param bool  $name_and_email
758
 * @param int   $length
759
 *
760
 * @return string
761
 */
762
function give_payment_gateway_donation_summary( $donation_data, $name_and_email = true, $length = 255 ) {
763
	$form_id = isset( $donation_data['post_data']['give-form-id'] ) ? $donation_data['post_data']['give-form-id'] : '';
764
765
	// Form title.
766
	$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' ) ) );
767
768
	// Form multilevel if applicable.
769
	if ( isset( $donation_data['post_data']['give-price-id'] ) ) {
770
		$summary .= ': ' . give_get_price_option_name( $form_id, $donation_data['post_data']['give-price-id'] );
771
	}
772
773
	// Add Donor's name + email if requested.
774
	if ( $name_and_email ) {
775
776
		// First name
777 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...
778
			$summary .= ' - ' . $donation_data['user_info']['first_name'];
779
		}
780
781 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...
782
			$summary .= ' ' . $donation_data['user_info']['last_name'];
783
		}
784
785
		$summary .= ' (' . $donation_data['user_email'] . ')';
786
	}
787
788
	// Cut the length
789
	$summary = substr( $summary, 0, $length );
790
791
	return apply_filters( 'give_payment_gateway_donation_summary', $summary );
792
}
793
794
795
/**
796
 * Get user host
797
 *
798
 * Returns the webhost this site is using if possible
799
 *
800
 * @since 1.0
801
 * @return string $host if detected, false otherwise
802
 */
803
function give_get_host() {
804
	$host = false;
0 ignored issues
show
Unused Code introduced by
$host is not used, you could remove the assignment.

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

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

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

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

Loading history...
805
806
	if ( defined( 'WPE_APIKEY' ) ) {
807
		$host = 'WP Engine';
808
	} elseif ( defined( 'PAGELYBIN' ) ) {
809
		$host = 'Pagely';
810
	} elseif ( DB_HOST == 'localhost:/tmp/mysql5.sock' ) {
0 ignored issues
show
introduced by
Found "== '". Use Yoda Condition checks, you must
Loading history...
811
		$host = 'ICDSoft';
812
	} elseif ( DB_HOST == 'mysqlv5' ) {
0 ignored issues
show
introduced by
Found "== '". Use Yoda Condition checks, you must
Loading history...
813
		$host = 'NetworkSolutions';
814
	} elseif ( strpos( DB_HOST, 'ipagemysql.com' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
815
		$host = 'iPage';
816
	} elseif ( strpos( DB_HOST, 'ipowermysql.com' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
817
		$host = 'IPower';
818
	} elseif ( strpos( DB_HOST, '.gridserver.com' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
819
		$host = 'MediaTemple Grid';
820
	} elseif ( strpos( DB_HOST, '.pair.com' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
821
		$host = 'pair Networks';
822
	} elseif ( strpos( DB_HOST, '.stabletransit.com' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
823
		$host = 'Rackspace Cloud';
824
	} elseif ( strpos( DB_HOST, '.sysfix.eu' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
825
		$host = 'SysFix.eu Power Hosting';
826
	} elseif ( strpos( $_SERVER['SERVER_NAME'], 'Flywheel' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
827
		$host = 'Flywheel';
828
	} else {
829
		// Adding a general fallback for data gathering
830
		$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...
831
	}
832
833
	return $host;
834
}
835
836
837
/**
838
 * Check site host
839
 *
840
 * @since 1.0
841
 *
842
 * @param bool /string $host The host to check
843
 *
844
 * @return bool true if host matches, false if not
845
 */
846
function give_is_host( $host = false ) {
847
848
	$return = false;
849
850
	if ( $host ) {
851
		$host = str_replace( ' ', '', strtolower( $host ) );
852
853
		switch ( $host ) {
854
			case 'wpengine':
855
				if ( defined( 'WPE_APIKEY' ) ) {
856
					$return = true;
857
				}
858
				break;
859
			case 'pagely':
860
				if ( defined( 'PAGELYBIN' ) ) {
861
					$return = true;
862
				}
863
				break;
864
			case 'icdsoft':
865
				if ( DB_HOST == 'localhost:/tmp/mysql5.sock' ) {
0 ignored issues
show
introduced by
Found "== '". Use Yoda Condition checks, you must
Loading history...
866
					$return = true;
867
				}
868
				break;
869
			case 'networksolutions':
870
				if ( DB_HOST == 'mysqlv5' ) {
0 ignored issues
show
introduced by
Found "== '". Use Yoda Condition checks, you must
Loading history...
871
					$return = true;
872
				}
873
				break;
874
			case 'ipage':
875
				if ( strpos( DB_HOST, 'ipagemysql.com' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
876
					$return = true;
877
				}
878
				break;
879
			case 'ipower':
880
				if ( strpos( DB_HOST, 'ipowermysql.com' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
881
					$return = true;
882
				}
883
				break;
884
			case 'mediatemplegrid':
885
				if ( strpos( DB_HOST, '.gridserver.com' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
886
					$return = true;
887
				}
888
				break;
889
			case 'pairnetworks':
890
				if ( strpos( DB_HOST, '.pair.com' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
891
					$return = true;
892
				}
893
				break;
894
			case 'rackspacecloud':
895
				if ( strpos( DB_HOST, '.stabletransit.com' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
896
					$return = true;
897
				}
898
				break;
899
			case 'sysfix.eu':
900
			case 'sysfix.eupowerhosting':
901
				if ( strpos( DB_HOST, '.sysfix.eu' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
902
					$return = true;
903
				}
904
				break;
905
			case 'flywheel':
906
				if ( strpos( $_SERVER['SERVER_NAME'], 'Flywheel' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
907
					$return = true;
908
				}
909
				break;
910
			default:
911
				$return = false;
912
		}// End switch().
913
	}// End if().
914
915
	return $return;
916
}
917
918
/**
919
 * Marks a function as deprecated and informs when it has been used.
920
 *
921
 * There is a hook give_deprecated_function_run that will be called that can be used
922
 * to get the backtrace up to what file and function called the deprecated
923
 * function.
924
 *
925
 * The current behavior is to trigger a user error if WP_DEBUG is true.
926
 *
927
 * This function is to be used in every function that is deprecated.
928
 *
929
 * @uses do_action() Calls 'give_deprecated_function_run' and passes the function name, what to use instead,
930
 *   and the version the function was deprecated in.
931
 * @uses apply_filters() Calls 'give_deprecated_function_trigger_error' and expects boolean value of true to do
932
 *   trigger or false to not trigger error.
933
 *
934
 * @param string $function    The function that was called.
935
 * @param string $version     The plugin version that deprecated the function.
936
 * @param string $replacement Optional. The function that should have been called.
937
 * @param array  $backtrace   Optional. Contains stack backtrace of deprecated function.
938
 */
939
function _give_deprecated_function( $function, $version, $replacement = null, $backtrace = null ) {
940
941
	/**
942
	 * Fires while give deprecated function call occurs.
943
	 *
944
	 * Allow you to hook to deprecated function call.
945
	 *
946
	 * @since 1.0
947
	 *
948
	 * @param string $function    The function that was called.
949
	 * @param string $replacement Optional. The function that should have been called.
950
	 * @param string $version     The plugin version that deprecated the function.
951
	 */
952
	do_action( 'give_deprecated_function_run', $function, $replacement, $version );
953
954
	$show_errors = current_user_can( 'manage_options' );
955
956
	// Allow plugin to filter the output error trigger.
957
	if ( WP_DEBUG && apply_filters( 'give_deprecated_function_trigger_error', $show_errors ) ) {
958
		if ( ! is_null( $replacement ) ) {
959
			trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since Give version %2$s! Use %3$s instead.', 'give' ), $function, $version, $replacement ) );
960
			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...
961
			// Alternatively we could dump this to a file.
962
		} else {
963
			trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since Give version %2$s with no alternative available.', 'give' ), $function, $version ) );
964
			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...
965
			// Alternatively we could dump this to a file.
966
		}
967
	}
968
}
969
970
/**
971
 * Give Get Admin ID
972
 *
973
 * Helper function to return the ID of the post for admin usage
974
 *
975
 * @return string $post_id
976
 */
977
function give_get_admin_post_id() {
978
	$post_id = isset( $_GET['post'] ) ? $_GET['post'] : null;
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...
979
	if ( ! $post_id && isset( $_POST['post_id'] ) ) {
980
		$post_id = $_POST['post_id'];
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
981
	}
982
983
	return $post_id;
984
}
985
986
/**
987
 * Get PHP Arg Separator Output
988
 *
989
 * @since 1.0
990
 * @return string Arg separator output
991
 */
992
function give_get_php_arg_separator_output() {
993
	return ini_get( 'arg_separator.output' );
994
}
995
996
997
/**
998
 * Month Num To Name
999
 *
1000
 * Takes a month number and returns the name three letter name of it.
1001
 *
1002
 * @since 1.0
1003
 *
1004
 * @param int $n
1005
 *
1006
 * @return string Short month name
1007
 */
1008
function give_month_num_to_name( $n ) {
1009
	$timestamp = mktime( 0, 0, 0, $n, 1, 2005 );
1010
1011
	return date_i18n( 'M', $timestamp );
1012
}
1013
1014
1015
/**
1016
 * Checks whether function is disabled.
1017
 *
1018
 * @since 1.0
1019
 *
1020
 * @param string $function Name of the function.
1021
 *
1022
 * @return bool Whether or not function is disabled.
1023
 */
1024
function give_is_func_disabled( $function ) {
1025
	$disabled = explode( ',', ini_get( 'disable_functions' ) );
1026
1027
	return in_array( $function, $disabled );
1028
}
1029
1030
/**
1031
 * Give Newsletter
1032
 *
1033
 * Returns the main Give newsletter form
1034
 */
1035
function give_get_newsletter() {
1036
	?>
1037
1038
	<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>
1039
1040
	<div class="give-newsletter-form-wrap">
1041
1042
		<form action="//givewp.us3.list-manage.com/subscribe/post?u=3ccb75d68bda4381e2f45794c&amp;id=12a081aa13"
1043
			  method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate"
1044
			  target="_blank" novalidate>
1045
			<div class="give-newsletter-confirmation">
1046
				<p><?php esc_html_e( 'Thanks for Subscribing!', 'give' ); ?> :)</p>
1047
			</div>
1048
1049
			<table class="form-table give-newsletter-form">
1050
				<tr valign="middle">
1051
					<td>
1052
						<label for="mce-EMAIL"
1053
							   class="screen-reader-text"><?php esc_html_e( 'Email Address (required)', 'give' ); ?></label>
1054
						<input type="email" name="EMAIL" id="mce-EMAIL"
1055
							   placeholder="<?php esc_attr_e( 'Email Address (required)', 'give' ); ?>"
1056
							   class="required email" value="">
1057
					</td>
1058
					<td>
1059
						<label for="mce-FNAME"
1060
							   class="screen-reader-text"><?php esc_html_e( 'First Name', 'give' ); ?></label>
1061
						<input type="text" name="FNAME" id="mce-FNAME"
1062
							   placeholder="<?php esc_attr_e( 'First Name', 'give' ); ?>" class="" value="">
1063
					</td>
1064
					<td>
1065
						<label for="mce-LNAME"
1066
							   class="screen-reader-text"><?php esc_html_e( 'Last Name', 'give' ); ?></label>
1067
						<input type="text" name="LNAME" id="mce-LNAME"
1068
							   placeholder="<?php esc_attr_e( 'Last Name', 'give' ); ?>" class="" value="">
1069
					</td>
1070
					<td>
1071
						<input type="submit" name="subscribe" id="mc-embedded-subscribe" class="button"
1072
							   value="<?php esc_attr_e( 'Subscribe', 'give' ); ?>">
1073
					</td>
1074
				</tr>
1075
			</table>
1076
		</form>
1077
1078
		<div style="position: absolute; left: -5000px;">
1079
			<input type="text" name="b_3ccb75d68bda4381e2f45794c_12a081aa13" tabindex="-1" value="">
1080
		</div>
1081
1082
	</div>
1083
1084
	<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...
1085
	<script type='text/javascript'>(function ($) {
1086
			window.fnames = new Array();
1087
			window.ftypes = new Array();
1088
			fnames[0] = 'EMAIL';
1089
			ftypes[0] = 'email';
1090
			fnames[1] = 'FNAME';
1091
			ftypes[1] = 'text';
1092
			fnames[2] = 'LNAME';
1093
			ftypes[2] = 'text';
1094
1095
			//Successful submission
1096
			$('form[name="mc-embedded-subscribe-form"]').on('submit', function () {
1097
1098
				var email_field = $(this).find('#mce-EMAIL').val();
1099
				if (!email_field) {
1100
					return false;
1101
				}
1102
				$(this).find('.give-newsletter-confirmation').show().delay(5000).slideUp();
1103
				$(this).find('.give-newsletter-form').hide();
1104
1105
			});
1106
1107
		}(jQuery));
1108
		var $mcj = jQuery.noConflict(true);
1109
1110
1111
	</script>
1112
	<!--End mc_embed_signup-->
1113
1114
	<?php
1115
}
1116
1117
1118
/**
1119
 * Create SVG library function
1120
 *
1121
 * @param string $icon
1122
 *
1123
 * @return string
1124
 */
1125
function give_svg_icons( $icon ) {
1126
1127
	// Store your SVGs in an associative array
1128
	$svgs = array(
1129
		'microphone'    => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE2LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgd2lkdGg9IjY0cHgiIGhlaWdodD0iMTAwcHgiIHZpZXdCb3g9IjAgLTIwIDY0IDEyMCIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNjQgMTAwOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8Zz4NCgk8Zz4NCgkJPHBhdGggZD0iTTYyLDM2LjIxNWgtM2MtMS4xLDAtMiwwLjktMiwyVjUyYzAsNi42ODYtNS4yNjYsMTgtMjUsMThTNyw1OC42ODYsNyw1MlYzOC4yMTVjMC0xLjEtMC45LTItMi0ySDJjLTEuMSwwLTIsMC45LTIsMlY1Mg0KCQkJYzAsMTEuMTg0LDguMjE1LDIzLjE1MiwyNywyNC44MDFWOTBIMTRjLTEuMSwwLTIsMC44OTgtMiwydjZjMCwxLjEsMC45LDIsMiwyaDM2YzEuMSwwLDItMC45LDItMnYtNmMwLTEuMTAyLTAuOS0yLTItMkgzN1Y3Ni44MDENCgkJCUM1NS43ODUsNzUuMTUyLDY0LDYzLjE4NCw2NCw1MlYzOC4yMTVDNjQsMzcuMTE1LDYzLjEsMzYuMjE1LDYyLDM2LjIxNXoiLz4NCgkJPHBhdGggZD0iTTMyLDYwYzExLjczMiwwLDE1LTQuODE4LDE1LThWMzYuMjE1SDE3VjUyQzE3LDU1LjE4MiwyMC4yNjYsNjAsMzIsNjB6Ii8+DQoJCTxwYXRoIGQ9Ik00Nyw4YzAtMy4xODQtMy4yNjgtOC0xNS04QzIwLjI2NiwwLDE3LDQuODE2LDE3LDh2MjEuMjE1aDMwVjh6Ii8+DQoJPC9nPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPC9zdmc+DQo=',
1130
		'alert'         => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE2LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgd2lkdGg9IjI4LjkzOHB4IiBoZWlnaHQ9IjI1LjAwNXB4IiB2aWV3Qm94PSIwIDAgMjguOTM4IDI1LjAwNSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMjguOTM4IDI1LjAwNTsiDQoJIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPHBhdGggc3R5bGU9ImZpbGw6IzAwMDAwMDsiIGQ9Ik0yOC44NTksMjQuMTU4TDE0Ljk1NywwLjI3OUMxNC44NTYsMC4xMDYsMTQuNjcsMCwxNC40NjgsMGMtMC4xOTgsMC0wLjM4MywwLjEwNi0wLjQ4MSwwLjI3OQ0KCUwwLjA3OSwyNC4xNThjLTAuMTAyLDAuMTc1LTAuMTA2LDAuMzg5LTAuMDA2LDAuNTY1YzAuMTAzLDAuMTc0LDAuMjg3LDAuMjgyLDAuNDg4LDAuMjgyaDI3LjgxNGMwLjIwMSwwLDAuMzg5LTAuMTA4LDAuNDg4LTAuMjgyDQoJYzAuMDQ3LTAuMDg4LDAuMDc0LTAuMTg2LDAuMDc0LTAuMjgxQzI4LjkzOCwyNC4zNDMsMjguOTExLDI0LjI0NSwyOC44NTksMjQuMTU4eiBNMTYuMzY5LDguNDc1bC0wLjQ2Miw5LjQ5M2gtMi4zODlsLTAuNDYxLTkuNDkzDQoJSDE2LjM2OXogTTE0LjcxMSwyMi44MjhoLTAuMDQyYy0xLjA4OSwwLTEuODQzLTAuODE3LTEuODQzLTEuOTA3YzAtMS4xMzEsMC43NzQtMS45MDcsMS44ODUtMS45MDdzMS44NDYsMC43NzUsMS44NjcsMS45MDcNCglDMTYuNTc5LDIyLjAxMSwxNS44NDQsMjIuODI4LDE0LjcxMSwyMi44Mjh6Ii8+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8L3N2Zz4NCg==',
1131
		'placemark'     => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxNi4wLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB3aWR0aD0iMTAwcHgiIGhlaWdodD0iMTAwcHgiIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMDAgMTAwIiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxnPg0KCTxwYXRoIGQ9Ik01MC40MzQsMjAuMjcxYy0xMi40OTksMC0yMi42NjgsMTAuMTY5LTIyLjY2OCwyMi42NjhjMCwxMS44MTQsMTguODE1LDMyLjE1NSwyMC45NiwzNC40MzdsMS43MDgsMS44MTZsMS43MDgtMS44MTYNCgkJYzIuMTQ1LTIuMjgxLDIwLjk2LTIyLjYyMywyMC45Ni0zNC40MzdDNzMuMTAzLDMwLjQ0LDYyLjkzNCwyMC4yNzEsNTAuNDM0LDIwLjI3MXogTTUwLjQzNCw1Mi4zMmMtNS4xNzIsMC05LjM4LTQuMjA4LTkuMzgtOS4zOA0KCQlzNC4yMDgtOS4zOCw5LjM4LTkuMzhjNS4xNzMsMCw5LjM4LDQuMjA4LDkuMzgsOS4zOFM1NS42MDcsNTIuMzIsNTAuNDM0LDUyLjMyeiIvPg0KPC9nPg0KPC9zdmc+DQo=',
1132
		'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==',
1133
		'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',
1134
	);
1135
1136
	// Return the chosen icon's SVG string
1137
	return $svgs[ $icon ];
1138
}
1139
1140
/**
1141
 * Modify Admin Nav Menu Label
1142
 *
1143
 * @since 1.3
1144
 *
1145
 * @param object $post_type The current object to add a menu items meta box for.
1146
 *
1147
 * @return mixed
1148
 */
1149
function modify_nav_menu_meta_box_object( $post_type ) {
1150
	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...
1151
		$post_type->labels->name = esc_html__( 'Donation Forms', 'give' );
1152
	}
1153
1154
	return $post_type;
1155
}
1156
1157
add_filter( 'nav_menu_meta_box_object', 'modify_nav_menu_meta_box_object' );
1158
1159
/**
1160
 * Show Donation Forms Post Type in Appearance > Menus by default on fresh install.
1161
 *
1162
 * @since 1.8.14
1163
 *
1164
 * @todo  Remove this, when WordPress Core ticket is resolved (https://core.trac.wordpress.org/ticket/16828).
1165
 *
1166
 * @return bool
1167
 */
1168
function give_donation_metabox_menu() {
1169
1170
	// Get Current Screen.
1171
	$screen = get_current_screen();
1172
1173
	// Proceed, if current screen is navigation menus.
1174
	if (
1175
		'nav-menus' === $screen->id &&
1176
		give_is_setting_enabled( give_get_option( 'forms_singular' ) ) &&
1177
		! get_user_option( 'give_is_donation_forms_menu_updated' )
1178
	) {
1179
1180
		// Return false, if it fails to retrieve hidden meta box list and is not admin.
1181
		if (
1182
			! is_admin() ||
1183
			( ! $hidden_meta_boxes = get_user_option( 'metaboxhidden_nav-menus' ) )
1184
		) {
1185
			return false;
1186
		}
1187
1188
		// Return false, In case, we don't find 'Donation Form' in hidden meta box list.
1189
		if ( ! in_array( 'add-post-type-give_forms', $hidden_meta_boxes, true ) ) {
1190
			return false;
1191
		}
1192
1193
		// Exclude 'Donation Form' value from hidden meta box's list.
1194
		$hidden_meta_boxes = array_diff( $hidden_meta_boxes, array( 'add-post-type-give_forms' ) );
1195
1196
		// Get current user ID.
1197
		$user = wp_get_current_user();
1198
1199
		update_user_option( $user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true );
1200
		update_user_option( $user->ID, 'give_is_donation_forms_menu_updated', true, true );
1201
	}
1202
}
1203
1204
add_action( 'current_screen', 'give_donation_metabox_menu' );
1205
1206
/**
1207
 * Array_column backup usage
1208
 *
1209
 * This file is part of the array_column library.
1210
 *
1211
 * @since      : 1.3.0.1
1212
 *
1213
 * @copyright  Copyright (c) Ben Ramsey (http://benramsey.com)
1214
 * @license    https://opensource.org/licenses/MIT MIT
1215
 */
1216
1217
if ( ! function_exists( 'array_column' ) ) {
1218
	/**
1219
	 * Returns the values from a single column of the input array, identified by
1220
	 * the $columnKey.
1221
	 *
1222
	 * Optionally, you may provide an $indexKey to index the values in the returned
1223
	 * array by the values from the $indexKey column in the input array.
1224
	 *
1225
	 * @param array      $input     A multi-dimensional array (record set) from which to pull
1226
	 *                              a column of values.
1227
	 * @param int|string $columnKey The column of values to return. This value may be the
1228
	 *                              integer key of the column you wish to retrieve, or it
1229
	 *                              may be the string key name for an associative array.
1230
	 * @param mixed      $indexKey  (Optional.) The column to use as the index/keys for
1231
	 *                              the returned array. This value may be the integer key
1232
	 *                              of the column, or it may be the string key name.
1233
	 *
1234
	 * @return array
1235
	 */
1236
	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...
1237
		// Using func_get_args() in order to check for proper number of
1238
		// parameters and trigger errors exactly as the built-in array_column()
1239
		// does in PHP 5.5.
1240
		$argc   = func_num_args();
1241
		$params = func_get_args();
1242
1243
		if ( $argc < 2 ) {
1244
			trigger_error( sprintf( esc_html__( 'array_column() expects at least 2 parameters, %s given.', 'give' ), $argc ), E_USER_WARNING );
1245
1246
			return null;
1247
		}
1248
1249
		if ( ! is_array( $params[0] ) ) {
1250
			trigger_error( sprintf( esc_html__( 'array_column() expects parameter 1 to be array, %s given.', 'give' ), gettype( $params[0] ) ), E_USER_WARNING );
1251
1252
			return null;
1253
		}
1254
1255 View Code Duplication
		if ( ! is_int( $params[1] )
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...
1256
			 && ! is_float( $params[1] )
1257
			 && ! is_string( $params[1] )
1258
			 && $params[1] !== null
1259
			 && ! ( is_object( $params[1] ) && method_exists( $params[1], '__toString' ) )
1260
		) {
1261
			trigger_error( esc_html__( 'array_column(): The column key should be either a string or an integer.', 'give' ), E_USER_WARNING );
1262
1263
			return false;
1264
		}
1265
1266 View Code Duplication
		if ( isset( $params[2] )
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...
1267
			 && ! is_int( $params[2] )
1268
			 && ! is_float( $params[2] )
1269
			 && ! is_string( $params[2] )
1270
			 && ! ( is_object( $params[2] ) && method_exists( $params[2], '__toString' ) )
1271
		) {
1272
			trigger_error( esc_html__( 'array_column(): The index key should be either a string or an integer.', 'give' ), E_USER_WARNING );
1273
1274
			return false;
1275
		}
1276
1277
		$paramsInput     = $params[0];
1278
		$paramsColumnKey = ( $params[1] !== null ) ? (string) $params[1] : null;
1279
1280
		$paramsIndexKey = null;
1281
		if ( isset( $params[2] ) ) {
1282
			if ( is_float( $params[2] ) || is_int( $params[2] ) ) {
1283
				$paramsIndexKey = (int) $params[2];
1284
			} else {
1285
				$paramsIndexKey = (string) $params[2];
1286
			}
1287
		}
1288
1289
		$resultArray = array();
1290
1291
		foreach ( $paramsInput as $row ) {
1292
			$key    = $value = null;
1293
			$keySet = $valueSet = false;
1294
1295
			if ( $paramsIndexKey !== null && array_key_exists( $paramsIndexKey, $row ) ) {
1296
				$keySet = true;
1297
				$key    = (string) $row[ $paramsIndexKey ];
1298
			}
1299
1300
			if ( $paramsColumnKey === null ) {
1301
				$valueSet = true;
1302
				$value    = $row;
1303
			} elseif ( is_array( $row ) && array_key_exists( $paramsColumnKey, $row ) ) {
1304
				$valueSet = true;
1305
				$value    = $row[ $paramsColumnKey ];
1306
			}
1307
1308
			if ( $valueSet ) {
1309
				if ( $keySet ) {
1310
					$resultArray[ $key ] = $value;
1311
				} else {
1312
					$resultArray[] = $value;
1313
				}
1314
			}
1315
		}
1316
1317
		return $resultArray;
1318
	}
1319
}// End if().
1320
1321
/**
1322
 * Determines the receipt visibility status.
1323
 *
1324
 * @since 1.3.2
1325
 *
1326
 * @param string $payment_key
1327
 *
1328
 * @return bool Whether the receipt is visible or not.
1329
 */
1330
function give_can_view_receipt( $payment_key = '' ) {
1331
1332
	$return = false;
1333
1334
	if ( empty( $payment_key ) ) {
1335
		return $return;
1336
	}
1337
1338
	global $give_receipt_args;
1339
1340
	$give_receipt_args['id'] = give_get_purchase_id_by_key( $payment_key );
1341
1342
	$user_id = (int) give_get_payment_user_id( $give_receipt_args['id'] );
1343
1344
	$payment_meta = give_get_payment_meta( $give_receipt_args['id'] );
1345
1346
	if ( is_user_logged_in() ) {
1347
		if ( $user_id === (int) get_current_user_id() ) {
1348
			$return = true;
1349
		} elseif ( wp_get_current_user()->user_email === give_get_payment_user_email( $give_receipt_args['id'] ) ) {
1350
			$return = true;
1351
		} elseif ( current_user_can( 'view_give_sensitive_data' ) ) {
1352
			$return = true;
1353
		}
1354
	}
1355
1356
	$session = give_get_purchase_session();
1357
	if ( ! empty( $session ) && ! is_user_logged_in() ) {
1358
		if ( $session['purchase_key'] === $payment_meta['key'] ) {
1359
			$return = true;
1360
		}
1361
	}
1362
1363
	return (bool) apply_filters( 'give_can_view_receipt', $return, $payment_key );
1364
1365
}
1366
1367
/**
1368
 * Fallback for cal_days_in_month
1369
 *
1370
 * Fallback in case the calendar extension is not loaded in PHP; Only supports Gregorian calendar
1371
 */
1372
if ( ! function_exists( 'cal_days_in_month' ) ) {
1373
	/**
1374
	 * cal_days_in_month
1375
	 *
1376
	 * @param int $calendar
1377
	 * @param int $month
1378
	 * @param int $year
1379
	 *
1380
	 * @return bool|string
1381
	 */
1382
	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...
1383
		return date( 't', mktime( 0, 0, 0, $month, 1, $year ) );
1384
	}
1385
}
1386
1387
/**
1388
 * Get plugin info including status, type, and license validation.
1389
 *
1390
 * This is an enhanced version of get_plugins() that returns the status
1391
 * (`active` or `inactive`) of all plugins, type of plugin (`add-on` or `other`
1392
 * and license validation for Give add-ons (`true` or `false`). Does not include
1393
 * MU plugins.
1394
 *
1395
 * @since 1.8.0
1396
 *
1397
 * @return array Plugin info plus status, type, and license validation if
1398
 *               available.
1399
 */
1400
function give_get_plugins() {
1401
	$plugins             = get_plugins();
1402
	$active_plugin_paths = (array) get_option( 'active_plugins', array() );
1403
1404
	if ( is_multisite() ) {
1405
		$network_activated_plugin_paths = array_keys( get_site_option( 'active_sitewide_plugins', array() ) );
1406
		$active_plugin_paths            = array_merge( $active_plugin_paths, $network_activated_plugin_paths );
1407
	}
1408
1409
	foreach ( $plugins as $plugin_path => $plugin_data ) {
1410
		// Is plugin active?
1411
		if ( in_array( $plugin_path, $active_plugin_paths ) ) {
1412
			$plugins[ $plugin_path ]['Status'] = 'active';
1413
		} else {
1414
			$plugins[ $plugin_path ]['Status'] = 'inactive';
1415
		}
1416
1417
		$dirname = strtolower( dirname( $plugin_path ) );
1418
1419
		// Is plugin a Give add-on by WordImpress?
1420
		if ( strstr( $dirname, 'give-' ) && strstr( $plugin_data['AuthorURI'], 'wordimpress.com' ) ) {
1421
			// Plugin is a Give-addon.
1422
			$plugins[ $plugin_path ]['Type'] = 'add-on';
1423
1424
			// Get license info from database.
1425
			$plugin_name    = str_replace( 'Give - ', '', $plugin_data['Name'] );
1426
			$db_option      = 'give_' . preg_replace( '/[^a-zA-Z0-9_\s]/', '', str_replace( ' ', '_', strtolower( $plugin_name ) ) ) . '_license_active';
1427
			$license_active = get_option( $db_option );
1428
1429
			// Does a valid license exist?
1430
			if ( ! empty( $license_active ) && 'valid' === $license_active->license ) {
1431
				$plugins[ $plugin_path ]['License'] = true;
1432
			} else {
1433
				$plugins[ $plugin_path ]['License'] = false;
1434
			}
1435
		} else {
1436
			// Plugin is not a Give add-on.
1437
			$plugins[ $plugin_path ]['Type'] = 'other';
1438
		}
1439
	}
1440
1441
	return $plugins;
1442
}
1443
1444
1445
/**
1446
 * Check if terms enabled or not for form.
1447
 *
1448
 * @since 1.8
1449
 *
1450
 * @param $form_id
1451
 *
1452
 * @return bool
1453
 */
1454
function give_is_terms_enabled( $form_id ) {
1455
	$form_option = give_get_meta( $form_id, '_give_terms_option', true );
1456
1457
	if (
1458
		give_is_setting_enabled( $form_option, 'global' )
1459
		&& give_is_setting_enabled( give_get_option( 'terms' ) )
1460
	) {
1461
		return true;
1462
1463
	} elseif ( give_is_setting_enabled( $form_option ) ) {
1464
		return true;
1465
1466
	} else {
1467
		return false;
1468
	}
1469
}
1470
1471
1472
/**
1473
 * Delete donation stats cache.
1474
 *
1475
 * @todo  Resolve stats cache key naming issue. Currently it is difficult to regenerate cache key.
1476
 *
1477
 * @since 1.8.7
1478
 *
1479
 * @param string|array $date_range Date for stats.
1480
 *                                 Date value should be in today, yesterday, this_week, last_week, this_month,
1481
 *                                 last_month, this_quarter, last_quarter, this_year, last_year. For date value other,
1482
 *                                 all cache will be removed.
1483
 *
1484
 * @param array        $args
1485
 *
1486
 * @return WP_Error|bool
1487
 */
1488
function give_delete_donation_stats( $date_range = '', $args = array() ) {
1489
	// Delete all cache.
1490
	$status = Give_Cache::delete( Give_Cache::get_options_like( 'give_stats' ) );
1491
1492
	/**
1493
	 * Fire the action when donation stats delete.
1494
	 *
1495
	 * @since 1.8.7
1496
	 *
1497
	 * @param string|array $date_range
1498
	 * @param array        $args
1499
	 */
1500
	do_action( 'give_delete_donation_stats', $status, $date_range, $args );
1501
1502
	return $status;
1503
}
1504
1505
1506
/**
1507
 * Get Form/Payment meta.
1508
 *
1509
 * @since 1.8.8
1510
 *
1511
 * @param int    $id
1512
 * @param string $meta_key
1513
 * @param bool   $single
1514
 * @param bool   $default
1515
 *
1516
 * @return mixed
1517
 */
1518
function give_get_meta( $id, $meta_key, $single = false, $default = false ) {
1519
	/**
1520
	 * Filter the meta value
1521
	 *
1522
	 * @since 1.8.8
1523
	 */
1524
	$meta_value = apply_filters(
1525
		'give_get_meta',
1526
		get_post_meta( $id, $meta_key, $single ),
1527
		$id,
1528
		$meta_key,
1529
		$default
1530
	);
1531
1532
	if (
1533
		( empty( $meta_key ) || empty( $meta_value ) )
1534
		&& $default
1535
	) {
1536
		$meta_value = $default;
1537
	}
1538
1539
	return $meta_value;
1540
}
1541
1542
/**
1543
 * Update Form/Payment meta.
1544
 *
1545
 * @since 1.8.8
1546
 *
1547
 * @param int    $id
1548
 * @param string $meta_key
1549
 * @param mixed  $meta_value
1550
 * @param mixed  $prev_value
1551
 *
1552
 * @return mixed
1553
 */
1554
function give_update_meta( $id, $meta_key, $meta_value, $prev_value = '' ) {
1555
	$status = update_post_meta( $id, $meta_key, $meta_value, $prev_value );
1556
1557
	/**
1558
	 * Filter the meta value update status
1559
	 *
1560
	 * @since 1.8.8
1561
	 */
1562
	return apply_filters( 'give_update_meta', $status, $id, $meta_key, $meta_value );
1563
}
1564
1565
/**
1566
 * Delete Form/Payment meta.
1567
 *
1568
 * @since 1.8.8
1569
 *
1570
 * @param int    $id
1571
 * @param string $meta_key
1572
 * @param string $meta_value
1573
 *
1574
 * @return mixed
1575
 */
1576
function give_delete_meta( $id, $meta_key, $meta_value = '' ) {
1577
	$status = delete_post_meta( $id, $meta_key, $meta_value );
1578
1579
	/**
1580
	 * Filter the meta value delete status
1581
	 *
1582
	 * @since 1.8.8
1583
	 */
1584
	return apply_filters( 'give_delete_meta', $status, $id, $meta_key, $meta_value );
1585
}
1586
1587
/**
1588
 * Check if the upgrade routine has been run for a specific action
1589
 *
1590
 * @since  1.0
1591
 *
1592
 * @param  string $upgrade_action The upgrade action to check completion for
1593
 *
1594
 * @return bool                   If the action has been added to the completed actions array
1595
 */
1596
function give_has_upgrade_completed( $upgrade_action = '' ) {
1597
1598
	if ( empty( $upgrade_action ) ) {
1599
		return false;
1600
	}
1601
1602
	$completed_upgrades = give_get_completed_upgrades();
1603
1604
	return in_array( $upgrade_action, $completed_upgrades );
1605
1606
}
1607
1608
/**
1609
 * For use when doing 'stepped' upgrade routines, to see if we need to start somewhere in the middle
1610
 *
1611
 * @since 1.8
1612
 *
1613
 * @return mixed   When nothing to resume returns false, otherwise starts the upgrade where it left off
1614
 */
1615
function give_maybe_resume_upgrade() {
1616
	$doing_upgrade = get_option( 'give_doing_upgrade', false );
1617
	if ( empty( $doing_upgrade ) ) {
1618
		return false;
1619
	}
1620
1621
	return $doing_upgrade;
1622
}
1623
1624
/**
1625
 * Adds an upgrade action to the completed upgrades array
1626
 *
1627
 * @since  1.0
1628
 *
1629
 * @param  string $upgrade_action The action to add to the completed upgrades array
1630
 *
1631
 * @return bool                   If the function was successfully added
1632
 */
1633
function give_set_upgrade_complete( $upgrade_action = '' ) {
1634
1635
	if ( empty( $upgrade_action ) ) {
1636
		return false;
1637
	}
1638
1639
	$completed_upgrades   = give_get_completed_upgrades();
1640
	$completed_upgrades[] = $upgrade_action;
1641
1642
	// Remove any blanks, and only show uniques.
1643
	$completed_upgrades = array_unique( array_values( $completed_upgrades ) );
1644
1645
	/**
1646
	 * Fire the action when any upgrade set to complete.
1647
	 *
1648
	 * @since 1.8.12
1649
	 */
1650
	do_action( 'give_set_upgrade_completed', $upgrade_action, $completed_upgrades );
1651
1652
	return update_option( 'give_completed_upgrades', $completed_upgrades );
1653
}
1654
1655
/**
1656
 * Get's the array of completed upgrade actions
1657
 *
1658
 * @since  1.0
1659
 * @return array The array of completed upgrades
1660
 */
1661
function give_get_completed_upgrades() {
1662
	return (array) get_option( 'give_completed_upgrades' );
1663
}
1664
1665
/**
1666
 * Remove the Give transaction pages from WP search results.
1667
 *
1668
 * @since 1.8.13
1669
 *
1670
 * @param \WP_Query
1671
 */
1672
function give_remove_pages_from_search( $query ) {
1673
	if ( ! $query->is_admin && $query->is_search && $query->is_main_query() ) {
1674
		$transaction_failed = give_get_option( 'failure_page', 0 );
1675
		$success_page       = give_get_option( 'success_page', 0 );
1676
		$args               = apply_filters(
1677
			'give_remove_pages_from_search', array(
1678
			$transaction_failed,
1679
			$success_page,
1680
		), $query
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 12 spaces, but found 8.
Loading history...
1681
		);
1682
		$query->set( 'post__not_in', $args );
1683
	}
1684
}
1685
1686
add_action( 'pre_get_posts', 'give_remove_pages_from_search', 10, 1 );
1687
1688
/**
1689
 * Inserts a new key/value before a key in the array.
1690
 *
1691
 * @since 1.8.13
1692
 *
1693
 * @param string       $key       The key to insert before.
1694
 * @param array        $array     An array to insert in to.
1695
 * @param string       $new_key   The key to insert.
1696
 * @param array|string $new_value An value to insert.
1697
 *
1698
 * @return array The new array if the key exists, the passed array otherwise.
1699
 *
1700
 * @see   array_insert_before()
1701
 */
1702 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...
1703
	if ( array_key_exists( $key, $array ) ) {
1704
		$new = array();
1705
		foreach ( $array as $k => $value ) {
1706
			if ( $k === $key ) {
1707
				$new[ $new_key ] = $new_value;
1708
			}
1709
			$new[ $k ] = $value;
1710
		}
1711
1712
		return $new;
1713
	}
1714
1715
	return $array;
1716
}
1717
1718
/**
1719
 * Inserts a new key/value after a key in the array.
1720
 *
1721
 * @since 1.8.13
1722
 *
1723
 * @param string       $key       The key to insert after.
1724
 * @param array        $array     An array to insert in to.
1725
 * @param string       $new_key   The key to insert.
1726
 * @param array|string $new_value An value to insert.
1727
 *
1728
 * @return array The new array if the key exists, the passed array otherwise.
1729
 *
1730
 * @see   array_insert_before()
1731
 */
1732 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...
1733
	if ( array_key_exists( $key, $array ) ) {
1734
		$new = array();
1735
		foreach ( $array as $k => $value ) {
1736
			$new[ $k ] = $value;
1737
			if ( $k === $key ) {
1738
				$new[ $new_key ] = $new_value;
1739
			}
1740
		}
1741
1742
		return $new;
1743
	}
1744
1745
	return $array;
1746
}
1747
1748
/**
1749
 * Pluck a certain field out of each object in a list.
1750
 *
1751
 * This has the same functionality and prototype of
1752
 * array_column() (PHP 5.5) but also supports objects.
1753
 *
1754
 * @since 1.8.13
1755
 *
1756
 * @param array      $list      List of objects or arrays
1757
 * @param int|string $field     Field from the object to place instead of the entire object
1758
 * @param int|string $index_key Optional. Field from the object to use as keys for the new array.
1759
 *                              Default null.
1760
 *
1761
 * @return array Array of found values. If `$index_key` is set, an array of found values with keys
1762
 *               corresponding to `$index_key`. If `$index_key` is null, array keys from the original
1763
 *               `$list` will be preserved in the results.
1764
 */
1765
function give_list_pluck( $list, $field, $index_key = null ) {
1766
1767
	if ( ! $index_key ) {
1768
		/*
1769
		 * This is simple. Could at some point wrap array_column()
1770
		 * if we knew we had an array of arrays.
1771
		 */
1772
		foreach ( $list as $key => $value ) {
1773
			if ( is_object( $value ) ) {
1774
				if ( isset( $value->$field ) ) {
1775
					$list[ $key ] = $value->$field;
1776
				}
1777
			} else {
1778
				if ( isset( $value[ $field ] ) ) {
1779
					$list[ $key ] = $value[ $field ];
1780
				}
1781
			}
1782
		}
1783
1784
		return $list;
1785
	}
1786
1787
	/*
1788
	 * When index_key is not set for a particular item, push the value
1789
	 * to the end of the stack. This is how array_column() behaves.
1790
	 */
1791
	$newlist = array();
1792
	foreach ( $list as $value ) {
1793
		if ( is_object( $value ) ) {
1794
			if ( isset( $value->$index_key ) ) {
1795
				$newlist[ $value->$index_key ] = $value->$field;
1796
			} else {
1797
				$newlist[] = $value->$field;
1798
			}
1799
		} else {
1800
			if ( isset( $value[ $index_key ] ) ) {
1801
				$newlist[ $value[ $index_key ] ] = $value[ $field ];
1802
			} else {
1803
				$newlist[] = $value[ $field ];
1804
			}
1805
		}
1806
	}
1807
1808
	$list = $newlist;
1809
1810
	return $list;
1811
}
1812
1813
/**
1814
 * Add meta data field to a donor.
1815
 *
1816
 * @since 1.8.13
1817
 *
1818
 * @param int    $donor_id   Donor ID.
1819
 * @param string $meta_key   Metadata name.
1820
 * @param mixed  $meta_value Metadata value. Must be serializable if non-scalar.
1821
 * @param bool   $unique     Optional. Whether the same key should not be added.
1822
 *                           Default false.
1823
 *
1824
 * @return int|false Meta ID on success, false on failure.
1825
 */
1826
function add_donor_meta( $donor_id, $meta_key, $meta_value, $unique = false ) {
1827
	return add_metadata( 'give_customer', $donor_id, $meta_key, $meta_value, $unique );
1828
}
1829
1830
/**
1831
 * Remove metadata matching criteria from a Donor meta.
1832
 *
1833
 * You can match based on the key, or key and value. Removing based on key and
1834
 * value, will keep from removing duplicate metadata with the same key. It also
1835
 * allows removing all metadata matching key, if needed.
1836
 *
1837
 * @since 1.8.13
1838
 *
1839
 * @param int    $donor_id   Donor ID
1840
 * @param string $meta_key   Metadata name.
1841
 * @param mixed  $meta_value Optional. Metadata value.
1842
 *
1843
 * @return bool True on success, false on failure.
1844
 */
1845
function delete_donor_meta( $donor_id, $meta_key, $meta_value = '' ) {
1846
	return delete_metadata( 'give_customer', $donor_id, $meta_key, $meta_value );
1847
}
1848
1849
/**
1850
 * Retrieve donor meta field for a donor meta table.
1851
 *
1852
 * @since 1.8.13
1853
 *
1854
 * @param int    $donor_id Donor ID.
1855
 * @param string $key      Optional. The meta key to retrieve. By default, returns data for all keys.
1856
 * @param bool   $single   Whether to return a single value.
1857
 *
1858
 * @return mixed Will be an array if $single is false. Will be value of meta data field if $single
1859
 *  is true.
1860
 */
1861
function get_donor_meta( $donor_id, $key = '', $single = false ) {
1862
	return get_metadata( 'give_customer', $donor_id, $key, $single );
1863
}
1864
1865
/**
1866
 * Update customer meta field based on Donor ID.
1867
 *
1868
 * If the meta field for the donor does not exist, it will be added.
1869
 *
1870
 * @since 1.8.13
1871
 *
1872
 * @param int    $donor_id   Donor ID.
1873
 * @param string $meta_key   Metadata key.
1874
 * @param mixed  $meta_value Metadata value.
1875
 * @param mixed  $prev_value Optional. Previous value to check before removing.
1876
 *
1877
 * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.
1878
 */
1879
function update_donor_meta( $donor_id, $meta_key, $meta_value, $prev_value = '' ) {
1880
	return update_metadata( 'give_customer', $donor_id, $meta_key, $meta_value, $prev_value );
1881
}
1882
1883
/*
1884
 * Give recalculate income and donation of the donation from ID
1885
 *
1886
 * @since 1.8.13
1887
 *
1888
 * @param int $form_id Form id of which recalculation needs to be done.
1889
 */
1890
function give_recount_form_income_donation( $form_id = false ) {
1891
	// Check if form id is not empty.
1892
	if ( ! empty( $form_id ) ) {
1893
		/**
1894
		 * Filter to modify payment status.
1895
		 *
1896
		 * @since 1.8.13
1897
		 */
1898
		$accepted_statuses = apply_filters( 'give_recount_accepted_statuses', array( 'publish' ) );
1899
1900
		/**
1901
		 * Filter to modify args of payment query before recalculating the form total
1902
		 *
1903
		 * @since 1.8.13
1904
		 */
1905
		$args = apply_filters(
1906
			'give_recount_form_stats_args', array(
1907
				'give_forms'     => $form_id,
1908
				'status'         => $accepted_statuses,
1909
				'posts_per_page' => - 1,
1910
				'fields'         => 'ids',
1911
			)
1912
		);
1913
1914
		$totals = array(
1915
			'sales'    => 0,
1916
			'earnings' => 0,
1917
		);
1918
1919
		$payments = new Give_Payments_Query( $args );
1920
		$payments = $payments->get_payments();
1921
1922
		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...
1923 View Code Duplication
			foreach ( $payments as $payment ) {
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...
1924
				// Ensure acceptible status only
1925
				if ( ! in_array( $payment->post_status, $accepted_statuses ) ) {
1926
					continue;
1927
				}
1928
1929
				// Ensure only payments for this form are counted
1930
				if ( $payment->form_id != $form_id ) {
1931
					continue;
1932
				}
1933
1934
				$totals['sales'] ++;
1935
				$totals['earnings'] += $payment->total;
1936
1937
			}
1938
		}
1939
		give_update_meta( $form_id, '_give_form_sales', $totals['sales'] );
1940
		give_update_meta( $form_id, '_give_form_earnings', give_sanitize_amount_for_db( $totals['earnings'] ) );
1941
	}// End if().
1942
}
1943
1944
/**
1945
 * Zero Decimal based Currency.
1946
 *
1947
 * @since 1.8.14
1948
 * @see   https://github.com/WordImpress/Give/issues/2191
1949
 *
1950
 * @param string $currency Currency code
1951
 *
1952
 * @return bool
1953
 */
1954
function give_is_zero_based_currency( $currency = '' ) {
1955
	$zero_based_currency = array(
1956
		'PYG', // Paraguayan Guarani.
1957
		'GNF', // Guinean Franc.
1958
		'RWF', // Rwandan Franc.
1959
		'JPY', // Japanese Yen.
1960
		'BIF', // Burundian Franc.
1961
		'KRW', // South Korean Won.
1962
		'MGA', // Malagasy Ariary.
1963
		'XAF', // Central African Cfa Franc.
1964
		'XPF', // Cfp Franc.
1965
		'CLP', // Chilean Peso.
1966
		'KMF', // Comorian Franc.
1967
		'DJF', // Djiboutian Franc.
1968
		'VUV', // Vanuatu Vatu.
1969
		'VND', // Vietnamese Dong.
1970
		'XOF', // West African Cfa Franc.
1971
	);
1972
1973
	// Set default currency.
1974
	if ( empty( $currency ) ) {
1975
		$currency = give_get_currency();
1976
	}
1977
1978
	// Check for Zero Based Currency.
1979
	if ( in_array( $currency, $zero_based_currency ) ) {
1980
		return true;
1981
	}
1982
1983
	return false;
1984
}
1985
1986
/**
1987
 * Get attribute string
1988
 *
1989
 * @since 1.8.17
1990
 *
1991
 * @param array $attributes
1992
 *
1993
 * @return string
1994
 */
1995
function give_get_attribute_str( $attributes ) {
1996
	$attribute_str = '';
1997
1998
	if ( empty( $attributes ) ) {
1999
		return $attribute_str;
2000
	}
2001
2002
	foreach ( $attributes as $tag => $value ) {
2003
		$attribute_str .= " {$tag}=\"{$value}\"";
2004
	}
2005
2006
	return trim( $attribute_str );
2007
}
2008
2009
/**
2010
 * Get the upload dir path
2011
 *
2012
 * @since 1.8.17
2013
 *
2014
 * @return string $wp_upload_dir;
2015
 */
2016
function give_get_wp_upload_dir() {
2017
	$wp_upload_dir = wp_upload_dir();
2018
2019
	return ( ! empty( $wp_upload_dir['path'] ) ? $wp_upload_dir['path'] : false );
2020
}
2021
2022
/**
2023
 * Get the data from uploaded JSON file
2024
 *
2025
 * @since 1.8.17
2026
 *
2027
 * @param string $file_name filename of the json file that is being uploaded
2028
 *
2029
 * @return string/bool $file_contents File content
0 ignored issues
show
Documentation introduced by
The doc-type string/bool could not be parsed: Unknown type name "string/bool" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
2030
 */
2031
function give_get_core_settings_json( $file_name ) {
2032
	$upload_dir = give_get_wp_upload_dir();
2033
	$file_path  = $upload_dir . '/' . $file_name;
2034
2035
	if ( is_wp_error( $file_path ) || empty( $file_path ) ) {
2036
		Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide a valid JSON file.', 'give' ) );
2037
	}
2038
2039
	$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...
2040
2041
	return $file_contents;
2042
}
2043