diff --git a/lib/Models/Newsletter.php b/lib/Models/Newsletter.php index 634abb2b57..6d9bdbfa2e 100644 --- a/lib/Models/Newsletter.php +++ b/lib/Models/Newsletter.php @@ -94,62 +94,111 @@ class Newsletter extends Model { function trash() { // trash queue associations - SendingQueue::rawExecute( - 'UPDATE `' . SendingQueue::$_table . '` ' . - 'SET `deleted_at` = NOW() ' . - 'WHERE `newsletter_id` = ' . $this->id - ); + $children = $this->children()->select('id')->findArray(); + if($children) { + $this->children()->rawExecute( + 'UPDATE `' . self::$_table . '` ' . + 'SET `deleted_at` = NOW() ' . + 'WHERE `parent_id` = ' . $this->id + ); + SendingQueue::rawExecute( + 'UPDATE `' . SendingQueue::$_table . '` ' . + 'SET `deleted_at` = NOW() ' . + 'WHERE `newsletter_id` IN (' . join(',', array_merge(Helpers::flattenArray($children), array($this->id))) . ')' + ); + } else { + SendingQueue::rawExecute( + 'UPDATE `' . SendingQueue::$_table . '` ' . + 'SET `deleted_at` = NOW() ' . + 'WHERE `newsletter_id` = ' . $this->id + ); + } return parent::trash(); } static function bulkTrash($orm) { - // bulk trash queue associations + // bulk trash queue and notification history associations parent::bulkAction($orm, function($ids) { - SendingQueue::rawExecute(join(' ', array( - 'UPDATE `' . SendingQueue::$_table . '`', - 'SET `deleted_at` = NOW()', - 'WHERE `newsletter_id` IN (' . rtrim(str_repeat('?,', count($ids)), ',') . ')' - )), - $ids - ); + $children = Newsletter::whereIn('parent_id', $ids)->select('id')->findArray(); + if($children) { + Newsletter::rawExecute( + 'UPDATE `' . Newsletter::$_table . '` ' . + 'SET `deleted_at` = NOW() ' . + 'WHERE `parent_id` IN (' . join(',', Helpers::flattenArray($ids)) . ')' + ); + SendingQueue::rawExecute( + 'UPDATE `' . SendingQueue::$_table . '` ' . + 'SET `deleted_at` = NOW() ' . + 'WHERE `newsletter_id` IN (' . join(',', array_merge(Helpers::flattenArray($children), $ids)) . ')' + ); + } else { + SendingQueue::rawExecute( + 'UPDATE `' . SendingQueue::$_table . '` ' . + 'SET `deleted_at` = NOW() ' . + 'WHERE `newsletter_id` IN (' . join(',', Helpers::flattenArray($ids)) . ')' + ); + } }); return parent::bulkTrash($orm); } function delete() { - // delete segment associations - $this->segmentRelations()->deleteMany(); - // delete queue associations - $this->queue()->deleteMany(); + // delete queue, notification history and segment associations + $children = $this->children()->select('id')->findArray(); + if($children) { + $children = Helpers::flattenArray($children); + $this->children()->deleteMany(); + SendingQueue::whereIn('newsletter_id', array_merge($children, array($this->id)))->deleteMany(); + NewsletterSegment::whereIn('newsletter_id', array_merge($children, array($this->id)))->deleteMany(); + } else { + $this->queue()->deleteMany(); + $this->segmentRelations()->deleteMany(); + } return parent::delete(); } static function bulkDelete($orm) { - // bulk delete segment associations + // bulk delete queue, notification history and segment associations parent::bulkAction($orm, function($ids) { - NewsletterSegment::whereIn('newsletter_id', $ids) - ->deleteMany(); - }); - - // bulk delete queue associations - parent::bulkAction($orm, function($ids) { - SendingQueue::whereIn('newsletter_id', $ids) - ->deleteMany(); + $children = Newsletter::whereIn('parent_id', $ids)->select('id')->findArray(); + if($children) { + $children = Helpers::flattenArray($children); + Newsletter::whereIn('parent_id', $ids)->deleteMany(); + SendingQueue::whereIn('newsletter_id', array_merge($children, $ids))->deleteMany(); + NewsletterSegment::whereIn('newsletter_id', array_merge($children, $ids))->deleteMany(); + } else { + SendingQueue::whereIn('newsletter_id', $ids)->deleteMany(); + NewsletterSegment::whereIn('newsletter_id', $ids)->deleteMany(); + } }); return parent::bulkDelete($orm); } function restore() { - // restore trashed queue associations - SendingQueue::rawExecute( - 'UPDATE `' . SendingQueue::$_table . '` ' . - 'SET `deleted_at` = null ' . - 'WHERE `newsletter_id` = ' . $this->id - ); + // restore trashed queue and notification history associations + $children = $this->children()->select('id')->findArray(); + if($children) { + $this->children()->rawExecute( + 'UPDATE `' . self::$_table . '` ' . + 'SET `deleted_at` = null ' . + 'WHERE `parent_id` = ' . $this->id + ); + SendingQueue::rawExecute( + 'UPDATE `' . SendingQueue::$_table . '` ' . + 'SET `deleted_at` = null ' . + 'WHERE `newsletter_id` IN (' . join(',', array_merge(Helpers::flattenArray($children), array($this->id))) . ')' + ); + } else { + SendingQueue::rawExecute( + 'UPDATE `' . SendingQueue::$_table . '` ' . + 'SET `deleted_at` = null ' . + 'WHERE `newsletter_id` = ' . $this->id + ); + } if($this->status == self::STATUS_SENDING) { $this->set('status', self::STATUS_DRAFT); @@ -159,13 +208,27 @@ class Newsletter extends Model { } static function bulkRestore($orm) { - // bulk restore trashed queue associations + // bulk restore trashed queue and notification history associations parent::bulkAction($orm, function($ids) { - SendingQueue::whereIn('newsletter_id', $ids) - ->whereNotNull('deleted_at') - ->findResultSet() - ->set('deleted_at', null) - ->save(); + $children = Newsletter::whereIn('parent_id', $ids)->select('id')->findArray(); + if($children) { + Newsletter::whereIn('parent_id', $ids) + ->whereNotNull('deleted_at') + ->findResultSet() + ->set('deleted_at', null) + ->save(); + SendingQueue::whereIn('newsletter_id', Helpers::flattenArray($children)) + ->whereNotNull('deleted_at') + ->findResultSet() + ->set('deleted_at', null) + ->save(); + } else { + SendingQueue::whereIn('newsletter_id', $ids) + ->whereNotNull('deleted_at') + ->findResultSet() + ->set('deleted_at', null) + ->save(); + } }); parent::bulkAction($orm, function($ids) { diff --git a/tests/unit/Models/NewsletterTest.php b/tests/unit/Models/NewsletterTest.php index b3a124b7bd..9310eeeb82 100644 --- a/tests/unit/Models/NewsletterTest.php +++ b/tests/unit/Models/NewsletterTest.php @@ -459,6 +459,39 @@ class NewsletterTest extends MailPoetTest { expect($newsletter_segments)->isEmpty(); } + function testItDeletesChildrenSegmentAndQueueAssociationsWhenParentNewsletterIsDeleted() { + $parent_newsletter = $this->newsletter; + // create multiple children (post notification history) newsletters and sending queues + for($i = 1; $i <= 5; $i++) { + $newsletter = Newsletter::createOrUpdate( + array( + 'subject' => 'test', + 'type' => Newsletter::TYPE_NOTIFICATION_HISTORY, + 'parent_id' => $parent_newsletter->id + ) + ); + $sending_queue = SendingQueue::create(); + $sending_queue->newsletter_id = $newsletter->id; + $sending_queue->save(); + $newsletter_segment = NewsletterSegment::create(); + $newsletter_segment->newsletter_id = $newsletter->id; + $newsletter_segment->segment_id = 1; + $newsletter_segment->save(); + } + + // make sure relations exist + // 1 parent newsletter/queues, 2 parent segments and 5 children queues/newsletters/segments + expect(Newsletter::findArray())->count(6); + expect(SendingQueue::findArray())->count(6); + expect(NewsletterSegment::findArray())->count(7); + + // delete parent newsletter and check that relations no longer exist + $parent_newsletter->delete(); + expect(Newsletter::findArray())->count(0); + expect(SendingQueue::findArray())->count(0); + expect(NewsletterSegment::findArray())->count(0); + } + function testItTrashesQueueAssociationsWhenNewsletterIsTrashed() { // create multiple sending queues $newsletter = $this->newsletter; @@ -475,6 +508,32 @@ class NewsletterTest extends MailPoetTest { expect(SendingQueue::whereNotNull('deleted_at')->findArray())->count(6); } + function testItTrashesChildrenQueueAssociationsWhenParentNewsletterIsTrashed() { + $parent_newsletter = $this->newsletter; + // create multiple children (post notification history) newsletters and sending queues + for($i = 1; $i <= 5; $i++) { + $newsletter = Newsletter::createOrUpdate( + array( + 'subject' => 'test', + 'type' => Newsletter::TYPE_NOTIFICATION_HISTORY, + 'parent_id' => $parent_newsletter->id + ) + ); + $sending_queue = SendingQueue::create(); + $sending_queue->newsletter_id = $newsletter->id; + $sending_queue->save(); + } + // 1 parent and 5 children queues/newsletters + expect(Newsletter::whereNull('deleted_at')->findArray())->count(6); + expect(SendingQueue::whereNull('deleted_at')->findArray())->count(6); + + // trash parent newsletter and check that relations are trashed + $parent_newsletter->trash(); + // 1 parent and 5 children queues/newsletters + expect(Newsletter::whereNotNull('deleted_at')->findArray())->count(6); + expect(SendingQueue::whereNotNull('deleted_at')->findArray())->count(6); + } + function testItRestoresTrashedQueueAssociationsWhenNewsletterIsRestored() { // create multiple sending queues $newsletter = $this->newsletter; @@ -492,6 +551,41 @@ class NewsletterTest extends MailPoetTest { expect(SendingQueue::whereNull('deleted_at')->findArray())->count(6); } + function testItRestoresTrashedChildrenQueueAssociationsWhenParentNewsletterIsRestored() { + // delete parent newsletter and sending queue + $parent_newsletter = $this->newsletter; + $parent_newsletter->deleted_at = date('Y-m-d H:i:s'); + $parent_newsletter->save(); + $parent_sending_queue = $this->sending_queue; + $parent_sending_queue->deleted_at = date('Y-m-d H:i:s'); + $parent_sending_queue->save(); + + // create multiple children (post notification history) newsletters and sending queues + for($i = 1; $i <= 5; $i++) { + $newsletter = Newsletter::createOrUpdate( + array( + 'subject' => 'test', + 'type' => Newsletter::TYPE_NOTIFICATION_HISTORY, + 'parent_id' => $parent_newsletter->id, + 'deleted_at' => date('Y-m-d H:i:s') + ) + ); + $sending_queue = SendingQueue::create(); + $sending_queue->newsletter_id = $newsletter->id; + $sending_queue->deleted_at = date('Y-m-d H:i:s'); + $sending_queue->save(); + } + // 1 parent and 5 children queues/newsletters + expect(Newsletter::whereNotNull('deleted_at')->findArray())->count(6); + expect(SendingQueue::whereNotNull('deleted_at')->findArray())->count(6); + + // restore parent newsletter and check that relations are restored + $parent_newsletter->restore(); + // 1 parent and 5 children queues/newsletters + expect(Newsletter::whereNull('deleted_at')->findArray())->count(6); + expect(SendingQueue::whereNull('deleted_at')->findArray())->count(6); + } + function testItTrashesAllQueueAssociationsWhenNewslettersAreBulkTrashed() { // create multiple newsletters and sending queues for($i = 1; $i <= 5; $i++) { @@ -515,6 +609,30 @@ class NewsletterTest extends MailPoetTest { expect(SendingQueue::whereNotNull('deleted_at')->findArray())->count(6); } + function testItTrashesAllChildrenQueueAssociationsWhenParentNewslettersAreBulkTrashed() { + // create multiple children (post notification history) newsletters and sending queues + for($i = 1; $i <= 5; $i++) { + $newsletter = Newsletter::createOrUpdate( + array( + 'subject' => 'test', + 'type' => Newsletter::TYPE_NOTIFICATION_HISTORY, + 'parent_id' => $this->newsletter->id, + ) + ); + $sending_queue = SendingQueue::create(); + $sending_queue->newsletter_id = $newsletter->id; + $sending_queue->save(); + } + // 5 queues/newsletters + 1 of each created in _before() method + expect(Newsletter::whereNull('deleted_at')->findArray())->count(6); + expect(SendingQueue::whereNull('deleted_at')->findArray())->count(6); + + // bulk trash parent newsletters and check that relations are trashed + Newsletter::bulkTrash(ORM::forTable(Newsletter::$_table)); + expect(Newsletter::whereNotNull('deleted_at')->findArray())->count(6); + expect(SendingQueue::whereNotNull('deleted_at')->findArray())->count(6); + } + function testItBulkRestoresTrashedQueueAssociationsWhenNewslettersAreBulkRestored() { // create multiple newsletters and sending queues for($i = 1; $i <= 5; $i++) { @@ -540,6 +658,32 @@ class NewsletterTest extends MailPoetTest { expect(SendingQueue::whereNull('deleted_at')->findArray())->count(6); } + function testItBulkRestoresTrashedChildrenQueueAssociationsWhenParentNewslettersAreBulkRestored() { + // create multiple children (post notification history) newsletters and sending queues + for($i = 1; $i <= 5; $i++) { + $newsletter = Newsletter::createOrUpdate( + array( + 'subject' => 'test', + 'type' => Newsletter::TYPE_NOTIFICATION_HISTORY, + 'parent_id' => $this->newsletter->id, + 'deleted_at' => date('Y-m-d H:i:s') + ) + ); + $sending_queue = SendingQueue::create(); + $sending_queue->newsletter_id = $newsletter->id; + $sending_queue->deleted_at = date('Y-m-d H:i:s'); + $sending_queue->save(); + } + expect(Newsletter::whereNotNull('deleted_at')->findArray())->count(5); + expect(SendingQueue::whereNotNull('deleted_at')->findArray())->count(5); + + // bulk restore parent newsletters and check that relations are restored + Newsletter::bulkRestore(ORM::forTable(Newsletter::$_table)); + // 1 parent and 5 queues/newsletters + expect(Newsletter::whereNull('deleted_at')->findArray())->count(6); + expect(SendingQueue::whereNull('deleted_at')->findArray())->count(6); + } + function testItBulkDeletesSegmentAndQueueAssociationsWhenNewslettersAreBulkDeleted() { // create multiple newsletters, sending queues and newsletter segments for($i = 1; $i <= 5; $i++) { @@ -570,6 +714,37 @@ class NewsletterTest extends MailPoetTest { expect(NewsletterSegment::findArray())->count(0); } + function testItBulkDeletesChildrenSegmentAndQueueAssociationsWhenParentNewslettersAreBulkDeleted() { + $this->_after(); + // create multiple children (post notification history) newsletters, sending queues and newsletter segments + for($i = 1; $i <= 5; $i++) { + $newsletter = Newsletter::createOrUpdate( + array( + 'subject' => 'test', + 'type' => Newsletter::TYPE_NOTIFICATION_HISTORY, + 'parent_id' => $this->newsletter->id + ) + ); + $sending_queue = SendingQueue::create(); + $sending_queue->newsletter_id = $newsletter->id; + $sending_queue->save(); + $newsletter_segment = NewsletterSegment::create(); + $newsletter_segment->newsletter_id = $newsletter->id; + $newsletter_segment->segment_id = 1; + $newsletter_segment->save(); + } + // 5 queues/newsletters/segment associations + expect(Newsletter::findArray())->count(5); + expect(SendingQueue::findArray())->count(5); + expect(NewsletterSegment::findArray())->count(5); + + // bulk delete newsletters and check that relations are deleted + Newsletter::bulkDelete(ORM::forTable(Newsletter::$_table)); + expect(Newsletter::findArray())->count(0); + expect(SendingQueue::findArray())->count(0); + expect(NewsletterSegment::findArray())->count(0); + } + function _after() { ORM::raw_execute('TRUNCATE ' . NewsletterOption::$_table); ORM::raw_execute('TRUNCATE ' . Newsletter::$_table);