From 4de855b5bb58b94a61d05e3b9d1042a704d8a91f Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Thu, 23 Jan 2025 17:00:12 +0800 Subject: [PATCH 1/9] Started work on requiring login via email login code for Restrict Content by Tag --- ...ertkit-admin-settings-restrict-content.php | 114 ++++++++++++------ includes/class-convertkit-ajax.php | 6 +- ...ass-convertkit-output-restrict-content.php | 76 ++++++++++-- ...s-convertkit-settings-restrict-content.php | 23 +++- resources/frontend/js/restrict-content.js | 1 - .../{product-code.php => code.php} | 0 views/frontend/restrict-content/header.php | 21 ++++ .../{product-email.php => login-email.php} | 0 ...-code.php => login-modal-content-code.php} | 0 ...mail.php => login-modal-content-email.php} | 2 +- .../{product-modal.php => login-modal.php} | 2 +- .../{product.php => login.php} | 20 ++- .../{tag.php => subscribe.php} | 11 +- 13 files changed, 195 insertions(+), 81 deletions(-) rename views/frontend/restrict-content/{product-code.php => code.php} (100%) create mode 100644 views/frontend/restrict-content/header.php rename views/frontend/restrict-content/{product-email.php => login-email.php} (100%) rename views/frontend/restrict-content/{product-modal-content-code.php => login-modal-content-code.php} (100%) rename views/frontend/restrict-content/{product-modal-content-email.php => login-modal-content-email.php} (93%) rename views/frontend/restrict-content/{product-modal.php => login-modal.php} (91%) rename views/frontend/restrict-content/{product.php => login.php} (66%) rename views/frontend/restrict-content/{tag.php => subscribe.php} (87%) diff --git a/admin/class-convertkit-admin-settings-restrict-content.php b/admin/class-convertkit-admin-settings-restrict-content.php index 28fd282a3..c19ecd709 100644 --- a/admin/class-convertkit-admin-settings-restrict-content.php +++ b/admin/class-convertkit-admin-settings-restrict-content.php @@ -99,6 +99,53 @@ public function register_fields() { ) ); + // Restrict by Tag. + add_settings_field( + 'subscribe_heading_tag', + __( 'Subscribe Heading', 'convertkit' ), + array( $this, 'text_callback' ), + $this->settings_key, + $this->name . '-tags', + array( + 'name' => 'subscribe_heading_tag', + 'label_for' => 'subscribe_heading_tag', + 'description' => array( + __( 'Displays text in a heading explaining why the content is only available to subscribers.', 'convertkit' ), + ), + ) + ); + + add_settings_field( + 'subscribe_text_tag', + __( 'Subscribe Text', 'convertkit' ), + array( $this, 'textarea_callback' ), + $this->settings_key, + $this->name . '-tags', + array( + 'name' => 'subscribe_text_tag', + 'label_for' => 'subscribe_text_tag', + 'description' => array( + __( 'Displays text explaining why the content is only available to subscribers.', 'convertkit' ), + ), + ) + ); + + add_settings_field( + 'require_login_for_tags', + __( 'Require Login', 'convertkit' ), + array( $this, 'require_login_for_tags_callback' ), + $this->settings_key, + $this->name . '-tags', + array( + 'name' => 'require_login_for_tags', + 'label_for' => 'require_login_for_tags', + 'label' => __( 'When enabled, subscribers enter their email to receive a login link to access the member-only content.', 'convertkit' ), + 'description' => array( + __( 'If unchecked, subscribers are immediately subscribed to the tag and granted access when entering their email address.', 'convertkit' ), + ), + ) + ); + // reCAPTCHA. add_settings_field( 'recaptcha_site_key', @@ -146,37 +193,6 @@ public function register_fields() { ) ); - // Restrict by Tag. - add_settings_field( - 'subscribe_heading_tag', - __( 'Subscribe Heading', 'convertkit' ), - array( $this, 'text_callback' ), - $this->settings_key, - $this->name . '-tags', - array( - 'name' => 'subscribe_heading_tag', - 'label_for' => 'subscribe_heading_tag', - 'description' => array( - __( 'Displays text in a heading explaining why the content is only available to subscribers.', 'convertkit' ), - ), - ) - ); - - add_settings_field( - 'subscribe_text_tag', - __( 'Subscribe Text', 'convertkit' ), - array( $this, 'textarea_callback' ), - $this->settings_key, - $this->name . '-tags', - array( - 'name' => 'subscribe_text_tag', - 'label_for' => 'subscribe_text_tag', - 'description' => array( - __( 'Displays text explaining why the content is only available to subscribers.', 'convertkit' ), - ), - ) - ); - // All. add_settings_field( 'subscribe_button_label', @@ -229,7 +245,7 @@ public function register_fields() { __( 'Email Text', 'convertkit' ), array( $this, 'text_callback' ), $this->settings_key, - $this->name . '-products', + $this->name, array( 'name' => 'email_text', 'label_for' => 'email_text', @@ -244,7 +260,7 @@ public function register_fields() { __( 'Email Heading', 'convertkit' ), array( $this, 'text_callback' ), $this->settings_key, - $this->name . '-products', + $this->name, array( 'name' => 'email_heading', 'label_for' => 'email_heading', @@ -259,7 +275,7 @@ public function register_fields() { __( 'Email Field Description', 'convertkit' ), array( $this, 'text_callback' ), $this->settings_key, - $this->name . '-products', + $this->name, array( 'name' => 'email_description_text', 'label_for' => 'email_description_text', @@ -274,7 +290,7 @@ public function register_fields() { __( 'Email Button Label', 'convertkit' ), array( $this, 'text_callback' ), $this->settings_key, - $this->name . '-products', + $this->name, array( 'name' => 'email_button_label', 'label_for' => 'email_button_label', @@ -289,7 +305,7 @@ public function register_fields() { __( 'Email Check Heading', 'convertkit' ), array( $this, 'text_callback' ), $this->settings_key, - $this->name . '-products', + $this->name, array( 'name' => 'email_check_heading', 'label_for' => 'email_check_heading', @@ -304,7 +320,7 @@ public function register_fields() { __( 'Email Check Text', 'convertkit' ), array( $this, 'text_callback' ), $this->settings_key, - $this->name . '-products', + $this->name, array( 'name' => 'email_check_text', 'label_for' => 'email_check_text', @@ -319,7 +335,7 @@ public function register_fields() { __( 'No Access Text', 'convertkit' ), array( $this, 'text_callback' ), $this->settings_key, - $this->name . '-products', + $this->name, array( 'name' => 'no_access_text', 'label_for' => 'no_access_text', @@ -384,7 +400,7 @@ public function documentation_url() { } /** - * Renders the input for the Enable setting. + * Renders the input for the Permit Crawlers setting. * * @since 2.4.1 * @@ -403,6 +419,26 @@ public function permit_crawlers_callback( $args ) { } + /** + * Renders the input for the Require Login setting. + * + * @since 2.7.2 + * + * @param array $args Setting field arguments (name,description). + */ + public function require_login_for_tags_callback( $args ) { + + // Output field. + echo $this->get_checkbox_field( // phpcs:ignore WordPress.Security.EscapeOutput + $args['name'], + 'on', + $this->settings->require_login_for_tags(), // phpcs:ignore WordPress.Security.EscapeOutput + $args['label'], // phpcs:ignore WordPress.Security.EscapeOutput + $args['description'] // phpcs:ignore WordPress.Security.EscapeOutput + ); + + } + /** * Renders the input for the text setting. * diff --git a/includes/class-convertkit-ajax.php b/includes/class-convertkit-ajax.php index 5206f4966..c1a520977 100644 --- a/includes/class-convertkit-ajax.php +++ b/includes/class-convertkit-ajax.php @@ -178,14 +178,14 @@ public function subscriber_authentication_send_code() { // If an error occured, build the email form view with the error message. if ( is_wp_error( $output_restrict_content->error ) ) { ob_start(); - include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/product-modal-content-email.php'; + include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/login-modal-content-email.php'; $output = trim( ob_get_clean() ); wp_send_json_success( $output ); } // Build authentication code view to return for output. ob_start(); - include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/product-modal-content-code.php'; + include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/login-modal-content-code.php'; $output = trim( ob_get_clean() ); wp_send_json_success( $output ); @@ -209,7 +209,7 @@ public function subscriber_verification() { // If an error occured, build the code form view with the error message. if ( is_wp_error( $output_restrict_content->error ) ) { ob_start(); - include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/product-modal-content-code.php'; + include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/login-modal-content-code.php'; $output = trim( ob_get_clean() ); wp_send_json_error( $output ); } diff --git a/includes/class-convertkit-output-restrict-content.php b/includes/class-convertkit-output-restrict-content.php index f38331d65..82487a49f 100644 --- a/includes/class-convertkit-output-restrict-content.php +++ b/includes/class-convertkit-output-restrict-content.php @@ -207,6 +207,29 @@ public function maybe_run_subscriber_authentication() { break; case 'tag': + // If require login is enabled, show the login screen. + if ( $this->restrict_content_settings->require_login_for_tags() ) { + // Send email to subscriber with a link to authenticate they have access to the email address submitted. + $result = $this->api->subscriber_authentication_send_code( + $email, + $this->get_url() + ); + + // Bail if an error occured. + if ( is_wp_error( $result ) ) { + $this->error = $result; + return; + } + + // Clear any existing subscriber ID cookie, as the authentication flow has started by sending the email. + $subscriber = new ConvertKit_Subscriber(); + $subscriber->forget(); + + // Store the token so it's included in the subscriber code form. + $this->token = $result; + break; + } + // If Google reCAPTCHA is enabled, check if the submission is spam. if ( $this->restrict_content_settings->has_recaptcha_site_and_secret_keys() ) { $response = wp_remote_post( @@ -1129,18 +1152,18 @@ private function get_call_to_action( $post_id ) { // phpcs:ignore Generic.CodeAn } + // Output code form if this request is after the user entered their email address, + // which means we're going through the authentication flow. + if ( $this->in_authentication_flow() ) { // phpcs:ignore WordPress.Security.NonceVerification + ob_start(); + include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/code.php'; + return trim( ob_get_clean() ); + } + // This is deliberately a switch statement, because we will likely add in support // for restrict by tag and form later. switch ( $this->resource_type ) { case 'product': - // Output product code form if this request is after the user entered their email address, - // which means we're going through the authentication flow. - if ( $this->in_authentication_flow() ) { // phpcs:ignore WordPress.Security.NonceVerification - ob_start(); - include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/product-code.php'; - return trim( ob_get_clean() ); - } - // Output product restricted message and email form. // Get Product. $products = new ConvertKit_Resource_Products( 'restrict_content' ); @@ -1159,19 +1182,50 @@ private function get_call_to_action( $post_id ) { // phpcs:ignore Generic.CodeAn 'wp_footer', function () { - include_once CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/product-modal.php'; + include_once CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/login-modal.php'; } ); } + // Get header and text from settings for Products. + $heading = $this->restrict_content_settings->get_by_key( 'subscribe_heading' ); + $text = $this->restrict_content_settings->get_by_key( 'subscribe_text' ); + // Output. ob_start(); $button = $products->get_html( $this->resource_id, $this->restrict_content_settings->get_by_key( 'subscribe_button_label' ) ); - include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/product.php'; + include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/login.php'; return trim( ob_get_clean() ); case 'tag': + // If require login is enabled, show the login screen. + if ( $this->restrict_content_settings->require_login_for_tags() ) { + // If scripts are enabled, output the email login form in a modal, which will be displayed + // when the 'log in' link is clicked. + if ( ! $this->settings->scripts_disabled() ) { + add_action( + 'wp_footer', + function () { + + include_once CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/login-modal.php'; + + } + ); + } + + // Get header and text from settings for Tags. + $heading = $this->restrict_content_settings->get_by_key( 'subscribe_heading_tag' ); + $text = $this->restrict_content_settings->get_by_key( 'subscribe_text_tag' ); + + // Output. + ob_start(); + include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/login.php'; + return trim( ob_get_clean() ); + } + + // If here, no login required. + // Users can enter their email to immediately subscribe to the tag and gain access. // Enqueue Google reCAPTCHA JS if site and secret keys specified. if ( $this->restrict_content_settings->has_recaptcha_site_and_secret_keys() ) { add_filter( @@ -1190,7 +1244,7 @@ function ( $scripts ) { // Output. ob_start(); - include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/tag.php'; + include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/subscribe.php'; return trim( ob_get_clean() ); default: diff --git a/includes/class-convertkit-settings-restrict-content.php b/includes/class-convertkit-settings-restrict-content.php index 9d1071f69..ca02caa81 100644 --- a/includes/class-convertkit-settings-restrict-content.php +++ b/includes/class-convertkit-settings-restrict-content.php @@ -77,6 +77,20 @@ public function permit_crawlers() { } + /** + * Returns whether login by email to receive a login link is required + * for Member Content by Tag functionality. + * + * @since 2.7.2 + * + * @return bool + */ + public function require_login_for_tags() { + + return ( $this->settings['require_login_for_tags'] === 'on' ? true : false ); + + } + /** * Returns the reCAPTCHA Site Key Plugin setting. * @@ -195,11 +209,6 @@ public function get_defaults() { // Permit Crawlers. 'permit_crawlers' => '', - // Google reCAPTCHA. - 'recaptcha_site_key' => '', - 'recaptcha_secret_key' => '', - 'recaptcha_minimum_score' => '0.5', - // Restrict by Product. 'subscribe_heading' => __( 'Read this post with a premium subscription', 'convertkit' ), 'subscribe_text' => __( 'This post is only available to premium subscribers. Join today to get access to all posts.', 'convertkit' ), @@ -207,6 +216,10 @@ public function get_defaults() { // Restrict by Tag. 'subscribe_heading_tag' => __( 'Subscribe to keep reading', 'convertkit' ), 'subscribe_text_tag' => __( 'This post is free to read but only available to subscribers. Join today to get access to all posts.', 'convertkit' ), + 'require_login_for_tags' => '', // blank|on. + 'recaptcha_site_key' => '', + 'recaptcha_secret_key' => '', + 'recaptcha_minimum_score' => '0.5', // All. 'subscribe_button_label' => __( 'Subscribe', 'convertkit' ), diff --git a/resources/frontend/js/restrict-content.js b/resources/frontend/js/restrict-content.js index d9ab7dceb..4f078e552 100644 --- a/resources/frontend/js/restrict-content.js +++ b/resources/frontend/js/restrict-content.js @@ -60,7 +60,6 @@ document.addEventListener( function convertKitRestrictContentTagFormSubmit( token ) { - console.log( token ); document.getElementById( 'convertkit-restrict-content-form' ).submit(); } diff --git a/views/frontend/restrict-content/product-code.php b/views/frontend/restrict-content/code.php similarity index 100% rename from views/frontend/restrict-content/product-code.php rename to views/frontend/restrict-content/code.php diff --git a/views/frontend/restrict-content/header.php b/views/frontend/restrict-content/header.php new file mode 100644 index 000000000..496701a21 --- /dev/null +++ b/views/frontend/restrict-content/header.php @@ -0,0 +1,21 @@ + +

