diff --git a/mailpoet/assets/js/src/public.jsx b/mailpoet/assets/js/src/public.jsx index 9fd8d810da..a4437c2dd7 100644 --- a/mailpoet/assets/js/src/public.jsx +++ b/mailpoet/assets/js/src/public.jsx @@ -77,6 +77,76 @@ jQuery(($) => { }); } + function submitSubscribeForm(form, formData, parsley) { + form.addClass('mailpoet_form_sending'); + // ajax request + MailPoet.Ajax.post({ + url: window.MailPoetForm.ajax_url, + token: formData.token, + api_version: formData.api_version, + endpoint: 'subscribers', + action: 'subscribe', + data: formData.data, + }) + .fail((response) => { + if ( + response.meta !== undefined && + response.meta.redirect_url !== undefined + ) { + // go to page + window.top.location.href = response.meta.redirect_url; + } else { + if (response.meta && response.meta.refresh_captcha) { + updateCaptcha(); + } + form + .find('.mailpoet_validate_error') + .html(response.errors.map((error) => error.message).join('
')) + .show(); + } + }) + .done((response) => { + if (window.grecaptcha && formData.recaptcha) { + window.grecaptcha.reset(formData.recaptcha); + } + return response; + }) + .done((response) => { + // successfully subscribed + if ( + response.meta !== undefined && + response.meta.redirect_url !== undefined + ) { + setFormCookieAfterSubscription(form); + // go to page + window.location.href = response.meta.redirect_url; + } else { + displaySuccessMessage(form); + } + + // reset form + form.trigger('reset'); + // reset validation + parsley.reset(); + // reset captcha + if (window.grecaptcha && formData.recaptcha) { + window.grecaptcha.reset(formData.recaptcha); + } + + // resize iframe + if ( + window.frameElement !== null && + MailPoet !== undefined && + MailPoet.Iframe + ) { + MailPoet.Iframe.autoSize(window.frameElement); + } + }) + .always(() => { + form.removeClass('mailpoet_form_sending'); + }); + } + function renderCaptcha(element, iteration) { if (!window.recaptcha || !window.grecaptcha.ready) { if (iteration < 20) { @@ -85,12 +155,31 @@ jQuery(($) => { return; } const recaptcha = $(element); + const form = $(recaptcha).parent('form'); const sitekey = recaptcha.attr('data-sitekey'); + let size = recaptcha.attr('data-size'); + + // Users should not be able to change the size if it is equal to 'invisible' as this would + // change the type of the ReCaptcha. + if (size !== 'invisible') { + size = Hooks.applyFilters('mailpoet_re_captcha_size', 'compact'); + } + const container = recaptcha.find('> .mailpoet_recaptcha_container').get(0); const field = recaptcha.find('> .mailpoet_recaptcha_field'); if (sitekey) { - const size = Hooks.applyFilters('mailpoet_re_captcha_size', 'compact'); - const widgetId = window.grecaptcha.render(container, { sitekey, size }); + const params = { sitekey, size }; + + if (size === 'invisible') { + params.callback = function invisibleReCaptchaCallback(token) { + const formData = form.mailpoetSerializeObject() || {}; + formData.data.recaptcha = token; + + submitSubscribeForm(form, formData, form.parsley()); + }; + } + + const widgetId = window.grecaptcha.render(container, params); field.val(widgetId); } } @@ -299,88 +388,36 @@ jQuery(($) => { }, 2500); return false; } - const formData = form.mailpoetSerializeObject() || {}; + // check if we're on the same domain if (isSameDomain(window.MailPoetForm.ajax_url) === false) { // non ajax post request return true; } + const formData = form.mailpoetSerializeObject() || {}; + const size = form.children('.mailpoet_recaptcha').attr('data-size'); + if (window.grecaptcha && formData.recaptcha) { - formData.data.recaptcha = window.grecaptcha.getResponse( - formData.recaptcha, - ); + // The API for the invisible and checkbox ReCaptchas is slightly different. For the + // former, we need to call execute() and then the ReCaptcha API calls the callback set + // inside renderCaptcha() with a token if the captcha was solved successfully. The + // callback then calls submitSubscribeForm() with the token. For the latter, we get the + // token here after calling getResponse() and then we can call submitSubscribeForm() + // directly. + if (size === 'invisible') { + window.grecaptcha.execute(); + } else { + formData.data.recaptcha = window.grecaptcha.getResponse( + formData.recaptcha, + ); + } } - form.addClass('mailpoet_form_sending'); - // ajax request - MailPoet.Ajax.post({ - url: window.MailPoetForm.ajax_url, - token: formData.token, - api_version: formData.api_version, - endpoint: 'subscribers', - action: 'subscribe', - data: formData.data, - }) - .fail((response) => { - if ( - response.meta !== undefined && - response.meta.redirect_url !== undefined - ) { - // go to page - window.top.location.href = response.meta.redirect_url; - } else { - if (response.meta && response.meta.refresh_captcha) { - updateCaptcha(); - } - form - .find('.mailpoet_validate_error') - .html( - response.errors.map((error) => error.message).join('
'), - ) - .show(); - } - }) - .done((response) => { - if (window.grecaptcha && formData.recaptcha) { - window.grecaptcha.reset(formData.recaptcha); - } - return response; - }) - .done((response) => { - // successfully subscribed - if ( - response.meta !== undefined && - response.meta.redirect_url !== undefined - ) { - setFormCookieAfterSubscription(form); - // go to page - window.location.href = response.meta.redirect_url; - } else { - displaySuccessMessage(form); - } + if (size !== 'invisible') { + submitSubscribeForm(form, formData, parsley); + } - // reset form - form.trigger('reset'); - // reset validation - parsley.reset(); - // reset captcha - if (window.grecaptcha && formData.recaptcha) { - window.grecaptcha.reset(formData.recaptcha); - } - - // resize iframe - if ( - window.frameElement !== null && - MailPoet !== undefined && - MailPoet.Iframe - ) { - MailPoet.Iframe.autoSize(window.frameElement); - } - }) - .always(() => { - form.removeClass('mailpoet_form_sending'); - }); return false; }); }); diff --git a/mailpoet/lib/Form/AssetsController.php b/mailpoet/lib/Form/AssetsController.php index 94318b8b1c..5ebf22f868 100644 --- a/mailpoet/lib/Form/AssetsController.php +++ b/mailpoet/lib/Form/AssetsController.php @@ -33,14 +33,14 @@ class AssetsController { public function printScripts() { ob_start(); $captcha = $this->settings->get('captcha'); - if (!empty($captcha['type']) && $captcha['type'] === Captcha::TYPE_RECAPTCHA) { + if (!empty($captcha['type']) && Captcha::isReCaptcha($captcha['type'])) { echo ''; } $this->wp->wpPrintScripts('jquery'); $this->wp->wpPrintScripts('mailpoet_vendor'); $this->wp->wpPrintScripts('mailpoet_public'); - + $scripts = ob_get_contents(); ob_end_clean(); if ($scripts === false) { @@ -62,7 +62,7 @@ class AssetsController { public function setupFrontEndDependencies() { $captcha = $this->settings->get('captcha'); - if (!empty($captcha['type']) && $captcha['type'] === Captcha::TYPE_RECAPTCHA) { + if (!empty($captcha['type']) && Captcha::isRecaptcha($captcha['type'])) { $this->wp->wpEnqueueScript( 'mailpoet_recaptcha', self::RECAPTCHA_API_URL diff --git a/mailpoet/lib/Form/Renderer.php b/mailpoet/lib/Form/Renderer.php index bd76dbdfa4..d5d3a9fa3c 100644 --- a/mailpoet/lib/Form/Renderer.php +++ b/mailpoet/lib/Form/Renderer.php @@ -70,7 +70,7 @@ class Renderer { if ( $captchaEnabled && $block['type'] === FormEntity::SUBMIT_BLOCK_TYPE - && $this->settings->get('captcha.type') === Captcha::TYPE_RECAPTCHA + && Captcha::isRecaptcha($this->settings->get('captcha.type')) ) { $html .= $this->renderReCaptcha(); } @@ -89,8 +89,15 @@ class Renderer { } private function renderReCaptcha(): string { - $siteKey = $this->settings->get('captcha.recaptcha_site_token'); - return '
+ if ($this->settings->get('captcha.type') === Captcha::TYPE_RECAPTCHA) { + $siteKey = $this->settings->get('captcha.recaptcha_site_token'); + $size = ''; + } else { + $siteKey = $this->settings->get('captcha.recaptcha_invisible_site_token'); + $size = 'invisible'; + } + + $html = '