PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 2.3.2
GiveWP – Donation Plugin and Fundraising Platform v2.3.2
4.17.0 4.16.9 4.16.8.1 4.16.8 4.16.7.2 4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 All 256 releases
give / includes / misc-functions.php

misc-functions.php in GiveWP – Donation Plugin and Fundraising Platform 2.3.2, at includes/misc-functions.php

2,312 lines 103.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Misc Functions
4 *
5 * @package Give
6 * @subpackage Functions
7 * @copyright Copyright (c) 2016, GiveWP
8 * @license https://opensource.org/licenses/gpl-license GNU Public License
9 * @since 1.0
10 */
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 /**
18 * Is Test Mode Enabled.
19 *
20 * @since 1.0
21 *
22 * @return bool $ret True if return mode is enabled, false otherwise
23 */
24 function give_is_test_mode() {
25
26 $ret = give_is_setting_enabled( give_get_option( 'test_mode' ) );
27
28 return (bool) apply_filters( 'give_is_test_mode', $ret );
29
30 }
31
32 /**
33 * Get the current page URL.
34 *
35 * @since 1.0
36 * @return string $current_url Current page URL.
37 */
38 function give_get_current_page_url() {
39
40 global $wp;
41
42 if ( get_option( 'permalink_structure' ) ) {
43 $base = trailingslashit( home_url( $wp->request ) );
44 } else {
45 $base = add_query_arg( $wp->query_string, '', trailingslashit( home_url( $wp->request ) ) );
46 $base = remove_query_arg( array( 'post_type', 'name' ), $base );
47 }
48
49 $scheme = is_ssl() ? 'https' : 'http';
50 $current_uri = set_url_scheme( $base, $scheme );
51
52 if ( is_front_page() ) {
53 $current_uri = home_url( '/' );
54 }
55
56 /**
57 * Filter the current page url
58 *
59 * @since 1.0
60 *
61 * @param string $current_uri
62 */
63 return apply_filters( 'give_get_current_page_url', $current_uri );
64
65 }
66
67
68 /**
69 * Verify credit card numbers live?
70 *
71 * @since 1.0
72 *
73 * @return bool $ret True is verify credit cards is live
74 */
75 function give_is_cc_verify_enabled() {
76
77 $ret = true;
78
79 /**
80 * Enable if use a single gateway other than PayPal or Manual. We have to assume it accepts credit cards.
81 * Enable if using more than one gateway if they are not both PayPal and manual, again assuming credit card usage.
82 */
83 $gateways = give_get_enabled_payment_gateways();
84
85 if ( count( $gateways ) == 1 && ! isset( $gateways['paypal'] ) && ! isset( $gateways['manual'] ) ) {
86 $ret = true;
87 } elseif ( count( $gateways ) == 1 ) {
88 $ret = false;
89 } elseif ( count( $gateways ) == 2 && isset( $gateways['paypal'] ) && isset( $gateways['manual'] ) ) {
90 $ret = false;
91 }
92
93 /**
94 * Fire the filter
95 *
96 * @since 1.0
97 *
98 * @param bool $ret
99 */
100 return (bool) apply_filters( 'give_is_cc_verify_enabled', $ret );
101 }
102
103 /**
104 * Retrieve timezone.
105 *
106 * @since 1.0
107 * @return string $timezone The timezone ID.
108 */
109 function give_get_timezone_id() {
110
111 // if site timezone string exists, return it.
112 if ( $timezone = get_option( 'timezone_string' ) ) {
113 return $timezone;
114 }
115
116 // get UTC offset, if it isn't set return UTC.
117 if ( ! ( $utc_offset = 3600 * get_option( 'gmt_offset', 0 ) ) ) {
118 return 'UTC';
119 }
120
121 // attempt to guess the timezone string from the UTC offset.
122 $timezone = timezone_name_from_abbr( '', $utc_offset );
123
124 // last try, guess timezone string manually.
125 if ( $timezone === false ) {
126
127 $is_dst = date( 'I' );
128
129 foreach ( timezone_abbreviations_list() as $abbr ) {
130 foreach ( $abbr as $city ) {
131 if ( $city['dst'] == $is_dst && $city['offset'] == $utc_offset ) {
132 return $city['timezone_id'];
133 }
134 }
135 }
136 }
137
138 // Fallback.
139 return 'UTC';
140 }
141
142
143 /**
144 * Get User IP
145 *
146 * Returns the IP address of the current visitor
147 *
148 * @since 1.0
149 * @return string $ip User's IP address
150 */
151 function give_get_ip() {
152
153 $ip = '127.0.0.1';
154
155 if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
156 // check ip from share internet
157 $ip = $_SERVER['HTTP_CLIENT_IP'];
158 } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
159 // to check ip is pass from proxy
160 $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
161 } elseif ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) {
162 $ip = $_SERVER['REMOTE_ADDR'];
163 }
164
165 /**
166 * Filter the IP
167 *
168 * @since 1.0
169 */
170 $ip = apply_filters( 'give_get_ip', $ip );
171
172 // Filter empty values.
173 if ( false !== strpos( $ip, ',' ) ) {
174 $ip = give_clean( explode( ',', $ip ) );
175 $ip = array_filter( $ip );
176 $ip = implode( ',', $ip );
177 } else {
178 $ip = give_clean( $ip );
179 }
180
181 return $ip;
182 }
183
184
185 /**
186 * Store Donation Data in Sessions
187 *
188 * Used for storing info about donation
189 *
190 * @since 1.0
191 *
192 * @param $purchase_data
193 *
194 * @uses Give()->session->set()
195 */
196 function give_set_purchase_session( $purchase_data = array() ) {
197 Give()->session->set( 'give_purchase', $purchase_data );
198 Give()->session->set( 'give_email', $purchase_data['user_email'] );
199 }
200
201 /**
202 * Retrieve Donation Data from Session
203 *
204 * Used for retrieving info about donation
205 * after completing a donation
206 *
207 * @since 1.0
208 * @uses Give()->session->get()
209 * @return mixed array | false
210 */
211 function give_get_purchase_session() {
212 return Give()->session->get( 'give_purchase' );
213 }
214
215 /**
216 * Retrieve Payment Key of the Receipt Access Session.
217 *
218 * @since 1.8.17
219 *
220 * @return array|string
221 */
222 function give_get_receipt_session() {
223 return Give()->session->get( 'receipt_access' );
224 }
225
226 /**
227 * Retrieve Payment Key of the History Access Session.
228 *
229 * @since 1.8.17
230 *
231 * @return array|string
232 */
233 function give_get_history_session() {
234 return (bool) Give()->session->get( 'history_access' );
235 }
236
237 /**
238 * Generate Item Title for Payment Gateway.
239 *
240 * @param array $payment_data Payment Data.
241 *
242 * @since 1.8.14
243 *
244 * @return string By default, the name of the form. Then the price level text if any is found.
245 */
246 function give_payment_gateway_item_title( $payment_data ) {
247
248 $form_id = intval( $payment_data['post_data']['give-form-id'] );
249 $item_name = isset( $payment_data['post_data']['give-form-title'] ) ? $payment_data['post_data']['give-form-title'] : '';
250 $price_id = isset( $payment_data['post_data']['give-price-id'] ) ? $payment_data['post_data']['give-price-id'] : '';
251
252 // Verify has variable prices.
253 if ( give_has_variable_prices( $form_id ) && ! empty( $price_id ) ) {
254
255 $item_price_level_text = give_get_price_option_name( $form_id, $price_id, 0, false );
256
257 /**
258 * Output donation level text if:
259 *
260 * 1. It's not a custom amount
261 * 2. The level field has actual text and isn't the amount (which is already displayed on the receipt).
262 */
263 if ( 'custom' !== $price_id && ! empty( $item_price_level_text ) ) {
264 // Matches a donation level - append level text.
265 $item_name .= ' - ' . $item_price_level_text;
266 }
267 }
268
269 /**
270 * Filter the Item Title of Payment Gateway.
271 *
272 * @param string $item_name Item Title of Payment Gateway.
273 * @param int $form_id Donation Form ID.
274 * @param array $payment_data Payment Data.
275 *
276 * @since 1.8.14
277 *
278 * @return string
279 */
280 return apply_filters( 'give_payment_gateway_item_title', $item_name, $form_id, $payment_data );
281 }
282
283 /**
284 * Get Donation Summary
285 *
286 * Creates a donation summary for payment gateways from the donation data before the payment is created in the database.
287 *
288 * @since 1.8.12
289 *
290 * @param array $donation_data
291 * @param bool $name_and_email
292 * @param int $length
293 *
294 * @return string
295 */
296 function give_payment_gateway_donation_summary( $donation_data, $name_and_email = true, $length = 255 ) {
297
298 $form_id = isset( $donation_data['post_data']['give-form-id'] ) ? $donation_data['post_data']['give-form-id'] : '';
299 $price_id = isset( $donation_data['post_data']['give-price-id'] ) ? $donation_data['post_data']['give-price-id'] : '';
300
301 // Form title.
302 $summary = ( ! empty( $donation_data['post_data']['give-form-title'] ) ? $donation_data['post_data']['give-form-title'] : ( ! empty( $form_id ) ? wp_sprintf( __( 'Donation Form ID: %d', 'give' ), $form_id ) : __( 'Untitled donation form', 'give' ) ) );
303
304 // Form multilevel if applicable.
305 if ( ! empty( $price_id ) && 'custom' !== $price_id ) {
306 $summary .= ': ' . give_get_price_option_name( $form_id, $donation_data['post_data']['give-price-id'] );
307 }
308
309 // Add Donor's name + email if requested.
310 if ( $name_and_email ) {
311
312 // First name
313 if ( isset( $donation_data['user_info']['first_name'] ) && ! empty( $donation_data['user_info']['first_name'] ) ) {
314 $summary .= ' - ' . $donation_data['user_info']['first_name'];
315 }
316
317 if ( isset( $donation_data['user_info']['last_name'] ) && ! empty( $donation_data['user_info']['last_name'] ) ) {
318 $summary .= ' ' . $donation_data['user_info']['last_name'];
319 }
320
321 $summary .= ' (' . $donation_data['user_email'] . ')';
322 }
323
324 // Cut the length
325 $summary = substr( $summary, 0, $length );
326
327 return apply_filters( 'give_payment_gateway_donation_summary', $summary );
328 }
329
330
331 /**
332 * Get user host
333 *
334 * Returns the webhost this site is using if possible
335 *
336 * @since 1.0
337 * @return string $host if detected, false otherwise
338 */
339 function give_get_host() {
340 $host = false;
341
342 if ( defined( 'WPE_APIKEY' ) ) {
343 $host = 'WP Engine';
344 } elseif ( defined( 'PAGELYBIN' ) ) {
345 $host = 'Pagely';
346 } elseif ( DB_HOST == 'localhost:/tmp/mysql5.sock' ) {
347 $host = 'ICDSoft';
348 } elseif ( DB_HOST == 'mysqlv5' ) {
349 $host = 'NetworkSolutions';
350 } elseif ( strpos( DB_HOST, 'ipagemysql.com' ) !== false ) {
351 $host = 'iPage';
352 } elseif ( strpos( DB_HOST, 'ipowermysql.com' ) !== false ) {
353 $host = 'IPower';
354 } elseif ( strpos( DB_HOST, '.gridserver.com' ) !== false ) {
355 $host = 'MediaTemple Grid';
356 } elseif ( strpos( DB_HOST, '.pair.com' ) !== false ) {
357 $host = 'pair Networks';
358 } elseif ( strpos( DB_HOST, '.stabletransit.com' ) !== false ) {
359 $host = 'Rackspace Cloud';
360 } elseif ( strpos( DB_HOST, '.sysfix.eu' ) !== false ) {
361 $host = 'SysFix.eu Power Hosting';
362 } elseif ( strpos( $_SERVER['SERVER_NAME'], 'Flywheel' ) !== false ) {
363 $host = 'Flywheel';
364 } else {
365 // Adding a general fallback for data gathering
366 $host = 'DBH: ' . DB_HOST . ', SRV: ' . $_SERVER['SERVER_NAME'];
367 }
368
369 return $host;
370 }
371
372
373 /**
374 * Check site host
375 *
376 * @since 1.0
377 *
378 * @param bool /string $host The host to check
379 *
380 * @return bool true if host matches, false if not
381 */
382 function give_is_host( $host = false ) {
383
384 $return = false;
385
386 if ( $host ) {
387 $host = str_replace( ' ', '', strtolower( $host ) );
388
389 switch ( $host ) {
390 case 'wpengine':
391 if ( defined( 'WPE_APIKEY' ) ) {
392 $return = true;
393 }
394 break;
395 case 'pagely':
396 if ( defined( 'PAGELYBIN' ) ) {
397 $return = true;
398 }
399 break;
400 case 'icdsoft':
401 if ( DB_HOST == 'localhost:/tmp/mysql5.sock' ) {
402 $return = true;
403 }
404 break;
405 case 'networksolutions':
406 if ( DB_HOST == 'mysqlv5' ) {
407 $return = true;
408 }
409 break;
410 case 'ipage':
411 if ( strpos( DB_HOST, 'ipagemysql.com' ) !== false ) {
412 $return = true;
413 }
414 break;
415 case 'ipower':
416 if ( strpos( DB_HOST, 'ipowermysql.com' ) !== false ) {
417 $return = true;
418 }
419 break;
420 case 'mediatemplegrid':
421 if ( strpos( DB_HOST, '.gridserver.com' ) !== false ) {
422 $return = true;
423 }
424 break;
425 case 'pairnetworks':
426 if ( strpos( DB_HOST, '.pair.com' ) !== false ) {
427 $return = true;
428 }
429 break;
430 case 'rackspacecloud':
431 if ( strpos( DB_HOST, '.stabletransit.com' ) !== false ) {
432 $return = true;
433 }
434 break;
435 case 'sysfix.eu':
436 case 'sysfix.eupowerhosting':
437 if ( strpos( DB_HOST, '.sysfix.eu' ) !== false ) {
438 $return = true;
439 }
440 break;
441 case 'flywheel':
442 if ( strpos( $_SERVER['SERVER_NAME'], 'Flywheel' ) !== false ) {
443 $return = true;
444 }
445 break;
446 default:
447 $return = false;
448 }// End switch().
449 }// End if().
450
451 return $return;
452 }
453
454 /**
455 * Marks a function as deprecated and informs when it has been used.
456 *
457 * There is a hook give_deprecated_function_run that will be called that can be used
458 * to get the backtrace up to what file and function called the deprecated
459 * function.
460 *
461 * The current behavior is to trigger a user error if WP_DEBUG is true.
462 *
463 * This function is to be used in every function that is deprecated.
464 *
465 * @uses do_action() Calls 'give_deprecated_function_run' and passes the function name, what to use instead,
466 * and the version the function was deprecated in.
467 * @uses apply_filters() Calls 'give_deprecated_function_trigger_error' and expects boolean value of true to do
468 * trigger or false to not trigger error.
469 *
470 * @param string $function The function that was called.
471 * @param string $version The plugin version that deprecated the function.
472 * @param string $replacement Optional. The function that should have been called.
473 * @param array $backtrace Optional. Contains stack backtrace of deprecated function.
474 */
475 function _give_deprecated_function( $function, $version, $replacement = null, $backtrace = null ) {
476
477 /**
478 * Fires while give deprecated function call occurs.
479 *
480 * Allow you to hook to deprecated function call.
481 *
482 * @since 1.0
483 *
484 * @param string $function The function that was called.
485 * @param string $replacement Optional. The function that should have been called.
486 * @param string $version The plugin version that deprecated the function.
487 */
488 do_action( 'give_deprecated_function_run', $function, $replacement, $version );
489
490 $show_errors = current_user_can( 'manage_options' );
491
492 // Allow plugin to filter the output error trigger.
493 if ( WP_DEBUG && apply_filters( 'give_deprecated_function_trigger_error', $show_errors ) ) {
494 if ( ! is_null( $replacement ) ) {
495 trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since Give version %2$s! Use %3$s instead.', 'give' ), $function, $version, $replacement ) );
496 trigger_error( print_r( $backtrace, 1 ) ); // Limited to previous 1028 characters, but since we only need to move back 1 in stack that should be fine.
497 // Alternatively we could dump this to a file.
498 } else {
499 trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since Give version %2$s with no alternative available.', 'give' ), $function, $version ) );
500 trigger_error( print_r( $backtrace, 1 ) );// Limited to previous 1028 characters, but since we only need to move back 1 in stack that should be fine.
501 // Alternatively we could dump this to a file.
502 }
503 }
504 }
505
506 /**
507 * Give Get Admin ID
508 *
509 * Helper function to return the ID of the post for admin usage
510 *
511 * @return string $post_id
512 */
513 function give_get_admin_post_id() {
514 $post_id = isset( $_REQUEST['post'] ) ? absint( $_REQUEST['post'] ) : null;
515
516 $post_id = ! empty( $post_id ) ? $post_id : ( isset( $_REQUEST['post_id'] ) ? absint( $_REQUEST['post_id'] ) : null );
517
518 $post_id = ! empty( $post_id ) ? $post_id : ( isset( $_REQUEST['post_ID'] ) ? absint( $_REQUEST['post_ID'] ) : null );
519
520 return $post_id;
521 }
522
523 /**
524 * Get PHP Arg Separator Output
525 *
526 * @since 1.0
527 * @return string Arg separator output
528 */
529 function give_get_php_arg_separator_output() {
530 return ini_get( 'arg_separator.output' );
531 }
532
533
534 /**
535 * Month Num To Name
536 *
537 * Takes a month number and returns the name three letter name of it.
538 *
539 * @since 1.0
540 *
541 * @param int $n
542 *
543 * @return string Short month name
544 */
545 function give_month_num_to_name( $n ) {
546 $timestamp = mktime( 0, 0, 0, $n, 1, 2005 );
547
548 return date_i18n( 'M', $timestamp );
549 }
550
551
552 /**
553 * Checks whether function is disabled.
554 *
555 * @since 1.0
556 *
557 * @param string $function Name of the function.
558 *
559 * @return bool Whether or not function is disabled.
560 */
561 function give_is_func_disabled( $function ) {
562 $disabled = explode( ',', ini_get( 'disable_functions' ) );
563
564 return in_array( $function, $disabled );
565 }
566
567 /**
568 * Give Newsletter
569 *
570 * Returns the main Give newsletter form
571 */
572 function give_get_newsletter() {
573 ?>
574
575 <p class="newsletter-intro"><?php esc_html_e( 'Be sure to sign up for the Give newsletter below to stay informed of important updates and news.', 'give' ); ?></p>
576
577 <div class="give-newsletter-form-wrap">
578
579 <form action="//givewp.us3.list-manage.com/subscribe/post?u=3ccb75d68bda4381e2f45794c&amp;id=12a081aa13"
580 method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate"
581 target="_blank">
582 <div class="give-newsletter-confirmation">
583 <p><?php esc_html_e( 'To complete your subscription, click the confirmation link in your email. Thank you!', 'give' ); ?></p>
584 </div>
585
586 <table class="form-table give-newsletter-form">
587 <tr valign="middle">
588 <td>
589 <label for="mce-EMAIL"
590 class="screen-reader-text"><?php esc_html_e( 'Email Address (required)', 'give' ); ?></label>
591 <input type="email" name="EMAIL" id="mce-EMAIL"
592 placeholder="<?php esc_attr_e( 'Email Address (required)', 'give' ); ?>"
593 class="required email" value="" required>
594 </td>
595 <td>
596 <label for="mce-FNAME"
597 class="screen-reader-text"><?php esc_html_e( 'First Name', 'give' ); ?></label>
598 <input type="text" name="FNAME" id="mce-FNAME"
599 placeholder="<?php esc_attr_e( 'First Name', 'give' ); ?>" class="" value="" required>
600 </td>
601 <td>
602 <label for="mce-LNAME"
603 class="screen-reader-text"><?php esc_html_e( 'Last Name', 'give' ); ?></label>
604 <input type="text" name="LNAME" id="mce-LNAME"
605 placeholder="<?php esc_attr_e( 'Last Name', 'give' ); ?>" class="" value="">
606 </td>
607 <td>
608 <input type="submit" name="subscribe" id="mc-embedded-subscribe" class="button"
609 value="<?php esc_attr_e( 'Subscribe', 'give' ); ?>">
610 </td>
611 </tr>
612 </table>
613 </form>
614
615 <div style="position: absolute; left: -5000px;">
616 <input type="text" name="b_3ccb75d68bda4381e2f45794c_12a081aa13" tabindex="-1" value="">
617 </div>
618
619 </div>
620
621 <script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'></script>
622 <script type='text/javascript'>(
623 function ( $ ) {
624 window.fnames = new Array();
625 window.ftypes = new Array();
626 fnames[0] = 'EMAIL';
627 ftypes[0] = 'email';
628 fnames[1] = 'FNAME';
629 ftypes[1] = 'text';
630 fnames[2] = 'LNAME';
631 ftypes[2] = 'text';
632
633 $( 'form[name="mc-embedded-subscribe-form"]' ).removeAttr( 'novalidate' );
634
635 //Successful submission
636 $( 'form[name="mc-embedded-subscribe-form"]' ).on( 'submit', function () {
637
638 var email_field = $( this ).find( '#mce-EMAIL' ).val();
639 if ( ! email_field ) {
640 return false;
641 }
642 $( this ).find( '.give-newsletter-confirmation' ).show().delay( 5000 ).slideUp();
643 $( this ).find( '.give-newsletter-form' ).hide();
644
645 } );
646
647 }( jQuery )
648 );
649 var $mcj = jQuery.noConflict( true );
650
651
652 </script>
653 <!--End mc_embed_signup-->
654
655 <?php
656 }
657
658
659 /**
660 * Create SVG library function
661 *
662 * @param string $icon
663 *
664 * @return string
665 */
666 function give_svg_icons( $icon ) {
667
668 // Store your SVGs in an associative array
669 $svgs = array(
670 'microphone' => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE2LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgd2lkdGg9IjY0cHgiIGhlaWdodD0iMTAwcHgiIHZpZXdCb3g9IjAgLTIwIDY0IDEyMCIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNjQgMTAwOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8Zz4NCgk8Zz4NCgkJPHBhdGggZD0iTTYyLDM2LjIxNWgtM2MtMS4xLDAtMiwwLjktMiwyVjUyYzAsNi42ODYtNS4yNjYsMTgtMjUsMThTNyw1OC42ODYsNyw1MlYzOC4yMTVjMC0xLjEtMC45LTItMi0ySDJjLTEuMSwwLTIsMC45LTIsMlY1Mg0KCQkJYzAsMTEuMTg0LDguMjE1LDIzLjE1MiwyNywyNC44MDFWOTBIMTRjLTEuMSwwLTIsMC44OTgtMiwydjZjMCwxLjEsMC45LDIsMiwyaDM2YzEuMSwwLDItMC45LDItMnYtNmMwLTEuMTAyLTAuOS0yLTItMkgzN1Y3Ni44MDENCgkJCUM1NS43ODUsNzUuMTUyLDY0LDYzLjE4NCw2NCw1MlYzOC4yMTVDNjQsMzcuMTE1LDYzLjEsMzYuMjE1LDYyLDM2LjIxNXoiLz4NCgkJPHBhdGggZD0iTTMyLDYwYzExLjczMiwwLDE1LTQuODE4LDE1LThWMzYuMjE1SDE3VjUyQzE3LDU1LjE4MiwyMC4yNjYsNjAsMzIsNjB6Ii8+DQoJCTxwYXRoIGQ9Ik00Nyw4YzAtMy4xODQtMy4yNjgtOC0xNS04QzIwLjI2NiwwLDE3LDQuODE2LDE3LDh2MjEuMjE1aDMwVjh6Ii8+DQoJPC9nPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPC9zdmc+DQo=',
671 'alert' => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE2LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgd2lkdGg9IjI4LjkzOHB4IiBoZWlnaHQ9IjI1LjAwNXB4IiB2aWV3Qm94PSIwIDAgMjguOTM4IDI1LjAwNSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMjguOTM4IDI1LjAwNTsiDQoJIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPHBhdGggc3R5bGU9ImZpbGw6IzAwMDAwMDsiIGQ9Ik0yOC44NTksMjQuMTU4TDE0Ljk1NywwLjI3OUMxNC44NTYsMC4xMDYsMTQuNjcsMCwxNC40NjgsMGMtMC4xOTgsMC0wLjM4MywwLjEwNi0wLjQ4MSwwLjI3OQ0KCUwwLjA3OSwyNC4xNThjLTAuMTAyLDAuMTc1LTAuMTA2LDAuMzg5LTAuMDA2LDAuNTY1YzAuMTAzLDAuMTc0LDAuMjg3LDAuMjgyLDAuNDg4LDAuMjgyaDI3LjgxNGMwLjIwMSwwLDAuMzg5LTAuMTA4LDAuNDg4LTAuMjgyDQoJYzAuMDQ3LTAuMDg4LDAuMDc0LTAuMTg2LDAuMDc0LTAuMjgxQzI4LjkzOCwyNC4zNDMsMjguOTExLDI0LjI0NSwyOC44NTksMjQuMTU4eiBNMTYuMzY5LDguNDc1bC0wLjQ2Miw5LjQ5M2gtMi4zODlsLTAuNDYxLTkuNDkzDQoJSDE2LjM2OXogTTE0LjcxMSwyMi44MjhoLTAuMDQyYy0xLjA4OSwwLTEuODQzLTAuODE3LTEuODQzLTEuOTA3YzAtMS4xMzEsMC43NzQtMS45MDcsMS44ODUtMS45MDdzMS44NDYsMC43NzUsMS44NjcsMS45MDcNCglDMTYuNTc5LDIyLjAxMSwxNS44NDQsMjIuODI4LDE0LjcxMSwyMi44Mjh6Ii8+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8L3N2Zz4NCg==',
672 'placemark' => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxNi4wLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB3aWR0aD0iMTAwcHgiIGhlaWdodD0iMTAwcHgiIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMDAgMTAwIiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxnPg0KCTxwYXRoIGQ9Ik01MC40MzQsMjAuMjcxYy0xMi40OTksMC0yMi42NjgsMTAuMTY5LTIyLjY2OCwyMi42NjhjMCwxMS44MTQsMTguODE1LDMyLjE1NSwyMC45NiwzNC40MzdsMS43MDgsMS44MTZsMS43MDgtMS44MTYNCgkJYzIuMTQ1LTIuMjgxLDIwLjk2LTIyLjYyMywyMC45Ni0zNC40MzdDNzMuMTAzLDMwLjQ0LDYyLjkzNCwyMC4yNzEsNTAuNDM0LDIwLjI3MXogTTUwLjQzNCw1Mi4zMmMtNS4xNzIsMC05LjM4LTQuMjA4LTkuMzgtOS4zOA0KCQlzNC4yMDgtOS4zOCw5LjM4LTkuMzhjNS4xNzMsMCw5LjM4LDQuMjA4LDkuMzgsOS4zOFM1NS42MDcsNTIuMzIsNTAuNDM0LDUyLjMyeiIvPg0KPC9nPg0KPC9zdmc+DQo=',
673 'give_grey' => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiIHZpZXdCb3g9IjEwMC4xIDAgNDAwIDQwMCIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAxMDAuMSAwIDQwMCA0MDAiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxnIGlkPSJMYXllcl8xXzFfIj48Y2lyY2xlIGZpbGw9IiM2NkJCNkEiIGN4PSItNDA3LjMiIGN5PSIzNDYuMyIgcj0iNDIuMiIvPjxnPjxnPjxwYXRoIGZpbGw9IiM1NDZFN0EiIGQ9Ik0tNzg2LjQsMTMzLjh2LTEyLjVoNC44YzMuOCwwLDYuNiwyLjUsNi42LDYuNHMtMi44LDYuNC02LjYsNi40aC00LjhWMTMzLjh6IE0tNzc3LjUsMTI3LjVjMC0yLjMtMS4zLTMuOC0zLjgtMy44aC0yLjN2Ny45aDIuM0MtNzc5LDEzMS42LTc3Ny41LDEyOS44LTc3Ny41LDEyNy41eiIvPjxwYXRoIGZpbGw9IiM1NDZFN0EiIGQ9Ik0tNzcxLjYsMTMzLjh2LTEyLjVoOC45djIuM2gtNi4xdjIuNWg2LjF2Mi4zaC02LjF2Mi44aDYuMXYyLjNoLTguOVYxMzMuOHoiLz48cGF0aCBmaWxsPSIjNTQ2RTdBIiBkPSJNLTc0OC41LDEzMy44di04LjdsLTMuNiw4LjdoLTEuM2wtMy42LTguN3Y4LjdoLTIuNXYtMTIuNWgzLjhsMy4xLDcuNmwzLjEtNy42aDMuOHYxMi41SC03NDguNXoiLz48cGF0aCBmaWxsPSIjNTQ2RTdBIiBkPSJNLTc0Mi40LDEyNy41YzAtMy44LDIuOC02LjQsNi42LTYuNHM2LjYsMi44LDYuNiw2LjRjMCwzLjgtMi44LDYuNC02LjYsNi40Qy03MzkuOCwxMzQuMS03NDIuNCwxMzEuMy03NDIuNCwxMjcuNXogTS03MzIuMiwxMjcuNWMwLTIuMy0xLjUtNC4xLTMuOC00LjFjLTIuMywwLTMuOCwxLjgtMy44LDQuMWMwLDIuMywxLjUsNC4xLDMuOCw0LjFDLTczMy43LDEzMS42LTczMi4yLDEyOS44LTczMi4yLDEyNy41eiIvPjxwYXRoIGZpbGw9IiM1NDZFN0EiIGQ9Ik0tNzI2LjgsMTI3LjVjMC0zLjgsMi44LTYuNCw2LjYtNi40YzIuOCwwLDQuMywxLjUsNS4zLDMuMWwtMi4zLDFjLTAuNS0xLTEuNS0xLjgtMy4xLTEuOGMtMi4zLDAtMy44LDEuOC0zLjgsNC4xYzAsMi4zLDEuNSw0LjEsMy44LDQuMWMxLjMsMCwyLjMtMC44LDMuMS0xLjhsMi4zLDFjLTEsMS41LTIuNSwzLjEtNS4zLDMuMUMtNzIzLjgsMTM0LjEtNzI2LjgsMTMxLjMtNzI2LjgsMTI3LjV6Ii8+PHBhdGggZmlsbD0iIzU0NkU3QSIgZD0iTS03MDQuNywxMzMuOGwtMi41LTQuM2gtMnY0LjNoLTIuNXYtMTIuNWg1LjljMi41LDAsNC4xLDEuOCw0LjEsNC4xYzAsMi4zLTEuMywzLjMtMi44LDMuOGwyLjgsNC44aC0yLjhWMTMzLjh6IE0tNzA0LjUsMTI1LjJjMC0xLTAuOC0xLjgtMS44LTEuOGgtMi44djMuM2gyLjhDLTcwNS41LDEyNy03MDQuNSwxMjYuNS03MDQuNSwxMjUuMnoiLz48cGF0aCBmaWxsPSIjNTQ2RTdBIiBkPSJNLTY4OS43LDEzMy44bC0wLjgtMmgtNS4zbC0wLjgsMmgtMy4xbDQuOC0xMi41aDMuM2w0LjgsMTIuNUgtNjg5Ljd6IE0tNjkzLjMsMTIzLjlsLTIsNS4zaDMuOEwtNjkzLjMsMTIzLjl6Ii8+PHBhdGggZmlsbD0iIzU0NkU3QSIgZD0iTS02ODIuNiwxMzMuOHYtMTAuMmgtMy42di0yLjNoOS45djIuM2gtMy42djEwLjJILTY4Mi42eiIvPjxwYXRoIGZpbGw9IiM1NDZFN0EiIGQ9Ik0tNjczLjIsMTMzLjh2LTEyLjVoMi41djEyLjVILTY3My4yeiIvPjxwYXRoIGZpbGw9IiM1NDZFN0EiIGQ9Ik0tNjY3LDEzMy44di0ybDUuOS03LjloLTUuOXYtMi4zaDkuNHYybC01LjksOC4xaDYuMXYyLjNoLTkuN1YxMzMuOHoiLz48cGF0aCBmaWxsPSIjNTQ2RTdBIiBkPSJNLTY1NC4xLDEzMy44di0xMi41aDIuNXYxMi41SC02NTQuMXoiLz48cGF0aCBmaWxsPSIjNTQ2RTdBIiBkPSJNLTYzOS4xLDEzMy44bC01LjktOC4xdjguMWgtMi41di0xMi41aDIuOGw1LjksNy45di03LjloMi41djEyLjVILTYzOS4xeiIvPjxwYXRoIGZpbGw9IiM1NDZFN0EiIGQ9Ik0tNjMzLjIsMTI3LjVjMC00LjEsMy4xLTYuNCw2LjYtNi40YzIuNSwwLDQuMywxLjMsNS4xLDIuOGwtMi4zLDEuM2MtMC41LTAuOC0xLjUtMS41LTMuMS0xLjVjLTIuMywwLTMuOCwxLjgtMy44LDQuMWMwLDIuMywxLjUsNC4xLDMuOCw0LjFjMSwwLDItMC41LDIuNS0xdi0xLjVoLTMuM1YxMjdoNS45djQuOGMtMS4zLDEuNS0zLjEsMi4zLTUuMywyLjNDLTYzMC4yLDEzNC4xLTYzMy4yLDEzMS42LTYzMy4yLDEyNy41eiIvPjxwYXRoIGZpbGw9IiM1NDZFN0EiIGQ9Ik0tNjEyLjEsMTI3LjVjMC00LjEsMy4xLTYuNCw2LjYtNi40YzIuNSwwLDQuMywxLjMsNS4xLDIuOGwtMi4zLDEuM2MtMC41LTAuOC0xLjUtMS41LTMuMS0xLjVjLTIuMywwLTMuOCwxLjgtMy44LDQuMWMwLDIuMywxLjUsNC4xLDMuOCw0LjFjMSwwLDItMC41LDIuNS0xdi0xLjVoLTMuM1YxMjdoNS45djQuOGMtMS4zLDEuNS0zLjEsMi4zLTUuMywyLjNDLTYwOSwxMzQuMS02MTIuMSwxMzEuNi02MTIuMSwxMjcuNXoiLz48cGF0aCBmaWxsPSIjNTQ2RTdBIiBkPSJNLTU5Ni42LDEzMy44di0xMi41aDguOXYyLjNoLTYuMXYyLjVoNi4xdjIuM2gtNi4xdjIuOGg2LjF2Mi4zaC04LjlWMTMzLjh6Ii8+PHBhdGggZmlsbD0iIzU0NkU3QSIgZD0iTS01NzUuNywxMzMuOGwtNS45LTguMXY4LjFoLTIuNXYtMTIuNWgyLjhsNS45LDcuOXYtNy45aDIuNXYxMi41SC01NzUuN3oiLz48cGF0aCBmaWxsPSIjNTQ2RTdBIiBkPSJNLTU2OS4xLDEzMy44di0xMi41aDguOXYyLjNoLTYuMXYyLjVoNi4xdjIuM2gtNi4xdjIuOGg2LjF2Mi4zaC04LjlWMTMzLjh6Ii8+PHBhdGggZmlsbD0iIzU0NkU3QSIgZD0iTS01NDkuNywxMzMuOGwtMi41LTQuM2gtMnY0LjNoLTIuNXYtMTIuNWg1LjljMi41LDAsNC4xLDEuOCw0LjEsNC4xYzAsMi4zLTEuMywzLjMtMi44LDMuOGwyLjgsNC44aC0yLjhWMTMzLjh6IE0tNTQ5LjUsMTI1LjJjMC0xLTAuOC0xLjgtMS44LTEuOGgtMi44djMuM2gyLjhDLTU1MC4zLDEyNy01NDkuNSwxMjYuNS01NDkuNSwxMjUuMnoiLz48cGF0aCBmaWxsPSIjNTQ2RTdBIiBkPSJNLTU0My45LDEyNy41YzAtMy44LDIuOC02LjQsNi42LTYuNHM2LjYsMi44LDYuNiw2LjRjMCwzLjgtMi44LDYuNC02LjYsNi40Qy01NDEuMywxMzQuMS01NDMuOSwxMzEuMy01NDMuOSwxMjcuNXogTS01MzMuNywxMjcuNWMwLTIuMy0xLjUtNC4xLTMuOC00LjFzLTMuOCwxLjgtMy44LDQuMWMwLDIuMywxLjUsNC4xLDMuOCw0LjFDLTUzNS4yLDEzMS42LTUzMy43LDEyOS44LTUzMy43LDEyNy41eiIvPjxwYXRoIGZpbGw9IiM1NDZFN0EiIGQ9Ik0tNTI4LjYsMTMyLjFsMS41LTJjMC44LDEsMi4zLDEuOCw0LjEsMS44YzEuNSwwLDIuMy0wLjgsMi4zLTEuM2MwLTIuMy03LjEtMC44LTcuMS01LjNjMC0yLDEuOC0zLjgsNC44LTMuOGMyLDAsMy42LDAuNSw0LjgsMS44bC0xLjUsMmMtMS0xLTIuMy0xLjMtMy42LTEuM2MtMSwwLTEuOCwwLjUtMS44LDEuM2MwLDIsNy4xLDAuOCw3LjEsNS4zYzAsMi4zLTEuNSw0LjEtNS4xLDQuMUMtNTI1LjYsMTM0LjEtNTI3LjQsMTMzLjEtNTI4LjYsMTMyLjF6Ii8+PHBhdGggZmlsbD0iIzU0NkU3QSIgZD0iTS01MTUuMSwxMzMuOHYtMTIuNWgyLjV2MTIuNUgtNTE1LjF6Ii8+PHBhdGggZmlsbD0iIzU0NkU3QSIgZD0iTS01MDUuNywxMzMuOHYtMTAuMmgtMy42di0yLjNoOS45djIuM2gtMy42djEwLjJILTUwNS43eiIvPjxwYXRoIGZpbGw9IiM1NDZFN0EiIGQ9Ik0tNDkyLjcsMTMzLjh2LTUuMWwtNC44LTcuNGgzLjFsMy4xLDUuMWwzLjEtNS4xaDMuMWwtNC44LDcuNHY1LjFILTQ5Mi43eiIvPjwvZz48Zz48Zz48cGF0aCBmaWxsPSIjNjZCQjZBIiBkPSJNLTQ4NS45LDQ0LjNoLTEuM2wwLjMsMS4zYzIsOS45LDAuMywyNC43LTcuNCwzMy44Yy00LjMsNS4zLTkuOSw4LjEtMTYuOCw4LjFjLTEwLjksMC0xNS0xMy0xNS41LTI3LjdjMTcuOC00LjMsMjkuOC0xNS41LDI5LjgtMjguNWMwLTkuNC0yLjgtMjQuOS0yMS40LTI0LjljLTE3LjYsMC0yNi41LDI2LjItMjguMiw0NC41Yy04LjktMC4zLTE1LjUtNC4zLTE5LjYtOC4xYzEuNS02LjQsMi4zLTEyLjIsMi4zLTE3LjZjMC03LjQtNS4xLTEwLjctOS45LTEwLjdjLTYuOSwwLTE0LDYuNi0xNCwxOS4zYzAsNy42LDIuOCwxNCw4LjcsMTguNmMtNS4xLDEyLTEzLjcsMjIuMS0xNi41LDI1LjRjLTIuMy00LjgtOS43LTIyLjQtMTItNDEuNWMyLjgtNy42LDQuMy0xNCw0LjMtMTdjMC00LjgtMy4xLTcuNi04LjEtNy42Yy02LjksMC0xNy44LDQuMy0xOC4xLDQuNmwtMC41LDAuM3YwLjhjMCwwLjMsMy4zLDE1LjUsNi42LDMyLjNjLTYuNCwxMC40LTE3LjYsMjcuNy0yMy4yLDI3LjdjLTEwLjIsMCw2LjYtNTIuMi0wLjgtNTMuOWMtMC4zLDAtMC41LDAtMC44LDAuM2MtMy42LDIuMy00My41LDI0LjQtOTYuNywyNC40YzAsMCwwLDEsMC41LDJjMC4zLDAuOCwxLDEuNSwxLDEuNWMxNSwxLjgsMzYuNC0wLjMsNTIuNy0yLjVjLTkuNCwyMC4xLTI2LDMzLjMtNDEuMiwzMy4zYy0yOC44LDAtNTAuOS0zNC45LTUwLjktMzQuOWM4LjktNy45LDIzLjQtMzMuMyw0NC44LTMzLjNjMjEuMSwwLDMwLjMsMTEuNywzMC4zLDExLjdsMi4zLTMuOGMwLDAtOS45LTM0LjYtMzcuOS0zNC42cy01Ny44LDQ1LjgtNzUuMSw1Ni41YzAsMCwyMy45LDU2LjUsNzYuMSw1Ni41YzQzLjgsMCw1NS00Miw1Ny01Mi4yYzEwLjctMS41LDE4LjEtMy4xLDE4LjEtMy4xcy0yLjgsMjEuNC0yLjgsMzAuM3M5LjksMTguMywxOC4xLDE4LjNjNi45LDAsMjAuOS0xNC4yLDMxLTMxLjZsMC41LDJjNS4zLDE5LjYsMTIsMjkuOCwxOS44LDI5LjhjNy45LDAsMjAuOS0xNi4zLDI5LjMtMzYuOWM4LjQsMy42LDE4LjMsNC42LDI0LjIsNC44YzIuMywzNS40LDMxLjgsMzYuNCwzNS40LDM2LjRjMjEuOSwwLDQwLjUtMTUuOCw0MC41LTM0LjRDLTQ3MC42LDQ0LjUtNDg1LjYsNDQuMy00ODUuOSw0NC4zeiBNLTUxMi42LDI5LjVjMCwwLTAuMywxMS43LTEzLjUsMTcuNmMxLjMtMTUuNSw1LjEtMjkuNSw3LjYtMjkuNUMtNTE1LjYsMTcuOC01MTIuNiwyMi4xLTUxMi42LDI5LjV6Ii8+PHBhdGggZmlsbD0iIzY2QkI2QSIgZD0iTS02NjUsMTUuNWMwLDAuNSwwLjMsMC44LDAuOCwxYzEwLjQsMS41LDE3LjMtMS44LDE3LjMtMTguNmMwLTE1LjgtMTYuMy0zLjMtMTkuMy0xYy0wLjMsMC4zLTAuMywwLjUtMC4zLDFDLTY2My43LDQuMS02NjQuOCwxMy02NjUsMTUuNXoiLz48L2c+PGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8xXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMjg5LjU4NjQiIHkxPSIzNzMuMjM3OSIgeDI9Ii0yODIuODg0MiIgeTI9IjM3NS40NzE5IiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDIuNTQ0NSAwIDAgLTIuNTQ0NSAxMDAuMTI3MiAxMDE3LjgxMTcpIj48c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+PHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzM3OEY0MyIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCNTVkdJRF8xXykiIGQ9Ik0tNjIzLDQ5LjRjLTQuMSw2LjktMTAuMiwxNi4zLTE1LjUsMjIuMWMxLjMsMy4xLDIuOCw2LjksNC4zLDkuOWM0LjgtNS4zLDkuNy0xMi4yLDE0LTE5LjNMLTYyMyw0OS40eiIvPjxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfMl8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTI2OS4wNTc3IiB5MT0iMzcxLjU0NDEiIHgyPSItMjY1LjE3MDUiIHkyPSIzNzguMzgwMiIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgyLjU0NDUgMCAwIC0yLjU0NDUgMTAwLjEyNzIgMTAxNy44MTE3KSI+PHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPjxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz48L2xpbmVhckdyYWRpZW50PjxwYXRoIGZpbGw9InVybCgjU1ZHSURfMl8pIiBkPSJNLTU3NC43LDU0LjdjLTItMS0zLjgtMi41LTMuOC0yLjVjLTMuNiw3LjktOC40LDE1LjMtMTIuMiwyMC4xYzEuOCwyLjUsNC44LDUuOSw3LjEsOC40YzQuNi02LjQsOS40LTE0LjgsMTMtMjMuN0MtNTcwLjQsNTYuNy01NzIuNiw1Ni01NzQuNyw1NC43eiIvPjxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfM18iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTI0OC42NDE2IiB5MT0iMzY4LjM4MzUiIHgyPSItMjQ5LjQ0NTkiIHkyPSIzNzUuNTMyMyIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgyLjU0NDUgMCAwIC0yLjU0NDUgMTAwLjEyNzIgMTAxNy44MTE3KSI+PHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPjxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz48L2xpbmVhckdyYWRpZW50PjxwYXRoIGZpbGw9InVybCgjU1ZHSURfM18pIiBkPSJNLTUyNi4zLDU5LjhjMCwwLTUuMSwxLTEwLjIsMS41cy05LjksMC4zLTkuOSwwLjNjMC44LDEwLjIsMy42LDE3LjMsNy40LDIyLjZsMTguNi0xLjVDLTUyNC4zLDc3LjYtNTI2LjEsNjktNTI2LjMsNTkuOHoiLz48bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzRfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ii0yNDkuOCIgeTE9IjM4My41ODEiIHgyPSItMjQ5LjgiIHkyPSIzNzYuMzc2MyIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgyLjU0NDUgMCAwIC0yLjU0NDUgMTAwLjEyNzIgMTAxNy44MTE3KSI+PHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPjxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz48L2xpbmVhckdyYWRpZW50PjxwYXRoIGZpbGw9InVybCgjU1ZHSURfNF8pIiBkPSJNLTU0MS4xLDI4LjhMLTU0MS4xLDI4LjhjLTAuNSwxLjUtMS4zLDMuMy0xLjgsNS4xYzAsMC41LTAuMywwLjgtMC4zLDEuM2MtMSwzLjMtMS44LDYuNi0yLjMsOS45YzAsMC41LTAuMywwLjgtMC4zLDEuM2MtMC4zLDEuNS0wLjUsMy4xLTAuNSw0LjZjMTIsMCwyMC4xLTMuNiwyMC4xLTMuNmMwLTEuMywwLjMtMi4zLDAuMy0zLjZjMC0wLjMsMC0wLjUsMC0wLjhjMC0xLDAuMy0xLjgsMC4zLTIuOGMwLTAuMywwLTAuNSwwLTAuOGMwLjMtMi4zLDAuOC00LjYsMS02LjZMLTU0MS4xLDI4Ljh6IE0tNTQ2LjQsNTAuNkwtNTQ2LjQsNTAuNkwtNTQ2LjQsNTAuNkwtNTQ2LjQsNTAuNnoiLz48bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzVfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ii0zMTMiIHkxPSIzNzEuNzcyMiIgeDI9Ii0zMTMiIHkyPSIzODAuNzA4MyIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgyLjU0NDUgMCAwIC0yLjU0NDUgMTAwLjEyNzIgMTAxNy44MTE3KSI+PHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPjxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz48L2xpbmVhckdyYWRpZW50PjxwYXRoIGZpbGw9InVybCgjU1ZHSURfNV8pIiBkPSJNLTcwOC4zLDcyLjhsMTEuMiw0LjhjNS4zLTcuNiw4LjctMTUuNSwxMC43LTIxLjZsMi04LjFsLTUuMywwLjhDLTY5NC41LDU4LjgtNzAxLjEsNjYuOS03MDguMyw3Mi44eiIvPjxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfNl8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTI3Ny41MjU1IiB5MT0iMzkwLjIxMyIgeDI9Ii0yNzguNjQ3OSIgeTI9IjM4OC40MjU0IiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDIuNTQ0NSAwIDAgLTIuNTQ0NSAxMDAuMTI3MiAxMDE3LjgxMTcpIj48c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+PHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzM3OEY0MyIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCNTVkdJRF82XykiIGQ9Ik0tNjA3LDM2LjFjMi44LTcuNiw0LjMtMTQsNC4zLTE3YzAtMC4zLDAtMC41LDAtMC44bC02LjYsMkMtNjA5LjMsMjAuNC02MDksMjQuNy02MDcsMzYuMXoiLz48bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzdfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ii0yNjIuNTgxMyIgeTE9IjM4Ni40ODI3IiB4Mj0iLTI2My4yMTUiIHkyPSIzODQuMDc0OSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgyLjU0NDUgMCAwIC0yLjU0NDUgMTAwLjEyNzIgMTAxNy44MTE3KSI+PHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPjxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz48L2xpbmVhckdyYWRpZW50PjxwYXRoIGZpbGw9InVybCgjU1ZHSURfN18pIiBkPSJNLTU3MS40LDMwLjVjMCwwLTEuOCw1LjMsNS42LDEyYzEuMy01LjMsMi0xMC43LDIuMy0xNS4zTC01NzEuNCwzMC41eiIvPjwvZz48L2c+PGc+PGc+PHBhdGggZmlsbD0iIzY2QkI2QSIgZD0iTS04MDcuOCwzNDYuNmgtMC41djAuNWMwLjgsNC4zLDAsMTAuNC0zLjEsMTQuNWMtMS44LDIuMy00LjMsMy42LTcuMSwzLjZjLTQuNiwwLTYuNC01LjYtNi42LTExLjdjNy42LTEuOCwxMi43LTYuNiwxMi43LTEyLjJjMC00LjEtMS4zLTEwLjctOS4yLTEwLjdjLTcuNCwwLTExLjIsMTEuMi0xMiwxOC44Yy0zLjgsMC02LjYtMS44LTguNC0zLjZjMC44LTIuOCwxLTUuMSwxLTcuNGMwLTMuMS0yLjMtNC42LTQuMS00LjZjLTMuMSwwLTUuOSwyLjgtNS45LDguMWMwLDMuMywxLjMsNS45LDMuOCw3LjljLTIuMyw1LjEtNS45LDkuNC03LjEsMTAuN2MtMS0yLTQuMS05LjctNS4xLTE3LjZjMS4zLTMuMywxLjgtNS45LDEuOC03LjFjMC0yLTEuMy0zLjMtMy42LTMuM2MtMy4xLDAtNy42LDEuOC03LjYsMmwtMC4zLDAuM3YwLjNjMCwwLDEuMyw2LjYsMi44LDEzLjdjLTIuOCw0LjMtNy40LDExLjctOS45LDExLjdjLTQuMywwLDIuOC0yMi4xLTAuMy0yMi45aC0wLjNjLTEuNSwxLTE4LjYsMTAuNC00MSwxMC40YzAsMCwwLDAuNSwwLjMsMC44YzAuMywwLjMsMC41LDAuNSwwLjUsMC41YzYuNCwwLjgsMTUuNSwwLDIyLjQtMWMtNC4xLDguNC0xMC45LDE0LjItMTcuNiwxNC4yYy0xMi4yLDAtMjEuNi0xNC44LTIxLjYtMTQuOGMzLjgtMy4zLDkuOS0xNC4yLDE5LjEtMTQuMmM4LjksMCwxMyw0LjgsMTMsNC44bDEtMS41YzAsMC00LjMtMTQuOC0xNi0xNC44cy0yNC40LDE5LjYtMzEuOCwyMy45YzAsMCwxMC4yLDI0LjIsMzIuMywyNC4yYzE4LjYsMCwyMy40LTE3LjgsMjQuMi0yMi4xYzQuNi0wLjgsNy42LTEuMyw3LjYtMS4zcy0xLDkuMi0xLDEzYzAsMy44LDQuMSw3LjksNy42LDcuOWMzLjEsMCw4LjktNi4xLDEzLjItMTMuNWwwLjMsMC44YzIuMyw4LjQsNS4xLDEyLjcsOC40LDEyLjdzOC45LTYuOSwxMi41LTE1LjVjMy42LDEuNSw3LjksMiwxMC4yLDJjMSwxNSwxMy41LDE1LjUsMTUsMTUuNWM5LjQsMCwxNy4zLTYuNiwxNy4zLTE0LjVDLTgwMS40LDM0Ni44LTgwNy44LDM0Ni42LTgwNy44LDM0Ni42eiBNLTgxOSwzNDAuMmMwLDAsMCw1LjEtNS45LDcuNmMwLjUtNi42LDItMTIuNSwzLjMtMTIuNUMtODIwLjUsMzM1LjQtODE5LDMzNy4yLTgxOSwzNDAuMnoiLz48cGF0aCBmaWxsPSIjNjZCQjZBIiBkPSJNLTg4My44LDMzNC40YzAsMC4zLDAsMC4zLDAuMywwLjVjNC4zLDAuNSw3LjQtMC44LDcuNC03LjljMC02LjYtNi45LTEuNS04LjEtMC41YzAsMC0wLjMsMC4zLDAsMC41Qy04ODMuMywzMjkuNS04ODMuOCwzMzMuMS04ODMuOCwzMzQuNHoiLz48L2c+PGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF84XyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMzgyLjAwNzQiIHkxPSIyNTkuODQ3NSIgeDI9Ii0zNzkuMTU4NSIgeTI9IjI2MC43OTcyIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDIuNTQ0NSAwIDAgLTIuNTQ0NSAxMDAuMTI3MiAxMDE3LjgxMTcpIj48c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+PHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzM3OEY0MyIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCNTVkdJRF84XykiIGQ9Ik0tODY2LDM0OC42Yy0xLjgsMi44LTQuMyw2LjktNi42LDkuNGMwLjUsMS4zLDEuMywyLjgsMS44LDQuM2MyLTIuMyw0LjEtNS4xLDYuMS04LjFMLTg2NiwzNDguNnoiLz48bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzlfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ii0zNzMuMTYyNiIgeTE9IjI1OS4wNDIzIiB4Mj0iLTM3MS41MTAyIiB5Mj0iMjYxLjk0ODIiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMi41NDQ1IDAgMCAtMi41NDQ1IDEwMC4xMjcyIDEwMTcuODExNykiPjxzdG9wICBvZmZzZXQ9IjAiIHN0eWxlPSJzdG9wLWNvbG9yOiM2NkJCNkEiLz48c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojMzc4RjQzIi8+PC9saW5lYXJHcmFkaWVudD48cGF0aCBmaWxsPSJ1cmwoI1NWR0lEXzlfKSIgZD0iTS04NDUuNCwzNTAuOWMtMC44LTAuNS0xLjUtMS0xLjUtMWMtMS41LDMuMy0zLjYsNi40LTUuMSw4LjdjMC44LDEsMiwyLjUsMy4xLDMuNmMyLTIuOCw0LjEtNi4xLDUuNi0xMC4yQy04NDMuNiwzNTEuOS04NDQuNywzNTEuNC04NDUuNCwzNTAuOXoiLz48bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzEwXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMzY0LjY5OTYiIHkxPSIyNTcuNzUwMyIgeDI9Ii0zNjUuMDQxNCIgeTI9IjI2MC43ODkyIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDIuNTQ0NSAwIDAgLTIuNTQ0NSAxMDAuMTI3MiAxMDE3LjgxMTcpIj48c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+PHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzM3OEY0MyIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCNTVkdJRF8xMF8pIiBkPSJNLTgyNS4xLDM1My4yYzAsMC0yLDAuNS00LjMsMC44Yy0yLDAuMy00LjMsMC00LjMsMGMwLjMsNC4zLDEuNSw3LjQsMy4xLDkuN2w3LjktMC44Qy04MjQsMzYwLjgtODI0LjgsMzU3LTgyNS4xLDM1My4yeiIvPjxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfMTFfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ii0zNjUiIHkxPSIyNjQuMjIyMyIgeDI9Ii0zNjUiIHkyPSIyNjEuMTU5NyIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgyLjU0NDUgMCAwIC0yLjU0NDUgMTAwLjEyNzIgMTAxNy44MTE3KSI+PHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPjxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz48L2xpbmVhckdyYWRpZW50PjxwYXRoIGZpbGw9InVybCgjU1ZHSURfMTFfKSIgZD0iTS04MzEuMiwzMzkuOUwtODMxLjIsMzM5LjljLTAuMywwLjgtMC41LDEuNS0wLjgsMmMwLDAuMywwLDAuMy0wLjMsMC41Yy0wLjUsMS41LTAuOCwyLjgtMSw0LjNjMCwwLjMsMCwwLjMsMCwwLjVjMCwwLjgtMC4zLDEuMy0wLjMsMmM1LjEsMCw4LjctMS41LDguNy0xLjVjMC0wLjUsMC0xLDAuMy0xLjV2LTAuM2MwLTAuNSwwLTAuOCwwLjMtMXYtMC4zYzAuMy0xLDAuMy0yLDAuNS0yLjhMLTgzMS4yLDMzOS45eiBNLTgzMy41LDM0OS40TC04MzMuNSwzNDkuNEwtODMzLjUsMzQ5LjRMLTgzMy41LDM0OS40eiIvPjxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfMTJfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ii0zOTIiIHkxPSIyNTkuMjAyNSIgeDI9Ii0zOTIiIHkyPSIyNjMuMDAxMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgyLjU0NDUgMCAwIC0yLjU0NDUgMTAwLjEyNzIgMTAxNy44MTE3KSI+PHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPjxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz48L2xpbmVhckdyYWRpZW50PjxwYXRoIGZpbGw9InVybCgjU1ZHSURfMTJfKSIgZD0iTS05MDIuNCwzNTguOGw0LjgsMmMyLjMtMy4zLDMuNi02LjYsNC42LTkuMmwwLjgtMy42bC0yLjMsMC4zQy04OTYuNiwzNTIuNy04OTkuMSwzNTYuMi05MDIuNCwzNTguOHoiLz48bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzEzXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMzc2Ljg2MzciIHkxPSIyNjcuMDM1NSIgeDI9Ii0zNzcuMzQwOSIgeTI9IjI2Ni4yNzU1IiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDIuNTQ0NSAwIDAgLTIuNTQ0NSAxMDAuMTI3MiAxMDE3LjgxMTcpIj48c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+PHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzM3OEY0MyIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCNTVkdJRF8xM18pIiBkPSJNLTg1OS4yLDM0M2MxLjMtMy4zLDEuOC01LjksMS44LTcuMXYtMC4zbC0yLjgsMC44Qy04NjAuMiwzMzYuNC04NjAuMiwzMzguMi04NTkuMiwzNDN6Ii8+PGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8xNF8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTM3MC41NTQzIiB5MT0iMjY1LjQ2NDUiIHgyPSItMzcwLjgyMzYiIHkyPSIyNjQuNDQxIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDIuNTQ0NSAwIDAgLTIuNTQ0NSAxMDAuMTI3MiAxMDE3LjgxMTcpIj48c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+PHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzM3OEY0MyIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCNTVkdJRF8xNF8pIiBkPSJNLTg0NC4xLDM0MC43YzAsMC0wLjgsMi4zLDIuMyw1LjFjMC41LTIuMywxLTQuNiwxLTYuNkwtODQ0LjEsMzQwLjd6Ii8+PC9nPjxnPjxyZWN0IHg9Ii02OTcuMyIgeT0iMjkyLjkiIGZpbGw9IiNGRkZGRkYiIHdpZHRoPSIxMDYuOSIgaGVpZ2h0PSIxMDYuOSIvPjxnPjxwYXRoIGZpbGw9IiM2NkJCNkEiIGQ9Ik0tNjQ0LjQsMzQ5LjljMC4zLDAuNSwwLjUsMC44LDAuNSwwLjhjOC43LDEsMjEuMSwwLDMwLjUtMS41Yy01LjMsMTEuNy0xNSwxOS4zLTIzLjksMTkuM2MtMTYuNSwwLTI5LjUtMjAuMS0yOS41LTIwLjFjNS4xLTQuNiwxMy43LTE5LjMsMjYtMTkuM2MxMi4yLDAsMTcuNiw2LjYsMTcuNiw2LjZsMS4zLTIuM2MwLDAtNS45LTIwLjEtMjEuOS0yMC4xYy0xNi4zLDAtMzMuMywyNi41LTQzLjUsMzIuNmMwLDAsMTMuNywzMi44LDQ0LDMyLjhjMjUuNCwwLDMxLjgtMjQuMiwzMy4xLTMwLjNjMy4zLTAuNSw2LjEtMSw4LjEtMS4zYzAuNS0xLjMsMS4zLTMuOCwwLjgtNy4xYy0xMC4yLDMuOC0yNS40LDguNC00My41LDguNEMtNjQ0LjcsMzQ4LjYtNjQ0LjcsMzQ5LjEtNjQ0LjQsMzQ5Ljl6Ii8+PGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8xNV8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTI4MS44NSIgeTE9IjI1Ny41MTg3IiB4Mj0iLTI4MS44NSIgeTI9IjI2Mi42NTExIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDIuNTQ0NSAwIDAgLTIuNTQ0NSAxMDAuMTI3MiAxMDE3LjgxMTcpIj48c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+PHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzM3OEY0MyIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCNTVkdJRF8xNV8pIiBkPSJNLTYxMC4xLDM0OC45bC0zLjEsMC4zYzAsMC4zLTAuMywwLjUtMC41LDAuOGMtMC41LDEtMSwxLjgtMS41LDIuOGMtMC4zLDAuNS0wLjUsMC44LTAuOCwxLjNjLTAuNSwxLTEuMywyLTIsMi44Yy0wLjMsMC4zLTAuMywwLjMtMC41LDAuNWMtMS44LDIuMy0zLjYsNC4zLTUuNiw1LjlsNi40LDIuOEMtNjEyLjYsMzU5LjMtNjEwLjYsMzUxLjctNjEwLjEsMzQ4Ljl6Ii8+PC9nPjwvZz48Zz48Zz48ZGVmcz48Y2lyY2xlIGlkPSJTVkdJRF8xNl8iIGN4PSItNDA3LjMiIGN5PSIzNDYuMyIgcj0iNDIuMiIvPjwvZGVmcz48Y2xpcFBhdGggaWQ9IlNWR0lEXzE3XyI+PHVzZSB4bGluazpocmVmPSIjU1ZHSURfMTZfIiAgb3ZlcmZsb3c9InZpc2libGUiLz48L2NsaXBQYXRoPjxwYXRoIGNsaXAtcGF0aD0idXJsKCNTVkdJRF8xN18pIiBmaWxsPSIjRkZGRkZGIiBkPSJNLTQwMS4xLDM0OS40YzAuMywwLjMsMC41LDAuOCwwLjUsMC44YzcuNCwxLDE4LjEsMCwyNi4yLTEuM2MtNC42LDkuOS0xMywxNi41LTIwLjQsMTYuNWMtMTQuMiwwLTI1LjItMTcuMy0yNS4yLTE3LjNjNC4zLTMuOCwxMS43LTE2LjUsMjIuMS0xNi41czE1LDUuOSwxNSw1LjlsMS4zLTEuOGMwLDAtNC44LTE3LTE4LjgtMTdzLTI4LjUsMjIuNi0zNy4yLDI4YzAsMCwxMiwyOCwzNy43LDI4YzIxLjYsMCwyNy4yLTIwLjksMjguMi0yNmMyLjgtMC41LDUuMy0wLjgsNi45LTFjMC41LTEuMywxLTMuMywwLjgtNi4xYy04LjcsMy4zLTIxLjYsNy4xLTM3LjIsNy4xQy00MDEuNCwzNDguMy00MDEuNCwzNDguOS00MDEuMSwzNDkuNHoiLz48L2c+PC9nPjwvZz48ZyBpZD0iTGF5ZXJfMiI+PHBhdGggZmlsbD0iIzg4ODg4OCIgZD0iTTQ2Ny4zLDIwOS45Yy00LjgsMjQuNC0zMC44LDEyMi42LTEzMy42LDEyMi42Yy0xMjIuNiwwLTE3OC42LTEzMi44LTE3OC42LTEzMi44YzQxLTI0LjksMTEwLjQtMTMyLjMsMTc2LjEtMTMyLjNzODguOCw4MS4yLDg4LjgsODEuMmwtNS42LDguOWMwLDAtMjEuNi0yNy4yLTcxLjItMjcuMnMtODMuNyw1OS44LTEwNC42LDc4LjRjMCwwLDUyLjIsODEuNywxMTkuMyw4MS43YzM2LjEsMCw3NS4xLTMxLjMsOTYuOS03OC40Yy0zOC4yLDUuMy04OC4zLDEwLjItMTIzLjcsNS42YzAsMC0xLjgtMS41LTIuNS0zLjNjLTEtMi4zLTEuMy00LjYtMS4zLTQuNmM3MC4yLDAsMTMwLjUtMTYuNSwxNzEuNS0zMS44QzQ4Ny43LDc3LjYsNDAyLjksMCwzMDAuMSwwYy0xMTAuNCwwLTIwMCw4OS42LTIwMCwyMDBzODkuNiwyMDAsMjAwLDIwMGMxMDguOSwwLDE5Ny41LTg3LDIwMC0xOTUuNEM0OTIuNSwyMDUuOSw0ODEsMjA3LjksNDY3LjMsMjA5Ljl6Ii8+PC9nPjwvc3ZnPg==',
674 'give_cpt_icon' => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxOC4wLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCAxNTcuMSAxNTcuMiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMTU3LjEgMTU3LjI7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoJLnN0MHtmaWxsOiM2NkJCNkE7fQ0KCS5zdDF7ZmlsbDojNTQ2RTdBO30NCgkuc3Qye2ZpbGw6dXJsKCNTVkdJRF8xXyk7fQ0KCS5zdDN7ZmlsbDp1cmwoI1NWR0lEXzJfKTt9DQoJLnN0NHtmaWxsOnVybCgjU1ZHSURfM18pO30NCgkuc3Q1e2ZpbGw6dXJsKCNTVkdJRF80Xyk7fQ0KCS5zdDZ7ZmlsbDp1cmwoI1NWR0lEXzVfKTt9DQoJLnN0N3tmaWxsOnVybCgjU1ZHSURfNl8pO30NCgkuc3Q4e2ZpbGw6dXJsKCNTVkdJRF83Xyk7fQ0KCS5zdDl7ZmlsbDp1cmwoI1NWR0lEXzhfKTt9DQoJLnN0MTB7ZmlsbDp1cmwoI1NWR0lEXzlfKTt9DQoJLnN0MTF7ZmlsbDp1cmwoI1NWR0lEXzEwXyk7fQ0KCS5zdDEye2ZpbGw6dXJsKCNTVkdJRF8xMV8pO30NCgkuc3QxM3tmaWxsOnVybCgjU1ZHSURfMTJfKTt9DQoJLnN0MTR7ZmlsbDp1cmwoI1NWR0lEXzEzXyk7fQ0KCS5zdDE1e2ZpbGw6dXJsKCNTVkdJRF8xNF8pO30NCgkuc3QxNntmaWxsOiNGRkZGRkY7fQ0KCS5zdDE3e2ZpbGw6dXJsKCNTVkdJRF8xNV8pO30NCgkuc3QxOHtjbGlwLXBhdGg6dXJsKCNTVkdJRF8xN18pO2ZpbGw6I0ZGRkZGRjt9DQoJLnN0MTl7ZmlsbDojRjFGMkYyO30NCjwvc3R5bGU+DQo8ZyBpZD0iTGF5ZXJfMSI+DQoJPGNpcmNsZSBjbGFzcz0ic3QwIiBjeD0iLTE5OS40IiBjeT0iMTM2LjEiIHI9IjE2LjYiLz4NCgk8Zz4NCgkJPGc+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTM0OC40LDUyLjZ2LTQuOWgxLjljMS41LDAsMi42LDEsMi42LDIuNWMwLDEuNS0xLjEsMi41LTIuNiwyLjVILTM0OC40eiBNLTM0NC45LDUwLjENCgkJCQljMC0wLjktMC41LTEuNS0xLjUtMS41aC0wLjl2My4xaDAuOUMtMzQ1LjUsNTEuNy0zNDQuOSw1MS0zNDQuOSw1MC4xeiIvPg0KCQkJPHBhdGggY2xhc3M9InN0MSIgZD0iTS0zNDIuNiw1Mi42di00LjloMy41djAuOWgtMi40djFoMi40djAuOWgtMi40djEuMWgyLjR2MC45SC0zNDIuNnoiLz4NCgkJCTxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0tMzMzLjUsNTIuNnYtMy40bC0xLjQsMy40aC0wLjVsLTEuNC0zLjR2My40aC0xdi00LjloMS41bDEuMiwzbDEuMi0zaDEuNXY0LjlILTMzMy41eiIvPg0KCQkJPHBhdGggY2xhc3M9InN0MSIgZD0iTS0zMzEuMSw1MC4xYzAtMS41LDEuMS0yLjUsMi42LTIuNWMxLjUsMCwyLjYsMS4xLDIuNiwyLjVjMCwxLjUtMS4xLDIuNS0yLjYsMi41DQoJCQkJQy0zMzAuMSw1Mi43LTMzMS4xLDUxLjYtMzMxLjEsNTAuMXogTS0zMjcuMSw1MC4xYzAtMC45LTAuNi0xLjYtMS41LTEuNnMtMS41LDAuNy0xLjUsMS42YzAsMC45LDAuNiwxLjYsMS41LDEuNg0KCQkJCVMtMzI3LjEsNTEtMzI3LjEsNTAuMXoiLz4NCgkJCTxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0tMzI1LDUwLjFjMC0xLjUsMS4xLTIuNSwyLjYtMi41YzEuMSwwLDEuNywwLjYsMi4xLDEuMmwtMC45LDAuNGMtMC4yLTAuNC0wLjYtMC43LTEuMi0wLjcNCgkJCQljLTAuOSwwLTEuNSwwLjctMS41LDEuNmMwLDAuOSwwLjYsMS42LDEuNSwxLjZjMC41LDAsMC45LTAuMywxLjItMC43bDAuOSwwLjRjLTAuNCwwLjYtMSwxLjItMi4xLDEuMg0KCQkJCUMtMzIzLjgsNTIuNy0zMjUsNTEuNi0zMjUsNTAuMXoiLz4NCgkJCTxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0tMzE2LjMsNTIuNmwtMS0xLjdoLTAuOHYxLjdoLTF2LTQuOWgyLjNjMSwwLDEuNiwwLjcsMS42LDEuNmMwLDAuOS0wLjUsMS4zLTEuMSwxLjVsMS4xLDEuOUgtMzE2LjN6DQoJCQkJIE0tMzE2LjIsNDkuMmMwLTAuNC0wLjMtMC43LTAuNy0wLjdoLTEuMXYxLjNoMS4xQy0zMTYuNiw0OS45LTMxNi4yLDQ5LjctMzE2LjIsNDkuMnoiLz4NCgkJCTxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0tMzEwLjQsNTIuNmwtMC4zLTAuOGgtMi4xbC0wLjMsMC44aC0xLjJsMS45LTQuOWgxLjNsMS45LDQuOUgtMzEwLjR6IE0tMzExLjgsNDguN2wtMC44LDIuMWgxLjUNCgkJCQlMLTMxMS44LDQ4Ljd6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTMwNy42LDUyLjZ2LTRoLTEuNHYtMC45aDMuOXYwLjloLTEuNHY0SC0zMDcuNnoiLz4NCgkJCTxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0tMzAzLjksNTIuNnYtNC45aDF2NC45SC0zMDMuOXoiLz4NCgkJCTxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0tMzAxLjUsNTIuNnYtMC44bDIuMy0zLjFoLTIuM3YtMC45aDMuN3YwLjhsLTIuMywzLjJoMi40djAuOUgtMzAxLjV6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTI5Ni40LDUyLjZ2LTQuOWgxdjQuOUgtMjk2LjR6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTI5MC41LDUyLjZsLTIuMy0zLjJ2My4yaC0xdi00LjloMS4xbDIuMywzLjF2LTMuMWgxdjQuOUgtMjkwLjV6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTI4OC4yLDUwLjFjMC0xLjYsMS4yLTIuNSwyLjYtMi41YzEsMCwxLjcsMC41LDIsMS4xbC0wLjksMC41Yy0wLjItMC4zLTAuNi0wLjYtMS4yLTAuNg0KCQkJCWMtMC45LDAtMS41LDAuNy0xLjUsMS42YzAsMC45LDAuNiwxLjYsMS41LDEuNmMwLjQsMCwwLjgtMC4yLDEtMC40di0wLjZoLTEuM3YtMC45aDIuM3YxLjljLTAuNSwwLjYtMS4yLDAuOS0yLjEsMC45DQoJCQkJQy0yODcsNTIuNy0yODguMiw1MS43LTI4OC4yLDUwLjF6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTI3OS45LDUwLjFjMC0xLjYsMS4yLTIuNSwyLjYtMi41YzEsMCwxLjcsMC41LDIsMS4xbC0wLjksMC41Yy0wLjItMC4zLTAuNi0wLjYtMS4yLTAuNg0KCQkJCWMtMC45LDAtMS41LDAuNy0xLjUsMS42YzAsMC45LDAuNiwxLjYsMS41LDEuNmMwLjQsMCwwLjgtMC4yLDEtMC40di0wLjZoLTEuM3YtMC45aDIuM3YxLjljLTAuNSwwLjYtMS4yLDAuOS0yLjEsMC45DQoJCQkJQy0yNzguNyw1Mi43LTI3OS45LDUxLjctMjc5LjksNTAuMXoiLz4NCgkJCTxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0tMjczLjgsNTIuNnYtNC45aDMuNXYwLjloLTIuNHYxaDIuNHYwLjloLTIuNHYxLjFoMi40djAuOUgtMjczLjh6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTI2NS42LDUyLjZsLTIuMy0zLjJ2My4yaC0xdi00LjloMS4xbDIuMywzLjF2LTMuMWgxdjQuOUgtMjY1LjZ6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTI2Myw1Mi42di00LjloMy41djAuOWgtMi40djFoMi40djAuOWgtMi40djEuMWgyLjR2MC45SC0yNjN6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTI1NS40LDUyLjZsLTEtMS43aC0wLjh2MS43aC0xdi00LjloMi4zYzEsMCwxLjYsMC43LDEuNiwxLjZjMCwwLjktMC41LDEuMy0xLjEsMS41bDEuMSwxLjlILTI1NS40eg0KCQkJCSBNLTI1NS4zLDQ5LjJjMC0wLjQtMC4zLTAuNy0wLjctMC43aC0xLjF2MS4zaDEuMUMtMjU1LjYsNDkuOS0yNTUuMyw0OS43LTI1NS4zLDQ5LjJ6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTI1My4xLDUwLjFjMC0xLjUsMS4xLTIuNSwyLjYtMi41YzEuNSwwLDIuNiwxLjEsMi42LDIuNWMwLDEuNS0xLjEsMi41LTIuNiwyLjUNCgkJCQlDLTI1Mi4xLDUyLjctMjUzLjEsNTEuNi0yNTMuMSw1MC4xeiBNLTI0OS4xLDUwLjFjMC0wLjktMC42LTEuNi0xLjUtMS42Yy0wLjksMC0xLjUsMC43LTEuNSwxLjZjMCwwLjksMC42LDEuNiwxLjUsMS42DQoJCQkJQy0yNDkuNyw1MS43LTI0OS4xLDUxLTI0OS4xLDUwLjF6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTI0Ny4xLDUxLjlsMC42LTAuOGMwLjMsMC40LDAuOSwwLjcsMS42LDAuN2MwLjYsMCwwLjktMC4zLDAuOS0wLjVjMC0wLjktMi44LTAuMy0yLjgtMi4xDQoJCQkJYzAtMC44LDAuNy0xLjUsMS45LTEuNWMwLjgsMCwxLjQsMC4yLDEuOSwwLjdsLTAuNiwwLjhjLTAuNC0wLjQtMC45LTAuNS0xLjQtMC41Yy0wLjQsMC0wLjcsMC4yLTAuNywwLjVjMCwwLjgsMi44LDAuMywyLjgsMi4xDQoJCQkJYzAsMC45LTAuNiwxLjYtMiwxLjZDLTI0NS45LDUyLjctMjQ2LjYsNTIuMy0yNDcuMSw1MS45eiIvPg0KCQkJPHBhdGggY2xhc3M9InN0MSIgZD0iTS0yNDEuOCw1Mi42di00LjloMXY0LjlILTI0MS44eiIvPg0KCQkJPHBhdGggY2xhc3M9InN0MSIgZD0iTS0yMzguMSw1Mi42di00aC0xLjR2LTAuOWgzLjl2MC45aC0xLjR2NEgtMjM4LjF6Ii8+DQoJCQk8cGF0aCBjbGFzcz0ic3QxIiBkPSJNLTIzMyw1Mi42di0ybC0xLjktMi45aDEuMmwxLjIsMmwxLjItMmgxLjJsLTEuOSwyLjl2MkgtMjMzeiIvPg0KCQk8L2c+DQoJCTxnPg0KCQkJPGc+DQoJCQkJPHBhdGggY2xhc3M9InN0MCIgZD0iTS0yMzAuMywxNy40bC0wLjUsMGwwLjEsMC41YzAuOCwzLjksMC4xLDkuNy0yLjksMTMuM2MtMS43LDIuMS0zLjksMy4yLTYuNiwzLjJjLTQuMywwLTUuOS01LjEtNi4xLTEwLjkNCgkJCQkJYzctMS43LDExLjctNi4xLDExLjctMTEuMmMwLTMuNy0xLjEtOS44LTguNC05LjhjLTYuOSwwLTEwLjQsMTAuMy0xMS4xLDE3LjVjLTMuNS0wLjEtNi4xLTEuNy03LjctMy4yYzAuNi0yLjUsMC45LTQuOCwwLjktNi45DQoJCQkJCWMwLTIuOS0yLTQuMi0zLjktNC4yYy0yLjcsMC01LjUsMi42LTUuNSw3LjZjMCwzLDEuMSw1LjUsMy40LDcuM2MtMiw0LjctNS40LDguNy02LjUsMTBjLTAuOS0xLjktMy44LTguOC00LjctMTYuMw0KCQkJCQljMS4xLTMsMS43LTUuNSwxLjctNi43YzAtMS45LTEuMi0zLTMuMi0zYy0yLjcsMC03LDEuNy03LjEsMS44bC0wLjIsMC4xbDAsMC4zYzAsMC4xLDEuMyw2LjEsMi42LDEyLjcNCgkJCQkJYy0yLjUsNC4xLTYuOSwxMC45LTkuMSwxMC45Yy00LDAsMi42LTIwLjUtMC4zLTIxLjJjLTAuMSwwLTAuMiwwLTAuMywwLjFjLTEuNCwwLjktMTcuMSw5LjYtMzgsOS42YzAsMCwwLDAuNCwwLjIsMC44DQoJCQkJCWMwLjEsMC4zLDAuNCwwLjYsMC40LDAuNmM1LjksMC43LDE0LjMtMC4xLDIwLjctMWMtMy43LDcuOS0xMC4yLDEzLjEtMTYuMiwxMy4xYy0xMS4zLDAtMjAtMTMuNy0yMC0xMy43DQoJCQkJCWMzLjUtMy4xLDkuMi0xMy4xLDE3LjYtMTMuMWM4LjMsMCwxMS45LDQuNiwxMS45LDQuNmwwLjktMS41YzAsMC0zLjktMTMuNi0xNC45LTEzLjZjLTExLDAtMjIuNywxOC0yOS41LDIyLjINCgkJCQkJYzAsMCw5LjQsMjIuMiwyOS45LDIyLjJjMTcuMiwwLDIxLjYtMTYuNSwyMi40LTIwLjVjNC4yLTAuNiw3LjEtMS4yLDcuMS0xLjJzLTEuMSw4LjQtMS4xLDExLjljMCwzLjUsMy45LDcuMiw3LjEsNy4yDQoJCQkJCWMyLjcsMCw4LjItNS42LDEyLjItMTIuNGwwLjIsMC44YzIuMSw3LjcsNC43LDExLjcsNy44LDExLjdjMy4xLDAsOC4yLTYuNCwxMS41LTE0LjVjMy4zLDEuNCw3LjIsMS44LDkuNSwxLjkNCgkJCQkJYzAuOSwxMy45LDEyLjUsMTQuMywxMy45LDE0LjNjOC42LDAsMTUuOS02LjIsMTUuOS0xMy41Qy0yMjQuMywxNy41LTIzMC4yLDE3LjQtMjMwLjMsMTcuNHogTS0yNDAuOCwxMS42YzAsMC0wLjEsNC42LTUuMyw2LjkNCgkJCQkJYzAuNS02LjEsMi0xMS42LDMtMTEuNkMtMjQyLDctMjQwLjgsOC43LTI0MC44LDExLjZ6Ii8+DQoJCQkJPHBhdGggY2xhc3M9InN0MCIgZD0iTS0zMDAuNyw2LjFjMCwwLjIsMC4xLDAuMywwLjMsMC40YzQuMSwwLjYsNi44LTAuNyw2LjgtNy4zYzAtNi4yLTYuNC0xLjMtNy42LTAuNA0KCQkJCQljLTAuMSwwLjEtMC4xLDAuMi0wLjEsMC40Qy0zMDAuMiwxLjYtMzAwLjYsNS4xLTMwMC43LDYuMXoiLz4NCgkJCTwvZz4NCgkJCTxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfMV8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTI4OS41ODQ0IiB5MT0iMjYuNzY4IiB4Mj0iLTI4Mi44ODIzIiB5Mj0iMjQuNTM0Ij4NCgkJCQk8c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+DQoJCQkJPHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzM3OEY0MyIvPg0KCQkJPC9saW5lYXJHcmFkaWVudD4NCgkJCTxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0tMjg0LjIsMTkuNGMtMS42LDIuNy00LDYuNC02LjEsOC43YzAuNSwxLjIsMS4xLDIuNywxLjcsMy45YzEuOS0yLjEsMy44LTQuOCw1LjUtNy42TC0yODQuMiwxOS40eiIvPg0KCQkJPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8yXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMjY5LjAxOTQiIHkxPSIyOC40Nzc3IiB4Mj0iLTI2NS4xMzIyIiB5Mj0iMjEuNjQxNiI+DQoJCQkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPg0KCQkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz4NCgkJCTwvbGluZWFyR3JhZGllbnQ+DQoJCQk8cGF0aCBjbGFzcz0ic3QzIiBkPSJNLTI2NS4yLDIxLjVjLTAuOC0wLjQtMS41LTEtMS41LTFjLTEuNCwzLjEtMy4zLDYtNC44LDcuOWMwLjcsMSwxLjksMi4zLDIuOCwzLjNjMS44LTIuNSwzLjctNS44LDUuMS05LjMNCgkJCQlDLTI2My41LDIyLjMtMjY0LjQsMjItMjY1LjIsMjEuNXoiLz4NCgkJCTxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfM18iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTI0OC42MjU0IiB5MT0iMzEuNjE0NyIgeDI9Ii0yNDkuNDI5NyIgeTI9IjI0LjQ2NTkiPg0KCQkJCTxzdG9wICBvZmZzZXQ9IjAiIHN0eWxlPSJzdG9wLWNvbG9yOiM2NkJCNkEiLz4NCgkJCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojMzc4RjQzIi8+DQoJCQk8L2xpbmVhckdyYWRpZW50Pg0KCQkJPHBhdGggY2xhc3M9InN0NCIgZD0iTS0yNDYuMiwyMy41YzAsMC0yLDAuNC00LDAuNmMtMiwwLjItMy45LDAuMS0zLjksMC4xYzAuMyw0LDEuNCw2LjgsMi45LDguOWw3LjMtMC42DQoJCQkJQy0yNDUuNCwzMC41LTI0Ni4xLDI3LjEtMjQ2LjIsMjMuNXoiLz4NCgkJCTxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfNF8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTI0OS43MjY3IiB5MT0iMTYuNDE5IiB4Mj0iLTI0OS43MjY3IiB5Mj0iMjMuNjIzNyI+DQoJCQkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPg0KCQkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz4NCgkJCTwvbGluZWFyR3JhZGllbnQ+DQoJCQk8cGF0aCBjbGFzcz0ic3Q1IiBkPSJNLTI1MiwxMS4zTC0yNTIsMTEuM2MtMC4yLDAuNi0wLjUsMS4zLTAuNywyYzAsMC4yLTAuMSwwLjMtMC4xLDAuNWMtMC40LDEuMy0wLjcsMi42LTAuOSwzLjkNCgkJCQljMCwwLjItMC4xLDAuMy0wLjEsMC41Yy0wLjEsMC42LTAuMiwxLjItMC4yLDEuOGM0LjcsMCw3LjktMS40LDcuOS0xLjRjMC0wLjUsMC4xLTAuOSwwLjEtMS40YzAtMC4xLDAtMC4yLDAtMC4zDQoJCQkJYzAtMC40LDAuMS0wLjcsMC4xLTEuMWMwLTAuMSwwLTAuMiwwLTAuM2MwLjEtMC45LDAuMy0xLjgsMC40LTIuNkwtMjUyLDExLjN6IE0tMjU0LjEsMTkuOUMtMjU0LjEsMTkuOS0yNTQuMSwxOS45LTI1NC4xLDE5LjkNCgkJCQlMLTI1NC4xLDE5LjlDLTI1NC4xLDE5LjktMjU0LjEsMTkuOS0yNTQuMSwxOS45eiIvPg0KCQkJPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF81XyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMzEzLjAyNzIiIHkxPSIyOC4yMjc4IiB4Mj0iLTMxMy4wMjcyIiB5Mj0iMTkuMjkxNyI+DQoJCQkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPg0KCQkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz4NCgkJCTwvbGluZWFyR3JhZGllbnQ+DQoJCQk8cGF0aCBjbGFzcz0ic3Q2IiBkPSJNLTMxNy43LDI4LjZsNC40LDEuOWMyLjEtMywzLjQtNi4xLDQuMi04LjVsMC44LTMuMmwtMi4xLDAuM0MtMzEyLjMsMjMuMS0zMTQuOSwyNi4zLTMxNy43LDI4LjZ6Ii8+DQoJCQk8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzZfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ii0yNzcuNTIzOSIgeTE9IjkuNzg4IiB4Mj0iLTI3OC42NDYzIiB5Mj0iMTEuNTc1NiI+DQoJCQkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPg0KCQkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz4NCgkJCTwvbGluZWFyR3JhZGllbnQ+DQoJCQk8cGF0aCBjbGFzcz0ic3Q3IiBkPSJNLTI3Ny45LDE0LjJjMS4xLTMsMS43LTUuNSwxLjctNi43YzAtMC4xLDAtMC4yLDAtMC4zbC0yLjYsMC44Qy0yNzguOCw4LTI3OC43LDkuNy0yNzcuOSwxNC4yeiIvPg0KCQkJPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF83XyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMjYyLjU1MjkiIHkxPSIxMy41MjQ4IiB4Mj0iLTI2My4xODY2IiB5Mj0iMTUuOTMyNiI+DQoJCQkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPg0KCQkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz4NCgkJCTwvbGluZWFyR3JhZGllbnQ+DQoJCQk8cGF0aCBjbGFzcz0ic3Q4IiBkPSJNLTI2My45LDEyYzAsMC0wLjcsMi4xLDIuMiw0LjdjMC41LTIuMSwwLjgtNC4yLDAuOS02TC0yNjMuOSwxMnoiLz4NCgkJPC9nPg0KCTwvZz4NCgk8Zz4NCgkJPGc+DQoJCQk8cGF0aCBjbGFzcz0ic3QwIiBkPSJNLTM1Ni44LDEzNi4ybC0wLjIsMGwwLDAuMmMwLjMsMS43LDAsNC4xLTEuMiw1LjdjLTAuNywwLjktMS43LDEuNC0yLjgsMS40Yy0xLjgsMC0yLjUtMi4yLTIuNi00LjYNCgkJCQljMy0wLjcsNS0yLjYsNS00LjhjMC0xLjYtMC41LTQuMi0zLjYtNC4yYy0yLjksMC00LjQsNC40LTQuNyw3LjRjLTEuNSwwLTIuNi0wLjctMy4zLTEuNGMwLjMtMS4xLDAuNC0yLDAuNC0yLjkNCgkJCQljMC0xLjItMC45LTEuOC0xLjYtMS44Yy0xLjIsMC0yLjMsMS4xLTIuMywzLjJjMCwxLjMsMC41LDIuMywxLjUsMy4xYy0wLjksMi0yLjMsMy43LTIuOCw0LjJjLTAuNC0wLjgtMS42LTMuOC0yLTYuOQ0KCQkJCWMwLjUtMS4zLDAuNy0yLjMsMC43LTIuOGMwLTAuOC0wLjUtMS4zLTEuNC0xLjNjLTEuMiwwLTMsMC43LTMsMC44bC0wLjEsMC4xbDAsMC4xYzAsMCwwLjUsMi42LDEuMSw1LjQNCgkJCQljLTEuMSwxLjctMi45LDQuNi0zLjksNC42Yy0xLjcsMCwxLjEtOC43LTAuMS05YzAsMC0wLjEsMC0wLjEsMGMtMC42LDAuNC03LjMsNC4xLTE2LjEsNC4xYzAsMCwwLDAuMiwwLjEsMC4zDQoJCQkJYzAuMSwwLjEsMC4yLDAuMiwwLjIsMC4yYzIuNSwwLjMsNi4xLDAsOC44LTAuNGMtMS42LDMuMy00LjMsNS42LTYuOSw1LjZjLTQuOCwwLTguNS01LjgtOC41LTUuOGMxLjUtMS4zLDMuOS01LjYsNy41LTUuNg0KCQkJCWMzLjUsMCw1LjEsMS45LDUuMSwxLjlsMC40LTAuNmMwLDAtMS43LTUuOC02LjMtNS44cy05LjYsNy43LTEyLjUsOS40YzAsMCw0LDkuNSwxMi43LDkuNWM3LjMsMCw5LjItNyw5LjUtOC43DQoJCQkJYzEuOC0wLjMsMy0wLjUsMy0wLjVzLTAuNCwzLjYtMC40LDUuMXMxLjYsMy4xLDMsMy4xYzEuMiwwLDMuNS0yLjQsNS4yLTUuM2wwLjEsMC4zYzAuOSwzLjMsMiw1LDMuMyw1YzEuMywwLDMuNS0yLjcsNC45LTYuMQ0KCQkJCWMxLjQsMC42LDMuMSwwLjgsNCwwLjhjMC40LDUuOSw1LjMsNi4xLDUuOSw2LjFjMy43LDAsNi44LTIuNiw2LjgtNS43Qy0zNTQuMywxMzYuMy0zNTYuOCwxMzYuMi0zNTYuOCwxMzYuMnogTS0zNjEuMiwxMzMuNw0KCQkJCWMwLDAsMCwyLTIuMywzYzAuMi0yLjYsMC44LTQuOSwxLjMtNC45Qy0zNjEuOCwxMzEuOC0zNjEuMiwxMzIuNS0zNjEuMiwxMzMuN3oiLz4NCgkJCTxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0tMzg2LjcsMTMxLjRjMCwwLjEsMCwwLjEsMC4xLDAuMmMxLjcsMC4yLDIuOS0wLjMsMi45LTMuMWMwLTIuNi0yLjctMC42LTMuMi0wLjJjMCwwLTAuMSwwLjEsMCwwLjINCgkJCQlDLTM4Ni41LDEyOS41LTM4Ni43LDEzMC45LTM4Ni43LDEzMS40eiIvPg0KCQk8L2c+DQoJCTxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfOF8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTM4MS45OTkzIiB5MT0iMTQwLjE3NjkiIHgyPSItMzc5LjE1MDQiIHkyPSIxMzkuMjI3MiI+DQoJCQk8c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+DQoJCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojMzc4RjQzIi8+DQoJCTwvbGluZWFyR3JhZGllbnQ+DQoJCTxwYXRoIGNsYXNzPSJzdDkiIGQ9Ik0tMzc5LjcsMTM3Yy0wLjcsMS4xLTEuNywyLjctMi42LDMuN2MwLjIsMC41LDAuNSwxLjEsMC43LDEuN2MwLjgtMC45LDEuNi0yLDIuNC0zLjJMLTM3OS43LDEzN3oiLz4NCgkJPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF85XyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMzczLjI1NzUiIHkxPSIxNDAuOTAzNyIgeDI9Ii0zNzEuNjA1MSIgeTI9IjEzNy45OTc4Ij4NCgkJCTxzdG9wICBvZmZzZXQ9IjAiIHN0eWxlPSJzdG9wLWNvbG9yOiM2NkJCNkEiLz4NCgkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz4NCgkJPC9saW5lYXJHcmFkaWVudD4NCgkJPHBhdGggY2xhc3M9InN0MTAiIGQ9Ik0tMzcxLjYsMTM3LjljLTAuMy0wLjItMC42LTAuNC0wLjYtMC40Yy0wLjYsMS4zLTEuNCwyLjUtMiwzLjRjMC4zLDAuNCwwLjgsMSwxLjIsMS40DQoJCQljMC44LTEuMSwxLjYtMi40LDIuMi00Qy0zNzAuOSwxMzguMy0zNzEuMywxMzguMS0zNzEuNiwxMzcuOXoiLz4NCgkJPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8xMF8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTM2NC41ODg0IiB5MT0iMTQyLjIzNzIiIHgyPSItMzY0LjkzMDMiIHkyPSIxMzkuMTk4MyI+DQoJCQk8c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+DQoJCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojMzc4RjQzIi8+DQoJCTwvbGluZWFyR3JhZGllbnQ+DQoJCTxwYXRoIGNsYXNzPSJzdDExIiBkPSJNLTM2My42LDEzOC44YzAsMC0wLjgsMC4yLTEuNywwLjNjLTAuOCwwLjEtMS43LDAtMS43LDBjMC4xLDEuNywwLjYsMi45LDEuMiwzLjhsMy4xLTAuMw0KCQkJQy0zNjMuMiwxNDEuOC0zNjMuNSwxNDAuMy0zNjMuNiwxMzguOHoiLz4NCgkJPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8xMV8iIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iLTM2NS4wNTY2IiB5MT0iMTM1Ljc3NzciIHgyPSItMzY1LjA1NjYiIHkyPSIxMzguODQwMyI+DQoJCQk8c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+DQoJCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojMzc4RjQzIi8+DQoJCTwvbGluZWFyR3JhZGllbnQ+DQoJCTxwYXRoIGNsYXNzPSJzdDEyIiBkPSJNLTM2NiwxMzMuNkwtMzY2LDEzMy42Yy0wLjEsMC4zLTAuMiwwLjYtMC4zLDAuOGMwLDAuMSwwLDAuMS0wLjEsMC4yYy0wLjIsMC42LTAuMywxLjEtMC40LDEuNw0KCQkJYzAsMC4xLDAsMC4xLDAsMC4yYzAsMC4zLTAuMSwwLjUtMC4xLDAuOGMyLDAsMy40LTAuNiwzLjQtMC42YzAtMC4yLDAtMC40LDAuMS0wLjZjMCwwLDAtMC4xLDAtMC4xYzAtMC4yLDAtMC4zLDAuMS0wLjQNCgkJCWMwLDAsMC0wLjEsMC0wLjFjMC4xLTAuNCwwLjEtMC44LDAuMi0xLjFMLTM2NiwxMzMuNnogTS0zNjYuOSwxMzcuM0MtMzY2LjksMTM3LjMtMzY2LjksMTM3LjMtMzY2LjksMTM3LjNMLTM2Ni45LDEzNy4zDQoJCQlDLTM2Ni45LDEzNy4zLTM2Ni45LDEzNy4zLTM2Ni45LDEzNy4zeiIvPg0KCQk8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzEyXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMzkxLjk2NDQiIHkxPSIxNDAuNzk3NSIgeDI9Ii0zOTEuOTY0NCIgeTI9IjEzNi45OTg5Ij4NCgkJCTxzdG9wICBvZmZzZXQ9IjAiIHN0eWxlPSJzdG9wLWNvbG9yOiM2NkJCNkEiLz4NCgkJCTxzdG9wICBvZmZzZXQ9IjEiIHN0eWxlPSJzdG9wLWNvbG9yOiMzNzhGNDMiLz4NCgkJPC9saW5lYXJHcmFkaWVudD4NCgkJPHBhdGggY2xhc3M9InN0MTMiIGQ9Ik0tMzk0LDE0MWwxLjksMC44YzAuOS0xLjMsMS40LTIuNiwxLjgtMy42bDAuMy0xLjRsLTAuOSwwLjFDLTM5MS43LDEzOC42LTM5Mi43LDE0MC0zOTQsMTQxeiIvPg0KCQk8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzEzXyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHgxPSItMzc2Ljg3MjYiIHkxPSIxMzIuOTU5IiB4Mj0iLTM3Ny4zNDk4IiB5Mj0iMTMzLjcxODkiPg0KCQkJPHN0b3AgIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29sb3I6IzY2QkI2QSIvPg0KCQkJPHN0b3AgIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IzM3OEY0MyIvPg0KCQk8L2xpbmVhckdyYWRpZW50Pg0KCQk8cGF0aCBjbGFzcz0ic3QxNCIgZD0iTS0zNzcsMTM0LjhjMC41LTEuMywwLjctMi4zLDAuNy0yLjhjMCwwLDAtMC4xLDAtMC4xbC0xLjEsMC4zQy0zNzcuNCwxMzIuMi0zNzcuNCwxMzIuOS0zNzcsMTM0Ljh6Ii8+DQoJCTxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfMTRfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ii0zNzAuNTA4OCIgeTE9IjEzNC41NDc1IiB4Mj0iLTM3MC43NzgxIiB5Mj0iMTM1LjU3MSI+DQoJCQk8c3RvcCAgb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjojNjZCQjZBIi8+DQoJCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojMzc4RjQzIi8+DQoJCTwvbGluZWFyR3JhZGllbnQ+DQoJCTxwYXRoIGNsYXNzPSJzdDE1IiBkPSJNLTM3MS4xLDEzMy45YzAsMC0wLjMsMC45LDAuOSwyYzAuMi0wLjksMC40LTEuOCwwLjQtMi42TC0zNzEuMSwxMzMuOXoiLz4NCgk8L2c+DQoJPGc+DQoJCTxyZWN0IHg9Ii0zMTMuNCIgeT0iMTE1LjEiIGNsYXNzPSJzdDE2IiB3aWR0aD0iNDIiIGhlaWdodD0iNDIiLz4NCgkJPGc+DQoJCQk8cGF0aCBjbGFzcz0ic3QwIiBkPSJNLTI5Mi42LDEzNy41YzAuMSwwLjIsMC4yLDAuMywwLjIsMC4zYzMuNCwwLjQsOC4zLDAsMTItMC42Yy0yLjEsNC42LTUuOSw3LjYtOS40LDcuNg0KCQkJCWMtNi41LDAtMTEuNi03LjktMTEuNi03LjljMi0xLjgsNS40LTcuNiwxMC4yLTcuNnM2LjksMi42LDYuOSwyLjZsMC41LTAuOWMwLDAtMi4zLTcuOS04LjYtNy45Yy02LjQsMC0xMy4xLDEwLjQtMTcuMSwxMi44DQoJCQkJYzAsMCw1LjQsMTIuOSwxNy4zLDEyLjljMTAsMCwxMi41LTkuNSwxMy0xMS45YzEuMy0wLjIsMi40LTAuNCwzLjItMC41YzAuMi0wLjUsMC41LTEuNSwwLjMtMi44Yy00LDEuNS0xMCwzLjMtMTcuMSwzLjMNCgkJCQlDLTI5Mi43LDEzNy0yOTIuNywxMzcuMi0yOTIuNiwxMzcuNXoiLz4NCgkJCTxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfMTVfIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9Ii0yODEuNzk2MiIgeTE9IjE0Mi40ODEzIiB4Mj0iLTI4MS43OTYyIiB5Mj0iMTM3LjM0ODkiPg0KCQkJCTxzdG9wICBvZmZzZXQ9IjAiIHN0eWxlPSJzdG9wLWNvbG9yOiM2NkJCNkEiLz4NCgkJCQk8c3RvcCAgb2Zmc2V0PSIxIiBzdHlsZT0ic3RvcC1jb2xvcjojMzc4RjQzIi8+DQoJCQk8L2xpbmVhckdyYWRpZW50Pg0KCQkJPHBhdGggY2xhc3M9InN0MTciIGQ9Ik0tMjc5LjEsMTM3LjFsLTEuMiwwLjFjMCwwLjEtMC4xLDAuMi0wLjIsMC4zYy0wLjIsMC40LTAuNCwwLjctMC42LDEuMWMtMC4xLDAuMi0wLjIsMC4zLTAuMywwLjUNCgkJCQljLTAuMiwwLjQtMC41LDAuOC0wLjgsMS4xYy0wLjEsMC4xLTAuMSwwLjEtMC4yLDAuMmMtMC43LDAuOS0xLjQsMS43LTIuMiwyLjNsMi41LDEuMUMtMjgwLjEsMTQxLjItMjc5LjMsMTM4LjItMjc5LjEsMTM3LjF6Ii8+DQoJCTwvZz4NCgk8L2c+DQoJPGc+DQoJCTxkZWZzPg0KCQkJPGNpcmNsZSBpZD0iU1ZHSURfMTZfIiBjeD0iLTE5OS40IiBjeT0iMTM2LjEiIHI9IjE2LjYiLz4NCgkJPC9kZWZzPg0KCQk8Y2xpcFBhdGggaWQ9IlNWR0lEXzE3XyI+DQoJCQk8dXNlIHhsaW5rOmhyZWY9IiNTVkdJRF8xNl8iICBzdHlsZT0ib3ZlcmZsb3c6dmlzaWJsZTsiLz4NCgkJPC9jbGlwUGF0aD4NCgkJPHBhdGggY2xhc3M9InN0MTgiIGQ9Ik0tMTk3LDEzNy4zYzAuMSwwLjEsMC4yLDAuMywwLjIsMC4zYzIuOSwwLjQsNy4xLDAsMTAuMy0wLjVjLTEuOCwzLjktNS4xLDYuNS04LDYuNWMtNS42LDAtOS45LTYuOC05LjktNi44DQoJCQljMS43LTEuNSw0LjYtNi41LDguNy02LjVzNS45LDIuMyw1LjksMi4zbDAuNS0wLjdjMCwwLTEuOS02LjctNy40LTYuN3MtMTEuMiw4LjktMTQuNiwxMWMwLDAsNC43LDExLDE0LjgsMTENCgkJCWM4LjUsMCwxMC43LTguMiwxMS4xLTEwLjJjMS4xLTAuMiwyLjEtMC4zLDIuNy0wLjRjMC4yLTAuNSwwLjQtMS4zLDAuMy0yLjRjLTMuNCwxLjMtOC41LDIuOC0xNC42LDIuOA0KCQkJQy0xOTcuMSwxMzYuOS0xOTcuMSwxMzcuMS0xOTcsMTM3LjN6Ii8+DQoJPC9nPg0KPC9nPg0KPGcgaWQ9IkxheWVyXzIiPg0KCTxwYXRoIGNsYXNzPSJzdDE5IiBkPSJNMTQ0LjMsODIuNWMtMS45LDkuNi0xMi4xLDQ4LjItNTIuNSw0OC4yYy00OC4yLDAtNzAuMi01Mi4yLTcwLjItNTIuMmMxNi4xLTkuOCw0My40LTUyLDY5LjItNTINCgkJczM0LjksMzEuOSwzNC45LDMxLjlsLTIuMiwzLjVjMCwwLTguNS0xMC43LTI4LTEwLjdTNjIuNiw3NC43LDU0LjQsODJjMCwwLDIwLjUsMzIuMSw0Ni45LDMyLjFjMTQuMiwwLDI5LjUtMTIuMywzOC4xLTMwLjgNCgkJYy0xNSwyLjEtMzQuNyw0LTQ4LjYsMi4yYzAsMC0wLjctMC42LTEtMS4zYy0wLjQtMC45LTAuNS0xLjgtMC41LTEuOGMyNy42LDAsNTEuMy02LjUsNjcuNC0xMi41QzE1Mi4zLDMwLjUsMTE5LDAsNzguNiwwDQoJCUMzNS4yLDAsMCwzNS4yLDAsNzguNmMwLDQzLjQsMzUuMiw3OC42LDc4LjYsNzguNmM0Mi44LDAsNzcuNi0zNC4yLDc4LjYtNzYuOEMxNTQuMiw4MC45LDE0OS43LDgxLjcsMTQ0LjMsODIuNXoiLz4NCjwvZz4NCjwvc3ZnPg0K',
675 );
676
677 // Return the chosen icon's SVG string
678 return $svgs[ $icon ];
679 }
680
681 /**
682 * Modify Admin Nav Menu Label
683 *
684 * @since 1.3
685 *
686 * @param object $post_type The current object to add a menu items meta box for.
687 *
688 * @return mixed
689 */
690 function modify_nav_menu_meta_box_object( $post_type ) {
691 if ( isset( $post_type->name ) && $post_type->name == 'give_forms' ) {
692 $post_type->labels->name = esc_html__( 'Donation Forms', 'give' );
693 }
694
695 return $post_type;
696 }
697
698 add_filter( 'nav_menu_meta_box_object', 'modify_nav_menu_meta_box_object' );
699
700 /**
701 * Show Donation Forms Post Type in Appearance > Menus by default on fresh install.
702 *
703 * @since 1.8.14
704 *
705 * @todo Remove this, when WordPress Core ticket is resolved (https://core.trac.wordpress.org/ticket/16828).
706 *
707 * @return bool
708 */
709 function give_donation_metabox_menu() {
710
711 // Get Current Screen.
712 $screen = get_current_screen();
713
714 // Proceed, if current screen is navigation menus.
715 if ( 'nav-menus' === $screen->id && give_is_setting_enabled( give_get_option( 'forms_singular' ) ) && ! get_user_option( 'give_is_donation_forms_menu_updated' ) ) {
716
717 // Return false, if it fails to retrieve hidden meta box list and is not admin.
718 if ( ! is_admin() || ( ! $hidden_meta_boxes = get_user_option( 'metaboxhidden_nav-menus' ) ) ) {
719 return false;
720 }
721
722 // Return false, In case, we don't find 'Donation Form' in hidden meta box list.
723 if ( ! in_array( 'add-post-type-give_forms', $hidden_meta_boxes, true ) ) {
724 return false;
725 }
726
727 // Exclude 'Donation Form' value from hidden meta box's list.
728 $hidden_meta_boxes = array_diff( $hidden_meta_boxes, array( 'add-post-type-give_forms' ) );
729
730 // Get current user ID.
731 $user = wp_get_current_user();
732
733 update_user_option( $user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true );
734 update_user_option( $user->ID, 'give_is_donation_forms_menu_updated', true, true );
735 }
736 }
737
738 add_action( 'current_screen', 'give_donation_metabox_menu' );
739
740 /**
741 * Array_column backup usage
742 *
743 * This file is part of the array_column library.
744 *
745 * @since : 1.3.0.1
746 *
747 * @copyright Copyright (c) Ben Ramsey (http://benramsey.com)
748 * @license https://opensource.org/licenses/MIT MIT
749 */
750
751 if ( ! function_exists( 'array_column' ) ) {
752 /**
753 * Returns the values from a single column of the input array, identified by
754 * the $columnKey.
755 *
756 * Optionally, you may provide an $indexKey to index the values in the returned
757 * array by the values from the $indexKey column in the input array.
758 *
759 * @param array $input A multi-dimensional array (record set) from which to pull
760 * a column of values.
761 * @param int|string $columnKey The column of values to return. This value may be the
762 * integer key of the column you wish to retrieve, or it
763 * may be the string key name for an associative array.
764 * @param mixed $indexKey (Optional.) The column to use as the index/keys for
765 * the returned array. This value may be the integer key
766 * of the column, or it may be the string key name.
767 *
768 * @return array
769 */
770 function array_column( $input = null, $columnKey = null, $indexKey = null ) {
771 // Using func_get_args() in order to check for proper number of
772 // parameters and trigger errors exactly as the built-in array_column()
773 // does in PHP 5.5.
774 $argc = func_num_args();
775 $params = func_get_args();
776
777 if ( $argc < 2 ) {
778 trigger_error( sprintf( esc_html__( 'array_column() expects at least 2 parameters, %s given.', 'give' ), $argc ), E_USER_WARNING );
779
780 return null;
781 }
782
783 if ( ! is_array( $params[0] ) ) {
784 trigger_error( sprintf( esc_html__( 'array_column() expects parameter 1 to be array, %s given.', 'give' ), gettype( $params[0] ) ), E_USER_WARNING );
785
786 return null;
787 }
788
789 if ( ! is_int( $params[1] ) && ! is_float( $params[1] ) && ! is_string( $params[1] ) && $params[1] !== null && ! ( is_object( $params[1] ) && method_exists( $params[1], '__toString' ) ) ) {
790 trigger_error( esc_html__( 'array_column(): The column key should be either a string or an integer.', 'give' ), E_USER_WARNING );
791
792 return false;
793 }
794
795 if ( isset( $params[2] ) && ! is_int( $params[2] ) && ! is_float( $params[2] ) && ! is_string( $params[2] ) && ! ( is_object( $params[2] ) && method_exists( $params[2], '__toString' ) ) ) {
796 trigger_error( esc_html__( 'array_column(): The index key should be either a string or an integer.', 'give' ), E_USER_WARNING );
797
798 return false;
799 }
800
801 $paramsInput = $params[0];
802 $paramsColumnKey = ( $params[1] !== null ) ? (string) $params[1] : null;
803
804 $paramsIndexKey = null;
805 if ( isset( $params[2] ) ) {
806 if ( is_float( $params[2] ) || is_int( $params[2] ) ) {
807 $paramsIndexKey = (int) $params[2];
808 } else {
809 $paramsIndexKey = (string) $params[2];
810 }
811 }
812
813 $resultArray = array();
814
815 foreach ( $paramsInput as $row ) {
816 $key = $value = null;
817 $keySet = $valueSet = false;
818
819 if ( $paramsIndexKey !== null && array_key_exists( $paramsIndexKey, $row ) ) {
820 $keySet = true;
821 $key = (string) $row[ $paramsIndexKey ];
822 }
823
824 if ( $paramsColumnKey === null ) {
825 $valueSet = true;
826 $value = $row;
827 } elseif ( is_array( $row ) && array_key_exists( $paramsColumnKey, $row ) ) {
828 $valueSet = true;
829 $value = $row[ $paramsColumnKey ];
830 }
831
832 if ( $valueSet ) {
833 if ( $keySet ) {
834 $resultArray[ $key ] = $value;
835 } else {
836 $resultArray[] = $value;
837 }
838 }
839 }
840
841 return $resultArray;
842 }
843 }// End if().
844
845 /**
846 * Determines the receipt visibility status.
847 *
848 * @since 1.3.2
849 *
850 * @param int $donation_id Donation ID.
851 *
852 * @return bool Whether the receipt is visible or not.
853 */
854 function give_can_view_receipt( $donation_id ) {
855
856 global $give_receipt_args;
857
858 $donor = false;
859 $can_view_receipt = false;
860
861 // Bail out, if donation id doesn't exist.
862 if ( empty( $donation_id ) ) {
863 return $can_view_receipt;
864 }
865
866 $give_receipt_args['id'] = $donation_id;
867
868 // Add backward compatibility.
869 if ( ! is_numeric( $donation_id ) ) {
870 $give_receipt_args['id'] = give_get_donation_id_by_key( $donation_id );
871 }
872
873 // Return to download receipts from admin panel.
874 if ( current_user_can( 'export_give_reports' ) ) {
875
876 /**
877 * This filter will be used to modify can view receipt response when accessed from admin.
878 *
879 * @since 2.3.1
880 */
881 return apply_filters( 'give_can_admin_view_receipt', true );
882 }
883
884 if ( is_user_logged_in() || current_user_can( 'view_give_sensitive_data' ) ) {
885
886 // Proceed only, if user is logged in or can view sensitive Give data.
887 $donor = Give()->donors->get_donor_by( 'user_id', get_current_user_id() );
888
889 } elseif ( ! is_user_logged_in() ) {
890
891 // Check whether it is purchase session?
892 // This condition is to show receipt to donor after donation.
893 $purchase_session = give_get_purchase_session();
894 if (
895 ! empty( $purchase_session )
896 && $purchase_session['donation_id'] === $donation_id
897 ) {
898 $donor = Give()->donors->get_donor_by( 'email', $purchase_session['user_email'] );
899 }
900
901 // Check whether it is receipt access session?
902 $receipt_session = give_get_receipt_session();
903 if (
904 give_is_setting_enabled( give_get_option( 'email_access' ) ) &&
905 ! empty( $receipt_session )
906 ) {
907 $email_access_token = ! empty( $_COOKIE['give_nl'] ) ? give_clean( $_COOKIE['give_nl'] ) : false;
908 $donor = ! empty( $email_access_token )
909 ? Give()->donors->get_donor_by_token( $email_access_token )
910 : false ;
911 }
912 }
913
914 // If donor object exists, compare the donation ids of donor with the donation receipt donor tries to access.
915 if ( is_object( $donor ) ) {
916 $is_donor_donated = in_array( (int) $donation_id, array_map( 'absint', explode( ',', $donor->payment_ids ) ), true );
917 $can_view_receipt = $is_donor_donated ? true : $can_view_receipt;
918
919 if( ! $is_donor_donated ) {
920 Give()->session->set( 'donor_donation_mismatch', true );
921 }
922 }
923
924 return (bool) apply_filters( 'give_can_view_receipt', $can_view_receipt, $donation_id );
925
926 }
927
928 /**
929 * Fallback for cal_days_in_month
930 *
931 * Fallback in case the calendar extension is not loaded in PHP; Only supports Gregorian calendar
932 */
933 if ( ! function_exists( 'cal_days_in_month' ) ) {
934 /**
935 * cal_days_in_month
936 *
937 * @param int $calendar
938 * @param int $month
939 * @param int $year
940 *
941 * @return bool|string
942 */
943 function cal_days_in_month( $calendar, $month, $year ) {
944 return date( 't', mktime( 0, 0, 0, $month, 1, $year ) );
945 }
946 }
947
948 /**
949 * Get plugin info including status, type, and license validation.
950 *
951 * This is an enhanced version of get_plugins() that returns the status
952 * (`active` or `inactive`) of all plugins, type of plugin (`add-on` or `other`
953 * and license validation for Give add-ons (`true` or `false`). Does not include
954 * MU plugins.
955 *
956 * @since 1.8.0
957 *
958 * @return array Plugin info plus status, type, and license validation if
959 * available.
960 */
961 function give_get_plugins() {
962 $plugins = get_plugins();
963 $active_plugin_paths = (array) get_option( 'active_plugins', array() );
964
965 if ( is_multisite() ) {
966 $network_activated_plugin_paths = array_keys( get_site_option( 'active_sitewide_plugins', array() ) );
967 $active_plugin_paths = array_merge( $active_plugin_paths, $network_activated_plugin_paths );
968 }
969
970 foreach ( $plugins as $plugin_path => $plugin_data ) {
971 // Is plugin active?
972 if ( in_array( $plugin_path, $active_plugin_paths ) ) {
973 $plugins[ $plugin_path ]['Status'] = 'active';
974 } else {
975 $plugins[ $plugin_path ]['Status'] = 'inactive';
976 }
977
978 $dirname = strtolower( dirname( $plugin_path ) );
979
980 // Is the plugin a Give add-on?
981 if ( strstr( $dirname, 'give-' ) && strstr( $plugin_data['AuthorURI'], 'wordimpress.com' ) ) {
982 // Plugin is a Give-addon.
983 $plugins[ $plugin_path ]['Type'] = 'add-on';
984
985 /* @var stdClass $license_active */
986 $license_active = __give_get_active_license_info( Give_License::get_short_name( $plugin_data['Name'] ) );
987
988 // Does a valid license exist?
989 if ( ! empty( $license_active ) && 'valid' === $license_active->license ) {
990 $plugins[ $plugin_path ]['License'] = true;
991 } else {
992 $plugins[ $plugin_path ]['License'] = false;
993 }
994 } else {
995 // Plugin is not a Give add-on.
996 $plugins[ $plugin_path ]['Type'] = 'other';
997 }
998 }
999
1000 return $plugins;
1001 }
1002
1003 /**
1004 * Check if terms enabled or not for form.
1005 *
1006 * @since 1.8
1007 *
1008 * @param $form_id
1009 *
1010 * @return bool
1011 */
1012 function give_is_terms_enabled( $form_id ) {
1013 $form_option = give_get_meta( $form_id, '_give_terms_option', true );
1014
1015 if ( give_is_setting_enabled( $form_option, 'global' ) && give_is_setting_enabled( give_get_option( 'terms' ) ) ) {
1016 return true;
1017
1018 } elseif ( give_is_setting_enabled( $form_option ) ) {
1019 return true;
1020
1021 } else {
1022 return false;
1023 }
1024 }
1025
1026 /**
1027 * Delete donation stats cache.
1028 *
1029 * @todo Resolve stats cache key naming issue. Currently it is difficult to regenerate cache key.
1030 *
1031 * @since 1.8.7
1032 *
1033 * @param string|array $date_range Date for stats.
1034 * Date value should be in today, yesterday, this_week, last_week, this_month,
1035 * last_month, this_quarter, last_quarter, this_year, last_year. For date value other,
1036 * all cache will be removed.
1037 *
1038 * @param array $args
1039 *
1040 * @return WP_Error|bool
1041 */
1042 function give_delete_donation_stats( $date_range = '', $args = array() ) {
1043
1044 // Delete all cache.
1045 $status = Give_Cache::delete( Give_Cache::get_options_like( 'give_stats' ) );
1046
1047 /**
1048 * Fire the action when donation stats delete.
1049 *
1050 * @since 1.8.7
1051 *
1052 * @param string|array $date_range
1053 * @param array $args
1054 */
1055 do_action( 'give_delete_donation_stats', $status, $date_range, $args );
1056
1057 return $status;
1058 }
1059
1060 /**
1061 * Check if admin creating new donation form or not.
1062 *
1063 * @since 2.0
1064 * @return bool
1065 */
1066 function give_is_add_new_form_page() {
1067 $status = false;
1068
1069 if ( false !== strpos( $_SERVER['REQUEST_URI'], '/wp-admin/post-new.php?post_type=give_forms' ) ) {
1070 $status = true;
1071 }
1072
1073 return $status;
1074 }
1075
1076 /**
1077 * Get Form/Payment meta.
1078 *
1079 * Note: This function will help you to get meta for payment and form.
1080 * If you want to get meta for donors then use get_meta of Give_Donor and
1081 * If you want to get meta for logs then use get_meta of Give_Logging->logmeta_db.
1082 *
1083 * @since 1.8.8
1084 *
1085 * @param int $id
1086 * @param string $meta_key
1087 * @param bool $single
1088 * @param bool $default
1089 *
1090 * @return mixed
1091 */
1092 function give_get_meta( $id, $meta_key = '', $single = false, $default = false ) {
1093 /**
1094 * Filter the meta value
1095 *
1096 * @since 1.8.8
1097 */
1098 $meta_value = apply_filters( 'give_get_meta', get_post_meta( $id, $meta_key, $single ), $id, $meta_key, $default );
1099
1100 if ( ( empty( $meta_key ) || empty( $meta_value ) ) && $default ) {
1101 $meta_value = $default;
1102 }
1103
1104 return $meta_value;
1105 }
1106
1107 /**
1108 * Update Form/Payment meta.
1109 *
1110 * @since 1.8.8
1111 *
1112 * @param int $id
1113 * @param string $meta_key
1114 * @param mixed $meta_value
1115 * @param mixed $prev_value
1116 *
1117 * @return mixed
1118 */
1119 function give_update_meta( $id, $meta_key, $meta_value, $prev_value = '' ) {
1120 $status = update_post_meta( $id, $meta_key, $meta_value, $prev_value );
1121
1122 /**
1123 * Filter the meta value update status
1124 *
1125 * @since 1.8.8
1126 */
1127 return apply_filters( 'give_update_meta', $status, $id, $meta_key, $meta_value );
1128 }
1129
1130 /**
1131 * Delete Form/Payment meta.
1132 *
1133 * @since 1.8.8
1134 *
1135 * @param int $id
1136 * @param string $meta_key
1137 * @param string $meta_value
1138 *
1139 * @return mixed
1140 */
1141 function give_delete_meta( $id, $meta_key, $meta_value = '' ) {
1142 $status = delete_post_meta( $id, $meta_key, $meta_value );
1143
1144 /**
1145 * Filter the meta value delete status
1146 *
1147 * @since 1.8.8
1148 */
1149 return apply_filters( 'give_delete_meta', $status, $id, $meta_key, $meta_value );
1150 }
1151
1152 /**
1153 * Check if the upgrade routine has been run for a specific action
1154 *
1155 * @since 1.0
1156 *
1157 * @param string $upgrade_action The upgrade action to check completion for
1158 *
1159 * @return bool If the action has been added to the completed actions array
1160 */
1161 function give_has_upgrade_completed( $upgrade_action = '' ) {
1162 // Bailout.
1163 if ( empty( $upgrade_action ) ) {
1164 return false;
1165 }
1166
1167 // Fresh install?
1168 // If fresh install then all upgrades will be consider as completed.
1169 $is_fresh_install = ! get_option( 'give_version' );
1170 if ( $is_fresh_install ) {
1171 return true;
1172 }
1173
1174 $completed_upgrades = give_get_completed_upgrades();
1175
1176 return in_array( $upgrade_action, $completed_upgrades );
1177
1178 }
1179
1180 /**
1181 * For use when doing 'stepped' upgrade routines, to see if we need to start somewhere in the middle
1182 *
1183 * @since 1.8
1184 *
1185 * @return mixed When nothing to resume returns false, otherwise starts the upgrade where it left off
1186 */
1187 function give_maybe_resume_upgrade() {
1188 $doing_upgrade = get_option( 'give_doing_upgrade', false );
1189 if ( empty( $doing_upgrade ) ) {
1190 return false;
1191 }
1192
1193 return $doing_upgrade;
1194 }
1195
1196 /**
1197 * Adds an upgrade action to the completed upgrades array
1198 *
1199 * @since 1.0
1200 *
1201 * @param string $upgrade_action The action to add to the completed upgrades array
1202 *
1203 * @return bool If the function was successfully added
1204 */
1205 function give_set_upgrade_complete( $upgrade_action = '' ) {
1206
1207 if ( empty( $upgrade_action ) ) {
1208 return false;
1209 }
1210
1211 $completed_upgrades = give_get_completed_upgrades();
1212 $completed_upgrades[] = $upgrade_action;
1213
1214 // Remove any blanks, and only show uniques.
1215 $completed_upgrades = array_unique( array_values( $completed_upgrades ) );
1216
1217 /**
1218 * Fire the action when any upgrade set to complete.
1219 *
1220 * @since 1.8.12
1221 */
1222 do_action( 'give_set_upgrade_completed', $upgrade_action, $completed_upgrades );
1223
1224 return update_option( 'give_completed_upgrades', $completed_upgrades, false );
1225 }
1226
1227 /**
1228 * Get's the array of completed upgrade actions
1229 *
1230 * @since 1.0
1231 * @return array The array of completed upgrades
1232 */
1233 function give_get_completed_upgrades() {
1234 return (array) get_option( 'give_completed_upgrades' );
1235 }
1236
1237 /**
1238 * In 2.0 we updated table for log, payment and form.
1239 *
1240 * Note: internal purpose only.
1241 *
1242 * @since 2.0
1243 * @global wpdb $wpdb
1244 *
1245 * @param string $type Context for table
1246 *
1247 * @return null|array
1248 */
1249 function __give_v20_bc_table_details( $type ) {
1250 global $wpdb;
1251 $table = array();
1252
1253 // Bailout.
1254 if ( empty( $type ) ) {
1255 return null;
1256 }
1257
1258 switch ( $type ) {
1259 case 'form':
1260 $table['name'] = $wpdb->formmeta;
1261 $table['column']['id'] = 'form_id';
1262
1263 break;
1264
1265 case 'payment':
1266 $table['name'] = $wpdb->donationmeta;
1267 $table['column']['id'] = Give()->payment_meta->get_meta_type() . '_id';
1268 }
1269
1270 // Backward compatibility.
1271 if ( ! give_has_upgrade_completed( 'v20_move_metadata_into_new_table' ) ) {
1272 $table['name'] = $wpdb->postmeta;
1273 $table['column']['id'] = 'post_id';
1274 }
1275
1276 return $table;
1277 }
1278
1279 /**
1280 * Remove the Give transaction pages from WP search results.
1281 *
1282 * @since 1.8.13
1283 *
1284 * @param WP_Query $query
1285 */
1286 function give_remove_pages_from_search( $query ) {
1287
1288 if ( ! $query->is_admin && $query->is_search && $query->is_main_query() ) {
1289
1290 $transaction_failed = give_get_option( 'failure_page', 0 );
1291 $success_page = give_get_option( 'success_page', 0 );
1292
1293 $args = apply_filters(
1294 'give_remove_pages_from_search', array(
1295 $transaction_failed,
1296 $success_page,
1297 ), $query
1298 );
1299 $query->set( 'post__not_in', $args );
1300 }
1301 }
1302
1303 add_action( 'pre_get_posts', 'give_remove_pages_from_search', 10, 1 );
1304
1305 /**
1306 * Inserts a new key/value before a key in the array.
1307 *
1308 * @since 1.8.13
1309 *
1310 * @param string $key The key to insert before.
1311 * @param array $array An array to insert in to.
1312 * @param string $new_key The key to insert.
1313 * @param array|string $new_value An value to insert.
1314 *
1315 * @return array The new array if the key exists, the passed array otherwise.
1316 *
1317 * @see array_insert_before()
1318 */
1319 function give_array_insert_before( $key, array &$array, $new_key, $new_value ) {
1320 if ( array_key_exists( $key, $array ) ) {
1321 $new = array();
1322 foreach ( $array as $k => $value ) {
1323 if ( $k === $key ) {
1324 $new[ $new_key ] = $new_value;
1325 }
1326 $new[ $k ] = $value;
1327 }
1328
1329 return $new;
1330 }
1331
1332 return $array;
1333 }
1334
1335 /**
1336 * Inserts a new key/value after a key in the array.
1337 *
1338 * @since 1.8.13
1339 *
1340 * @param string $key The key to insert after.
1341 * @param array $array An array to insert in to.
1342 * @param string $new_key The key to insert.
1343 * @param array|string $new_value An value to insert.
1344 *
1345 * @return array The new array if the key exists, the passed array otherwise.
1346 *
1347 * @see array_insert_before()
1348 */
1349 function give_array_insert_after( $key, array &$array, $new_key, $new_value ) {
1350 if ( array_key_exists( $key, $array ) ) {
1351 $new = array();
1352 foreach ( $array as $k => $value ) {
1353 $new[ $k ] = $value;
1354 if ( $k === $key ) {
1355 $new[ $new_key ] = $new_value;
1356 }
1357 }
1358
1359 return $new;
1360 }
1361
1362 return $array;
1363 }
1364
1365 /**
1366 * Pluck a certain field out of each object in a list.
1367 *
1368 * This has the same functionality and prototype of
1369 * array_column() (PHP 5.5) but also supports objects.
1370 *
1371 * @since 1.8.13
1372 *
1373 * @param array $list List of objects or arrays
1374 * @param int|string $field Field from the object to place instead of the entire object
1375 * @param int|string $index_key Optional. Field from the object to use as keys for the new array.
1376 * Default null.
1377 *
1378 * @return array Array of found values. If `$index_key` is set, an array of found values with keys
1379 * corresponding to `$index_key`. If `$index_key` is null, array keys from the original
1380 * `$list` will be preserved in the results.
1381 */
1382 function give_list_pluck( $list, $field, $index_key = null ) {
1383
1384 if ( ! $index_key ) {
1385 /**
1386 * This is simple. Could at some point wrap array_column()
1387 * if we knew we had an array of arrays.
1388 */
1389 foreach ( $list as $key => $value ) {
1390 if ( is_object( $value ) ) {
1391 if ( isset( $value->$field ) ) {
1392 $list[ $key ] = $value->$field;
1393 }
1394 } else {
1395 if ( isset( $value[ $field ] ) ) {
1396 $list[ $key ] = $value[ $field ];
1397 }
1398 }
1399 }
1400
1401 return $list;
1402 }
1403
1404 /*
1405 * When index_key is not set for a particular item, push the value
1406 * to the end of the stack. This is how array_column() behaves.
1407 */
1408 $newlist = array();
1409 foreach ( $list as $value ) {
1410 if ( is_object( $value ) ) {
1411 if ( isset( $value->$index_key ) ) {
1412 $newlist[ $value->$index_key ] = $value->$field;
1413 } else {
1414 $newlist[] = $value->$field;
1415 }
1416 } else {
1417 if ( isset( $value[ $index_key ] ) ) {
1418 $newlist[ $value[ $index_key ] ] = $value[ $field ];
1419 } else {
1420 $newlist[] = $value[ $field ];
1421 }
1422 }
1423 }
1424
1425 $list = $newlist;
1426
1427 return $list;
1428 }
1429
1430 /**
1431 * Add meta data field to a donor.
1432 *
1433 * @since 1.8.13
1434 *
1435 * @param int $donor_id Donor ID.
1436 * @param string $meta_key Metadata name.
1437 * @param mixed $meta_value Metadata value. Must be serializable if non-scalar.
1438 * @param bool $unique Optional. Whether the same key should not be added.
1439 * Default false.
1440 *
1441 * @return int|false Meta ID on success, false on failure.
1442 */
1443 function add_donor_meta( $donor_id, $meta_key, $meta_value, $unique = false ) {
1444 return add_metadata( 'give_customer', $donor_id, $meta_key, $meta_value, $unique );
1445 }
1446
1447 /**
1448 * Remove metadata matching criteria from a Donor meta.
1449 *
1450 * You can match based on the key, or key and value. Removing based on key and
1451 * value, will keep from removing duplicate metadata with the same key. It also
1452 * allows removing all metadata matching key, if needed.
1453 *
1454 * @since 1.8.13
1455 *
1456 * @param int $donor_id Donor ID
1457 * @param string $meta_key Metadata name.
1458 * @param mixed $meta_value Optional. Metadata value.
1459 *
1460 * @return bool True on success, false on failure.
1461 */
1462 function delete_donor_meta( $donor_id, $meta_key, $meta_value = '' ) {
1463 return delete_metadata( 'give_customer', $donor_id, $meta_key, $meta_value );
1464 }
1465
1466 /**
1467 * Retrieve donor meta field for a donor meta table.
1468 *
1469 * @since 1.8.13
1470 *
1471 * @param int $donor_id Donor ID.
1472 * @param string $key Optional. The meta key to retrieve. By default, returns data for all keys.
1473 * @param bool $single Whether to return a single value.
1474 *
1475 * @return mixed Will be an array if $single is false. Will be value of meta data field if $single
1476 * is true.
1477 */
1478 function get_donor_meta( $donor_id, $key = '', $single = false ) {
1479 return get_metadata( 'give_customer', $donor_id, $key, $single );
1480 }
1481
1482 /**
1483 * Update customer meta field based on Donor ID.
1484 *
1485 * If the meta field for the donor does not exist, it will be added.
1486 *
1487 * @since 1.8.13
1488 *
1489 * @param int $donor_id Donor ID.
1490 * @param string $meta_key Metadata key.
1491 * @param mixed $meta_value Metadata value.
1492 * @param mixed $prev_value Optional. Previous value to check before removing.
1493 *
1494 * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.
1495 */
1496 function update_donor_meta( $donor_id, $meta_key, $meta_value, $prev_value = '' ) {
1497 return update_metadata( 'give_customer', $donor_id, $meta_key, $meta_value, $prev_value );
1498 }
1499
1500
1501 /**
1502 * Give recalculate income and donation of the donation from ID
1503 *
1504 * @since 1.8.13
1505 *
1506 * @param int $form_id Form id of which recalculation needs to be done.
1507 *
1508 * @return void
1509 */
1510 function give_recount_form_income_donation( $form_id = 0 ) {
1511 // Check if form id is not empty.
1512 if ( ! empty( $form_id ) ) {
1513 /**
1514 * Filter to modify payment status.
1515 *
1516 * @since 1.8.13
1517 */
1518 $accepted_statuses = apply_filters( 'give_recount_accepted_statuses', array( 'publish' ) );
1519
1520 /**
1521 * Filter to modify args of payment query before recalculating the form total
1522 *
1523 * @since 1.8.13
1524 */
1525 $args = apply_filters(
1526 'give_recount_form_stats_args', array(
1527 'give_forms' => $form_id,
1528 'status' => $accepted_statuses,
1529 'posts_per_page' => - 1,
1530 'fields' => 'ids',
1531 )
1532 );
1533
1534 $totals = array(
1535 'sales' => 0,
1536 'earnings' => 0,
1537 );
1538
1539 $payments = new Give_Payments_Query( $args );
1540 $payments = $payments->get_payments();
1541
1542 if ( $payments ) {
1543 foreach ( $payments as $payment ) {
1544 // Ensure acceptible status only
1545 if ( ! in_array( $payment->post_status, $accepted_statuses ) ) {
1546 continue;
1547 }
1548
1549 // Ensure only payments for this form are counted
1550 if ( $payment->form_id != $form_id ) {
1551 continue;
1552 }
1553
1554 $totals['sales'] ++;
1555 $totals['earnings'] += $payment->total;
1556
1557 }
1558 }
1559 give_update_meta( $form_id, '_give_form_sales', $totals['sales'] );
1560 give_update_meta( $form_id, '_give_form_earnings', give_sanitize_amount_for_db( $totals['earnings'] ) );
1561 }// End if().
1562 }
1563
1564
1565 /**
1566 * Get attribute string
1567 *
1568 * @since 1.8.17
1569 *
1570 * @param array $attributes
1571 * @param array $default_attributes
1572 *
1573 * @return string
1574 */
1575 function give_get_attribute_str( $attributes, $default_attributes = array() ) {
1576 $attribute_str = '';
1577
1578 if ( isset( $attributes['attributes'] ) ) {
1579 $attributes = $attributes['attributes'];
1580 }
1581
1582 if ( ! empty( $default_attributes ) ) {
1583 $attributes = wp_parse_args( $attributes, $default_attributes );
1584 }
1585
1586 if ( empty( $attributes ) ) {
1587 return $attribute_str;
1588 }
1589
1590 foreach ( $attributes as $tag => $value ) {
1591 if( 'value' == $tag ){
1592 $value = esc_attr( $value );
1593 }
1594
1595 $attribute_str .= " {$tag}=\"{$value}\"";
1596 }
1597
1598 return trim( $attribute_str );
1599 }
1600
1601 /**
1602 * Get the upload dir path
1603 *
1604 * @since 1.8.17
1605 *
1606 * @return string $wp_upload_dir;
1607 */
1608 function give_get_wp_upload_dir() {
1609 $wp_upload_dir = wp_upload_dir();
1610
1611 return ( ! empty( $wp_upload_dir['path'] ) ? $wp_upload_dir['path'] : false );
1612 }
1613
1614 /**
1615 * Get the data from uploaded JSON file
1616 *
1617 * @since 1.8.17
1618 *
1619 * @param string $file_name filename of the json file that is being uploaded
1620 *
1621 * @return string|bool $file_contents File content
1622 */
1623 function give_get_core_settings_json( $file_name ) {
1624 $upload_dir = give_get_wp_upload_dir();
1625 $file_path = $upload_dir . '/' . $file_name;
1626
1627 if ( is_wp_error( $file_path ) || empty( $file_path ) ) {
1628 Give_Admin_Settings::add_error( 'give-import-csv', __( 'Please upload or provide a valid JSON file.', 'give' ) );
1629 }
1630
1631 $file_contents = file_get_contents( $file_path );
1632
1633 return $file_contents;
1634 }
1635
1636 /**
1637 * Get number of donation to show when user is not login.
1638 *
1639 * @since 1.8.17
1640 *
1641 * @return int $country The two letter country code for the site's base country
1642 */
1643 function give_get_limit_display_donations() {
1644 return give_get_option( 'limit_display_donations', 1 );
1645 }
1646
1647 /**
1648 * Add footer to the table when donor is view the donation history page with out login
1649 *
1650 * @since 1.8.17
1651 */
1652 function give_donation_history_table_end() {
1653 $email = Give()->session->get( 'give_email' );
1654 ?>
1655 <tfoot>
1656 <tr>
1657 <td colspan="9999">
1658 <div class="give-security-wrap">
1659 <div class="give-security-column give-security-description-wrap">
1660 <?php
1661 echo sprintf( __( 'For security reasons, please confirm your email address (%s) to view your complete donation history.', 'give' ), $email );
1662 ?>
1663 </div>
1664 <div class="give-security-column give-security-button-wrap">
1665 <a href="#" data-email="<?php echo $email; ?>" id="give-confirm-email-btn"
1666 class="give-confirm-email-btn give-btn">
1667 <?php _e( 'Confirm Email', 'give' ); ?>
1668 </a>
1669 <span><?php _e( 'Email Sent!', 'give' ); ?></span>
1670 </div>
1671 </div>
1672 </td>
1673 </tr>
1674 </tfoot>
1675 <?php
1676 }
1677
1678
1679 /**
1680 * Wrapper for _doing_it_wrong.
1681 *
1682 * @since 1.8.18
1683 *
1684 * @param string $function
1685 * @param string $message
1686 * @param string $version
1687 *
1688 * @return void
1689 */
1690 function give_doing_it_wrong( $function, $message, $version ) {
1691 $message .= "\nBacktrace:" . wp_debug_backtrace_summary();
1692
1693 _doing_it_wrong( $function, $message, $version );
1694 }
1695
1696
1697 /**
1698 * Remove limit from running php script complete.
1699 *
1700 * @since 1.8.18
1701 */
1702 function give_ignore_user_abort() {
1703 ignore_user_abort( true );
1704
1705 if ( ! give_is_func_disabled( 'set_time_limit' ) && ! ini_get( 'safe_mode' ) ) {
1706 set_time_limit( 0 );
1707 }
1708 }
1709
1710 /**
1711 * Get post type count.
1712 *
1713 * @since 2.0.2
1714 *
1715 * @param string $post_type
1716 * @param array $args
1717 *
1718 * @return int
1719 */
1720 function give_get_total_post_type_count( $post_type = '', $args = array() ) {
1721 global $wpdb;
1722 $where = '';
1723
1724 if ( ! $post_type ) {
1725 return 0;
1726 }
1727
1728 // Bulit where query
1729 if ( ! empty( $post_type ) ) {
1730 $where .= ' WHERE';
1731
1732 if ( is_array( $post_type ) ) {
1733 $where .= " post_type='" . implode( "' OR post_type='", $post_type ) . "'";
1734 } else {
1735 $where .= " post_type='{$post_type}'";
1736 }
1737 }
1738
1739 $result = $wpdb->get_var( "SELECT count(ID) FROM {$wpdb->posts}{$where}" );
1740
1741 return absint( $result );
1742 }
1743
1744 /**
1745 * Define a constant if it is not already defined.
1746 *
1747 * @since 2.0.5
1748 *
1749 * @param string $name Constant name.
1750 * @param string $value Value.
1751 *
1752 * @credit WooCommerce
1753 */
1754 function give_maybe_define_constant( $name, $value ) {
1755 if ( ! defined( $name ) ) {
1756 define( $name, $value );
1757 }
1758 }
1759
1760 /**
1761 * Decode time short tag in string
1762 *
1763 * @since 2.1.0
1764 *
1765 * @param string $string
1766 * @param int $timestamp
1767 *
1768 * @return string
1769 */
1770 function give_time_do_tags( $string, $timestamp = 0 ) {
1771 $current_time = ! empty( $timestamp ) ? $timestamp : current_time( 'timestamp' );
1772
1773 $formatted_string = str_replace(
1774 array(
1775 '{D}',
1776 '{DD}',
1777 '{M}',
1778 '{MM}',
1779 '{YY}',
1780 '{YYYY}',
1781 '{H}',
1782 '{HH}',
1783 '{N}',
1784 '{S}',
1785 ), array(
1786 date( 'j', $current_time ),
1787 date( 'd', $current_time ),
1788 date( 'n', $current_time ),
1789 date( 'm', $current_time ),
1790 date( 'Y', $current_time ),
1791 date( 'Y', $current_time ),
1792 date( 'G', $current_time ),
1793 date( 'H', $current_time ),
1794 date( 's', $current_time ),
1795 ), $string
1796 );
1797
1798 /**
1799 * Filter the parsed string.
1800 *
1801 * @since 2.1.0
1802 */
1803 return apply_filters( 'give_time_do_tags', $formatted_string, $string, $timestamp );
1804 }
1805
1806
1807 /**
1808 * Check if Company field enabled or not for form or globally.
1809 *
1810 * @since 2.1
1811 *
1812 * @param $form_id
1813 *
1814 * @return bool
1815 */
1816 function give_is_company_field_enabled( $form_id ) {
1817 $form_setting_val = give_get_meta( $form_id, '_give_company_field', true );
1818 $global_setting_val = give_get_option( 'company_field' );
1819
1820 if ( ! empty( $form_setting_val ) ) {
1821 if ( give_is_setting_enabled( $form_setting_val, array( 'required', 'optional' ) ) ) {
1822 return true;
1823 } elseif ( 'global' === $form_setting_val && give_is_setting_enabled(
1824 $global_setting_val, array(
1825 'required',
1826 'optional',
1827 )
1828 ) ) {
1829 return true;
1830 } else {
1831 return false;
1832 }
1833 } elseif ( give_is_setting_enabled( $global_setting_val, array( 'required', 'optional' ) ) ) {
1834 return true;
1835
1836 } else {
1837 return false;
1838 }
1839 }
1840
1841 /**
1842 * Check if anonymous donation field enabled or not for form or globally.
1843 *
1844 * @since 2.1
1845 *
1846 * @param $form_id
1847 *
1848 * @return bool
1849 */
1850 function give_is_anonymous_donation_field_enabled( $form_id ) {
1851 $form_setting_val = give_get_meta( $form_id, '_give_anonymous_donation', true, 'global' );
1852 $global_setting_val = give_get_option( 'anonymous_donation', 'disabled' );
1853
1854 if ( ! empty( $form_setting_val ) ) {
1855 if ( give_is_setting_enabled( $form_setting_val ) ) {
1856 return true;
1857 } elseif ( 'global' === $form_setting_val && give_is_setting_enabled( $global_setting_val ) ) {
1858 return true;
1859 } else {
1860 return false;
1861 }
1862 } elseif ( give_is_setting_enabled( $global_setting_val ) ) {
1863 return true;
1864 }
1865
1866 return false;
1867 }
1868
1869 /**
1870 * Check if donor comment field enabled or not for form or globally.
1871 *
1872 * @since 2.1
1873 *
1874 * @param $form_id
1875 *
1876 * @return bool
1877 */
1878 function give_is_donor_comment_field_enabled( $form_id ) {
1879 $form_setting_val = give_get_meta( $form_id, '_give_donor_comment', true, 'global' );
1880 $global_setting_val = give_get_option( 'donor_comment', 'disabled' );
1881
1882 if ( ! empty( $form_setting_val ) ) {
1883 if ( give_is_setting_enabled( $form_setting_val ) ) {
1884 return true;
1885 } elseif ( 'global' === $form_setting_val && give_is_setting_enabled( $global_setting_val ) ) {
1886 return true;
1887 } else {
1888 return false;
1889 }
1890 } elseif ( give_is_setting_enabled( $global_setting_val ) ) {
1891 return true;
1892 }
1893
1894 return false;
1895
1896 }
1897
1898 /**
1899 * Get add-on user meta value information
1900 * Note: only for internal use.
1901 *
1902 * @since 2.1.0
1903 *
1904 * @param string $license_id
1905 *
1906 * @return array
1907 */
1908 function __give_get_active_license_info( $license_id ) {
1909 global $wpdb;
1910 $option_name = "{$license_id}_license_active";
1911 $data = array();
1912
1913 if ( ! isset( $GLOBALS['give_active_licenses_info'] ) ) {
1914 $GLOBALS['give_active_licenses_info'] = array();
1915
1916 $licenses_info = $wpdb->get_results(
1917 "
1918 SELECT option_name, option_value
1919 FROM {$wpdb->options}
1920 WHERE option_name LIKE '%_license_active%'
1921 AND option_name LIKE '%give_%'
1922 ",
1923 ARRAY_A
1924 );
1925
1926 if ( ! empty( $licenses_info ) ) {
1927 $GLOBALS['give_active_licenses_info'] = array_combine(
1928 wp_list_pluck( $licenses_info, 'option_name' ),
1929 wp_list_pluck( $licenses_info, 'option_value' )
1930 );
1931 }
1932 }
1933
1934 if ( in_array( $option_name, array_keys( $GLOBALS['give_active_licenses_info'] ) ) ) {
1935 $data = maybe_unserialize( $GLOBALS['give_active_licenses_info'][ $option_name ] );
1936 }
1937
1938 return $data;
1939 }
1940
1941 /**
1942 * Get add-on user meta value information
1943 * Note: only for internal use.
1944 *
1945 * @since 2.1.0
1946 *
1947 * @param string $banner_addon_name Give add-on name.
1948 *
1949 * @return array
1950 */
1951 function __give_get_active_by_user_meta( $banner_addon_name ) {
1952 global $wpdb;
1953
1954 // Get the option key.
1955 $option_name = Give_Addon_Activation_Banner::get_banner_user_meta_key( $banner_addon_name );
1956 $data = array();
1957
1958 if (
1959 ! isset( $GLOBALS['give_addon_activated_by_user'][ $banner_addon_name ] )
1960 || empty( $GLOBALS['give_addon_activated_by_user'][ $banner_addon_name ] )
1961 ) {
1962 $GLOBALS['give_addon_activated_by_user'][ $banner_addon_name ] = array();
1963
1964 // Get the meta of activation banner by user.
1965 $activation_banners = $wpdb->get_results(
1966 "
1967 SELECT option_name, option_value
1968 FROM {$wpdb->options}
1969 WHERE option_name LIKE '%_active_by_user%'
1970 AND option_name LIKE '%give_addon%'
1971 ",
1972 ARRAY_A
1973 );
1974
1975 if ( ! empty( $activation_banners ) ) {
1976 $GLOBALS['give_addon_activated_by_user'] = array_combine(
1977 wp_list_pluck( $activation_banners, 'option_name' ),
1978 wp_list_pluck( $activation_banners, 'option_value' )
1979 );
1980 }
1981 }
1982
1983 if ( in_array( $option_name, array_keys( $GLOBALS['give_addon_activated_by_user'] ) ) ) {
1984 $data = maybe_unserialize( $GLOBALS['give_addon_activated_by_user'][ $option_name ] );
1985 }
1986
1987 return $data;
1988 }
1989
1990 /**
1991 * Get time interval for which nonce is valid
1992 *
1993 * @since 2.1.3
1994 *
1995 * @return int
1996 */
1997 function give_get_nonce_life() {
1998 /**
1999 * Filters the lifespan of nonces in seconds.
2000 *
2001 * @see wp-inlucdes/pluggable.php:wp_nonce_tick
2002 */
2003 return (int) apply_filters( 'nonce_life', DAY_IN_SECONDS );
2004 }
2005
2006 /**
2007 * Get nonce field without id
2008 *
2009 * @since 2.1.3
2010 *
2011 * @param string $action
2012 * @param string $name
2013 * @param bool $referer
2014 *
2015 * @return string
2016 */
2017 function give_get_nonce_field( $action, $name, $referer = false ) {
2018 return str_replace(
2019 "id=\"{$name}\"",
2020 '',
2021 wp_nonce_field( $action, $name, $referer, false )
2022 );
2023 }
2024
2025 /**
2026 * Display/Return a formatted goal for a donation form
2027 *
2028 * @param int|Give_Donate_Form $form Form ID or Form Object.
2029 *
2030 * @since 2.1
2031 *
2032 * @return array
2033 */
2034 function give_goal_progress_stats( $form ) {
2035
2036 if ( ! $form instanceof Give_Donate_Form ) {
2037 $form = new Give_Donate_Form( $form );
2038 }
2039
2040 $donors = '';
2041
2042 $goal_format = give_get_form_goal_format( $form->ID );
2043
2044 /**
2045 * Filter the form.
2046 *
2047 * @since 1.8.8
2048 */
2049 $total_goal = apply_filters( 'give_goal_amount_target_output', round( give_maybe_sanitize_amount( $form->goal ), 2 ), $form->ID, $form );
2050
2051 switch ( $goal_format ) {
2052 case 'donation':
2053 /**
2054 * Filter the form donations.
2055 *
2056 * @since 2.1
2057 */
2058 $actual = $donations = apply_filters( 'give_goal_donations_raised_output', $form->sales, $form->ID, $form );
2059 break;
2060 case 'donors':
2061 /**
2062 * Filter to modify total number if donor for the donation form.
2063 *
2064 * @since 2.1.3
2065 *
2066 * @param int $donors Total number of donors that donated to the form.
2067 * @param int $form_id Donation Form ID.
2068 * @param Give_Donate_Form $form instances of Give_Donate_Form.
2069 *
2070 * @return int $donors Total number of donors that donated to the form.
2071 */
2072 $actual = $donors = apply_filters( 'give_goal_donors_target_output', give_get_form_donor_count( $form->ID ), $form->ID, $form );
2073 break;
2074 default:
2075 /**
2076 * Filter the form income.
2077 *
2078 * @since 1.8.8
2079 */
2080 $actual = $income = apply_filters( 'give_goal_amount_raised_output', $form->earnings, $form->ID, $form );
2081 break;
2082 }
2083
2084 $progress = $total_goal ? round( ( $actual / $total_goal ) * 100, 2 ) : 0;
2085
2086 $stats_array = array(
2087 'raw_actual' => $actual,
2088 'raw_goal' => $total_goal,
2089 );
2090
2091 /**
2092 * Filter the goal progress output
2093 *
2094 * @since 1.8.8
2095 */
2096 $progress = apply_filters( 'give_goal_amount_funded_percentage_output', $progress, $form->ID, $form );
2097
2098 // Define Actual Goal based on the goal format.
2099 if ( 'percentage' === $goal_format ) {
2100 $actual = "{$actual}%";
2101 } elseif ( 'amount' === $goal_format ) {
2102 $actual = give_currency_filter( give_format_amount( $actual ) );
2103 }
2104
2105 // Define Total Goal based on the goal format.
2106 if ( 'percentage' === $goal_format ) {
2107 $total_goal = '';
2108 } elseif ( 'amount' === $goal_format ) {
2109 $total_goal = give_currency_filter( give_format_amount( $total_goal ) );
2110 }
2111
2112 $stats_array = array_merge(
2113 array(
2114 'progress' => $progress,
2115 'actual' => $actual,
2116 'goal' => $total_goal,
2117 'format' => $goal_format,
2118 ),
2119 $stats_array
2120 );
2121
2122 /**
2123 * Filter the goal stats
2124 *
2125 * @since 2.1
2126 */
2127 return apply_filters( 'give_goal_progress_stats', $stats_array );
2128 }
2129
2130 /**
2131 * Get the admin messages key to show the notices.
2132 *
2133 * @since 2.1.4
2134 *
2135 * @return array $message admin message key.
2136 */
2137 function give_get_admin_messages_key() {
2138 $messages = empty( $_GET['give-messages'] ) ? array() : give_clean( $_GET['give-messages'] );
2139
2140 // backward compatibility.
2141 if ( ! empty( $_GET['give-message'] ) ) {
2142 $messages[] = give_clean( $_GET['give-message'] );
2143 }
2144
2145 /**
2146 * Filter to modify the admin messages key.
2147 *
2148 * @since 2.1.4
2149 *
2150 * @param array $message admin message key.
2151 *
2152 * @return array $message admin message key.
2153 */
2154 return (array) apply_filters( 'give_get_admin_messages_key', $messages );
2155 }
2156
2157 /**
2158 * Get User Agent String.
2159 *
2160 * @since 2.1.4
2161 *
2162 * @return array|string
2163 */
2164 function give_get_user_agent() {
2165
2166 // Get User Agent.
2167 $user_agent = ! empty( $_SERVER['HTTP_USER_AGENT'] ) ? give_clean( $_SERVER['HTTP_USER_AGENT'] ) : ''; // WPCS: input var ok.
2168
2169 return $user_agent;
2170 }
2171
2172 /**
2173 * Set a cookie - wrapper for setcookie using WP constants.
2174 *
2175 * @since 2.2.0
2176 *
2177 * @param string $name Name of the cookie being set.
2178 * @param string $value Value of the cookie.
2179 * @param integer $expire Expiry of the cookie.
2180 * @param bool $secure Whether the cookie should be served only over https.
2181 */
2182 function give_setcookie( $name, $value, $expire = 0, $secure = false ) {
2183 if ( ! headers_sent() ) {
2184 setcookie(
2185 $name, $value, $expire, COOKIEPATH ? COOKIEPATH : '/', COOKIE_DOMAIN, $secure,
2186 apply_filters( 'give_cookie_httponly', false, $name, $value, $expire, $secure )
2187 );
2188 }
2189 }
2190
2191 /**
2192 * Get formatted billing address.
2193 *
2194 * @since 2.2.0
2195 *
2196 * @param array $address
2197 *
2198 * @return string Formatted address.
2199 */
2200 function give_get_formatted_address( $address = array() ) {
2201 $formatted_address = '';
2202
2203 /**
2204 * Address format.
2205 *
2206 * @since 2.2.0
2207 */
2208 $address_format = apply_filters( 'give_address_format_template', "{street_address}\n{city}, {state} {postal_code}\n{country}" );
2209 preg_match_all( '/{([A-z0-9\-\_\ ]+)}/s', $address_format, $matches );
2210
2211 if ( ! empty( $matches ) && ! empty( $address ) ) {
2212 $address_values = array();
2213
2214 foreach ( $matches[1] as $address_tag ) {
2215 $address_values[ $address_tag ] = '';
2216
2217 if ( isset( $address[ $address_tag ] ) ) {
2218 $address_values[ $address_tag ] = $address[ $address_tag ];
2219 }
2220 }
2221
2222 $formatted_address = str_ireplace( $matches[0], $address_values, $address_format );
2223 }
2224
2225 /**
2226 * Give get formatted address.
2227 *
2228 * @since 2.2.0
2229 *
2230 * @param string $formatted_address Formatted address.
2231 * @param string $address_format Format of the address.
2232 */
2233 $formatted_address = apply_filters( 'give_get_formatted_address', $formatted_address, $address_format, $address );
2234
2235 return $formatted_address;
2236 }
2237
2238 /**
2239 * Get safe url for assets
2240 * Note: this function will return url without http protocol
2241 *
2242 * @since 2.2.0
2243 *
2244 * @param string $url URL
2245 *
2246 * @return string
2247 */
2248 function give_get_safe_asset_url( $url ) {
2249
2250 // Bailout, if empty URL passed.
2251 if ( empty( $url ) ) {
2252 return $url;
2253 }
2254
2255 $schema = parse_url( $url, PHP_URL_SCHEME );
2256 $schema_length = strlen( $schema ) + 1;
2257 $url = substr( $url, $schema_length );
2258
2259 /**
2260 * Fire the filter
2261 *
2262 * @since 2.2.0
2263 */
2264 return apply_filters( 'give_get_safe_asset_url', $url );
2265 }
2266
2267 /**
2268 * Give get formatted date.
2269 *
2270 * @since 2.3.0
2271 *
2272 * @param string $date Date.
2273 * @param string $format Date Format.
2274 * @param string $current_format Current date Format.
2275 *
2276 * @return string
2277 */
2278 function give_get_formatted_date( $date, $format = 'Y-m-d', $current_format = '' ) {
2279 $current_format = empty( $current_format ) ? give_date_format() : $current_format;
2280 $date_obj = DateTime::createFromFormat( $current_format, $date );
2281 $formatted_date = $date_obj->format( $format );
2282
2283 /**
2284 * Give get formatted date.
2285 *
2286 * @since 2.3.0
2287 *
2288 * @param string $formatted_date Formatted date.
2289 * @param array
2290 */
2291 return apply_filters( 'give_get_formatted_date', $formatted_date, array( $date, $format, $current_format ) );
2292 }
2293
2294 /**
2295 * This function will be used to fetch the donation receipt link.
2296 *
2297 * @param int $donation_id Donation ID.
2298 *
2299 * @since 2.3.1
2300 *
2301 * @return string
2302 */
2303 function give_get_receipt_link( $donation_id ) {
2304
2305 return sprintf(
2306 '<a href="%1$s">%2$s</a>',
2307 esc_url( give_get_receipt_url( $donation_id ) ),
2308 esc_html__( 'View the receipt in your browser &raquo;', 'give' )
2309 );
2310
2311 }
2312