+

+ '; + } + ?> +

\ No newline at end of file diff --git a/views/frontend/restrict-content/product-email.php b/views/frontend/restrict-content/login-email.php similarity index 100% rename from views/frontend/restrict-content/product-email.php rename to views/frontend/restrict-content/login-email.php diff --git a/views/frontend/restrict-content/product-modal-content-code.php b/views/frontend/restrict-content/login-modal-content-code.php similarity index 100% rename from views/frontend/restrict-content/product-modal-content-code.php rename to views/frontend/restrict-content/login-modal-content-code.php diff --git a/views/frontend/restrict-content/product-modal-content-email.php b/views/frontend/restrict-content/login-modal-content-email.php similarity index 93% rename from views/frontend/restrict-content/product-modal-content-email.php rename to views/frontend/restrict-content/login-modal-content-email.php index 2771e1413..fa1e262ca 100644 --- a/views/frontend/restrict-content/product-modal-content-email.php +++ b/views/frontend/restrict-content/login-modal-content-email.php @@ -12,5 +12,5 @@ ?>

get_class( 'output_restrict_content' )->restrict_content_settings->get_by_key( 'email_heading' ) ); ?>

\ No newline at end of file diff --git a/views/frontend/restrict-content/product-modal.php b/views/frontend/restrict-content/login-modal.php similarity index 91% rename from views/frontend/restrict-content/product-modal.php rename to views/frontend/restrict-content/login-modal.php index 0d9465184..a2d0a7dd8 100644 --- a/views/frontend/restrict-content/product-modal.php +++ b/views/frontend/restrict-content/login-modal.php @@ -14,7 +14,7 @@
diff --git a/views/frontend/restrict-content/product.php b/views/frontend/restrict-content/login.php similarity index 66% rename from views/frontend/restrict-content/product.php rename to views/frontend/restrict-content/login.php index d5819775d..d039552c5 100644 --- a/views/frontend/restrict-content/product.php +++ b/views/frontend/restrict-content/login.php @@ -1,9 +1,9 @@
-

