PluginProbe
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages / 3.3.2
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages v3.3.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-admin-section-general.php

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

1,152 lines 33.7 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 // Get Settings class.
197 $settings = new ConvertKit_Settings();
198
199 // Setup API.
200 $api = new ConvertKit_API_V4(
201 CONVERTKIT_OAUTH_CLIENT_ID,
202 CONVERTKIT_OAUTH_CLIENT_REDIRECT_URI,
203 $settings->get_access_token(),
204 $settings->get_refresh_token(),
205 $settings->debug_enabled(),
206 'settings'
207 );
208
209 // Check that we're using the Kit WordPress Libraries 2.1.4 or higher.
210 // If another Kit Plugin is active and out of date, its libraries might
211 // be loaded that don't have this method.
212 if ( ! method_exists( $api, 'revoke_tokens' ) ) { // @phpstan-ignore-line Older WordPress Libraries won't have this function.
213 $this->output_error( __( 'The Kit WordPress Libraries is missing the `revoke_tokens` method. Please update all Kit WordPress Plugins to their latest versions, and click Disconnect again.', 'convertkit' ) );
214 return;
215 }
216
217 // Revoke Access and Refresh Tokens.
218 // See convertkit_delete_credentials() method in functions.php, which is called
219 // by the `convertkit_api_revoke_tokens` action and deletes credentials from the Plugin's settings.
220 $result = $api->revoke_tokens();
221 if ( is_wp_error( $result ) ) {
222 $this->output_error( $result->get_error_message() );
223 return;
224 }
225
226 // Delete cached resources.
227 $creator_network = new ConvertKit_Resource_Creator_Network_Recommendations();
228 $custom_fields = new ConvertKit_Resource_Custom_Fields();
229 $forms = new ConvertKit_Resource_Forms();
230 $landing_pages = new ConvertKit_Resource_Landing_Pages();
231 $posts = new ConvertKit_Resource_Posts();
232 $products = new ConvertKit_Resource_Products();
233 $sequences = new ConvertKit_Resource_Sequences();
234 $tags = new ConvertKit_Resource_Tags();
235 $creator_network->delete();
236 $custom_fields->delete();
237 $forms->delete();
238 $landing_pages->delete();
239 $posts->delete();
240 $products->delete();
241 $sequences->delete();
242 $tags->delete();
243
244 // Redirect to General screen, which will now show the ConvertKit_Settings_OAuth screen, because
245 // the Plugin has no access token.
246 wp_safe_redirect(
247 add_query_arg(
248 array(
249 'page' => $this->settings_key,
250 ),
251 'options-general.php'
252 )
253 );
254 exit();
255
256 }
257
258 /**
259 * Enqueues scripts for the Settings > General screen.
260 *
261 * @since 2.2.4
262 *
263 * @param string $section Settings section / tab (general|tools|restrict-content).
264 */
265 public function enqueue_scripts( $section ) {
266
267 // Bail if we're not on the general section.
268 if ( $section !== $this->name ) {
269 return;
270 }
271
272 // Enqueue Select2 JS.
273 convertkit_select2_enqueue_scripts();
274
275 // Enqueue JS.
276 wp_enqueue_script( 'convertkit-admin-preview-output', CONVERTKIT_PLUGIN_URL . 'resources/backend/js/preview-output.js', array( 'jquery' ), CONVERTKIT_PLUGIN_VERSION, true );
277 wp_enqueue_script( 'convertkit-admin-settings-conditional-display', CONVERTKIT_PLUGIN_URL . 'resources/backend/js/settings-conditional-display.js', array( 'jquery' ), CONVERTKIT_PLUGIN_VERSION, true );
278
279 }
280
281 /**
282 * Enqueues styles for the Settings > General screen.
283 *
284 * @since 2.2.4
285 *
286 * @param string $section Settings section / tab (general|tools|restrict-content).
287 */
288 public function enqueue_styles( $section ) {
289
290 // Bail if we're not on the general section.
291 if ( $section !== $this->name ) {
292 return;
293 }
294
295 // Enqueue Select2 CSS.
296 convertkit_select2_enqueue_styles();
297
298 }
299
300 /**
301 * Registers settings fields for this section.
302 */
303 public function register_fields() {
304
305 // Initialize resource classes.
306 $this->maybe_initialize_and_refresh_resources();
307
308 add_settings_field(
309 'account_name',
310 __( 'Account Name', 'convertkit' ),
311 array( $this, 'account_name_callback' ),
312 $this->settings_key,
313 $this->name
314 );
315
316 // Initialize resource classes and perform a refresh if this hasn't yet been done.
317 foreach ( convertkit_get_supported_post_types() as $supported_post_type ) {
318 // Get Post Type's Label.
319 $post_type = get_post_type_object( $supported_post_type );
320
321 // Skip if the Post Type doesn't exist.
322 if ( ! $post_type ) {
323 continue;
324 }
325
326 // Add Settings Fields.
327 add_settings_field(
328 $supported_post_type . '_form',
329 sprintf(
330 /* translators: Post Type Name, plural */
331 __( 'Default Form (%s)', 'convertkit' ),
332 $post_type->label
333 ),
334 array( $this, 'default_form_callback' ),
335 $this->settings_key,
336 $this->name,
337 array(
338 'label_for' => '_wp_convertkit_settings_' . $supported_post_type . '_form',
339 'post_type' => $supported_post_type,
340 'post_type_object' => $post_type,
341 )
342 );
343
344 if ( $this->forms->exist() ) {
345 add_settings_field(
346 $supported_post_type . '_form_position',
347 sprintf(
348 /* translators: Post Type Name, plural */
349 __( 'Form Position (%s)', 'convertkit' ),
350 $post_type->label
351 ),
352 array( $this, 'default_form_position_callback' ),
353 $this->settings_key,
354 $this->name,
355 array(
356 'label_for' => '_wp_convertkit_settings_' . $supported_post_type . '_form_position',
357 'post_type' => $supported_post_type,
358 'post_type_object' => $post_type,
359 )
360 );
361
362 add_settings_field(
363 $supported_post_type . '_form_position_element',
364 '',
365 array( $this, 'default_form_position_element_callback' ),
366 $this->settings_key,
367 $this->name,
368 array(
369 'label_for' => '_wp_convertkit_settings_' . $supported_post_type . '_form_position_element',
370 'post_type' => $supported_post_type,
371 'post_type_object' => $post_type,
372 )
373 );
374 }
375 }
376
377 // Site Wide.
378 add_settings_field(
379 'non_inline_form',
380 __( 'Default Forms (Site Wide)', 'convertkit' ),
381 array( $this, 'non_inline_form_callback' ),
382 $this->settings_key,
383 $this->name . '-site-wide',
384 array(
385 'label_for' => 'non_inline_form',
386 )
387 );
388
389 add_settings_field(
390 'non_inline_form_honor_none_setting',
391 __( 'Behavior', 'convertkit' ),
392 array( $this, 'non_inline_form_honor_none_setting_callback' ),
393 $this->settings_key,
394 $this->name . '-site-wide',
395 array(
396 'label_for' => 'non_inline_form_honor_none_setting',
397 )
398 );
399
400 // Non-inline Form Limit per Session.
401 add_settings_field(
402 'non_inline_form_limit_per_session',
403 __( 'Limit Display', 'convertkit' ),
404 array( $this, 'non_inline_form_limit_per_session_callback' ),
405 $this->settings_key,
406 $this->name . '-site-wide',
407 array(
408 'label_for' => 'non_inline_form_limit_per_session',
409 )
410 );
411
412 // reCAPTCHA.
413 add_settings_field(
414 'recaptcha_site_key',
415 __( 'reCAPTCHA: Site Key', 'convertkit' ),
416 array( $this, 'recaptcha_site_key_callback' ),
417 $this->settings_key,
418 $this->name . '-recaptcha',
419 array(
420 'label_for' => 'recaptcha_site_key',
421 'description' => array(
422 __( 'Enter your Google reCAPTCHA v3 Site Key. When specified, this will be used to reduce spam signups.', 'convertkit' ),
423 ),
424 )
425 );
426 add_settings_field(
427 'recaptcha_secret_key',
428 __( 'reCAPTCHA: Secret Key', 'convertkit' ),
429 array( $this, 'recaptcha_secret_key_callback' ),
430 $this->settings_key,
431 $this->name . '-recaptcha',
432 array(
433 'label_for' => 'recaptcha_secret_key',
434 'description' => array(
435 __( 'Enter your Google reCAPTCHA v3 Secret Key. When specified, this will be used to reduce spam signups.', 'convertkit' ),
436 ),
437 )
438 );
439 add_settings_field(
440 'recaptcha_minimum_score',
441 __( 'reCAPTCHA: Minimum Score', 'convertkit' ),
442 array( $this, 'recaptcha_minimum_score_callback' ),
443 $this->settings_key,
444 $this->name . '-recaptcha',
445 array(
446 'label_for' => 'recaptcha_minimum_score',
447 'min' => 0,
448 'max' => 1,
449 'step' => 0.01,
450 'description' => array(
451 __( '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' ),
452 ),
453 )
454 );
455
456 // Advanced.
457 add_settings_field(
458 'debug',
459 __( 'Debug', 'convertkit' ),
460 array( $this, 'debug_callback' ),
461 $this->settings_key,
462 $this->name . '-advanced',
463 array(
464 'label_for' => 'debug',
465 )
466 );
467
468 add_settings_field(
469 'no_scripts',
470 __( 'Disable JavaScript', 'convertkit' ),
471 array( $this, 'no_scripts_callback' ),
472 $this->settings_key,
473 $this->name . '-advanced',
474 array(
475 'label_for' => 'no_scripts',
476 )
477 );
478
479 add_settings_field(
480 'no_css',
481 __( 'Disable CSS', 'convertkit' ),
482 array( $this, 'no_css_callback' ),
483 $this->settings_key,
484 $this->name . '-advanced',
485 array(
486 'label_for' => 'no_css',
487 )
488 );
489
490 add_settings_field(
491 'no_add_new_button',
492 __( 'Disable Add New Landing Page / Member Content Button', 'convertkit' ),
493 array( $this, 'no_add_new_button_callback' ),
494 $this->settings_key,
495 $this->name . '-advanced',
496 array(
497 'label_for' => 'no_add_new_button',
498 )
499 );
500
501 add_settings_field(
502 'usage_tracking',
503 __( 'Usage Tracking', 'convertkit' ),
504 array( $this, 'usage_tracking_callback' ),
505 $this->settings_key,
506 $this->name . '-advanced',
507 array(
508 'label_for' => 'usage_tracking',
509 )
510 );
511
512 }
513
514 /**
515 * Prints help info for this section
516 */
517 public function print_section_info() {
518
519 ?>
520 <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' ); ?>
521 <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>
522 <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>
523 <p>
524 <?php
525 printf(
526 /* translators: [convertkit] shortcode, wrapped in <code> tags */
527 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' ),
528 '<code>[convertkit]</code>'
529 );
530 ?>
531 </p>
532 <?php
533
534 }
535
536 /**
537 * Prints help info for the site wide section of the settings screen.
538 *
539 * @since 2.7.3
540 */
541 public function print_section_info_site_wide() {
542
543 ?>
544 <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>
545 <?php
546
547 }
548
549 /**
550 * Prints help info for the recaptcha section of the settings screen.
551 *
552 * @since 3.0.0
553 */
554 public function print_section_info_recaptcha() {
555 ?>
556 <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>
557 <?php
558 }
559
560 /**
561 * Prints help info for the advanced section of the settings screen.
562 *
563 * @since 2.7.1
564 */
565 public function print_section_info_advanced() {
566
567 ?>
568 <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>
569 <?php
570
571 }
572
573 /**
574 * Returns the URL for the ConvertKit documentation for this setting section.
575 *
576 * @since 2.0.8
577 *
578 * @return string Documentation URL.
579 */
580 public function documentation_url() {
581
582 return 'https://help.kit.com/en/articles/2502591-how-to-set-up-the-kit-plugin-on-your-wordpress-website';
583
584 }
585
586 /**
587 * Outputs the Account Name
588 *
589 * @since 1.9.6
590 */
591 public function account_name_callback() {
592
593 // Output Account Name.
594 // If account is an error, check_credentials() will output an error above the settings section.
595 $html = sprintf(
596 '<p>%s</p>',
597 ! is_wp_error( $this->account ) && isset( $this->account['account']['name'] ) ? esc_attr( $this->account['account']['name'] ) : esc_html__( '(Not specified)', 'convertkit' )
598 );
599
600 // Display an option to disconnect.
601 $html .= sprintf(
602 '<p><a href="%1$s" class="button button-secondary">%2$s</a></p>',
603 esc_url(
604 add_query_arg(
605 array(
606 'page' => '_wp_convertkit_settings',
607 '_convertkit_settings_oauth_disconnect' => wp_create_nonce( 'convertkit-oauth-disconnect' ),
608 ),
609 'options-general.php'
610 )
611 ),
612 esc_html__( 'Disconnect', 'convertkit' )
613 );
614
615 echo wp_kses( $html, convertkit_kses_allowed_html() );
616
617 }
618
619 /**
620 * Initialize resource classes and perform a and refresh of resources,
621 * if initialization has not yet taken place.
622 *
623 * @since 2.5.9
624 */
625 public function maybe_initialize_and_refresh_resources() {
626
627 // If the Forms resource class is initialized, this has already been done.
628 if ( $this->forms !== false ) {
629 return;
630 }
631
632 // Initialize forms resource class.
633 $this->forms = new ConvertKit_Resource_Forms( 'settings' );
634
635 // Don't refresh resources if we're not on the settings screen, as
636 // it's a resource intense process that can take several seconds.
637 // We don't want to block other parts of the admin UI.
638 if ( ! $this->on_settings_screen( $this->name ) ) {
639 return;
640 }
641
642 // Refresh Forms.
643 $result = $this->forms->refresh();
644
645 // Bail if an error occured.
646 if ( is_wp_error( $result ) ) {
647 return;
648 }
649
650 // Also refresh Landing Pages, Tags and Posts. Whilst not displayed in the Plugin Settings, this ensures up to date
651 // lists are stored for when editing e.g. Pages.
652 $landing_pages = new ConvertKit_Resource_Landing_Pages( 'settings' );
653 $result = $landing_pages->refresh();
654
655 // Bail if an error occured.
656 if ( is_wp_error( $result ) ) {
657 return;
658 }
659
660 remove_all_actions( 'convertkit_resource_refreshed_posts' );
661 $posts = new ConvertKit_Resource_Posts( 'settings' );
662 $result = $posts->refresh();
663
664 // Bail if an error occured.
665 if ( is_wp_error( $result ) ) {
666 return;
667 }
668
669 $products = new ConvertKit_Resource_Products( 'settings' );
670 $result = $products->refresh();
671
672 // Bail if an error occured.
673 if ( is_wp_error( $result ) ) {
674 return;
675 }
676
677 $sequences = new ConvertKit_Resource_Sequences( 'settings' );
678 $result = $sequences->refresh();
679
680 // Bail if an error occured.
681 if ( is_wp_error( $result ) ) {
682 return;
683 }
684
685 $tags = new ConvertKit_Resource_Tags( 'settings' );
686 $result = $tags->refresh();
687
688 // Bail if an error occured.
689 if ( is_wp_error( $result ) ) {
690 return;
691 }
692
693 }
694
695 /**
696 * Renders the input for the Default Form setting for the given Post Type.
697 *
698 * @since 1.9.6
699 *
700 * @param array $args Field arguments.
701 */
702 public function default_form_callback( $args ) {
703
704 // Bail if no Forms exist.
705 if ( ! $this->forms->exist() ) {
706 esc_html_e( 'No Forms exist in Kit.', 'convertkit' );
707 echo '<br /><a href="' . esc_url( convertkit_get_new_form_url() ) . '" target="_blank">' . esc_html__( 'Click here to create your first form', 'convertkit' ) . '</a>';
708 return;
709 }
710
711 // Build description with preview link.
712 $description = false;
713 $preview_url = WP_ConvertKit()->get_class( 'preview_output' )->get_preview_form_url( $args['post_type'] );
714 if ( $preview_url ) {
715 // Include a preview link in the description.
716 $description = sprintf(
717 '%s %s %s',
718 sprintf(
719 /* translators: Post Type name, plural */
720 esc_html__( 'Select a form above to automatically output below all %s.', 'convertkit' ),
721 $args['post_type_object']->label
722 ),
723 '<a href="' . esc_url( $preview_url ) . '" id="convertkit-preview-form-' . esc_attr( $args['post_type'] ) . '" target="_blank">' . esc_html__( 'Click here', 'convertkit' ) . '</a>',
724 esc_html__( 'to preview how this will display.', 'convertkit' )
725 );
726 } else {
727 // Just output the field's description.
728 $description = sprintf(
729 /* translators: Post Type name, plural */
730 esc_html__( 'Select a form above to automatically output below all %s.', 'convertkit' ),
731 $args['post_type_object']->label
732 );
733 }
734
735 // Output field.
736 echo '<div class="convertkit-select2-container">';
737 $this->forms->output_select_field_all(
738 $this->settings_key . '[' . $args['post_type'] . '_form]',
739 $this->settings_key . '_' . $args['post_type'] . '_form',
740 array(
741 'convertkit-select2',
742 'convertkit-preview-output-link',
743 ),
744 $this->settings->get_default_form( $args['post_type'] ),
745 array(
746 'default' => esc_html__( 'None', 'convertkit' ),
747 ),
748 array(
749 'data-target' => '#convertkit-preview-form-' . esc_attr( $args['post_type'] ),
750 'data-link' => esc_attr( $preview_url ) . '&convertkit_form_id=',
751 ),
752 $description
753 );
754 echo '</div>';
755
756 }
757
758 /**
759 * Renders the input for the Default Form Position setting for the given Post Type.
760 *
761 * @since 2.5.8
762 *
763 * @param array $args Field arguments.
764 */
765 public function default_form_position_callback( $args ) {
766
767 $this->output_select_field(
768 $args['post_type'] . '_form_position',
769 esc_attr( $this->settings->get_default_form_position( $args['post_type'] ) ),
770 array(
771 'before_content' => sprintf(
772 /* translators: Post type singular name */
773 esc_attr__( 'Before %s content', 'convertkit' ),
774 esc_attr( $args['post_type_object']->labels->singular_name )
775 ),
776 'after_content' => sprintf(
777 /* translators: Post type singular name */
778 esc_attr__( 'After %s content', 'convertkit' ),
779 esc_attr( $args['post_type_object']->labels->singular_name )
780 ),
781 'before_after_content' => sprintf(
782 /* translators: Post type singular name */
783 esc_attr__( 'Before and after %s content', 'convertkit' ),
784 esc_attr( $args['post_type_object']->labels->singular_name )
785 ),
786 'after_element' => esc_html__( 'After element', 'convertkit' ),
787 ),
788 sprintf(
789 /* translators: Post Type name, plural */
790 esc_html__( 'Where forms should display relative to the %s content', 'convertkit' ),
791 esc_html( $args['post_type_object']->labels->singular_name )
792 ),
793 array( 'convertkit-conditional-display' ),
794 array(
795 'data-conditional-value' => 'after_element',
796 'data-conditional-element' => esc_attr( $args['post_type'] ) . '_form_position_element_index',
797 )
798 );
799
800 }
801
802 /**
803 * Renders the input for the Default Form Position Index setting for the given Post Type.
804 *
805 * @since 2.6.1
806 *
807 * @param array $args Field arguments.
808 */
809 public function default_form_position_element_callback( $args ) {
810
811 $this->output_number_field(
812 $args['post_type'] . '_form_position_element_index',
813 esc_attr( (string) $this->settings->get_default_form_position_element_index( $args['post_type'] ) ),
814 1,
815 999,
816 1,
817 false,
818 array( 'after_element' )
819 );
820
821 $this->output_select_field(
822 $args['post_type'] . '_form_position_element',
823 esc_attr( $this->settings->get_default_form_position_element( $args['post_type'] ) ),
824 array(
825 'p' => esc_html__( 'Paragraphs', 'convertkit' ),
826 'h2' => esc_html__( 'Headings <h2>', 'convertkit' ),
827 'h3' => esc_html__( 'Headings <h3>', 'convertkit' ),
828 'h4' => esc_html__( 'Headings <h4>', 'convertkit' ),
829 'h5' => esc_html__( 'Headings <h5>', 'convertkit' ),
830 'h6' => esc_html__( 'Headings <h6>', 'convertkit' ),
831 'img' => esc_html__( 'Images', 'convertkit' ),
832 ),
833 esc_html__( 'The number of elements before outputting the form.', 'convertkit' ),
834 array( 'after_element' )
835 );
836
837 }
838
839 /**
840 * Renders the input for the Non-inline Form setting.
841 *
842 * @since 2.2.3
843 *
844 * @param array $args Field arguments.
845 */
846 public function non_inline_form_callback( $args ) {
847
848 // Bail if no non-inline Forms exist.
849 if ( ! $this->forms->non_inline_exist() ) {
850 esc_html_e( 'No non-inline Forms exist in Kit.', 'convertkit' );
851 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>';
852 return;
853 }
854
855 // Build description with preview link.
856 $preview_url = WP_ConvertKit()->get_class( 'preview_output' )->get_preview_form_home_url();
857 $description = sprintf(
858 '%s %s %s',
859 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' ),
860 '<a href="' . esc_url( $preview_url ) . '" id="convertkit-preview-non-inline-form" target="_blank">' . esc_html__( 'Click here', 'convertkit' ) . '</a>',
861 esc_html__( 'to preview how this will display.', 'convertkit' )
862 );
863
864 // Output field.
865 echo '<div class="convertkit-select2-container">';
866 $this->forms->output_select_field_non_inline(
867 $this->settings_key . '[non_inline_form]',
868 $this->settings_key . '_non_inline_form',
869 array(
870 'convertkit-select2',
871 'convertkit-preview-output-link',
872 ),
873 $this->settings->get_non_inline_form(),
874 false,
875 array(
876 'data-target' => '#convertkit-preview-non-inline-form',
877 'data-link' => esc_attr( $preview_url ) . '&convertkit_form_id=',
878 ),
879 $description
880 );
881 echo '</div>';
882
883 }
884
885 /**
886 * Renders the input for the Non-inline Form override setting.
887 *
888 * @since 2.7.3
889 */
890 public function non_inline_form_honor_none_setting_callback() {
891
892 // Output field.
893 $this->output_checkbox_field(
894 'non_inline_form_honor_none_setting',
895 'on',
896 $this->settings->non_inline_form_honor_none_setting(),
897 esc_html__( 'If checked, do not display the site wide form(s) above on Pages / Posts that have their Kit Form setting = None.', 'convertkit' )
898 );
899
900 }
901
902
903 /**
904 * Renders the input for the Modal Form Limit per Session setting.
905 *
906 * @since 3.0.0
907 *
908 * @param array $args Setting field arguments (name,description).
909 */
910 public function non_inline_form_limit_per_session_callback( $args ) {
911
912 // Output field.
913 $this->output_checkbox_field(
914 'non_inline_form_limit_per_session',
915 'on',
916 $this->settings->non_inline_form_limit_per_session(),
917 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' )
918 );
919
920 }
921
922 /**
923 * Renders the input for the reCAPTCHA Site Key setting.
924 *
925 * @since 3.0.0
926 *
927 * @param array $args Setting field arguments (name,description).
928 */
929 public function recaptcha_site_key_callback( $args ) {
930
931 // Output field.
932 $this->output_text_field(
933 'recaptcha_site_key',
934 esc_attr( $this->settings->recaptcha_site_key() ),
935 $args['description'],
936 array(
937 'widefat',
938 )
939 );
940
941 }
942
943 /**
944 * Renders the input for the reCAPTCHA Secret Key setting.
945 *
946 * @since 3.0.0
947 *
948 * @param array $args Setting field arguments (name,description).
949 */
950 public function recaptcha_secret_key_callback( $args ) {
951
952 // Output field.
953 $this->output_text_field(
954 'recaptcha_secret_key',
955 esc_attr( $this->settings->recaptcha_secret_key() ),
956 $args['description'],
957 array(
958 'widefat',
959 )
960 );
961
962 }
963
964 /**
965 * Renders the input for the reCAPTCHA Minimum Score setting.
966 *
967 * @since 3.0.0
968 *
969 * @param array $args Setting field arguments (name,description).
970 */
971 public function recaptcha_minimum_score_callback( $args ) {
972
973 // Output field.
974 $this->output_number_field(
975 'recaptcha_minimum_score',
976 esc_attr( (string) $this->settings->recaptcha_minimum_score() ),
977 $args['min'],
978 $args['max'],
979 $args['step'],
980 $args['description'],
981 array(
982 'widefat',
983 )
984 );
985
986 }
987
988 /**
989 * Renders the input for the Debug setting.
990 *
991 * @since 1.9.6
992 */
993 public function debug_callback() {
994
995 // Output field.
996 $this->output_checkbox_field(
997 'debug',
998 'on',
999 $this->settings->debug_enabled(),
1000 esc_html__( 'Log requests to file and output browser console messages.', 'convertkit' ),
1001 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' )
1002 );
1003
1004 }
1005
1006 /**
1007 * Renders the input for the Disable Javascript setting.
1008 *
1009 * @since 1.9.6
1010 */
1011 public function no_scripts_callback() {
1012
1013 // Output field.
1014 $this->output_checkbox_field(
1015 'no_scripts',
1016 'on',
1017 $this->settings->scripts_disabled(),
1018 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' )
1019 );
1020
1021 }
1022
1023 /**
1024 * Renders the input for the Disable CSS setting.
1025 *
1026 * @since 1.9.6.9
1027 */
1028 public function no_css_callback() {
1029
1030 // Output field.
1031 $this->output_checkbox_field(
1032 'no_css',
1033 'on',
1034 $this->settings->css_disabled(),
1035 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' ),
1036 array(
1037 sprintf(
1038 '%s <a href="%s" target="_blank">%s</a>',
1039 esc_html__( 'To customize forms and their styling, use the', 'convertkit' ),
1040 esc_url( convertkit_get_form_editor_url() ),
1041 esc_html__( 'Kit form editor', 'convertkit' )
1042 ),
1043 esc_html__( 'For creators who require form designs to follow their WordPress theme, use the Kit Form Builder block in the block editor.', 'convertkit' ),
1044 sprintf(
1045 '%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',
1046 esc_html__( 'For developers who require custom form designs through use of CSS, consider using the', 'convertkit' ),
1047 esc_html__( 'or', 'convertkit' ),
1048 esc_html__( 'integrations.', 'convertkit' )
1049 ),
1050 )
1051 );
1052
1053 }
1054
1055 /**
1056 * Renders the input for the Disable Add New Landing Page / Member Content setting.
1057 *
1058 * @since 3.2.0
1059 */
1060 public function no_add_new_button_callback() {
1061
1062 // Output field.
1063 $this->output_checkbox_field(
1064 'no_add_new_button',
1065 'on',
1066 $this->settings->add_new_button_disabled(),
1067 esc_html__( 'Hide the "Add New" button on Pages for creating Landing Pages and Member Content.', 'convertkit' )
1068 );
1069
1070 }
1071
1072 /**
1073 * Renders the input for the Usage Tracking setting.
1074 *
1075 * @since 3.0.4
1076 */
1077 public function usage_tracking_callback() {
1078
1079 // Output field.
1080 $this->output_checkbox_field(
1081 'usage_tracking',
1082 'on',
1083 $this->settings->usage_tracking(),
1084 esc_html__( 'By allowing us to collect usage data, we can better understand which WordPress configurations, themes and plugins we should test.', 'convertkit' ),
1085 array(
1086 sprintf(
1087 '%s <a href="%s" target="_blank">%s</a>',
1088 esc_html__( 'Complete documentation on usage tracking can be found', 'convertkit' ),
1089 $this->documentation_url(),
1090 esc_html__( 'here', 'convertkit' )
1091 ),
1092 )
1093 );
1094
1095 }
1096
1097 /**
1098 * Sanitizes the settings prior to being saved.
1099 *
1100 * @since 2.4.3
1101 *
1102 * @param null|array $settings Submitted Settings Fields.
1103 * @return array Sanitized Settings with Defaults
1104 */
1105 public function sanitize_settings( $settings ) {
1106
1107 // If no Access Token, Refresh Token or Token Expiry keys were specified in the settings
1108 // prior to save, don't overwrite them with the blank setting from get_defaults().
1109 // This ensures we only blank these values if we explicitly do so via $settings,
1110 // as they won't be included in the Settings screen for security.
1111 if ( ! filter_has_var( INPUT_GET, 'disconnect' ) ) {
1112 // If settings are null, no checkboxes were ticked and no other form elements
1113 // were submitted i.e. the Kit account has no forms.
1114 if ( is_null( $settings ) ) {
1115 $settings = array();
1116 }
1117
1118 if ( ! array_key_exists( 'access_token', $settings ) ) {
1119 $settings['access_token'] = $this->settings->get_access_token();
1120 }
1121 if ( ! array_key_exists( 'refresh_token', $settings ) ) {
1122 $settings['refresh_token'] = $this->settings->get_refresh_token();
1123 }
1124 if ( ! array_key_exists( 'token_expires', $settings ) ) {
1125 $settings['token_expires'] = $this->settings->get_token_expiry();
1126 }
1127 }
1128
1129 // Call parent class to merge settings with defaults.
1130 $settings = parent::sanitize_settings( $settings );
1131
1132 // If a Form or Landing Page was specified that isn't the default,
1133 // request a review.
1134 // Since switching to OAuth means the settings screen will only display
1135 // settings if the access token is valid, the Default Forms options will
1136 // always be submitted. Previously, if no API Key/Secret was specified,
1137 // no Default Forms options would render.
1138 // This can safely be called multiple times, as the review request
1139 // class will ensure once a review request is dismissed by the user,
1140 // it is never displayed again.
1141 if ( ( isset( $settings['page_form'] ) && $settings['page_form'] !== 'default' ) ||
1142 ( isset( $settings['post_form'] ) && $settings['post_form'] !== 'default' ) ) {
1143 WP_ConvertKit()->get_class( 'review_request' )->request_review();
1144 }
1145
1146 // Return settings to be saved.
1147 return $settings;
1148
1149 }
1150
1151 }
1152