diff --git a/.env.example b/.env.example index d2b260095..6f185284e 100644 --- a/.env.example +++ b/.env.example @@ -24,6 +24,8 @@ CONVERTKIT_API_KEY= CONVERTKIT_API_SECRET= CONVERTKIT_API_SIGNED_SUBSCRIBER_ID= CONVERTKIT_API_SIGNED_SUBSCRIBER_ID_NO_ACCESS= +CONVERTKIT_API_RECAPTCHA_SITE_KEY= +CONVERTKIT_API_RECAPTCHA_SECRET_KEY= CONVERTKIT_API_FORM_NAME="Page Form [inline]" CONVERTKIT_API_FORM_ID="2765139" CONVERTKIT_API_FORM_FORMAT_MODAL_NAME="Modal Form [modal]" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9732e7d84..9f8f97906 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -46,6 +46,8 @@ jobs: KIT_OAUTH_REDIRECT_URI: ${{ secrets.KIT_OAUTH_REDIRECT_URI }} CONVERTKIT_API_SIGNED_SUBSCRIBER_ID: ${{ secrets.CONVERTKIT_API_SIGNED_SUBSCRIBER_ID }} # ConvertKit API Signed Subscriber ID, stored in the repository's Settings > Secrets CONVERTKIT_API_SIGNED_SUBSCRIBER_ID_NO_ACCESS: ${{ secrets.CONVERTKIT_API_SIGNED_SUBSCRIBER_ID_NO_ACCESS }} # ConvertKit API Signed Subscriber ID with no access to Products, stored in the repository's Settings > Secrets + CONVERTKIT_API_RECAPTCHA_SITE_KEY: ${{ secrets.CONVERTKIT_API_RECAPTCHA_SITE_KEY }} # Google reCAPTCHA v3 Site Key, stored in the repository's Settings > Secrets + CONVERTKIT_API_RECAPTCHA_SECRET_KEY: ${{ secrets.CONVERTKIT_API_RECAPTCHA_SECRET_KEY }} # Google reCAPTCHA v3 Secret Key, stored in the repository's Settings > Secrets # Defines the WordPress and PHP Versions matrix to run tests on # WooCommerce 5.9.0 requires WordPress 5.6 or greater, so we do not test on earlier versions @@ -218,6 +220,9 @@ jobs: KIT_OAUTH_REDIRECT_URI=${{ env.KIT_OAUTH_REDIRECT_URI }} CONVERTKIT_API_SIGNED_SUBSCRIBER_ID=${{ env.CONVERTKIT_API_SIGNED_SUBSCRIBER_ID }} CONVERTKIT_API_SIGNED_SUBSCRIBER_ID_NO_ACCESS=${{ env.CONVERTKIT_API_SIGNED_SUBSCRIBER_ID_NO_ACCESS }} + CONVERTKIT_API_RECAPTCHA_SITE_KEY=${{ env.CONVERTKIT_API_RECAPTCHA_SITE_KEY }} + CONVERTKIT_API_RECAPTCHA_SECRET_KEY=${{ env.CONVERTKIT_API_RECAPTCHA_SECRET_KEY }} + write-mode: append # Installs wp-browser, Codeception, PHP CodeSniffer and anything else needed to run tests. diff --git a/admin/class-convertkit-admin-settings-restrict-content.php b/admin/class-convertkit-admin-settings-restrict-content.php index fbaee9b03..36ca211fe 100644 --- a/admin/class-convertkit-admin-settings-restrict-content.php +++ b/admin/class-convertkit-admin-settings-restrict-content.php @@ -80,6 +80,53 @@ public function register_fields() { ) ); + // reCAPTCHA. + add_settings_field( + 'recaptcha_site_key', + __( 'reCAPTCHA: Site Key', 'convertkit' ), + array( $this, 'text_callback' ), + $this->settings_key, + $this->name, + array( + 'name' => 'recaptcha_site_key', + 'label_for' => 'recaptcha_site_key', + 'description' => array( + __( 'Enter your Google reCAPTCHA v3 Site Key. When specified, this will be used in Member Content by Tag functionality to reduce spam signups.', 'convertkit' ), + ), + ) + ); + add_settings_field( + 'recaptcha_secret_key', + __( 'reCAPTCHA: Secret Key', 'convertkit' ), + array( $this, 'text_callback' ), + $this->settings_key, + $this->name, + array( + 'name' => 'recaptcha_secret_key', + 'label_for' => 'recaptcha_secret_key', + 'description' => array( + __( 'Enter your Google reCAPTCHA v3 Secret Key. When specified, this will be used in Member Content by Tag functionality to reduce spam signups.', 'convertkit' ), + ), + ) + ); + add_settings_field( + 'recaptcha_minimum_score', + __( 'reCAPTCHA: Minimum Score', 'convertkit' ), + array( $this, 'number_callback' ), + $this->settings_key, + $this->name, + array( + 'name' => 'recaptcha_minimum_score', + 'label_for' => 'recaptcha_minimum_score', + 'min' => 0, + 'max' => 1, + 'step' => 0.01, + 'description' => array( + __( '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' ), + ), + ) + ); + // Restrict by Product. add_settings_field( 'subscribe_heading', @@ -345,6 +392,29 @@ public function text_callback( $args ) { } + /** + * Renders the input for the decimal setting. + * + * @since 2.6.8 + * + * @param array $args Setting field arguments (name,description). + */ + public function number_callback( $args ) { + + echo $this->get_number_field( // phpcs:ignore WordPress.Security.EscapeOutput + $args['name'], + esc_attr( $this->settings->get_by_key( $args['name'] ) ), + $args['min'], // phpcs:ignore WordPress.Security.EscapeOutput + $args['max'], // phpcs:ignore WordPress.Security.EscapeOutput + $args['step'], // phpcs:ignore WordPress.Security.EscapeOutput + $args['description'], // phpcs:ignore WordPress.Security.EscapeOutput + array( + 'widefat', + ) + ); + + } + /** * Renders the input for the textarea setting. * diff --git a/admin/section/class-convertkit-settings-base.php b/admin/section/class-convertkit-settings-base.php index bb1923d56..e3adc8d00 100644 --- a/admin/section/class-convertkit-settings-base.php +++ b/admin/section/class-convertkit-settings-base.php @@ -443,9 +443,9 @@ public function get_text_field( $name, $value = '', $description = false, $css_c * * @param string $name Name. * @param string $value Value. - * @param int $min `min` attribute value. - * @param int $max `max` attribute value. - * @param int $step `step` attribute value. + * @param int|float $min `min` attribute value. + * @param int|float $max `max` attribute value. + * @param int|float $step `step` attribute value. * @param bool|string|array $description Description (false|string|array). * @param bool|array $css_classes CSS Classes (false|array). * @return string HTML Field diff --git a/includes/class-convertkit-output-restrict-content.php b/includes/class-convertkit-output-restrict-content.php index 30ac4f108..86defd3d4 100644 --- a/includes/class-convertkit-output-restrict-content.php +++ b/includes/class-convertkit-output-restrict-content.php @@ -207,6 +207,61 @@ public function maybe_run_subscriber_authentication() { break; case 'tag': + // 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( + 'https://www.google.com/recaptcha/api/siteverify', + array( + 'body' => array( + 'secret' => $this->restrict_content_settings->get_recaptcha_secret_key(), + 'response' => $_POST['g-recaptcha-response'], + 'remoteip' => $_SERVER['REMOTE_ADDR'], + ), + ) + ); + + // Bail if an error occured. + if ( is_wp_error( $response ) ) { + $this->error = $response; + return; + } + + // Inspect response. + $body = json_decode( wp_remote_retrieve_body( $response ), true ); + + // If the request wasn't successful, throw an error. + if ( ! $body['success'] ) { + $this->error = new WP_Error( + 'convertkit_output_restrict_content_maybe_run_subscriber_authentication_error', + sprintf( + /* translators: Error codes */ + __( 'Google reCAPTCHA failure: %s', 'convertkit' ), + implode( ', ', $body['error-codes'] ) + ) + ); + return; + } + + // If the action doesn't match the Plugin action, this might not be a reCAPTCHA request + // for this Plugin. + if ( $body['action'] !== 'convertkit_restrict_content_tag' ) { + // Just silently return. + return; + } + + // If the score is less than 0.5 (on a scale of 0.0 to 1.0, with 0.0 being a bot, 1.0 being very good), + // it's likely a spam submission. + if ( $body['score'] < $this->restrict_content_settings->get_recaptcha_minimum_score() ) { + $this->error = new WP_Error( + 'convertkit_output_restrict_content_maybe_run_subscriber_authentication_error', + __( 'Google reCAPTCHA failed', 'convertkit' ) + ); + return; + } + + // If here, the submission looks genuine. Continue the request. + } + // Tag the subscriber. $result = $this->api->tag_subscribe( $this->resource_id, $email ); @@ -1051,6 +1106,22 @@ function () { return trim( ob_get_clean() ); case 'tag': + // Enqueue Google reCAPTCHA JS if site and secret keys specified. + if ( $this->restrict_content_settings->has_recaptcha_site_and_secret_keys() ) { + add_filter( + 'convertkit_output_scripts_footer', + function ( $scripts ) { + + $scripts[] = array( + 'src' => 'https://www.google.com/recaptcha/api.js?', + ); + + return $scripts; + + } + ); + } + // Output. ob_start(); include CONVERTKIT_PLUGIN_PATH . '/views/frontend/restrict-content/tag.php'; diff --git a/includes/class-convertkit-settings-restrict-content.php b/includes/class-convertkit-settings-restrict-content.php index ffa1bf836..9d1071f69 100644 --- a/includes/class-convertkit-settings-restrict-content.php +++ b/includes/class-convertkit-settings-restrict-content.php @@ -77,6 +77,85 @@ public function permit_crawlers() { } + /** + * Returns the reCAPTCHA Site Key Plugin setting. + * + * @since 2.6.8 + * + * @return string + */ + public function get_recaptcha_site_key() { + + return $this->settings['recaptcha_site_key']; + + } + + /** + * Returns whether the reCAPTCHA Site Key has been set in the Plugin settings. + * + * @since 2.6.8 + * + * @return bool + */ + public function has_recaptcha_site_key() { + + return ! empty( $this->get_recaptcha_site_key() ); + + } + + /** + * Returns the reCAPTCHA Secret Key Plugin setting. + * + * @since 2.6.8 + * + * @return string + */ + public function get_recaptcha_secret_key() { + + return $this->settings['recaptcha_secret_key']; + + } + + /** + * Returns whether the reCAPTCHA Secret Key has been set in the Plugin settings. + * + * @since 2.6.8 + * + * @return bool + */ + public function has_recaptcha_secret_key() { + + return ! empty( $this->get_recaptcha_secret_key() ); + + } + + /** + * Returns whether the reCAPTCH Site Key and Secret Key are defined + * in the Plugin settings. + * + * @since 2.6.8 + * + * @return bool + */ + public function has_recaptcha_site_and_secret_keys() { + + return $this->get_recaptcha_site_key() && $this->has_recaptcha_secret_key(); + + } + + /** + * Returns the reCAPTCHA minimum score Plugin setting. + * + * @since 2.6.8 + * + * @return float + */ + public function get_recaptcha_minimum_score() { + + return (float) $this->settings['recaptcha_minimum_score']; + + } + /** * Returns Restrict Content settings value for the given key. * @@ -114,25 +193,30 @@ public function get_defaults() { $defaults = array( // Permit Crawlers. - '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' ), + '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' ), // 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' ), + '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' ), // All. - 'subscribe_button_label' => __( 'Subscribe', 'convertkit' ), - 'email_text' => __( 'Already subscribed?', 'convertkit' ), - 'email_button_label' => __( 'Log in', 'convertkit' ), - 'email_heading' => __( 'Log in to read this post', 'convertkit' ), - 'email_description_text' => __( 'We\'ll email you a magic code to log you in without a password.', 'convertkit' ), - 'email_check_heading' => __( 'We just emailed you a log in code', 'convertkit' ), - 'email_check_text' => __( 'Enter the code below to finish logging in', 'convertkit' ), - 'no_access_text' => __( 'Your account does not have access to this content. Please use the button above to purchase, or enter the email address you used to purchase the product.', 'convertkit' ), + 'subscribe_button_label' => __( 'Subscribe', 'convertkit' ), + 'email_text' => __( 'Already subscribed?', 'convertkit' ), + 'email_button_label' => __( 'Log in', 'convertkit' ), + 'email_heading' => __( 'Log in to read this post', 'convertkit' ), + 'email_description_text' => __( 'We\'ll email you a magic code to log you in without a password.', 'convertkit' ), + 'email_check_heading' => __( 'We just emailed you a log in code', 'convertkit' ), + 'email_check_text' => __( 'Enter the code below to finish logging in', 'convertkit' ), + 'no_access_text' => __( 'Your account does not have access to this content. Please use the button above to purchase, or enter the email address you used to purchase the product.', 'convertkit' ), ); /** diff --git a/resources/frontend/js/restrict-content.js b/resources/frontend/js/restrict-content.js index 98019aaab..d9ab7dceb 100644 --- a/resources/frontend/js/restrict-content.js +++ b/resources/frontend/js/restrict-content.js @@ -58,6 +58,13 @@ document.addEventListener( } ); +function convertKitRestrictContentTagFormSubmit( token ) { + + console.log( token ); + document.getElementById( 'convertkit-restrict-content-form' ).submit(); + +} + /** * Handles Restrict Content form submission. * diff --git a/tests/_support/Helper/Acceptance/ConvertKitRestrictContent.php b/tests/_support/Helper/Acceptance/ConvertKitRestrictContent.php index 3221cf19f..ca9481254 100644 --- a/tests/_support/Helper/Acceptance/ConvertKitRestrictContent.php +++ b/tests/_support/Helper/Acceptance/ConvertKitRestrictContent.php @@ -54,24 +54,27 @@ public function getRestrictedContentDefaultSettings() { return array( // Permit Crawlers. - 'permit_crawlers' => '', + 'permit_crawlers' => '', + 'recaptcha_site_key' => '', + 'recaptcha_secret_key' => '', + 'recaptcha_minimum_score' => '0.5', // Restrict by Product. - 'subscribe_heading' => 'Read this post with a premium subscription', - 'subscribe_text' => 'This post is only available to premium subscribers. Join today to get access to all posts.', + 'subscribe_heading' => 'Read this post with a premium subscription', + 'subscribe_text' => 'This post is only available to premium subscribers. Join today to get access to all posts.', // Restrict by Tag. - 'subscribe_heading_tag' => 'Subscribe to keep reading', - 'subscribe_text_tag' => 'This post is free to read but only available to subscribers. Join today to get access to all posts.', + 'subscribe_heading_tag' => 'Subscribe to keep reading', + 'subscribe_text_tag' => 'This post is free to read but only available to subscribers. Join today to get access to all posts.', // All. - 'subscribe_button_label' => 'Subscribe', - 'email_text' => 'Already subscribed?', - 'email_button_label' => 'Log in', - 'email_description_text' => 'We\'ll email you a magic code to log you in without a password.', - 'email_check_heading' => 'We just emailed you a log in code', - 'email_check_text' => 'Enter the code below to finish logging in', - 'no_access_text' => 'Your account does not have access to this content. Please use the button above to purchase, or enter the email address you used to purchase the product.', + 'subscribe_button_label' => 'Subscribe', + 'email_text' => 'Already subscribed?', + 'email_button_label' => 'Log in', + 'email_description_text' => 'We\'ll email you a magic code to log you in without a password.', + 'email_check_heading' => 'We just emailed you a log in code', + 'email_check_text' => 'Enter the code below to finish logging in', + 'no_access_text' => 'Your account does not have access to this content. Please use the button above to purchase, or enter the email address you used to purchase the product.', ); } @@ -95,6 +98,14 @@ public function checkRestrictContentSettings($I, $settings) } break; + case 'recaptcha_minimum_score': + if ( $value ) { + $I->seeInField('_wp_convertkit_settings_restrict_content[' . $key . ']', $value); + } else { + $I->seeInField('_wp_convertkit_settings_restrict_content[' . $key . ']', '0.5'); + } + break; + default: $I->seeInField('_wp_convertkit_settings_restrict_content[' . $key . ']', $value); break; @@ -341,8 +352,9 @@ public function testRestrictedContentModalByProductOnFrontend($I, $urlOrPageID, * @type string $member_content Content that should only be available to authenticated subscribers. * @type array $text_items Expected text for subscribe text, subscribe button label, email text etc. If not defined, uses expected defaults. * } + * @param bool $recaptchaEnabled Whether the reCAPTCHA settings are enabled in the Plugin settings. */ - public function testRestrictedContentByTagOnFrontend($I, $urlOrPageID, $emailAddress, $options = false) + public function testRestrictedContentByTagOnFrontend($I, $urlOrPageID, $emailAddress, $options = false, $recaptchaEnabled = false) { // Merge options with defaults. $options = $this->_getRestrictedContentOptionsWithDefaultsMerged($options); @@ -372,14 +384,16 @@ public function testRestrictedContentByTagOnFrontend($I, $urlOrPageID, $emailAdd $I->seeElementInDOM('#convertkit-restrict-content'); $I->seeInSource('

