diff --git a/lib/DI/ContainerConfigurator.php b/lib/DI/ContainerConfigurator.php index 99417788c8..e8a0313af9 100644 --- a/lib/DI/ContainerConfigurator.php +++ b/lib/DI/ContainerConfigurator.php @@ -268,6 +268,7 @@ class ContainerConfigurator implements IContainerConfigurator { $container->autowire(\MailPoet\Newsletter\NewslettersRepository::class)->setPublic(true); $container->autowire(\MailPoet\Newsletter\Listing\NewsletterListingRepository::class)->setPublic(true); $container->autowire(\MailPoet\Newsletter\Preview\SendPreviewController::class); + $container->autowire(\MailPoet\Newsletter\Segment\NewsletterSegmentRepository::class); $container->autowire(\MailPoet\Newsletter\Statistics\NewsletterStatisticsRepository::class); $container->autowire(\MailPoet\Newsletter\Scheduler\WelcomeScheduler::class)->setPublic(true); $container->autowire(\MailPoet\Newsletter\Scheduler\PostNotificationScheduler::class); diff --git a/lib/Entities/NewsletterSegmentEntity.php b/lib/Entities/NewsletterSegmentEntity.php index 5957a552f6..c925b2d65d 100644 --- a/lib/Entities/NewsletterSegmentEntity.php +++ b/lib/Entities/NewsletterSegmentEntity.php @@ -30,6 +30,11 @@ class NewsletterSegmentEntity { */ private $segment; + public function __construct(NewsletterEntity $newsletter, SegmentEntity $segment) { + $this->newsletter = $newsletter; + $this->segment = $segment; + } + /** * @return NewsletterEntity|null */ @@ -38,10 +43,6 @@ class NewsletterSegmentEntity { return $this->newsletter; } - public function setNewsletter(NewsletterEntity $newsletter) { - $this->newsletter = $newsletter; - } - /** * @return SegmentEntity|null */ @@ -49,8 +50,4 @@ class NewsletterSegmentEntity { $this->safelyLoadToOneAssociation('segment'); return $this->segment; } - - public function setSegment(SegmentEntity $segment) { - $this->segment = $segment; - } } diff --git a/lib/Newsletter/NewsletterSaveController.php b/lib/Newsletter/NewsletterSaveController.php index b55696299d..18e9465b3d 100644 --- a/lib/Newsletter/NewsletterSaveController.php +++ b/lib/Newsletter/NewsletterSaveController.php @@ -4,14 +4,16 @@ namespace MailPoet\Newsletter; use MailPoet\Cron\Workers\SendingQueue\Tasks\Newsletter as NewsletterQueueTask; use MailPoet\Entities\NewsletterEntity; +use MailPoet\Entities\NewsletterSegmentEntity; +use MailPoet\Entities\SegmentEntity; use MailPoet\InvalidStateException; use MailPoet\Models\Newsletter; use MailPoet\Models\NewsletterOption; use MailPoet\Models\NewsletterOptionField; -use MailPoet\Models\NewsletterSegment; use MailPoet\Models\SendingQueue; use MailPoet\Newsletter\Scheduler\PostNotificationScheduler; use MailPoet\Newsletter\Scheduler\Scheduler; +use MailPoet\Newsletter\Segment\NewsletterSegmentRepository; use MailPoet\Newsletter\Url as NewsletterUrl; use MailPoet\NewsletterTemplates\NewsletterTemplatesRepository; use MailPoet\NotFoundException; @@ -20,6 +22,7 @@ use MailPoet\Settings\SettingsController; use MailPoet\UnexpectedValueException; use MailPoet\WP\Emoji; use MailPoet\WP\Functions as WPFunctions; +use MailPoetVendor\Doctrine\ORM\EntityManager; class NewsletterSaveController { /** @var AuthorizedEmailsController */ @@ -28,9 +31,15 @@ class NewsletterSaveController { /** @var Emoji */ private $emoji; + /** @var EntityManager */ + private $entityManager; + /** @var NewslettersRepository */ private $newslettersRepository; + /** @var NewsletterSegmentRepository */ + private $newsletterSegmentRepository; + /** @var NewsletterTemplatesRepository */ private $newsletterTemplatesRepository; @@ -46,7 +55,9 @@ class NewsletterSaveController { public function __construct( AuthorizedEmailsController $authorizedEmailsController, Emoji $emoji, + EntityManager $entityManager, NewslettersRepository $newslettersRepository, + NewsletterSegmentRepository $newsletterSegmentRepository, NewsletterTemplatesRepository $newsletterTemplatesRepository, PostNotificationScheduler $postNotificationScheduler, SettingsController $settings, @@ -54,7 +65,9 @@ class NewsletterSaveController { ) { $this->authorizedEmailsController = $authorizedEmailsController; $this->emoji = $emoji; + $this->entityManager = $entityManager; $this->newslettersRepository = $newslettersRepository; + $this->newsletterSegmentRepository = $newsletterSegmentRepository; $this->newsletterTemplatesRepository = $newsletterTemplatesRepository; $this->postNotificationScheduler = $postNotificationScheduler; $this->settings = $settings; @@ -83,6 +96,7 @@ class NewsletterSaveController { $newsletter = $this->getNewsletter($data); $this->updateNewsletter($newsletter, $data); + $this->updateSegments($newsletter, $data['segments'] ?? []); // fetch old model for back compatibility $newsletterModel = Newsletter::findOne((int)$data['id']); @@ -90,19 +104,6 @@ class NewsletterSaveController { throw new InvalidStateException(); } - $segments = $data['segments'] ?? []; - if ($segments) { - NewsletterSegment::where('newsletter_id', $newsletterModel->id) - ->deleteMany(); - foreach ($segments as $segment) { - if (!is_array($segment)) continue; - $relation = NewsletterSegment::create(); - $relation->segmentId = (int)$segment['id']; - $relation->newsletterId = $newsletterModel->id; - $relation->save(); - } - } - // save default sender if needed if (!$this->settings->get('sender') && !empty($data['sender_address']) && !empty($data['sender_name'])) { $this->settings->set('sender', [ @@ -221,4 +222,35 @@ class NewsletterSaveController { $this->newslettersRepository->flush(); } + + private function updateSegments(NewsletterEntity $newsletter, array $segments) { + $oldNewsletterSegments = $newsletter->getNewsletterSegments()->toArray(); + + // clear old & add new newsletter segments + $newsletter->getNewsletterSegments()->clear(); + foreach ($segments as $segment) { + if (!is_array($segment) || !isset($segment['id'])) { + continue; + } + + $segment = $this->entityManager->getReference(SegmentEntity::class, (int)$segment['id']); + $newsletterSegment = $this->newsletterSegmentRepository->findBy([ + 'newsletter' => $newsletter, + 'segment' => $segment, + ]); + + if (!$newsletterSegment) { + $newsletterSegment = new NewsletterSegmentEntity($newsletter, $segment); + $this->entityManager->persist($newsletterSegment); + } + $newsletter->getNewsletterSegments()->add($newsletterSegment); + } + + // remove orphaned newsletter segments + foreach (array_diff($oldNewsletterSegments, $newsletter->getNewsletterSegments()->toArray()) as $newsletterSegment) { + $this->newsletterSegmentRepository->remove($newsletterSegment); + } + + $this->entityManager->flush(); + } } diff --git a/lib/Newsletter/Segment/NewsletterSegmentRepository.php b/lib/Newsletter/Segment/NewsletterSegmentRepository.php new file mode 100644 index 0000000000..4652f35409 --- /dev/null +++ b/lib/Newsletter/Segment/NewsletterSegmentRepository.php @@ -0,0 +1,15 @@ + + */ +class NewsletterSegmentRepository extends Repository { + protected function getEntityClassName() { + return NewsletterSegmentEntity::class; + } +} diff --git a/tasks/phpstan/phpstan-baseline.neon b/tasks/phpstan/phpstan-baseline.neon index 40126acbcb..bcad949f62 100644 --- a/tasks/phpstan/phpstan-baseline.neon +++ b/tasks/phpstan/phpstan-baseline.neon @@ -243,3 +243,8 @@ parameters: message: "#^Parameter \\#1 \\$newsletter of method MailPoet\\\\Entities\\\\NewsletterTemplateEntity\\:\\:setNewsletter\\(\\) expects MailPoet\\\\Entities\\\\NewsletterEntity\\|null, object given\\.$#" count: 1 path: ../../lib/NewsletterTemplates/NewsletterTemplatesRepository.php + + - + message: "#^Parameter \\#2 \\$segment of class MailPoet\\\\Entities\\\\NewsletterSegmentEntity constructor expects MailPoet\\\\Entities\\\\SegmentEntity, object given\\.$#" + count: 1 + path: ../../lib/Newsletter/NewsletterSaveController.php diff --git a/tests/integration/Newsletter/Listing/NewsletterListingRepositoryTest.php b/tests/integration/Newsletter/Listing/NewsletterListingRepositoryTest.php index 6c83f00ea3..7220b3779e 100644 --- a/tests/integration/Newsletter/Listing/NewsletterListingRepositoryTest.php +++ b/tests/integration/Newsletter/Listing/NewsletterListingRepositoryTest.php @@ -80,9 +80,7 @@ class NewsletterListingRepositoryTest extends \MailPoetTest { $newsletter->setSubject('Newsletter with segment'); $this->entityManager->persist($newsletter); - $newsletterSegment = new NewsletterSegmentEntity(); - $newsletterSegment->setSegment($segment); - $newsletterSegment->setNewsletter($newsletter); + $newsletterSegment = new NewsletterSegmentEntity($newsletter, $segment); $this->entityManager->persist($newsletterSegment); $this->entityManager->flush();