212 lines
8.4 KiB
PHP
212 lines
8.4 KiB
PHP
<?php declare(strict_types = 1);
|
|
|
|
namespace MailPoet\Subscribers;
|
|
|
|
use MailPoet\ConflictException;
|
|
use MailPoet\Entities\SegmentEntity;
|
|
use MailPoet\Entities\SubscriberEntity;
|
|
use MailPoet\Entities\SubscriberSegmentEntity;
|
|
use MailPoet\Entities\SubscriberTagEntity;
|
|
use MailPoet\Segments\SegmentsRepository;
|
|
use MailPoet\WP\Functions as WPFunctions;
|
|
use MailPoetVendor\Carbon\Carbon;
|
|
|
|
class SubscriberSaveControllerTest extends \MailPoetTest {
|
|
/** @var SubscriberSaveController */
|
|
private $saveController;
|
|
|
|
/** @var SegmentsRepository */
|
|
private $segmentsRepository;
|
|
|
|
/** @var SubscriberSegmentRepository */
|
|
private $subscriberSegmentRepository;
|
|
|
|
public function _before() {
|
|
parent::_before();
|
|
$this->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;
|
|
}
|
|
}
|