Disallow trashing single dynamic segment with active email

[MAILPOET-3463]
This commit is contained in:
Rostislav Wolny
2021-03-19 16:31:21 +01:00
committed by Veljko V
parent 9ffc3372e6
commit f066bc8fdd
3 changed files with 65 additions and 1 deletions

View File

@ -10,6 +10,7 @@ use MailPoet\API\JSON\ResponseBuilders\DynamicSegmentsResponseBuilder;
use MailPoet\Config\AccessControl;
use MailPoet\Entities\SegmentEntity;
use MailPoet\Listing\Handler;
use MailPoet\Newsletter\Segment\NewsletterSegmentRepository;
use MailPoet\Segments\DynamicSegments\DynamicSegmentsListingRepository;
use MailPoet\Segments\DynamicSegments\Exceptions\InvalidFilterException;
use MailPoet\Segments\DynamicSegments\FilterDataMapper;
@ -46,6 +47,9 @@ class DynamicSegments extends APIEndpoint {
/** @var FilterDataMapper */
private $filterDataMapper;
/** @var NewsletterSegmentRepository */
private $newsletterSegmentRepository;
public function __construct(
Handler $handler,
DynamicSegmentsListingRepository $dynamicSegmentsListingRepository,
@ -53,7 +57,8 @@ class DynamicSegments extends APIEndpoint {
SegmentsRepository $segmentsRepository,
SegmentSubscribersRepository $segmentSubscribersRepository,
FilterDataMapper $filterDataMapper,
SegmentSaveController $saveController
SegmentSaveController $saveController,
NewsletterSegmentRepository $newsletterSegmentRepository
) {
$this->listingHandler = $handler;
$this->dynamicSegmentsListingRepository = $dynamicSegmentsListingRepository;
@ -62,6 +67,7 @@ class DynamicSegments extends APIEndpoint {
$this->saveController = $saveController;
$this->segmentSubscribersRepository = $segmentSubscribersRepository;
$this->filterDataMapper = $filterDataMapper;
$this->newsletterSegmentRepository = $newsletterSegmentRepository;
}
public function get($data = []) {
@ -148,6 +154,17 @@ class DynamicSegments extends APIEndpoint {
]);
}
$activelyUsedNewslettersSubjects = $this->newsletterSegmentRepository->getSubjectsOfActivelyUsedEmailsForSegments([$segment->getId()]);
if (isset($activelyUsedNewslettersSubjects[$segment->getId()])) {
return $this->badRequest([
Error::BAD_REQUEST => str_replace(
'%$1s',
$activelyUsedNewslettersSubjects[$segment->getId()][0],
_x('List cannot be deleted because its used for %$1s email', 'Alert shown when trying to delete segment, which is assigned to any automatic emails.')
),
]);
}
$this->segmentsRepository->bulkTrash([$segment->getId()], SegmentEntity::TYPE_DYNAMIC);
return $this->successResponse(
$this->segmentsResponseBuilder->build($segment),

View File

@ -14,6 +14,32 @@ class NewsletterSegmentRepository extends Repository {
return NewsletterSegmentEntity::class;
}
public function getSubjectsOfActivelyUsedEmailsForSegments(array $segmentIds): array {
$results = $this->doctrineRepository->createQueryBuilder('ns')
->join('ns.newsletter', 'n')
->leftJoin('n.queues', 'q')
->leftJoin('q.task', 't')
->select('IDENTITY(ns.segment) AS segment_id, n.subject')
->where('(n.type IN (:types) OR n.status = :scheduled OR (t.id IS NOT NULL AND t.status IS NULL))')
->andWhere('ns.segment IN (:segmentIds)')
->setParameter('types', [
NewsletterEntity::TYPE_AUTOMATIC,
NewsletterEntity::TYPE_WELCOME,
NewsletterEntity::TYPE_NOTIFICATION,
])
->setParameter('segmentIds', $segmentIds)
->setParameter('scheduled', NewsletterEntity::STATUS_SCHEDULED)
->addGroupBy('n.id, q.id, t.id')
->getQuery()
->getResult();
$nameMap = [];
foreach ($results as $result) {
$nameMap[(string)$result['segment_id']][] = $result['subject'];
}
return $nameMap;
}
public function getAutomatedEmailSubjectsBySegmentIds(array $segmentIds): array {
$results = $this->doctrineRepository->createQueryBuilder('ns')
->join('ns.newsletter', 'n')

View File

@ -2,9 +2,12 @@
namespace MailPoet\API\JSON\v1;
use MailPoet\API\JSON\Response as APIResponse;
use MailPoet\DI\ContainerWrapper;
use MailPoet\Entities\DynamicSegmentFilterData;
use MailPoet\Entities\DynamicSegmentFilterEntity;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Entities\NewsletterSegmentEntity;
use MailPoet\Entities\SegmentEntity;
class DynamicSegmentsTest extends \MailPoetTest {
@ -83,6 +86,22 @@ class DynamicSegmentsTest extends \MailPoetTest {
expect($dynamicSegment->getDeletedAt())->notNull();
}
public function testItReturnsErrorWhenTrashingSegmentWithActiveNewsletter() {
$dynamicSegment = $this->createDynamicSegmentEntity('Trash test 2', 'description');
$newsletter = new NewsletterEntity();
$newsletter->setSubject('Subject');
$newsletter->setType(NewsletterEntity::TYPE_WELCOME);
$newsletterSegment = new NewsletterSegmentEntity($newsletter, $dynamicSegment);
$this->entityManager->persist($newsletter);
$this->entityManager->persist($newsletterSegment);
$this->entityManager->flush();
$response = $this->endpoint->trash(['id' => $dynamicSegment->getId()]);
$this->entityManager->refresh($dynamicSegment);
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
expect($response->errors[0]['message'])->equals("List cannot be deleted because its used for 'Subject' email");
}
public function testItCanRestoreASegment() {
$dynamicSegment = $this->createDynamicSegmentEntity('Trash test', 'description');
@ -187,5 +206,7 @@ class DynamicSegmentsTest extends \MailPoetTest {
parent::_after();
$this->truncateEntity(SegmentEntity::class);
$this->truncateEntity(DynamicSegmentFilterEntity::class);
$this->truncateEntity(NewsletterSegmentEntity::class);
$this->truncateEntity(NewsletterEntity::class);
}
}