diff --git a/lib/API/JSON/v1/Segments.php b/lib/API/JSON/v1/Segments.php index 5622a1bb3f..7de807bb96 100644 --- a/lib/API/JSON/v1/Segments.php +++ b/lib/API/JSON/v1/Segments.php @@ -13,6 +13,7 @@ use MailPoet\Doctrine\Validator\ValidationException; use MailPoet\Entities\SegmentEntity; use MailPoet\Entities\SubscriberEntity; use MailPoet\Listing; +use MailPoet\Newsletter\Segment\NewsletterSegmentRepository; use MailPoet\Segments\SegmentListingRepository; use MailPoet\Segments\SegmentSaveController; use MailPoet\Segments\SegmentsRepository; @@ -51,6 +52,9 @@ class Segments extends APIEndpoint { /** @var SegmentListingRepository */ private $segmentListingRepository; + /** @var NewsletterSegmentRepository */ + private $newsletterSegmentRepository; + public function __construct( Listing\Handler $listingHandler, SegmentsRepository $segmentsRepository, @@ -59,7 +63,8 @@ class Segments extends APIEndpoint { SegmentSaveController $segmentSavecontroller, SubscribersRepository $subscribersRepository, WooCommerce $wooCommerce, - WP $wpSegment + WP $wpSegment, + NewsletterSegmentRepository $newsletterSegmentRepository ) { $this->listingHandler = $listingHandler; $this->wooCommerceSync = $wooCommerce; @@ -69,6 +74,7 @@ class Segments extends APIEndpoint { $this->subscribersRepository = $subscribersRepository; $this->wpSegment = $wpSegment; $this->segmentListingRepository = $segmentListingRepository; + $this->newsletterSegmentRepository = $newsletterSegmentRepository; } public function get($data = []) { @@ -147,32 +153,45 @@ class Segments extends APIEndpoint { public function trash($data = []) { $segment = $this->getSegment($data); - if ($segment instanceof SegmentEntity) { - if (!$this->isTrashOrRestoreAllowed($segment)) { - return $this->errorResponse([ - APIError::FORBIDDEN => WPFunctions::get()->__('This list cannot be moved to trash.', 'mailpoet'), - ]); - } - // When the segment is of type WP_USERS we want to trash all subscribers who aren't subscribed in another list - if ($segment->getType() === SegmentEntity::TYPE_WP_USERS) { - $subscribers = $this->subscribersRepository->findExclusiveSubscribersBySegment((int)$segment->getId()); - $subscriberIds = array_map(function (SubscriberEntity $subscriberEntity): int { - return (int)$subscriberEntity->getId(); - }, $subscribers); - $this->subscribersRepository->bulkTrash($subscriberIds); - } + if (!$segment instanceof SegmentEntity) { - $this->segmentsRepository->bulkTrash([$segment->getId()], $segment->getType()); - $this->segmentsRepository->refresh($segment); - return $this->successResponse( - $this->segmentsResponseBuilder->build($segment), - ['count' => 1] - ); - } else { return $this->errorResponse([ APIError::NOT_FOUND => WPFunctions::get()->__('This list does not exist.', 'mailpoet'), ]); } + + if (!$this->isTrashOrRestoreAllowed($segment)) { + return $this->errorResponse([ + APIError::FORBIDDEN => WPFunctions::get()->__('This list cannot be moved to trash.', 'mailpoet'), + ]); + } + + $activelyUsedNewslettersSubjects = $this->newsletterSegmentRepository->getSubjectsOfActivelyUsedEmailsForSegments([$segment->getId()]); + if (isset($activelyUsedNewslettersSubjects[$segment->getId()])) { + return $this->badRequest([ + APIError::BAD_REQUEST => str_replace( + '%$1s', + "'" . join("', '", $activelyUsedNewslettersSubjects[$segment->getId()] ) . "'", + _x('List cannot be deleted because it’s used for %$1s email', 'Alert shown when trying to delete segment, which is assigned to any automatic emails.', 'mailpoet') + ), + ]); + } + + // When the segment is of type WP_USERS we want to trash all subscribers who aren't subscribed in another list + if ($segment->getType() === SegmentEntity::TYPE_WP_USERS) { + $subscribers = $this->subscribersRepository->findExclusiveSubscribersBySegment((int)$segment->getId()); + $subscriberIds = array_map(function (SubscriberEntity $subscriberEntity): int { + return (int)$subscriberEntity->getId(); + }, $subscribers); + $this->subscribersRepository->bulkTrash($subscriberIds); + } + + $this->segmentsRepository->bulkTrash([$segment->getId()], $segment->getType()); + $this->segmentsRepository->refresh($segment); + return $this->successResponse( + $this->segmentsResponseBuilder->build($segment), + ['count' => 1] + ); } public function delete($data = []) { diff --git a/tests/integration/API/JSON/v1/SegmentsTest.php b/tests/integration/API/JSON/v1/SegmentsTest.php index 1c04700fe2..b5379087af 100644 --- a/tests/integration/API/JSON/v1/SegmentsTest.php +++ b/tests/integration/API/JSON/v1/SegmentsTest.php @@ -7,6 +7,8 @@ use MailPoet\API\JSON\Response as APIResponse; use MailPoet\API\JSON\ResponseBuilders\SegmentsResponseBuilder; use MailPoet\API\JSON\v1\Segments; use MailPoet\DI\ContainerWrapper; +use MailPoet\Entities\NewsletterEntity; +use MailPoet\Entities\NewsletterSegmentEntity; use MailPoet\Entities\SegmentEntity; use MailPoet\Entities\SubscriberEntity; use MailPoet\Entities\SubscriberSegmentEntity; @@ -145,6 +147,21 @@ class SegmentsTest extends \MailPoetTest { expect($response->meta['count'])->equals(1); } + public function testItReturnsErrorWhenTrashingSegmentWithActiveNewsletter() { + $newsletter = new NewsletterEntity(); + $newsletter->setSubject('Subject'); + $newsletter->setType(NewsletterEntity::TYPE_WELCOME); + $newsletterSegment = new NewsletterSegmentEntity($newsletter, $this->segment2); + $this->entityManager->persist($newsletter); + $this->entityManager->persist($newsletterSegment); + $this->entityManager->flush(); + + $response = $this->endpoint->trash(['id' => $this->segment2->getId()]); + $this->entityManager->refresh($this->segment2); + expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST); + expect($response->errors[0]['message'])->equals("List cannot be deleted because it’s used for 'Subject' email"); + } + public function testItCanDeleteASegment() { $response = $this->endpoint->delete(['id' => $this->segment3->getId()]); expect($response->data)->isEmpty(); @@ -213,5 +230,7 @@ class SegmentsTest extends \MailPoetTest { $this->truncateEntity(SegmentEntity::class); $this->truncateEntity(SubscriberEntity::class); $this->truncateEntity(SubscriberSegmentEntity::class); + $this->truncateEntity(NewsletterEntity::class); + $this->truncateEntity(NewsletterSegmentEntity::class); } }