PluginProbe
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages / 3.1.8
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages v3.1.8
3.4.4 3.4.3 3.4.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 All 197 releases
convertkit / admin / section / class-convertkit-admin-section-general.php

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

1,098 lines 31.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * ConvertKit Settings General class.
4 *
5 * @package ConvertKit
6 * @author ConvertKit
7 */
8
9 /**
10 * Registers General Settings that can be edited at Settings > Kit > General.
11 *
12 * @package ConvertKit
13 * @author ConvertKit
14 */
15 class ConvertKit_Admin_Section_General extends ConvertKit_Admin_Section_Base {
16
17 /**
18 * Holds the API instance.
19 *
20 * @since 1.9.6
21 *
22 * @var ConvertKit_API_V4
23 */
24 private $api;
25
26 /**
27 * Holds the ConvertKit Account Name.
28 *
29 * @since 1.9.6
30 *
31 * @var bool|WP_Error|array
32 */
33 private $account = false;
34
35 /**
36 * Holds the ConvertKit Forms Resource.
37 *
38 * @since 1.9.6
39 *
40 * @var bool|ConvertKit_Resource_Forms
41 */
42 private $forms = false;
43
44 /**
45 * Constructor.
46 */
47 public function __construct() {
48
49 // Define the class that reads/writes settings.
50 $this->settings = new ConvertKit_Settings();
51
52 // Define the settings key.
53 $this->settings_key = $this->settings::SETTINGS_NAME;
54
55 // Define the programmatic name, Title and Tab Text.
56 $this->name = 'general';
57 $this->title = __( 'General Settings', 'convertkit' );
58 $this->tab_text = __( 'General', 'convertkit' );
59
60 // Define settings sections.
61 $this->settings_sections = array(
62 'general' => array(
63 'title' => $this->title,
64 'callback' => array( $this, 'print_section_info' ),
65 'wrap' => true,
66 ),
67 'site-wide' => array(
68 'title' => __( 'Non-inline Forms', 'convertkit' ),
69 'callback' => array( $this, 'print_section_info_site_wide' ),
70 'wrap' => true,
71 ),
72 'recaptcha' => array(
73 'title' => __( 'reCAPTCHA', 'convertkit' ),
74 'callback' => array( $this, 'print_section_info_recaptcha' ),
75 'wrap' => true,
76 ),
77 'advanced' => array(
78 'title' => __( 'Advanced', 'convertkit' ),
79 'callback' => array( $this, 'print_section_info_advanced' ),
80 'wrap' => true,
81 ),
82 );
83
84 $this->maybe_disconnect();
85
86 // Register and maybe output notices for this settings screen, and the Intercom messenger.
87 if ( $this->on_settings_screen( $this->name ) ) {
88 add_filter( 'convertkit_settings_base_register_notices', array( $this, 'register_notices' ) );
89 add_action( 'convertkit_settings_base_render_before', array( $this, 'maybe_output_notices' ) );
90 }
91
92 // Enqueue scripts and CSS.
93 add_action( 'convertkit_admin_settings_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
94 add_action( 'convertkit_admin_settings_enqueue_styles', array( $this, 'enqueue_styles' ) );
95
96 parent::__construct();
97
98 $this->check_credentials();
99
100 }
101
102 /**
103 * Registers success and error notices for the General screen, to be displayed
104 * depending on the action.
105 *
106 * @since 2.5.1
107 *
108 * @param array $notices Regsitered success and error notices.
109 * @return array
110 */
111 public function register_notices( $notices ) {
112
113 return array_merge(
114 $notices,
115 array(
116 'oauth2_success' => __( 'Successfully authorized with Kit.', 'convertkit' ),
117 )
118 );
119
120 }
121
122 /**
123 * Test the access token, if it exists.
124 * If the access token has been revoked or is invalid, remove it from the settings now.
125 *
126 * @since 2.5.0
127 */
128 private function check_credentials() {
129
130 // Bail if we're not on the settings screen.
131 if ( ! $this->on_settings_screen( $this->name ) ) {
132 return;
133 }
134
135 // Bail if no access and refresh token exist.
136 if ( ! $this->settings->has_access_and_refresh_token() ) {
137 // Redirect to General screen, which will now show the ConvertKit_Admin_Section_OAuth screen, because
138 // the Plugin has no access token.
139 wp_safe_redirect(
140 add_query_arg(
141 array(
142 'page' => $this->settings_key,
143 ),
144 'options-general.php'
145 )
146 );
147 exit();
148 }
149
150 // Initialize the API.
151 $this->api = new ConvertKit_API_V4(
152 CONVERTKIT_OAUTH_CLIENT_ID,
153 CONVERTKIT_OAUTH_CLIENT_REDIRECT_URI,
154 $this->settings->get_access_token(),
155 $this->settings->get_refresh_token(),
156 $this->settings->debug_enabled(),
157 'settings'
158 );
159
160 // Get Account Details, which we'll use in account_name_callback(), but also lets us test
161 // whether the API credentials are valid.
162 $this->account = $this->api->get_account();
163
164 // If the request succeeded, no need to perform further actions.
165 if ( ! is_wp_error( $this->account ) ) {
166 return;
167 }
168
169 // Depending on the error code, display an error notice in the settings screen until the user
170 // fixes the problem.
171 $this->output_error( $this->account->get_error_message() );
172
173 }
174
175 /**
176 * Deletes the OAuth Access Token, Refresh Token and Expiry from the Plugin's settings, if the user
177 * clicked the Disconnect button.
178 *
179 * @since 2.5.0
180 */
181 private function maybe_disconnect() {
182
183 // Bail if we're not on the settings screen.
184 if ( ! $this->on_settings_screen( $this->name ) ) {
185 return;
186 }
187
188 // Bail if nonce verification fails.
189 if ( ! isset( $_REQUEST['_convertkit_settings_oauth_disconnect'] ) ) {
190 return;
191 }
192 if ( ! wp_verify_nonce( sanitize_key( $_REQUEST['_convertkit_settings_oauth_disconnect'] ), 'convertkit-oauth-disconnect' ) ) {
193 return;
194 }
195
196 // Delete Access Token.
197 $settings = new ConvertKit_Settings();
198 $settings->delete_credentials();
199
200 // Delete cached resources.
201 $creator_network = new ConvertKit_Resource_Creator_Network_Recommendations();
202 $custom_fields = new ConvertKit_Resource_Custom_Fields();
203 $forms = new ConvertKit_Resource_Forms();
204 $landing_pages = new ConvertKit_Resource_Landing_Pages();
205 $posts = new ConvertKit_Resource_Posts();
206 $products = new ConvertKit_Resource_Products();
207 $sequences = new ConvertKit_Resource_Sequences();
208 $tags = new ConvertKit_Resource_Tags();
209 $creator_network->delete();
210 $custom_fields->delete();
211 $forms->delete();
212 $landing_pages->delete();
213 $posts->delete();
214 $products->delete();
215 $sequences->delete();
216 $tags->delete();
217
218 // Redirect to General screen, which will now show the ConvertKit_Settings_OAuth screen, because
219 // the Plugin has no access token.
220 wp_safe_redirect(
221 add_query_arg(
222 array(
223 'page' => $this->settings_key,
224 ),
225 'options-general.php'
226 )
227 );
228 exit();
229
230 }
231
232 /**
233 * Enqueues scripts for the Settings > General screen.
234 *
235 * @since 2.2.4
236 *
237 * @param string $section Settings section / tab (general|tools|restrict-content).
238 */
239 public function enqueue_scripts( $section ) {
240
241 // Bail if we're not on the general section.
242 if ( $section !== $this->name ) {
243 return;
244 }
245
246 // Enqueue Select2 JS.
247 convertkit_select2_enqueue_scripts();
248
249 // Enqueue JS.
250 wp_enqueue_script( 'convertkit-admin-preview-output', CONVERTKIT_PLUGIN_URL . 'resources/backend/js/preview-output.js', array( 'jquery' ), CONVERTKIT_PLUGIN_VERSION, true );
251 wp_enqueue_script( 'convertkit-admin-settings-conditional-display', CONVERTKIT_PLUGIN_URL . 'resources/backend/js/settings-conditional-display.js', array( 'jquery' ), CONVERTKIT_PLUGIN_VERSION, true );
252
253 }
254
255 /**
256 * Enqueues styles for the Settings > General screen.
257 *
258 * @since 2.2.4
259 *
260 * @param string $section Settings section / tab (general|tools|restrict-content).
261 */
262 public function enqueue_styles( $section ) {
263
264 // Bail if we're not on the general section.
265 if ( $section !== $this->name ) {
266 return;
267 }
268
269 // Enqueue Select2 CSS.
270 convertkit_select2_enqueue_styles();
271
272 }
273
274 /**
275 * Registers settings fields for this section.
276 */
277 public function register_fields() {
278
279 // Initialize resource classes.
280 $this->maybe_initialize_and_refresh_resources();
281
282 add_settings_field(
283 'account_name',
284 __( 'Account Name', 'convertkit' ),
285 array( $this, 'account_name_callback' ),
286 $this->settings_key,
287 $this->name
288 );
289
290 // Initialize resource classes and perform a refresh if this hasn't yet been done.
291 foreach ( convertkit_get_supported_post_types() as $supported_post_type ) {
292 // Get Post Type's Label.
293 $post_type = get_post_type_object( $supported_post_type );
294
295 // Skip if the Post Type doesn't exist.
296 if ( ! $post_type ) {
297 continue;
298 }
299
300 // Add Settings Fields.
301 add_settings_field(
302 $supported_post_type . '_form',
303 sprintf(
304 /* translators: Post Type Name, plural */
305 __( 'Default Form (%s)', 'convertkit' ),
306 $post_type->label
307 ),
308 array( $this, 'default_form_callback' ),
309 $this->settings_key,
310 $this->name,
311 array(
312 'label_for' => '_wp_convertkit_settings_' . $supported_post_type . '_form',
313 'post_type' => $supported_post_type,
314 'post_type_object' => $post_type,
315 )
316 );
317
318 if ( $this->forms->exist() ) {
319 add_settings_field(
320 $supported_post_type . '_form_position',
321 sprintf(
322 /* translators: Post Type Name, plural */
323 __( 'Form Position (%s)', 'convertkit' ),
324 $post_type->label
325 ),
326 array( $this, 'default_form_position_callback' ),
327 $this->settings_key,
328 $this->name,
329 array(
330 'label_for' => '_wp_convertkit_settings_' . $supported_post_type . '_form_position',
331 'post_type' => $supported_post_type,
332 'post_type_object' => $post_type,
333 )
334 );
335
336 add_settings_field(
337 $supported_post_type . '_form_position_element',
338 '',
339 array( $this, 'default_form_position_element_callback' ),
340 $this->settings_key,
341 $this->name,
342 array(
343 'label_for' => '_wp_convertkit_settings_' . $supported_post_type . '_form_position_element',
344 'post_type' => $supported_post_type,
345 'post_type_object' => $post_type,
346 )
347 );
348 }
349 }
350
351 // Site Wide.
352 add_settings_field(
353 'non_inline_form',
354 __( 'Default Forms (Site Wide)', 'convertkit' ),
355 array( $this, 'non_inline_form_callback' ),
356 $this->settings_key,
357 $this->name . '-site-wide',
358 array(
359 'label_for' => 'non_inline_form',
360 )
361 );
362
363 add_settings_field(
364 'non_inline_form_honor_none_setting',
365 __( 'Behavior', 'convertkit' ),
366 array( $this, 'non_inline_form_honor_none_setting_callback' ),
367 $this->settings_key,
368 $this->name . '-site-wide',
369 array(
370 'label_for' => 'non_inline_form_honor_none_setting',
371 )
372 );
373
374 // Non-inline Form Limit per Session.
375 add_settings_field(
376 'non_inline_form_limit_per_session',
377 __( 'Limit Display', 'convertkit' ),
378 array( $this, 'non_inline_form_limit_per_session_callback' ),
379 $this->settings_key,
380 $this->name . '-site-wide',
381 array(
382 'label_for' => 'non_inline_form_limit_per_session',
383 )
384 );
385
386 // reCAPTCHA.
387 add_settings_field(
388 'recaptcha_site_key',
389 __( 'reCAPTCHA: Site Key', 'convertkit' ),
390 array( $this, 'recaptcha_site_key_callback' ),
391 $this->settings_key,
392 $this->name . '-recaptcha',
393 array(
394 'label_for' => 'recaptcha_site_key',
395 'description' => array(
396 __( 'Enter your Google reCAPTCHA v3 Site Key. When specified, this will be used to reduce spam signups.', 'convertkit' ),
397 ),
398 )
399 );
400 add_settings_field(
401 'recaptcha_secret_key',
402 __( 'reCAPTCHA: Secret Key', 'convertkit' ),
403 array( $this, 'recaptcha_secret_key_callback' ),
404 $this->settings_key,
405 $this->name . '-recaptcha',
406 array(
407 'label_for' => 'recaptcha_secret_key',
408 'description' => array(
409 __( 'Enter your Google reCAPTCHA v3 Secret Key. When specified, this will be used to reduce spam signups.', 'convertkit' ),
410 ),
411 )
412 );
413 add_settings_field(
414 'recaptcha_minimum_score',
415 __( 'reCAPTCHA: Minimum Score', 'convertkit' ),
416 array( $this, 'recaptcha_minimum_score_callback' ),
417 $this->settings_key,
418 $this->name . '-recaptcha',
419 array(
420 'label_for' => 'recaptcha_minimum_score',
421 'min' => 0,
422 'max' => 1,
423 'step' => 0.01,
424 'description' => array(
425 __( 'Enter the minimum threshold for a subscriber to pass Google reCAPTCHA. A higher number will reduce spam signups (1.0 is very likely a good interaction, 0.0 is very likely a bot).', 'convertkit' ),
426 ),
427 )
428 );
429
430 // Advanced.
431 add_settings_field(
432 'debug',
433 __( 'Debug', 'convertkit' ),
434 array( $this, 'debug_callback' ),
435 $this->settings_key,
436 $this->name . '-advanced',
437 array(
438 'label_for' => 'debug',
439 )
440 );
441
442 add_settings_field(
443 'no_scripts',
444 __( 'Disable JavaScript', 'convertkit' ),
445 array( $this, 'no_scripts_callback' ),
446 $this->settings_key,
447 $this->name . '-advanced',
448 array(
449 'label_for' => 'no_scripts',
450 )
451 );
452
453 add_settings_field(
454 'no_css',
455 __( 'Disable CSS', 'convertkit' ),
456 array( $this, 'no_css_callback' ),
457 $this->settings_key,
458 $this->name . '-advanced',
459 array(
460 'label_for' => 'no_css',
461 )
462 );
463
464 add_settings_field(
465 'usage_tracking',
466 __( 'Usage Tracking', 'convertkit' ),
467 array( $this, 'usage_tracking_callback' ),
468 $this->settings_key,
469 $this->name . '-advanced',
470 array(
471 'label_for' => 'usage_tracking',
472 )
473 );
474
475 }
476
477 /**
478 * Prints help info for this section
479 */
480 public function print_section_info() {
481
482 ?>
483 <p><?php esc_html_e( 'Forms can be embedded before and/or after (or following number of elements) on every post or page (in single view only) across your site by using the settings below.', 'convertkit' ); ?>
484 <p><?php esc_html_e( 'You can also configure non-inline forms to display site wide under the "Non-inline Forms" section below.', 'convertkit' ); ?></p>
485 <p><?php esc_html_e( 'These default form settings can be overridden using the Kit meta box on a page or post\'s edit screen. For site wide non-inline forms to respect when a post/page has forms disabled, enable the "Behavior" option in the "Non-inline Forms" section below.', 'convertkit' ); ?></p>
486 <p>
487 <?php
488 printf(
489 /* translators: [convertkit] shortcode, wrapped in <code> tags */
490 esc_html__( 'The default form can be inserted into the middle of post or page content by using either the %s shortcode or block.', 'convertkit' ),
491 '<code>[convertkit]</code>'
492 );
493 ?>
494 </p>
495 <?php
496
497 }
498
499 /**
500 * Prints help info for the site wide section of the settings screen.
501 *
502 * @since 2.7.3
503 */
504 public function print_section_info_site_wide() {
505
506 ?>
507 <p class="description"><?php esc_html_e( 'Defines non-inline forms to display site wide, and if these forms should display on Pages / Posts that have the Kit Form setting = None.', 'convertkit' ); ?></p>
508 <?php
509
510 }
511
512 /**
513 * Prints help info for the recaptcha section of the settings screen.
514 *
515 * @since 3.0.0
516 */
517 public function print_section_info_recaptcha() {
518 ?>
519 <p class="description"><?php esc_html_e( 'Configure reCAPTCHA to protect the Member Content signup form and Form Builder block from spam and abuse.', 'convertkit' ); ?></p>
520 <?php
521 }
522
523 /**
524 * Prints help info for the advanced section of the settings screen.
525 *
526 * @since 2.7.1
527 */
528 public function print_section_info_advanced() {
529
530 ?>
531 <p class="description"><?php esc_html_e( 'Defines advanced configuration settings, usually when working with support or needing to disable JS or CSS.', 'convertkit' ); ?></p>
532 <?php
533
534 }
535
536 /**
537 * Returns the URL for the ConvertKit documentation for this setting section.
538 *
539 * @since 2.0.8
540 *
541 * @return string Documentation URL.
542 */
543 public function documentation_url() {
544
545 return 'https://help.kit.com/en/articles/2502591-how-to-set-up-the-kit-plugin-on-your-wordpress-website';
546
547 }
548
549 /**
550 * Outputs the Account Name
551 *
552 * @since 1.9.6
553 */
554 public function account_name_callback() {
555
556 // Output Account Name.
557 // If account is an error, check_credentials() will output an error above the settings section.
558 $html = sprintf(
559 '<p>%s</p>',
560 ! is_wp_error( $this->account ) && isset( $this->account['account']['name'] ) ? esc_attr( $this->account['account']['name'] ) : esc_html__( '(Not specified)', 'convertkit' )
561 );
562
563 // Display an option to disconnect.
564 $html .= sprintf(
565 '<p><a href="%1$s" class="button button-secondary">%2$s</a></p>',
566 esc_url(
567 add_query_arg(
568 array(
569 'page' => '_wp_convertkit_settings',
570 '_convertkit_settings_oauth_disconnect' => wp_create_nonce( 'convertkit-oauth-disconnect' ),
571 ),
572 'options-general.php'
573 )
574 ),
575 esc_html__( 'Disconnect', 'convertkit' )
576 );
577
578 echo wp_kses( $html, convertkit_kses_allowed_html() );
579
580 }
581
582 /**
583 * Initialize resource classes and perform a and refresh of resources,
584 * if initialization has not yet taken place.
585 *
586 * @since 2.5.9
587 */
588 public function maybe_initialize_and_refresh_resources() {
589
590 // If the Forms resource class is initialized, this has already been done.
591 if ( $this->forms !== false ) {
592 return;
593 }
594
595 // Initialize forms resource class.
596 $this->forms = new ConvertKit_Resource_Forms( 'settings' );
597
598 // Don't refresh resources if we're not on the settings screen, as
599 // it's a resource intense process that can take several seconds.
600 // We don't want to block other parts of the admin UI.
601 if ( ! $this->on_settings_screen( $this->name ) ) {
602 return;
603 }
604
605 // Refresh Forms.
606 $result = $this->forms->refresh();
607
608 // Bail if an error occured.
609 if ( is_wp_error( $result ) ) {
610 return;
611 }
612
613 // Also refresh Landing Pages, Tags and Posts. Whilst not displayed in the Plugin Settings, this ensures up to date
614 // lists are stored for when editing e.g. Pages.
615 $landing_pages = new ConvertKit_Resource_Landing_Pages( 'settings' );
616 $result = $landing_pages->refresh();
617
618 // Bail if an error occured.
619 if ( is_wp_error( $result ) ) {
620 return;
621 }
622
623 remove_all_actions( 'convertkit_resource_refreshed_posts' );
624 $posts = new ConvertKit_Resource_Posts( 'settings' );
625 $result = $posts->refresh();
626
627 // Bail if an error occured.
628 if ( is_wp_error( $result ) ) {
629 return;
630 }
631
632 $products = new ConvertKit_Resource_Products( 'settings' );
633 $result = $products->refresh();
634
635 // Bail if an error occured.
636 if ( is_wp_error( $result ) ) {
637 return;
638 }
639
640 $sequences = new ConvertKit_Resource_Sequences( 'settings' );
641 $result = $sequences->refresh();
642
643 // Bail if an error occured.
644 if ( is_wp_error( $result ) ) {
645 return;
646 }
647
648 $tags = new ConvertKit_Resource_Tags( 'settings' );
649 $result = $tags->refresh();
650
651 // Bail if an error occured.
652 if ( is_wp_error( $result ) ) {
653 return;
654 }
655
656 }
657
658 /**
659 * Renders the input for the Default Form setting for the given Post Type.
660 *
661 * @since 1.9.6
662 *
663 * @param array $args Field arguments.
664 */
665 public function default_form_callback( $args ) {
666
667 // Bail if no Forms exist.
668 if ( ! $this->forms->exist() ) {
669 esc_html_e( 'No Forms exist in Kit.', 'convertkit' );
670 echo '<br /><a href="' . esc_url( convertkit_get_new_form_url() ) . '" target="_blank">' . esc_html__( 'Click here to create your first form', 'convertkit' ) . '</a>';
671 return;
672 }
673
674 // Build description with preview link.
675 $description = false;
676 $preview_url = WP_ConvertKit()->get_class( 'preview_output' )->get_preview_form_url( $args['post_type'] );
677 if ( $preview_url ) {
678 // Include a preview link in the description.
679 $description = sprintf(
680 '%s %s %s',
681 sprintf(
682 /* translators: Post Type name, plural */
683 esc_html__( 'Select a form above to automatically output below all %s.', 'convertkit' ),
684 $args['post_type_object']->label
685 ),
686 '<a href="' . esc_url( $preview_url ) . '" id="convertkit-preview-form-' . esc_attr( $args['post_type'] ) . '" target="_blank">' . esc_html__( 'Click here', 'convertkit' ) . '</a>',
687 esc_html__( 'to preview how this will display.', 'convertkit' )
688 );
689 } else {
690 // Just output the field's description.
691 $description = sprintf(
692 /* translators: Post Type name, plural */
693 esc_html__( 'Select a form above to automatically output below all %s.', 'convertkit' ),
694 $args['post_type_object']->label
695 );
696 }
697
698 // Output field.
699 echo '<div class="convertkit-select2-container">';
700 $this->forms->output_select_field_all(
701 $this->settings_key . '[' . $args['post_type'] . '_form]',
702 $this->settings_key . '_' . $args['post_type'] . '_form',
703 array(
704 'convertkit-select2',
705 'convertkit-preview-output-link',
706 ),
707 $this->settings->get_default_form( $args['post_type'] ),
708 array(
709 'default' => esc_html__( 'None', 'convertkit' ),
710 ),
711 array(
712 'data-target' => '#convertkit-preview-form-' . esc_attr( $args['post_type'] ),
713 'data-link' => esc_attr( $preview_url ) . '&convertkit_form_id=',
714 ),
715 $description
716 );
717 echo '</div>';
718
719 }
720
721 /**
722 * Renders the input for the Default Form Position setting for the given Post Type.
723 *
724 * @since 2.5.8
725 *
726 * @param array $args Field arguments.
727 */
728 public function default_form_position_callback( $args ) {
729
730 $this->output_select_field(
731 $args['post_type'] . '_form_position',
732 esc_attr( $this->settings->get_default_form_position( $args['post_type'] ) ),
733 array(
734 'before_content' => sprintf(
735 /* translators: Post type singular name */
736 esc_attr__( 'Before %s content', 'convertkit' ),
737 esc_attr( $args['post_type_object']->labels->singular_name )
738 ),
739 'after_content' => sprintf(
740 /* translators: Post type singular name */
741 esc_attr__( 'After %s content', 'convertkit' ),
742 esc_attr( $args['post_type_object']->labels->singular_name )
743 ),
744 'before_after_content' => sprintf(
745 /* translators: Post type singular name */
746 esc_attr__( 'Before and after %s content', 'convertkit' ),
747 esc_attr( $args['post_type_object']->labels->singular_name )
748 ),
749 'after_element' => esc_html__( 'After element', 'convertkit' ),
750 ),
751 sprintf(
752 /* translators: Post Type name, plural */
753 esc_html__( 'Where forms should display relative to the %s content', 'convertkit' ),
754 esc_html( $args['post_type_object']->labels->singular_name )
755 ),
756 array( 'convertkit-conditional-display' ),
757 array(
758 'data-conditional-value' => 'after_element',
759 'data-conditional-element' => esc_attr( $args['post_type'] ) . '_form_position_element_index',
760 )
761 );
762
763 }
764
765 /**
766 * Renders the input for the Default Form Position Index setting for the given Post Type.
767 *
768 * @since 2.6.1
769 *
770 * @param array $args Field arguments.
771 */
772 public function default_form_position_element_callback( $args ) {
773
774 $this->output_number_field(
775 $args['post_type'] . '_form_position_element_index',
776 esc_attr( (string) $this->settings->get_default_form_position_element_index( $args['post_type'] ) ),
777 1,
778 999,
779 1,
780 false,
781 array( 'after_element' )
782 );
783
784 $this->output_select_field(
785 $args['post_type'] . '_form_position_element',
786 esc_attr( $this->settings->get_default_form_position_element( $args['post_type'] ) ),
787 array(
788 'p' => esc_html__( 'Paragraphs', 'convertkit' ),
789 'h2' => esc_html__( 'Headings <h2>', 'convertkit' ),
790 'h3' => esc_html__( 'Headings <h3>', 'convertkit' ),
791 'h4' => esc_html__( 'Headings <h4>', 'convertkit' ),
792 'h5' => esc_html__( 'Headings <h5>', 'convertkit' ),
793 'h6' => esc_html__( 'Headings <h6>', 'convertkit' ),
794 'img' => esc_html__( 'Images', 'convertkit' ),
795 ),
796 esc_html__( 'The number of elements before outputting the form.', 'convertkit' ),
797 array( 'after_element' )
798 );
799
800 }
801
802 /**
803 * Renders the input for the Non-inline Form setting.
804 *
805 * @since 2.2.3
806 *
807 * @param array $args Field arguments.
808 */
809 public function non_inline_form_callback( $args ) {
810
811 // Bail if no non-inline Forms exist.
812 if ( ! $this->forms->non_inline_exist() ) {
813 esc_html_e( 'No non-inline Forms exist in Kit.', 'convertkit' );
814 echo '<br /><a href="' . esc_url( convertkit_get_new_form_url() ) . '" target="_blank">' . esc_html__( 'Click here to create your first modal, slide in or sticky bar form', 'convertkit' ) . '</a>';
815 return;
816 }
817
818 // Build description with preview link.
819 $preview_url = WP_ConvertKit()->get_class( 'preview_output' )->get_preview_form_home_url();
820 $description = sprintf(
821 '%s %s %s',
822 esc_html__( 'Automatically display one or more modal, slide-in, or sticky bar forms across your site. This setting is overridden if a default non-inline form is set above, a specific non-inline form or "None" option is chosen for a post/page, or a non-inline form is specified in a block/shortcode.', 'convertkit' ),
823 '<a href="' . esc_url( $preview_url ) . '" id="convertkit-preview-non-inline-form" target="_blank">' . esc_html__( 'Click here', 'convertkit' ) . '</a>',
824 esc_html__( 'to preview how this will display.', 'convertkit' )
825 );
826
827 // Output field.
828 echo '<div class="convertkit-select2-container">';
829 $this->forms->output_select_field_non_inline(
830 $this->settings_key . '[non_inline_form]',
831 $this->settings_key . '_non_inline_form',
832 array(
833 'convertkit-select2',
834 'convertkit-preview-output-link',
835 ),
836 $this->settings->get_non_inline_form(),
837 false,
838 array(
839 'data-target' => '#convertkit-preview-non-inline-form',
840 'data-link' => esc_attr( $preview_url ) . '&convertkit_form_id=',
841 ),
842 $description
843 );
844 echo '</div>';
845
846 }
847
848 /**
849 * Renders the input for the Non-inline Form override setting.
850 *
851 * @since 2.7.3
852 */
853 public function non_inline_form_honor_none_setting_callback() {
854
855 // Output field.
856 $this->output_checkbox_field(
857 'non_inline_form_honor_none_setting',
858 'on',
859 $this->settings->non_inline_form_honor_none_setting(),
860 esc_html__( 'If checked, do not display the site wide form(s) above on Pages / Posts that have their Kit Form setting = None.', 'convertkit' )
861 );
862
863 }
864
865
866 /**
867 * Renders the input for the Modal Form Limit per Session setting.
868 *
869 * @since 3.0.0
870 *
871 * @param array $args Setting field arguments (name,description).
872 */
873 public function non_inline_form_limit_per_session_callback( $args ) {
874
875 // Output field.
876 $this->output_checkbox_field(
877 'non_inline_form_limit_per_session',
878 'on',
879 $this->settings->non_inline_form_limit_per_session(),
880 esc_html__( 'If checked, one non-inline form will be displayed per session. This applies to all non-inline forms defined on this screen, Page / Post / Category settings, and any Form blocks or shortcodes specifying a non-inline form.', 'convertkit' )
881 );
882
883 }
884
885 /**
886 * Renders the input for the reCAPTCHA Site Key setting.
887 *
888 * @since 3.0.0
889 *
890 * @param array $args Setting field arguments (name,description).
891 */
892 public function recaptcha_site_key_callback( $args ) {
893
894 // Output field.
895 $this->output_text_field(
896 'recaptcha_site_key',
897 esc_attr( $this->settings->recaptcha_site_key() ),
898 $args['description'],
899 array(
900 'widefat',
901 )
902 );
903
904 }
905
906 /**
907 * Renders the input for the reCAPTCHA Secret Key setting.
908 *
909 * @since 3.0.0
910 *
911 * @param array $args Setting field arguments (name,description).
912 */
913 public function recaptcha_secret_key_callback( $args ) {
914
915 // Output field.
916 $this->output_text_field(
917 'recaptcha_secret_key',
918 esc_attr( $this->settings->recaptcha_secret_key() ),
919 $args['description'],
920 array(
921 'widefat',
922 )
923 );
924
925 }
926
927 /**
928 * Renders the input for the reCAPTCHA Minimum Score setting.
929 *
930 * @since 3.0.0
931 *
932 * @param array $args Setting field arguments (name,description).
933 */
934 public function recaptcha_minimum_score_callback( $args ) {
935
936 // Output field.
937 $this->output_number_field(
938 'recaptcha_minimum_score',
939 esc_attr( (string) $this->settings->recaptcha_minimum_score() ),
940 $args['min'],
941 $args['max'],
942 $args['step'],
943 $args['description'],
944 array(
945 'widefat',
946 )
947 );
948
949 }
950
951 /**
952 * Renders the input for the Debug setting.
953 *
954 * @since 1.9.6
955 */
956 public function debug_callback() {
957
958 // Output field.
959 $this->output_checkbox_field(
960 'debug',
961 'on',
962 $this->settings->debug_enabled(),
963 esc_html__( 'Log requests to file and output browser console messages.', 'convertkit' ),
964 esc_html__( 'You can ignore this unless you\'re working with our support team to resolve an issue. Decheck this option to improve performance.', 'convertkit' )
965 );
966
967 }
968
969 /**
970 * Renders the input for the Disable Javascript setting.
971 *
972 * @since 1.9.6
973 */
974 public function no_scripts_callback() {
975
976 // Output field.
977 $this->output_checkbox_field(
978 'no_scripts',
979 'on',
980 $this->settings->scripts_disabled(),
981 esc_html__( 'Prevent plugin JavaScript files loading on the frontend site. This will disable the custom content and tagging features of the plugin. Does not apply to embedding forms or landing pages. Use with caution!', 'convertkit' )
982 );
983
984 }
985
986 /**
987 * Renders the input for the Disable CSS setting.
988 *
989 * @since 1.9.6.9
990 */
991 public function no_css_callback() {
992
993 // Output field.
994 $this->output_checkbox_field(
995 'no_css',
996 'on',
997 $this->settings->css_disabled(),
998 esc_html__( 'Prevents loading plugin CSS files. This will disable styling on broadcasts, form trigger buttons, product buttons and member\'s content. Use with caution!', 'convertkit' ),
999 array(
1000 sprintf(
1001 '%s <a href="%s" target="_blank">%s</a>',
1002 esc_html__( 'To customize forms and their styling, use the', 'convertkit' ),
1003 esc_url( convertkit_get_form_editor_url() ),
1004 esc_html__( 'Kit form editor', 'convertkit' )
1005 ),
1006 esc_html__( 'For creators who require form designs to follow their WordPress theme, use the Kit Form Builder block in the block editor.', 'convertkit' ),
1007 sprintf(
1008 '%s <a href="https://wordpress.org/plugins/contact-form-7/" target="_blank">Contact Form 7</a>, <a href="https://wordpress.org/plugins/convertkit-gravity-forms/" target="_blank">Gravity Forms</a> %s <a href="https://wordpress.org/plugins/integrate-convertkit-wpforms/" target="_blank">WPForms</a> %s',
1009 esc_html__( 'For developers who require custom form designs through use of CSS, consider using the', 'convertkit' ),
1010 esc_html__( 'or', 'convertkit' ),
1011 esc_html__( 'integrations.', 'convertkit' )
1012 ),
1013 )
1014 );
1015
1016 }
1017
1018 /**
1019 * Renders the input for the Usage Tracking setting.
1020 *
1021 * @since 3.0.4
1022 */
1023 public function usage_tracking_callback() {
1024
1025 // Output field.
1026 $this->output_checkbox_field(
1027 'usage_tracking',
1028 'on',
1029 $this->settings->usage_tracking(),
1030 esc_html__( 'By allowing us to collect usage data, we can better understand which WordPress configurations, themes and plugins we should test.', 'convertkit' ),
1031 array(
1032 sprintf(
1033 '%s <a href="%s" target="_blank">%s</a>',
1034 esc_html__( 'Complete documentation on usage tracking can be found', 'convertkit' ),
1035 $this->documentation_url(),
1036 esc_html__( 'here', 'convertkit' )
1037 ),
1038 )
1039 );
1040
1041 }
1042
1043 /**
1044 * Sanitizes the settings prior to being saved.
1045 *
1046 * @since 2.4.3
1047 *
1048 * @param null|array $settings Submitted Settings Fields.
1049 * @return array Sanitized Settings with Defaults
1050 */
1051 public function sanitize_settings( $settings ) {
1052
1053 // If no Access Token, Refresh Token or Token Expiry keys were specified in the settings
1054 // prior to save, don't overwrite them with the blank setting from get_defaults().
1055 // This ensures we only blank these values if we explicitly do so via $settings,
1056 // as they won't be included in the Settings screen for security.
1057 if ( ! filter_has_var( INPUT_GET, 'disconnect' ) ) {
1058 // If settings are null, no checkboxes were ticked and no other form elements
1059 // were submitted i.e. the Kit account has no forms.
1060 if ( is_null( $settings ) ) {
1061 $settings = array();
1062 }
1063
1064 if ( ! array_key_exists( 'access_token', $settings ) ) {
1065 $settings['access_token'] = $this->settings->get_access_token();
1066 }
1067 if ( ! array_key_exists( 'refresh_token', $settings ) ) {
1068 $settings['refresh_token'] = $this->settings->get_refresh_token();
1069 }
1070 if ( ! array_key_exists( 'token_expires', $settings ) ) {
1071 $settings['token_expires'] = $this->settings->get_token_expiry();
1072 }
1073 }
1074
1075 // Call parent class to merge settings with defaults.
1076 $settings = parent::sanitize_settings( $settings );
1077
1078 // If a Form or Landing Page was specified that isn't the default,
1079 // request a review.
1080 // Since switching to OAuth means the settings screen will only display
1081 // settings if the access token is valid, the Default Forms options will
1082 // always be submitted. Previously, if no API Key/Secret was specified,
1083 // no Default Forms options would render.
1084 // This can safely be called multiple times, as the review request
1085 // class will ensure once a review request is dismissed by the user,
1086 // it is never displayed again.
1087 if ( ( isset( $settings['page_form'] ) && $settings['page_form'] !== 'default' ) ||
1088 ( isset( $settings['post_form'] ) && $settings['post_form'] !== 'default' ) ) {
1089 WP_ConvertKit()->get_class( 'review_request' )->request_review();
1090 }
1091
1092 // Return settings to be saved.
1093 return $settings;
1094
1095 }
1096
1097 }
1098