diff --git a/mailpoet/lib/API/JSON/v1/Newsletters.php b/mailpoet/lib/API/JSON/v1/Newsletters.php index 04dd502e62..6eb2c804d1 100644 --- a/mailpoet/lib/API/JSON/v1/Newsletters.php +++ b/mailpoet/lib/API/JSON/v1/Newsletters.php @@ -25,7 +25,6 @@ use MailPoet\Newsletter\Scheduler\Scheduler; use MailPoet\Newsletter\Url as NewsletterUrl; use MailPoet\Settings\SettingsController; use MailPoet\UnexpectedValueException; -use MailPoet\Util\License\Features\Subscribers as SubscribersFeature; use MailPoet\Util\Security; use MailPoet\WP\Emoji; use MailPoet\WP\Functions as WPFunctions; @@ -64,9 +63,6 @@ class Newsletters extends APIEndpoint { /** @var Emoji */ private $emoji; - /** @var SubscribersFeature */ - private $subscribersFeature; - /** @var SendPreviewController */ private $sendPreviewController; @@ -92,7 +88,6 @@ class Newsletters extends APIEndpoint { NewslettersResponseBuilder $newslettersResponseBuilder, PostNotificationScheduler $postNotificationScheduler, Emoji $emoji, - SubscribersFeature $subscribersFeature, SendPreviewController $sendPreviewController, NewsletterSaveController $newsletterSaveController, NewsletterUrl $newsletterUrl, @@ -108,7 +103,6 @@ class Newsletters extends APIEndpoint { $this->newslettersResponseBuilder = $newslettersResponseBuilder; $this->postNotificationScheduler = $postNotificationScheduler; $this->emoji = $emoji; - $this->subscribersFeature = $subscribersFeature; $this->sendPreviewController = $sendPreviewController; $this->newsletterSaveController = $newsletterSaveController; $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); if ($newsletter === null) { return $this->errorResponse([ diff --git a/mailpoet/lib/Newsletter/NewsletterValidator.php b/mailpoet/lib/Newsletter/NewsletterValidator.php index 085803f98f..43b4d2786f 100644 --- a/mailpoet/lib/Newsletter/NewsletterValidator.php +++ b/mailpoet/lib/Newsletter/NewsletterValidator.php @@ -5,6 +5,7 @@ namespace MailPoet\Newsletter; use MailPoet\Entities\NewsletterEntity; use MailPoet\Services\Bridge; use MailPoet\Settings\TrackingConfig; +use MailPoet\Util\License\Features\Subscribers as SubscribersFeature; use MailPoet\Validator\ValidationException; class NewsletterValidator { @@ -15,16 +16,22 @@ class NewsletterValidator { /** @var TrackingConfig */ private $trackingConfig; + /** @var SubscribersFeature */ + private $subscribersFeature; + public function __construct( Bridge $bridge, - TrackingConfig $trackingConfig + TrackingConfig $trackingConfig, + SubscribersFeature $subscribersFeature ) { $this->bridge = $bridge; $this->trackingConfig = $trackingConfig; + $this->subscribersFeature = $subscribersFeature; } public function validate(NewsletterEntity $newsletterEntity): ?string { try { + $this->validateSubscriberLimit(); $this->validateBody($newsletterEntity); $this->validateUnsubscribeRequirements($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.'); } } + + private function validateSubscriberLimit(): void { + if ($this->subscribersFeature->check()) { + throw new ValidationException('Subscribers limit reached.'); + } + } } diff --git a/mailpoet/tests/integration/API/JSON/v1/NewslettersTest.php b/mailpoet/tests/integration/API/JSON/v1/NewslettersTest.php index 956ec41752..b860da17be 100644 --- a/mailpoet/tests/integration/API/JSON/v1/NewslettersTest.php +++ b/mailpoet/tests/integration/API/JSON/v1/NewslettersTest.php @@ -19,18 +19,14 @@ use MailPoet\Entities\SegmentEntity; use MailPoet\Entities\SendingQueueEntity; use MailPoet\Entities\SubscriberEntity; use MailPoet\Entities\SubscriberSegmentEntity; -use MailPoet\Listing\Handler; use MailPoet\Models\ScheduledTask; use MailPoet\Models\SendingQueue; -use MailPoet\Newsletter\Listing\NewsletterListingRepository; -use MailPoet\Newsletter\NewsletterSaveController; use MailPoet\Newsletter\NewslettersRepository; use MailPoet\Newsletter\NewsletterValidator; use MailPoet\Newsletter\Options\NewsletterOptionFieldsRepository; use MailPoet\Newsletter\Options\NewsletterOptionsRepository; use MailPoet\Newsletter\Preview\SendPreviewController; use MailPoet\Newsletter\Preview\SendPreviewException; -use MailPoet\Newsletter\Scheduler\PostNotificationScheduler; use MailPoet\Newsletter\Scheduler\Scheduler; use MailPoet\Newsletter\Segment\NewsletterSegmentRepository; use MailPoet\Newsletter\Sending\SendingQueuesRepository; @@ -41,7 +37,7 @@ use MailPoet\Segments\SegmentsRepository; use MailPoet\Settings\SettingsController; use MailPoet\Tasks\Sending as SendingTask; 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\WP\Emoji; use MailPoet\WP\Functions as WPFunctions; @@ -183,7 +179,6 @@ class NewslettersTest extends \MailPoetTest { $this->endpoint = $this->createNewslettersEndpointWithMocks([ 'wp' => $wp, 'cronHelper' => $this->cronHelper, - 'subscribersFeature' => Stub::make(SubscribersFeature::class), ]); $response = $this->endpoint->get(['id' => $this->newsletter->getId()]); @@ -233,7 +228,9 @@ class NewslettersTest extends \MailPoetTest { public function testItReturnsErrorIfSubscribersLimitReached() { $endpoint = $this->createNewslettersEndpointWithMocks([ '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([ 'id' => $this->newsletter->getId(), @@ -375,7 +372,6 @@ class NewslettersTest extends \MailPoetTest { $this->endpoint = $this->createNewslettersEndpointWithMocks([ 'wp' => $wp, 'cronHelper' => $this->cronHelper, - 'subscribersFeature' => Stub::make(SubscribersFeature::class), ]); $response = $this->endpoint->duplicate(['id' => $this->newsletter->getId()]); @@ -647,7 +643,6 @@ class NewslettersTest extends \MailPoetTest { 'wp' => $wp, 'cronHelper' => $this->cronHelper, 'emoji' => $emoji, - 'subscribersFeature' => Stub::make(SubscribersFeature::class), ]); $response = $this->endpoint->showPreview($data); @@ -679,23 +674,7 @@ class NewslettersTest extends \MailPoetTest { } private function createNewslettersEndpointWithMocks(array $mocks): Newsletters { - return new Newsletters( - $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) - ); + return $this->getServiceWithOverrides(Newsletters::class, $mocks); } private function createNewsletterOptionField(string $name, string $type): NewsletterOptionFieldEntity { diff --git a/mailpoet/tests/integration/API/JSON/v1/SendingQueueTest.php b/mailpoet/tests/integration/API/JSON/v1/SendingQueueTest.php index aec022aa52..e62dc5f5b6 100644 --- a/mailpoet/tests/integration/API/JSON/v1/SendingQueueTest.php +++ b/mailpoet/tests/integration/API/JSON/v1/SendingQueueTest.php @@ -23,8 +23,8 @@ use MailPoet\Segments\SubscribersFinder; use MailPoet\Services\Bridge; use MailPoet\Settings\SettingsController; use MailPoet\Settings\SettingsRepository; -use MailPoet\Settings\TrackingConfig; use MailPoet\Tasks\Sending; +use MailPoet\Test\DataFactories\Newsletter; use MailPoet\Util\License\Features\Subscribers as SubscribersFeature; class SendingQueueTest extends \MailPoetTest { @@ -141,38 +141,27 @@ class SendingQueueTest extends \MailPoetTest { } public function testItRejectsNewsletterWithoutUnsubscribeLink() { - $newsletter = new NewsletterEntity(); - $newsletter->setSubject('subject'); - $newsletter->setType(NewsletterEntity::TYPE_STANDARD); - $newsletter->setBody([ - 'content' => - [ - 'type' => 'container', - 'columnLayout' => false, - 'orientation' => 'vertical', - 'blocks' => [ - [ - 'type' => 'header', - 'link' => '', - 'text' => 'Hello!' + $newsletter = (new Newsletter())->withBody([ + 'content' => + [ + 'type' => 'container', + 'columnLayout' => false, + 'orientation' => 'vertical', + 'blocks' => [ + [ + '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 = $response->getData(); expect($response['errors'][0])->array(); diff --git a/mailpoet/tests/integration/Newsletter/NewsletterValidatorTest.php b/mailpoet/tests/integration/Newsletter/NewsletterValidatorTest.php index 392980f75e..ab70596a8b 100644 --- a/mailpoet/tests/integration/Newsletter/NewsletterValidatorTest.php +++ b/mailpoet/tests/integration/Newsletter/NewsletterValidatorTest.php @@ -7,6 +7,7 @@ use MailPoet\Newsletter\NewsletterValidator; use MailPoet\Services\Bridge; use MailPoet\Settings\TrackingConfig; use MailPoet\Test\DataFactories\Newsletter; +use MailPoet\Util\License\Features\Subscribers; class NewsletterValidatorTest extends \MailPoetTest { /** @var NewsletterValidator */ @@ -106,4 +107,13 @@ class NewsletterValidatorTest extends \MailPoetTest { 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.'); + } + }