saveController = $this->diContainer->get(SubscriberSaveController::class); $this->segmentsRepository = $this->diContainer->get(SegmentsRepository::class); $this->subscriberSegmentRepository = $this->diContainer->get(SubscriberSegmentRepository::class); } public function testItCreatesNewSubscriber(): void { $segmentOne = $this->segmentsRepository->createOrUpdate('Segment One'); $segmentTwo = $this->segmentsRepository->createOrUpdate('Segment Two'); $data = [ 'email' => 'first@test.com', 'first_name' => 'John', 'last_name' => 'Doe', 'status' => SubscriberEntity::STATUS_SUBSCRIBED, 'segments' => [ $segmentOne->getId(), $segmentTwo->getId(), ], 'created_at' => '2020-04-30 13:14:15', 'confirmed_at' => '2020-04-31 13:14:15', 'confirmed_ip' => '192.168.1.32', 'subscribed_ip' => '192.168.1.16', 'wp_user_id' => 7, 'tags' => [ 'First', 'Second', ], ]; $subscriber = $this->saveController->save($data); verify($subscriber->getEmail())->equals($data['email']); verify($subscriber->getStatus())->equals($data['status']); verify($subscriber->getFirstName())->equals($data['first_name']); verify($subscriber->getLastName())->equals($data['last_name']); verify($subscriber->getCreatedAt())->equals(Carbon::createFromFormat('Y-m-d H:i:s', $data['created_at'])); verify($subscriber->getConfirmedAt())->equals(Carbon::createFromFormat('Y-m-d H:i:s', $data['confirmed_at'])); verify($subscriber->getConfirmedIp())->equals($data['confirmed_ip']); verify($subscriber->getSubscribedIp())->equals($data['subscribed_ip']); verify($subscriber->getWpUserId())->equals($data['wp_user_id']); verify($subscriber->getUnsubscribeToken())->notNull(); verify($subscriber->getLinkToken())->notNull(); verify($subscriber->getId())->notNull(); verify($subscriber->getLastSubscribedAt())->notNull(); verify($subscriber->getSegments())->arrayCount(2); verify($subscriber->getSubscriberSegments())->arrayCount(2); verify($subscriber->getSubscriberTags())->arrayCount(2); } public function testItCanUpdateASubscriber(): void { $subscriber = $this->createSubscriber('second@test.com', SubscriberEntity::STATUS_UNCONFIRMED); $segmentOne = $this->segmentsRepository->createOrUpdate('Segment One'); $data = [ 'id' => $subscriber->getId(), 'first_name' => 'John', 'last_name' => 'Doe', 'status' => SubscriberEntity::STATUS_SUBSCRIBED, 'segments' => [ $segmentOne->getId(), ], 'tags' => [ 'First', ], ]; $this->entityManager->clear(); $subscriber = $this->saveController->save($data); verify($subscriber->getEmail())->equals('second@test.com'); verify($subscriber->getStatus())->equals($data['status']); verify($subscriber->getFirstName())->equals($data['first_name']); verify($subscriber->getLastName())->equals($data['last_name']); verify($subscriber->getLastSubscribedAt())->notNull(); verify($subscriber->getSegments())->arrayCount(1); verify($subscriber->getSubscriberSegments())->arrayCount(1); verify($subscriber->getSubscriberTags())->arrayCount(1); // Check exact tag name $tagNames = array_values(array_map(function (SubscriberTagEntity $subscriberTag): string { return ($tag = $subscriberTag->getTag()) ? $tag->getName() : ''; }, $subscriber->getSubscriberTags()->toArray())); verify($data['tags'])->equals($tagNames); // Test updating tags $data['tags'] = [ 'Second', 'Third', ]; $subscriber = $this->saveController->save($data); verify($subscriber->getSubscriberTags())->arrayCount(2); $tagNames = array_values(array_map(function (SubscriberTagEntity $subscriberTag): string { return ($tag = $subscriberTag->getTag()) ? $tag->getName() : ''; }, $subscriber->getSubscriberTags()->toArray())); verify($data['tags'])->equals($tagNames); } public function testItThrowsExceptionWhenUpdatingSubscriberEmailIfNotUnique(): void { $subscriber = $this->createSubscriber('second@test.com', SubscriberEntity::STATUS_UNCONFIRMED); $subscriber2 = $this->createSubscriber('third@test.com', SubscriberEntity::STATUS_UNCONFIRMED); $data = [ 'id' => $subscriber->getId(), 'email' => $subscriber2->getEmail(), ]; $this->entityManager->clear(); $this->expectException(ConflictException::class); $this->expectExceptionMessage('A subscriber with E-mail "' . $subscriber2->getEmail() . '" already exists.'); $this->saveController->save($data); } public function testItDeletesOrphanSubscriberSegmentsOnUpdate(): void { $subscriber = $this->createSubscriber('second@test.com', SubscriberEntity::STATUS_UNCONFIRMED); $segmentOne = $this->segmentsRepository->createOrUpdate('Segment One'); $segmentTwo = $this->segmentsRepository->createOrUpdate('Segment Two'); // Create orphan record on SubscriberSegments $orphanSegment = $this->segmentsRepository->createOrUpdate('Orphan'); $this->createSubscriberSegment($subscriber, $orphanSegment); $this->entityManager->remove($orphanSegment); $this->entityManager->flush(); $subscriberSegments = $this->subscriberSegmentRepository->findBy(['subscriber' => $subscriber]); verify($subscriberSegments)->arrayCount(1); // Update subscriber with new segments $data = [ 'id' => $subscriber->getId(), 'first_name' => 'John', 'last_name' => 'Doe', 'status' => SubscriberEntity::STATUS_SUBSCRIBED, 'segments' => [ $segmentOne->getId(), $segmentTwo->getId(), ], ]; $this->entityManager->clear(); $subscriber = $this->saveController->save($data); // Check the $orphanSegment is gone $subscriberSegments = $this->subscriberSegmentRepository->findBy(['subscriber' => $subscriber]); verify($subscriberSegments)->arrayCount(2); } public function testItTriggersSegmentSubscribedHook(): void { $segmentOne = $this->segmentsRepository->createOrUpdate('Segment One'); $segmentTwo = $this->segmentsRepository->createOrUpdate('Segment Two'); $data = [ 'email' => 'test@test.com', 'status' => SubscriberEntity::STATUS_SUBSCRIBED, 'segments' => [$segmentOne->getId(), $segmentTwo->getId()], ]; $count = 0; $this->diContainer->get(WPFunctions::class)->addAction('mailpoet_segment_subscribed', function () use (&$count) { $count++; }); // create subscriber with subscribed status $count = 0; $this->saveController->save($data); $this->assertSame(2, $count); // @phpstan-ignore-line -- PHPStan doesn't get the $count side effect // update subscriber to non-subscribed status $count = 0; $this->saveController->save(array_merge($data, ['status' => SubscriberEntity::STATUS_UNCONFIRMED])); $this->assertSame(0, $count); // update subscriber to subscribed status $count = 0; $this->saveController->save($data); $this->assertSame(2, $count); // @phpstan-ignore-line -- PHPStan doesn't get the $count side effect } private function createSubscriber(string $email, string $status): SubscriberEntity { $subscriber = new SubscriberEntity(); $subscriber->setEmail($email); $subscriber->setStatus($status); $this->entityManager->persist($subscriber); $this->entityManager->flush(); return $subscriber; } private function createSubscriberSegment(SubscriberEntity $subscriber, SegmentEntity $segment): SubscriberSegmentEntity { $subscriberSegment = new SubscriberSegmentEntity($segment, $subscriber, SubscriberEntity::STATUS_SUBSCRIBED); $this->entityManager->persist($subscriberSegment); $this->entityManager->flush(); return $subscriberSegment; } }