PluginProbe
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages / 2.6.2
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages v2.6.2
3.4.1 3.4.0 3.3.9 3.3.8 3.3.7 3.3.6 3.3.5 3.3.4 3.3.3 3.3.2 3.3.1 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 2.3.0 2.3.1 2.3.2 2.3.3 All 194 releases
convertkit / admin / section / class-convertkit-settings-base.php

class-convertkit-settings-base.php in Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages 2.6.2, at admin/section/class-convertkit-settings-base.php

692 lines 16.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * ConvertKit Settings Base class.
4 *
5 * @package ConvertKit
6 * @author ConvertKit
7 */
8
9 /**
10 * ConvertKit Settings class
11 *
12 * @package ConvertKit
13 * @author ConvertKit
14 */
15 abstract class ConvertKit_Settings_Base {
16
17 /**
18 * Section name
19 *
20 * @var string
21 */
22 public $name;
23
24 /**
25 * Section title
26 *
27 * @var string
28 */
29 public $title;
30
31 /**
32 * Section tab text
33 *
34 * @var string
35 */
36 public $tab_text;
37
38 /**
39 * Options table key
40 *
41 * @var string
42 */
43 public $settings_key;
44
45 /**
46 * Holds the settings class for the section.
47 *
48 * @since 1.9.6
49 *
50 * @var false|ConvertKit_Settings|ConvertKit_ContactForm7_Settings|ConvertKit_Wishlist_Settings|ConvertKit_Settings_Restrict_Content|ConvertKit_Settings_Broadcasts|ConvertKit_Forminator_Settings
51 */
52 public $settings;
53
54 /**
55 * Holds whether this settings section is for beta functionality.
56 *
57 * @since 2.1.0
58 *
59 * @var bool
60 */
61 public $is_beta = false;
62
63 /**
64 * Holds whether the save button should be disabled e.g. there are no
65 * settings on screen to save.
66 *
67 * @since 2.4.9
68 *
69 * @var bool
70 */
71 public $save_disabled = false;
72
73 /**
74 * Constructor
75 */
76 public function __construct() {
77
78 // If tab text is not defined, use the title for the tab's text.
79 if ( empty( $this->tab_text ) ) {
80 $this->tab_text = $this->title;
81 }
82
83 // Register the settings section.
84 $this->register_section();
85
86 }
87
88 /**
89 * Helper method to determine if we're viewing the current settings screen.
90 *
91 * @since 2.5.0
92 *
93 * @param string $tab Current settings tab (general|tools|restrict-content|broadcasts).
94 * @return bool
95 */
96 public function on_settings_screen( $tab ) {
97
98 // phpcs:disable WordPress.Security.NonceVerification
99
100 // Bail if we're not on the settings screen.
101 if ( ! array_key_exists( 'page', $_REQUEST ) ) {
102 return false;
103 }
104 if ( sanitize_text_field( $_REQUEST['page'] ) !== '_wp_convertkit_settings' ) {
105 return false;
106 }
107
108 // Define current settings tab.
109 // General screen won't always be loaded with a `tab` parameter.
110 $current_tab = ( array_key_exists( 'tab', $_REQUEST ) ? sanitize_text_field( $_REQUEST['tab'] ) : 'general' );
111
112 // Return whether the request is for the current settings tab.
113 return ( $current_tab === $tab );
114
115 // phpcs:enable
116
117 }
118
119 /**
120 * Register settings section.
121 */
122 public function register_section() {
123
124 add_settings_section(
125 $this->name,
126 $this->title,
127 array( $this, 'print_section_info' ),
128 $this->settings_key
129 );
130
131 $this->register_fields();
132
133 register_setting(
134 $this->settings_key,
135 $this->settings_key,
136 array( $this, 'sanitize_settings' )
137 );
138
139 }
140
141 /**
142 * Register fields for this section
143 */
144 abstract public function register_fields();
145
146 /**
147 * Prints help info for this section
148 */
149 abstract public function print_section_info();
150
151 /**
152 * Returns the URL for the ConvertKit documentation for this setting section.
153 */
154 abstract public function documentation_url();
155
156 /**
157 * Outputs success and/or error notices if required.
158 *
159 * @since 2.0.0
160 */
161 public function maybe_output_notices() {
162
163 // Define notices that might be displayed as a notification.
164 $notices = array();
165
166 /**
167 * Register success and error notices for settings screens.
168 *
169 * @since 2.5.1
170 *
171 * @param array $notices Regsitered success and error notices.
172 * @return array
173 */
174 $notices = apply_filters( 'convertkit_settings_base_register_notices', $notices );
175
176 // Output the verbose error description if supplied (e.g. OAuth).
177 if ( isset( $_REQUEST['error_description'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
178 $this->output_error( sanitize_text_field( $_REQUEST['error_description'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
179 }
180
181 // Output error notification if defined.
182 if ( isset( $_REQUEST['error'] ) && array_key_exists( sanitize_text_field( $_REQUEST['error'] ), $notices ) ) { // phpcs:ignore WordPress.Security.NonceVerification
183 $this->output_error( $notices[ sanitize_text_field( $_REQUEST['error'] ) ] ); // phpcs:ignore WordPress.Security.NonceVerification
184 }
185
186 // Output success notification if defined.
187 if ( isset( $_REQUEST['success'] ) && array_key_exists( sanitize_text_field( $_REQUEST['success'] ), $notices ) ) { // phpcs:ignore WordPress.Security.NonceVerification
188 $this->output_success( $notices[ sanitize_text_field( $_REQUEST['success'] ) ] ); // phpcs:ignore WordPress.Security.NonceVerification
189 }
190
191 }
192
193 /**
194 * Renders the section
195 */
196 public function render() {
197
198 /**
199 * Performs actions prior to rendering the settings form.
200 *
201 * @since 1.9.6
202 */
203 do_action( 'convertkit_settings_base_render_before' );
204
205 $this->render_container_start();
206
207 do_settings_sections( $this->settings_key );
208
209 settings_fields( $this->settings_key );
210
211 if ( ! $this->save_disabled ) {
212 submit_button();
213 }
214
215 $this->render_container_end();
216
217 /**
218 * Performs actions after rendering of the settings form.
219 *
220 * @since 1.9.6
221 */
222 do_action( 'convertkit_settings_base_render_after' );
223
224 }
225
226 /**
227 * Outputs .metabox-holder and .postbox container div elements,
228 * used before beginning a setting screen's output.
229 *
230 * @since 2.0.0
231 */
232 public function render_container_start() {
233
234 ?>
235 <div class="metabox-holder">
236 <div class="postbox <?php echo sanitize_html_class( $this->is_beta ? 'convertkit-beta' : '' ); ?>">
237 <?php
238
239 }
240
241 /**
242 * Outputs closing .metabox-holder and .postbox container div elements,
243 * used after finishing a setting screen's output.
244 *
245 * @since 2.0.0
246 */
247 public function render_container_end() {
248
249 ?>
250 </div>
251 </div>
252 <?php
253
254 }
255
256 /**
257 * Redirects to the settings screen.
258 *
259 * @since 2.2.9
260 */
261 public function redirect() {
262
263 wp_safe_redirect(
264 add_query_arg(
265 array(
266 'page' => '_wp_convertkit_settings',
267 'tab' => $this->name,
268 ),
269 'options-general.php'
270 )
271 );
272 exit();
273
274 }
275
276 /**
277 * Redirects to the settings screen with an error notice key.
278 *
279 * The function maybe_output_notices() will then output the translated error notice
280 * based on the supplied key.
281 *
282 * @since 2.5.1
283 *
284 * @param string $error The error notice key, registered using `convertkit_settings_base_register_notices`.
285 */
286 public function redirect_with_error_notice( $error ) {
287
288 wp_safe_redirect(
289 add_query_arg(
290 array(
291 'page' => '_wp_convertkit_settings',
292 'tab' => $this->name,
293 'error' => $error,
294 ),
295 'options-general.php'
296 )
297 );
298 exit();
299
300 }
301
302 /**
303 * Redirects to the settings screen with the verbose error description.
304 *
305 * @since 2.5.1
306 *
307 * @param string $error_description The error description.
308 */
309 public function redirect_with_error_description( $error_description ) {
310
311 wp_safe_redirect(
312 add_query_arg(
313 array(
314 'page' => '_wp_convertkit_settings',
315 'tab' => $this->name,
316 'error_description' => $error_description,
317 ),
318 'options-general.php'
319 )
320 );
321 exit();
322
323 }
324
325 /**
326 * Redirects to the settings screen with a success notice key.
327 *
328 * The function maybe_output_notices() will then output the translated success notice
329 * based on the supplied key.
330 *
331 * @since 2.5.1
332 *
333 * @param string $success The success notice key, registered using `convertkit_settings_base_register_notices`.
334 */
335 public function redirect_with_success_notice( $success ) {
336
337 wp_safe_redirect(
338 add_query_arg(
339 array(
340 'page' => '_wp_convertkit_settings',
341 'tab' => $this->name,
342 'success' => $success,
343 ),
344 'options-general.php'
345 )
346 );
347 exit();
348
349 }
350
351 /**
352 * Outputs the given success message in an inline notice.
353 *
354 * @since 2.0.0
355 *
356 * @param string $success_message Success Message.
357 */
358 public function output_success( $success_message ) {
359
360 ?>
361 <div class="notice notice-success is-dismissible">
362 <p>
363 <?php echo esc_attr( $success_message ); ?>
364 </p>
365 </div>
366 <?php
367
368 }
369
370 /**
371 * Outputs the given error message in an inline notice.
372 *
373 * @since 1.9.6
374 *
375 * @param string $error_message Error Message.
376 */
377 public function output_error( $error_message ) {
378
379 ?>
380 <div class="notice notice-error is-dismissible">
381 <p>
382 <?php echo esc_attr( $error_message ); ?>
383 </p>
384 </div>
385 <?php
386
387 }
388
389 /**
390 * Returns a masked value.
391 *
392 * @since 1.9.6
393 *
394 * @param string $value Value.
395 * @param bool|string $description Description.
396 * @return string Masked Value
397 */
398 public function get_masked_value( $value, $description = false ) {
399
400 $html = sprintf(
401 '<code>%s</code>',
402 str_repeat( '*', strlen( $value ) - 4 ) . substr( $value, - 4 )
403 );
404
405 if ( $description ) {
406 $html .= $this->get_description( $description );
407 }
408
409 return $html;
410
411 }
412
413 /**
414 * Returns a text field.
415 *
416 * @since 1.9.6
417 *
418 * @param string $name Name.
419 * @param string $value Value.
420 * @param bool|string|array $description Description (false|string|array).
421 * @param bool|array $css_classes CSS Classes (false|array).
422 * @return string HTML Field
423 */
424 public function get_text_field( $name, $value = '', $description = false, $css_classes = false ) {
425
426 $html = sprintf(
427 '<input type="text" class="%s" id="%s" name="%s[%s]" value="%s" />',
428 ( is_array( $css_classes ) ? implode( ' ', $css_classes ) : 'regular-text' ),
429 $name,
430 $this->settings_key,
431 $name,
432 $value
433 );
434
435 return $html . $this->get_description( $description );
436
437 }
438
439 /**
440 * Returns a number field.
441 *
442 * @since 2.6.1
443 *
444 * @param string $name Name.
445 * @param string $value Value.
446 * @param int $min `min` attribute value.
447 * @param int $max `max` attribute value.
448 * @param int $step `step` attribute value.
449 * @param bool|string|array $description Description (false|string|array).
450 * @param bool|array $css_classes CSS Classes (false|array).
451 * @return string HTML Field
452 */
453 public function get_number_field( $name, $value = '', $min = 0, $max = 9999, $step = 1, $description = false, $css_classes = false ) {
454
455 $html = sprintf(
456 '<input type="number" class="%s" id="%s" name="%s[%s]" value="%s" min="%s" max="%s" step="%s" />',
457 ( is_array( $css_classes ) ? implode( ' ', $css_classes ) : 'small-text' ),
458 $name,
459 $this->settings_key,
460 $name,
461 $value,
462 $min,
463 $max,
464 $step
465 );
466
467 return $html . $this->get_description( $description );
468
469 }
470
471 /**
472 * Returns a textarea field.
473 *
474 * @since 2.3.5
475 *
476 * @param string $name Name.
477 * @param string $value Value.
478 * @param bool|string|array $description Description (false|string|array).
479 * @param bool|array $css_classes CSS Classes (false|array).
480 * @return string HTML Field
481 */
482 public function get_textarea_field( $name, $value = '', $description = false, $css_classes = false ) {
483
484 $html = sprintf(
485 '<textarea class="%s" id="%s" name="%s[%s]">%s</textarea>',
486 ( is_array( $css_classes ) ? implode( ' ', $css_classes ) : 'regular-text' ),
487 $name,
488 $this->settings_key,
489 $name,
490 $value
491 );
492
493 return $html . $this->get_description( $description );
494
495 }
496
497 /**
498 * Returns a date field.
499 *
500 * @since 2.2.8
501 *
502 * @param string $name Name.
503 * @param string $value Value.
504 * @param bool|string|array $description Description (false|string|array).
505 * @param bool|array $css_classes CSS Classes (false|array).
506 * @return string HTML Field
507 */
508 public function get_date_field( $name, $value = '', $description = false, $css_classes = false ) {
509
510 $html = sprintf(
511 '<input type="date" class="%s" id="%s" name="%s[%s]" value="%s" />',
512 ( is_array( $css_classes ) ? implode( ' ', $css_classes ) : 'regular-text' ),
513 $name,
514 $this->settings_key,
515 $name,
516 $value
517 );
518
519 return $html . $this->get_description( $description );
520
521 }
522
523 /**
524 * Returns a select dropdown field.
525 *
526 * @since 1.9.6
527 *
528 * @param string $name Name.
529 * @param string $value Value.
530 * @param array $options Options / Choices.
531 * @param bool|string $description Description.
532 * @param bool|array $css_classes <select> CSS class(es).
533 * @param bool|array $attributes <select> attributes.
534 * @return string HTML Select Field
535 */
536 public function get_select_field( $name, $value = '', $options = array(), $description = false, $css_classes = false, $attributes = false ) {
537
538 // Build opening <select> tag.
539 $html = sprintf(
540 '<select id="%s" name="%s[%s]" class="%s" size="1" %s>',
541 $this->settings_key . '_' . $name,
542 $this->settings_key,
543 $name,
544 ( is_array( $css_classes ) ? implode( ' ', $css_classes ) : '' ),
545 ( is_array( $attributes ) ? $this->array_to_attributes( $attributes ) : '' )
546 );
547
548 // Build <option> tags.
549 foreach ( $options as $option => $label ) {
550 $html .= sprintf(
551 '<option value="%s"%s>%s</option>',
552 $option,
553 selected( $value, $option, false ),
554 $label
555 );
556 }
557
558 // Close <select>.
559 $html .= '</select>';
560
561 // If no description exists, just return the select field.
562 if ( empty( $description ) ) {
563 return $html;
564 }
565
566 // Return select field with description appended to it.
567 return $html . $this->get_description( $description );
568
569 }
570
571 /**
572 * Returns a checkbox field.
573 *
574 * @since 1.9.6
575 *
576 * @param string $name Name.
577 * @param string $value Value.
578 * @param bool $checked Should checkbox be checked/ticked.
579 * @param bool|string $label Label.
580 * @param bool|string|array $description Description.
581 * @param bool|array $css_classes CSS class(es).
582 * @return string HTML Checkbox
583 */
584 public function get_checkbox_field( $name, $value, $checked = false, $label = '', $description = false, $css_classes = false ) {
585
586 $html = '';
587
588 if ( $label ) {
589 $html .= sprintf(
590 '<label for="%s">',
591 $name
592 );
593 }
594
595 $html .= sprintf(
596 '<input type="checkbox" id="%s" name="%s[%s]" class="%s" value="%s" %s />',
597 $name,
598 $this->settings_key,
599 $name,
600 ( is_array( $css_classes ) ? implode( ' ', $css_classes ) : '' ),
601 $value,
602 ( $checked ? ' checked' : '' )
603 );
604
605 if ( $label ) {
606 $html .= sprintf(
607 '%s</label>',
608 $label
609 );
610 }
611
612 // If no description exists, just return the field.
613 if ( empty( $description ) ) {
614 return $html;
615 }
616
617 // Return field with description appended to it.
618 return $html . $this->get_description( $description );
619
620 }
621
622 /**
623 * Returns the given text wrapped in a paragraph with the description class.
624 *
625 * @since 1.9.6
626 *
627 * @param bool|string|array $description Description.
628 * @return string HTML Description
629 */
630 public function get_description( $description ) {
631
632 // Return blank string if no description specified.
633 if ( ! $description ) {
634 return '';
635 }
636
637 // Return description in paragraph if a string.
638 if ( ! is_array( $description ) ) {
639 return '<p class="description">' . $description . '</p>';
640 }
641
642 // Return description lines in a paragraph, using breaklines for each description entry in the array.
643 return '<p class="description">' . implode( '<br />', $description ) . '</p>';
644
645 }
646
647 /**
648 * Converts the given key/value array pairs into a HTML attribute="value" string.
649 *
650 * @since 1.9.8.5
651 *
652 * @param array $attributes_array Attributes.
653 * @return string HTML attributes string
654 */
655 private function array_to_attributes( $attributes_array ) {
656
657 $attributes = '';
658 foreach ( $attributes_array as $key => $value ) {
659 $attributes .= esc_attr( $key ) . '="' . esc_attr( $value ) . '" ';
660 }
661
662 return trim( $attributes );
663
664 }
665
666 /**
667 * Sanitizes the settings prior to being saved.
668 *
669 * @since 1.9.6
670 *
671 * @param array $settings Submitted Settings Fields.
672 * @return array Sanitized Settings with Defaults
673 */
674 public function sanitize_settings( $settings ) {
675
676 // Merge settings with defaults.
677 $updated_settings = wp_parse_args( $settings, $this->settings->get_defaults() );
678
679 /**
680 * Performs actions prior to settings being saved.
681 *
682 * @since 2.2.8
683 */
684 do_action( 'convertkit_settings_base_sanitize_settings', $this->name, $updated_settings );
685
686 // Return settings to be saved.
687 return $updated_settings;
688
689 }
690
691 }
692