PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.16.9
GiveWP – Donation Plugin and Fundraising Platform v4.16.9
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 2.30.0 All 255 releases
← All changes | includes/misc-functions.php +989 -533 2.3.14.16.9 View file →
@@ -8,8 +8,12 @@
8 8 * @license https://opensource.org/licenses/gpl-license GNU Public License
9 9 * @since 1.0
10 10 */
11 11
12 +use Give\License\PremiumAddonsListManager;
13 +use Give\License\Repositories\LicenseRepository;
14 +use Give\License\ValueObjects\LicenseOptionKeys;
15 +
12 16 // Exit if accessed directly.
13 17 if ( ! defined( 'ABSPATH' ) ) {
14 18 exit;
15 19 }
@@ -16,11 +20,10 @@
16 20
17 21 /**
18 22 * Is Test Mode Enabled.
19 23 *
24 + * @return bool $ret True if return mode is enabled, false otherwise
20 25 * @since 1.0
21 - *
22 - * @return bool $ret True if return mode is enabled, false otherwise
23 26 */
24 27 function give_is_test_mode() {
25 28
26 29 $ret = give_is_setting_enabled( give_get_option( 'test_mode' ) );
@@ -31,10 +34,10 @@
31 34
32 35 /**
33 36 * Get the current page URL.
34 37 *
38 + * @return string $current_url Current page URL.
35 39 * @since 1.0
36 - * @return string $current_url Current page URL.
37 40 */
38 41 function give_get_current_page_url() {
39 42
40 43 global $wp;
@@ -42,9 +45,9 @@
42 45 if ( get_option( 'permalink_structure' ) ) {
43 46 $base = trailingslashit( home_url( $wp->request ) );
44 47 } else {
45 48 $base = add_query_arg( $wp->query_string, '', trailingslashit( home_url( $wp->request ) ) );
46 - $base = remove_query_arg( array( 'post_type', 'name' ), $base );
49 + $base = remove_query_arg( [ 'post_type', 'name' ], $base );
47 50 }
48 51
49 52 $scheme = is_ssl() ? 'https' : 'http';
50 53 $current_uri = set_url_scheme( $base, $scheme );
@@ -55,13 +58,13 @@
55 58
56 59 /**
57 60 * Filter the current page url
58 61 *
62 + * @param string $current_uri
63 + *
59 64 * @since 1.0
60 - *
61 - * @param string $current_uri
62 65 */
63 - return apply_filters( 'give_get_current_page_url', $current_uri );
66 + return esc_url_raw( apply_filters( 'give_get_current_page_url', $current_uri ) );
64 67
65 68 }
66 69
67 70
@@ -67,11 +70,10 @@
67 70
68 71 /**
69 72 * Verify credit card numbers live?
70 73 *
74 + * @return bool $ret True is verify credit cards is live
71 75 * @since 1.0
72 - *
73 - * @return bool $ret True is verify credit cards is live
74 76 */
75 77 function give_is_cc_verify_enabled() {
76 78
77 79 $ret = true;
@@ -92,11 +94,11 @@
92 94
93 95 /**
94 96 * Fire the filter
95 97 *
98 + * @param bool $ret
99 + *
96 100 * @since 1.0
97 - *
98 - * @param bool $ret
99 101 */
100 102 return (bool) apply_filters( 'give_is_cc_verify_enabled', $ret );
101 103 }
102 104
@@ -102,10 +104,10 @@
102 104
103 105 /**
104 106 * Retrieve timezone.
105 107 *
108 + * @return string $timezone The timezone ID.
106 109 * @since 1.0
107 - * @return string $timezone The timezone ID.
108 110 */
109 111 function give_get_timezone_id() {
110 112
111 113 // if site timezone string exists, return it.
@@ -144,42 +146,53 @@
144 146 * Get User IP
145 147 *
146 148 * Returns the IP address of the current visitor
147 149 *
148 - * @since 1.0
150 + * @since 2.33.5 Add $single param.
151 + * @since 1.0
152 + *
149 153 * @return string $ip User's IP address
150 154 */
151 -function give_get_ip() {
155 +function give_get_ip($single = true)
156 +{
157 + $ip_addresses = '127.0.0.1';
158 + $header_type = '';
152 159
153 - $ip = '127.0.0.1';
154 -
155 160 if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
156 161 // check ip from share internet
157 - $ip = $_SERVER['HTTP_CLIENT_IP'];
162 + $ip_addresses = $_SERVER['HTTP_CLIENT_IP'];
163 + $header_type = 'HTTP_CLIENT_IP';
158 164 } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
159 165 // to check ip is pass from proxy
160 - $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
166 + $ip_addresses = $_SERVER['HTTP_X_FORWARDED_FOR'];
167 + $header_type = 'HTTP_X_FORWARDED_FOR';
161 168 } elseif ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) {
162 - $ip = $_SERVER['REMOTE_ADDR'];
169 + $ip_addresses = $_SERVER['REMOTE_ADDR'];
170 + $header_type = 'REMOTE_ADDR';
163 171 }
164 172
165 173 /**
166 174 * Filter the IP
167 175 *
168 - * @since 1.0
176 + * @since 2.33.5 Add $single and $header_type params.
177 + * @since 1.0
169 178 */
170 - $ip = apply_filters( 'give_get_ip', $ip );
179 + $ip_addresses = apply_filters('give_get_ip', $ip_addresses, $single, $header_type);
171 180
172 181 // Filter empty values.
173 - if ( false !== strpos( $ip, ',' ) ) {
174 - $ip = give_clean( explode( ',', $ip ) );
175 - $ip = array_filter( $ip );
176 - $ip = implode( ',', $ip );
182 + if (false !== strpos($ip_addresses, ',')) {
183 + $ip_addresses = give_clean(explode(',', $ip_addresses));
184 + $ip_addresses = array_filter($ip_addresses);
185 + $ip_addresses = implode(',', $ip_addresses);
177 186 } else {
178 - $ip = give_clean( $ip );
187 + $ip_addresses = give_clean($ip_addresses);
179 188 }
180 189
181 - return $ip;
190 + if ($single && false !== strpos($ip_addresses, ',')) {
191 + return explode(',', $ip_addresses)[0];
192 + }
193 +
194 + return $ip_addresses;
182 195 }
183 196
184 197
185 198 /**
@@ -186,15 +199,15 @@
186 199 * Store Donation Data in Sessions
187 200 *
188 201 * Used for storing info about donation
189 202 *
203 + * @param $purchase_data
204 + *
190 205 * @since 1.0
191 206 *
192 - * @param $purchase_data
193 - *
194 207 * @uses Give()->session->set()
195 208 */
196 -function give_set_purchase_session( $purchase_data = array() ) {
209 +function give_set_purchase_session( $purchase_data = [] ) {
197 210 Give()->session->set( 'give_purchase', $purchase_data );
198 211 Give()->session->set( 'give_email', $purchase_data['user_email'] );
199 212 }
200 213
@@ -203,11 +216,11 @@
203 216 *
204 217 * Used for retrieving info about donation
205 218 * after completing a donation
206 219 *
220 + * @return mixed array | false
221 + * @uses Give()->session->get()
207 222 * @since 1.0
208 - * @uses Give()->session->get()
209 - * @return mixed array | false
210 223 */
211 224 function give_get_purchase_session() {
212 225 return Give()->session->get( 'give_purchase' );
213 226 }
@@ -214,11 +227,10 @@
214 227
215 228 /**
216 229 * Retrieve Payment Key of the Receipt Access Session.
217 230 *
231 + * @return array|string
218 232 * @since 1.8.17
219 - *
220 - * @return array|string
221 233 */
222 234 function give_get_receipt_session() {
223 235 return Give()->session->get( 'receipt_access' );
224 236 }
@@ -225,11 +237,10 @@
225 237
226 238 /**
227 239 * Retrieve Payment Key of the History Access Session.
228 240 *
241 + * @return array|string
229 242 * @since 1.8.17
230 - *
231 - * @return array|string
232 243 */
233 244 function give_get_history_session() {
234 245 return (bool) Give()->session->get( 'history_access' );
235 246 }
@@ -236,15 +247,18 @@
236 247
237 248 /**
238 249 * Generate Item Title for Payment Gateway.
239 250 *
240 - * @param array $payment_data Payment Data.
251 + * @since 1.8.14
252 + * @since 2.9.6 Function will return form title with selected form level if price id set to zero. Added second param to return result with requested character length.
241 253 *
242 - * @since 1.8.14
254 + * @param array $payment_data Payment Data.
243 255 *
256 + * @param string|null $length
257 + *
244 258 * @return string By default, the name of the form. Then the price level text if any is found.
245 259 */
246 -function give_payment_gateway_item_title( $payment_data ) {
260 +function give_payment_gateway_item_title( $payment_data, $length = null ) {
247 261
248 262 $form_id = intval( $payment_data['post_data']['give-form-id'] );
249 263 $item_name = isset( $payment_data['post_data']['give-form-title'] ) ? $payment_data['post_data']['give-form-title'] : '';
250 264 $price_id = isset( $payment_data['post_data']['give-price-id'] ) ? $payment_data['post_data']['give-price-id'] : '';
@@ -249,9 +263,9 @@
249 263 $item_name = isset( $payment_data['post_data']['give-form-title'] ) ? $payment_data['post_data']['give-form-title'] : '';
250 264 $price_id = isset( $payment_data['post_data']['give-price-id'] ) ? $payment_data['post_data']['give-price-id'] : '';
251 265
252 266 // Verify has variable prices.
253 - if ( give_has_variable_prices( $form_id ) && ! empty( $price_id ) ) {
267 + if ( give_has_variable_prices( $form_id ) ) {
254 268
255 269 $item_price_level_text = give_get_price_option_name( $form_id, $price_id, 0, false );
256 270
257 271 /**
@@ -272,13 +286,19 @@
272 286 * @param string $item_name Item Title of Payment Gateway.
273 287 * @param int $form_id Donation Form ID.
274 288 * @param array $payment_data Payment Data.
275 289 *
290 + * @return string
276 291 * @since 1.8.14
277 - *
278 - * @return string
279 292 */
280 - return apply_filters( 'give_payment_gateway_item_title', $item_name, $form_id, $payment_data );
293 + $item_name = apply_filters( 'give_payment_gateway_item_title', $item_name, $form_id, $payment_data );
294 +
295 + // Cut the length
296 + if ( $length ) {
297 + $item_name = substr( $item_name, 0, $length );
298 + }
299 +
300 + return $item_name;
281 301 }
282 302
283 303 /**
284 304 * Get Donation Summary
@@ -284,15 +304,14 @@
284 304 * Get Donation Summary
285 305 *
286 306 * Creates a donation summary for payment gateways from the donation data before the payment is created in the database.
287 307 *
288 - * @since 1.8.12
289 - *
290 308 * @param array $donation_data
291 309 * @param bool $name_and_email
292 310 * @param int $length
293 311 *
294 312 * @return string
313 + * @since 1.8.12
295 314 */
296 315 function give_payment_gateway_donation_summary( $donation_data, $name_and_email = true, $length = 255 ) {
297 316
298 317 $form_id = isset( $donation_data['post_data']['give-form-id'] ) ? $donation_data['post_data']['give-form-id'] : '';
@@ -332,18 +351,22 @@
332 351 * Get user host
333 352 *
334 353 * Returns the webhost this site is using if possible
335 354 *
355 + * @return string $host if detected, false otherwise
336 356 * @since 1.0
337 - * @return string $host if detected, false otherwise
338 357 */
339 358 function give_get_host() {
340 - $host = false;
359 + $find_host = gethostname();
341 360
342 - if ( defined( 'WPE_APIKEY' ) ) {
361 + if ( strpos( $find_host, 'sgvps.net' ) ) {
362 + $host = 'Siteground';
363 + } elseif ( defined( 'WPE_APIKEY' ) ) {
343 364 $host = 'WP Engine';
344 - } elseif ( defined( 'PAGELYBIN' ) ) {
365 + } elseif ( defined( 'PAGELYBIN' ) || strpos( $find_host, 'pagelyhosting.com' ) ) {
345 366 $host = 'Pagely';
367 + } elseif ( strpos( $find_host, 'secureserver.net' ) ) {
368 + $host = 'GoDaddy/Media Temple';
346 369 } elseif ( DB_HOST == 'localhost:/tmp/mysql5.sock' ) {
347 370 $host = 'ICDSoft';
348 371 } elseif ( DB_HOST == 'mysqlv5' ) {
349 372 $host = 'NetworkSolutions';
@@ -358,9 +381,9 @@
358 381 } elseif ( strpos( DB_HOST, '.stabletransit.com' ) !== false ) {
359 382 $host = 'Rackspace Cloud';
360 383 } elseif ( strpos( DB_HOST, '.sysfix.eu' ) !== false ) {
361 384 $host = 'SysFix.eu Power Hosting';
362 - } elseif ( strpos( $_SERVER['SERVER_NAME'], 'Flywheel' ) !== false ) {
385 + } elseif ( strpos( $_SERVER['SERVER_NAME'], 'Flywheel' ) !== false || strpos( $find_host, 'fw' ) ) {
363 386 $host = 'Flywheel';
364 387 } else {
365 388 // Adding a general fallback for data gathering
366 389 $host = 'DBH: ' . DB_HOST . ', SRV: ' . $_SERVER['SERVER_NAME'];
@@ -368,91 +391,9 @@
368 391
369 392 return $host;
370 393 }
371 394
372 -
373 395 /**
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 396 * Marks a function as deprecated and informs when it has been used.
456 397 *
457 398 * There is a hook give_deprecated_function_run that will be called that can be used
458 399 * to get the backtrace up to what file and function called the deprecated
@@ -461,17 +402,17 @@
461 402 * The current behavior is to trigger a user error if WP_DEBUG is true.
462 403 *
463 404 * This function is to be used in every function that is deprecated.
464 405 *
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 406 * @param string $function The function that was called.
471 407 * @param string $version The plugin version that deprecated the function.
472 408 * @param string $replacement Optional. The function that should have been called.
473 409 * @param array $backtrace Optional. Contains stack backtrace of deprecated function.
410 + *
411 + * @uses do_action() Calls 'give_deprecated_function_run' and passes the function name, what to use instead,
412 + * and the version the function was deprecated in.
413 + * @uses apply_filters() Calls 'give_deprecated_function_trigger_error' and expects boolean value of true to do
414 + * trigger or false to not trigger error.
474 415 */
475 416 function _give_deprecated_function( $function, $version, $replacement = null, $backtrace = null ) {
476 417
477 418 /**
@@ -478,13 +419,13 @@
478 419 * Fires while give deprecated function call occurs.
479 420 *
480 421 * Allow you to hook to deprecated function call.
481 422 *
482 - * @since 1.0
483 - *
484 423 * @param string $function The function that was called.
485 424 * @param string $replacement Optional. The function that should have been called.
486 425 * @param string $version The plugin version that deprecated the function.
426 + *
427 + * @since 1.0
487 428 */
488 429 do_action( 'give_deprecated_function_run', $function, $replacement, $version );
489 430
490 431 $show_errors = current_user_can( 'manage_options' );
@@ -491,13 +432,13 @@
491 432
492 433 // Allow plugin to filter the output error trigger.
493 434 if ( WP_DEBUG && apply_filters( 'give_deprecated_function_trigger_error', $show_errors ) ) {
494 435 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 ) );
436 + trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since GiveWP version %2$s! Use %3$s instead.', 'give' ), $function, $version, $replacement ) );
496 437 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 438 // Alternatively we could dump this to a file.
498 439 } else {
499 - trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since Give version %2$s with no alternative available.', 'give' ), $function, $version ) );
440 + trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since GiveWP version %2$s with no alternative available.', 'give' ), $function, $version ) );
500 441 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 442 // Alternatively we could dump this to a file.
502 443 }
503 444 }
@@ -522,10 +463,10 @@
522 463
523 464 /**
524 465 * Get PHP Arg Separator Output
525 466 *
467 + * @return string Arg separator output
526 468 * @since 1.0
527 - * @return string Arg separator output
528 469 */
529 470 function give_get_php_arg_separator_output() {
530 471 return ini_get( 'arg_separator.output' );
531 472 }
@@ -535,13 +476,12 @@
535 476 * Month Num To Name
536 477 *
537 478 * Takes a month number and returns the name three letter name of it.
538 479 *
539 - * @since 1.0
540 - *
541 480 * @param int $n
542 481 *
543 482 * @return string Short month name
483 + * @since 1.0
544 484 */
545 485 function give_month_num_to_name( $n ) {
546 486 $timestamp = mktime( 0, 0, 0, $n, 1, 2005 );
547 487
@@ -547,17 +487,15 @@
547 487
548 488 return date_i18n( 'M', $timestamp );
549 489 }
550 490
551 -
552 491 /**
553 492 * Checks whether function is disabled.
554 493 *
555 - * @since 1.0
556 - *
557 494 * @param string $function Name of the function.
558 495 *
559 496 * @return bool Whether or not function is disabled.
497 + * @since 1.0
560 498 */
561 499 function give_is_func_disabled( $function ) {
562 500 $disabled = explode( ',', ini_get( 'disable_functions' ) );
563 501
@@ -563,100 +501,9 @@
563 501
564 502 return in_array( $function, $disabled );
565 503 }
566 504
567 -/**
568 - * Give Newsletter
569 - *
570 - * Returns the main Give newsletter form
571 - */
572 -function give_get_newsletter() {
573 - ?>
574 505
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 506 /**
660 507 * Create SVG library function
661 508 *
662 509 * @param string $icon
@@ -665,15 +512,15 @@
665 512 */
666 513 function give_svg_icons( $icon ) {
667 514
668 515 // Store your SVGs in an associative array
669 - $svgs = array(
516 + $svgs = [
670 517 'microphone' => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE2LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgd2lkdGg9IjY0cHgiIGhlaWdodD0iMTAwcHgiIHZpZXdCb3g9IjAgLTIwIDY0IDEyMCIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNjQgMTAwOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8Zz4NCgk8Zz4NCgkJPHBhdGggZD0iTTYyLDM2LjIxNWgtM2MtMS4xLDAtMiwwLjktMiwyVjUyYzAsNi42ODYtNS4yNjYsMTgtMjUsMThTNyw1OC42ODYsNyw1MlYzOC4yMTVjMC0xLjEtMC45LTItMi0ySDJjLTEuMSwwLTIsMC45LTIsMlY1Mg0KCQkJYzAsMTEuMTg0LDguMjE1LDIzLjE1MiwyNywyNC44MDFWOTBIMTRjLTEuMSwwLTIsMC44OTgtMiwydjZjMCwxLjEsMC45LDIsMiwyaDM2YzEuMSwwLDItMC45LDItMnYtNmMwLTEuMTAyLTAuOS0yLTItMkgzN1Y3Ni44MDENCgkJCUM1NS43ODUsNzUuMTUyLDY0LDYzLjE4NCw2NCw1MlYzOC4yMTVDNjQsMzcuMTE1LDYzLjEsMzYuMjE1LDYyLDM2LjIxNXoiLz4NCgkJPHBhdGggZD0iTTMyLDYwYzExLjczMiwwLDE1LTQuODE4LDE1LThWMzYuMjE1SDE3VjUyQzE3LDU1LjE4MiwyMC4yNjYsNjAsMzIsNjB6Ii8+DQoJCTxwYXRoIGQ9Ik00Nyw4YzAtMy4xODQtMy4yNjgtOC0xNS04QzIwLjI2NiwwLDE3LDQuODE2LDE3LDh2MjEuMjE1aDMwVjh6Ii8+DQoJPC9nPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPC9zdmc+DQo=',
671 518 'alert' => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE2LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgd2lkdGg9IjI4LjkzOHB4IiBoZWlnaHQ9IjI1LjAwNXB4IiB2aWV3Qm94PSIwIDAgMjguOTM4IDI1LjAwNSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMjguOTM4IDI1LjAwNTsiDQoJIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPHBhdGggc3R5bGU9ImZpbGw6IzAwMDAwMDsiIGQ9Ik0yOC44NTksMjQuMTU4TDE0Ljk1NywwLjI3OUMxNC44NTYsMC4xMDYsMTQuNjcsMCwxNC40NjgsMGMtMC4xOTgsMC0wLjM4MywwLjEwNi0wLjQ4MSwwLjI3OQ0KCUwwLjA3OSwyNC4xNThjLTAuMTAyLDAuMTc1LTAuMTA2LDAuMzg5LTAuMDA2LDAuNTY1YzAuMTAzLDAuMTc0LDAuMjg3LDAuMjgyLDAuNDg4LDAuMjgyaDI3LjgxNGMwLjIwMSwwLDAuMzg5LTAuMTA4LDAuNDg4LTAuMjgyDQoJYzAuMDQ3LTAuMDg4LDAuMDc0LTAuMTg2LDAuMDc0LTAuMjgxQzI4LjkzOCwyNC4zNDMsMjguOTExLDI0LjI0NSwyOC44NTksMjQuMTU4eiBNMTYuMzY5LDguNDc1bC0wLjQ2Miw5LjQ5M2gtMi4zODlsLTAuNDYxLTkuNDkzDQoJSDE2LjM2OXogTTE0LjcxMSwyMi44MjhoLTAuMDQyYy0xLjA4OSwwLTEuODQzLTAuODE3LTEuODQzLTEuOTA3YzAtMS4xMzEsMC43NzQtMS45MDcsMS44ODUtMS45MDdzMS44NDYsMC43NzUsMS44NjcsMS45MDcNCglDMTYuNTc5LDIyLjAxMSwxNS44NDQsMjIuODI4LDE0LjcxMSwyMi44Mjh6Ii8+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8L3N2Zz4NCg==',
672 519 'placemark' => 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxNi4wLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB3aWR0aD0iMTAwcHgiIGhlaWdodD0iMTAwcHgiIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMDAgMTAwIiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxnPg0KCTxwYXRoIGQ9Ik01MC40MzQsMjAuMjcxYy0xMi40OTksMC0yMi42NjgsMTAuMTY5LTIyLjY2OCwyMi42NjhjMCwxMS44MTQsMTguODE1LDMyLjE1NSwyMC45NiwzNC40MzdsMS43MDgsMS44MTZsMS43MDgtMS44MTYNCgkJYzIuMTQ1LTIuMjgxLDIwLjk2LTIyLjYyMywyMC45Ni0zNC40MzdDNzMuMTAzLDMwLjQ0LDYyLjkzNCwyMC4yNzEsNTAuNDM0LDIwLjI3MXogTTUwLjQzNCw1Mi4zMmMtNS4xNzIsMC05LjM4LTQuMjA4LTkuMzgtOS4zOA0KCQlzNC4yMDgtOS4zOCw5LjM4LTkuMzhjNS4xNzMsMCw5LjM4LDQuMjA4LDkuMzgsOS4zOFM1NS42MDcsNTIuMzIsNTAuNDM0LDUyLjMyeiIvPg0KPC9nPg0KPC9zdmc+DQo=',
673 520 '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 521 '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 - );
522 + ];
676 523
677 524 // Return the chosen icon's SVG string
678 525 return $svgs[ $icon ];
679 526 }
@@ -680,13 +527,12 @@
680 527
681 528 /**
682 529 * Modify Admin Nav Menu Label
683 530 *
684 - * @since 1.3
685 - *
686 531 * @param object $post_type The current object to add a menu items meta box for.
687 532 *
688 533 * @return mixed
534 + * @since 1.3
689 535 */
690 536 function modify_nav_menu_meta_box_object( $post_type ) {
691 537 if ( isset( $post_type->name ) && $post_type->name == 'give_forms' ) {
692 538 $post_type->labels->name = esc_html__( 'Donation Forms', 'give' );
@@ -699,13 +545,12 @@
699 545
700 546 /**
701 547 * Show Donation Forms Post Type in Appearance > Menus by default on fresh install.
702 548 *
703 - * @since 1.8.14
704 - *
549 + * @return bool
705 550 * @todo Remove this, when WordPress Core ticket is resolved (https://core.trac.wordpress.org/ticket/16828).
706 551 *
707 - * @return bool
552 + * @since 1.8.14
708 553 */
709 554 function give_donation_metabox_menu() {
710 555
711 556 // Get Current Screen.
@@ -724,9 +569,9 @@
724 569 return false;
725 570 }
726 571
727 572 // 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' ) );
573 + $hidden_meta_boxes = array_diff( $hidden_meta_boxes, [ 'add-post-type-give_forms' ] );
729 574
730 575 // Get current user ID.
731 576 $user = wp_get_current_user();
732 577
@@ -764,9 +609,9 @@
764 609 * @param mixed $indexKey (Optional.) The column to use as the index/keys for
765 610 * the returned array. This value may be the integer key
766 611 * of the column, or it may be the string key name.
767 612 *
768 - * @return array
613 + * @return array|boolean|null
769 614 */
770 615 function array_column( $input = null, $columnKey = null, $indexKey = null ) {
771 616 // Using func_get_args() in order to check for proper number of
772 617 // parameters and trigger errors exactly as the built-in array_column()
@@ -774,27 +619,27 @@
774 619 $argc = func_num_args();
775 620 $params = func_get_args();
776 621
777 622 if ( $argc < 2 ) {
778 - trigger_error( sprintf( esc_html__( 'array_column() expects at least 2 parameters, %s given.', 'give' ), $argc ), E_USER_WARNING );
623 + trigger_error( sprintf( 'array_column() expects at least 2 parameters, %s given.', $argc ), E_USER_WARNING );
779 624
780 625 return null;
781 626 }
782 627
783 628 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 );
629 + trigger_error( sprintf( 'array_column() expects parameter 1 to be array, %s given.', gettype( $params[0] ) ), E_USER_WARNING );
785 630
786 631 return null;
787 632 }
788 633
789 634 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 );
635 + trigger_error( 'array_column(): The column key should be either a string or an integer.', E_USER_WARNING );
791 636
792 637 return false;
793 638 }
794 639
795 640 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 );
641 + trigger_error( 'array_column(): The index key should be either a string or an integer.', E_USER_WARNING );
797 642
798 643 return false;
799 644 }
800 645
@@ -809,9 +654,9 @@
809 654 $paramsIndexKey = (string) $params[2];
810 655 }
811 656 }
812 657
813 - $resultArray = array();
658 + $resultArray = [];
814 659
815 660 foreach ( $paramsInput as $row ) {
816 661 $key = $value = null;
817 662 $keySet = $valueSet = false;
@@ -844,13 +689,14 @@
844 689
845 690 /**
846 691 * Determines the receipt visibility status.
847 692 *
848 - * @since 1.3.2
849 - *
850 693 * @param int $donation_id Donation ID.
851 694 *
852 695 * @return bool Whether the receipt is visible or not.
696 +
697 + * @since 4.16.6 Require the give_nl cookie to be a scalar string before using it as a donor lookup token.
698 + * @since 1.3.2
853 699 */
854 700 function give_can_view_receipt( $donation_id ) {
855 701
856 702 global $give_receipt_args;
@@ -872,13 +718,13 @@
872 718
873 719 // Return to download receipts from admin panel.
874 720 if ( current_user_can( 'export_give_reports' ) ) {
875 721
876 - /**
877 - * This filter will be used to modify can view receipt response when accessed from admin.
878 - *
879 - * @since 2.3.1
880 - */
722 + /**
723 + * This filter will be used to modify can view receipt response when accessed from admin.
724 + *
725 + * @since 2.3.1
726 + */
881 727 return apply_filters( 'give_can_admin_view_receipt', true );
882 728 }
883 729
884 730 if ( is_user_logged_in() || current_user_can( 'view_give_sensitive_data' ) ) {
@@ -890,25 +736,34 @@
890 736
891 737 // Check whether it is purchase session?
892 738 // This condition is to show receipt to donor after donation.
893 739 $purchase_session = give_get_purchase_session();
740 +
894 741 if (
895 742 ! empty( $purchase_session )
896 - && $purchase_session['donation_id'] === $donation_id
743 + && absint( $purchase_session['donation_id'] ) === absint( $donation_id )
897 744 ) {
898 745 $donor = Give()->donors->get_donor_by( 'email', $purchase_session['user_email'] );
899 746 }
900 747
901 748 // Check whether it is receipt access session?
902 - $receipt_session = give_get_receipt_session();
749 + $receipt_session = give_get_receipt_session();
750 + // The give_nl cookie must be a scalar string token; give_clean() does not coerce arrays
751 + // to a string, so require is_string() explicitly before treating it as a token.
752 + $email_access_token = ! empty( $_COOKIE['give_nl'] ) && is_string( $_COOKIE['give_nl'] )
753 + ? give_clean( $_COOKIE['give_nl'] )
754 + : false;
755 +
903 756 if (
904 - give_is_setting_enabled( give_get_option( 'email_access' ) ) &&
905 - ! empty( $receipt_session )
757 + ! empty( $receipt_session ) ||
758 + (
759 + give_is_setting_enabled( give_get_option( 'email_access' ) ) &&
760 + ! empty( $email_access_token )
761 + )
906 762 ) {
907 - $email_access_token = ! empty( $_COOKIE['give_nl'] ) ? give_clean( $_COOKIE['give_nl'] ) : false;
908 - $donor = ! empty( $email_access_token )
763 + $donor = ! empty( $email_access_token )
909 764 ? Give()->donors->get_donor_by_token( $email_access_token )
910 - : false ;
765 + : false;
911 766 }
912 767 }
913 768
914 769 // If donor object exists, compare the donation ids of donor with the donation receipt donor tries to access.
@@ -915,9 +770,9 @@
915 770 if ( is_object( $donor ) ) {
916 771 $is_donor_donated = in_array( (int) $donation_id, array_map( 'absint', explode( ',', $donor->payment_ids ) ), true );
917 772 $can_view_receipt = $is_donor_donated ? true : $can_view_receipt;
918 773
919 - if( ! $is_donor_donated ) {
774 + if ( ! $is_donor_donated ) {
920 775 Give()->session->set( 'donor_donation_mismatch', true );
921 776 }
922 777 }
923 778
@@ -947,24 +802,25 @@
947 802
948 803 /**
949 804 * Get plugin info including status, type, and license validation.
950 805 *
806 + * @return array Plugin info plus status, type, and license validation if
807 + * available.
808 + * @since 1.8.0
809 + *
810 + * @todo update this function to query give addon and additional
811 + *
951 812 * This is an enhanced version of get_plugins() that returns the status
952 813 * (`active` or `inactive`) of all plugins, type of plugin (`add-on` or `other`
953 814 * and license validation for Give add-ons (`true` or `false`). Does not include
954 815 * MU plugins.
955 - *
956 - * @since 1.8.0
957 - *
958 - * @return array Plugin info plus status, type, and license validation if
959 - * available.
960 816 */
961 -function give_get_plugins() {
817 +function give_get_plugins( $args = [] ) {
962 818 $plugins = get_plugins();
963 - $active_plugin_paths = (array) get_option( 'active_plugins', array() );
819 + $active_plugin_paths = (array) get_option( 'active_plugins', [] );
964 820
965 821 if ( is_multisite() ) {
966 - $network_activated_plugin_paths = array_keys( get_site_option( 'active_sitewide_plugins', array() ) );
822 + $network_activated_plugin_paths = array_keys( get_site_option( 'active_sitewide_plugins', [] ) );
967 823 $active_plugin_paths = array_merge( $active_plugin_paths, $network_activated_plugin_paths );
968 824 }
969 825
970 826 foreach ( $plugins as $plugin_path => $plugin_data ) {
@@ -974,24 +830,33 @@
974 830 } else {
975 831 $plugins[ $plugin_path ]['Status'] = 'inactive';
976 832 }
977 833
978 - $dirname = strtolower( dirname( $plugin_path ) );
834 + $dirname = strtolower( dirname( $plugin_path ) );
835 + $plugins[ $plugin_path ]['Dir'] = $dirname;
836 + $plugins[ $plugin_path ]['Path'] = $plugin_path;
979 837
838 + // A third party add-on may contain more then one author like sofort, so it is better to compare array.
839 + $author = false !== strpos( $plugin_data['Author'], ',' )
840 + ? array_map( 'trim', explode( ',', $plugin_data['Author'] ) )
841 + : [ $plugin_data['Author'] ];
842 +
980 843 // Is the plugin a Give add-on?
981 - if ( strstr( $dirname, 'give-' ) && strstr( $plugin_data['AuthorURI'], 'wordimpress.com' ) ) {
844 + if (
845 + false !== strpos( $dirname, 'give-' )
846 + && (
847 + false !== strpos( $plugin_data['PluginURI'], 'givewp.com' )
848 + || array_intersect( $author, [ 'WordImpress', 'GiveWP' ] )
849 + )
850 + ) {
982 851 // Plugin is a Give-addon.
983 852 $plugins[ $plugin_path ]['Type'] = 'add-on';
984 853
985 - /* @var stdClass $license_active */
986 - $license_active = __give_get_active_license_info( Give_License::get_short_name( $plugin_data['Name'] ) );
854 + $license_active = Give_License::get_license_by_plugin_dirname( $dirname );
987 855
988 856 // 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 - }
857 + $plugins[ $plugin_path ]['License'] = $license_active && 'valid' === $license_active['license'];
858 +
994 859 } else {
995 860 // Plugin is not a Give add-on.
996 861 $plugins[ $plugin_path ]['Type'] = 'other';
997 862 }
@@ -996,8 +861,31 @@
996 861 $plugins[ $plugin_path ]['Type'] = 'other';
997 862 }
998 863 }
999 864
865 + if ( ! empty( $args['only_add_on'] ) ) {
866 + $plugins = array_filter(
867 + $plugins,
868 + static function( $plugin ) {
869 + return 'add-on' === $plugin['Type'];
870 + }
871 + );
872 + }
873 +
874 + if ( ! empty( $args['only_premium_add_ons'] ) ) {
875 + $premiumAddonsListManger = give( PremiumAddonsListManager::class );
876 +
877 + foreach ( $plugins as $key => $plugin ) {
878 + if ( 'add-on' !== $plugin['Type'] ) {
879 + unset( $plugins[ $key ] );
880 + }
881 +
882 + if ( ! $premiumAddonsListManger->isPremiumAddons( $plugin['PluginURI'] ) ) {
883 + unset( $plugins[ $key ] );
884 + }
885 + }
886 + }
887 +
1000 888 return $plugins;
1001 889 }
1002 890
1003 891 /**
@@ -1002,13 +890,12 @@
1002 890
1003 891 /**
1004 892 * Check if terms enabled or not for form.
1005 893 *
1006 - * @since 1.8
1007 - *
1008 894 * @param $form_id
1009 895 *
1010 896 * @return bool
897 + * @since 1.8
1011 898 */
1012 899 function give_is_terms_enabled( $form_id ) {
1013 900 $form_option = give_get_meta( $form_id, '_give_terms_option', true );
1014 901
@@ -1025,12 +912,8 @@
1025 912
1026 913 /**
1027 914 * Delete donation stats cache.
1028 915 *
1029 - * @todo Resolve stats cache key naming issue. Currently it is difficult to regenerate cache key.
1030 - *
1031 - * @since 1.8.7
1032 - *
1033 916 * @param string|array $date_range Date for stats.
1034 917 * Date value should be in today, yesterday, this_week, last_week, this_month,
1035 918 * last_month, this_quarter, last_quarter, this_year, last_year. For date value other,
1036 919 * all cache will be removed.
@@ -1037,10 +920,13 @@
1037 920 *
1038 921 * @param array $args
1039 922 *
1040 923 * @return WP_Error|bool
924 + * @since 1.8.7
925 + *
926 + * @todo Resolve stats cache key naming issue. Currently it is difficult to regenerate cache key.
1041 927 */
1042 -function give_delete_donation_stats( $date_range = '', $args = array() ) {
928 +function give_delete_donation_stats( $date_range = '', $args = [] ) {
1043 929
1044 930 // Delete all cache.
1045 931 $status = Give_Cache::delete( Give_Cache::get_options_like( 'give_stats' ) );
1046 932
@@ -1046,12 +932,12 @@
1046 932
1047 933 /**
1048 934 * Fire the action when donation stats delete.
1049 935 *
1050 - * @since 1.8.7
1051 - *
1052 936 * @param string|array $date_range
1053 937 * @param array $args
938 + *
939 + * @since 1.8.7
1054 940 */
1055 941 do_action( 'give_delete_donation_stats', $status, $date_range, $args );
1056 942
1057 943 return $status;
@@ -1059,10 +945,10 @@
1059 945
1060 946 /**
1061 947 * Check if admin creating new donation form or not.
1062 948 *
949 + * @return bool
1063 950 * @since 2.0
1064 - * @return bool
1065 951 */
1066 952 function give_is_add_new_form_page() {
1067 953 $status = false;
1068 954
@@ -1079,24 +965,41 @@
1079 965 * Note: This function will help you to get meta for payment and form.
1080 966 * If you want to get meta for donors then use get_meta of Give_Donor and
1081 967 * If you want to get meta for logs then use get_meta of Give_Logging->logmeta_db.
1082 968 *
1083 - * @since 1.8.8
1084 - *
1085 969 * @param int $id
1086 970 * @param string $meta_key
1087 971 * @param bool $single
1088 972 * @param bool $default
973 + * @param string $meta_type
1089 974 *
1090 975 * @return mixed
976 + * @since 1.8.8
1091 977 */
1092 -function give_get_meta( $id, $meta_key = '', $single = false, $default = false ) {
978 +function give_get_meta( $id, $meta_key = '', $single = false, $default = false, $meta_type = '' ) {
979 + switch ( $meta_type ) {
980 + case 'donation':
981 + $meta_value = Give()->payment_meta->get_meta( $id, $meta_key, $single );
982 + break;
983 +
984 + case 'form':
985 + $meta_value = Give()->form_meta->get_meta( $id, $meta_key, $single );
986 + break;
987 +
988 + case 'donor':
989 + $meta_value = Give()->donor_meta->get_meta( $id, $meta_key, $single );
990 + break;
991 +
992 + default:
993 + $meta_value = get_post_meta( $id, $meta_key, $single );
994 + }
995 +
1093 996 /**
1094 997 * Filter the meta value
1095 998 *
1096 999 * @since 1.8.8
1097 1000 */
1098 - $meta_value = apply_filters( 'give_get_meta', get_post_meta( $id, $meta_key, $single ), $id, $meta_key, $default );
1001 + $meta_value = apply_filters( 'give_get_meta', $meta_value, $id, $meta_key, $default, $meta_type );
1099 1002
1100 1003 if ( ( empty( $meta_key ) || empty( $meta_value ) ) && $default ) {
1101 1004 $meta_value = $default;
1102 1005 }
@@ -1106,58 +1009,87 @@
1106 1009
1107 1010 /**
1108 1011 * Update Form/Payment meta.
1109 1012 *
1110 - * @since 1.8.8
1111 - *
1112 1013 * @param int $id
1113 1014 * @param string $meta_key
1114 1015 * @param mixed $meta_value
1115 1016 * @param mixed $prev_value
1017 + * @param string $meta_type
1116 1018 *
1117 1019 * @return mixed
1020 + * @since 1.8.8
1118 1021 */
1119 -function give_update_meta( $id, $meta_key, $meta_value, $prev_value = '' ) {
1120 - $status = update_post_meta( $id, $meta_key, $meta_value, $prev_value );
1022 +function give_update_meta( $id, $meta_key, $meta_value, $prev_value = '', $meta_type = '' ) {
1023 + switch ( $meta_type ) {
1024 + case 'donation':
1025 + $status = Give()->payment_meta->update_meta( $id, $meta_key, $meta_value, $prev_value );
1026 + break;
1121 1027
1028 + case 'form':
1029 + $status = Give()->form_meta->update_meta( $id, $meta_key, $meta_value, $prev_value );
1030 + break;
1031 +
1032 + case 'donor':
1033 + $status = Give()->donor_meta->update_meta( $id, $meta_key, $meta_value, $prev_value );
1034 + break;
1035 +
1036 + default:
1037 + $status = update_post_meta( $id, $meta_key, $meta_value, $prev_value );
1038 + }
1039 +
1122 1040 /**
1123 1041 * Filter the meta value update status
1124 1042 *
1125 1043 * @since 1.8.8
1126 1044 */
1127 - return apply_filters( 'give_update_meta', $status, $id, $meta_key, $meta_value );
1045 + return apply_filters( 'give_update_meta', $status, $id, $meta_key, $meta_value, $meta_type );
1128 1046 }
1129 1047
1130 1048 /**
1131 1049 * Delete Form/Payment meta.
1132 1050 *
1133 - * @since 1.8.8
1134 - *
1135 1051 * @param int $id
1136 1052 * @param string $meta_key
1137 1053 * @param string $meta_value
1054 + * @param string $meta_type
1138 1055 *
1139 1056 * @return mixed
1057 + * @since 1.8.8
1140 1058 */
1141 -function give_delete_meta( $id, $meta_key, $meta_value = '' ) {
1142 - $status = delete_post_meta( $id, $meta_key, $meta_value );
1059 +function give_delete_meta( $id, $meta_key, $meta_value = '', $meta_type = '' ) {
1060 + switch ( $meta_type ) {
1061 + case 'donation':
1062 + $status = Give()->payment_meta->delete_meta( $id, $meta_key, $meta_value );
1063 + break;
1143 1064
1065 + case 'form':
1066 + $status = Give()->form_meta->delete_meta( $id, $meta_key, $meta_value );
1067 + break;
1068 +
1069 + case 'donor':
1070 + $status = Give()->donor_meta->delete_meta( $id, $meta_key, $meta_value );
1071 + break;
1072 +
1073 + default:
1074 + $status = delete_post_meta( $id, $meta_key, $meta_value );
1075 + }
1076 +
1144 1077 /**
1145 1078 * Filter the meta value delete status
1146 1079 *
1147 1080 * @since 1.8.8
1148 1081 */
1149 - return apply_filters( 'give_delete_meta', $status, $id, $meta_key, $meta_value );
1082 + return apply_filters( 'give_delete_meta', $status, $id, $meta_key, $meta_value, $meta_type );
1150 1083 }
1151 1084
1152 1085 /**
1153 1086 * Check if the upgrade routine has been run for a specific action
1154 1087 *
1155 - * @since 1.0
1088 + * @param string $upgrade_action The upgrade action to check completion for
1156 1089 *
1157 - * @param string $upgrade_action The upgrade action to check completion for
1158 - *
1159 1090 * @return bool If the action has been added to the completed actions array
1091 + * @since 1.0
1160 1092 */
1161 1093 function give_has_upgrade_completed( $upgrade_action = '' ) {
1162 1094 // Bailout.
1163 1095 if ( empty( $upgrade_action ) ) {
@@ -1165,9 +1097,9 @@
1165 1097 }
1166 1098
1167 1099 // Fresh install?
1168 1100 // If fresh install then all upgrades will be consider as completed.
1169 - $is_fresh_install = ! get_option( 'give_version' );
1101 + $is_fresh_install = ! Give_Cache_Setting::get_option( 'give_version' );
1170 1102 if ( $is_fresh_install ) {
1171 1103 return true;
1172 1104 }
1173 1105
@@ -1179,11 +1111,10 @@
1179 1111
1180 1112 /**
1181 1113 * For use when doing 'stepped' upgrade routines, to see if we need to start somewhere in the middle
1182 1114 *
1115 + * @return mixed When nothing to resume returns false, otherwise starts the upgrade where it left off
1183 1116 * @since 1.8
1184 - *
1185 - * @return mixed When nothing to resume returns false, otherwise starts the upgrade where it left off
1186 1117 */
1187 1118 function give_maybe_resume_upgrade() {
1188 1119 $doing_upgrade = get_option( 'give_doing_upgrade', false );
1189 1120 if ( empty( $doing_upgrade ) ) {
@@ -1195,13 +1126,12 @@
1195 1126
1196 1127 /**
1197 1128 * Adds an upgrade action to the completed upgrades array
1198 1129 *
1199 - * @since 1.0
1130 + * @param string $upgrade_action The action to add to the completed upgrades array
1200 1131 *
1201 - * @param string $upgrade_action The action to add to the completed upgrades array
1202 - *
1203 1132 * @return bool If the function was successfully added
1133 + * @since 1.0
1204 1134 */
1205 1135 function give_set_upgrade_complete( $upgrade_action = '' ) {
1206 1136
1207 1137 if ( empty( $upgrade_action ) ) {
@@ -1226,13 +1156,13 @@
1226 1156
1227 1157 /**
1228 1158 * Get's the array of completed upgrade actions
1229 1159 *
1160 + * @return array The array of completed upgrades
1230 1161 * @since 1.0
1231 - * @return array The array of completed upgrades
1232 1162 */
1233 1163 function give_get_completed_upgrades() {
1234 - return (array) get_option( 'give_completed_upgrades' );
1164 + return (array) Give_Cache_Setting::get_option( 'give_completed_upgrades' );
1235 1165 }
1236 1166
1237 1167 /**
1238 1168 * In 2.0 we updated table for log, payment and form.
@@ -1238,18 +1168,19 @@
1238 1168 * In 2.0 we updated table for log, payment and form.
1239 1169 *
1240 1170 * Note: internal purpose only.
1241 1171 *
1242 - * @since 2.0
1243 - * @global wpdb $wpdb
1244 - *
1245 1172 * @param string $type Context for table
1246 1173 *
1247 1174 * @return null|array
1175 + *
1176 + * @since 4.9.0 rename function - PHP 8 compatibility
1177 + * @since 2.0
1178 + * @global wpdb $wpdb
1248 1179 */
1249 -function __give_v20_bc_table_details( $type ) {
1180 +function give_v20_bc_table_details( $type ) {
1250 1181 global $wpdb;
1251 - $table = array();
1182 + $table = [];
1252 1183
1253 1184 // Bailout.
1254 1185 if ( empty( $type ) ) {
1255 1186 return null;
@@ -1278,11 +1209,11 @@
1278 1209
1279 1210 /**
1280 1211 * Remove the Give transaction pages from WP search results.
1281 1212 *
1213 + * @param WP_Query $query
1214 + *
1282 1215 * @since 1.8.13
1283 - *
1284 - * @param WP_Query $query
1285 1216 */
1286 1217 function give_remove_pages_from_search( $query ) {
1287 1218
1288 1219 if ( ! $query->is_admin && $query->is_search && $query->is_main_query() ) {
@@ -1290,12 +1221,14 @@
1290 1221 $transaction_failed = give_get_option( 'failure_page', 0 );
1291 1222 $success_page = give_get_option( 'success_page', 0 );
1292 1223
1293 1224 $args = apply_filters(
1294 - 'give_remove_pages_from_search', array(
1225 + 'give_remove_pages_from_search',
1226 + [
1295 1227 $transaction_failed,
1296 1228 $success_page,
1297 - ), $query
1229 + ],
1230 + $query
1298 1231 );
1299 1232 $query->set( 'post__not_in', $args );
1300 1233 }
1301 1234 }
@@ -1304,10 +1237,8 @@
1304 1237
1305 1238 /**
1306 1239 * Inserts a new key/value before a key in the array.
1307 1240 *
1308 - * @since 1.8.13
1309 - *
1310 1241 * @param string $key The key to insert before.
1311 1242 * @param array $array An array to insert in to.
1312 1243 * @param string $new_key The key to insert.
1313 1244 * @param array|string $new_value An value to insert.
@@ -1313,13 +1244,15 @@
1313 1244 * @param array|string $new_value An value to insert.
1314 1245 *
1315 1246 * @return array The new array if the key exists, the passed array otherwise.
1316 1247 *
1248 + * @since 1.8.13
1249 + *
1317 1250 * @see array_insert_before()
1318 1251 */
1319 1252 function give_array_insert_before( $key, array &$array, $new_key, $new_value ) {
1320 1253 if ( array_key_exists( $key, $array ) ) {
1321 - $new = array();
1254 + $new = [];
1322 1255 foreach ( $array as $k => $value ) {
1323 1256 if ( $k === $key ) {
1324 1257 $new[ $new_key ] = $new_value;
1325 1258 }
@@ -1334,10 +1267,8 @@
1334 1267
1335 1268 /**
1336 1269 * Inserts a new key/value after a key in the array.
1337 1270 *
1338 - * @since 1.8.13
1339 - *
1340 1271 * @param string $key The key to insert after.
1341 1272 * @param array $array An array to insert in to.
1342 1273 * @param string $new_key The key to insert.
1343 1274 * @param array|string $new_value An value to insert.
@@ -1343,13 +1274,15 @@
1343 1274 * @param array|string $new_value An value to insert.
1344 1275 *
1345 1276 * @return array The new array if the key exists, the passed array otherwise.
1346 1277 *
1278 + * @since 1.8.13
1279 + *
1347 1280 * @see array_insert_before()
1348 1281 */
1349 1282 function give_array_insert_after( $key, array &$array, $new_key, $new_value ) {
1350 1283 if ( array_key_exists( $key, $array ) ) {
1351 - $new = array();
1284 + $new = [];
1352 1285 foreach ( $array as $k => $value ) {
1353 1286 $new[ $k ] = $value;
1354 1287 if ( $k === $key ) {
1355 1288 $new[ $new_key ] = $new_value;
@@ -1367,10 +1300,8 @@
1367 1300 *
1368 1301 * This has the same functionality and prototype of
1369 1302 * array_column() (PHP 5.5) but also supports objects.
1370 1303 *
1371 - * @since 1.8.13
1372 - *
1373 1304 * @param array $list List of objects or arrays
1374 1305 * @param int|string $field Field from the object to place instead of the entire object
1375 1306 * @param int|string $index_key Optional. Field from the object to use as keys for the new array.
1376 1307 * Default null.
@@ -1377,8 +1308,9 @@
1377 1308 *
1378 1309 * @return array Array of found values. If `$index_key` is set, an array of found values with keys
1379 1310 * corresponding to `$index_key`. If `$index_key` is null, array keys from the original
1380 1311 * `$list` will be preserved in the results.
1312 + * @since 1.8.13
1381 1313 */
1382 1314 function give_list_pluck( $list, $field, $index_key = null ) {
1383 1315
1384 1316 if ( ! $index_key ) {
@@ -1404,9 +1336,9 @@
1404 1336 /*
1405 1337 * When index_key is not set for a particular item, push the value
1406 1338 * to the end of the stack. This is how array_column() behaves.
1407 1339 */
1408 - $newlist = array();
1340 + $newlist = [];
1409 1341 foreach ( $list as $value ) {
1410 1342 if ( is_object( $value ) ) {
1411 1343 if ( isset( $value->$index_key ) ) {
1412 1344 $newlist[ $value->$index_key ] = $value->$field;
@@ -1429,10 +1361,8 @@
1429 1361
1430 1362 /**
1431 1363 * Add meta data field to a donor.
1432 1364 *
1433 - * @since 1.8.13
1434 - *
1435 1365 * @param int $donor_id Donor ID.
1436 1366 * @param string $meta_key Metadata name.
1437 1367 * @param mixed $meta_value Metadata value. Must be serializable if non-scalar.
1438 1368 * @param bool $unique Optional. Whether the same key should not be added.
@@ -1438,8 +1368,9 @@
1438 1368 * @param bool $unique Optional. Whether the same key should not be added.
1439 1369 * Default false.
1440 1370 *
1441 1371 * @return int|false Meta ID on success, false on failure.
1372 + * @since 1.8.13
1442 1373 */
1443 1374 function add_donor_meta( $donor_id, $meta_key, $meta_value, $unique = false ) {
1444 1375 return add_metadata( 'give_customer', $donor_id, $meta_key, $meta_value, $unique );
1445 1376 }
@@ -1450,15 +1381,14 @@
1450 1381 * You can match based on the key, or key and value. Removing based on key and
1451 1382 * value, will keep from removing duplicate metadata with the same key. It also
1452 1383 * allows removing all metadata matching key, if needed.
1453 1384 *
1454 - * @since 1.8.13
1455 - *
1456 1385 * @param int $donor_id Donor ID
1457 1386 * @param string $meta_key Metadata name.
1458 1387 * @param mixed $meta_value Optional. Metadata value.
1459 1388 *
1460 1389 * @return bool True on success, false on failure.
1390 + * @since 1.8.13
1461 1391 */
1462 1392 function delete_donor_meta( $donor_id, $meta_key, $meta_value = '' ) {
1463 1393 return delete_metadata( 'give_customer', $donor_id, $meta_key, $meta_value );
1464 1394 }
@@ -1465,10 +1395,8 @@
1465 1395
1466 1396 /**
1467 1397 * Retrieve donor meta field for a donor meta table.
1468 1398 *
1469 - * @since 1.8.13
1470 - *
1471 1399 * @param int $donor_id Donor ID.
1472 1400 * @param string $key Optional. The meta key to retrieve. By default, returns data for all keys.
1473 1401 * @param bool $single Whether to return a single value.
1474 1402 *
@@ -1473,8 +1401,9 @@
1473 1401 * @param bool $single Whether to return a single value.
1474 1402 *
1475 1403 * @return mixed Will be an array if $single is false. Will be value of meta data field if $single
1476 1404 * is true.
1405 + * @since 1.8.13
1477 1406 */
1478 1407 function get_donor_meta( $donor_id, $key = '', $single = false ) {
1479 1408 return get_metadata( 'give_customer', $donor_id, $key, $single );
1480 1409 }
@@ -1483,10 +1412,8 @@
1483 1412 * Update customer meta field based on Donor ID.
1484 1413 *
1485 1414 * If the meta field for the donor does not exist, it will be added.
1486 1415 *
1487 - * @since 1.8.13
1488 - *
1489 1416 * @param int $donor_id Donor ID.
1490 1417 * @param string $meta_key Metadata key.
1491 1418 * @param mixed $meta_value Metadata value.
1492 1419 * @param mixed $prev_value Optional. Previous value to check before removing.
@@ -1491,8 +1418,9 @@
1491 1418 * @param mixed $meta_value Metadata value.
1492 1419 * @param mixed $prev_value Optional. Previous value to check before removing.
1493 1420 *
1494 1421 * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.
1422 + * @since 1.8.13
1495 1423 */
1496 1424 function update_donor_meta( $donor_id, $meta_key, $meta_value, $prev_value = '' ) {
1497 1425 return update_metadata( 'give_customer', $donor_id, $meta_key, $meta_value, $prev_value );
1498 1426 }
@@ -1500,13 +1428,12 @@
1500 1428
1501 1429 /**
1502 1430 * Give recalculate income and donation of the donation from ID
1503 1431 *
1504 - * @since 1.8.13
1505 - *
1506 1432 * @param int $form_id Form id of which recalculation needs to be done.
1507 1433 *
1508 1434 * @return void
1435 + * @since 1.8.13
1509 1436 */
1510 1437 function give_recount_form_income_donation( $form_id = 0 ) {
1511 1438 // Check if form id is not empty.
1512 1439 if ( ! empty( $form_id ) ) {
@@ -1514,9 +1441,9 @@
1514 1441 * Filter to modify payment status.
1515 1442 *
1516 1443 * @since 1.8.13
1517 1444 */
1518 - $accepted_statuses = apply_filters( 'give_recount_accepted_statuses', array( 'publish' ) );
1445 + $accepted_statuses = apply_filters( 'give_recount_accepted_statuses', [ 'publish' ] );
1519 1446
1520 1447 /**
1521 1448 * Filter to modify args of payment query before recalculating the form total
1522 1449 *
@@ -1522,20 +1449,21 @@
1522 1449 *
1523 1450 * @since 1.8.13
1524 1451 */
1525 1452 $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 - )
1453 + 'give_recount_form_stats_args',
1454 + [
1455 + 'give_forms' => $form_id,
1456 + 'status' => $accepted_statuses,
1457 + 'number' => - 1,
1458 + 'fields' => 'ids',
1459 + ]
1532 1460 );
1533 1461
1534 - $totals = array(
1462 + $totals = [
1535 1463 'sales' => 0,
1536 1464 'earnings' => 0,
1537 - );
1465 + ];
1538 1466
1539 1467 $payments = new Give_Payments_Query( $args );
1540 1468 $payments = $payments->get_payments();
1541 1469
@@ -1540,14 +1468,14 @@
1540 1468 $payments = $payments->get_payments();
1541 1469
1542 1470 if ( $payments ) {
1543 1471 foreach ( $payments as $payment ) {
1544 - // Ensure acceptible status only
1472 + // Ensure acceptable status only.
1545 1473 if ( ! in_array( $payment->post_status, $accepted_statuses ) ) {
1546 1474 continue;
1547 1475 }
1548 1476
1549 - // Ensure only payments for this form are counted
1477 + // Ensure only payments for this form are counted.
1550 1478 if ( $payment->form_id != $form_id ) {
1551 1479 continue;
1552 1480 }
1553 1481
@@ -1564,16 +1492,15 @@
1564 1492
1565 1493 /**
1566 1494 * Get attribute string
1567 1495 *
1568 - * @since 1.8.17
1569 - *
1570 1496 * @param array $attributes
1571 1497 * @param array $default_attributes
1572 1498 *
1573 1499 * @return string
1500 + * @since 1.8.17
1574 1501 */
1575 -function give_get_attribute_str( $attributes, $default_attributes = array() ) {
1502 +function give_get_attribute_str( $attributes, $default_attributes = [] ) {
1576 1503 $attribute_str = '';
1577 1504
1578 1505 if ( isset( $attributes['attributes'] ) ) {
1579 1506 $attributes = $attributes['attributes'];
@@ -1587,9 +1514,9 @@
1587 1514 return $attribute_str;
1588 1515 }
1589 1516
1590 1517 foreach ( $attributes as $tag => $value ) {
1591 - if( 'value' == $tag ){
1518 + if ( 'value' == $tag ) {
1592 1519 $value = esc_attr( $value );
1593 1520 }
1594 1521
1595 1522 $attribute_str .= " {$tag}=\"{$value}\"";
@@ -1600,11 +1527,10 @@
1600 1527
1601 1528 /**
1602 1529 * Get the upload dir path
1603 1530 *
1531 + * @return string $wp_upload_dir;
1604 1532 * @since 1.8.17
1605 - *
1606 - * @return string $wp_upload_dir;
1607 1533 */
1608 1534 function give_get_wp_upload_dir() {
1609 1535 $wp_upload_dir = wp_upload_dir();
1610 1536
@@ -1613,13 +1539,12 @@
1613 1539
1614 1540 /**
1615 1541 * Get the data from uploaded JSON file
1616 1542 *
1617 - * @since 1.8.17
1618 - *
1619 1543 * @param string $file_name filename of the json file that is being uploaded
1620 1544 *
1621 1545 * @return string|bool $file_contents File content
1546 + * @since 1.8.17
1622 1547 */
1623 1548 function give_get_core_settings_json( $file_name ) {
1624 1549 $upload_dir = give_get_wp_upload_dir();
1625 1550 $file_path = $upload_dir . '/' . $file_name;
@@ -1635,11 +1560,10 @@
1635 1560
1636 1561 /**
1637 1562 * Get number of donation to show when user is not login.
1638 1563 *
1564 + * @return int $country The two letter country code for the site's base country
1639 1565 * @since 1.8.17
1640 - *
1641 - * @return int $country The two letter country code for the site's base country
1642 1566 */
1643 1567 function give_get_limit_display_donations() {
1644 1568 return give_get_option( 'limit_display_donations', 1 );
1645 1569 }
@@ -1652,26 +1576,26 @@
1652 1576 function give_donation_history_table_end() {
1653 1577 $email = Give()->session->get( 'give_email' );
1654 1578 ?>
1655 1579 <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 - ?>
1580 + <tr>
1581 + <td colspan="9999">
1582 + <div class="give-security-wrap">
1583 + <div class="give-security-column give-security-description-wrap">
1584 + <?php
1585 + echo sprintf( __( 'For security reasons, please confirm your email address (%s) to view your complete donation history.', 'give' ), $email );
1586 + ?>
1587 + </div>
1588 + <div class="give-security-column give-security-button-wrap">
1589 + <a href="#" data-email="<?php echo $email; ?>" id="give-confirm-email-btn"
1590 + class="give-confirm-email-btn give-btn">
1591 + <?php _e( 'Confirm Email', 'give' ); ?>
1592 + </a>
1593 + <span><?php _e( 'Email Sent!', 'give' ); ?></span>
1594 + </div>
1663 1595 </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>
1596 + </td>
1597 + </tr>
1674 1598 </tfoot>
1675 1599 <?php
1676 1600 }
1677 1601
@@ -1678,20 +1602,37 @@
1678 1602
1679 1603 /**
1680 1604 * Wrapper for _doing_it_wrong.
1681 1605 *
1682 - * @since 1.8.18
1606 + * @param string $function
1607 + * @param string $message
1608 + * @param string $version deprecated
1683 1609 *
1684 - * @param string $function
1685 - * @param string $message
1686 - * @param string $version
1687 - *
1688 1610 * @return void
1611 + * @since 1.8.18
1612 + * @since 2.5.13 Refactor function
1689 1613 */
1690 -function give_doing_it_wrong( $function, $message, $version ) {
1691 - $message .= "\nBacktrace:" . wp_debug_backtrace_summary();
1614 +function give_doing_it_wrong( $function, $message, $version = null ) {
1615 + /**
1616 + * Fires while calling function incorrectly.
1617 + *
1618 + * Allow you to hook to incorrect function call.
1619 + *
1620 + * @param string $function The function that was called.
1621 + * @param string $replacement Optional. The function that should have been called.
1622 + * @param string $version The plugin version that deprecated the function.
1623 + *
1624 + * @since 2.5.13
1625 + */
1626 + do_action( 'give_doing_it_wrong', $function, $message, $version );
1692 1627
1693 - _doing_it_wrong( $function, $message, $version );
1628 + $show_errors = current_user_can( 'manage_options' );
1629 +
1630 + // Allow plugin to filter the output error trigger.
1631 + if ( WP_DEBUG && apply_filters( 'give_doing_it_wrong_trigger_error', $show_errors ) ) {
1632 + trigger_error( sprintf( __( '%1$s was called <strong>incorrectly</strong>. %2$s', 'give' ), $function, $message ) );
1633 + trigger_error( print_r( wp_debug_backtrace_summary(), 1 ) );// Limited to previous 1028 characters, but since we only need to move back 1 in stack that should be fine.
1634 + }
1694 1635 }
1695 1636
1696 1637
1697 1638 /**
@@ -1701,9 +1642,9 @@
1701 1642 */
1702 1643 function give_ignore_user_abort() {
1703 1644 ignore_user_abort( true );
1704 1645
1705 - if ( ! give_is_func_disabled( 'set_time_limit' ) && ! ini_get( 'safe_mode' ) ) {
1646 + if ( ! give_is_func_disabled( 'set_time_limit' )) {
1706 1647 set_time_limit( 0 );
1707 1648 }
1708 1649 }
1709 1650
@@ -1709,16 +1650,15 @@
1709 1650
1710 1651 /**
1711 1652 * Get post type count.
1712 1653 *
1713 - * @since 2.0.2
1714 - *
1715 1654 * @param string $post_type
1716 1655 * @param array $args
1717 1656 *
1718 1657 * @return int
1658 + * @since 2.0.2
1719 1659 */
1720 -function give_get_total_post_type_count( $post_type = '', $args = array() ) {
1660 +function give_get_total_post_type_count( $post_type = '', $args = [] ) {
1721 1661 global $wpdb;
1722 1662 $where = '';
1723 1663
1724 1664 if ( ! $post_type ) {
@@ -1743,14 +1683,13 @@
1743 1683
1744 1684 /**
1745 1685 * Define a constant if it is not already defined.
1746 1686 *
1747 - * @since 2.0.5
1748 - *
1749 1687 * @param string $name Constant name.
1750 1688 * @param string $value Value.
1751 1689 *
1752 1690 * @credit WooCommerce
1691 + * @since 2.0.5
1753 1692 */
1754 1693 function give_maybe_define_constant( $name, $value ) {
1755 1694 if ( ! defined( $name ) ) {
1756 1695 define( $name, $value );
@@ -1759,20 +1698,19 @@
1759 1698
1760 1699 /**
1761 1700 * Decode time short tag in string
1762 1701 *
1763 - * @since 2.1.0
1764 - *
1765 1702 * @param string $string
1766 1703 * @param int $timestamp
1767 1704 *
1768 1705 * @return string
1706 + * @since 2.1.0
1769 1707 */
1770 1708 function give_time_do_tags( $string, $timestamp = 0 ) {
1771 1709 $current_time = ! empty( $timestamp ) ? $timestamp : current_time( 'timestamp' );
1772 1710
1773 1711 $formatted_string = str_replace(
1774 - array(
1712 + [
1775 1713 '{D}',
1776 1714 '{DD}',
1777 1715 '{M}',
1778 1716 '{MM}',
@@ -1781,9 +1719,10 @@
1781 1719 '{H}',
1782 1720 '{HH}',
1783 1721 '{N}',
1784 1722 '{S}',
1785 - ), array(
1723 + ],
1724 + [
1786 1725 date( 'j', $current_time ),
1787 1726 date( 'd', $current_time ),
1788 1727 date( 'n', $current_time ),
1789 1728 date( 'm', $current_time ),
@@ -1791,9 +1730,10 @@
1791 1730 date( 'Y', $current_time ),
1792 1731 date( 'G', $current_time ),
1793 1732 date( 'H', $current_time ),
1794 1733 date( 's', $current_time ),
1795 - ), $string
1734 + ],
1735 + $string
1796 1736 );
1797 1737
1798 1738 /**
1799 1739 * Filter the parsed string.
@@ -1806,13 +1746,12 @@
1806 1746
1807 1747 /**
1808 1748 * Check if Company field enabled or not for form or globally.
1809 1749 *
1810 - * @since 2.1
1811 - *
1812 1750 * @param $form_id
1813 1751 *
1814 1752 * @return bool
1753 + * @since 2.1
1815 1754 */
1816 1755 function give_is_company_field_enabled( $form_id ) {
1817 1756 $form_setting_val = give_get_meta( $form_id, '_give_company_field', true );
1818 1757 $global_setting_val = give_get_option( 'company_field' );
@@ -1817,21 +1756,22 @@
1817 1756 $form_setting_val = give_get_meta( $form_id, '_give_company_field', true );
1818 1757 $global_setting_val = give_get_option( 'company_field' );
1819 1758
1820 1759 if ( ! empty( $form_setting_val ) ) {
1821 - if ( give_is_setting_enabled( $form_setting_val, array( 'required', 'optional' ) ) ) {
1760 + if ( give_is_setting_enabled( $form_setting_val, [ 'required', 'optional' ] ) ) {
1822 1761 return true;
1823 1762 } elseif ( 'global' === $form_setting_val && give_is_setting_enabled(
1824 - $global_setting_val, array(
1763 + $global_setting_val,
1764 + [
1825 1765 'required',
1826 1766 'optional',
1827 - )
1767 + ]
1828 1768 ) ) {
1829 1769 return true;
1830 1770 } else {
1831 1771 return false;
1832 1772 }
1833 - } elseif ( give_is_setting_enabled( $global_setting_val, array( 'required', 'optional' ) ) ) {
1773 + } elseif ( give_is_setting_enabled( $global_setting_val, [ 'required', 'optional' ] ) ) {
1834 1774 return true;
1835 1775
1836 1776 } else {
1837 1777 return false;
@@ -1838,15 +1778,37 @@
1838 1778 }
1839 1779 }
1840 1780
1841 1781 /**
1782 + * Check if Last Name field is required
1783 + *
1784 + * @param $form_id
1785 + *
1786 + * @return bool
1787 + * @since 2.15.0
1788 + */
1789 +function give_is_last_name_required( $form_id ) {
1790 + $form_setting_val = give_get_meta( $form_id, '_give_last_name_field_required', true );
1791 + $global_setting_val = give_get_option( 'last_name_field_required' );
1792 +
1793 + if ( ! empty( $form_setting_val ) ) {
1794 + if ( 'required' === $form_setting_val ) {
1795 + return true;
1796 + }
1797 +
1798 + return 'global' === $form_setting_val && 'required' === $global_setting_val;
1799 + }
1800 +
1801 + return 'required' === $global_setting_val;
1802 +}
1803 +
1804 +/**
1842 1805 * Check if anonymous donation field enabled or not for form or globally.
1843 1806 *
1844 - * @since 2.1
1845 - *
1846 1807 * @param $form_id
1847 1808 *
1848 1809 * @return bool
1810 + * @since 2.1
1849 1811 */
1850 1812 function give_is_anonymous_donation_field_enabled( $form_id ) {
1851 1813 $form_setting_val = give_get_meta( $form_id, '_give_anonymous_donation', true, 'global' );
1852 1814 $global_setting_val = give_get_option( 'anonymous_donation', 'disabled' );
@@ -1868,13 +1830,12 @@
1868 1830
1869 1831 /**
1870 1832 * Check if donor comment field enabled or not for form or globally.
1871 1833 *
1872 - * @since 2.1
1873 - *
1874 1834 * @param $form_id
1875 1835 *
1876 1836 * @return bool
1837 + * @since 2.1
1877 1838 */
1878 1839 function give_is_donor_comment_field_enabled( $form_id ) {
1879 1840 $form_setting_val = give_get_meta( $form_id, '_give_donor_comment', true, 'global' );
1880 1841 $global_setting_val = give_get_option( 'donor_comment', 'disabled' );
@@ -1898,69 +1859,24 @@
1898 1859 /**
1899 1860 * Get add-on user meta value information
1900 1861 * Note: only for internal use.
1901 1862 *
1902 - * @since 2.1.0
1863 + * @param string $banner_addon_name Give add-on name.
1903 1864 *
1904 - * @param string $license_id
1905 - *
1906 1865 * @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 1866 *
1867 + * @since 4.9.0 rename function - PHP 8 compatibility
1945 1868 * @since 2.1.0
1946 - *
1947 - * @param string $banner_addon_name Give add-on name.
1948 - *
1949 - * @return array
1950 1869 */
1951 -function __give_get_active_by_user_meta( $banner_addon_name ) {
1870 +function give_get_active_by_user_meta( $banner_addon_name ) {
1952 1871 global $wpdb;
1953 1872
1954 1873 // Get the option key.
1955 1874 $option_name = Give_Addon_Activation_Banner::get_banner_user_meta_key( $banner_addon_name );
1956 - $data = array();
1875 + $data = [];
1957 1876
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();
1877 + if ( empty( $GLOBALS['give_addon_activated_by_user'] ) ) {
1878 + $GLOBALS['give_addon_activated_by_user'] = [];
1963 1879
1964 1880 // Get the meta of activation banner by user.
1965 1881 $activation_banners = $wpdb->get_results(
1966 1882 "
@@ -1979,9 +1895,9 @@
1979 1895 );
1980 1896 }
1981 1897 }
1982 1898
1983 - if ( in_array( $option_name, array_keys( $GLOBALS['give_addon_activated_by_user'] ) ) ) {
1899 + if ( array_key_exists( $option_name, $GLOBALS['give_addon_activated_by_user'] ) ) {
1984 1900 $data = maybe_unserialize( $GLOBALS['give_addon_activated_by_user'][ $option_name ] );
1985 1901 }
1986 1902
1987 1903 return $data;
@@ -1987,13 +1903,82 @@
1987 1903 return $data;
1988 1904 }
1989 1905
1990 1906 /**
1991 - * Get time interval for which nonce is valid
1907 + * Store recently activated Give's addons to wp options.
1992 1908 *
1909 + * @since 4.16.7.1 Moved from includes/admin/plugins.php so the listener is registered on every
1910 + * request, and fall back to the plugin file passed by the `activated_plugin`
1911 + * action so add-ons activated outside of plugins.php (REST, WP-CLI,
1912 + * programmatic `activate_plugin()`, etc.) are recorded too.
1913 + * @since 2.1.0
1914 + *
1915 + * @param string $activated_plugin Plugin file passed by the `activated_plugin` action.
1916 + */
1917 +function give_recently_activated_addons( $activated_plugin = '' ) {
1918 + $plugins = [];
1919 +
1920 + // Check if action is set.
1921 + if ( isset( $_REQUEST['action'] ) ) {
1922 + $plugin_action = ( '-1' !== $_REQUEST['action'] ) ? $_REQUEST['action'] : ( isset( $_REQUEST['action2'] ) ? $_REQUEST['action2'] : '' );
1923 +
1924 + switch ( $plugin_action ) {
1925 + case 'activate': // Single add-on activation.
1926 + $plugins[] = $_REQUEST['plugin'];
1927 + break;
1928 + case 'activate-selected': // If multiple add-ons activated.
1929 + $plugins = $_REQUEST['checked'];
1930 + break;
1931 + }
1932 + }
1933 +
1934 + /**
1935 + * Activations that do not come from the plugins.php form (Harbor's feature manager,
1936 + * WP-CLI, plugin dependencies, any direct `activate_plugin()` call) have no matching
1937 + * request parameters, so use the plugin file the action itself provides.
1938 + */
1939 + if ( empty( $plugins ) && ! empty( $activated_plugin ) ) {
1940 + $plugins[] = $activated_plugin;
1941 + }
1942 +
1943 + if ( ! empty( $plugins ) ) {
1944 +
1945 + $give_addons = give_get_recently_activated_addons();
1946 +
1947 + foreach ( $plugins as $plugin ) {
1948 + // Get plugins which has 'Give-' as prefix.
1949 + if ( stripos( $plugin, 'Give-' ) !== false ) {
1950 + $give_addons[] = $plugin;
1951 + }
1952 + }
1953 +
1954 + if ( ! empty( $give_addons ) ) {
1955 + // Update the Give's activated add-ons.
1956 + update_option( 'give_recently_activated_addons', $give_addons, false );
1957 + }
1958 + }
1959 +}
1960 +
1961 +// Add add-on plugins to wp option table.
1962 +add_action( 'activated_plugin', 'give_recently_activated_addons', 10 );
1963 +
1964 +/**
1965 + * Get list of add-on last activated.
1966 + *
1967 + * @since 4.16.7.1 Moved from includes/admin/plugins.php.
1993 1968 * @since 2.1.3
1994 1969 *
1970 + * @return mixed|array list of recently activated add-on
1971 + */
1972 +function give_get_recently_activated_addons() {
1973 + return get_option( 'give_recently_activated_addons', [] );
1974 +}
1975 +
1976 +/**
1977 + * Get time interval for which nonce is valid
1978 + *
1995 1979 * @return int
1980 + * @since 2.1.3
1996 1981 */
1997 1982 function give_get_nonce_life() {
1998 1983 /**
1999 1984 * Filters the lifespan of nonces in seconds.
@@ -2005,15 +1990,14 @@
2005 1990
2006 1991 /**
2007 1992 * Get nonce field without id
2008 1993 *
2009 - * @since 2.1.3
2010 - *
2011 - * @param string $action
2012 - * @param string $name
1994 + * @param string $action
1995 + * @param string $name
2013 1996 * @param bool $referer
2014 1997 *
2015 1998 * @return string
1999 + * @since 2.1.3
2016 2000 */
2017 2001 function give_get_nonce_field( $action, $name, $referer = false ) {
2018 2002 return str_replace(
2019 2003 "id=\"{$name}\"",
@@ -2024,12 +2008,13 @@
2024 2008
2025 2009 /**
2026 2010 * Display/Return a formatted goal for a donation form
2027 2011 *
2012 + * @since 3.16.0 Add form_id to the array return
2013 + * @since 2.1
2014 + *
2028 2015 * @param int|Give_Donate_Form $form Form ID or Form Object.
2029 2016 *
2030 - * @since 2.1
2031 - *
2032 2017 * @return array
2033 2018 */
2034 2019 function give_goal_progress_stats( $form ) {
2035 2020
@@ -2036,15 +2021,12 @@
2036 2021 if ( ! $form instanceof Give_Donate_Form ) {
2037 2022 $form = new Give_Donate_Form( $form );
2038 2023 }
2039 2024
2040 - $donors = '';
2041 -
2042 2025 $goal_format = give_get_form_goal_format( $form->ID );
2043 2026
2044 2027 /**
2045 2028 * Filter the form.
2046 - *
2047 2029 * @since 1.8.8
2048 2030 */
2049 2031 $total_goal = apply_filters( 'give_goal_amount_target_output', round( give_maybe_sanitize_amount( $form->goal ), 2 ), $form->ID, $form );
2050 2032
@@ -2054,40 +2036,41 @@
2054 2036 * Filter the form donations.
2055 2037 *
2056 2038 * @since 2.1
2057 2039 */
2058 - $actual = $donations = apply_filters( 'give_goal_donations_raised_output', $form->sales, $form->ID, $form );
2040 + $actual = apply_filters( 'give_goal_donations_raised_output', $form->sales, $form->ID, $form );
2059 2041 break;
2060 2042 case 'donors':
2061 2043 /**
2062 2044 * Filter to modify total number if donor for the donation form.
2063 2045 *
2064 - * @since 2.1.3
2046 + * @param int $donors Total number of donors that donated to the form.
2047 + * @param int $form_id Donation Form ID.
2048 + * @param Give_Donate_Form $form instances of Give_Donate_Form.
2065 2049 *
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 2050 * @return int $donors Total number of donors that donated to the form.
2051 + * @since 2.1.3
2071 2052 */
2072 - $actual = $donors = apply_filters( 'give_goal_donors_target_output', give_get_form_donor_count( $form->ID ), $form->ID, $form );
2053 + $actual = apply_filters( 'give_goal_donors_target_output', give_get_form_donor_count( $form->ID ), $form->ID, $form );
2073 2054 break;
2074 2055 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 );
2056 + /**
2057 + * Filter the form income.
2058 + *
2059 + * @since 3.16.0 Revert changes implemented on the 3.14.0 version
2060 + * @since 3.14.0 Replace "$form->earnings" with (new DonationQuery())->form($form->ID)->sumIntendedAmount()
2061 + * @since 1.8.8
2062 + */
2063 + $actual = apply_filters( 'give_goal_amount_raised_output', $form->earnings, $form->ID, $form );
2081 2064 break;
2082 2065 }
2083 2066
2084 2067 $progress = $total_goal ? round( ( $actual / $total_goal ) * 100, 2 ) : 0;
2085 2068
2086 - $stats_array = array(
2069 + $stats_array = [
2087 2070 'raw_actual' => $actual,
2088 2071 'raw_goal' => $total_goal,
2089 - );
2072 + ];
2090 2073
2091 2074 /**
2092 2075 * Filter the goal progress output
2093 2076 *
@@ -2095,28 +2078,33 @@
2095 2078 */
2096 2079 $progress = apply_filters( 'give_goal_amount_funded_percentage_output', $progress, $form->ID, $form );
2097 2080
2098 2081 // 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 - }
2082 + switch ( $goal_format ) {
2083 + case 'percentage':
2084 + $actual = "{$progress}%";
2085 + $total_goal = '';
2086 + break;
2104 2087
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 ) );
2088 + case 'amount' === $goal_format:
2089 + $actual = give_currency_filter( give_format_amount( $actual ) );
2090 + $total_goal = give_currency_filter( give_format_amount( $total_goal ) );
2091 + break;
2092 +
2093 + default:
2094 + $actual = give_format_amount( $actual, [ 'decimal' => false ] );
2095 + $total_goal = give_format_amount( $total_goal, [ 'decimal' => false ] );
2096 + break;
2110 2097 }
2111 2098
2112 2099 $stats_array = array_merge(
2113 - array(
2100 + [
2114 2101 'progress' => $progress,
2115 2102 'actual' => $actual,
2116 2103 'goal' => $total_goal,
2117 2104 'format' => $goal_format,
2118 - ),
2105 + 'form_id' => $form->ID
2106 + ],
2119 2107 $stats_array
2120 2108 );
2121 2109
2122 2110 /**
@@ -2129,14 +2117,13 @@
2129 2117
2130 2118 /**
2131 2119 * Get the admin messages key to show the notices.
2132 2120 *
2121 + * @return array $message admin message key.
2133 2122 * @since 2.1.4
2134 - *
2135 - * @return array $message admin message key.
2136 2123 */
2137 2124 function give_get_admin_messages_key() {
2138 - $messages = empty( $_GET['give-messages'] ) ? array() : give_clean( $_GET['give-messages'] );
2125 + $messages = empty( $_GET['give-messages'] ) ? [] : give_clean( $_GET['give-messages'] );
2139 2126
2140 2127 // backward compatibility.
2141 2128 if ( ! empty( $_GET['give-message'] ) ) {
2142 2129 $messages[] = give_clean( $_GET['give-message'] );
@@ -2144,13 +2131,12 @@
2144 2131
2145 2132 /**
2146 2133 * Filter to modify the admin messages key.
2147 2134 *
2148 - * @since 2.1.4
2149 - *
2150 2135 * @param array $message admin message key.
2151 2136 *
2152 2137 * @return array $message admin message key.
2138 + * @since 2.1.4
2153 2139 */
2154 2140 return (array) apply_filters( 'give_get_admin_messages_key', $messages );
2155 2141 }
2156 2142
@@ -2156,11 +2142,10 @@
2156 2142
2157 2143 /**
2158 2144 * Get User Agent String.
2159 2145 *
2146 + * @return array|string
2160 2147 * @since 2.1.4
2161 - *
2162 - * @return array|string
2163 2148 */
2164 2149 function give_get_user_agent() {
2165 2150
2166 2151 // Get User Agent.
@@ -2171,19 +2156,24 @@
2171 2156
2172 2157 /**
2173 2158 * Set a cookie - wrapper for setcookie using WP constants.
2174 2159 *
2160 + * @param string $name Name of the cookie being set.
2161 + * @param string $value Value of the cookie.
2162 + * @param integer $expire Expiry of the cookie.
2163 + * @param bool $secure Whether the cookie should be served only over https.
2164 + *
2175 2165 * @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 2166 */
2182 2167 function give_setcookie( $name, $value, $expire = 0, $secure = false ) {
2183 2168 if ( ! headers_sent() ) {
2184 2169 setcookie(
2185 - $name, $value, $expire, COOKIEPATH ? COOKIEPATH : '/', COOKIE_DOMAIN, $secure,
2170 + $name,
2171 + $value,
2172 + $expire,
2173 + COOKIEPATH ? COOKIEPATH : '/',
2174 + COOKIE_DOMAIN,
2175 + $secure,
2186 2176 apply_filters( 'give_cookie_httponly', false, $name, $value, $expire, $secure )
2187 2177 );
2188 2178 }
2189 2179 }
@@ -2190,15 +2180,14 @@
2190 2180
2191 2181 /**
2192 2182 * Get formatted billing address.
2193 2183 *
2194 - * @since 2.2.0
2195 - *
2196 2184 * @param array $address
2197 2185 *
2198 2186 * @return string Formatted address.
2187 + * @since 2.2.0
2199 2188 */
2200 -function give_get_formatted_address( $address = array() ) {
2189 +function give_get_formatted_address( $address = [] ) {
2201 2190 $formatted_address = '';
2202 2191
2203 2192 /**
2204 2193 * Address format.
@@ -2208,9 +2197,9 @@
2208 2197 $address_format = apply_filters( 'give_address_format_template', "{street_address}\n{city}, {state} {postal_code}\n{country}" );
2209 2198 preg_match_all( '/{([A-z0-9\-\_\ ]+)}/s', $address_format, $matches );
2210 2199
2211 2200 if ( ! empty( $matches ) && ! empty( $address ) ) {
2212 - $address_values = array();
2201 + $address_values = [];
2213 2202
2214 2203 foreach ( $matches[1] as $address_tag ) {
2215 2204 $address_values[ $address_tag ] = '';
2216 2205
@@ -2224,12 +2213,12 @@
2224 2213
2225 2214 /**
2226 2215 * Give get formatted address.
2227 2216 *
2228 - * @since 2.2.0
2229 - *
2230 2217 * @param string $formatted_address Formatted address.
2231 2218 * @param string $address_format Format of the address.
2219 + *
2220 + * @since 2.2.0
2232 2221 */
2233 2222 $formatted_address = apply_filters( 'give_get_formatted_address', $formatted_address, $address_format, $address );
2234 2223
2235 2224 return $formatted_address;
@@ -2238,13 +2227,12 @@
2238 2227 /**
2239 2228 * Get safe url for assets
2240 2229 * Note: this function will return url without http protocol
2241 2230 *
2242 - * @since 2.2.0
2243 - *
2244 2231 * @param string $url URL
2245 2232 *
2246 2233 * @return string
2234 + * @since 2.2.0
2247 2235 */
2248 2236 function give_get_safe_asset_url( $url ) {
2249 2237
2250 2238 // Bailout, if empty URL passed.
@@ -2265,31 +2253,38 @@
2265 2253 }
2266 2254
2267 2255 /**
2268 2256 * Give get formatted date.
2257 + * Note: This function does not work well with localize translated date strings
2269 2258 *
2270 - * @since 2.3.0
2271 - *
2272 2259 * @param string $date Date.
2273 2260 * @param string $format Date Format.
2274 2261 * @param string $current_format Current date Format.
2262 + * @param bool $localize
2275 2263 *
2276 2264 * @return string
2265 + * @since 2.3.0
2277 2266 */
2278 -function give_get_formatted_date( $date, $format = 'Y-m-d', $current_format = '' ) {
2267 +function give_get_formatted_date( $date, $format = 'Y-m-d', $current_format = '', $localize = false ) {
2279 2268 $current_format = empty( $current_format ) ? give_date_format() : $current_format;
2280 2269 $date_obj = DateTime::createFromFormat( $current_format, $date );
2281 - $formatted_date = $date_obj->format( $format );
2270 + $formatted_date = '';
2282 2271
2272 + if ( $date_obj instanceof DateTime ) {
2273 + $formatted_date = $localize ?
2274 + date_i18n( $format, $date_obj->getTimestamp() ) :
2275 + $date_obj->format( $format );
2276 + }
2277 +
2283 2278 /**
2284 2279 * Give get formatted date.
2285 2280 *
2286 - * @since 2.3.0
2287 - *
2288 2281 * @param string $formatted_date Formatted date.
2289 2282 * @param array
2283 + *
2284 + * @since 2.3.0
2290 2285 */
2291 - return apply_filters( 'give_get_formatted_date', $formatted_date, array( $date, $format, $current_format ) );
2286 + return apply_filters( 'give_get_formatted_date', $formatted_date, [ $date, $format, $current_format ] );
2292 2287 }
2293 2288
2294 2289 /**
2295 2290 * This function will be used to fetch the donation receipt link.
@@ -2295,17 +2290,478 @@
2295 2290 * This function will be used to fetch the donation receipt link.
2296 2291 *
2297 2292 * @param int $donation_id Donation ID.
2298 2293 *
2294 + * @return string
2299 2295 * @since 2.3.1
2296 + */
2297 +function give_get_receipt_link( $donation_id ) {
2298 +
2299 + return sprintf(
2300 + '<a href="%1$s">%2$s</a>',
2301 + esc_url( give_get_receipt_url( $donation_id ) ),
2302 + esc_html__( 'View the receipt in your browser &raquo;', 'give' )
2303 + );
2304 +
2305 +}
2306 +
2307 +/**
2308 + * Get receipt_url
2300 2309 *
2310 + * @param int $donation_id Donation ID.
2311 + *
2301 2312 * @return string
2313 + * @since 2.0
2302 2314 */
2303 -function give_get_receipt_link( $donation_id ) {
2315 +function give_get_receipt_url( $donation_id ) {
2304 2316
2317 + $receipt_url = esc_url_raw(
2318 + add_query_arg(
2319 + [
2320 + 'donation_id' => $donation_id,
2321 + ],
2322 + give_get_history_page_uri()
2323 + )
2324 + );
2325 +
2326 + return $receipt_url;
2327 +}
2328 +
2329 +/**
2330 + * Get "View in browser" Receipt Link for email.
2331 + *
2332 + * @param int $donation_id Donation ID.
2333 + *
2334 + * @return string
2335 + * @since 2.4.1
2336 + */
2337 +function give_get_view_receipt_link( $donation_id ) {
2338 +
2305 2339 return sprintf(
2306 2340 '<a href="%1$s">%2$s</a>',
2307 - esc_url( give_get_receipt_url( $donation_id ) ),
2341 + give_get_view_receipt_url( $donation_id ),
2308 2342 esc_html__( 'View the receipt in your browser &raquo;', 'give' )
2309 2343 );
2310 2344
2345 +}
2346 +
2347 +/**
2348 + * Get "View in browser" Receipt URL for email.
2349 + *
2350 + * @param int $donation_id Donation ID.
2351 + *
2352 + * @return string
2353 + * @since 2.4.1
2354 + */
2355 +function give_get_view_receipt_url( $donation_id ) {
2356 +
2357 + $receipt_url = esc_url_raw(
2358 + add_query_arg(
2359 + [
2360 + 'action' => 'view_in_browser',
2361 + '_give_hash' => give_get_payment_key( $donation_id ),
2362 + ],
2363 + give_get_history_page_uri()
2364 + )
2365 + );
2366 +
2367 + return $receipt_url;
2368 +}
2369 +
2370 +/**
2371 + * This function is used to display donation receipt content based on the parameters.
2372 + *
2373 + * @param $args
2374 + *
2375 + * @return bool|mixed
2376 + * @since 2.4.1
2377 + */
2378 +function give_display_donation_receipt( $args ) {
2379 +
2380 + global $give_receipt_args;
2381 +
2382 + $give_receipt_args = $args;
2383 +
2384 + ob_start();
2385 +
2386 + $get_data = give_clean( filter_input_array( INPUT_GET ) );
2387 + $donation_id = ! empty( $get_data['donation_id'] ) ? $get_data['donation_id'] : false;
2388 + $receipt_type = ! empty( $get_data['receipt_type'] ) ? $get_data['receipt_type'] : false;
2389 +
2390 + $give_receipt_args['id'] = $donation_id;
2391 +
2392 + if ( 'view_in_browser' !== $receipt_type ) {
2393 +
2394 + $email_access = give_get_option( 'email_access' );
2395 + $is_email_access = give_is_setting_enabled( $email_access ) && ! Give()->email_access->token_exists;
2396 +
2397 + // No donation id found & Email Access is Turned on.
2398 + if ( ! $donation_id ) {
2399 +
2400 + if ( $is_email_access ) {
2401 + give_get_template_part( 'email-login-form' );
2402 + } else {
2403 + echo Give_Notices::print_frontend_notice( $args['error'], false, 'error' );
2404 + }
2405 +
2406 + return ob_get_clean();
2407 + }
2408 +
2409 + // Donation id provided, but user is logged out. Offer them the ability to login and view the receipt.
2410 + if ( ! ( $user_can_view = give_can_view_receipt( $donation_id ) ) ) {
2411 +
2412 + if ( true === Give()->session->get( 'donor_donation_mismatch' ) ) {
2413 +
2414 + /**
2415 + * This filter will be used to modify the donor mismatch text for front end error notice.
2416 + *
2417 + * @since 2.3.1
2418 + */
2419 + $donor_mismatch_text = apply_filters( 'give_receipt_donor_mismatch_notice_text', __( 'You are trying to access invalid donation receipt. Please try again.', 'give' ) );
2420 +
2421 + echo Give_Notices::print_frontend_notice(
2422 + $donor_mismatch_text,
2423 + false,
2424 + 'error'
2425 + );
2426 +
2427 + } elseif ( $is_email_access ) {
2428 +
2429 + give_get_template_part( 'email-login-form' );
2430 +
2431 + } else {
2432 +
2433 + global $give_login_redirect;
2434 +
2435 + $give_login_redirect = give_get_current_page_url();
2436 +
2437 + Give_Notices::print_frontend_notice(
2438 + apply_filters(
2439 + 'give_must_be_logged_in_error_message',
2440 + __( 'You must be logged in to view this donation receipt.', 'give' )
2441 + )
2442 + );
2443 +
2444 + give_get_template_part( 'shortcode', 'login' );
2445 + }
2446 +
2447 + return ob_get_clean();
2448 + }
2449 +
2450 + /**
2451 + * Check if the user has permission to view the receipt.
2452 + *
2453 + * If user is logged in, user ID is compared to user ID of ID stored in payment meta
2454 + * or if user is logged out and donation was made as a guest, the donation session is checked for
2455 + * or if user is logged in and the user can view sensitive shop data.
2456 + */
2457 + if ( ! apply_filters( 'give_user_can_view_receipt', $user_can_view, $args ) ) {
2458 + return Give_Notices::print_frontend_notice( $args['error'], false, 'error' );
2459 + }
2460 + } else {
2461 + $donation_id = give_get_donation_id_by_key( $get_data['donation_id'] );
2462 + $give_receipt_args['id'] = $donation_id;
2463 + }
2464 +
2465 + give_get_template_part( 'shortcode', 'receipt' );
2466 +
2467 + return ob_get_clean();
2468 +}
2469 +
2470 +
2471 +/**
2472 + * Get plugin add-on readme.txt path
2473 + * Note: only for internal use
2474 + *
2475 + * @param $plugin_slug
2476 + * @param bool $by_plugin_name
2477 + *
2478 + * @return mixed|void
2479 + * @since 2.5.0
2480 + */
2481 +function give_get_addon_readme_url( $plugin_slug, $by_plugin_name = false ) {
2482 +
2483 + if ( $by_plugin_name ) {
2484 + $plugin_slug = Give_License::get_short_name( $plugin_slug );
2485 + }
2486 +
2487 + $website_url = trailingslashit( Give_License::get_website_url() );
2488 +
2489 + /**
2490 + * Filter the addon readme.txt url
2491 + *
2492 + * @since 2.1.4
2493 + */
2494 + $url = apply_filters(
2495 + 'give_addon_readme_file_url',
2496 + "{$website_url}downloads/plugins/{$plugin_slug}/readme.txt",
2497 + $plugin_slug,
2498 + $by_plugin_name
2499 + );
2500 +
2501 + return $url;
2502 +}
2503 +
2504 +/**
2505 + * Refresh all givewp license.
2506 + *
2507 + * @since 4.15.0 add support for Harbor unified licenses
2508 + * @since 4.8.0 Update active license date after license refresh when active license is found
2509 + * @since 4.3.0 updated to store platform fee percentage
2510 + * @since 2.27.0 delete update_plugins transient instead of invalidate it
2511 + * @since 2.5.0
2512 + *
2513 + * @param bool $wp_check_updates
2514 + *
2515 + * @access public
2516 + * @return array|WP_Error
2517 + */
2518 +function give_refresh_licenses( $wp_check_updates = true ) {
2519 + $give_licenses = get_option( 'give_licenses', [] );
2520 + $give_addons = give_get_plugins( [ 'only_premium_add_ons' => true ] );
2521 +
2522 + if ( ! $give_licenses && ! $give_addons ) {
2523 + return [];
2524 + }
2525 +
2526 + $license_keys = $give_licenses ? implode( ',', array_keys( $give_licenses ) ) : '';
2527 +
2528 + // Exclude addons already licensed via Harbor from the unlicensed list sent to the legacy API.
2529 + $legacy_unlicensed_addons = array_filter( $give_addons, static function ( $plugin ) {
2530 + return ! $plugin['License'];
2531 + } );
2532 +
2533 + $unlicensed_give_addon = $legacy_unlicensed_addons
2534 + ? array_values(
2535 + array_diff(
2536 + array_map(
2537 + function ( $plugin_name ) {
2538 + return trim( str_replace( 'Give - ', '', $plugin_name ) );
2539 + },
2540 + wp_list_pluck( $legacy_unlicensed_addons, 'Name', true )
2541 + ),
2542 + wp_list_pluck( $give_licenses, 'item_name', true )
2543 + )
2544 + )
2545 + : [];
2546 +
2547 + // Nothing for the legacy API to check.
2548 + if ( empty( $give_licenses ) && empty( $unlicensed_give_addon ) ) {
2549 + return [];
2550 + }
2551 +
2552 + $tmp = Give_License::request_license_api(
2553 + [
2554 + 'edd_action' => 'check_licenses',
2555 + 'licenses' => $license_keys,
2556 + 'unlicensed' => implode( ',', $unlicensed_give_addon ),
2557 + ],
2558 + true
2559 + );
2560 +
2561 + if ( ! $tmp || is_wp_error( $tmp ) ) {
2562 + return [];
2563 + }
2564 +
2565 + // Prevent fatal error on WP 4.9.10
2566 + // Because wp_list_pluck accept only array or array of array in that version.
2567 + // @see https://github.com/impress-org/give/issues/4176
2568 + $tmp = json_decode( json_encode( $tmp ), true );
2569 +
2570 + // Remove unlicensed add-on from response.
2571 + $tmp_unlicensed = [];
2572 + foreach ( $tmp as $key => $data ) {
2573 + if ( empty( $data ) ) {
2574 + unset( $tmp[ "{$key}" ] );
2575 + continue;
2576 + }
2577 +
2578 + if ( empty( $data['check_license'] ) ) {
2579 + $tmp_unlicensed[ $key ] = $data;
2580 + unset( $tmp[ "{$key}" ] );
2581 + }
2582 + }
2583 +
2584 + $check_licenses = wp_list_pluck( $tmp, 'check_license' );
2585 +
2586 + /* @var stdClass $data */
2587 + foreach ( $check_licenses as $key => $data ) {
2588 + if ( is_wp_error( $data ) ) {
2589 + continue;
2590 + }
2591 +
2592 + if ( ! $data['success'] ) {
2593 + unset( $give_licenses[ $key ] );
2594 + continue;
2595 + }
2596 +
2597 + $give_licenses[ $key ] = $data;
2598 + }
2599 +
2600 + $tmp_update_plugins = array_merge(
2601 + array_filter( wp_list_pluck( $tmp, 'get_version' ) ),
2602 + array_filter( wp_list_pluck( $tmp, 'get_versions' ) )
2603 + );
2604 +
2605 + if ( $tmp_unlicensed ) {
2606 + $tmp_update_plugins = array_merge( $tmp_update_plugins, $tmp_unlicensed );
2607 + }
2608 +
2609 + update_option( 'give_licenses', $give_licenses, 'no' );
2610 + update_option( 'give_get_versions', $tmp_update_plugins, 'no' );
2611 +
2612 + $refresh = Give_License::refresh_license_status();
2613 + $refresh['time'] = time();
2614 +
2615 + update_option( 'give_licenses_refreshed_last_checked', $refresh, 'no' );
2616 +
2617 + $platform_fee_percentage = get_platform_fee_from_licenses();
2618 +
2619 + if (!is_null($platform_fee_percentage)) {
2620 + update_option( LicenseOptionKeys::PLATFORM_FEE_PERCENTAGE, $platform_fee_percentage, 'no' );
2621 + }
2622 +
2623 + // Update active license date after license refresh when active license is found
2624 + $active_license_date = get_active_license_date();
2625 +
2626 + if(!is_null($active_license_date)) {
2627 + update_option(LicenseOptionKeys::LAST_ACTIVE_LICENSE_DATE, $active_license_date, 'no');
2628 + }
2629 +
2630 + // Tell WordPress to look for updates.
2631 + if ( $wp_check_updates ) {
2632 + delete_site_transient('update_plugins');
2633 + }
2634 +
2635 + return [
2636 + 'give_licenses' => $give_licenses,
2637 + 'give_get_versions' => $tmp_update_plugins,
2638 + ];
2639 +}
2640 +
2641 +/**
2642 + * Get platform fee from stored licenses
2643 + */
2644 +function get_platform_fee_from_licenses(): ?float
2645 +{
2646 + /** @var LicenseRepository $repository */
2647 + $repository = give(LicenseRepository::class);
2648 +
2649 + return $repository->findLowestPlatformFeePercentageFromActiveLicenses();
2650 +}
2651 +
2652 +/**
2653 + * Set Active License Date
2654 + *
2655 + * @since 4.8.0
2656 + */
2657 +function get_active_license_date(): ?int
2658 +{
2659 + /** @var LicenseRepository $repository */
2660 + $repository = give(LicenseRepository::class);
2661 +
2662 + return $repository->getCurrentActiveLicenseDate();
2663 +}
2664 +
2665 +/**
2666 + * Check add-ons updates
2667 + * Note: only for internal use
2668 + *
2669 + * @param stdClass $_transient_data Plugin updates information
2670 + *
2671 + * @return stdClass
2672 + * @since 2.5.0
2673 + */
2674 +function give_check_addon_updates( $_transient_data ) {
2675 + if ( ! is_object( $_transient_data ) ) {
2676 + $_transient_data = new stdClass();
2677 + }
2678 +
2679 + $update_plugins = get_option( 'give_get_versions', [] );
2680 + $check_licenses = get_option( 'give_licenses', [] );
2681 +
2682 + // Skip legacy update checks when Harbor is managing licensing and no legacy licenses exist.
2683 + if ( empty( $check_licenses ) && lw_harbor_is_product_license_active( 'give' ) ) {
2684 + return $_transient_data;
2685 + }
2686 +
2687 + if ( ! $update_plugins ) {
2688 + $data = give_refresh_licenses( false );
2689 +
2690 + if (
2691 + empty( $data['give_get_versions'] )
2692 + || is_wp_error( $data )
2693 + ) {
2694 + return $_transient_data;
2695 + }
2696 +
2697 + $update_plugins = $data['give_get_versions'];
2698 + }
2699 +
2700 + foreach ( $update_plugins as $key => $data ) {
2701 + $plugins = ! empty( $check_licenses[ $key ] )
2702 + ? ( ! empty( $check_licenses[ $key ]['is_all_access_pass'] ) ? $data : [ $data ] )
2703 + : [ $data ];
2704 +
2705 + foreach ( $plugins as $plugin ) {
2706 + // This value will be empty if any error occurred when verifying version of add-on.
2707 + if ( empty( $plugin['new_version'] ) ) {
2708 + continue;
2709 + }
2710 +
2711 + $plugin = array_map( 'maybe_unserialize', $plugin );
2712 + $tmp_plugin = Give_License::get_plugin_by_slug( $plugin['slug'] );
2713 +
2714 + if ( ! $tmp_plugin ) {
2715 + continue;
2716 + }
2717 +
2718 + $plugin['plugin'] = $tmp_plugin['Path'];
2719 +
2720 + if ( - 1 !== version_compare( $tmp_plugin['Version'], $plugin['new_version'] ) ) {
2721 + $_transient_data->no_update[ $tmp_plugin['Path'] ] = (object) $plugin;
2722 + } else {
2723 + $_transient_data->response[ $tmp_plugin['Path'] ] = (object) $plugin;
2724 + }
2725 +
2726 + $_transient_data->checked[ $tmp_plugin['Path'] ] = $tmp_plugin['Version'];
2727 + }
2728 + }
2729 +
2730 + $_transient_data->last_checked = time();
2731 +
2732 + return $_transient_data;
2733 +}
2734 +
2735 +/**
2736 + * Get page by title
2737 + *
2738 + * @since 2.26.0
2739 + *
2740 + * @param string $page_title
2741 + * @param string $output
2742 + * @param string $post_type
2743 + *
2744 + * @return null|WP_Post
2745 + */
2746 +function give_get_page_by_title(string $page_title, string $output = OBJECT, string $post_type = 'page')
2747 +{
2748 + $args = [
2749 + 'title' => $page_title,
2750 + 'post_type' => $post_type,
2751 + 'post_status' => get_post_stati(),
2752 + 'posts_per_page' => 1,
2753 + 'update_post_term_cache' => false,
2754 + 'update_post_meta_cache' => false,
2755 + 'no_found_rows' => true,
2756 + 'orderby' => 'post_date ID',
2757 + 'order' => 'ASC',
2758 + ];
2759 + $query = new WP_Query($args);
2760 + $pages = $query->posts;
2761 +
2762 + if (empty($pages)) {
2763 + return null;
2764 + }
2765 +
2766 + return get_post($pages[0], $output);
2311 2767 }