Do not display form if logged in and registered to any segment.
[MAILPOET-3059]
This commit is contained in:
@ -5,6 +5,8 @@ namespace MailPoet\Form;
|
||||
use MailPoet\API\JSON\API;
|
||||
use MailPoet\Config\Renderer as TemplateRenderer;
|
||||
use MailPoet\Entities\FormEntity;
|
||||
use MailPoet\Subscribers\SubscribersRepository;
|
||||
use MailPoet\Subscribers\SubscriberSubscribeController;
|
||||
use MailPoet\Util\Security;
|
||||
use MailPoet\WP\Functions as WPFunctions;
|
||||
|
||||
@ -19,6 +21,12 @@ class DisplayFormInWPContent {
|
||||
FormEntity::DISPLAY_TYPE_SLIDE_IN,
|
||||
];
|
||||
|
||||
const WITH_COOKIE_TYPES = [
|
||||
FormEntity::DISPLAY_TYPE_POPUP,
|
||||
FormEntity::DISPLAY_TYPE_FIXED_BAR,
|
||||
FormEntity::DISPLAY_TYPE_SLIDE_IN,
|
||||
];
|
||||
|
||||
const SUPPORTED_POST_TYPES = [
|
||||
'post',
|
||||
'product',
|
||||
@ -40,18 +48,28 @@ class DisplayFormInWPContent {
|
||||
/** @var TemplateRenderer */
|
||||
private $templateRenderer;
|
||||
|
||||
/** @var SubscribersRepository */
|
||||
private $subscribersRepository;
|
||||
|
||||
/** @var SubscriberSubscribeController */
|
||||
private $subscriberSubscribeController;
|
||||
|
||||
public function __construct(
|
||||
WPFunctions $wp,
|
||||
FormsRepository $formsRepository,
|
||||
Renderer $formRenderer,
|
||||
AssetsController $assetsController,
|
||||
TemplateRenderer $templateRenderer
|
||||
TemplateRenderer $templateRenderer,
|
||||
SubscriberSubscribeController $subscriberSubscribeController,
|
||||
SubscribersRepository $subscribersRepository
|
||||
) {
|
||||
$this->wp = $wp;
|
||||
$this->formsRepository = $formsRepository;
|
||||
$this->formRenderer = $formRenderer;
|
||||
$this->assetsController = $assetsController;
|
||||
$this->templateRenderer = $templateRenderer;
|
||||
$this->subscriberSubscribeController = $subscriberSubscribeController;
|
||||
$this->subscribersRepository = $subscribersRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -177,6 +195,25 @@ class DisplayFormInWPContent {
|
||||
return $this->templateRenderer->render('form/front_end_form.html', $templateData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the form should be displayed for current WordPress user
|
||||
*
|
||||
* @param FormEntity $form The form to check
|
||||
* @param string $formType Display type of the current form, from self::TYPES
|
||||
* @return bool False if form can be dismissed and user is subscribed to any of the form's lists
|
||||
*/
|
||||
private function shouldDisplayFormForWPUser(FormEntity $form, string $formType): bool {
|
||||
if (!in_array($formType, self::WITH_COOKIE_TYPES, true)) return true;
|
||||
|
||||
$subscriber = $this->subscribersRepository->getCurrentWPUser();
|
||||
if (!$subscriber) return true;
|
||||
|
||||
if ($this->subscriberSubscribeController->isSubscribedToAnyFormSegments($form, $subscriber)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function shouldDisplayFormType(FormEntity $form, string $formType): bool {
|
||||
$settings = $form->getSettings();
|
||||
// check the structure just to be sure
|
||||
@ -192,6 +229,8 @@ class DisplayFormInWPContent {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->shouldDisplayFormForWPUser($form, $formType)) return false;
|
||||
|
||||
if ($this->wp->isSingular($this->wp->applyFilters('mailpoet_display_form_supported_post_types', self::SUPPORTED_POST_TYPES))) {
|
||||
if ($this->shouldDisplayFormOnPost($setup, 'posts')) return true;
|
||||
if ($this->shouldDisplayFormOnCategory($setup)) return true;
|
||||
|
@ -3,9 +3,11 @@
|
||||
namespace MailPoet\Subscribers;
|
||||
|
||||
use MailPoet\Entities\FormEntity;
|
||||
use MailPoet\Entities\SubscriberEntity;
|
||||
use MailPoet\Form\FormsRepository;
|
||||
use MailPoet\Form\Util\FieldNameObfuscator;
|
||||
use MailPoet\NotFoundException;
|
||||
use MailPoet\Segments\SubscribersFinder;
|
||||
use MailPoet\Settings\SettingsController;
|
||||
use MailPoet\Statistics\StatisticsFormsRepository;
|
||||
use MailPoet\Subscription\Captcha;
|
||||
@ -49,10 +51,14 @@ class SubscriberSubscribeController {
|
||||
/** @var StatisticsFormsRepository */
|
||||
private $statisticsFormsRepository;
|
||||
|
||||
/** @var SubscribersFinder */
|
||||
private $subscribersFinder;
|
||||
|
||||
public function __construct(
|
||||
Captcha $subscriptionCaptcha,
|
||||
CaptchaSession $captchaSession,
|
||||
SubscriberActions $subscriberActions,
|
||||
SubscribersFinder $subscribersFinder,
|
||||
SubscriptionUrlFactory $subscriptionUrlFactory,
|
||||
SubscriptionThrottling $throttling,
|
||||
FieldNameObfuscator $fieldNameObfuscator,
|
||||
@ -70,6 +76,7 @@ class SubscriberSubscribeController {
|
||||
$this->fieldNameObfuscator = $fieldNameObfuscator;
|
||||
$this->settings = $settings;
|
||||
$this->subscriberActions = $subscriberActions;
|
||||
$this->subscribersFinder = $subscribersFinder;
|
||||
$this->wp = $wp;
|
||||
$this->throttling = $throttling;
|
||||
$this->statisticsFormsRepository = $statisticsFormsRepository;
|
||||
@ -153,6 +160,22 @@ class SubscriberSubscribeController {
|
||||
return $meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the subscriber is subscribed to any segments in the form
|
||||
*
|
||||
* @param FormEntity $form The form entity
|
||||
* @param SubscriberEntity $subscriber The subscriber entity
|
||||
* @return bool True if the subscriber is subscribed to any of the segments in the form
|
||||
*/
|
||||
public function isSubscribedToAnyFormSegments(FormEntity $form, SubscriberEntity $subscriber): bool {
|
||||
$formSegments = array_merge( $form->getSegmentBlocksSegmentIds(), $form->getSettingsSegmentIds());
|
||||
|
||||
$subscribersFound = $this->subscribersFinder->findSubscribersInSegments([$subscriber->getId()], $formSegments);
|
||||
if (!empty($subscribersFound)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function deobfuscateFormPayload($data): array {
|
||||
return $this->fieldNameObfuscator->deobfuscateFormPayload($data);
|
||||
}
|
||||
|
@ -4,6 +4,9 @@ namespace MailPoet\Form;
|
||||
|
||||
use MailPoet\Config\Renderer as TemplateRenderer;
|
||||
use MailPoet\Entities\FormEntity;
|
||||
use MailPoet\Entities\SubscriberEntity;
|
||||
use MailPoet\Subscribers\SubscribersRepository;
|
||||
use MailPoet\Subscribers\SubscriberSubscribeController;
|
||||
use MailPoet\WP\Functions as WPFunctions;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
|
||||
@ -27,6 +30,12 @@ class DisplayFormInWPContentTest extends \MailPoetUnitTest {
|
||||
/** @var DisplayFormInWPContent */
|
||||
private $hook;
|
||||
|
||||
/** @var SubscribersRepository & MockObject */
|
||||
private $subscribersRepository;
|
||||
|
||||
/** @var SubscriberSubscribeController & MockObject */
|
||||
private $subscriberSubscribeController;
|
||||
|
||||
public function _before() {
|
||||
parent::_before();
|
||||
if (!defined('ARRAY_A')) define('ARRAY_A', 'ARRAY_A');
|
||||
@ -42,7 +51,17 @@ class DisplayFormInWPContentTest extends \MailPoetUnitTest {
|
||||
$this->renderer = $this->createMock(Renderer::class);
|
||||
$this->renderer->expects($this->any())->method('renderStyles')->willReturn('<style></style>');
|
||||
$this->renderer->expects($this->any())->method('renderHTML')->willReturn('<form></form>');
|
||||
$this->hook = new DisplayFormInWPContent($this->wp, $this->repository, $this->renderer, $this->assetsController, $this->templateRenderer);
|
||||
$this->subscribersRepository = $this->createMock( SubscribersRepository::class);
|
||||
$this->subscriberSubscribeController = $this->createMock(SubscriberSubscribeController::class);
|
||||
$this->hook = new DisplayFormInWPContent(
|
||||
$this->wp,
|
||||
$this->repository,
|
||||
$this->renderer,
|
||||
$this->assetsController,
|
||||
$this->templateRenderer,
|
||||
$this->subscriberSubscribeController,
|
||||
$this->subscribersRepository
|
||||
);
|
||||
}
|
||||
|
||||
public function testAppendsRenderedFormAfterPostContent() {
|
||||
@ -364,6 +383,62 @@ class DisplayFormInWPContentTest extends \MailPoetUnitTest {
|
||||
expect($result)->endsWith($formHtml);
|
||||
}
|
||||
|
||||
public function testDoesNotAppendPopupFormIfLoggedInAndSubscribed() {
|
||||
$formHtml = '<form id="test-form"></form>';
|
||||
$subscriber = new SubscriberEntity();
|
||||
$this->subscribersRepository->expects($this->once())->method('getCurrentWPUser')->willReturn($subscriber);
|
||||
$this->subscriberSubscribeController->expects($this->once())->method('isSubscribedToAnyFormSegments')->willReturn(true);
|
||||
$this->wp->expects($this->once())->method('isSingle')->willReturn(false);
|
||||
$this->wp->expects($this->any())->method('isPage')->willReturn(true);
|
||||
$this->assetsController->expects($this->never())->method('setupFrontEndDependencies');
|
||||
$this->templateRenderer->expects($this->never())->method('render')->willReturn($formHtml);
|
||||
$this->wp
|
||||
->expects($this->never())
|
||||
->method('setTransient');
|
||||
$form = new FormEntity('My Form');
|
||||
$form->setSettings([
|
||||
'segments' => ['3'],
|
||||
'form_placement' => [
|
||||
'below_posts' => ['enabled' => '', 'pages' => ['all' => ''], 'posts' => ['all' => '']],
|
||||
'popup' => ['enabled' => '1', 'pages' => ['all' => '1'], 'posts' => ['all' => '']],
|
||||
],
|
||||
'success_message' => 'Hello',
|
||||
]);
|
||||
$form->setBody([['type' => 'submit', 'params' => ['label' => 'Subscribe!'], 'id' => 'submit', 'name' => 'Submit']]);
|
||||
$this->repository->expects($this->once())->method('findBy')->willReturn([$form]);
|
||||
|
||||
$result = $this->hook->display('content');
|
||||
expect($result)->equals('content');
|
||||
}
|
||||
|
||||
public function testAppendsPopupFormIfLoggedInAndNotSubscribed() {
|
||||
$formHtml = '<form id="test-form"></form>';
|
||||
$subscriber = new SubscriberEntity();
|
||||
$this->subscribersRepository->expects($this->any())->method('getCurrentWPUser')->willReturn($subscriber);
|
||||
$this->subscriberSubscribeController->expects($this->any())->method('isSubscribedToAnyFormSegments')->willReturn(false);
|
||||
$this->wp->expects($this->once())->method('isSingle')->willReturn(false);
|
||||
$this->wp->expects($this->any())->method('isPage')->willReturn(true);
|
||||
$this->assetsController->expects($this->once())->method('setupFrontEndDependencies');
|
||||
$this->templateRenderer->expects($this->once())->method('render')->willReturn($formHtml);
|
||||
$this->wp
|
||||
->expects($this->never())
|
||||
->method('setTransient');
|
||||
$form = new FormEntity('My Form');
|
||||
$form->setSettings([
|
||||
'segments' => ['3'],
|
||||
'form_placement' => [
|
||||
'below_posts' => ['enabled' => '', 'pages' => ['all' => ''], 'posts' => ['all' => '']],
|
||||
'popup' => ['enabled' => '1', 'pages' => ['all' => '1'], 'posts' => ['all' => '']],
|
||||
],
|
||||
'success_message' => 'Hello',
|
||||
]);
|
||||
$form->setBody([['type' => 'submit', 'params' => ['label' => 'Subscribe!'], 'id' => 'submit', 'name' => 'Submit']]);
|
||||
$this->repository->expects($this->once())->method('findBy')->willReturn([$form]);
|
||||
|
||||
$result = $this->hook->display('content');
|
||||
expect($result)->endsWith($formHtml);
|
||||
}
|
||||
|
||||
public function testAppendsRenderedFixedBarForm() {
|
||||
$formHtml = '<form id="test-form"></form>';
|
||||
$this->wp->expects($this->once())->method('isSingle')->willReturn(false);
|
||||
|
@ -9,11 +9,13 @@ use MailPoet\Entities\FormEntity;
|
||||
use MailPoet\Entities\SubscriberEntity;
|
||||
use MailPoet\Form\FormsRepository;
|
||||
use MailPoet\Form\Util\FieldNameObfuscator;
|
||||
use MailPoet\Segments\SubscribersFinder;
|
||||
use MailPoet\Settings\SettingsController;
|
||||
use MailPoet\Statistics\StatisticsFormsRepository;
|
||||
use MailPoet\Subscription\Captcha;
|
||||
use MailPoet\Subscription\CaptchaSession;
|
||||
use MailPoet\Subscription\SubscriptionUrlFactory;
|
||||
use MailPoet\Subscription\Throttling;
|
||||
use MailPoet\Subscription\Throttling as SubscriptionThrottling;
|
||||
use MailPoet\UnexpectedValueException;
|
||||
use MailPoet\WP\Functions as WPFunctions;
|
||||
@ -29,6 +31,7 @@ class SubscriberSubscribeControllerUnitTest extends \MailPoetUnitTest {
|
||||
],
|
||||
$this
|
||||
);
|
||||
$subscribersFinder = Stub::makeEmpty(SubscribersFinder::class);
|
||||
$subscriptionUrlFactory = Stub::makeEmpty(SubscriptionUrlFactory::class);
|
||||
$throttling = Stub::makeEmpty(SubscriptionThrottling::class);
|
||||
$fieldNameObfuscator = Stub::makeEmpty(FieldNameObfuscator::class);
|
||||
@ -63,6 +66,7 @@ class SubscriberSubscribeControllerUnitTest extends \MailPoetUnitTest {
|
||||
$subscriptionCaptcha,
|
||||
$captchaSession,
|
||||
$subscriberActions,
|
||||
$subscribersFinder,
|
||||
$subscriptionUrlFactory,
|
||||
$throttling,
|
||||
$fieldNameObfuscator,
|
||||
@ -92,6 +96,7 @@ class SubscriberSubscribeControllerUnitTest extends \MailPoetUnitTest {
|
||||
],
|
||||
$this
|
||||
);
|
||||
$subscribersFinder = Stub::makeEmpty(SubscribersFinder::class);
|
||||
$subscriptionUrlFactory = Stub::makeEmpty(SubscriptionUrlFactory::class);
|
||||
$throttling = Stub::makeEmpty(
|
||||
SubscriptionThrottling::class,
|
||||
@ -144,6 +149,7 @@ class SubscriberSubscribeControllerUnitTest extends \MailPoetUnitTest {
|
||||
$subscriptionCaptcha,
|
||||
$captchaSession,
|
||||
$subscriberActions,
|
||||
$subscribersFinder,
|
||||
$subscriptionUrlFactory,
|
||||
$throttling,
|
||||
$fieldNameObfuscator,
|
||||
@ -171,6 +177,7 @@ class SubscriberSubscribeControllerUnitTest extends \MailPoetUnitTest {
|
||||
],
|
||||
$this
|
||||
);
|
||||
$subscribersFinder = Stub::makeEmpty(SubscribersFinder::class);
|
||||
$subscriptionUrlFactory = Stub::makeEmpty(SubscriptionUrlFactory::class);
|
||||
$throttling = Stub::makeEmpty(SubscriptionThrottling::class);
|
||||
$fieldNameObfuscator = Stub::makeEmpty(FieldNameObfuscator::class,
|
||||
@ -221,6 +228,7 @@ class SubscriberSubscribeControllerUnitTest extends \MailPoetUnitTest {
|
||||
$subscriptionCaptcha,
|
||||
$captchaSession,
|
||||
$subscriberActions,
|
||||
$subscribersFinder,
|
||||
$subscriptionUrlFactory,
|
||||
$throttling,
|
||||
$fieldNameObfuscator,
|
||||
@ -254,6 +262,7 @@ class SubscriberSubscribeControllerUnitTest extends \MailPoetUnitTest {
|
||||
],
|
||||
$this
|
||||
);
|
||||
$subscribersFinder = Stub::makeEmpty(SubscribersFinder::class);
|
||||
$expectedRedirectLink = 'redirect';
|
||||
$subscriptionUrlFactory = Stub::makeEmpty(
|
||||
SubscriptionUrlFactory::class,
|
||||
@ -324,6 +333,7 @@ class SubscriberSubscribeControllerUnitTest extends \MailPoetUnitTest {
|
||||
$subscriptionCaptcha,
|
||||
$captchaSession,
|
||||
$subscriberActions,
|
||||
$subscribersFinder,
|
||||
$subscriptionUrlFactory,
|
||||
$throttling,
|
||||
$fieldNameObfuscator,
|
||||
@ -362,6 +372,7 @@ class SubscriberSubscribeControllerUnitTest extends \MailPoetUnitTest {
|
||||
],
|
||||
$this
|
||||
);
|
||||
$subscribersFinder = Stub::makeEmpty(SubscribersFinder::class);
|
||||
$expectedRedirectLink = 'redirect';
|
||||
$subscriptionUrlFactory = Stub::makeEmpty(
|
||||
SubscriptionUrlFactory::class,
|
||||
@ -436,6 +447,7 @@ class SubscriberSubscribeControllerUnitTest extends \MailPoetUnitTest {
|
||||
$subscriptionCaptcha,
|
||||
$captchaSession,
|
||||
$subscriberActions,
|
||||
$subscribersFinder,
|
||||
$subscriptionUrlFactory,
|
||||
$throttling,
|
||||
$fieldNameObfuscator,
|
||||
@ -453,6 +465,108 @@ class SubscriberSubscribeControllerUnitTest extends \MailPoetUnitTest {
|
||||
]);
|
||||
}
|
||||
|
||||
public function testItShouldReturnTrueIfSubscribedToAnySegmentsInForm() {
|
||||
$blockSegmentIds = [15,16];
|
||||
$segmentIds = [17];
|
||||
$formSegments = [15,16,17];
|
||||
$subscriberId = 1;
|
||||
|
||||
$form = Stub::makeEmpty(
|
||||
FormEntity::class,
|
||||
[
|
||||
'getSettingsSegmentIds' => function() use ($segmentIds): array {
|
||||
return $segmentIds;
|
||||
},
|
||||
'getSegmentBlocksSegmentIds' => function() use ($blockSegmentIds) {
|
||||
return $blockSegmentIds;
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
$subscriber = Stub::makeEmpty(
|
||||
SubscriberEntity::class,
|
||||
[
|
||||
'getId' => function() use($subscriberId): int {
|
||||
return $subscriberId;
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
$subscribersFinder = $this->createMock(SubscribersFinder::class);
|
||||
$subscribersFinder->expects($this->once())->method('findSubscribersInSegments')
|
||||
->with([$subscriberId], $formSegments)
|
||||
->willReturn([15]);
|
||||
|
||||
$testee = new SubscriberSubscribeController(
|
||||
Stub::makeEmpty(Captcha::class),
|
||||
Stub::makeEmpty(CaptchaSession::class),
|
||||
Stub::makeEmpty(SubscriberActions::class),
|
||||
$subscribersFinder,
|
||||
Stub::makeEmpty(SubscriptionUrlFactory::class),
|
||||
Stub::makeEmpty(Throttling::class),
|
||||
Stub::makeEmpty(FieldNameObfuscator::class),
|
||||
Stub::makeEmpty(RequiredCustomFieldValidator::class),
|
||||
Stub::makeEmpty(SettingsController::class),
|
||||
Stub::makeEmpty(FormsRepository::class),
|
||||
Stub::makeEmpty(StatisticsFormsRepository::class),
|
||||
Stub::makeEmpty(WPFunctions::class)
|
||||
);
|
||||
|
||||
$result = $testee->isSubscribedToAnyFormSegments($form, $subscriber);
|
||||
expect($result)->equals(true);
|
||||
}
|
||||
|
||||
public function testItShouldReturnFalseIfNotSubscribedToAnySegmentsInForm() {
|
||||
$blockSegmentIds = [];
|
||||
$segmentIds = [17];
|
||||
$formSegments = [17];
|
||||
$subscriberId = 1;
|
||||
|
||||
$form = Stub::makeEmpty(
|
||||
FormEntity::class,
|
||||
[
|
||||
'getSettingsSegmentIds' => function() use ($segmentIds): array {
|
||||
return $segmentIds;
|
||||
},
|
||||
'getSegmentBlocksSegmentIds' => function() use ($blockSegmentIds) {
|
||||
return $blockSegmentIds;
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
$subscriber = Stub::makeEmpty(
|
||||
SubscriberEntity::class,
|
||||
[
|
||||
'getId' => function() use($subscriberId): int {
|
||||
return $subscriberId;
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
$subscribersFinder = $this->createMock(SubscribersFinder::class);
|
||||
$subscribersFinder->expects($this->once())->method('findSubscribersInSegments')
|
||||
->with([$subscriberId], $formSegments)
|
||||
->willReturn([]);
|
||||
|
||||
$testee = new SubscriberSubscribeController(
|
||||
Stub::makeEmpty(Captcha::class),
|
||||
Stub::makeEmpty(CaptchaSession::class),
|
||||
Stub::makeEmpty(SubscriberActions::class),
|
||||
$subscribersFinder,
|
||||
Stub::makeEmpty(SubscriptionUrlFactory::class),
|
||||
Stub::makeEmpty(SubscriptionThrottling::class),
|
||||
Stub::makeEmpty(FieldNameObfuscator::class),
|
||||
Stub::makeEmpty(RequiredCustomFieldValidator::class),
|
||||
Stub::makeEmpty(SettingsController::class),
|
||||
Stub::makeEmpty(FormsRepository::class),
|
||||
Stub::makeEmpty(StatisticsFormsRepository::class),
|
||||
Stub::makeEmpty(WPFunctions::class)
|
||||
);
|
||||
|
||||
$result = $testee->isSubscribedToAnyFormSegments($form, $subscriber);
|
||||
expect($result)->equals(false);
|
||||
}
|
||||
|
||||
public function testSubscribeSuccess() {
|
||||
|
||||
$captchaSessionId = 'captcha_session_id';
|
||||
@ -509,6 +623,7 @@ class SubscriberSubscribeControllerUnitTest extends \MailPoetUnitTest {
|
||||
],
|
||||
$this
|
||||
);
|
||||
$subscribersFinder = Stub::makeEmpty(SubscribersFinder::class);
|
||||
$subscriptionUrlFactory = Stub::makeEmpty(SubscriptionUrlFactory::class,
|
||||
[
|
||||
'subscribe' => function($receivedSubscriber, $receivedForm) use ($subscriber, $form) {
|
||||
@ -560,6 +675,7 @@ class SubscriberSubscribeControllerUnitTest extends \MailPoetUnitTest {
|
||||
$subscriptionCaptcha,
|
||||
$captchaSession,
|
||||
$subscriberActions,
|
||||
$subscribersFinder,
|
||||
$subscriptionUrlFactory,
|
||||
$throttling,
|
||||
$fieldNameObfuscator,
|
||||
|
Reference in New Issue
Block a user