repository = $this->diContainer->get(SubscribersRepository::class); $this->segmentRepository = $this->diContainer->get(SegmentsRepository::class); $this->subscriberSegmentRepository = $this->diContainer->get(SubscriberSegmentRepository::class); $this->subscriberCustomFieldRepository = $this->diContainer->get(SubscriberCustomFieldRepository::class); } public function testItBulkTrashSubscribers(): void { $subscriberOne = $this->createSubscriber('one@trash.com'); $subscriberTwo = $this->createSubscriber('two@trash.com'); $subscriberThree = $this->createSubscriber('three@trash.com'); $subscriberOneId = $subscriberOne->getId(); $subscriberTwoId = $subscriberTwo->getId(); $subscriberThreeId = $subscriberThree->getId(); $this->repository->bulkTrash([ $subscriberOneId, $subscriberTwoId, ]); $this->entityManager->clear(); // trashed subscriber $subscriberOne = $this->repository->findOneById($subscriberOneId); $this->assertInstanceOf(SubscriberEntity::class, $subscriberOne); verify($subscriberOne->getDeletedAt())->notNull(); $subscriberTwo = $this->repository->findOneById($subscriberOneId); $this->assertInstanceOf(SubscriberEntity::class, $subscriberTwo); verify($subscriberTwo->getDeletedAt())->notNull(); // don't trashed subscriber $subscriberThree = $this->repository->findOneById($subscriberThreeId); $this->assertInstanceOf(SubscriberEntity::class, $subscriberThree); verify($subscriberThree->getDeletedAt())->null(); } public function testItBulkRestoreTrashedSubscribers(): void { $subscriberOne = $this->createSubscriber('one@restore.com', new DateTimeImmutable()); $subscriberTwo = $this->createSubscriber('two@restore.com', new DateTimeImmutable()); $subscriberOneId = $subscriberOne->getId(); $subscriberTwoId = $subscriberTwo->getId(); $this->repository->bulkRestore([ $subscriberOneId, ]); $this->entityManager->clear(); // restored subscriber $subscriberOne = $this->repository->findOneById($subscriberOneId); $this->assertInstanceOf(SubscriberEntity::class, $subscriberOne); verify($subscriberOne->getDeletedAt())->null(); // don't restored subscriber $subscriberTwo = $this->repository->findOneById($subscriberTwoId); $this->assertInstanceOf(SubscriberEntity::class, $subscriberTwo); verify($subscriberTwo->getDeletedAt())->notNull(); } public function testItBulkUpdatesLastSendingAt(): void { $subscriberOne = $this->createSubscriber('one@e.com'); $subscriberTwo = $this->createSubscriber('two@e.com'); $subscriberThree = $this->createSubscriber('three@e.com'); verify($subscriberOne->getLastSendingAt())->null(); verify($subscriberTwo->getLastSendingAt())->null(); verify($subscriberThree->getLastSendingAt())->null(); $idsToUpdate = [ $subscriberOne->getId(), $subscriberThree->getId(), ]; $now = new DateTimeImmutable(); $this->repository->bulkUpdateLastSendingAt($idsToUpdate, $now); $this->repository->refresh($subscriberOne); $this->repository->refresh($subscriberTwo); $this->repository->refresh($subscriberThree); $this->assertInstanceOf(DateTimeInterface::class, $subscriberOne->getLastSendingAt()); verify($subscriberOne->getLastSendingAt()->getTimestamp())->equals($now->getTimestamp()); verify($subscriberTwo->getLastSendingAt())->null(); $this->assertInstanceOf(DateTimeInterface::class, $subscriberThree->getLastSendingAt()); verify($subscriberThree->getLastSendingAt()->getTimestamp())->equals($now->getTimestamp()); } public function testItBulkUpdatesEngagementScoreUpdatedAt(): void { $subscriberOne = $this->createSubscriber('one@e.com'); $subscriberTwo = $this->createSubscriber('two@e.com'); $subscriberThree = $this->createSubscriber('three@e.com'); verify($subscriberOne->getEngagementScoreUpdatedAt())->null(); verify($subscriberTwo->getEngagementScoreUpdatedAt())->null(); verify($subscriberThree->getEngagementScoreUpdatedAt())->null(); $idsToUpdate = [ $subscriberOne->getId(), $subscriberThree->getId(), ]; $now = new DateTimeImmutable(); $this->repository->bulkUpdateEngagementScoreUpdatedAt($idsToUpdate, $now); $this->repository->refresh($subscriberOne); $this->repository->refresh($subscriberTwo); $this->repository->refresh($subscriberThree); $this->assertInstanceOf(DateTimeInterface::class, $subscriberOne->getEngagementScoreUpdatedAt()); verify($subscriberOne->getEngagementScoreUpdatedAt()->getTimestamp())->equals($now->getTimestamp()); verify($subscriberTwo->getEngagementScoreUpdatedAt())->null(); $this->assertInstanceOf(DateTimeInterface::class, $subscriberThree->getEngagementScoreUpdatedAt()); verify($subscriberThree->getEngagementScoreUpdatedAt()->getTimestamp())->equals($now->getTimestamp()); } public function testBulkUpdatesOfEngagementScoreCanNullifyData(): void { $subscriberOne = $this->createSubscriber('one@e.com'); $subscriberTwo = $this->createSubscriber('two@e.com'); $subscriberThree = $this->createSubscriber('three@e.com'); $now = new DateTimeImmutable(); $subscriberOne->setEngagementScoreUpdatedAt($now); $subscriberTwo->setEngagementScoreUpdatedAt($now); $subscriberThree->setEngagementScoreUpdatedAt($now); $this->entityManager->persist($subscriberOne); $this->entityManager->persist($subscriberTwo); $this->entityManager->persist($subscriberThree); $this->entityManager->flush(); $this->repository->refresh($subscriberOne); $this->repository->refresh($subscriberTwo); $this->repository->refresh($subscriberThree); $this->assertInstanceOf(DateTimeInterface::class, $subscriberOne->getEngagementScoreUpdatedAt()); $this->assertInstanceOf(DateTimeInterface::class, $subscriberTwo->getEngagementScoreUpdatedAt()); $this->assertInstanceOf(DateTimeInterface::class, $subscriberThree->getEngagementScoreUpdatedAt()); $idsToUpdate = [ $subscriberOne->getId(), $subscriberThree->getId(), ]; $this->repository->bulkUpdateEngagementScoreUpdatedAt($idsToUpdate, null); $this->repository->refresh($subscriberOne); $this->repository->refresh($subscriberTwo); $this->repository->refresh($subscriberThree); verify($subscriberOne->getEngagementScoreUpdatedAt())->null(); $this->assertInstanceOf(DateTimeInterface::class, $subscriberTwo->getEngagementScoreUpdatedAt()); verify($subscriberOne->getEngagementScoreUpdatedAt())->null(); } public function testItBulkDeleteSubscribers(): void { $subscriberOne = $this->createSubscriber('one@delete.com', new DateTimeImmutable()); $subscriberTwo = $this->createSubscriber('two@delete.com', new DateTimeImmutable()); $segmentOne = $this->segmentRepository->createOrUpdate('One Delete'); $this->createSubscriberSegment($segmentOne, $subscriberOne); $this->createSubscriberSegment($segmentOne, $subscriberTwo); $customField = $this->createCustomField('CF'); $this->createSubscriberCustomField($subscriberOne, $customField); $this->createSubscriberCustomField($subscriberTwo, $customField); $subscriberOneId = $subscriberOne->getId(); $subscriberTwoId = $subscriberTwo->getId(); $this->repository->bulkDelete([ $subscriberOneId, ]); $this->entityManager->clear(); // deleted subscriber verify($this->repository->findOneById($subscriberOneId))->null(); verify($this->subscriberSegmentRepository->findOneBy(['subscriber' => $subscriberOneId]))->null(); verify($this->subscriberCustomFieldRepository->findOneBy(['subscriber' => $subscriberOneId]))->null(); // don't restored subscriber $subscriberTwo = $this->repository->findOneById($subscriberTwoId); $this->assertInstanceOf(SubscriberEntity::class, $subscriberTwo); verify($subscriberTwo->getDeletedAt())->notNull(); verify($this->subscriberSegmentRepository->findOneBy(['subscriber' => $subscriberTwoId]))->notNull(); verify($this->subscriberCustomFieldRepository->findOneBy(['subscriber' => $subscriberTwoId]))->notNull(); } public function testItBulkRemoveSubscribersFromSegment(): void { $subscriberOne = $this->createSubscriber('one@remove.com', new DateTimeImmutable()); $subscriberTwo = $this->createSubscriber('two@remove.com', new DateTimeImmutable()); $segmentOne = $this->segmentRepository->createOrUpdate('One Remove'); $segmentTwo = $this->segmentRepository->createOrUpdate('Two Remove'); $this->createSubscriberSegment($segmentOne, $subscriberOne); $this->createSubscriberSegment($segmentOne, $subscriberTwo); $this->createSubscriberSegment($segmentTwo, $subscriberOne); $this->createSubscriberSegment($segmentTwo, $subscriberTwo); $subscriberOneId = $subscriberOne->getId(); $subscriberTwoId = $subscriberTwo->getId(); $segmentOneId = $segmentOne->getId(); $segmentTwoId = $segmentTwo->getId(); $this->repository->bulkRemoveFromSegment($segmentOne, [$subscriberOneId]); $this->repository->bulkRemoveFromSegment($segmentTwo, [$subscriberTwoId]); $this->entityManager->clear(); // subscriber with removed segment one verify($this->repository->findOneById($subscriberOneId))->notNull(); verify($this->subscriberSegmentRepository->findOneBy([ 'subscriber' => $subscriberOneId, 'segment' => $segmentOneId, ]))->null(); verify($this->subscriberSegmentRepository->findOneBy([ 'subscriber' => $subscriberOneId, 'segment' => $segmentTwoId, ]))->notNull(); // subscriber with removed segment two verify($this->repository->findOneById($subscriberTwoId))->notNull(); verify($this->subscriberSegmentRepository->findOneBy([ 'subscriber' => $subscriberTwoId, 'segment' => $segmentTwoId, ]))->null(); verify($this->subscriberSegmentRepository->findOneBy([ 'subscriber' => $subscriberTwoId, 'segment' => $segmentOneId, ]))->notNull(); } public function testItBulkUnsubscribes(): void { $subscriberOne = $this->createSubscriber('one@removeAll.com', new DateTimeImmutable()); $subscriberTwo = $this->createSubscriber('two@removeAll.com', new DateTimeImmutable()); $subscriberOneId = $subscriberOne->getId(); $subscriberTwoId = $subscriberTwo->getId(); $this->repository->bulkUnsubscribe([$subscriberOneId]); $this->entityManager->clear(); // subscriber with removed segments $unsubscribedSubscriber = $this->repository->findOneById($subscriberOneId); verify($unsubscribedSubscriber)->notNull(); $this->assertInstanceOf(SubscriberEntity::class, $unsubscribedSubscriber); verify($unsubscribedSubscriber->getStatus())->equals(SubscriberEntity::STATUS_UNSUBSCRIBED); // subscriber still subscribed $subscribedSubscriber = $this->repository->findOneById($subscriberTwoId); verify($subscribedSubscriber)->notNull(); $this->assertInstanceOf(SubscriberEntity::class, $subscribedSubscriber); verify($subscribedSubscriber->getStatus())->equals(SubscriberEntity::STATUS_SUBSCRIBED); } public function testItBulkRemoveSubscriberFromAllSegments(): void { $subscriberOne = $this->createSubscriber('one@removeAll.com', new DateTimeImmutable()); $subscriberTwo = $this->createSubscriber('two@removeAll.com', new DateTimeImmutable()); $segmentOne = $this->segmentRepository->createOrUpdate('One Remove All'); $segmentTwo = $this->segmentRepository->createOrUpdate('Two Remove All'); $this->createSubscriberSegment($segmentOne, $subscriberOne); $this->createSubscriberSegment($segmentOne, $subscriberTwo); $this->createSubscriberSegment($segmentTwo, $subscriberOne); $this->createSubscriberSegment($segmentTwo, $subscriberTwo); $subscriberOneId = $subscriberOne->getId(); $subscriberTwoId = $subscriberTwo->getId(); $segmentOneId = $segmentOne->getId(); $segmentTwoId = $segmentTwo->getId(); $this->repository->bulkRemoveFromAllSegments([$subscriberOneId]); $this->entityManager->clear(); // subscriber with removed segments verify($this->repository->findOneById($subscriberOneId))->notNull(); verify($this->subscriberSegmentRepository->findBy(['subscriber' => $subscriberOneId]))->arrayCount(0); // subscriber with segments verify($this->repository->findOneById($subscriberTwoId))->notNull(); verify($this->subscriberSegmentRepository->findOneBy([ 'subscriber' => $subscriberTwoId, 'segment' => $segmentOneId, ]))->notNull(); verify($this->subscriberSegmentRepository->findOneBy([ 'subscriber' => $subscriberTwoId, 'segment' => $segmentTwoId, ]))->notNull(); } public function testItBulkAddSubscribersToSegment(): void { $subscriberOne = $this->createSubscriber('one@add.com', new DateTimeImmutable()); $subscriberTwo = $this->createSubscriber('two@add.com', new DateTimeImmutable()); $segmentOne = $this->segmentRepository->createOrUpdate('One Add'); $subscriberOneId = $subscriberOne->getId(); $subscriberTwoId = $subscriberTwo->getId(); $segmentOneId = $segmentOne->getId(); $this->repository->bulkAddToSegment($segmentOne, [$subscriberOneId]); $this->entityManager->clear(); // subscriber with segment verify($this->repository->findOneById($subscriberOneId))->notNull(); verify($this->subscriberSegmentRepository->findOneBy([ 'subscriber' => $subscriberOneId, 'segment' => $segmentOneId, ]))->notNull(); // subscriber without segment verify($this->repository->findOneById($subscriberTwoId))->notNull(); verify($this->subscriberSegmentRepository->findBy(['subscriber' => $subscriberTwoId]))->arrayCount(0); } public function testItBulMoveSubscribersToSegment(): void { $subscriberOne = $this->createSubscriber('one@move.com', new DateTimeImmutable()); $subscriberTwo = $this->createSubscriber('two@move.com', new DateTimeImmutable()); $segmentOne = $this->segmentRepository->createOrUpdate('One Move'); $segmentTwo = $this->segmentRepository->createOrUpdate('Two Move'); $this->createSubscriberSegment($segmentOne, $subscriberOne); $this->createSubscriberSegment($segmentTwo, $subscriberTwo); $subscriberOneId = $subscriberOne->getId(); $subscriberTwoId = $subscriberTwo->getId(); $segmentOneId = $segmentOne->getId(); $segmentTwoId = $segmentTwo->getId(); $this->repository->bulkMoveToSegment($segmentTwo, [$subscriberOneId]); $this->entityManager->clear(); // subscriber moved to segment two verify($this->repository->findOneById($subscriberOneId))->notNull(); verify($this->subscriberSegmentRepository->findOneBy([ 'subscriber' => $subscriberOneId, 'segment' => $segmentOneId, ]))->null(); verify($this->subscriberSegmentRepository->findOneBy([ 'subscriber' => $subscriberOneId, 'segment' => $segmentTwoId, ]))->notNull(); // subscriber which stay in segment two verify($this->repository->findOneById($subscriberTwoId))->notNull(); verify($this->subscriberSegmentRepository->findOneBy([ 'subscriber' => $subscriberTwoId, 'segment' => $segmentOneId, ]))->null(); verify($this->subscriberSegmentRepository->findOneBy([ 'subscriber' => $subscriberTwoId, 'segment' => $segmentTwoId, ]))->notNull(); } public function testItDoesntRemovePermanentlyWordpressSubscriber(): void { $subscriber = $this->createSubscriber('wpsubscriber@delete.com'); $subscriber->setWpUserId(1); $this->repository->flush(); $this->entityManager->clear(); $subscriberId = $subscriber->getId(); $count = $this->repository->bulkDelete([$subscriber->getId()]); verify($count)->equals(0); verify($this->repository->findOneById($subscriberId))->notNull(); } public function testItDoesntRemovePermanentlyWoocommerceSubscriber(): void { $subscriber = $this->createSubscriber('wcsubscriber@delete.com'); $subscriber->setIsWoocommerceUser(true); $this->repository->flush(); $this->entityManager->clear(); $subscriberId = $subscriber->getId(); $count = $this->repository->bulkDelete([$subscriberId]); verify($count)->equals(0); verify($this->repository->findOneById($subscriberId))->notNull(); } public function testItGetsMaxSubscriberId(): void { // check if equals to zero when no subscribers verify($this->repository->getMaxSubscriberId())->equals(0); // check if equals to max subscriber id $this->createSubscriber('sub1@test.com'); $subscriberTwo = $this->createSubscriber('sub2@test.com'); verify($this->repository->getMaxSubscriberId())->equals($subscriberTwo->getId()); } public function testRemoveOrphanedSubscribersFromWpSegment(): void { $wpUserId1 = $this->tester->createWordPressUser('subscriber1@email.com', 'author'); $wpUserId2 = $this->tester->createWordPressUser('subscriber2@email.com', 'author'); $wpUserId3 = $this->tester->createWordPressUser('subscriber3@email.com', 'author'); $subscriber2 = $this->repository->findOneBy(['wpUserId' => $wpUserId2]); $subscriber3 = $this->repository->findOneBy(['wpUserId' => $wpUserId3]); $this->tester->deleteWPUserFromDatabase($wpUserId1); $this->repository->removeOrphanedSubscribersFromWpSegment(); $subscribers = $this->repository->findAll(); $this->assertCount(2, $subscribers); $this->assertSame($subscribers[0], $subscriber2); $this->assertSame($subscribers[1], $subscriber3); } public function testRemoveByWpUserIds(): void { $wpUserId1 = $this->tester->createWordPressUser('subscriber1@email.com', 'author'); $wpUserId2 = $this->tester->createWordPressUser('subscriber2@email.com', 'author'); $wpUserId3 = $this->tester->createWordPressUser('subscriber3@email.com', 'author'); $subscriber3 = $this->repository->findOneBy(['wpUserId' => $wpUserId3]); $deletedRows = $this->repository->removeByWpUserIds([$wpUserId1, $wpUserId2]); $this->assertSame(2, $deletedRows); $subscribers = $this->repository->findAll(); $this->assertCount(1, $subscribers); $this->assertSame($subscribers[0], $subscriber3); } private function createSubscriber(string $email, ?DateTimeImmutable $deletedAt = null): SubscriberEntity { $subscriber = new SubscriberEntity(); $subscriber->setEmail($email); $subscriber->setFirstName('John'); $subscriber->setLastName('Doe'); $subscriber->setStatus(SubscriberEntity::STATUS_SUBSCRIBED); $subscriber->setDeletedAt($deletedAt); $this->entityManager->persist($subscriber); $this->entityManager->flush(); return $subscriber; } private function createSubscriberSegment(SegmentEntity $segment, SubscriberEntity $subscriber): SubscriberSegmentEntity { $subscriberSegment = new SubscriberSegmentEntity($segment, $subscriber, SubscriberEntity::STATUS_SUBSCRIBED); $this->entityManager->persist($subscriberSegment); $this->entityManager->flush(); return $subscriberSegment; } private function createCustomField(string $name): CustomFieldEntity { $customField = new CustomFieldEntity(); $customField->setName($name); $customField->setType(CustomFieldEntity::TYPE_TEXT); $this->entityManager->persist($customField); $this->entityManager->flush(); return $customField; } private function createSubscriberCustomField(SubscriberEntity $subscriber, CustomFieldEntity $customField): SubscriberCustomFieldEntity { $subscirberCustomField = new SubscriberCustomFieldEntity($subscriber, $customField, 'some value'); $this->entityManager->persist($subscirberCustomField); $this->entityManager->flush(); return $subscirberCustomField; } }