Files
piratepoet/mailpoet/tests/integration/Subscribers/EngagementDataBackfillerTest.php
2024-03-21 16:57:59 +01:00

397 lines
17 KiB
PHP

<?php declare(strict_types = 1);
namespace MailPoet\Subscribers;
use DateTimeInterface;
use MailPoet\Entities\SubscriberEntity;
use MailPoet\Test\DataFactories\Newsletter;
use MailPoet\Test\DataFactories\NewsletterLink;
use MailPoet\Test\DataFactories\StatisticsClicks;
use MailPoet\Test\DataFactories\StatisticsNewsletters;
use MailPoet\Test\DataFactories\StatisticsOpens;
use MailPoet\Test\DataFactories\Subscriber;
use MailPoetVendor\Carbon\Carbon;
/**
* @group woo
*/
class EngagementDataBackfillerTest extends \MailPoetTest {
/** @var EngagementDataBackfiller */
private $backfiller;
/** @var SubscribersRepository */
private $subscribersRepository;
public function _before() {
parent::_before();
$this->backfiller = $this->diContainer->get(EngagementDataBackfiller::class);
$this->subscribersRepository = $this->diContainer->get(SubscribersRepository::class);
}
public function testItRetrievesPurchaseData(): void {
$customerId = $this->tester->createCustomer('1@e.com');
$sub1 = $this->subscribersRepository->findOneBy(['email' => '1@e.com']);
$older = Carbon::now()->subDays(200);
$newer = Carbon::now()->subDays(100);
$this->createOrder($customerId, '1@e.com', $older);
$this->createOrder($customerId, '1@e.com', $newer);
$customerId2 = $this->tester->createCustomer('2@e.com');
$sub2 = $this->subscribersRepository->findOneBy(['email' => '2@e.com']);
$older2 = Carbon::now()->subDays(150);
$newer2 = Carbon::now()->subDays(50);
$this->createOrder($customerId2, '2@e.com', $newer2);
$this->createOrder($customerId2, '2@e.com', $older2);
$customerId3 = $this->tester->createCustomer('3@e.com');
$batch = $this->backfiller->getBatch();
$subscriberIds = array_map(function($subscriber) {
return $subscriber->getId();
}, $batch);
verify($batch)->arrayCount(3);
$data = $this->backfiller->getPurchaseDataForBatch($subscriberIds);
$this->assertInstanceOf(SubscriberEntity::class, $sub1);
$this->assertInstanceOf(SubscriberEntity::class, $sub2);
verify($data[$sub1->getId()]['last_purchase_at'])->equals((string)$newer);
verify($data[$sub2->getId()]['last_purchase_at'])->equals((string)$newer2);
verify(!isset($data[$customerId3]))->true();
}
public function testItUpdatesSubscribersPurchaseData(): void {
$customerId = $this->tester->createCustomer('1@e.com');
$sub1 = $this->subscribersRepository->findOneBy(['email' => '1@e.com']);
$older = Carbon::now()->subDays(200);
$newer = Carbon::now()->subDays(100);
$this->createOrder($customerId, '1@e.com', $older);
$this->createOrder($customerId, '1@e.com', $newer);
$customerId2 = $this->tester->createCustomer('2@e.com');
$sub2 = $this->subscribersRepository->findOneBy(['email' => '2@e.com']);
$older2 = Carbon::now()->subDays(150);
$newer2 = Carbon::now()->subDays(50);
$this->createOrder($customerId2, '2@e.com', $newer2);
$this->createOrder($customerId2, '2@e.com', $older2);
$this->assertInstanceOf(SubscriberEntity::class, $sub1);
$this->assertInstanceOf(SubscriberEntity::class, $sub2);
// These need to be manually cleared because creating orders triggers an update via our hooks
$sub1->setLastPurchaseAt(null);
$sub2->setLastPurchaseAt(null);
$this->entityManager->flush();
verify($sub2->getLastPurchaseAt())->null();
verify($sub1->getLastPurchaseAt())->null();
$this->backfiller->updateBatch([$sub1, $sub2]);
$this->entityManager->refresh($sub1);
$this->entityManager->refresh($sub2);
$this->assertInstanceOf(DateTimeInterface::class, $sub1->getLastPurchaseAt());
$this->assertInstanceOf(DateTimeInterface::class, $sub2->getLastPurchaseAt());
verify($sub1->getLastPurchaseAt()->getTimestamp())->equals($newer->getTimestamp());
verify($sub2->getLastPurchaseAt()->getTimestamp())->equals($newer2->getTimestamp());
}
public function testItRetrievesOpensData(): void {
$sub1 = (new Subscriber())->withEmail('1@e.com')->create();
$sub2 = (new Subscriber())->withEmail('2@e.com')->create();
$sub3 = (new Subscriber())->withEmail('3@e.com')->create();
$sub4 = (new Subscriber())->withEmail('4@e.com')->create();
$this->assertInstanceOf(SubscriberEntity::class, $sub1);
$this->assertInstanceOf(SubscriberEntity::class, $sub2);
$this->assertInstanceOf(SubscriberEntity::class, $sub3);
$this->assertInstanceOf(SubscriberEntity::class, $sub4);
$newsletter = (new Newsletter())->withSendingQueue()->create();
$sub1open = (new StatisticsOpens($newsletter, $sub1))->create();
$older = Carbon::now()->subDays(200);
$sub1open->setCreatedAt($older);
$sub1open2 = (new StatisticsOpens($newsletter, $sub1))->create();
$newer = Carbon::now()->subDays(20);
$sub1open2->setCreatedAt($newer);
$sub2open = (new StatisticsOpens($newsletter, $sub2))->create();
$sub2date = Carbon::now()->subDays(22);
$sub2open->setCreatedAt($sub2date);
$sub3open = (new StatisticsOpens($newsletter, $sub3))->create();
$sub3date = Carbon::now()->subDays(33);
$sub3open->setCreatedAt($sub3date);
$this->entityManager->flush();
$openData = $this->backfiller->getOpenDataForBatch([$sub1->getId(), $sub2->getId(), $sub3->getId(), $sub4->getId()]);
verify($openData)->arrayCount(3);
verify($openData[$sub1->getId()]['last_open_at'])->equals((string)$newer);
verify($openData[$sub2->getId()]['last_open_at'])->equals((string)$sub2date);
verify($openData[$sub3->getId()]['last_open_at'])->equals((string)$sub3date);
verify(!isset($openData[$sub4->getId()]))->true();
}
public function testItUpdatesOpensData(): void {
$sub1 = (new Subscriber())->withEmail('1@e.com')->create();
$sub2 = (new Subscriber())->withEmail('2@e.com')->create();
$sub3 = (new Subscriber())->withEmail('3@e.com')->create();
$sub4 = (new Subscriber())->withEmail('4@e.com')->create();
$this->assertInstanceOf(SubscriberEntity::class, $sub1);
$this->assertInstanceOf(SubscriberEntity::class, $sub2);
$this->assertInstanceOf(SubscriberEntity::class, $sub3);
$this->assertInstanceOf(SubscriberEntity::class, $sub4);
$newsletter = (new Newsletter())->withSendingQueue()->create();
$sub1open = (new StatisticsOpens($newsletter, $sub1))->create();
$older = Carbon::now()->subDays(200);
$sub1open->setCreatedAt($older);
$sub1open2 = (new StatisticsOpens($newsletter, $sub1))->create();
$newer = Carbon::now()->subDays(20);
$sub1open2->setCreatedAt($newer);
$sub2open = (new StatisticsOpens($newsletter, $sub2))->create();
$sub2date = Carbon::now()->subDays(22);
$sub2open->setCreatedAt($sub2date);
$sub3open = (new StatisticsOpens($newsletter, $sub3))->create();
$sub3date = Carbon::now()->subDays(33);
$sub3open->setCreatedAt($sub3date);
$this->entityManager->flush();
verify($sub1->getLastOpenAt())->null();
verify($sub2->getLastOpenAt())->null();
verify($sub3->getLastOpenAt())->null();
verify($sub4->getLastOpenAt())->null();
$this->backfiller->updateBatch([$sub1, $sub2, $sub3, $sub4]);
$this->entityManager->refresh($sub1);
$this->entityManager->refresh($sub2);
$this->entityManager->refresh($sub3);
$this->entityManager->refresh($sub4);
$this->assertInstanceOf(DateTimeInterface::class, $sub1->getLastOpenAt());
$this->assertInstanceOf(DateTimeInterface::class, $sub2->getLastOpenAt());
$this->assertInstanceOf(DateTimeInterface::class, $sub3->getLastOpenAt());
verify($sub1->getLastOpenAt()->getTimestamp())->equals($newer->getTimestamp());
verify($sub2->getLastOpenAt()->getTimestamp())->equals($sub2date->getTimestamp());
verify($sub3->getLastOpenAt()->getTimestamp())->equals($sub3date->getTimestamp());
verify($sub4->getLastOpenAt())->null();
}
public function testItRetrievesClicksData(): void {
$sub1 = (new Subscriber())->withEmail('1@e.com')->create();
$sub2 = (new Subscriber())->withEmail('2@e.com')->create();
$sub3 = (new Subscriber())->withEmail('3@e.com')->create();
$sub4 = (new Subscriber())->withEmail('4@e.com')->create();
$this->assertInstanceOf(SubscriberEntity::class, $sub1);
$this->assertInstanceOf(SubscriberEntity::class, $sub2);
$this->assertInstanceOf(SubscriberEntity::class, $sub3);
$this->assertInstanceOf(SubscriberEntity::class, $sub4);
$newsletter = (new Newsletter())->withSendingQueue()->create();
$link = (new NewsletterLink($newsletter))->create();
$sub1open = (new StatisticsClicks($link, $sub1))->create();
$older = Carbon::now()->subDays(200);
$sub1open->setCreatedAt($older);
$sub1open2 = (new StatisticsClicks($link, $sub1))->create();
$newer = Carbon::now()->subDays(20);
$sub1open2->setCreatedAt($newer);
$sub2open = (new StatisticsClicks($link, $sub2))->create();
$sub2date = Carbon::now()->subDays(22);
$sub2open->setCreatedAt($sub2date);
$sub3open = (new StatisticsClicks($link, $sub3))->create();
$sub3date = Carbon::now()->subDays(33);
$sub3open->setCreatedAt($sub3date);
$this->entityManager->flush();
$clickData = $this->backfiller->getClickDataForBatch([$sub1->getId(), $sub2->getId(), $sub3->getId(), $sub4->getId()]);
verify($clickData)->arrayCount(3);
verify($clickData[$sub1->getId()]['last_click_at'])->equals((string)$newer);
verify($clickData[$sub2->getId()]['last_click_at'])->equals((string)$sub2date);
verify($clickData[$sub3->getId()]['last_click_at'])->equals((string)$sub3date);
verify(!isset($clickData[$sub4->getId()]))->true();
}
public function testItUpdatesClicksData(): void {
$sub1 = (new Subscriber())->withEmail('1@e.com')->create();
$sub2 = (new Subscriber())->withEmail('2@e.com')->create();
$sub3 = (new Subscriber())->withEmail('3@e.com')->create();
$sub4 = (new Subscriber())->withEmail('4@e.com')->create();
$this->assertInstanceOf(SubscriberEntity::class, $sub1);
$this->assertInstanceOf(SubscriberEntity::class, $sub2);
$this->assertInstanceOf(SubscriberEntity::class, $sub3);
$this->assertInstanceOf(SubscriberEntity::class, $sub4);
$newsletter = (new Newsletter())->withSendingQueue()->create();
$link = (new NewsletterLink($newsletter))->create();
$sub1open = (new StatisticsClicks($link, $sub1))->create();
$older = Carbon::now()->subDays(200);
$sub1open->setCreatedAt($older);
$sub1open2 = (new StatisticsClicks($link, $sub1))->create();
$newer = Carbon::now()->subDays(20);
$sub1open2->setCreatedAt($newer);
$sub2open = (new StatisticsClicks($link, $sub2))->create();
$sub2date = Carbon::now()->subDays(22);
$sub2open->setCreatedAt($sub2date);
$sub3open = (new StatisticsClicks($link, $sub3))->create();
$sub3date = Carbon::now()->subDays(33);
$sub3open->setCreatedAt($sub3date);
$this->entityManager->flush();
verify($sub1->getLastClickAt())->null();
verify($sub2->getLastClickAt())->null();
verify($sub3->getLastClickAt())->null();
verify($sub4->getLastClickAt())->null();
$this->backfiller->updateBatch([$sub1, $sub2, $sub3, $sub4]);
$this->entityManager->refresh($sub1);
$this->entityManager->refresh($sub2);
$this->entityManager->refresh($sub3);
$this->entityManager->refresh($sub4);
$this->assertInstanceOf(DateTimeInterface::class, $sub1->getLastClickAt());
$this->assertInstanceOf(DateTimeInterface::class, $sub2->getLastClickAt());
$this->assertInstanceOf(DateTimeInterface::class, $sub3->getLastClickAt());
verify($sub1->getLastClickAt()->getTimestamp())->equals($newer->getTimestamp());
verify($sub2->getLastClickAt()->getTimestamp())->equals($sub2date->getTimestamp());
verify($sub3->getLastClickAt()->getTimestamp())->equals($sub3date->getTimestamp());
verify($sub4->getLastOpenAt())->null();
}
public function testItRetrievesSendingData(): void {
$sub1 = (new Subscriber())->withEmail('1@e.com')->create();
$sub2 = (new Subscriber())->withEmail('2@e.com')->create();
$sub3 = (new Subscriber())->withEmail('3@e.com')->create();
$sub4 = (new Subscriber())->withEmail('4@e.com')->create();
$this->assertInstanceOf(SubscriberEntity::class, $sub1);
$this->assertInstanceOf(SubscriberEntity::class, $sub2);
$this->assertInstanceOf(SubscriberEntity::class, $sub3);
$this->assertInstanceOf(SubscriberEntity::class, $sub4);
$newsletter = (new Newsletter())->withSendingQueue()->create();
$newsletter2 = (new Newsletter())->withSendingQueue()->create();
$sub1sending = (new StatisticsNewsletters($newsletter, $sub1))->create();
$older = Carbon::now()->subDays(200);
$sub1sending->setSentAt($older);
$sub1sending2 = (new StatisticsNewsletters($newsletter2, $sub1))->create();
$newer = Carbon::now()->subDays(20);
$sub1sending2->setSentAt($newer);
$sub2sending = (new StatisticsNewsletters($newsletter2, $sub2))->create();
$sub2date = Carbon::now()->subDays(22);
$sub2sending->setSentAt($sub2date);
$sub3sending = (new StatisticsNewsletters($newsletter, $sub3))->create();
$sub3date = Carbon::now()->subDays(33);
$sub3sending->setSentAt($sub3date);
$this->entityManager->flush();
$clickData = $this->backfiller->getSendingDataForBatch([$sub1->getId(), $sub2->getId(), $sub3->getId(), $sub4->getId()]);
verify($clickData)->arrayCount(3);
verify($clickData[$sub1->getId()]['last_sending_at'])->equals((string)$newer);
verify($clickData[$sub2->getId()]['last_sending_at'])->equals((string)$sub2date);
verify($clickData[$sub3->getId()]['last_sending_at'])->equals((string)$sub3date);
verify(!isset($clickData[$sub4->getId()]))->true();
}
public function testItUpdatesSendingData(): void {
$sub1 = (new Subscriber())->withEmail('1@e.com')->create();
$sub2 = (new Subscriber())->withEmail('2@e.com')->create();
$sub3 = (new Subscriber())->withEmail('3@e.com')->create();
$sub4 = (new Subscriber())->withEmail('4@e.com')->create();
$this->assertInstanceOf(SubscriberEntity::class, $sub1);
$this->assertInstanceOf(SubscriberEntity::class, $sub2);
$this->assertInstanceOf(SubscriberEntity::class, $sub3);
$this->assertInstanceOf(SubscriberEntity::class, $sub4);
$newsletter = (new Newsletter())->withSendingQueue()->create();
$newsletter2 = (new Newsletter())->withSendingQueue()->create();
$sub1sending = (new StatisticsNewsletters($newsletter, $sub1))->create();
$older = Carbon::now()->subDays(200);
$sub1sending->setSentAt($older);
$sub1sending2 = (new StatisticsNewsletters($newsletter2, $sub1))->create();
$newer = Carbon::now()->subDays(20);
$sub1sending2->setSentAt($newer);
$sub2sending = (new StatisticsNewsletters($newsletter2, $sub2))->create();
$sub2date = Carbon::now()->subDays(22);
$sub2sending->setSentAt($sub2date);
$sub3sending = (new StatisticsNewsletters($newsletter, $sub3))->create();
$sub3date = Carbon::now()->subDays(33);
$sub3sending->setSentAt($sub3date);
$this->entityManager->flush();
verify($sub1->getLastSendingAt())->null();
verify($sub2->getLastSendingAt())->null();
verify($sub3->getLastSendingAt())->null();
verify($sub4->getLastSendingAt())->null();
$this->backfiller->updateBatch([$sub1, $sub2, $sub3, $sub4]);
$this->entityManager->refresh($sub1);
$this->entityManager->refresh($sub2);
$this->entityManager->refresh($sub3);
$this->entityManager->refresh($sub4);
$this->assertInstanceOf(DateTimeInterface::class, $sub1->getLastSendingAt());
$this->assertInstanceOf(DateTimeInterface::class, $sub2->getLastSendingAt());
$this->assertInstanceOf(DateTimeInterface::class, $sub3->getLastSendingAt());
verify($sub1->getLastSendingAt()->getTimestamp())->equals($newer->getTimestamp());
verify($sub2->getLastSendingAt()->getTimestamp())->equals($sub2date->getTimestamp());
verify($sub3->getLastSendingAt()->getTimestamp())->equals($sub3date->getTimestamp());
verify($sub4->getLastSendingAt())->null();
}
public function testItRetrievesSubscribersInBatches(): void {
for ($i = 0; $i < 30; $i++) {
(new Subscriber())->withEmail("$i@example.com")->create();
}
$batch = $this->backfiller->getBatch(0, 10);
verify($batch)->arrayCount(10);
$last = end($batch);
$this->assertInstanceOf(SubscriberEntity::class, $last);
$this->assertIsInt($last->getId());
$batch2 = $this->backfiller->getBatch($last->getId(), 5);
verify($batch2)->arrayCount(5);
}
private function createOrder(int $customerId, string $email, Carbon $createdAt, $status = 'wc-completed'): int {
$order = $this->tester->createWooCommerceOrder(['billing_email' => $email]);
$order->set_customer_id($customerId);
$order->set_date_created($createdAt->toDateTimeString());
$order->set_status($status);
$order->save();
$this->tester->updateWooOrderStats($order->get_id());
return $order->get_id();
}
public function _after() {
parent::_after();
global $wpdb;
$this->connection->executeQuery("TRUNCATE TABLE {$wpdb->prefix}wc_customer_lookup");
$this->connection->executeQuery("TRUNCATE TABLE {$wpdb->prefix}wc_order_stats");
$this->connection->executeQuery("TRUNCATE TABLE {$wpdb->prefix}wc_order_product_lookup");
}
}