restrict_content_settings->get_by_key( 'subscribe_heading' ) ); ?>

-

- restrict_content_settings->get_by_key( 'subscribe_text' ) ) as $text_line ) { - echo esc_html( $text_line ) . '
'; - } - ?> -

- settings->scripts_disabled() ) { diff --git a/views/frontend/restrict-content/tag.php b/views/frontend/restrict-content/subscribe.php similarity index 87% rename from views/frontend/restrict-content/tag.php rename to views/frontend/restrict-content/subscribe.php index 50fa02867..17db376bf 100644 --- a/views/frontend/restrict-content/tag.php +++ b/views/frontend/restrict-content/subscribe.php @@ -13,14 +13,9 @@
-

restrict_content_settings->get_by_key( 'subscribe_heading_tag' ) ); ?>

-

- restrict_content_settings->get_by_key( 'subscribe_text_tag' ) ) as $text_line ) { - echo esc_html( $text_line ) . '
'; - } - ?> -

+
From 67c7dea1144d8d840dfd35dcd3a707a2d35310fd Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Thu, 23 Jan 2025 17:12:09 +0800 Subject: [PATCH 2/9] Tags: Get heading and text --- includes/class-convertkit-output-restrict-content.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/includes/class-convertkit-output-restrict-content.php b/includes/class-convertkit-output-restrict-content.php index 82487a49f..ef4f0d94a 100644 --- a/includes/class-convertkit-output-restrict-content.php +++ b/includes/class-convertkit-output-restrict-content.php @@ -1199,6 +1199,10 @@ function () { return trim( ob_get_clean() ); case 'tag': + // Get header and text from settings for Tags. + $heading = $this->restrict_content_settings->get_by_key( 'subscribe_heading_tag' ); + $text = $this->restrict_content_settings->get_by_key( 'subscribe_text_tag' ); + // If require login is enabled, show the login screen. if ( $this->restrict_content_settings->require_login_for_tags() ) { // If scripts are enabled, output the email login form in a modal, which will be displayed @@ -1214,10 +1218,6 @@ function () { ); } - // Get header and text from settings for Tags. - $heading = $this->restrict_content_settings->get_by_key( 'subscribe_heading_tag' ); - $text = $this->restrict_content_settings->get_by_key( 'subscribe_text_tag' ); - // Output. ob_start(); include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/login.php'; From d491e4c2ad40a65ad76b795ddea0b1225cccbb7d Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Thu, 23 Jan 2025 21:58:52 +0800 Subject: [PATCH 3/9] WIP --- ...ertkit-admin-settings-restrict-content.php | 91 ++++++++++-- .../class-convertkit-settings-general.php | 2 +- .../class-convertkit-block-form-trigger.php | 110 ++------------- ...ass-convertkit-output-restrict-content.php | 13 +- includes/class-convertkit-resource-forms.php | 131 +++++++++++++++++- ...s-convertkit-settings-restrict-content.php | 34 ++++- 6 files changed, 261 insertions(+), 120 deletions(-) diff --git a/admin/class-convertkit-admin-settings-restrict-content.php b/admin/class-convertkit-admin-settings-restrict-content.php index c19ecd709..838ebdd05 100644 --- a/admin/class-convertkit-admin-settings-restrict-content.php +++ b/admin/class-convertkit-admin-settings-restrict-content.php @@ -14,6 +14,15 @@ */ class ConvertKit_Admin_Settings_Restrict_Content extends ConvertKit_Settings_Base { + /** + * Holds the ConvertKit Forms Resource. + * + * @since 2.7.2 + * + * @var bool|ConvertKit_Resource_Forms + */ + private $forms = false; + /** * Constructor. * @@ -131,14 +140,30 @@ public function register_fields() { ); add_settings_field( - 'require_login_for_tags', - __( 'Require Login', 'convertkit' ), - array( $this, 'require_login_for_tags_callback' ), + 'subscribe_tag_method', + __( 'Method', 'convertkit' ), + array( $this, 'subscribe_tag_method_callback' ), + $this->settings_key, + $this->name . '-tags', + array( + 'name' => 'subscribe_tag_method', + 'label_for' => 'subscribe_tag_method', + 'label' => __( 'When enabled, subscribers enter their email to receive a login link to access the member-only content.', 'convertkit' ), + 'description' => array( + __( 'If unchecked, subscribers are immediately subscribed to the tag and granted access when entering their email address.', 'convertkit' ), + ), + ) + ); + + add_settings_field( + 'subscribe_tag_form', + __( 'Form', 'convertkit' ), + array( $this, 'subscribe_tag_form_callback' ), $this->settings_key, $this->name . '-tags', array( - 'name' => 'require_login_for_tags', - 'label_for' => 'require_login_for_tags', + 'name' => 'subscribe_tag_form', + 'label_for' => 'subscribe_tag_form', 'label' => __( 'When enabled, subscribers enter their email to receive a login link to access the member-only content.', 'convertkit' ), 'description' => array( __( 'If unchecked, subscribers are immediately subscribed to the tag and granted access when entering their email address.', 'convertkit' ), @@ -426,17 +451,61 @@ public function permit_crawlers_callback( $args ) { * * @param array $args Setting field arguments (name,description). */ - public function require_login_for_tags_callback( $args ) { + public function subscribe_tag_method_callback( $args ) { // Output field. - echo $this->get_checkbox_field( // phpcs:ignore WordPress.Security.EscapeOutput + echo $this->get_select_field( $args['name'], - 'on', - $this->settings->require_login_for_tags(), // phpcs:ignore WordPress.Security.EscapeOutput - $args['label'], // phpcs:ignore WordPress.Security.EscapeOutput - $args['description'] // phpcs:ignore WordPress.Security.EscapeOutput + $this->settings->subscribe_tag_method(), + array( + '' => __( 'Instant confirmation and tagging', 'convertkit' ), + 'login' => __( 'Sign up using Kit Form, enter email to receive login link (Recommended)', 'convertkit' ), + ), + $args['description'], + array( + 'enabled', + 'widefat', + ) + ); + + } + + /** + * Renders the input for the Subscribe Form setting. + * + * @since 2.7.2 + * + * @param array $args Field arguments. + */ + public function subscribe_tag_form_callback( $args ) { + + // Initialize forms resource class. + $this->forms = new ConvertKit_Resource_Forms( 'settings' ); + + // Bail if no non-inline Forms exist. + if ( ! $this->forms->non_inline_exist() ) { + esc_html_e( 'No non-inline Forms exist in Kit.', 'convertkit' ); + echo '
' . esc_html__( 'Click here to create your first modal, slide in or sticky bar form', 'convertkit' ) . ''; + return; + } + + // Build field. + $select_field = $this->forms->get_select_field_non_inline( + '_wp_convertkit_settings_restrict_content[' . $args['name'] . ']', + $args['name'], + array( + 'convertkit-select2', + 'convertkit-preview-output-link', + ), + $this->settings->subscribe_tag_form(), + false, + false, + esc_html__( 'Select the non-inline modal, slide in or sticky bar form to display when the visitor clicks the subscribe button.', 'convertkit' ) ); + // Output field. + echo '
' . $select_field . '
'; // phpcs:ignore WordPress.Security.EscapeOutput + } /** diff --git a/admin/section/class-convertkit-settings-general.php b/admin/section/class-convertkit-settings-general.php index 146114a6b..c74f90a39 100644 --- a/admin/section/class-convertkit-settings-general.php +++ b/admin/section/class-convertkit-settings-general.php @@ -691,7 +691,7 @@ public function non_inline_form_callback( $args ) { ); // Build field. - $select_field = $this->forms->get_select_field_non_inline( + $select_field = $this->forms->get_multi_select_field_non_inline( $this->settings_key . '[non_inline_form]', $this->settings_key . '_non_inline_form', array( diff --git a/includes/blocks/class-convertkit-block-form-trigger.php b/includes/blocks/class-convertkit-block-form-trigger.php index 8851e3935..d17f9fe1b 100644 --- a/includes/blocks/class-convertkit-block-form-trigger.php +++ b/includes/blocks/class-convertkit-block-form-trigger.php @@ -372,11 +372,18 @@ public function render( $atts ) { // and moving some attributes (such as Gutenberg's styles), if defined. $atts = $this->sanitize_and_declare_atts( $atts ); - // Setup Settings class. + // Load classes. $settings = new ConvertKit_Settings(); + $convertkit_forms = new ConvertKit_Resource_Forms( 'render' ); - // Build HTML. - $html = $this->get_html( $atts['form'], $atts['text'], $atts['_css_classes'], $atts['_css_styles'], $this->is_block_editor_request() ); + // Build button HTML. + $html = $convertkit_forms->get_button_html( + $atts['form'], + $atts['text'], + $atts['_css_classes'], + $atts['_css_styles'], + $this->is_block_editor_request() + ); // Bail if an error occured. if ( is_wp_error( $html ) ) { @@ -401,101 +408,4 @@ public function render( $atts ) { } - /** - * Returns the HTML button markup for the given Form ID. - * - * @since 2.0.0 - * - * @param int $id Form ID. - * @param string $button_text Button Text. - * @param array $css_classes CSS classes to apply to link (typically included when using Gutenberg). - * @param array $css_styles CSS inline styles to apply to link (typically included when using Gutenberg). - * @param bool $return_as_span If true, returns a instead of . Useful for the block editor so that the element is interactible. - * @return WP_Error|string Button HTML - */ - private function get_html( $id, $button_text, $css_classes = array(), $css_styles = array(), $return_as_span = false ) { - - // Cast ID to integer. - $id = absint( $id ); - - // Load classes. - $convertkit_forms = new ConvertKit_Resource_Forms( 'render' ); - - // Get form. - $form = $convertkit_forms->get_by_id( $id ); - - // Bail if the form could not be found. - if ( ! $form ) { - return new WP_Error( - 'convertkit_block_form_trigger_get_html', - sprintf( - /* translators: ConvertKit Form ID */ - __( 'Kit Form ID %s does not exist on Kit.', 'convertkit' ), - $id - ) - ); - } - - // Bail if no uid or embed_js properties exist. - if ( ! array_key_exists( 'uid', $form ) ) { - return new WP_Error( - 'convertkit_block_form_trigger_get_html', - sprintf( - /* translators: ConvertKit Form ID */ - __( 'Kit Form ID %s has no uid property.', 'convertkit' ), - $id - ) - ); - } - if ( ! array_key_exists( 'embed_js', $form ) ) { - return new WP_Error( - 'convertkit_block_form_trigger_get_html', - sprintf( - /* translators: ConvertKit Form ID */ - __( 'Kit Form ID %s has no embed_js property.', 'convertkit' ), - $id - ) - ); - } - - // Build button HTML. - $html = ''; - - // Register the script, so it's only loaded once for this non-inline form across the entire page. - add_filter( - 'convertkit_output_scripts_footer', - function ( $scripts ) use ( $form ) { - - $scripts[] = array( - 'async' => true, - 'data-uid' => $form['uid'], - 'src' => $form['embed_js'], - ); - - return $scripts; - - } - ); - - // Return. - return $html; - } - } diff --git a/includes/class-convertkit-output-restrict-content.php b/includes/class-convertkit-output-restrict-content.php index ef4f0d94a..6e6076178 100644 --- a/includes/class-convertkit-output-restrict-content.php +++ b/includes/class-convertkit-output-restrict-content.php @@ -208,7 +208,7 @@ public function maybe_run_subscriber_authentication() { case 'tag': // If require login is enabled, show the login screen. - if ( $this->restrict_content_settings->require_login_for_tags() ) { + if ( $this->restrict_content_settings->subscribe_tag_require_login() ) { // Send email to subscriber with a link to authenticate they have access to the email address submitted. $result = $this->api->subscriber_authentication_send_code( $email, @@ -1204,7 +1204,7 @@ function () { $text = $this->restrict_content_settings->get_by_key( 'subscribe_text_tag' ); // If require login is enabled, show the login screen. - if ( $this->restrict_content_settings->require_login_for_tags() ) { + if ( $this->restrict_content_settings->subscribe_tag_require_login() ) { // If scripts are enabled, output the email login form in a modal, which will be displayed // when the 'log in' link is clicked. if ( ! $this->settings->scripts_disabled() ) { @@ -1218,6 +1218,15 @@ function () { ); } + // Define button if a Form is selected. + if ( ! empty( $this->restrict_content_settings->subscribe_tag_form() ) ) { + $forms = new ConvertKit_Resource_Forms( 'output_form' ); + $button = $forms->get_button_html( + $this->restrict_content_settings->subscribe_tag_form(), + $this->restrict_content_settings->get_by_key( 'subscribe_button_label' ) + ); + } + // Output. ob_start(); include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/login.php'; diff --git a/includes/class-convertkit-resource-forms.php b/includes/class-convertkit-resource-forms.php index 84466858c..6a4a11801 100644 --- a/includes/class-convertkit-resource-forms.php +++ b/includes/class-convertkit-resource-forms.php @@ -150,9 +150,10 @@ public function get_select_field_all( $name, $id, $css_classes, $selected_option } /** - * Returns a field populated with all non-inline forms, based on the given parameters, + * that supports multiple selection. * - * @since 2.3.9 + * @since 2.7.1 * * @param string $name Name. * @param string $id ID. @@ -163,7 +164,7 @@ public function get_select_field_all( $name, $id, $css_classes, $selected_option * @param bool|string|array $description Description. * @return string HTML Select Field */ - public function get_select_field_non_inline( $name, $id, $css_classes, $selected_options, $prepend_options = false, $attributes = false, $description = false ) { + public function get_multi_select_field_non_inline( $name, $id, $css_classes, $selected_options, $prepend_options = false, $attributes = false, $description = false ) { return $this->get_multi_select_field( $this->get_non_inline(), @@ -178,6 +179,35 @@ public function get_select_field_non_inline( $name, $id, $css_classes, $selected } + /** + * Returns a CSS class(es). + * @param string $selected_option
From 43d53eedbb38fe5c1d87a0ad95e50853c1d5251b Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Thu, 23 Jan 2025 22:45:29 +0800 Subject: [PATCH 5/9] Fix incorrect login script --- ...ass-convertkit-output-restrict-content.php | 33 ++++++++----------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/includes/class-convertkit-output-restrict-content.php b/includes/class-convertkit-output-restrict-content.php index 1356c3689..a769470d7 100644 --- a/includes/class-convertkit-output-restrict-content.php +++ b/includes/class-convertkit-output-restrict-content.php @@ -1183,6 +1183,10 @@ private function get_call_to_action( $post_id ) { // phpcs:ignore Generic.CodeAn // for restrict by tag and form later. switch ( $this->resource_type ) { case 'product': + // Get header and text from settings for Products. + $heading = $this->restrict_content_settings->get_by_key( 'subscribe_heading' ); + $text = $this->restrict_content_settings->get_by_key( 'subscribe_text' ); + // Output product restricted message and email form. // Get Product. $products = new ConvertKit_Resource_Products( 'restrict_content' ); @@ -1207,14 +1211,10 @@ function () { ); } - // Get header and text from settings for Products. - $heading = $this->restrict_content_settings->get_by_key( 'subscribe_heading' ); - $text = $this->restrict_content_settings->get_by_key( 'subscribe_text' ); - // Output. ob_start(); $button = $products->get_html( $this->resource_id, $this->restrict_content_settings->get_by_key( 'subscribe_button_label' ) ); - include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/login.php'; + include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/product.php'; return trim( ob_get_clean() ); case 'tag': @@ -1222,24 +1222,19 @@ function () { $heading = $this->restrict_content_settings->get_by_key( 'subscribe_heading_tag' ); $text = $this->restrict_content_settings->get_by_key( 'subscribe_text_tag' ); - // If require login is enabled, show the login screen. - if ( $this->restrict_content_settings->subscribe_tag_require_login() ) { - // If scripts are enabled, output the email login form in a modal, which will be displayed - // when the 'log in' link is clicked. - if ( ! $this->settings->scripts_disabled() ) { - add_action( - 'wp_footer', - function () { + // If require login is enabled and scripts are enabled, output the email login form in a modal, which will be displayed + // when the 'log in' link is clicked. + if ( $this->restrict_content_settings->subscribe_tag_require_login() && ! $this->settings->scripts_disabled() ) { + add_action( + 'wp_footer', + function () { - include_once CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/login-modal.php'; + include_once CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/login-modal.php'; - } - ); - } + } + ); } - // If here, no login required. - // Users can enter their email to immediately subscribe to the tag and gain access. // Enqueue Google reCAPTCHA JS if site and secret keys specified. if ( $this->restrict_content_settings->has_recaptcha_site_and_secret_keys() ) { add_filter( From 519c8ac8259f7274e7a28d2b2696310202424c1c Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Thu, 23 Jan 2025 22:46:23 +0800 Subject: [PATCH 6/9] Revert form changes --- .../class-convertkit-block-form-trigger.php | 110 +++++++++++++-- includes/class-convertkit-resource-forms.php | 131 +----------------- 2 files changed, 103 insertions(+), 138 deletions(-) diff --git a/includes/blocks/class-convertkit-block-form-trigger.php b/includes/blocks/class-convertkit-block-form-trigger.php index d17f9fe1b..8851e3935 100644 --- a/includes/blocks/class-convertkit-block-form-trigger.php +++ b/includes/blocks/class-convertkit-block-form-trigger.php @@ -372,18 +372,11 @@ public function render( $atts ) { // and moving some attributes (such as Gutenberg's styles), if defined. $atts = $this->sanitize_and_declare_atts( $atts ); - // Load classes. + // Setup Settings class. $settings = new ConvertKit_Settings(); - $convertkit_forms = new ConvertKit_Resource_Forms( 'render' ); - // Build button HTML. - $html = $convertkit_forms->get_button_html( - $atts['form'], - $atts['text'], - $atts['_css_classes'], - $atts['_css_styles'], - $this->is_block_editor_request() - ); + // Build HTML. + $html = $this->get_html( $atts['form'], $atts['text'], $atts['_css_classes'], $atts['_css_styles'], $this->is_block_editor_request() ); // Bail if an error occured. if ( is_wp_error( $html ) ) { @@ -408,4 +401,101 @@ public function render( $atts ) { } + /** + * Returns the HTML button markup for the given Form ID. + * + * @since 2.0.0 + * + * @param int $id Form ID. + * @param string $button_text Button Text. + * @param array $css_classes CSS classes to apply to link (typically included when using Gutenberg). + * @param array $css_styles CSS inline styles to apply to link (typically included when using Gutenberg). + * @param bool $return_as_span If true, returns a instead of . Useful for the block editor so that the element is interactible. + * @return WP_Error|string Button HTML + */ + private function get_html( $id, $button_text, $css_classes = array(), $css_styles = array(), $return_as_span = false ) { + + // Cast ID to integer. + $id = absint( $id ); + + // Load classes. + $convertkit_forms = new ConvertKit_Resource_Forms( 'render' ); + + // Get form. + $form = $convertkit_forms->get_by_id( $id ); + + // Bail if the form could not be found. + if ( ! $form ) { + return new WP_Error( + 'convertkit_block_form_trigger_get_html', + sprintf( + /* translators: ConvertKit Form ID */ + __( 'Kit Form ID %s does not exist on Kit.', 'convertkit' ), + $id + ) + ); + } + + // Bail if no uid or embed_js properties exist. + if ( ! array_key_exists( 'uid', $form ) ) { + return new WP_Error( + 'convertkit_block_form_trigger_get_html', + sprintf( + /* translators: ConvertKit Form ID */ + __( 'Kit Form ID %s has no uid property.', 'convertkit' ), + $id + ) + ); + } + if ( ! array_key_exists( 'embed_js', $form ) ) { + return new WP_Error( + 'convertkit_block_form_trigger_get_html', + sprintf( + /* translators: ConvertKit Form ID */ + __( 'Kit Form ID %s has no embed_js property.', 'convertkit' ), + $id + ) + ); + } + + // Build button HTML. + $html = ''; + + // Register the script, so it's only loaded once for this non-inline form across the entire page. + add_filter( + 'convertkit_output_scripts_footer', + function ( $scripts ) use ( $form ) { + + $scripts[] = array( + 'async' => true, + 'data-uid' => $form['uid'], + 'src' => $form['embed_js'], + ); + + return $scripts; + + } + ); + + // Return. + return $html; + } + } diff --git a/includes/class-convertkit-resource-forms.php b/includes/class-convertkit-resource-forms.php index 6a4a11801..84466858c 100644 --- a/includes/class-convertkit-resource-forms.php +++ b/includes/class-convertkit-resource-forms.php @@ -150,10 +150,9 @@ public function get_select_field_all( $name, $id, $css_classes, $selected_option } /** - * Returns a field populated with all non-inline forms, based on the given parameters. * - * @since 2.7.1 + * @since 2.3.9 * * @param string $name Name. * @param string $id ID. @@ -164,7 +163,7 @@ public function get_select_field_all( $name, $id, $css_classes, $selected_option * @param bool|string|array $description Description. * @return string HTML Select Field */ - public function get_multi_select_field_non_inline( $name, $id, $css_classes, $selected_options, $prepend_options = false, $attributes = false, $description = false ) { + public function get_select_field_non_inline( $name, $id, $css_classes, $selected_options, $prepend_options = false, $attributes = false, $description = false ) { return $this->get_multi_select_field( $this->get_non_inline(), @@ -179,35 +178,6 @@ public function get_multi_select_field_non_inline( $name, $id, $css_classes, $se } - /** - * Returns a CSS class(es). - * @param string $selected_option