Move subscriber limit check into validator

[MAILPOET-4236]
This commit is contained in:
John Oleksowicz
2022-04-18 16:25:44 -05:00
committed by Veljko V
parent 9bfe2b2ca1
commit 8983d5e3f7
5 changed files with 47 additions and 68 deletions

View File

@ -25,7 +25,6 @@ use MailPoet\Newsletter\Scheduler\Scheduler;
use MailPoet\Newsletter\Url as NewsletterUrl; use MailPoet\Newsletter\Url as NewsletterUrl;
use MailPoet\Settings\SettingsController; use MailPoet\Settings\SettingsController;
use MailPoet\UnexpectedValueException; use MailPoet\UnexpectedValueException;
use MailPoet\Util\License\Features\Subscribers as SubscribersFeature;
use MailPoet\Util\Security; use MailPoet\Util\Security;
use MailPoet\WP\Emoji; use MailPoet\WP\Emoji;
use MailPoet\WP\Functions as WPFunctions; use MailPoet\WP\Functions as WPFunctions;
@ -64,9 +63,6 @@ class Newsletters extends APIEndpoint {
/** @var Emoji */ /** @var Emoji */
private $emoji; private $emoji;
/** @var SubscribersFeature */
private $subscribersFeature;
/** @var SendPreviewController */ /** @var SendPreviewController */
private $sendPreviewController; private $sendPreviewController;
@ -92,7 +88,6 @@ class Newsletters extends APIEndpoint {
NewslettersResponseBuilder $newslettersResponseBuilder, NewslettersResponseBuilder $newslettersResponseBuilder,
PostNotificationScheduler $postNotificationScheduler, PostNotificationScheduler $postNotificationScheduler,
Emoji $emoji, Emoji $emoji,
SubscribersFeature $subscribersFeature,
SendPreviewController $sendPreviewController, SendPreviewController $sendPreviewController,
NewsletterSaveController $newsletterSaveController, NewsletterSaveController $newsletterSaveController,
NewsletterUrl $newsletterUrl, NewsletterUrl $newsletterUrl,
@ -108,7 +103,6 @@ class Newsletters extends APIEndpoint {
$this->newslettersResponseBuilder = $newslettersResponseBuilder; $this->newslettersResponseBuilder = $newslettersResponseBuilder;
$this->postNotificationScheduler = $postNotificationScheduler; $this->postNotificationScheduler = $postNotificationScheduler;
$this->emoji = $emoji; $this->emoji = $emoji;
$this->subscribersFeature = $subscribersFeature;
$this->sendPreviewController = $sendPreviewController; $this->sendPreviewController = $sendPreviewController;
$this->newsletterSaveController = $newsletterSaveController; $this->newsletterSaveController = $newsletterSaveController;
$this->newsletterUrl = $newsletterUrl; $this->newsletterUrl = $newsletterUrl;
@ -171,12 +165,6 @@ class Newsletters extends APIEndpoint {
]); ]);
} }
if ($status === NewsletterEntity::STATUS_ACTIVE && $this->subscribersFeature->check()) {
return $this->errorResponse([
APIError::FORBIDDEN => __('Subscribers limit reached.', 'mailpoet'),
], [], Response::STATUS_FORBIDDEN);
}
$newsletter = $this->getNewsletter($data); $newsletter = $this->getNewsletter($data);
if ($newsletter === null) { if ($newsletter === null) {
return $this->errorResponse([ return $this->errorResponse([

View File

@ -5,6 +5,7 @@ namespace MailPoet\Newsletter;
use MailPoet\Entities\NewsletterEntity; use MailPoet\Entities\NewsletterEntity;
use MailPoet\Services\Bridge; use MailPoet\Services\Bridge;
use MailPoet\Settings\TrackingConfig; use MailPoet\Settings\TrackingConfig;
use MailPoet\Util\License\Features\Subscribers as SubscribersFeature;
use MailPoet\Validator\ValidationException; use MailPoet\Validator\ValidationException;
class NewsletterValidator { class NewsletterValidator {
@ -15,16 +16,22 @@ class NewsletterValidator {
/** @var TrackingConfig */ /** @var TrackingConfig */
private $trackingConfig; private $trackingConfig;
/** @var SubscribersFeature */
private $subscribersFeature;
public function __construct( public function __construct(
Bridge $bridge, Bridge $bridge,
TrackingConfig $trackingConfig TrackingConfig $trackingConfig,
SubscribersFeature $subscribersFeature
) { ) {
$this->bridge = $bridge; $this->bridge = $bridge;
$this->trackingConfig = $trackingConfig; $this->trackingConfig = $trackingConfig;
$this->subscribersFeature = $subscribersFeature;
} }
public function validate(NewsletterEntity $newsletterEntity): ?string { public function validate(NewsletterEntity $newsletterEntity): ?string {
try { try {
$this->validateSubscriberLimit();
$this->validateBody($newsletterEntity); $this->validateBody($newsletterEntity);
$this->validateUnsubscribeRequirements($newsletterEntity); $this->validateUnsubscribeRequirements($newsletterEntity);
$this->validateReEngagementRequirements($newsletterEntity); $this->validateReEngagementRequirements($newsletterEntity);
@ -88,4 +95,10 @@ class NewsletterValidator {
throw new ValidationException('Please add an “Automatic Latest Content” widget to the email from the right sidebar.'); throw new ValidationException('Please add an “Automatic Latest Content” widget to the email from the right sidebar.');
} }
} }
private function validateSubscriberLimit(): void {
if ($this->subscribersFeature->check()) {
throw new ValidationException('Subscribers limit reached.');
}
}
} }

View File

@ -19,18 +19,14 @@ use MailPoet\Entities\SegmentEntity;
use MailPoet\Entities\SendingQueueEntity; use MailPoet\Entities\SendingQueueEntity;
use MailPoet\Entities\SubscriberEntity; use MailPoet\Entities\SubscriberEntity;
use MailPoet\Entities\SubscriberSegmentEntity; use MailPoet\Entities\SubscriberSegmentEntity;
use MailPoet\Listing\Handler;
use MailPoet\Models\ScheduledTask; use MailPoet\Models\ScheduledTask;
use MailPoet\Models\SendingQueue; use MailPoet\Models\SendingQueue;
use MailPoet\Newsletter\Listing\NewsletterListingRepository;
use MailPoet\Newsletter\NewsletterSaveController;
use MailPoet\Newsletter\NewslettersRepository; use MailPoet\Newsletter\NewslettersRepository;
use MailPoet\Newsletter\NewsletterValidator; use MailPoet\Newsletter\NewsletterValidator;
use MailPoet\Newsletter\Options\NewsletterOptionFieldsRepository; use MailPoet\Newsletter\Options\NewsletterOptionFieldsRepository;
use MailPoet\Newsletter\Options\NewsletterOptionsRepository; use MailPoet\Newsletter\Options\NewsletterOptionsRepository;
use MailPoet\Newsletter\Preview\SendPreviewController; use MailPoet\Newsletter\Preview\SendPreviewController;
use MailPoet\Newsletter\Preview\SendPreviewException; use MailPoet\Newsletter\Preview\SendPreviewException;
use MailPoet\Newsletter\Scheduler\PostNotificationScheduler;
use MailPoet\Newsletter\Scheduler\Scheduler; use MailPoet\Newsletter\Scheduler\Scheduler;
use MailPoet\Newsletter\Segment\NewsletterSegmentRepository; use MailPoet\Newsletter\Segment\NewsletterSegmentRepository;
use MailPoet\Newsletter\Sending\SendingQueuesRepository; use MailPoet\Newsletter\Sending\SendingQueuesRepository;
@ -41,7 +37,7 @@ use MailPoet\Segments\SegmentsRepository;
use MailPoet\Settings\SettingsController; use MailPoet\Settings\SettingsController;
use MailPoet\Tasks\Sending as SendingTask; use MailPoet\Tasks\Sending as SendingTask;
use MailPoet\Test\DataFactories\Newsletter; use MailPoet\Test\DataFactories\Newsletter;
use MailPoet\Util\License\Features\Subscribers as SubscribersFeature; use MailPoet\Util\License\Features\Subscribers;
use MailPoet\WooCommerce\Helper as WCHelper; use MailPoet\WooCommerce\Helper as WCHelper;
use MailPoet\WP\Emoji; use MailPoet\WP\Emoji;
use MailPoet\WP\Functions as WPFunctions; use MailPoet\WP\Functions as WPFunctions;
@ -183,7 +179,6 @@ class NewslettersTest extends \MailPoetTest {
$this->endpoint = $this->createNewslettersEndpointWithMocks([ $this->endpoint = $this->createNewslettersEndpointWithMocks([
'wp' => $wp, 'wp' => $wp,
'cronHelper' => $this->cronHelper, 'cronHelper' => $this->cronHelper,
'subscribersFeature' => Stub::make(SubscribersFeature::class),
]); ]);
$response = $this->endpoint->get(['id' => $this->newsletter->getId()]); $response = $this->endpoint->get(['id' => $this->newsletter->getId()]);
@ -233,7 +228,9 @@ class NewslettersTest extends \MailPoetTest {
public function testItReturnsErrorIfSubscribersLimitReached() { public function testItReturnsErrorIfSubscribersLimitReached() {
$endpoint = $this->createNewslettersEndpointWithMocks([ $endpoint = $this->createNewslettersEndpointWithMocks([
'cronHelper' => $this->cronHelper, 'cronHelper' => $this->cronHelper,
'subscribersFeature' => Stub::make(SubscribersFeature::class, ['check' => true]), 'newsletterValidator' => $this->getServiceWithOverrides(NewsletterValidator::class, [
'subscribersFeature' => Stub::make(Subscribers::class, ['check' => true])
])
]); ]);
$res = $endpoint->setStatus([ $res = $endpoint->setStatus([
'id' => $this->newsletter->getId(), 'id' => $this->newsletter->getId(),
@ -375,7 +372,6 @@ class NewslettersTest extends \MailPoetTest {
$this->endpoint = $this->createNewslettersEndpointWithMocks([ $this->endpoint = $this->createNewslettersEndpointWithMocks([
'wp' => $wp, 'wp' => $wp,
'cronHelper' => $this->cronHelper, 'cronHelper' => $this->cronHelper,
'subscribersFeature' => Stub::make(SubscribersFeature::class),
]); ]);
$response = $this->endpoint->duplicate(['id' => $this->newsletter->getId()]); $response = $this->endpoint->duplicate(['id' => $this->newsletter->getId()]);
@ -647,7 +643,6 @@ class NewslettersTest extends \MailPoetTest {
'wp' => $wp, 'wp' => $wp,
'cronHelper' => $this->cronHelper, 'cronHelper' => $this->cronHelper,
'emoji' => $emoji, 'emoji' => $emoji,
'subscribersFeature' => Stub::make(SubscribersFeature::class),
]); ]);
$response = $this->endpoint->showPreview($data); $response = $this->endpoint->showPreview($data);
@ -679,23 +674,7 @@ class NewslettersTest extends \MailPoetTest {
} }
private function createNewslettersEndpointWithMocks(array $mocks): Newsletters { private function createNewslettersEndpointWithMocks(array $mocks): Newsletters {
return new Newsletters( return $this->getServiceWithOverrides(Newsletters::class, $mocks);
$this->diContainer->get(Handler::class),
$mocks['wp'] ?? $this->diContainer->get(WPFunctions::class),
$this->diContainer->get(SettingsController::class),
$mocks['cronHelper'] ?? $this->diContainer->get(CronHelper::class),
$this->diContainer->get(NewslettersRepository::class),
$this->diContainer->get(NewsletterListingRepository::class),
$this->diContainer->get(NewslettersResponseBuilder::class),
$this->diContainer->get(PostNotificationScheduler::class),
$mocks['emoji'] ?? $this->diContainer->get(Emoji::class),
$mocks['subscribersFeature'] ?? $this->diContainer->get(SubscribersFeature::class),
$mocks['sendPreviewController'] ?? $this->diContainer->get(SendPreviewController::class),
$this->diContainer->get(NewsletterSaveController::class),
$this->diContainer->get(Url::class),
$this->scheduler,
$this->diContainer->get(NewsletterValidator::class)
);
} }
private function createNewsletterOptionField(string $name, string $type): NewsletterOptionFieldEntity { private function createNewsletterOptionField(string $name, string $type): NewsletterOptionFieldEntity {

View File

@ -23,8 +23,8 @@ use MailPoet\Segments\SubscribersFinder;
use MailPoet\Services\Bridge; use MailPoet\Services\Bridge;
use MailPoet\Settings\SettingsController; use MailPoet\Settings\SettingsController;
use MailPoet\Settings\SettingsRepository; use MailPoet\Settings\SettingsRepository;
use MailPoet\Settings\TrackingConfig;
use MailPoet\Tasks\Sending; use MailPoet\Tasks\Sending;
use MailPoet\Test\DataFactories\Newsletter;
use MailPoet\Util\License\Features\Subscribers as SubscribersFeature; use MailPoet\Util\License\Features\Subscribers as SubscribersFeature;
class SendingQueueTest extends \MailPoetTest { class SendingQueueTest extends \MailPoetTest {
@ -141,38 +141,27 @@ class SendingQueueTest extends \MailPoetTest {
} }
public function testItRejectsNewsletterWithoutUnsubscribeLink() { public function testItRejectsNewsletterWithoutUnsubscribeLink() {
$newsletter = new NewsletterEntity(); $newsletter = (new Newsletter())->withBody([
$newsletter->setSubject('subject'); 'content' =>
$newsletter->setType(NewsletterEntity::TYPE_STANDARD); [
$newsletter->setBody([ 'type' => 'container',
'content' => 'columnLayout' => false,
[ 'orientation' => 'vertical',
'type' => 'container', 'blocks' => [
'columnLayout' => false, [
'orientation' => 'vertical', 'type' => 'header',
'blocks' => [ 'link' => '',
[ 'text' => 'Hello!'
'type' => 'header', ]
'link' => '',
'text' => 'Hello!'
] ]
] ]
] ]
)->create();
$sendingQueue = $this->getServiceWithOverrides(SendingQueueAPI::class, [
'newsletterValidator' => $this->getServiceWithOverrides(NewsletterValidator::class, [
'bridge' => Stub::make(Bridge::class, ['isMailpoetSendingServiceEnabled' => true])
])
]); ]);
$this->entityManager->persist($newsletter);
$this->entityManager->flush();
$sendingQueue = new SendingQueueAPI(
$this->diContainer->get(SubscribersFeature::class),
$this->diContainer->get(NewslettersRepository::class),
$this->diContainer->get(SendingQueuesRepository::class),
$this->diContainer->get(SubscribersFinder::class),
$this->diContainer->get(ScheduledTasksRepository::class),
$this->diContainer->get(MailerFactory::class),
$this->diContainer->get(Scheduler::class),
new NewsletterValidator(Stub::make(Bridge::class, [
'isMailpoetSendingServiceEnabled' => true,
]), $this->diContainer->get(TrackingConfig::class))
);
$response = $sendingQueue->add(['newsletter_id' => $newsletter->getId()]); $response = $sendingQueue->add(['newsletter_id' => $newsletter->getId()]);
$response = $response->getData(); $response = $response->getData();
expect($response['errors'][0])->array(); expect($response['errors'][0])->array();

View File

@ -7,6 +7,7 @@ use MailPoet\Newsletter\NewsletterValidator;
use MailPoet\Services\Bridge; use MailPoet\Services\Bridge;
use MailPoet\Settings\TrackingConfig; use MailPoet\Settings\TrackingConfig;
use MailPoet\Test\DataFactories\Newsletter; use MailPoet\Test\DataFactories\Newsletter;
use MailPoet\Util\License\Features\Subscribers;
class NewsletterValidatorTest extends \MailPoetTest { class NewsletterValidatorTest extends \MailPoetTest {
/** @var NewsletterValidator */ /** @var NewsletterValidator */
@ -106,4 +107,13 @@ class NewsletterValidatorTest extends \MailPoetTest {
expect($validationError)->null(); expect($validationError)->null();
} }
public function testItIsNotValidIfSubscriberLimitReached() {
$newsletter = (new Newsletter())->withDefaultBody()->create();
$validator = $this->getServiceWithOverrides(NewsletterValidator::class, [
'subscribersFeature' => Stub::make(Subscribers::class, ['check' => true])
]);
$validationError = $validator->validate($newsletter);
expect($validationError)->equals('Subscribers limit reached.');
}
} }