' . $options['text_items']['subscribe_heading_tag'] . '

'); $I->see($options['text_items']['subscribe_text_tag']); - $I->seeInSource(''); + $I->seeInSource('fillField('convertkit_email', $emailAddress); $I->click('input.wp-block-button__link'); - // Check that no PHP warnings or notices were output. - $I->checkNoWarningsAndNoticesOnScreen($I); + // Wait for reCAPTCHA to fully load. + if ( $recaptchaEnabled ) { + $I->wait(3); + } // Confirm that the restricted content is now displayed. $I->testRestrictContentDisplaysContent($I, $options); @@ -462,7 +476,7 @@ public function testRestrictContentByProductHidesContentWithCTA($I, $options = f $I->seeInSource(''); + $I->seeInSource('seeInSource('' . $options['text_items']['email_description_text'] . ''); } diff --git a/tests/acceptance/restrict-content/general/RestrictContentSettingsCest.php b/tests/acceptance/restrict-content/general/RestrictContentSettingsCest.php index 95fc382ca..03bd1238b 100644 --- a/tests/acceptance/restrict-content/general/RestrictContentSettingsCest.php +++ b/tests/acceptance/restrict-content/general/RestrictContentSettingsCest.php @@ -82,25 +82,30 @@ public function testSaveBlankSettings(AcceptanceTester $I) // Define settings. $settings = array( // Permit Crawlers. - 'permit_crawlers' => '', + 'permit_crawlers' => '', + + // Google reCAPTCHA. + 'recaptcha_site_key' => '', + 'recaptcha_secret_key' => '', + 'recaptcha_minimum_score' => '', // Restrict by Product. - 'subscribe_heading' => '', - 'subscribe_text' => '', + 'subscribe_heading' => '', + 'subscribe_text' => '', // Restrict by Tag. - 'subscribe_heading_tag' => '', - 'subscribe_text_tag' => '', + 'subscribe_heading_tag' => '', + 'subscribe_text_tag' => '', // All. - 'subscribe_button_label' => '', - 'email_text' => '', - 'email_button_label' => '', - 'email_heading' => '', - 'email_description_text' => '', - 'email_check_heading' => '', - 'email_check_text' => '', - 'no_access_text' => '', + 'subscribe_button_label' => '', + 'email_text' => '', + 'email_button_label' => '', + 'email_heading' => '', + 'email_description_text' => '', + 'email_check_heading' => '', + 'email_check_text' => '', + 'no_access_text' => '', ); // Save settings. @@ -135,25 +140,30 @@ public function testSaveSettings(AcceptanceTester $I) // Define settings. $settings = array( // Permit Crawlers. - 'permit_crawlers' => true, + 'permit_crawlers' => true, + + // Google reCAPTCHA. + 'recaptcha_site_key' => 'reCAPTCHASiteKey', + 'recaptcha_secret_key' => 'reCAPTCHASecretKey', + 'recaptcha_minimum_score' => '0.8', // Restrict by Product. - 'subscribe_heading' => 'Subscribe Heading', - 'subscribe_text' => 'Subscribe Text', + 'subscribe_heading' => 'Subscribe Heading', + 'subscribe_text' => 'Subscribe Text', // Restrict by Tag. - 'subscribe_heading_tag' => 'Subscribe Heading Tag', - 'subscribe_text_tag' => 'Subscribe Text Tag', + 'subscribe_heading_tag' => 'Subscribe Heading Tag', + 'subscribe_text_tag' => 'Subscribe Text Tag', // All. - 'subscribe_button_label' => 'Subscribe Button Label', - 'email_text' => 'Email Text', - 'email_button_label' => 'Email Button Label', - 'email_heading' => 'Email Heading', - 'email_description_text' => 'Email Description Text', - 'email_check_heading' => 'Email Check Heading', - 'email_check_text' => 'Email Check Text', - 'no_access_text' => 'No Access Text', + 'subscribe_button_label' => 'Subscribe Button Label', + 'email_text' => 'Email Text', + 'email_button_label' => 'Email Button Label', + 'email_heading' => 'Email Heading', + 'email_description_text' => 'Email Description Text', + 'email_check_heading' => 'Email Check Heading', + 'email_check_text' => 'Email Check Text', + 'no_access_text' => 'No Access Text', ); // Save settings. diff --git a/tests/acceptance/restrict-content/general/RestrictContentTagCest.php b/tests/acceptance/restrict-content/general/RestrictContentTagCest.php index de68e1eee..8e3379e8f 100644 --- a/tests/acceptance/restrict-content/general/RestrictContentTagCest.php +++ b/tests/acceptance/restrict-content/general/RestrictContentTagCest.php @@ -84,6 +84,107 @@ public function testRestrictContentByInvalidTag(AcceptanceTester $I) $I->testRestrictContentDisplaysContent($I); } + /** + * Test that restricting content by a Tag specified in the Page Settings works when + * creating and viewing a new WordPress Page, with Google's reCAPTCHA enabled. + * + * @since 2.6.8 + * + * @param AcceptanceTester $I Tester. + */ + public function testRestrictContentByTagWithRecaptchaEnabled(AcceptanceTester $I) + { + // Setup Restrict Content functionality with reCAPTCHA enabled. + $I->setupConvertKitPluginRestrictContent( + $I, + [ + 'recaptcha_site_key' => $_ENV['CONVERTKIT_API_RECAPTCHA_SITE_KEY'], + 'recaptcha_secret_key' => $_ENV['CONVERTKIT_API_RECAPTCHA_SECRET_KEY'], + 'recaptcha_minimum_score' => '0.5', + ] + ); + + // Add a Page using the Gutenberg editor. + $I->addGutenbergPage($I, 'page', 'Kit: Page: Restrict Content: Tag: reCAPTCHA'); + + // Configure metabox's Restrict Content setting = Tag name. + $I->configureMetaboxSettings( + $I, + 'wp-convertkit-meta-box', + [ + 'form' => [ 'select2', 'None' ], + 'restrict_content' => [ 'select2', $_ENV['CONVERTKIT_API_TAG_NAME'] ], + ] + ); + + // Add blocks. + $I->addGutenbergParagraphBlock($I, 'Visible content.'); + $I->addGutenbergBlock($I, 'More', 'more'); + $I->addGutenbergParagraphBlock($I, 'Member-only content.'); + + // Publish Page. + $url = $I->publishGutenbergPage($I); + + // Test Restrict Content functionality. + $I->testRestrictedContentByTagOnFrontend($I, $url, $I->generateEmailAddress(), false, true); + } + + /** + * Test that restricting content by a Tag specified in the Page Settings works when + * creating and viewing a new WordPress Page, with Google's reCAPTCHA enabled. + * + * @since 2.6.8 + * + * @param AcceptanceTester $I Tester. + */ + public function testRestrictContentByTagWithRecaptchaEnabledWithHighMinimumScore(AcceptanceTester $I) + { + // Setup Restrict Content functionality with reCAPTCHA enabled. + $I->setupConvertKitPluginRestrictContent( + $I, + [ + 'recaptcha_site_key' => $_ENV['CONVERTKIT_API_RECAPTCHA_SITE_KEY'], + 'recaptcha_secret_key' => $_ENV['CONVERTKIT_API_RECAPTCHA_SECRET_KEY'], + 'recaptcha_minimum_score' => '0.99', // Set a high score to ensure reCAPTCHA blocks the subscriber. + ] + ); + + // Add a Page using the Gutenberg editor. + $I->addGutenbergPage($I, 'page', 'Kit: Page: Restrict Content: Tag: reCAPTCHA High Min Score'); + + // Configure metabox's Restrict Content setting = Tag name. + $I->configureMetaboxSettings( + $I, + 'wp-convertkit-meta-box', + [ + 'form' => [ 'select2', 'None' ], + 'restrict_content' => [ 'select2', $_ENV['CONVERTKIT_API_TAG_NAME'] ], + ] + ); + + // Add blocks. + $I->addGutenbergParagraphBlock($I, 'Visible content.'); + $I->addGutenbergBlock($I, 'More', 'more'); + $I->addGutenbergParagraphBlock($I, 'Member-only content.'); + + // Publish Page. + $url = $I->publishGutenbergPage($I); + + // Load page. + $I->amOnUrl($url); + + // Enter the email address and submit the form. + $I->fillField('convertkit_email', $I->generateEmailAddress()); + $I->click('input.wp-block-button__link'); + + // Wait for reCAPTCHA to fully load. + $I->wait(3); + + // Confirm an error message is displayed. + $I->waitForElementVisible('#convertkit-restrict-content'); + $I->seeInSource('
Google reCAPTCHA failed
'); + } + /** * Test that restricting content by a Tag specified in the Page Settings works when * using the Quick Edit functionality. diff --git a/views/frontend/restrict-content/tag.php b/views/frontend/restrict-content/tag.php index 10b1bf83b..50fa02867 100644 --- a/views/frontend/restrict-content/tag.php +++ b/views/frontend/restrict-content/tag.php @@ -25,7 +25,21 @@
- + restrict_content_settings->has_recaptcha_site_and_secret_keys() ) { + ?> + + + +