Add fetching of global subscribers stats to Homepage data controller
[MAILPOET-4828]
This commit is contained in:
committed by
Aschepikov
parent
9217f197f9
commit
ab35f5c8c1
@ -8,6 +8,7 @@ use MailPoet\Automation\Integrations\MailPoet\Actions\SendEmailAction;
|
|||||||
use MailPoet\Automation\Integrations\MailPoet\Triggers\SomeoneSubscribesTrigger;
|
use MailPoet\Automation\Integrations\MailPoet\Triggers\SomeoneSubscribesTrigger;
|
||||||
use MailPoet\Automation\Integrations\MailPoet\Triggers\UserRegistrationTrigger;
|
use MailPoet\Automation\Integrations\MailPoet\Triggers\UserRegistrationTrigger;
|
||||||
use MailPoet\Entities\NewsletterEntity;
|
use MailPoet\Entities\NewsletterEntity;
|
||||||
|
use MailPoet\Entities\SubscriberEntity;
|
||||||
use MailPoet\Form\FormsRepository;
|
use MailPoet\Form\FormsRepository;
|
||||||
use MailPoet\Newsletter\NewslettersRepository;
|
use MailPoet\Newsletter\NewslettersRepository;
|
||||||
use MailPoet\Services\Bridge;
|
use MailPoet\Services\Bridge;
|
||||||
@ -15,6 +16,8 @@ use MailPoet\Settings\SettingsController;
|
|||||||
use MailPoet\Subscribers\SubscribersRepository;
|
use MailPoet\Subscribers\SubscribersRepository;
|
||||||
use MailPoet\Util\License\Features\Subscribers;
|
use MailPoet\Util\License\Features\Subscribers;
|
||||||
use MailPoet\WooCommerce\Helper as WooCommerceHelper;
|
use MailPoet\WooCommerce\Helper as WooCommerceHelper;
|
||||||
|
use MailPoet\WP\Functions as WPFunctions;
|
||||||
|
use MailPoetVendor\Carbon\Carbon;
|
||||||
|
|
||||||
class HomepageDataController {
|
class HomepageDataController {
|
||||||
public const UPSELL_SUBSCRIBERS_COUNT_REQUIRED = 600;
|
public const UPSELL_SUBSCRIBERS_COUNT_REQUIRED = 600;
|
||||||
@ -40,6 +43,9 @@ class HomepageDataController {
|
|||||||
/** @var Subscribers */
|
/** @var Subscribers */
|
||||||
private $subscribers;
|
private $subscribers;
|
||||||
|
|
||||||
|
/** @var WPFunctions */
|
||||||
|
private $wp;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
SettingsController $settingsController,
|
SettingsController $settingsController,
|
||||||
SubscribersRepository $subscribersRepository,
|
SubscribersRepository $subscribersRepository,
|
||||||
@ -47,6 +53,7 @@ class HomepageDataController {
|
|||||||
NewslettersRepository $newslettersRepository,
|
NewslettersRepository $newslettersRepository,
|
||||||
AutomationStorage $automationStorage,
|
AutomationStorage $automationStorage,
|
||||||
Subscribers $subscribers,
|
Subscribers $subscribers,
|
||||||
|
WPFunctions $wp,
|
||||||
WooCommerceHelper $wooCommerceHelper
|
WooCommerceHelper $wooCommerceHelper
|
||||||
) {
|
) {
|
||||||
$this->settingsController = $settingsController;
|
$this->settingsController = $settingsController;
|
||||||
@ -54,6 +61,7 @@ class HomepageDataController {
|
|||||||
$this->formsRepository = $formsRepository;
|
$this->formsRepository = $formsRepository;
|
||||||
$this->newslettersRepository = $newslettersRepository;
|
$this->newslettersRepository = $newslettersRepository;
|
||||||
$this->automationStorage = $automationStorage;
|
$this->automationStorage = $automationStorage;
|
||||||
|
$this->wp = $wp;
|
||||||
$this->wooCommerceHelper = $wooCommerceHelper;
|
$this->wooCommerceHelper = $wooCommerceHelper;
|
||||||
$this->subscribers = $subscribers;
|
$this->subscribers = $subscribers;
|
||||||
}
|
}
|
||||||
@ -73,6 +81,7 @@ class HomepageDataController {
|
|||||||
'upsellStatus' => $showUpsell ? $this->getUpsellStatus($subscribersCount) : null,
|
'upsellStatus' => $showUpsell ? $this->getUpsellStatus($subscribersCount) : null,
|
||||||
'wooCustomersCount' => $this->wooCommerceHelper->getCustomersCount(),
|
'wooCustomersCount' => $this->wooCommerceHelper->getCustomersCount(),
|
||||||
'subscribersCount' => $subscribersCount,
|
'subscribersCount' => $subscribersCount,
|
||||||
|
'subscribersStats' => $this->getSubscribersStats(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,4 +138,17 @@ class HomepageDataController {
|
|||||||
'canDisplay' => !$hasValidMssKey && $subscribersCount > self::UPSELL_SUBSCRIBERS_COUNT_REQUIRED,
|
'canDisplay' => !$hasValidMssKey && $subscribersCount > self::UPSELL_SUBSCRIBERS_COUNT_REQUIRED,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array{global:array{subscribed:int, unsubscribed:int}}
|
||||||
|
*/
|
||||||
|
private function getSubscribersStats(): array {
|
||||||
|
$thirtyDaysAgo = Carbon::createFromTimestamp($this->wp->currentTime('timestamp'))->subDays(30);
|
||||||
|
return [
|
||||||
|
'global' => [
|
||||||
|
'subscribed' => $this->subscribersRepository->getCountOfCreatedAfterWithStatues($thirtyDaysAgo, [SubscriberEntity::STATUS_SUBSCRIBED]),
|
||||||
|
'unsubscribed' => $this->subscribersRepository->getCountOfUnsubscribedAfter($thirtyDaysAgo),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ namespace MailPoet\Subscribers;
|
|||||||
use MailPoet\Config\SubscriberChangesNotifier;
|
use MailPoet\Config\SubscriberChangesNotifier;
|
||||||
use MailPoet\Doctrine\Repository;
|
use MailPoet\Doctrine\Repository;
|
||||||
use MailPoet\Entities\SegmentEntity;
|
use MailPoet\Entities\SegmentEntity;
|
||||||
|
use MailPoet\Entities\StatisticsUnsubscribeEntity;
|
||||||
use MailPoet\Entities\SubscriberCustomFieldEntity;
|
use MailPoet\Entities\SubscriberCustomFieldEntity;
|
||||||
use MailPoet\Entities\SubscriberEntity;
|
use MailPoet\Entities\SubscriberEntity;
|
||||||
use MailPoet\Entities\SubscriberSegmentEntity;
|
use MailPoet\Entities\SubscriberSegmentEntity;
|
||||||
@ -370,6 +371,35 @@ class SubscribersRepository extends Repository {
|
|||||||
return is_int($maxSubscriberId) ? $maxSubscriberId : 0;
|
return is_int($maxSubscriberId) ? $maxSubscriberId : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getCountOfCreatedAfterWithStatues(\DateTimeInterface $createdAfter, array $statuses): int {
|
||||||
|
$result = $this->entityManager->createQueryBuilder()
|
||||||
|
->select('COUNT(s.id)')
|
||||||
|
->from(SubscriberEntity::class, 's')
|
||||||
|
->where('s.createdAt > :createdAfter')
|
||||||
|
->andWhere('s.status IN (:statuses)')
|
||||||
|
->andWhere('s.deletedAt IS NULL')
|
||||||
|
->setParameter('createdAfter', $createdAfter)
|
||||||
|
->setParameter('statuses', $statuses)
|
||||||
|
->getQuery()
|
||||||
|
->getSingleScalarResult();
|
||||||
|
return intval($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCountOfUnsubscribedAfter(\DateTimeInterface $unsubscribedAfter): int {
|
||||||
|
$result = $this->entityManager->createQueryBuilder()
|
||||||
|
->select('COUNT(s.id)')
|
||||||
|
->from(StatisticsUnsubscribeEntity::class, 'su')
|
||||||
|
->join('su.subscriber', 's')
|
||||||
|
->where('s.createdAt > :unsubscribedAfter')
|
||||||
|
->andWhere('s.status = :status')
|
||||||
|
->andWhere('s.deletedAt IS NULL')
|
||||||
|
->setParameter('unsubscribedAfter', $unsubscribedAfter)
|
||||||
|
->setParameter('status', SubscriberEntity::STATUS_UNSUBSCRIBED)
|
||||||
|
->getQuery()
|
||||||
|
->getSingleScalarResult();
|
||||||
|
return intval($result);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return int - number of processed ids
|
* @return int - number of processed ids
|
||||||
*/
|
*/
|
||||||
|
@ -136,7 +136,7 @@ class Subscriber {
|
|||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function withCreatedAt(DateTimeInterface $createdAt) {
|
public function withCreatedAt(DateTimeInterface $createdAt) {
|
||||||
$this->data['setCreatedAt'] = $createdAt;
|
$this->data['createdAt'] = $createdAt;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,6 +208,7 @@ class Subscriber {
|
|||||||
if (isset($this->data['subscribedIp'])) $subscriber->setSubscribedIp($this->data['subscribedIp']);
|
if (isset($this->data['subscribedIp'])) $subscriber->setSubscribedIp($this->data['subscribedIp']);
|
||||||
if (isset($this->data['confirmedIp'])) $subscriber->setConfirmedIp($this->data['confirmedIp']);
|
if (isset($this->data['confirmedIp'])) $subscriber->setConfirmedIp($this->data['confirmedIp']);
|
||||||
if (isset($this->data['unconfirmedData'])) $subscriber->setUnconfirmedData($this->data['unconfirmedData']);
|
if (isset($this->data['unconfirmedData'])) $subscriber->setUnconfirmedData($this->data['unconfirmedData']);
|
||||||
|
if (isset($this->data['createdAt'])) $subscriber->setCreatedAt($this->data['createdAt']);
|
||||||
if (isset($this->data['source'])) {
|
if (isset($this->data['source'])) {
|
||||||
$subscriber->setSource($this->data['source']);
|
$subscriber->setSource($this->data['source']);
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,13 @@ use MailPoet\Entities\NewsletterEntity;
|
|||||||
use MailPoet\Entities\NewsletterOptionEntity;
|
use MailPoet\Entities\NewsletterOptionEntity;
|
||||||
use MailPoet\Entities\NewsletterOptionFieldEntity;
|
use MailPoet\Entities\NewsletterOptionFieldEntity;
|
||||||
use MailPoet\Entities\SettingEntity;
|
use MailPoet\Entities\SettingEntity;
|
||||||
|
use MailPoet\Entities\StatisticsUnsubscribeEntity;
|
||||||
use MailPoet\Entities\SubscriberEntity;
|
use MailPoet\Entities\SubscriberEntity;
|
||||||
use MailPoet\Settings\SettingsController;
|
use MailPoet\Settings\SettingsController;
|
||||||
use MailPoet\Test\DataFactories\Form;
|
use MailPoet\Test\DataFactories\Form;
|
||||||
use MailPoet\Test\DataFactories\Newsletter;
|
use MailPoet\Test\DataFactories\Newsletter;
|
||||||
use MailPoet\Test\DataFactories\Subscriber;
|
use MailPoet\Test\DataFactories\Subscriber;
|
||||||
|
use MailPoetVendor\Carbon\Carbon;
|
||||||
|
|
||||||
class HomepageDataControllerTest extends \MailPoetTest {
|
class HomepageDataControllerTest extends \MailPoetTest {
|
||||||
/** @var HomepageDataController */
|
/** @var HomepageDataController */
|
||||||
@ -34,6 +36,8 @@ class HomepageDataControllerTest extends \MailPoetTest {
|
|||||||
expect($data['productDiscoveryStatus'])->notEmpty();
|
expect($data['productDiscoveryStatus'])->notEmpty();
|
||||||
expect($data['wooCustomersCount'])->int();
|
expect($data['wooCustomersCount'])->int();
|
||||||
expect($data['subscribersCount'])->int();
|
expect($data['subscribersCount'])->int();
|
||||||
|
expect($data['subscribersStats'])->array();
|
||||||
|
expect($data['taskListStatus'])->notEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItFetchesSenderTaskListStatus(): void {
|
public function testItFetchesSenderTaskListStatus(): void {
|
||||||
@ -169,6 +173,37 @@ class HomepageDataControllerTest extends \MailPoetTest {
|
|||||||
expect($productDiscoveryStatus['setUpAbandonedCartEmail'])->true();
|
expect($productDiscoveryStatus['setUpAbandonedCartEmail'])->true();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testItFetchesSubscriberStatsForZeroSubscribers(): void {
|
||||||
|
$subscribersStats = $this->homepageDataController->getPageData()['subscribersStats'];
|
||||||
|
expect($subscribersStats['global']['subscribed'])->equals(0);
|
||||||
|
expect($subscribersStats['global']['unsubscribed'])->equals(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItFetchesCorrectGlobalSubscriberStats(): void {
|
||||||
|
$thirtyOneDaysAgo = Carbon::now()->subDays(31);
|
||||||
|
$twentyNineDaysAgo = Carbon::now()->subDays(29);
|
||||||
|
// Old subscribed
|
||||||
|
(new Subscriber())->withCreatedAt($thirtyOneDaysAgo)->withStatus(SubscriberEntity::STATUS_SUBSCRIBED)->create();
|
||||||
|
// New subscribed
|
||||||
|
(new Subscriber())->withCreatedAt($twentyNineDaysAgo)->withStatus(SubscriberEntity::STATUS_SUBSCRIBED)->create();
|
||||||
|
// Unsubscribed long time ago
|
||||||
|
$oldUnsubscribed = (new Subscriber())->withCreatedAt($thirtyOneDaysAgo)->withStatus(SubscriberEntity::STATUS_UNSUBSCRIBED)->create();
|
||||||
|
$oldUnsubscribedStats = new StatisticsUnsubscribeEntity(null, null, $oldUnsubscribed);
|
||||||
|
$oldUnsubscribedStats->setCreatedAt($thirtyOneDaysAgo);
|
||||||
|
$this->entityManager->persist($oldUnsubscribedStats);
|
||||||
|
$this->entityManager->flush();
|
||||||
|
// Freshly unsubscribed
|
||||||
|
$newUnsubscribed = (new Subscriber())->withCreatedAt($twentyNineDaysAgo)->withStatus(SubscriberEntity::STATUS_UNSUBSCRIBED)->create();
|
||||||
|
$newUnsubscribedStats = new StatisticsUnsubscribeEntity(null, null, $newUnsubscribed);
|
||||||
|
$newUnsubscribedStats->setCreatedAt($twentyNineDaysAgo);
|
||||||
|
$this->entityManager->persist($newUnsubscribedStats);
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
$subscribersStats = $this->homepageDataController->getPageData()['subscribersStats'];
|
||||||
|
expect($subscribersStats['global']['subscribed'])->equals(1);
|
||||||
|
expect($subscribersStats['global']['unsubscribed'])->equals(1);
|
||||||
|
}
|
||||||
|
|
||||||
private function cleanup(): void {
|
private function cleanup(): void {
|
||||||
$this->truncateEntity(SettingEntity::class);
|
$this->truncateEntity(SettingEntity::class);
|
||||||
$this->truncateEntity(SubscriberEntity::class);
|
$this->truncateEntity(SubscriberEntity::class);
|
||||||
|
Reference in New Issue
Block a user