PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.7.0.5
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.7.0.5
1.8.13.1 1.8.13 1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 All 212 releases
charitable / includes / admin / settings / class-charitable-settings.php

class-charitable-settings.php in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.7.0.5, at includes/admin/settings/class-charitable-settings.php

802 lines 26.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Charitable Settings UI.
4 *
5 * @package Charitable/Classes/Charitable_Settings
6 * @author David Bisset
7 * @copyright Copyright (c) 2022, WP Charitable LLC
8 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9 * @since 1.0.0
10 * @version 1.0.0
11 */
12
13 // Exit if accessed directly.
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit;
16 }
17
18 if ( ! class_exists( 'Charitable_Settings' ) ) :
19
20 /**
21 * Charitable_Settings
22 *
23 * @final
24 * @since 1.0.0
25 */
26 final class Charitable_Settings {
27
28 /**
29 * The single instance of this class.
30 *
31 * @var Charitable_Settings|null
32 */
33 private static $instance = null;
34
35 /**
36 * Dynamic groups.
37 *
38 * @since 1.5.7
39 *
40 * @var array
41 */
42 private $dynamic_groups;
43
44 /**
45 * List of static pages, used in some settings.
46 *
47 * @since 1.5.9
48 *
49 * @var array
50 */
51 private $pages;
52
53 /**
54 * Create object instance.
55 *
56 * @since 1.0.0
57 */
58 private function __construct() {
59 do_action( 'charitable_admin_settings_start', $this );
60
61 add_action( 'charitable_after_admin_settings', [ $this, 'settings_cta' ] );
62 }
63
64 /**
65 * Returns and/or create the single instance of this class.
66 *
67 * @since 1.2.0
68 *
69 * @return Charitable_Settings
70 */
71 public static function get_instance() {
72 if ( is_null( self::$instance ) ) {
73 self::$instance = new self();
74 }
75
76 return self::$instance;
77 }
78
79 /**
80 * Return the array of tabs used on the settings page.
81 *
82 * @since 1.0.0
83 *
84 * @return string[]
85 */
86 public function get_sections() {
87 /**
88 * Filter the settings tabs.
89 *
90 * @since 1.0.0
91 *
92 * @param string[] $tabs List of tabs in key=>label format.
93 */
94 return apply_filters(
95 'charitable_settings_tabs',
96 array(
97 'general' => __( 'General', 'charitable' ),
98 'gateways' => __( 'Payment Gateways', 'charitable' ),
99 'emails' => __( 'Emails', 'charitable' ),
100 'privacy' => __( 'Privacy', 'charitable' ),
101 'advanced' => __( 'Advanced', 'charitable' ),
102 )
103 );
104
105 }
106
107 /**
108 * Optionally add the extensions tab.
109 *
110 * @since 1.3.0
111 *
112 * @param string[] $tabs The existing set of tabs.
113 * @return string[]
114 */
115 public function maybe_add_extensions_tab( $tabs ) {
116 $actual_tab = isset( $_GET['tab'] ) ? $_GET['tab'] : 'general';
117
118 /* Set the tab to 'extensions' */
119 $_GET['tab'] = 'extensions';
120
121 /**
122 * Filter the settings in the extensions tab.
123 *
124 * @since 1.3.0
125 *
126 * @param array $fields Array of fields. Empty by default.
127 */
128 $settings = apply_filters( 'charitable_settings_tab_fields_extensions', array() );
129
130 /* Set the tab back to whatever it actually is */
131 $_GET['tab'] = $actual_tab;
132
133 if ( ! empty( $settings ) ) {
134 $tabs = charitable_add_settings_tab(
135 $tabs,
136 'extensions',
137 __( 'Extensions', 'charitable' ),
138 array(
139 'index' => 4,
140 )
141 );
142 }
143
144 return $tabs;
145 }
146
147 /**
148 * Add the hidden "extensions" section field.
149 *
150 * @since 1.6.7
151 *
152 * @param array $fields All the settings fields.
153 * @return array
154 */
155 public function add_hidden_extensions_setting_field( $fields ) {
156 if ( ! array_key_exists( 'extensions', $fields ) ) {
157 return $fields;
158 }
159
160 $fields['extensions']['section'] = array(
161 'title' => '',
162 'type' => 'hidden',
163 'priority' => 10000,
164 'value' => 'extensions',
165 'save' => false,
166 );
167
168 return $fields;
169 }
170
171 /**
172 * Register setting.
173 *
174 * @since 1.0.0
175 *
176 * @return void
177 */
178 public function register_settings() {
179 if ( ! charitable_is_settings_view() ) {
180 return;
181 }
182
183 register_setting( 'charitable_settings', 'charitable_settings', array( $this, 'sanitize_settings' ) );
184
185 $fields = $this->get_fields();
186
187 if ( empty( $fields ) ) {
188 return;
189 }
190
191 $sections = array_merge( $this->get_sections(), $this->get_dynamic_groups() );
192
193 /* Register each section */
194 foreach ( $sections as $section_key => $section ) {
195 $section_id = 'charitable_settings_' . $section_key;
196
197 add_settings_section(
198 $section_id,
199 __return_null(),
200 '__return_false',
201 $section_id
202 );
203
204 if ( ! isset( $fields[ $section_key ] ) || empty( $fields[ $section_key ] ) ) {
205 continue;
206 }
207
208 /* Sort by priority */
209 $section_fields = $fields[ $section_key ];
210 uasort( $section_fields, 'charitable_priority_sort' );
211
212 /* Add the individual fields within the section */
213 foreach ( $section_fields as $key => $field ) {
214 $this->register_field( $field, array( $section_key, $key ) );
215 }
216 }
217 }
218
219 /**
220 * Sanitize submitted settings before saving to the database including "workaround".
221 *
222 * @since 1.0.0
223 *
224 * @param array $values The submitted values.
225 * @return string
226 */
227 public function sanitize_settings( $values ) {
228
229 $old_values = get_option( 'charitable_settings', array() );
230 $new_values = array();
231
232 if ( ! is_array( $old_values ) ) {
233 $old_values = array();
234 }
235
236 if ( ! is_array( $values ) ) {
237 $values = array();
238 }
239
240 /* Loop through all fields, merging the submitted values into the master array */
241 foreach ( $values as $section => $submitted ) {
242 $new_values = array_merge( $new_values, $this->get_section_submitted_values( $section, $submitted ) );
243 }
244
245 $settings_keys = array_keys( $new_values );
246
247 if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) {
248 error_log( 'santiize_settings' );
249 error_log( 'values:' );
250 error_log( print_r( $values, true ) );
251 error_log( 'old_values:' );
252 error_log( print_r( $old_values, true ) );
253 error_log( 'new_values:' );
254 error_log( print_r( $new_values, true ) );
255 }
256
257 // determine if Charitable gateway "test mode" is being changed, and if so add a notice to the user.
258 if ( array_key_exists('test_mode', $new_values ) && array_key_exists('test_mode', $old_values ) && $old_values['test_mode'] !== $new_values['test_mode'] ) {
259 $old_settings_keys = array_keys( $old_values );
260 $dismissible = true;
261 if ( in_array( 'gateways_stripe', $old_settings_keys ) ) {
262 charitable_get_admin_notices()->add_notice( 'Some active payment gateways <strong>(including Stripe)</strong> might have reset their connections due to an update in the test mode. Please check your active payment gateways in ensure they are still connected.', 'warning', false, $dismissible );
263 } else {
264 charitable_get_admin_notices()->add_notice( 'Some active payment gateways might have reset their connections due to an update in the test mode. Please check your active payment gateways in ensure they are still connected.', 'warning', false, $dismissible );
265 }
266 }
267
268 if ( in_array( 'gateways_stripe', $settings_keys ) && charitable()->is_stripe_connect_addon() && false === charitable_using_stripe_connect() ) {
269 // non-existant array keys in the array for API keys might be a result of the "manual update key" feature which is based on ajax and might not load keys into form if the user doesn't click on the link in the settings to view/edit them.
270 if ( ! array_key_exists( 'live_secret_key', $values['gateways_stripe'] ) && isset( $old_values['gateways_stripe']['live_secret_key'] ) && ( false !== $old_values['gateways_stripe']['live_secret_key'] ) ) {
271 $values['gateways_stripe']['live_secret_key'] = $old_values['gateways_stripe']['live_secret_key'];
272 }
273 if ( ! array_key_exists( 'live_public_key', $values['gateways_stripe'] ) && isset( $old_values['gateways_stripe']['live_public_key'] ) && ( false !== $old_values['gateways_stripe']['live_public_key'] ) ) {
274 $values['gateways_stripe']['live_public_key'] = $old_values['gateways_stripe']['live_secret_key'];
275 }
276 if ( ! array_key_exists( 'test_secret_key', $values['gateways_stripe'] ) && isset( $old_values['gateways_stripe']['test_secret_key'] ) && ( false !== $old_values['gateways_stripe']['test_secret_key'] ) ) {
277 $values['gateways_stripe']['test_secret_key'] = $old_values['gateways_stripe']['test_secret_key'];
278 }
279 if ( ! array_key_exists( 'test_public_key', $values['gateways_stripe'] ) && isset( $old_values['gateways_stripe']['test_public_key'] ) && ( false !== $old_values['gateways_stripe']['test_public_key'] ) ) {
280 $values['gateways_stripe']['test_public_key'] = $old_values['gateways_stripe']['test_public_key'];
281 }
282 if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) {
283 error_log( 'update:' );
284 error_log( print_r( $values, true ) );
285 }
286 }
287
288 // determine if stripe is being returned as new values - if so, then perform the API key save workaround
289 if ( in_array( 'gateways_stripe', $settings_keys ) && charitable()->is_stripe_connect_addon() && false === charitable_using_stripe_connect() ) {
290 if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) {
291 error_log( 'there is a stripe connect addon but we are not using stripe connect' );
292 }
293 // the stripe connect addon is installed AND the AM Stripe Connect isn't being used... so it's possible the keys could be manual and the user could be updating them... therefore let's just make sure the new values match the values incoming.
294 $new_values['gateways_stripe']['live_secret_key'] = ( isset( $values['gateways_stripe']['live_secret_key'] ) && ( false !== $values['gateways_stripe']['live_secret_key'] ) ) ? $values['gateways_stripe']['live_secret_key'] : null;
295 $new_values['gateways_stripe']['live_public_key'] = ( isset( $values['gateways_stripe']['live_public_key'] ) && ( false !== $values['gateways_stripe']['live_public_key'] ) ) ? $values['gateways_stripe']['live_public_key'] : null;
296 $new_values['gateways_stripe']['test_secret_key'] = ( isset( $values['gateways_stripe']['test_secret_key'] ) && ( false !== $values['gateways_stripe']['test_secret_key'] ) ) ? $values['gateways_stripe']['test_secret_key'] : null;
297 $new_values['gateways_stripe']['test_public_key'] = ( isset( $values['gateways_stripe']['test_public_key'] ) && ( false !== $values['gateways_stripe']['test_public_key'] ) ) ? $values['gateways_stripe']['test_public_key'] : null;
298 } else if ( in_array( 'gateways_stripe', $settings_keys ) ) {
299 // otherwise we preserve the keys
300 if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) {
301 error_log( 'charitable debug, final with debug on:' );
302 $new_values['gateways_stripe']['live_secret_key'] = ( isset( $values['gateways_stripe']['live_secret_key'] ) && ( false !== $values['gateways_stripe']['live_secret_key'] ) ) ? $values['gateways_stripe']['live_secret_key'] : null;
303 $new_values['gateways_stripe']['live_public_key'] = ( isset( $values['gateways_stripe']['live_public_key'] ) && ( false !== $values['gateways_stripe']['live_public_key'] ) ) ? $values['gateways_stripe']['live_public_key'] : null;
304 $new_values['gateways_stripe']['test_secret_key'] = ( isset( $values['gateways_stripe']['test_secret_key'] ) && ( false !== $values['gateways_stripe']['test_secret_key'] ) ) ? $values['gateways_stripe']['test_secret_key'] : null;
305 $new_values['gateways_stripe']['test_public_key'] = ( isset( $values['gateways_stripe']['test_public_key'] ) && ( false !== $values['gateways_stripe']['test_public_key'] ) ) ? $values['gateways_stripe']['test_public_key'] : null;
306 } else {
307 $new_values['gateways_stripe']['live_secret_key'] = ( isset( $old_values['gateways_stripe']['live_secret_key'] ) && ( false !== $old_values['gateways_stripe']['live_secret_key'] ) ) ? $old_values['gateways_stripe']['live_secret_key'] : null;
308 $new_values['gateways_stripe']['live_public_key'] = ( isset( $old_values['gateways_stripe']['live_public_key'] ) && ( false !== $old_values['gateways_stripe']['live_public_key'] ) ) ? $old_values['gateways_stripe']['live_public_key'] : null;
309 $new_values['gateways_stripe']['test_secret_key'] = ( isset( $old_values['gateways_stripe']['test_secret_key'] ) && ( false !== $old_values['gateways_stripe']['test_secret_key'] ) ) ? $old_values['gateways_stripe']['test_secret_key'] : null;
310 $new_values['gateways_stripe']['test_public_key'] = ( isset( $old_values['gateways_stripe']['test_public_key'] ) && ( false !== $old_values['gateways_stripe']['test_public_key'] ) ) ? $old_values['gateways_stripe']['test_public_key'] : null;
311 }
312 }
313
314 // preserve any webhook keys, regardless if stripe connect addon is active or not.
315 if ( in_array( 'gateways_stripe', $settings_keys ) ) {
316 if ( array_key_exists( 'test_webhook_id', $old_values['gateways_stripe'] ) && isset( $old_values['gateways_stripe']['test_webhook_id'] ) ) {
317 $new_values['gateways_stripe']['test_webhook_id'] = $old_values['gateways_stripe']['test_webhook_id'];
318 }
319 if ( array_key_exists( 'live_webhook_id', $old_values['gateways_stripe'] ) && isset( $old_values['gateways_stripe']['live_webhook_id'] ) ) {
320 $new_values['gateways_stripe']['live_webhook_id'] = $old_values['gateways_stripe']['live_webhook_id'];
321 }
322 }
323
324 // account for incoming legacy licenses (1.7.0.4+)
325 // all we are doing is adding the licenses into the values so that the save_license hook can retreieve them and validate, etc.
326 if ( ! empty( $values['legacy_licenses'] ) && isset( $values['advanced']['section'] ) && 'licenses' === $values['advanced']['section'] ) {
327 if ( ! isset( $new_values['licenses']['legacy'] ) ) {
328 $new_values['licenses_legacy'] = (array) $values['legacy_licenses'];
329 }
330 }
331
332 $values = wp_parse_args( $new_values, $old_values );
333
334 if ( defined( 'CHARITABLE_DEBUG' ) && CHARITABLE_DEBUG ) {
335 error_log( 'santiize_settings values updated' );
336 error_log( print_r( $values, true ) );
337 }
338
339 /**
340 * Filter sanitized settings.
341 *
342 * @since 1.0.0
343 *
344 * @param array $values All values, merged.
345 * @param array $new_values Newly submitted values.
346 * @param array $old_values Old settings.
347 */
348
349 $values = apply_filters( 'charitable_save_settings', $values, $new_values, $old_values );
350
351 $this->add_update_message( __( 'Settings saved', 'charitable' ), 'success' );
352
353 return $values;
354 }
355
356 /**
357 * Checkbox settings should always be either 1 or 0.
358 *
359 * @since 1.0.0
360 *
361 * @param mixed $value Submitted value for field.
362 * @param array $field Field definition.
363 * @return int
364 */
365 public function sanitize_checkbox_value( $value, $field ) {
366 if ( isset( $field['type'] ) && 'checkbox' == $field['type'] ) {
367 $value = intval( $value && 'on' == $value );
368 }
369
370 return $value;
371 }
372
373 /**
374 * Render field. This is the default callback used for all fields, unless an alternative callback has been specified.
375 *
376 * @since 1.0.0
377 *
378 * @param array $args Field definition.
379 * @return void
380 */
381 public function render_field( $args ) {
382 $field_type = isset( $args['type'] ) ? $args['type'] : 'text';
383
384 charitable_admin_view( 'settings/' . $field_type, $args );
385 }
386
387 /**
388 * Returns an array of all pages in the id=>title format.
389 *
390 * @since 1.0.0
391 *
392 * @return string[]
393 */
394 public function get_pages() {
395 if ( ! isset( $this->pages ) ) {
396 $this->pages = charitable_get_pages_options();
397 }
398
399 return $this->pages;
400 }
401
402 /**
403 * Add an update message.
404 *
405 * @since 1.4.6
406 *
407 * @param string $message The message text.
408 * @param string $type The type of message. Options: 'error', 'success', 'warning', 'info'.
409 * @param boolean $dismissible Whether the message can be dismissed.
410 * @return void
411 */
412 public function add_update_message( $message, $type = 'error', $dismissible = true ) {
413 if ( ! in_array( $type, array( 'error', 'success', 'warning', 'info' ) ) ) {
414 $type = 'error';
415 }
416
417 charitable_get_admin_notices()->add_notice( $message, $type, false, $dismissible );
418 }
419
420 /**
421 * Recursively add settings fields, given an array.
422 *
423 * @since 1.0.0
424 *
425 * @param array $field The setting field.
426 * @param array $keys Array containing the section key and field key.
427 * @return void
428 */
429 private function register_field( $field, $keys ) {
430 $section_id = 'charitable_settings_' . $keys[0];
431
432 if ( isset( $field['render'] ) && ! $field['render'] ) {
433 return;
434 }
435
436 /* Drop the first key, which is the section identifier */
437 $field['name'] = implode( '][', $keys );
438
439 if ( ! $this->is_dynamic_group( $keys[0] ) ) {
440 array_shift( $keys );
441 }
442
443 $field['key'] = $keys;
444 $field['classes'] = $this->get_field_classes( $field );
445 $callback = isset( $field['callback'] ) ? $field['callback'] : array( $this, 'render_field' );
446 $label = $this->get_field_label( $field, end( $keys ) );
447
448 add_settings_field(
449 sprintf( 'charitable_settings_%s', implode( '_', $keys ) ),
450 $label,
451 $callback,
452 $section_id,
453 $section_id,
454 $field
455 );
456 }
457
458 /**
459 * Return the label for the given field.
460 *
461 * @since 1.0.0
462 *
463 * @param array $field The field definition.
464 * @param string $key The field key.
465 * @return string
466 */
467 private function get_field_label( $field, $key ) {
468 $label = '';
469
470 if ( isset( $field['label_for'] ) ) {
471 $label = $field['label_for'];
472 }
473
474 if ( isset( $field['title'] ) ) {
475 $label = $field['title'];
476 }
477
478 return $label;
479 }
480
481 /**
482 * Return a space separated string of classes for the given field.
483 *
484 * @since 1.0.0
485 *
486 * @param array $field Field definition.
487 * @return string
488 */
489 private function get_field_classes( $field ) {
490 $classes = array( 'charitable-settings-field' );
491
492 if ( isset( $field['class'] ) ) {
493 $classes[] = $field['class'];
494 }
495
496 /**
497 * Filter the list of classes to apply to settings fields.
498 *
499 * @since 1.0.0
500 *
501 * @param array $classes The list of classes.
502 * @param array $field The field definition.
503 */
504 $classes = apply_filters( 'charitable_settings_field_classes', $classes, $field );
505
506 return implode( ' ', $classes );
507 }
508
509 /**
510 * Return an array with all the fields & sections to be displayed.
511 *
512 * @uses charitable_settings_fields
513 * @see Charitable_Settings::register_setting()
514 * @since 1.0.0
515 *
516 * @return array
517 */
518 private function get_fields() {
519 /**
520 * Use the charitable_settings_tab_fields to include the fields for new tabs.
521 * DO NOT use it to add individual fields. That should be done with the
522 * filters within each of the methods.
523 */
524 $fields = array();
525
526 foreach ( $this->get_sections() as $section_key => $section ) {
527 /**
528 * Filter the array of fields to display in a particular tab.
529 *
530 * @since 1.0.0
531 *
532 * @param array $fields Array of fields.
533 */
534 $fields[ $section_key ] = apply_filters( 'charitable_settings_tab_fields_' . $section_key, array() );
535 }
536
537 /**
538 * Filter the array of settings fields.
539 *
540 * @since 1.0.0
541 *
542 * @param array $fields Array of fields.
543 */
544 return apply_filters( 'charitable_settings_tab_fields', $fields );
545 }
546
547 /**
548 * Get the submitted value for a particular setting.
549 *
550 * @since 1.0.0
551 *
552 * @param string $key The key of the setting being saved.
553 * @param array $field The setting field.
554 * @param array $submitted The submitted values.
555 * @param string $section The section being saved.
556 * @return mixed|null Returns null if the value was not submitted or is not applicable.
557 */
558 private function get_setting_submitted_value( $key, $field, $submitted, $section ) {
559 $value = null;
560
561 if ( isset( $field['save'] ) && ! $field['save'] ) {
562 return $value;
563 }
564
565 $field_type = isset( $field['type'] ) ? $field['type'] : '';
566
567 switch ( $field_type ) {
568
569 case 'checkbox':
570 $value = intval( array_key_exists( $key, $submitted ) && 'on' == $submitted[ $key ] );
571 break;
572
573 case 'multi-checkbox':
574 $value = isset( $submitted[ $key ] ) ? $submitted[ $key ] : array();
575 break;
576
577 case '':
578 case 'heading':
579 return $value;
580
581 default:
582 if ( ! array_key_exists( $key, $submitted ) ) {
583 return $value;
584 }
585
586 $value = $submitted[ $key ];
587
588 }//end switch
589
590 /**
591 * General way to sanitize values. If you only need to sanitize a
592 * specific setting, used the filter below instead.
593 *
594 * @since 1.0.0
595 *
596 * @param mixed $value The current setting value.
597 * @param array $field The field configuration.
598 * @param array $submitted All submitted data.
599 * @param string $key The setting key.
600 * @param string $section The section being saved.
601 */
602 $value = apply_filters( 'charitable_sanitize_value', $value, $field, $submitted, $key, $section );
603
604 /**
605 * Sanitize the setting value.
606 *
607 * The filter hook is formatted like this: charitable_sanitize_value_{$section}_{$key}.
608 *
609 * @since 1.5.0
610 *
611 * @param mixed $value The current setting value.
612 * @param array $field The field configuration.
613 * @param array $submitted All submitted data.
614 */
615 return apply_filters( 'charitable_sanitize_value_' . $section . '_' . $key, $value, $field, $submitted );
616 }
617
618 /**
619 * Return the submitted values for the given section.
620 *
621 * @since 1.0.0
622 *
623 * @param string $section The section being edited.
624 * @param array $submitted The submitted values.
625 * @return array
626 */
627 private function get_section_submitted_values( $section, $submitted ) {
628 $values = array();
629 $form_fields = $this->get_fields();
630
631 if ( ! isset( $form_fields[ $section ] ) ) {
632 return $values;
633 }
634
635 foreach ( $form_fields[ $section ] as $key => $field ) {
636 $value = $this->get_setting_submitted_value( $key, $field, $submitted, $section );
637
638 if ( is_null( $value ) ) {
639 continue;
640 }
641
642 if ( $this->is_dynamic_group( $section ) ) {
643 $values[ $section ][ $key ] = $value;
644 continue;
645 }
646
647 $values[ $key ] = $value;
648 }
649
650 return $values;
651 }
652
653 /**
654 * Return list of dynamic groups.
655 *
656 * @since 1.0.0
657 *
658 * @return string[]
659 */
660 private function get_dynamic_groups() {
661 if ( ! isset( $this->dynamic_groups ) ) {
662 /**
663 * Filter the list of dynamic groups.
664 *
665 * @since 1.0.0
666 *
667 * @param array $groups The dynamic groups.
668 */
669 $this->dynamic_groups = apply_filters( 'charitable_dynamic_groups', array() );
670 }
671
672 return $this->dynamic_groups;
673 }
674
675 /**
676 * Returns whether the given key indicates the start of a new section of the settings.
677 *
678 * @since 1.0.0
679 *
680 * @param string $composite_key The unique key for this group.
681 * @return boolean
682 */
683 private function is_dynamic_group( $composite_key ) {
684 return array_key_exists( $composite_key, $this->get_dynamic_groups() );
685 }
686
687 /* DEPRECATED FUNCTIONS */
688
689 /**
690 * Get the update messages.
691 *
692 * @deprecated 1.7.0
693 *
694 * @since 1.4.13 Deprecated.
695 */
696 public function get_update_messages() {
697 charitable_get_deprecated()->deprecated_function(
698 __METHOD__,
699 '1.4.13',
700 'Charitable_Admin_Notices::get_notices()'
701 );
702
703 return charitable_get_admin_notices()->get_notices();
704 }
705
706 /**
707 * Display upgrade notice at the bottom on the plugin settings pages.
708 *
709 * @since 1.7.0.4
710 *
711 * @param string $view Current view inside the plugin settings page.
712 */
713 public function settings_cta( $view = false ) {
714
715 if ( charitable_is_pro() ) {
716 // no need to display this cta since they have a valid license.
717 return;
718 }
719
720 if ( get_option( 'charitable_lite_settings_upgrade', false ) || apply_filters( 'charitable_lite_settings_upgrade', false ) ) {
721 return;
722 }
723 ?>
724 <div class="settings-lite-cta">
725 <button type="button" class="button-link charitable-banner-dismiss dismiss">x</button>
726 <h5><?php esc_html_e( 'Get Charitable Pro and Unlock all the Powerful Features', 'charitable-lite' ); ?></h5>
727 <p><?php esc_html_e( 'Thanks for being a loyal Charitable Lite user. Upgrade to Charitable Pro to unlock all the awesome features and experience why Charitable is consistently rated a top WordPress donation and fundraising plugin.', 'charitable-lite' ); ?></p>
728 <p>
729 <?php
730 printf( __( 'We know that you will truly love Charitable. Over 10,000+ non-profits who have chosen Charitable to get more donations from their website can\'t be wrong!', 'charitable-lite' ) );
731 ?>
732 </p>
733 <h6><?php esc_html_e( 'Pro Features:', 'charitable-lite' ); ?></h6>
734 <div class="list">
735 <ul>
736 <li><?php esc_html_e( 'Offer recurring donations to donors', 'charitable-lite' ); ?></li>
737 <li><?php esc_html_e( 'Use fee relief to keep more donation dollars', 'charitable-lite' ); ?></li>
738 <li><?php esc_html_e( 'Integrate with popular email marketing platforms', 'charitable-lite' ); ?></li>
739 <li><?php esc_html_e( 'Expand your reach with peer-to-peer fundraising', 'charitable-lite' ); ?></li>
740 <li><?php esc_html_e( 'Allow donors to crowdfund donations', 'charitable-lite' ); ?></li>
741 </ul>
742 <ul>
743 <li><?php esc_html_e( 'Automate common tasks with Zapier and smart workflows', 'charitable-lite' ); ?></li>
744 <li><?php esc_html_e( 'Run campaigns with ambassador and team support', 'charitable-lite' ); ?></li>
745 <li><?php esc_html_e( 'Advanced donation management with annual receipts' ); ?></li>
746 <li><?php esc_html_e( 'Allow donors to give donations anonymously', 'charitable-lite' ); ?></li>
747 <li><?php esc_html_e( 'Add videos and updates to all campaigns', 'charitable-lite' ); ?></li>
748 </ul>
749 </div>
750 <p>
751 <a href="<?php echo esc_url( charitable_pro_upgrade_url( 'settings-upgrade' ) ); ?>" target="_blank" rel="noopener noreferrer">
752 <?php esc_html_e( 'Get Charitable Pro Today and Unlock all the Powerful Features »', 'charitable-lite' ); ?>
753 </a>
754 </p>
755 <p>
756 <?php
757 echo wp_kses(
758 __( '<strong>Bonus:</strong> Charitable Lite users get up to <span class="green">$200 off regular price</span>, automatically applied at checkout.', 'charitable-lite' ),
759 [
760 'strong' => [],
761 'span' => [
762 'class' => [],
763 ],
764 ]
765 );
766 ?>
767 </p>
768 </div>
769 <script type="text/javascript">
770 jQuery( function ( $ ) {
771 $( document ).on( 'click', '.settings-lite-cta .dismiss', function ( event ) {
772 event.preventDefault();
773 $.post( ajaxurl, {
774 action: 'charitable_lite_settings_upgrade',
775 chartiable_action: 'remove_lite_cta'
776 } );
777 $( '.settings-lite-cta' ).remove();
778 } );
779 } );
780 </script>
781 <?php
782 }
783
784 /**
785 * Dismiss upgrade notice at the bottom on the plugin settings pages.
786 *
787 * @since 1.7.0.4
788 */
789 public function settings_cta_dismiss() {
790
791 if ( ! charitable_current_user_can() ) {
792 wp_send_json_error();
793 }
794
795 update_option( 'charitable_lite_settings_upgrade', time() );
796
797 wp_send_json_success();
798 }
799 }
800
801 endif;
802