PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.12
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.12
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 1.7.0.9 1.8.0 All 210 releases
charitable / includes / admin / tools / class-charitable-tools.php

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

563 lines 16.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Charitable Tools UI.
4 *
5 * @package Charitable/Classes/Charitable_Tools
6 * @author David Bisset
7 * @copyright Copyright (c) 2023, WP Charitable LLC
8 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9 * @since 1.8.1.6
10 * @version 1.8.9
11 */
12
13 // Exit if accessed directly.
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit;
16 }
17
18 if ( ! class_exists( 'Charitable_Tools' ) ) :
19
20 /**
21 * Charitable_Tools
22 *
23 * @final
24 * @since 1.8.1.6
25 */
26 class Charitable_Tools {
27
28 /**
29 * The single instance of this class.
30 *
31 * @var Charitable_Tools|null
32 */
33 private static $instance = null;
34
35
36 /**
37 * The dynamic groups.
38 *
39 * @var array
40 */
41 public $dynamic_groups;
42
43 /**
44 * Create object instance.
45 *
46 * @since 1.8.1.6
47 * @version 1.8.9
48 */
49 public function __construct() {
50
51 // Set the default tab.
52 // Only redirect if we're on the tools page (not options.php) and no tab is set.
53 // Don't redirect when processing form submissions (options.php).
54 $is_options_page = isset( $_SERVER['REQUEST_URI'] ) && false !== strpos( $_SERVER['REQUEST_URI'], 'options.php' ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
55 if ( charitable_is_tools_view() && ! isset( $_GET['tab'] ) && ! $is_options_page ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
56 $link = admin_url( 'edit-tags.php?taxonomy=campaign_category&post_type=campaign' );
57 wp_safe_redirect( $link );
58 exit();
59 }
60
61 add_action( 'campaign_category_pre_add_form', array( $this, 'add_tools_nav_to_taxononmy_pages' ), 10, 1 );
62 add_action( 'campaign_tag_pre_add_form', array( $this, 'add_tools_nav_to_taxononmy_pages' ), 10, 1 );
63 add_action( 'campaign_category_pre_edit_form', array( $this, 'add_tools_nav_to_taxononmy_pages' ), 10, 1 );
64 add_action( 'campaign_tag_pre_edit_form', array( $this, 'add_tools_nav_to_taxononmy_pages' ), 10, 1 );
65 add_action( 'admin_init', array( $this, 'taxonomy_redirects' ), 10, 1 );
66 }
67
68 /**
69 * Redirects to the correct taxonomy page.
70 *
71 * @since 1.8.2
72 * @version 1.8.9
73 *
74 * @return void
75 */
76 public function taxonomy_redirects() {
77 if ( isset( $_GET['page'] ) && 'charitable-tools' == $_GET['page'] && isset( $_GET['tab'] ) && 'categories' == $_GET['tab'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
78 $link = admin_url( 'edit-tags.php?taxonomy=campaign_category&post_type=campaign' );
79 wp_safe_redirect( $link );
80 exit();
81 }
82
83 if ( isset( $_GET['page'] ) && 'charitable-tools' == $_GET['page'] && isset( $_GET['tab'] ) && 'tags' == $_GET['tab'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
84 $link = admin_url( 'edit-tags.php?taxonomy=campaign_tag&post_type=campaign' );
85 wp_safe_redirect( $link );
86 exit();
87 }
88 }
89
90 /**
91 * Returns and/or create the single instance of this class.
92 *
93 * @since 1.8.1.6
94 *
95 * @return Charitable_Tools
96 */
97 public static function get_instance() {
98 if ( is_null( self::$instance ) ) {
99 self::$instance = new self();
100 }
101
102 return self::$instance;
103 }
104
105 /**
106 * Run things upon init.
107 *
108 * @since 1.8.1.6
109 *
110 * @return void
111 */
112 public function init() {
113 }
114
115 /**
116 * Return the sub-sections for the Import tab.
117 *
118 * @since 1.8.10
119 *
120 * @return array
121 */
122 public function get_sub_sections_import() {
123 /**
124 * Filter the import sub-tabs.
125 *
126 * @since 1.8.10
127 *
128 * @param array $sub_tabs List of sub-tabs in key=>label format.
129 */
130 return apply_filters(
131 'charitable_tools_import_sub_tabs',
132 array(
133 'import__charitable' => __( 'Charitable', 'charitable' ),
134 'import__givewp' => __( 'GiveWP', 'charitable' ),
135 'import__givebutter' => __( 'GiveButter', 'charitable' ),
136 )
137 );
138 }
139
140 /**
141 * Redirect to default sub-tab when on the import tab without a sub_tab parameter.
142 *
143 * @since 1.8.10
144 *
145 * @return void
146 */
147 public function tools_sub_tab_default() {
148 // Don't redirect during form submissions.
149 if ( ! empty( $_POST ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
150 return;
151 }
152
153 if ( ! charitable_is_tools_view( 'import' ) ) {
154 return;
155 }
156
157 if ( isset( $_GET['sub_tab'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
158 return;
159 }
160
161 $link = admin_url( 'admin.php?page=charitable-tools&tab=import&sub_tab=charitable' );
162 wp_safe_redirect( $link );
163 exit();
164 }
165
166 /**
167 * Return the array of tabs used on the settings page.
168 *
169 * @since 1.8.1.6
170 *
171 * @return string[]
172 */
173 public function get_sections() {
174 /**
175 * Filter the settings tabs.
176 *
177 * @since 1.8.1.6
178 *
179 * @param string[] $tabs List of tabs in key=>label format.
180 */
181 return apply_filters(
182 'charitable_tools_tabs',
183 array(
184 'categories' => __( 'Categories', 'charitable' ),
185 'tags' => __( 'Tags', 'charitable' ),
186 'customize' => __( 'Customize', 'charitable' ),
187 'export' => __( 'Export', 'charitable' ),
188 'import' => __( 'Import', 'charitable' ),
189 'system-info' => __( 'System Info', 'charitable' ),
190 'snippets' => __( 'Code Snippets', 'charitable' ),
191 'logs' => __( 'Logs', 'charitable' ),
192 'misc' => __( 'Misc', 'charitable' ),
193 )
194 );
195 }
196
197 /**
198 * Register setting.
199 *
200 * @since 1.0.0
201 *
202 * @return void
203 */
204 public function register_settings() {
205
206 if ( ! charitable_is_tools_view() ) {
207 return;
208 }
209
210 register_setting( 'charitable_tools', 'charitable_tools', array( $this, 'sanitize_settings' ) );
211
212 $fields = $this->get_fields();
213
214 if ( empty( $fields ) ) {
215 return;
216 }
217
218 $sections = array_merge( $this->get_sections(), $this->get_sub_sections_import(), $this->get_dynamic_groups() );
219
220 /* Register each section */
221 foreach ( $sections as $section_key => $section ) {
222 $section_id = 'charitable_tools_' . $section_key;
223
224 add_settings_section(
225 $section_id,
226 __return_null(),
227 '__return_false',
228 $section_id
229 );
230
231 if ( ! isset( $fields[ $section_key ] ) || empty( $fields[ $section_key ] ) ) {
232 continue;
233 }
234
235 /* Sort by priority */
236 $section_fields = $fields[ $section_key ];
237 uasort( $section_fields, 'charitable_priority_sort' );
238
239 /* Add the individual fields within the section */
240 foreach ( $section_fields as $key => $field ) {
241 $this->register_field( $field, array( $section_key, $key ) );
242 }
243 }
244 }
245
246 /**
247 * Return list of dynamic groups.
248 *
249 * @since 1.8.1.6
250 *
251 * @return string[]
252 */
253 private function get_dynamic_groups() {
254 if ( ! isset( $this->dynamic_groups ) ) {
255 /**
256 * Filter the list of dynamic groups.
257 *
258 * @since 1.8.1.6
259 *
260 * @param array $groups The dynamic groups.
261 */
262 $this->dynamic_groups = apply_filters( 'charitable_dynamic_tools_groups', array() );
263 }
264
265 return $this->dynamic_groups;
266 }
267
268 /**
269 * Returns whether the given key indicates the start of a new section of the settings.
270 *
271 * @since 1.0.0
272 *
273 * @param string $composite_key The unique key for this group.
274 * @return boolean
275 */
276 private function is_dynamic_group( $composite_key ) {
277 return array_key_exists( $composite_key, $this->get_dynamic_groups() );
278 }
279
280 /**
281 * Return the label for the given field.
282 *
283 * @since 1.0.0
284 *
285 * @param array $field The field definition.
286 * @param string $key The field key.
287 * @return string
288 */
289 private function get_field_label( $field, $key ) { // phpcs:ignore
290 $label = '';
291
292 if ( isset( $field['label_for'] ) ) {
293 $label = $field['label_for'];
294 }
295
296 if ( isset( $field['title'] ) ) {
297 $label = $field['title'];
298 }
299
300 return $label;
301 }
302
303 /**
304 * Return a space separated string of classes for the given field.
305 *
306 * @since 1.0.0
307 *
308 * @param array $field Field definition.
309 * @return string
310 */
311 private function get_field_classes( $field ) {
312 $classes = array( 'charitable-settings-field' );
313
314 if ( isset( $field['class'] ) ) {
315 $classes[] = $field['class'];
316 }
317
318 /**
319 * Filter the list of classes to apply to settings fields.
320 *
321 * @since 1.0.0
322 *
323 * @param array $classes The list of classes.
324 * @param array $field The field definition.
325 */
326 $classes = apply_filters( 'charitable_settings_field_classes', $classes, $field );
327
328 return implode( ' ', $classes );
329 }
330
331 /**
332 * Return an array with all the fields & sections to be displayed.
333 *
334 * @uses charitable_settings_fields
335 * @see Charitable_Settings::register_setting()
336 * @since 1.0.0
337 *
338 * @return array
339 */
340 private function get_fields() {
341 /**
342 * Use the charitable_settings_tab_fields to include the fields for new tabs.
343 * DO NOT use it to add individual fields. That should be done with the
344 * filters within each of the methods.
345 */
346 $fields = array();
347
348 $all_sections = array_merge( $this->get_sections(), $this->get_sub_sections_import() );
349
350 foreach ( $all_sections as $section_key => $section ) {
351 /**
352 * Filter the array of fields to display in a particular tab.
353 *
354 * For sub-tabs, uses the filter name charitable_tools_tab_fields_sub_{key}.
355 *
356 * @since 1.0.0
357 *
358 * @param array $fields Array of fields.
359 */
360 $filter_name = ( false !== strpos( $section_key, '__' ) )
361 ? 'charitable_tools_tab_fields_sub_' . $section_key
362 : 'charitable_tools_tab_fields_' . $section_key;
363
364 $fields[ $section_key ] = apply_filters( $filter_name, array() );
365 }
366
367 /**
368 * Filter the array of settings fields.
369 *
370 * @since 1.0.0
371 *
372 * @param array $fields Array of fields.
373 */
374 return apply_filters( 'charitable_tools_tab_fields', $fields );
375 }
376
377 /**
378 * Recursively add settings fields, given an array.
379 *
380 * @since 1.0.0
381 *
382 * @param array $field The setting field.
383 * @param array $keys Array containing the section key and field key.
384 * @return void
385 */
386 private function register_field( $field, $keys ) {
387 $section_id = 'charitable_tools_' . $keys[0];
388
389 if ( isset( $field['render'] ) && ! $field['render'] ) {
390 return;
391 }
392
393 /* Drop the first key, which is the section identifier */
394 $field['name'] = implode( '][', $keys );
395
396 if ( ! $this->is_dynamic_group( $keys[0] ) ) {
397 array_shift( $keys );
398 }
399
400 $field['key'] = $keys;
401 $field['classes'] = $this->get_field_classes( $field );
402 $callback = isset( $field['callback'] ) ? $field['callback'] : array( $this, 'render_field' );
403 $label = $this->get_field_label( $field, end( $keys ) );
404
405 add_settings_field(
406 sprintf( 'charitable_tools_%s', implode( '_', $keys ) ),
407 $label,
408 $callback,
409 $section_id,
410 $section_id,
411 $field
412 );
413 }
414
415 /**
416 * Sanitize settings before saving.
417 *
418 * @since 1.8.9
419 *
420 * @param array $values Submitted values.
421 * @return array
422 */
423 public function sanitize_settings( $values ) {
424 $old_values = get_option( 'charitable_tools', array() );
425 $new_values = array();
426
427 if ( ! is_array( $old_values ) ) {
428 $old_values = array();
429 }
430
431 if ( ! is_array( $values ) ) {
432 $values = array();
433 }
434
435 // Merge submitted values into the master array.
436 foreach ( $values as $section => $submitted ) {
437 if ( ! is_array( $submitted ) ) {
438 continue;
439 }
440 foreach ( $submitted as $key => $value ) {
441 if ( $this->is_dynamic_group( $section ) ) {
442 $new_values[ $section ][ $key ] = $value;
443 } else {
444 $new_values[ $key ] = $value;
445 }
446 }
447 }
448
449 $values = wp_parse_args( $new_values, $old_values );
450
451 if ( charitable_is_debug() ) {
452 error_log( 'sanitize_settings tools' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
453 error_log( 'values:' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
454 error_log( print_r( $values, true ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log,WordPress.PHP.DevelopmentFunctions.error_log_print_r
455 error_log( 'old_values:' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
456 error_log( print_r( $old_values, true ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log,WordPress.PHP.DevelopmentFunctions.error_log_print_r
457 error_log( 'new_values:' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
458 error_log( print_r( $new_values, true ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log,WordPress.PHP.DevelopmentFunctions.error_log_print_r
459 }
460
461 /**
462 * Filter sanitized tools settings.
463 *
464 * @since 1.8.9
465 *
466 * @param array $values All values, merged.
467 * @param array $new_values Newly submitted values.
468 * @param array $old_values Old settings.
469 */
470 $values = apply_filters( 'charitable_save_tools', $values, $new_values, $old_values );
471
472 return $values;
473 }
474
475 /**
476 * Checkbox settings should always be either 1 or 0.
477 *
478 * @since 1.0.0
479 *
480 * @param mixed $value Submitted value for field.
481 * @param array $field Field definition.
482 * @return int
483 */
484 public function sanitize_checkbox_value( $value, $field ) {
485 if ( isset( $field['type'] ) && 'checkbox' == $field['type'] ) {
486 $value = intval( $value && 'on' == $value );
487 }
488
489 return $value;
490 }
491
492 /**
493 * Render field. This is the default callback used for all fields, unless an alternative callback has been specified.
494 *
495 * @since 1.0.0
496 *
497 * @param array $args Field definition.
498 * @return void
499 */
500 public function render_field( $args ) {
501 $field_type = isset( $args['type'] ) ? $args['type'] : 'text';
502
503 charitable_admin_view( 'settings/' . $field_type, $args );
504 }
505
506 /**
507 * Returns an array of all pages in the id=>title format.
508 *
509 * @since 1.0.0
510 *
511 * @return string[]
512 */
513 public function get_pages() {
514 if ( ! isset( $this->pages ) ) {
515 $this->pages = charitable_get_pages_options();
516 }
517
518 return $this->pages;
519 }
520
521 /**
522 * Add tools nav to taxonomy pages.
523 *
524 * @since 1.8.2
525 *
526 * @param string $taxonomy The taxonomy.
527 *
528 * @return void
529 */
530 public function add_tools_nav_to_taxononmy_pages( $taxonomy = false ) { // phpcs:ignore
531
532 ob_start();
533
534 $categories_css = isset( $_GET['taxonomy'] ) && 'campaign_category' == $_GET['taxonomy'] ? 'nav-tab-active' : ''; // phpcs:ignore
535 $tags_css = isset( $_GET['taxonomy'] ) && 'campaign_tag' == $_GET['taxonomy'] ? 'nav-tab-active' : ''; // phpcs:ignore
536
537 ?>
538
539 <div id="charitable-tools-nav">
540 <h1><?php echo esc_html__( 'Charitable Tools', 'charitable' ); ?></h1>
541 <h2 class="nav-tab-wrapper">
542 <a href="<?php echo esc_url( admin_url( 'edit-tags.php?taxonomy=campaign_category&post_type=campaign' ) ); ?>" class="nav-tab <?php echo esc_attr( $categories_css ); ?>"><?php echo esc_html__( 'Categories', 'charitable' ); ?></a>
543 <a href="<?php echo esc_url( admin_url( 'edit-tags.php?taxonomy=campaign_tag&post_type=campaign' ) ); ?>" class="nav-tab <?php echo esc_attr( $tags_css ); ?>"><?php echo esc_html__( 'Tags', 'charitable' ); ?></a>
544 <a href="<?php echo esc_url( admin_url( 'admin.php?page=charitable-tools&tab=customize' ) ); ?>" class="nav-tab "><?php echo esc_html__( 'Customize', 'charitable' ); ?></a>
545 <a href="<?php echo esc_url( admin_url( 'admin.php?page=charitable-tools&tab=export' ) ); ?>" class="nav-tab"><?php echo esc_html__( 'Export', 'charitable' ); ?></a>
546 <a href="<?php echo esc_url( admin_url( 'admin.php?page=charitable-tools&tab=import' ) ); ?>" class="nav-tab"><?php echo esc_html__( 'Import', 'charitable' ); ?></a>
547 <a href="<?php echo esc_url( admin_url( 'admin.php?page=charitable-tools&tab=system-info' ) ); ?>" class="nav-tab"><?php echo esc_html__( 'System Info', 'charitable' ); ?></a>
548 <a href="<?php echo esc_url( admin_url( 'admin.php?page=charitable-tools&tab=snippets' ) ); ?>" class="nav-tab"><?php echo esc_html__( 'Code Snippets', 'charitable' ); ?></a>
549 <a href="<?php echo esc_url( admin_url( 'admin.php?page=charitable-tools&tab=logs' ) ); ?>" class="nav-tab"><?php echo esc_html__( 'Logs', 'charitable' ); ?></a>
550 <a href="<?php echo esc_url( admin_url( 'admin.php?page=charitable-tools&tab=misc' ) ); ?>" class="nav-tab"><?php echo esc_html__( 'Misc', 'charitable' ); ?></a>
551 </h2>
552 </div>
553
554 <?php
555
556 $content = ob_get_clean();
557
558 echo $content; // phpcs:ignore
559 }
560 }
561
562 endif;
563