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 +1055 -553 2.3.04.16.9 View file →
@@ -3,13 +3,17 @@
3 3 * Misc Functions
4 4 *
5 5 * @package Give
6 6 * @subpackage Functions
7 - * @copyright Copyright (c) 2016, WordImpress
7 + * @copyright Copyright (c) 2016, GiveWP
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,63 +689,96 @@
844 689
845 690 /**
846 691 * Determines the receipt visibility status.
847 692 *
848 - * @since 1.3.2
693 + * @param int $donation_id Donation ID.
849 694 *
850 - * @param string $payment_key
851 - *
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 -function give_can_view_receipt( $payment_key = '' ) {
700 +function give_can_view_receipt( $donation_id ) {
855 701
856 - $return = false;
702 + global $give_receipt_args;
857 703
858 - if ( empty( $payment_key ) ) {
859 - return $return;
704 + $donor = false;
705 + $can_view_receipt = false;
706 +
707 + // Bail out, if donation id doesn't exist.
708 + if ( empty( $donation_id ) ) {
709 + return $can_view_receipt;
860 710 }
861 711
862 - global $give_receipt_args;
712 + $give_receipt_args['id'] = $donation_id;
863 713
864 - $give_receipt_args['id'] = give_get_donation_id_by_key( $payment_key );
714 + // Add backward compatibility.
715 + if ( ! is_numeric( $donation_id ) ) {
716 + $give_receipt_args['id'] = give_get_donation_id_by_key( $donation_id );
717 + }
865 718
866 - $user_id = (int) give_get_payment_user_id( $give_receipt_args['id'] );
719 + // Return to download receipts from admin panel.
720 + if ( current_user_can( 'export_give_reports' ) ) {
867 721
868 - $payment_meta = give_get_payment_meta( $give_receipt_args['id'] );
722 + /**
723 + * This filter will be used to modify can view receipt response when accessed from admin.
724 + *
725 + * @since 2.3.1
726 + */
727 + return apply_filters( 'give_can_admin_view_receipt', true );
728 + }
869 729
870 - if ( is_user_logged_in() ) {
871 - if ( $user_id === (int) get_current_user_id() ) {
872 - $return = true;
873 - } elseif ( wp_get_current_user()->user_email === give_get_payment_user_email( $give_receipt_args['id'] ) ) {
874 - $return = true;
875 - } elseif ( current_user_can( 'view_give_sensitive_data' ) ) {
876 - $return = true;
730 + if ( is_user_logged_in() || current_user_can( 'view_give_sensitive_data' ) ) {
731 +
732 + // Proceed only, if user is logged in or can view sensitive Give data.
733 + $donor = Give()->donors->get_donor_by( 'user_id', get_current_user_id() );
734 +
735 + } elseif ( ! is_user_logged_in() ) {
736 +
737 + // Check whether it is purchase session?
738 + // This condition is to show receipt to donor after donation.
739 + $purchase_session = give_get_purchase_session();
740 +
741 + if (
742 + ! empty( $purchase_session )
743 + && absint( $purchase_session['donation_id'] ) === absint( $donation_id )
744 + ) {
745 + $donor = Give()->donors->get_donor_by( 'email', $purchase_session['user_email'] );
877 746 }
878 - }
879 747
880 - // Check whether it is purchase session?
881 - $purchase_session = give_get_purchase_session();
882 - if ( ! empty( $purchase_session ) && ! is_user_logged_in() ) {
883 - if ( $purchase_session['purchase_key'] === $payment_meta['key'] ) {
884 - $return = true;
748 + // Check whether it is receipt access 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 +
756 + if (
757 + ! empty( $receipt_session ) ||
758 + (
759 + give_is_setting_enabled( give_get_option( 'email_access' ) ) &&
760 + ! empty( $email_access_token )
761 + )
762 + ) {
763 + $donor = ! empty( $email_access_token )
764 + ? Give()->donors->get_donor_by_token( $email_access_token )
765 + : false;
885 766 }
886 767 }
887 768
888 - // Check whether it is receipt access session?
889 - $receipt_session = give_get_receipt_session();
890 - if ( ! empty( $receipt_session ) && ! is_user_logged_in() ) {
891 - if ( $receipt_session === $payment_meta['key'] ) {
892 - $return = true;
769 + // If donor object exists, compare the donation ids of donor with the donation receipt donor tries to access.
770 + if ( is_object( $donor ) ) {
771 + $is_donor_donated = in_array( (int) $donation_id, array_map( 'absint', explode( ',', $donor->payment_ids ) ), true );
772 + $can_view_receipt = $is_donor_donated ? true : $can_view_receipt;
773 +
774 + if ( ! $is_donor_donated ) {
775 + Give()->session->set( 'donor_donation_mismatch', true );
893 776 }
894 777 }
895 778
896 - // Check whether it is history access session?
897 - if ( true === give_get_history_session() ) {
898 - $return = true;
899 - }
779 + return (bool) apply_filters( 'give_can_view_receipt', $can_view_receipt, $donation_id );
900 780
901 - return (bool) apply_filters( 'give_can_view_receipt', $return, $payment_key );
902 -
903 781 }
904 782
905 783 /**
906 784 * Fallback for cal_days_in_month
@@ -924,24 +802,25 @@
924 802
925 803 /**
926 804 * Get plugin info including status, type, and license validation.
927 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 + *
928 812 * This is an enhanced version of get_plugins() that returns the status
929 813 * (`active` or `inactive`) of all plugins, type of plugin (`add-on` or `other`
930 814 * and license validation for Give add-ons (`true` or `false`). Does not include
931 815 * MU plugins.
932 - *
933 - * @since 1.8.0
934 - *
935 - * @return array Plugin info plus status, type, and license validation if
936 - * available.
937 816 */
938 -function give_get_plugins() {
817 +function give_get_plugins( $args = [] ) {
939 818 $plugins = get_plugins();
940 - $active_plugin_paths = (array) get_option( 'active_plugins', array() );
819 + $active_plugin_paths = (array) get_option( 'active_plugins', [] );
941 820
942 821 if ( is_multisite() ) {
943 - $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', [] ) );
944 823 $active_plugin_paths = array_merge( $active_plugin_paths, $network_activated_plugin_paths );
945 824 }
946 825
947 826 foreach ( $plugins as $plugin_path => $plugin_data ) {
@@ -951,24 +830,33 @@
951 830 } else {
952 831 $plugins[ $plugin_path ]['Status'] = 'inactive';
953 832 }
954 833
955 - $dirname = strtolower( dirname( $plugin_path ) );
834 + $dirname = strtolower( dirname( $plugin_path ) );
835 + $plugins[ $plugin_path ]['Dir'] = $dirname;
836 + $plugins[ $plugin_path ]['Path'] = $plugin_path;
956 837
957 - // Is plugin a Give add-on by WordImpress?
958 - if ( strstr( $dirname, 'give-' ) && strstr( $plugin_data['AuthorURI'], 'wordimpress.com' ) ) {
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 +
843 + // Is the plugin a Give add-on?
844 + if (
845 + false !== strpos( $dirname, 'give-' )
846 + && (
847 + false !== strpos( $plugin_data['PluginURI'], 'givewp.com' )
848 + || array_intersect( $author, [ 'WordImpress', 'GiveWP' ] )
849 + )
850 + ) {
959 851 // Plugin is a Give-addon.
960 852 $plugins[ $plugin_path ]['Type'] = 'add-on';
961 853
962 - /* @var stdClass $license_active */
963 - $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 );
964 855
965 856 // Does a valid license exist?
966 - if ( ! empty( $license_active ) && 'valid' === $license_active->license ) {
967 - $plugins[ $plugin_path ]['License'] = true;
968 - } else {
969 - $plugins[ $plugin_path ]['License'] = false;
970 - }
857 + $plugins[ $plugin_path ]['License'] = $license_active && 'valid' === $license_active['license'];
858 +
971 859 } else {
972 860 // Plugin is not a Give add-on.
973 861 $plugins[ $plugin_path ]['Type'] = 'other';
974 862 }
@@ -973,8 +861,31 @@
973 861 $plugins[ $plugin_path ]['Type'] = 'other';
974 862 }
975 863 }
976 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 +
977 888 return $plugins;
978 889 }
979 890
980 891 /**
@@ -979,13 +890,12 @@
979 890
980 891 /**
981 892 * Check if terms enabled or not for form.
982 893 *
983 - * @since 1.8
984 - *
985 894 * @param $form_id
986 895 *
987 896 * @return bool
897 + * @since 1.8
988 898 */
989 899 function give_is_terms_enabled( $form_id ) {
990 900 $form_option = give_get_meta( $form_id, '_give_terms_option', true );
991 901
@@ -1002,12 +912,8 @@
1002 912
1003 913 /**
1004 914 * Delete donation stats cache.
1005 915 *
1006 - * @todo Resolve stats cache key naming issue. Currently it is difficult to regenerate cache key.
1007 - *
1008 - * @since 1.8.7
1009 - *
1010 916 * @param string|array $date_range Date for stats.
1011 917 * Date value should be in today, yesterday, this_week, last_week, this_month,
1012 918 * last_month, this_quarter, last_quarter, this_year, last_year. For date value other,
1013 919 * all cache will be removed.
@@ -1014,10 +920,13 @@
1014 920 *
1015 921 * @param array $args
1016 922 *
1017 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.
1018 927 */
1019 -function give_delete_donation_stats( $date_range = '', $args = array() ) {
928 +function give_delete_donation_stats( $date_range = '', $args = [] ) {
1020 929
1021 930 // Delete all cache.
1022 931 $status = Give_Cache::delete( Give_Cache::get_options_like( 'give_stats' ) );
1023 932
@@ -1023,12 +932,12 @@
1023 932
1024 933 /**
1025 934 * Fire the action when donation stats delete.
1026 935 *
1027 - * @since 1.8.7
1028 - *
1029 936 * @param string|array $date_range
1030 937 * @param array $args
938 + *
939 + * @since 1.8.7
1031 940 */
1032 941 do_action( 'give_delete_donation_stats', $status, $date_range, $args );
1033 942
1034 943 return $status;
@@ -1036,10 +945,10 @@
1036 945
1037 946 /**
1038 947 * Check if admin creating new donation form or not.
1039 948 *
949 + * @return bool
1040 950 * @since 2.0
1041 - * @return bool
1042 951 */
1043 952 function give_is_add_new_form_page() {
1044 953 $status = false;
1045 954
@@ -1056,24 +965,41 @@
1056 965 * Note: This function will help you to get meta for payment and form.
1057 966 * If you want to get meta for donors then use get_meta of Give_Donor and
1058 967 * If you want to get meta for logs then use get_meta of Give_Logging->logmeta_db.
1059 968 *
1060 - * @since 1.8.8
1061 - *
1062 969 * @param int $id
1063 970 * @param string $meta_key
1064 971 * @param bool $single
1065 972 * @param bool $default
973 + * @param string $meta_type
1066 974 *
1067 975 * @return mixed
976 + * @since 1.8.8
1068 977 */
1069 -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 +
1070 996 /**
1071 997 * Filter the meta value
1072 998 *
1073 999 * @since 1.8.8
1074 1000 */
1075 - $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 );
1076 1002
1077 1003 if ( ( empty( $meta_key ) || empty( $meta_value ) ) && $default ) {
1078 1004 $meta_value = $default;
1079 1005 }
@@ -1083,58 +1009,87 @@
1083 1009
1084 1010 /**
1085 1011 * Update Form/Payment meta.
1086 1012 *
1087 - * @since 1.8.8
1088 - *
1089 1013 * @param int $id
1090 1014 * @param string $meta_key
1091 1015 * @param mixed $meta_value
1092 1016 * @param mixed $prev_value
1017 + * @param string $meta_type
1093 1018 *
1094 1019 * @return mixed
1020 + * @since 1.8.8
1095 1021 */
1096 -function give_update_meta( $id, $meta_key, $meta_value, $prev_value = '' ) {
1097 - $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;
1098 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 +
1099 1040 /**
1100 1041 * Filter the meta value update status
1101 1042 *
1102 1043 * @since 1.8.8
1103 1044 */
1104 - 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 );
1105 1046 }
1106 1047
1107 1048 /**
1108 1049 * Delete Form/Payment meta.
1109 1050 *
1110 - * @since 1.8.8
1111 - *
1112 1051 * @param int $id
1113 1052 * @param string $meta_key
1114 1053 * @param string $meta_value
1054 + * @param string $meta_type
1115 1055 *
1116 1056 * @return mixed
1057 + * @since 1.8.8
1117 1058 */
1118 -function give_delete_meta( $id, $meta_key, $meta_value = '' ) {
1119 - $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;
1120 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 +
1121 1077 /**
1122 1078 * Filter the meta value delete status
1123 1079 *
1124 1080 * @since 1.8.8
1125 1081 */
1126 - 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 );
1127 1083 }
1128 1084
1129 1085 /**
1130 1086 * Check if the upgrade routine has been run for a specific action
1131 1087 *
1132 - * @since 1.0
1088 + * @param string $upgrade_action The upgrade action to check completion for
1133 1089 *
1134 - * @param string $upgrade_action The upgrade action to check completion for
1135 - *
1136 1090 * @return bool If the action has been added to the completed actions array
1091 + * @since 1.0
1137 1092 */
1138 1093 function give_has_upgrade_completed( $upgrade_action = '' ) {
1139 1094 // Bailout.
1140 1095 if ( empty( $upgrade_action ) ) {
@@ -1142,9 +1097,9 @@
1142 1097 }
1143 1098
1144 1099 // Fresh install?
1145 1100 // If fresh install then all upgrades will be consider as completed.
1146 - $is_fresh_install = ! get_option( 'give_version' );
1101 + $is_fresh_install = ! Give_Cache_Setting::get_option( 'give_version' );
1147 1102 if ( $is_fresh_install ) {
1148 1103 return true;
1149 1104 }
1150 1105
@@ -1156,11 +1111,10 @@
1156 1111
1157 1112 /**
1158 1113 * For use when doing 'stepped' upgrade routines, to see if we need to start somewhere in the middle
1159 1114 *
1115 + * @return mixed When nothing to resume returns false, otherwise starts the upgrade where it left off
1160 1116 * @since 1.8
1161 - *
1162 - * @return mixed When nothing to resume returns false, otherwise starts the upgrade where it left off
1163 1117 */
1164 1118 function give_maybe_resume_upgrade() {
1165 1119 $doing_upgrade = get_option( 'give_doing_upgrade', false );
1166 1120 if ( empty( $doing_upgrade ) ) {
@@ -1172,13 +1126,12 @@
1172 1126
1173 1127 /**
1174 1128 * Adds an upgrade action to the completed upgrades array
1175 1129 *
1176 - * @since 1.0
1130 + * @param string $upgrade_action The action to add to the completed upgrades array
1177 1131 *
1178 - * @param string $upgrade_action The action to add to the completed upgrades array
1179 - *
1180 1132 * @return bool If the function was successfully added
1133 + * @since 1.0
1181 1134 */
1182 1135 function give_set_upgrade_complete( $upgrade_action = '' ) {
1183 1136
1184 1137 if ( empty( $upgrade_action ) ) {
@@ -1203,13 +1156,13 @@
1203 1156
1204 1157 /**
1205 1158 * Get's the array of completed upgrade actions
1206 1159 *
1160 + * @return array The array of completed upgrades
1207 1161 * @since 1.0
1208 - * @return array The array of completed upgrades
1209 1162 */
1210 1163 function give_get_completed_upgrades() {
1211 - return (array) get_option( 'give_completed_upgrades' );
1164 + return (array) Give_Cache_Setting::get_option( 'give_completed_upgrades' );
1212 1165 }
1213 1166
1214 1167 /**
1215 1168 * In 2.0 we updated table for log, payment and form.
@@ -1215,18 +1168,19 @@
1215 1168 * In 2.0 we updated table for log, payment and form.
1216 1169 *
1217 1170 * Note: internal purpose only.
1218 1171 *
1219 - * @since 2.0
1220 - * @global wpdb $wpdb
1221 - *
1222 1172 * @param string $type Context for table
1223 1173 *
1224 1174 * @return null|array
1175 + *
1176 + * @since 4.9.0 rename function - PHP 8 compatibility
1177 + * @since 2.0
1178 + * @global wpdb $wpdb
1225 1179 */
1226 -function __give_v20_bc_table_details( $type ) {
1180 +function give_v20_bc_table_details( $type ) {
1227 1181 global $wpdb;
1228 - $table = array();
1182 + $table = [];
1229 1183
1230 1184 // Bailout.
1231 1185 if ( empty( $type ) ) {
1232 1186 return null;
@@ -1255,11 +1209,11 @@
1255 1209
1256 1210 /**
1257 1211 * Remove the Give transaction pages from WP search results.
1258 1212 *
1213 + * @param WP_Query $query
1214 + *
1259 1215 * @since 1.8.13
1260 - *
1261 - * @param WP_Query $query
1262 1216 */
1263 1217 function give_remove_pages_from_search( $query ) {
1264 1218
1265 1219 if ( ! $query->is_admin && $query->is_search && $query->is_main_query() ) {
@@ -1267,12 +1221,14 @@
1267 1221 $transaction_failed = give_get_option( 'failure_page', 0 );
1268 1222 $success_page = give_get_option( 'success_page', 0 );
1269 1223
1270 1224 $args = apply_filters(
1271 - 'give_remove_pages_from_search', array(
1225 + 'give_remove_pages_from_search',
1226 + [
1272 1227 $transaction_failed,
1273 1228 $success_page,
1274 - ), $query
1229 + ],
1230 + $query
1275 1231 );
1276 1232 $query->set( 'post__not_in', $args );
1277 1233 }
1278 1234 }
@@ -1281,10 +1237,8 @@
1281 1237
1282 1238 /**
1283 1239 * Inserts a new key/value before a key in the array.
1284 1240 *
1285 - * @since 1.8.13
1286 - *
1287 1241 * @param string $key The key to insert before.
1288 1242 * @param array $array An array to insert in to.
1289 1243 * @param string $new_key The key to insert.
1290 1244 * @param array|string $new_value An value to insert.
@@ -1290,13 +1244,15 @@
1290 1244 * @param array|string $new_value An value to insert.
1291 1245 *
1292 1246 * @return array The new array if the key exists, the passed array otherwise.
1293 1247 *
1248 + * @since 1.8.13
1249 + *
1294 1250 * @see array_insert_before()
1295 1251 */
1296 1252 function give_array_insert_before( $key, array &$array, $new_key, $new_value ) {
1297 1253 if ( array_key_exists( $key, $array ) ) {
1298 - $new = array();
1254 + $new = [];
1299 1255 foreach ( $array as $k => $value ) {
1300 1256 if ( $k === $key ) {
1301 1257 $new[ $new_key ] = $new_value;
1302 1258 }
@@ -1311,10 +1267,8 @@
1311 1267
1312 1268 /**
1313 1269 * Inserts a new key/value after a key in the array.
1314 1270 *
1315 - * @since 1.8.13
1316 - *
1317 1271 * @param string $key The key to insert after.
1318 1272 * @param array $array An array to insert in to.
1319 1273 * @param string $new_key The key to insert.
1320 1274 * @param array|string $new_value An value to insert.
@@ -1320,13 +1274,15 @@
1320 1274 * @param array|string $new_value An value to insert.
1321 1275 *
1322 1276 * @return array The new array if the key exists, the passed array otherwise.
1323 1277 *
1278 + * @since 1.8.13
1279 + *
1324 1280 * @see array_insert_before()
1325 1281 */
1326 1282 function give_array_insert_after( $key, array &$array, $new_key, $new_value ) {
1327 1283 if ( array_key_exists( $key, $array ) ) {
1328 - $new = array();
1284 + $new = [];
1329 1285 foreach ( $array as $k => $value ) {
1330 1286 $new[ $k ] = $value;
1331 1287 if ( $k === $key ) {
1332 1288 $new[ $new_key ] = $new_value;
@@ -1344,10 +1300,8 @@
1344 1300 *
1345 1301 * This has the same functionality and prototype of
1346 1302 * array_column() (PHP 5.5) but also supports objects.
1347 1303 *
1348 - * @since 1.8.13
1349 - *
1350 1304 * @param array $list List of objects or arrays
1351 1305 * @param int|string $field Field from the object to place instead of the entire object
1352 1306 * @param int|string $index_key Optional. Field from the object to use as keys for the new array.
1353 1307 * Default null.
@@ -1354,8 +1308,9 @@
1354 1308 *
1355 1309 * @return array Array of found values. If `$index_key` is set, an array of found values with keys
1356 1310 * corresponding to `$index_key`. If `$index_key` is null, array keys from the original
1357 1311 * `$list` will be preserved in the results.
1312 + * @since 1.8.13
1358 1313 */
1359 1314 function give_list_pluck( $list, $field, $index_key = null ) {
1360 1315
1361 1316 if ( ! $index_key ) {
@@ -1381,9 +1336,9 @@
1381 1336 /*
1382 1337 * When index_key is not set for a particular item, push the value
1383 1338 * to the end of the stack. This is how array_column() behaves.
1384 1339 */
1385 - $newlist = array();
1340 + $newlist = [];
1386 1341 foreach ( $list as $value ) {
1387 1342 if ( is_object( $value ) ) {
1388 1343 if ( isset( $value->$index_key ) ) {
1389 1344 $newlist[ $value->$index_key ] = $value->$field;
@@ -1406,10 +1361,8 @@
1406 1361
1407 1362 /**
1408 1363 * Add meta data field to a donor.
1409 1364 *
1410 - * @since 1.8.13
1411 - *
1412 1365 * @param int $donor_id Donor ID.
1413 1366 * @param string $meta_key Metadata name.
1414 1367 * @param mixed $meta_value Metadata value. Must be serializable if non-scalar.
1415 1368 * @param bool $unique Optional. Whether the same key should not be added.
@@ -1415,8 +1368,9 @@
1415 1368 * @param bool $unique Optional. Whether the same key should not be added.
1416 1369 * Default false.
1417 1370 *
1418 1371 * @return int|false Meta ID on success, false on failure.
1372 + * @since 1.8.13
1419 1373 */
1420 1374 function add_donor_meta( $donor_id, $meta_key, $meta_value, $unique = false ) {
1421 1375 return add_metadata( 'give_customer', $donor_id, $meta_key, $meta_value, $unique );
1422 1376 }
@@ -1427,15 +1381,14 @@
1427 1381 * You can match based on the key, or key and value. Removing based on key and
1428 1382 * value, will keep from removing duplicate metadata with the same key. It also
1429 1383 * allows removing all metadata matching key, if needed.
1430 1384 *
1431 - * @since 1.8.13
1432 - *
1433 1385 * @param int $donor_id Donor ID
1434 1386 * @param string $meta_key Metadata name.
1435 1387 * @param mixed $meta_value Optional. Metadata value.
1436 1388 *
1437 1389 * @return bool True on success, false on failure.
1390 + * @since 1.8.13
1438 1391 */
1439 1392 function delete_donor_meta( $donor_id, $meta_key, $meta_value = '' ) {
1440 1393 return delete_metadata( 'give_customer', $donor_id, $meta_key, $meta_value );
1441 1394 }
@@ -1442,10 +1395,8 @@
1442 1395
1443 1396 /**
1444 1397 * Retrieve donor meta field for a donor meta table.
1445 1398 *
1446 - * @since 1.8.13
1447 - *
1448 1399 * @param int $donor_id Donor ID.
1449 1400 * @param string $key Optional. The meta key to retrieve. By default, returns data for all keys.
1450 1401 * @param bool $single Whether to return a single value.
1451 1402 *
@@ -1450,8 +1401,9 @@
1450 1401 * @param bool $single Whether to return a single value.
1451 1402 *
1452 1403 * @return mixed Will be an array if $single is false. Will be value of meta data field if $single
1453 1404 * is true.
1405 + * @since 1.8.13
1454 1406 */
1455 1407 function get_donor_meta( $donor_id, $key = '', $single = false ) {
1456 1408 return get_metadata( 'give_customer', $donor_id, $key, $single );
1457 1409 }
@@ -1460,10 +1412,8 @@
1460 1412 * Update customer meta field based on Donor ID.
1461 1413 *
1462 1414 * If the meta field for the donor does not exist, it will be added.
1463 1415 *
1464 - * @since 1.8.13
1465 - *
1466 1416 * @param int $donor_id Donor ID.
1467 1417 * @param string $meta_key Metadata key.
1468 1418 * @param mixed $meta_value Metadata value.
1469 1419 * @param mixed $prev_value Optional. Previous value to check before removing.
@@ -1468,8 +1418,9 @@
1468 1418 * @param mixed $meta_value Metadata value.
1469 1419 * @param mixed $prev_value Optional. Previous value to check before removing.
1470 1420 *
1471 1421 * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.
1422 + * @since 1.8.13
1472 1423 */
1473 1424 function update_donor_meta( $donor_id, $meta_key, $meta_value, $prev_value = '' ) {
1474 1425 return update_metadata( 'give_customer', $donor_id, $meta_key, $meta_value, $prev_value );
1475 1426 }
@@ -1477,13 +1428,12 @@
1477 1428
1478 1429 /**
1479 1430 * Give recalculate income and donation of the donation from ID
1480 1431 *
1481 - * @since 1.8.13
1482 - *
1483 1432 * @param int $form_id Form id of which recalculation needs to be done.
1484 1433 *
1485 1434 * @return void
1435 + * @since 1.8.13
1486 1436 */
1487 1437 function give_recount_form_income_donation( $form_id = 0 ) {
1488 1438 // Check if form id is not empty.
1489 1439 if ( ! empty( $form_id ) ) {
@@ -1491,9 +1441,9 @@
1491 1441 * Filter to modify payment status.
1492 1442 *
1493 1443 * @since 1.8.13
1494 1444 */
1495 - $accepted_statuses = apply_filters( 'give_recount_accepted_statuses', array( 'publish' ) );
1445 + $accepted_statuses = apply_filters( 'give_recount_accepted_statuses', [ 'publish' ] );
1496 1446
1497 1447 /**
1498 1448 * Filter to modify args of payment query before recalculating the form total
1499 1449 *
@@ -1499,20 +1449,21 @@
1499 1449 *
1500 1450 * @since 1.8.13
1501 1451 */
1502 1452 $args = apply_filters(
1503 - 'give_recount_form_stats_args', array(
1504 - 'give_forms' => $form_id,
1505 - 'status' => $accepted_statuses,
1506 - 'posts_per_page' => - 1,
1507 - 'fields' => 'ids',
1508 - )
1453 + 'give_recount_form_stats_args',
1454 + [
1455 + 'give_forms' => $form_id,
1456 + 'status' => $accepted_statuses,
1457 + 'number' => - 1,
1458 + 'fields' => 'ids',
1459 + ]
1509 1460 );
1510 1461
1511 - $totals = array(
1462 + $totals = [
1512 1463 'sales' => 0,
1513 1464 'earnings' => 0,
1514 - );
1465 + ];
1515 1466
1516 1467 $payments = new Give_Payments_Query( $args );
1517 1468 $payments = $payments->get_payments();
1518 1469
@@ -1517,14 +1468,14 @@
1517 1468 $payments = $payments->get_payments();
1518 1469
1519 1470 if ( $payments ) {
1520 1471 foreach ( $payments as $payment ) {
1521 - // Ensure acceptible status only
1472 + // Ensure acceptable status only.
1522 1473 if ( ! in_array( $payment->post_status, $accepted_statuses ) ) {
1523 1474 continue;
1524 1475 }
1525 1476
1526 - // Ensure only payments for this form are counted
1477 + // Ensure only payments for this form are counted.
1527 1478 if ( $payment->form_id != $form_id ) {
1528 1479 continue;
1529 1480 }
1530 1481
@@ -1541,16 +1492,15 @@
1541 1492
1542 1493 /**
1543 1494 * Get attribute string
1544 1495 *
1545 - * @since 1.8.17
1546 - *
1547 1496 * @param array $attributes
1548 1497 * @param array $default_attributes
1549 1498 *
1550 1499 * @return string
1500 + * @since 1.8.17
1551 1501 */
1552 -function give_get_attribute_str( $attributes, $default_attributes = array() ) {
1502 +function give_get_attribute_str( $attributes, $default_attributes = [] ) {
1553 1503 $attribute_str = '';
1554 1504
1555 1505 if ( isset( $attributes['attributes'] ) ) {
1556 1506 $attributes = $attributes['attributes'];
@@ -1564,8 +1514,12 @@
1564 1514 return $attribute_str;
1565 1515 }
1566 1516
1567 1517 foreach ( $attributes as $tag => $value ) {
1518 + if ( 'value' == $tag ) {
1519 + $value = esc_attr( $value );
1520 + }
1521 +
1568 1522 $attribute_str .= " {$tag}=\"{$value}\"";
1569 1523 }
1570 1524
1571 1525 return trim( $attribute_str );
@@ -1573,11 +1527,10 @@
1573 1527
1574 1528 /**
1575 1529 * Get the upload dir path
1576 1530 *
1531 + * @return string $wp_upload_dir;
1577 1532 * @since 1.8.17
1578 - *
1579 - * @return string $wp_upload_dir;
1580 1533 */
1581 1534 function give_get_wp_upload_dir() {
1582 1535 $wp_upload_dir = wp_upload_dir();
1583 1536
@@ -1586,13 +1539,12 @@
1586 1539
1587 1540 /**
1588 1541 * Get the data from uploaded JSON file
1589 1542 *
1590 - * @since 1.8.17
1591 - *
1592 1543 * @param string $file_name filename of the json file that is being uploaded
1593 1544 *
1594 1545 * @return string|bool $file_contents File content
1546 + * @since 1.8.17
1595 1547 */
1596 1548 function give_get_core_settings_json( $file_name ) {
1597 1549 $upload_dir = give_get_wp_upload_dir();
1598 1550 $file_path = $upload_dir . '/' . $file_name;
@@ -1608,11 +1560,10 @@
1608 1560
1609 1561 /**
1610 1562 * Get number of donation to show when user is not login.
1611 1563 *
1564 + * @return int $country The two letter country code for the site's base country
1612 1565 * @since 1.8.17
1613 - *
1614 - * @return int $country The two letter country code for the site's base country
1615 1566 */
1616 1567 function give_get_limit_display_donations() {
1617 1568 return give_get_option( 'limit_display_donations', 1 );
1618 1569 }
@@ -1625,26 +1576,26 @@
1625 1576 function give_donation_history_table_end() {
1626 1577 $email = Give()->session->get( 'give_email' );
1627 1578 ?>
1628 1579 <tfoot>
1629 - <tr>
1630 - <td colspan="9999">
1631 - <div class="give-security-wrap">
1632 - <div class="give-security-column give-security-description-wrap">
1633 - <?php
1634 - echo sprintf( __( 'For security reasons, please confirm your email address (%s) to view your complete donation history.', 'give' ), $email );
1635 - ?>
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>
1636 1595 </div>
1637 - <div class="give-security-column give-security-button-wrap">
1638 - <a href="#" data-email="<?php echo $email; ?>" id="give-confirm-email-btn"
1639 - class="give-confirm-email-btn give-btn">
1640 - <?php _e( 'Confirm Email', 'give' ); ?>
1641 - </a>
1642 - <span><?php _e( 'Email Sent!', 'give' ); ?></span>
1643 - </div>
1644 - </div>
1645 - </td>
1646 - </tr>
1596 + </td>
1597 + </tr>
1647 1598 </tfoot>
1648 1599 <?php
1649 1600 }
1650 1601
@@ -1651,20 +1602,37 @@
1651 1602
1652 1603 /**
1653 1604 * Wrapper for _doing_it_wrong.
1654 1605 *
1655 - * @since 1.8.18
1606 + * @param string $function
1607 + * @param string $message
1608 + * @param string $version deprecated
1656 1609 *
1657 - * @param string $function
1658 - * @param string $message
1659 - * @param string $version
1660 - *
1661 1610 * @return void
1611 + * @since 1.8.18
1612 + * @since 2.5.13 Refactor function
1662 1613 */
1663 -function give_doing_it_wrong( $function, $message, $version ) {
1664 - $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 );
1665 1627
1666 - _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 + }
1667 1635 }
1668 1636
1669 1637
1670 1638 /**
@@ -1674,9 +1642,9 @@
1674 1642 */
1675 1643 function give_ignore_user_abort() {
1676 1644 ignore_user_abort( true );
1677 1645
1678 - if ( ! give_is_func_disabled( 'set_time_limit' ) && ! ini_get( 'safe_mode' ) ) {
1646 + if ( ! give_is_func_disabled( 'set_time_limit' )) {
1679 1647 set_time_limit( 0 );
1680 1648 }
1681 1649 }
1682 1650
@@ -1682,16 +1650,15 @@
1682 1650
1683 1651 /**
1684 1652 * Get post type count.
1685 1653 *
1686 - * @since 2.0.2
1687 - *
1688 1654 * @param string $post_type
1689 1655 * @param array $args
1690 1656 *
1691 1657 * @return int
1658 + * @since 2.0.2
1692 1659 */
1693 -function give_get_total_post_type_count( $post_type = '', $args = array() ) {
1660 +function give_get_total_post_type_count( $post_type = '', $args = [] ) {
1694 1661 global $wpdb;
1695 1662 $where = '';
1696 1663
1697 1664 if ( ! $post_type ) {
@@ -1716,14 +1683,13 @@
1716 1683
1717 1684 /**
1718 1685 * Define a constant if it is not already defined.
1719 1686 *
1720 - * @since 2.0.5
1721 - *
1722 1687 * @param string $name Constant name.
1723 1688 * @param string $value Value.
1724 1689 *
1725 1690 * @credit WooCommerce
1691 + * @since 2.0.5
1726 1692 */
1727 1693 function give_maybe_define_constant( $name, $value ) {
1728 1694 if ( ! defined( $name ) ) {
1729 1695 define( $name, $value );
@@ -1732,20 +1698,19 @@
1732 1698
1733 1699 /**
1734 1700 * Decode time short tag in string
1735 1701 *
1736 - * @since 2.1.0
1737 - *
1738 1702 * @param string $string
1739 1703 * @param int $timestamp
1740 1704 *
1741 1705 * @return string
1706 + * @since 2.1.0
1742 1707 */
1743 1708 function give_time_do_tags( $string, $timestamp = 0 ) {
1744 1709 $current_time = ! empty( $timestamp ) ? $timestamp : current_time( 'timestamp' );
1745 1710
1746 1711 $formatted_string = str_replace(
1747 - array(
1712 + [
1748 1713 '{D}',
1749 1714 '{DD}',
1750 1715 '{M}',
1751 1716 '{MM}',
@@ -1754,9 +1719,10 @@
1754 1719 '{H}',
1755 1720 '{HH}',
1756 1721 '{N}',
1757 1722 '{S}',
1758 - ), array(
1723 + ],
1724 + [
1759 1725 date( 'j', $current_time ),
1760 1726 date( 'd', $current_time ),
1761 1727 date( 'n', $current_time ),
1762 1728 date( 'm', $current_time ),
@@ -1764,9 +1730,10 @@
1764 1730 date( 'Y', $current_time ),
1765 1731 date( 'G', $current_time ),
1766 1732 date( 'H', $current_time ),
1767 1733 date( 's', $current_time ),
1768 - ), $string
1734 + ],
1735 + $string
1769 1736 );
1770 1737
1771 1738 /**
1772 1739 * Filter the parsed string.
@@ -1779,13 +1746,12 @@
1779 1746
1780 1747 /**
1781 1748 * Check if Company field enabled or not for form or globally.
1782 1749 *
1783 - * @since 2.1
1784 - *
1785 1750 * @param $form_id
1786 1751 *
1787 1752 * @return bool
1753 + * @since 2.1
1788 1754 */
1789 1755 function give_is_company_field_enabled( $form_id ) {
1790 1756 $form_setting_val = give_get_meta( $form_id, '_give_company_field', true );
1791 1757 $global_setting_val = give_get_option( 'company_field' );
@@ -1790,21 +1756,22 @@
1790 1756 $form_setting_val = give_get_meta( $form_id, '_give_company_field', true );
1791 1757 $global_setting_val = give_get_option( 'company_field' );
1792 1758
1793 1759 if ( ! empty( $form_setting_val ) ) {
1794 - if ( give_is_setting_enabled( $form_setting_val, array( 'required', 'optional' ) ) ) {
1760 + if ( give_is_setting_enabled( $form_setting_val, [ 'required', 'optional' ] ) ) {
1795 1761 return true;
1796 1762 } elseif ( 'global' === $form_setting_val && give_is_setting_enabled(
1797 - $global_setting_val, array(
1763 + $global_setting_val,
1764 + [
1798 1765 'required',
1799 1766 'optional',
1800 - )
1767 + ]
1801 1768 ) ) {
1802 1769 return true;
1803 1770 } else {
1804 1771 return false;
1805 1772 }
1806 - } elseif ( give_is_setting_enabled( $global_setting_val, array( 'required', 'optional' ) ) ) {
1773 + } elseif ( give_is_setting_enabled( $global_setting_val, [ 'required', 'optional' ] ) ) {
1807 1774 return true;
1808 1775
1809 1776 } else {
1810 1777 return false;
@@ -1811,15 +1778,37 @@
1811 1778 }
1812 1779 }
1813 1780
1814 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 +/**
1815 1805 * Check if anonymous donation field enabled or not for form or globally.
1816 1806 *
1817 - * @since 2.1
1818 - *
1819 1807 * @param $form_id
1820 1808 *
1821 1809 * @return bool
1810 + * @since 2.1
1822 1811 */
1823 1812 function give_is_anonymous_donation_field_enabled( $form_id ) {
1824 1813 $form_setting_val = give_get_meta( $form_id, '_give_anonymous_donation', true, 'global' );
1825 1814 $global_setting_val = give_get_option( 'anonymous_donation', 'disabled' );
@@ -1841,13 +1830,12 @@
1841 1830
1842 1831 /**
1843 1832 * Check if donor comment field enabled or not for form or globally.
1844 1833 *
1845 - * @since 2.1
1846 - *
1847 1834 * @param $form_id
1848 1835 *
1849 1836 * @return bool
1837 + * @since 2.1
1850 1838 */
1851 1839 function give_is_donor_comment_field_enabled( $form_id ) {
1852 1840 $form_setting_val = give_get_meta( $form_id, '_give_donor_comment', true, 'global' );
1853 1841 $global_setting_val = give_get_option( 'donor_comment', 'disabled' );
@@ -1871,69 +1859,24 @@
1871 1859 /**
1872 1860 * Get add-on user meta value information
1873 1861 * Note: only for internal use.
1874 1862 *
1875 - * @since 2.1.0
1863 + * @param string $banner_addon_name Give add-on name.
1876 1864 *
1877 - * @param string $license_id
1878 - *
1879 1865 * @return array
1880 - */
1881 -function __give_get_active_license_info( $license_id ) {
1882 - global $wpdb;
1883 - $option_name = "{$license_id}_license_active";
1884 - $data = array();
1885 -
1886 - if ( ! isset( $GLOBALS['give_active_licenses_info'] ) ) {
1887 - $GLOBALS['give_active_licenses_info'] = array();
1888 -
1889 - $licenses_info = $wpdb->get_results(
1890 - "
1891 - SELECT option_name, option_value
1892 - FROM {$wpdb->options}
1893 - WHERE option_name LIKE '%_license_active%'
1894 - AND option_name LIKE '%give_%'
1895 - ",
1896 - ARRAY_A
1897 - );
1898 -
1899 - if ( ! empty( $licenses_info ) ) {
1900 - $GLOBALS['give_active_licenses_info'] = array_combine(
1901 - wp_list_pluck( $licenses_info, 'option_name' ),
1902 - wp_list_pluck( $licenses_info, 'option_value' )
1903 - );
1904 - }
1905 - }
1906 -
1907 - if ( in_array( $option_name, array_keys( $GLOBALS['give_active_licenses_info'] ) ) ) {
1908 - $data = maybe_unserialize( $GLOBALS['give_active_licenses_info'][ $option_name ] );
1909 - }
1910 -
1911 - return $data;
1912 -}
1913 -
1914 -/**
1915 - * Get add-on user meta value information
1916 - * Note: only for internal use.
1917 1866 *
1867 + * @since 4.9.0 rename function - PHP 8 compatibility
1918 1868 * @since 2.1.0
1919 - *
1920 - * @param string $banner_addon_name Give add-on name.
1921 - *
1922 - * @return array
1923 1869 */
1924 -function __give_get_active_by_user_meta( $banner_addon_name ) {
1870 +function give_get_active_by_user_meta( $banner_addon_name ) {
1925 1871 global $wpdb;
1926 1872
1927 1873 // Get the option key.
1928 1874 $option_name = Give_Addon_Activation_Banner::get_banner_user_meta_key( $banner_addon_name );
1929 - $data = array();
1875 + $data = [];
1930 1876
1931 - if (
1932 - ! isset( $GLOBALS['give_addon_activated_by_user'][ $banner_addon_name ] )
1933 - || empty( $GLOBALS['give_addon_activated_by_user'][ $banner_addon_name ] )
1934 - ) {
1935 - $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'] = [];
1936 1879
1937 1880 // Get the meta of activation banner by user.
1938 1881 $activation_banners = $wpdb->get_results(
1939 1882 "
@@ -1952,9 +1895,9 @@
1952 1895 );
1953 1896 }
1954 1897 }
1955 1898
1956 - 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'] ) ) {
1957 1900 $data = maybe_unserialize( $GLOBALS['give_addon_activated_by_user'][ $option_name ] );
1958 1901 }
1959 1902
1960 1903 return $data;
@@ -1960,13 +1903,82 @@
1960 1903 return $data;
1961 1904 }
1962 1905
1963 1906 /**
1964 - * Get time interval for which nonce is valid
1907 + * Store recently activated Give's addons to wp options.
1965 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.
1966 1968 * @since 2.1.3
1967 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 + *
1968 1979 * @return int
1980 + * @since 2.1.3
1969 1981 */
1970 1982 function give_get_nonce_life() {
1971 1983 /**
1972 1984 * Filters the lifespan of nonces in seconds.
@@ -1978,15 +1990,14 @@
1978 1990
1979 1991 /**
1980 1992 * Get nonce field without id
1981 1993 *
1982 - * @since 2.1.3
1983 - *
1984 - * @param string $action
1985 - * @param string $name
1994 + * @param string $action
1995 + * @param string $name
1986 1996 * @param bool $referer
1987 1997 *
1988 1998 * @return string
1999 + * @since 2.1.3
1989 2000 */
1990 2001 function give_get_nonce_field( $action, $name, $referer = false ) {
1991 2002 return str_replace(
1992 2003 "id=\"{$name}\"",
@@ -1997,12 +2008,13 @@
1997 2008
1998 2009 /**
1999 2010 * Display/Return a formatted goal for a donation form
2000 2011 *
2012 + * @since 3.16.0 Add form_id to the array return
2013 + * @since 2.1
2014 + *
2001 2015 * @param int|Give_Donate_Form $form Form ID or Form Object.
2002 2016 *
2003 - * @since 2.1
2004 - *
2005 2017 * @return array
2006 2018 */
2007 2019 function give_goal_progress_stats( $form ) {
2008 2020
@@ -2009,18 +2021,15 @@
2009 2021 if ( ! $form instanceof Give_Donate_Form ) {
2010 2022 $form = new Give_Donate_Form( $form );
2011 2023 }
2012 2024
2013 - $donors = '';
2014 -
2015 2025 $goal_format = give_get_form_goal_format( $form->ID );
2016 2026
2017 2027 /**
2018 2028 * Filter the form.
2019 - *
2020 2029 * @since 1.8.8
2021 2030 */
2022 - $total_goal = apply_filters( 'give_goal_amount_target_output', round( give_maybe_sanitize_amount( $form->goal ) ), $form->ID, $form );
2031 + $total_goal = apply_filters( 'give_goal_amount_target_output', round( give_maybe_sanitize_amount( $form->goal ), 2 ), $form->ID, $form );
2023 2032
2024 2033 switch ( $goal_format ) {
2025 2034 case 'donation':
2026 2035 /**
@@ -2027,40 +2036,41 @@
2027 2036 * Filter the form donations.
2028 2037 *
2029 2038 * @since 2.1
2030 2039 */
2031 - $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 );
2032 2041 break;
2033 2042 case 'donors':
2034 2043 /**
2035 2044 * Filter to modify total number if donor for the donation form.
2036 2045 *
2037 - * @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.
2038 2049 *
2039 - * @param int $donors Total number of donors that donated to the form.
2040 - * @param int $form_id Donation Form ID.
2041 - * @param Give_Donate_Form $form instances of Give_Donate_Form.
2042 - *
2043 2050 * @return int $donors Total number of donors that donated to the form.
2051 + * @since 2.1.3
2044 2052 */
2045 - $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 );
2046 2054 break;
2047 2055 default:
2048 - /**
2049 - * Filter the form income.
2050 - *
2051 - * @since 1.8.8
2052 - */
2053 - $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 );
2054 2064 break;
2055 2065 }
2056 2066
2057 2067 $progress = $total_goal ? round( ( $actual / $total_goal ) * 100, 2 ) : 0;
2058 2068
2059 - $stats_array = array(
2069 + $stats_array = [
2060 2070 'raw_actual' => $actual,
2061 2071 'raw_goal' => $total_goal,
2062 - );
2072 + ];
2063 2073
2064 2074 /**
2065 2075 * Filter the goal progress output
2066 2076 *
@@ -2068,28 +2078,33 @@
2068 2078 */
2069 2079 $progress = apply_filters( 'give_goal_amount_funded_percentage_output', $progress, $form->ID, $form );
2070 2080
2071 2081 // Define Actual Goal based on the goal format.
2072 - if ( 'percentage' === $goal_format ) {
2073 - $actual = "{$actual}%";
2074 - } elseif ( 'amount' === $goal_format ) {
2075 - $actual = give_currency_filter( give_format_amount( $actual ) );
2076 - }
2082 + switch ( $goal_format ) {
2083 + case 'percentage':
2084 + $actual = "{$progress}%";
2085 + $total_goal = '';
2086 + break;
2077 2087
2078 - // Define Total Goal based on the goal format.
2079 - if ( 'percentage' === $goal_format ) {
2080 - $total_goal = '';
2081 - } elseif ( 'amount' === $goal_format ) {
2082 - $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;
2083 2097 }
2084 2098
2085 2099 $stats_array = array_merge(
2086 - array(
2100 + [
2087 2101 'progress' => $progress,
2088 2102 'actual' => $actual,
2089 2103 'goal' => $total_goal,
2090 2104 'format' => $goal_format,
2091 - ),
2105 + 'form_id' => $form->ID
2106 + ],
2092 2107 $stats_array
2093 2108 );
2094 2109
2095 2110 /**
@@ -2102,14 +2117,13 @@
2102 2117
2103 2118 /**
2104 2119 * Get the admin messages key to show the notices.
2105 2120 *
2121 + * @return array $message admin message key.
2106 2122 * @since 2.1.4
2107 - *
2108 - * @return array $message admin message key.
2109 2123 */
2110 2124 function give_get_admin_messages_key() {
2111 - $messages = empty( $_GET['give-messages'] ) ? array() : give_clean( $_GET['give-messages'] );
2125 + $messages = empty( $_GET['give-messages'] ) ? [] : give_clean( $_GET['give-messages'] );
2112 2126
2113 2127 // backward compatibility.
2114 2128 if ( ! empty( $_GET['give-message'] ) ) {
2115 2129 $messages[] = give_clean( $_GET['give-message'] );
@@ -2117,13 +2131,12 @@
2117 2131
2118 2132 /**
2119 2133 * Filter to modify the admin messages key.
2120 2134 *
2121 - * @since 2.1.4
2122 - *
2123 2135 * @param array $message admin message key.
2124 2136 *
2125 2137 * @return array $message admin message key.
2138 + * @since 2.1.4
2126 2139 */
2127 2140 return (array) apply_filters( 'give_get_admin_messages_key', $messages );
2128 2141 }
2129 2142
@@ -2129,11 +2142,10 @@
2129 2142
2130 2143 /**
2131 2144 * Get User Agent String.
2132 2145 *
2146 + * @return array|string
2133 2147 * @since 2.1.4
2134 - *
2135 - * @return array|string
2136 2148 */
2137 2149 function give_get_user_agent() {
2138 2150
2139 2151 // Get User Agent.
@@ -2144,19 +2156,24 @@
2144 2156
2145 2157 /**
2146 2158 * Set a cookie - wrapper for setcookie using WP constants.
2147 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 + *
2148 2165 * @since 2.2.0
2149 - *
2150 - * @param string $name Name of the cookie being set.
2151 - * @param string $value Value of the cookie.
2152 - * @param integer $expire Expiry of the cookie.
2153 - * @param bool $secure Whether the cookie should be served only over https.
2154 2166 */
2155 2167 function give_setcookie( $name, $value, $expire = 0, $secure = false ) {
2156 2168 if ( ! headers_sent() ) {
2157 2169 setcookie(
2158 - $name, $value, $expire, COOKIEPATH ? COOKIEPATH : '/', COOKIE_DOMAIN, $secure,
2170 + $name,
2171 + $value,
2172 + $expire,
2173 + COOKIEPATH ? COOKIEPATH : '/',
2174 + COOKIE_DOMAIN,
2175 + $secure,
2159 2176 apply_filters( 'give_cookie_httponly', false, $name, $value, $expire, $secure )
2160 2177 );
2161 2178 }
2162 2179 }
@@ -2163,15 +2180,14 @@
2163 2180
2164 2181 /**
2165 2182 * Get formatted billing address.
2166 2183 *
2167 - * @since 2.2.0
2168 - *
2169 2184 * @param array $address
2170 2185 *
2171 2186 * @return string Formatted address.
2187 + * @since 2.2.0
2172 2188 */
2173 -function give_get_formatted_address( $address = array() ) {
2189 +function give_get_formatted_address( $address = [] ) {
2174 2190 $formatted_address = '';
2175 2191
2176 2192 /**
2177 2193 * Address format.
@@ -2181,9 +2197,9 @@
2181 2197 $address_format = apply_filters( 'give_address_format_template', "{street_address}\n{city}, {state} {postal_code}\n{country}" );
2182 2198 preg_match_all( '/{([A-z0-9\-\_\ ]+)}/s', $address_format, $matches );
2183 2199
2184 2200 if ( ! empty( $matches ) && ! empty( $address ) ) {
2185 - $address_values = array();
2201 + $address_values = [];
2186 2202
2187 2203 foreach ( $matches[1] as $address_tag ) {
2188 2204 $address_values[ $address_tag ] = '';
2189 2205
@@ -2197,12 +2213,12 @@
2197 2213
2198 2214 /**
2199 2215 * Give get formatted address.
2200 2216 *
2201 - * @since 2.2.0
2202 - *
2203 2217 * @param string $formatted_address Formatted address.
2204 2218 * @param string $address_format Format of the address.
2219 + *
2220 + * @since 2.2.0
2205 2221 */
2206 2222 $formatted_address = apply_filters( 'give_get_formatted_address', $formatted_address, $address_format, $address );
2207 2223
2208 2224 return $formatted_address;
@@ -2211,13 +2227,12 @@
2211 2227 /**
2212 2228 * Get safe url for assets
2213 2229 * Note: this function will return url without http protocol
2214 2230 *
2215 - * @since 2.2.0
2216 - *
2217 2231 * @param string $url URL
2218 2232 *
2219 2233 * @return string
2234 + * @since 2.2.0
2220 2235 */
2221 2236 function give_get_safe_asset_url( $url ) {
2222 2237
2223 2238 // Bailout, if empty URL passed.
@@ -2238,28 +2253,515 @@
2238 2253 }
2239 2254
2240 2255 /**
2241 2256 * Give get formatted date.
2257 + * Note: This function does not work well with localize translated date strings
2242 2258 *
2243 - * @since 2.3.0
2244 - *
2245 2259 * @param string $date Date.
2246 2260 * @param string $format Date Format.
2247 2261 * @param string $current_format Current date Format.
2262 + * @param bool $localize
2248 2263 *
2249 2264 * @return string
2265 + * @since 2.3.0
2250 2266 */
2251 -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 ) {
2252 2268 $current_format = empty( $current_format ) ? give_date_format() : $current_format;
2253 2269 $date_obj = DateTime::createFromFormat( $current_format, $date );
2254 - $formatted_date = $date_obj->format( $format );
2270 + $formatted_date = '';
2255 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 +
2256 2278 /**
2257 2279 * Give get formatted date.
2258 2280 *
2281 + * @param string $formatted_date Formatted date.
2282 + * @param array
2283 + *
2259 2284 * @since 2.3.0
2285 + */
2286 + return apply_filters( 'give_get_formatted_date', $formatted_date, [ $date, $format, $current_format ] );
2287 +}
2288 +
2289 +/**
2290 + * This function will be used to fetch the donation receipt link.
2291 + *
2292 + * @param int $donation_id Donation ID.
2293 + *
2294 + * @return string
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
2309 + *
2310 + * @param int $donation_id Donation ID.
2311 + *
2312 + * @return string
2313 + * @since 2.0
2314 + */
2315 +function give_get_receipt_url( $donation_id ) {
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 +
2339 + return sprintf(
2340 + '<a href="%1$s">%2$s</a>',
2341 + give_get_view_receipt_url( $donation_id ),
2342 + esc_html__( 'View the receipt in your browser &raquo;', 'give' )
2343 + );
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
2260 2491 *
2261 - * @param string $formatted_date Formatted date.
2262 - * @param array
2492 + * @since 2.1.4
2263 2493 */
2264 - return apply_filters( 'give_get_formatted_date', $formatted_date, array( $date, $format, $current_format ) );
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);
2265 2767 }