Add deleting closely related entities into newsletter bulk delete
[MAILPOET-2898]
This commit is contained in:
committed by
Veljko V
parent
913029165a
commit
01b61abc28
@ -10,6 +10,7 @@ use MailPoet\AutomaticEmails\WooCommerce\Events\PurchasedProduct;
|
|||||||
use MailPoet\Doctrine\Repository;
|
use MailPoet\Doctrine\Repository;
|
||||||
use MailPoet\Entities\NewsletterEntity;
|
use MailPoet\Entities\NewsletterEntity;
|
||||||
use MailPoet\Entities\NewsletterOptionFieldEntity;
|
use MailPoet\Entities\NewsletterOptionFieldEntity;
|
||||||
|
use MailPoet\Entities\NewsletterSegmentEntity;
|
||||||
use MailPoet\Entities\ScheduledTaskEntity;
|
use MailPoet\Entities\ScheduledTaskEntity;
|
||||||
use MailPoet\Entities\SendingQueueEntity;
|
use MailPoet\Entities\SendingQueueEntity;
|
||||||
use MailPoetVendor\Carbon\Carbon;
|
use MailPoetVendor\Carbon\Carbon;
|
||||||
@ -133,7 +134,7 @@ class NewslettersRepository extends Repository {
|
|||||||
WHERE q.`newsletter_id` IN (:ids)
|
WHERE q.`newsletter_id` IN (:ids)
|
||||||
", ['ids' => $ids], ['ids' => Connection::PARAM_INT_ARRAY]);
|
", ['ids' => $ids], ['ids' => Connection::PARAM_INT_ARRAY]);
|
||||||
|
|
||||||
// Trash scheduled tasks
|
// Trash sending queues tasks
|
||||||
$this->entityManager->getConnection()->executeUpdate("
|
$this->entityManager->getConnection()->executeUpdate("
|
||||||
UPDATE $sendingQueueTable q
|
UPDATE $sendingQueueTable q
|
||||||
SET q.`deleted_at` = NOW()
|
SET q.`deleted_at` = NOW()
|
||||||
@ -201,10 +202,45 @@ class NewslettersRepository extends Repository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function bulkDelete(array $ids) {
|
public function bulkDelete(array $ids) {
|
||||||
|
// Delete children
|
||||||
|
$childrenIds = $this->entityManager->createQueryBuilder()->select( 'n.id')
|
||||||
|
->from(NewsletterEntity::class, 'n')
|
||||||
|
->where('n.parent IN (:ids)')
|
||||||
|
->setParameter('ids', $ids)
|
||||||
|
->getQuery()->getScalarResult();
|
||||||
|
$deletedChildrenCount = 0;
|
||||||
|
if (count($childrenIds)) {
|
||||||
|
$deletedChildrenCount = $this->bulkDelete(array_column($childrenIds, 'id'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete scheduled tasks and queues
|
||||||
|
$scheduledTasksTable = $this->entityManager->getClassMetadata(ScheduledTaskEntity::class)->getTableName();
|
||||||
|
$sendingQueueTable = $this->entityManager->getClassMetadata(SendingQueueEntity::class)->getTableName();
|
||||||
|
$this->entityManager->getConnection()->executeUpdate("
|
||||||
|
DELETE t FROM $scheduledTasksTable t
|
||||||
|
JOIN $sendingQueueTable q ON t.`id` = q.`task_id`
|
||||||
|
WHERE q.`newsletter_id` IN (:ids)
|
||||||
|
", ['ids' => $ids], ['ids' => Connection::PARAM_INT_ARRAY]);
|
||||||
|
|
||||||
|
// Delete sending queues
|
||||||
|
$this->entityManager->getConnection()->executeUpdate("
|
||||||
|
DELETE q FROM $sendingQueueTable q
|
||||||
|
WHERE q.`newsletter_id` IN (:ids)
|
||||||
|
", ['ids' => $ids], ['ids' => Connection::PARAM_INT_ARRAY]);
|
||||||
|
|
||||||
|
// Delete newsletter segments
|
||||||
|
$newsletterSegmentsTable = $this->entityManager->getClassMetadata(NewsletterSegmentEntity::class)->getTableName();
|
||||||
|
$this->entityManager->getConnection()->executeUpdate("
|
||||||
|
DELETE ns FROM $newsletterSegmentsTable ns
|
||||||
|
WHERE ns.`newsletter_id` IN (:ids)
|
||||||
|
", ['ids' => $ids], ['ids' => Connection::PARAM_INT_ARRAY]);
|
||||||
|
|
||||||
$queryBuilder = $this->entityManager->createQueryBuilder();
|
$queryBuilder = $this->entityManager->createQueryBuilder();
|
||||||
$queryBuilder->delete(NewsletterEntity::class, 'n')
|
$queryBuilder->delete(NewsletterEntity::class, 'n')
|
||||||
->where('n.id IN (:ids)')
|
->where('n.id IN (:ids)')
|
||||||
->setParameter('ids', $ids)
|
->setParameter('ids', $ids)
|
||||||
->getQuery()->execute();
|
->getQuery()->execute();
|
||||||
|
|
||||||
|
return $deletedChildrenCount + count($ids);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,9 @@ namespace MailPoet\Newsletter;
|
|||||||
|
|
||||||
use Codeception\Util\Fixtures;
|
use Codeception\Util\Fixtures;
|
||||||
use MailPoet\Entities\NewsletterEntity;
|
use MailPoet\Entities\NewsletterEntity;
|
||||||
|
use MailPoet\Entities\NewsletterSegmentEntity;
|
||||||
use MailPoet\Entities\ScheduledTaskEntity;
|
use MailPoet\Entities\ScheduledTaskEntity;
|
||||||
|
use MailPoet\Entities\SegmentEntity;
|
||||||
use MailPoet\Entities\SendingQueueEntity;
|
use MailPoet\Entities\SendingQueueEntity;
|
||||||
use MailPoet\Tasks\Sending as SendingTask;
|
use MailPoet\Tasks\Sending as SendingTask;
|
||||||
|
|
||||||
@ -20,10 +22,10 @@ class NewsletterRepositoryTest extends \MailPoetTest {
|
|||||||
|
|
||||||
public function testItBulkTrashNewslettersAndChildren() {
|
public function testItBulkTrashNewslettersAndChildren() {
|
||||||
$newsletter1 = $this->createNewsletter(NewsletterEntity::TYPE_STANDARD);
|
$newsletter1 = $this->createNewsletter(NewsletterEntity::TYPE_STANDARD);
|
||||||
$this->createQueueWithTask($newsletter1);
|
$this->createQueueWithTaskAndSegment($newsletter1);
|
||||||
$newsletter2 = $this->createNewsletter(NewsletterEntity::TYPE_NOTIFICATION, NewsletterEntity::STATUS_ACTIVE);
|
$newsletter2 = $this->createNewsletter(NewsletterEntity::TYPE_NOTIFICATION, NewsletterEntity::STATUS_ACTIVE);
|
||||||
$newsletter2Child1 = $this->createNewsletter(NewsletterEntity::TYPE_NOTIFICATION, NewsletterEntity::STATUS_SCHEDULED, $newsletter2);
|
$newsletter2Child1 = $this->createNewsletter(NewsletterEntity::TYPE_NOTIFICATION, NewsletterEntity::STATUS_SCHEDULED, $newsletter2);
|
||||||
$this->createQueueWithTask($newsletter2Child1);
|
$this->createQueueWithTaskAndSegment($newsletter2Child1);
|
||||||
$this->repository->bulkTrash([$newsletter1->getId(), $newsletter2->getId()]);
|
$this->repository->bulkTrash([$newsletter1->getId(), $newsletter2->getId()]);
|
||||||
$this->entityManager->refresh($newsletter1);
|
$this->entityManager->refresh($newsletter1);
|
||||||
$this->entityManager->refresh($newsletter2);
|
$this->entityManager->refresh($newsletter2);
|
||||||
@ -57,10 +59,10 @@ class NewsletterRepositoryTest extends \MailPoetTest {
|
|||||||
|
|
||||||
public function testItBulkRestoresNewslettersAndChildren() {
|
public function testItBulkRestoresNewslettersAndChildren() {
|
||||||
$newsletter1 = $this->createNewsletter(NewsletterEntity::TYPE_STANDARD, NewsletterEntity::STATUS_SENDING);
|
$newsletter1 = $this->createNewsletter(NewsletterEntity::TYPE_STANDARD, NewsletterEntity::STATUS_SENDING);
|
||||||
$this->createQueueWithTask($newsletter1, null); // Null for scheduled task being processed
|
$this->createQueueWithTaskAndSegment($newsletter1, null); // Null for scheduled task being processed
|
||||||
$newsletter2 = $this->createNewsletter(NewsletterEntity::TYPE_NOTIFICATION, NewsletterEntity::STATUS_ACTIVE);
|
$newsletter2 = $this->createNewsletter(NewsletterEntity::TYPE_NOTIFICATION, NewsletterEntity::STATUS_ACTIVE);
|
||||||
$newsletter2Child1 = $this->createNewsletter(NewsletterEntity::TYPE_NOTIFICATION, NewsletterEntity::STATUS_SCHEDULED, $newsletter2);
|
$newsletter2Child1 = $this->createNewsletter(NewsletterEntity::TYPE_NOTIFICATION, NewsletterEntity::STATUS_SCHEDULED, $newsletter2);
|
||||||
$this->createQueueWithTask($newsletter2Child1);
|
$this->createQueueWithTaskAndSegment($newsletter2Child1);
|
||||||
// Trash
|
// Trash
|
||||||
$this->repository->bulkTrash([$newsletter1->getId(), $newsletter2->getId()]);
|
$this->repository->bulkTrash([$newsletter1->getId(), $newsletter2->getId()]);
|
||||||
// Restore
|
// Restore
|
||||||
@ -100,6 +102,60 @@ class NewsletterRepositoryTest extends \MailPoetTest {
|
|||||||
expect($scheduledTask->getDeletedAt())->null();
|
expect($scheduledTask->getDeletedAt())->null();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testItBulkDeleteNewslettersAndChildren() {
|
||||||
|
$newsletter1 = $this->createNewsletter(NewsletterEntity::TYPE_STANDARD, NewsletterEntity::STATUS_SENDING);
|
||||||
|
$this->createQueueWithTaskAndSegment($newsletter1, null); // Null for scheduled task being processed
|
||||||
|
$newsletter2 = $this->createNewsletter(NewsletterEntity::TYPE_NOTIFICATION, NewsletterEntity::STATUS_ACTIVE);
|
||||||
|
$newsletter2Child1 = $this->createNewsletter(NewsletterEntity::TYPE_NOTIFICATION, NewsletterEntity::STATUS_SCHEDULED, $newsletter2);
|
||||||
|
$this->createQueueWithTaskAndSegment($newsletter2Child1);
|
||||||
|
// Trash
|
||||||
|
$this->repository->bulkTrash([$newsletter1->getId(), $newsletter2->getId()]);
|
||||||
|
$newsletter1Queue = $newsletter1->getLatestQueue();
|
||||||
|
assert($newsletter1Queue instanceof SendingQueueEntity);
|
||||||
|
$newsletter1Segment = $newsletter1->getNewsletterSegments()->first();
|
||||||
|
assert($newsletter1Segment instanceof NewsletterSegmentEntity);
|
||||||
|
$childrenQueue = $newsletter2Child1->getLatestQueue();
|
||||||
|
assert($childrenQueue instanceof SendingQueueEntity);
|
||||||
|
$scheduledTask1 = $newsletter1Queue->getTask();
|
||||||
|
assert($scheduledTask1 instanceof ScheduledTaskEntity);
|
||||||
|
$childrenScheduledTask = $childrenQueue->getTask();
|
||||||
|
assert($childrenScheduledTask instanceof ScheduledTaskEntity);
|
||||||
|
$childSegment = $newsletter2Child1->getNewsletterSegments()->first();
|
||||||
|
assert($childSegment instanceof NewsletterSegmentEntity);
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
$this->repository->bulkDelete([$newsletter1->getId(), $newsletter2->getId()]);
|
||||||
|
|
||||||
|
// Detach entities so that ORM forget them
|
||||||
|
$this->entityManager->detach($newsletter1);
|
||||||
|
$this->entityManager->detach($newsletter2);
|
||||||
|
$this->entityManager->detach($newsletter2Child1);
|
||||||
|
$this->entityManager->detach($newsletter1Queue);
|
||||||
|
$this->entityManager->detach($childrenQueue);
|
||||||
|
$this->entityManager->detach($scheduledTask1);
|
||||||
|
$this->entityManager->detach($childrenScheduledTask);
|
||||||
|
$this->entityManager->detach($newsletter1Segment);
|
||||||
|
$this->entityManager->detach($childSegment);
|
||||||
|
|
||||||
|
// Check they were all deleted
|
||||||
|
// Newsletters
|
||||||
|
expect($this->repository->findOneById($newsletter1->getId()))->null();
|
||||||
|
expect($this->repository->findOneById($newsletter2->getId()))->null();
|
||||||
|
expect($this->repository->findOneById($newsletter2Child1->getId()))->null();
|
||||||
|
|
||||||
|
// Sending queues
|
||||||
|
expect($this->entityManager->find(SendingQueueEntity::class, $newsletter1Queue->getId()))->null();
|
||||||
|
expect($this->entityManager->find(SendingQueueEntity::class, $childrenQueue->getId()))->null();
|
||||||
|
|
||||||
|
// Scheduled tasks
|
||||||
|
expect($this->entityManager->find(ScheduledTaskEntity::class, $scheduledTask1->getId()))->null();
|
||||||
|
expect($this->entityManager->find(ScheduledTaskEntity::class, $childrenScheduledTask->getId()))->null();
|
||||||
|
|
||||||
|
// Newsletter segments
|
||||||
|
expect($this->entityManager->find(NewsletterSegmentEntity::class, $newsletter1Segment->getId()))->null();
|
||||||
|
expect($this->entityManager->find(NewsletterSegmentEntity::class, $childSegment->getId()))->null();
|
||||||
|
}
|
||||||
|
|
||||||
public function _after() {
|
public function _after() {
|
||||||
$this->cleanup();
|
$this->cleanup();
|
||||||
}
|
}
|
||||||
@ -116,7 +172,7 @@ class NewsletterRepositoryTest extends \MailPoetTest {
|
|||||||
return $newsletter;
|
return $newsletter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createQueueWithTask(NewsletterEntity $newsletter, $status = ScheduledTaskEntity::STATUS_SCHEDULED): SendingQueueEntity {
|
private function createQueueWithTaskAndSegment(NewsletterEntity $newsletter, $status = ScheduledTaskEntity::STATUS_SCHEDULED): SendingQueueEntity {
|
||||||
$task = new ScheduledTaskEntity();
|
$task = new ScheduledTaskEntity();
|
||||||
$task->setType(SendingTask::TASK_TYPE);
|
$task->setType(SendingTask::TASK_TYPE);
|
||||||
$task->setStatus($status);
|
$task->setStatus($status);
|
||||||
@ -126,8 +182,17 @@ class NewsletterRepositoryTest extends \MailPoetTest {
|
|||||||
$queue->setNewsletter($newsletter);
|
$queue->setNewsletter($newsletter);
|
||||||
$queue->setTask($task);
|
$queue->setTask($task);
|
||||||
$this->entityManager->persist($queue);
|
$this->entityManager->persist($queue);
|
||||||
|
|
||||||
$newsletter->getQueues()->add($queue);
|
$newsletter->getQueues()->add($queue);
|
||||||
|
|
||||||
|
$segment = new SegmentEntity();
|
||||||
|
$segment->setType(SegmentEntity::TYPE_DEFAULT);
|
||||||
|
$segment->setName(" List for newsletter id {$newsletter->getId()}");
|
||||||
|
$segment->setDescription('');
|
||||||
|
$this->entityManager->persist($segment);
|
||||||
|
|
||||||
|
$newsletterSegment = new NewsletterSegmentEntity($newsletter, $segment);
|
||||||
|
$newsletter->getNewsletterSegments()->add($newsletterSegment);
|
||||||
|
$this->entityManager->persist($newsletterSegment);
|
||||||
$this->entityManager->flush();
|
$this->entityManager->flush();
|
||||||
return $queue;
|
return $queue;
|
||||||
}
|
}
|
||||||
@ -136,5 +201,7 @@ class NewsletterRepositoryTest extends \MailPoetTest {
|
|||||||
$this->truncateEntity(NewsletterEntity::class);
|
$this->truncateEntity(NewsletterEntity::class);
|
||||||
$this->truncateEntity(ScheduledTaskEntity::class);
|
$this->truncateEntity(ScheduledTaskEntity::class);
|
||||||
$this->truncateEntity(SendingQueueEntity::class);
|
$this->truncateEntity(SendingQueueEntity::class);
|
||||||
|
$this->truncateEntity(NewsletterSegmentEntity::class);
|
||||||
|
$this->truncateEntity(SegmentEntity::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user