Refactor segment lists fetching methods to separate repository
[MAILPOET-3164]
This commit is contained in:
committed by
Veljko V
parent
cd578e6475
commit
8456581695
@@ -77,7 +77,7 @@ use MailPoet\Form\Util\Export;
|
|||||||
use MailPoet\Models\Form;
|
use MailPoet\Models\Form;
|
||||||
use MailPoet\Router\Endpoints\FormPreview;
|
use MailPoet\Router\Endpoints\FormPreview;
|
||||||
use MailPoet\Router\Router;
|
use MailPoet\Router\Router;
|
||||||
use MailPoet\Segments\SegmentSubscribersRepository;
|
use MailPoet\Segments\SegmentsSimpleListRepository;
|
||||||
use MailPoet\Settings\Pages;
|
use MailPoet\Settings\Pages;
|
||||||
use MailPoet\Settings\UserFlagsController;
|
use MailPoet\Settings\UserFlagsController;
|
||||||
use MailPoet\WP\AutocompletePostListLoader as WPPostListLoader;
|
use MailPoet\WP\AutocompletePostListLoader as WPPostListLoader;
|
||||||
@@ -117,8 +117,8 @@ class FormEditor {
|
|||||||
/** @var WPPostListLoader */
|
/** @var WPPostListLoader */
|
||||||
private $wpPostListLoader;
|
private $wpPostListLoader;
|
||||||
|
|
||||||
/** @var SegmentSubscribersRepository */
|
/** @var SegmentsSimpleListRepository */
|
||||||
private $segmentSubscribersRepository;
|
private $segmentsListRepository;
|
||||||
|
|
||||||
private $activeTemplates = [
|
private $activeTemplates = [
|
||||||
FormEntity::DISPLAY_TYPE_POPUP => [
|
FormEntity::DISPLAY_TYPE_POPUP => [
|
||||||
@@ -205,7 +205,7 @@ class FormEditor {
|
|||||||
UserFlagsController $userFlags,
|
UserFlagsController $userFlags,
|
||||||
WPPostListLoader $wpPostListLoader,
|
WPPostListLoader $wpPostListLoader,
|
||||||
TemplateRepository $templateRepository,
|
TemplateRepository $templateRepository,
|
||||||
SegmentSubscribersRepository $segmentSubscribersRepository
|
SegmentsSimpleListRepository $segmentsListRepository
|
||||||
) {
|
) {
|
||||||
$this->pageRenderer = $pageRenderer;
|
$this->pageRenderer = $pageRenderer;
|
||||||
$this->customFieldsRepository = $customFieldsRepository;
|
$this->customFieldsRepository = $customFieldsRepository;
|
||||||
@@ -218,7 +218,7 @@ class FormEditor {
|
|||||||
$this->templatesRepository = $templateRepository;
|
$this->templatesRepository = $templateRepository;
|
||||||
$this->userFlags = $userFlags;
|
$this->userFlags = $userFlags;
|
||||||
$this->wpPostListLoader = $wpPostListLoader;
|
$this->wpPostListLoader = $wpPostListLoader;
|
||||||
$this->segmentSubscribersRepository = $segmentSubscribersRepository;
|
$this->segmentsListRepository = $segmentsListRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render() {
|
public function render() {
|
||||||
@@ -240,7 +240,7 @@ class FormEditor {
|
|||||||
'shortcode' => Export::get('shortcode', $form),
|
'shortcode' => Export::get('shortcode', $form),
|
||||||
],
|
],
|
||||||
'mailpoet_pages' => Pages::getMailPoetPages(),
|
'mailpoet_pages' => Pages::getMailPoetPages(),
|
||||||
'segments' => $this->segmentSubscribersRepository->getSimpleSegmentListWithSubscribersCounts(SegmentEntity::TYPE_DEFAULT),
|
'segments' => $this->segmentsListRepository->getListWithSubscribedSubscribersCounts([SegmentEntity::TYPE_DEFAULT]),
|
||||||
'styles' => $this->formRenderer->getCustomStyles($form),
|
'styles' => $this->formRenderer->getCustomStyles($form),
|
||||||
'date_types' => array_map(function ($label, $value) {
|
'date_types' => array_map(function ($label, $value) {
|
||||||
return [
|
return [
|
||||||
|
@@ -12,7 +12,7 @@ use MailPoet\Features\FeaturesController;
|
|||||||
use MailPoet\Listing\PageLimit;
|
use MailPoet\Listing\PageLimit;
|
||||||
use MailPoet\Models\Newsletter;
|
use MailPoet\Models\Newsletter;
|
||||||
use MailPoet\NewsletterTemplates\NewsletterTemplatesRepository;
|
use MailPoet\NewsletterTemplates\NewsletterTemplatesRepository;
|
||||||
use MailPoet\Segments\SegmentSubscribersRepository;
|
use MailPoet\Segments\SegmentsSimpleListRepository;
|
||||||
use MailPoet\Services\Bridge;
|
use MailPoet\Services\Bridge;
|
||||||
use MailPoet\Settings\SettingsController;
|
use MailPoet\Settings\SettingsController;
|
||||||
use MailPoet\Settings\UserFlagsController;
|
use MailPoet\Settings\UserFlagsController;
|
||||||
@@ -65,8 +65,8 @@ class Newsletters {
|
|||||||
/** @var WPPostListLoader */
|
/** @var WPPostListLoader */
|
||||||
private $wpPostListLoader;
|
private $wpPostListLoader;
|
||||||
|
|
||||||
/** @var SegmentSubscribersRepository */
|
/** @var SegmentsSimpleListRepository */
|
||||||
private $segmentSubscribersRepository;
|
private $segmentsListRepository;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
PageRenderer $pageRenderer,
|
PageRenderer $pageRenderer,
|
||||||
@@ -82,7 +82,7 @@ class Newsletters {
|
|||||||
NewsletterTemplatesRepository $newsletterTemplatesRepository,
|
NewsletterTemplatesRepository $newsletterTemplatesRepository,
|
||||||
WPPostListLoader $wpPostListLoader,
|
WPPostListLoader $wpPostListLoader,
|
||||||
AutomaticEmails $automaticEmails,
|
AutomaticEmails $automaticEmails,
|
||||||
SegmentSubscribersRepository $segmentSubscribersRepository
|
SegmentsSimpleListRepository $segmentsListRepository
|
||||||
) {
|
) {
|
||||||
$this->pageRenderer = $pageRenderer;
|
$this->pageRenderer = $pageRenderer;
|
||||||
$this->listingPageLimit = $listingPageLimit;
|
$this->listingPageLimit = $listingPageLimit;
|
||||||
@@ -97,7 +97,7 @@ class Newsletters {
|
|||||||
$this->newsletterTemplatesRepository = $newsletterTemplatesRepository;
|
$this->newsletterTemplatesRepository = $newsletterTemplatesRepository;
|
||||||
$this->automaticEmails = $automaticEmails;
|
$this->automaticEmails = $automaticEmails;
|
||||||
$this->wpPostListLoader = $wpPostListLoader;
|
$this->wpPostListLoader = $wpPostListLoader;
|
||||||
$this->segmentSubscribersRepository = $segmentSubscribersRepository;
|
$this->segmentsListRepository = $segmentsListRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render() {
|
public function render() {
|
||||||
@@ -115,7 +115,7 @@ class Newsletters {
|
|||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
$data['items_per_page'] = $this->listingPageLimit->getLimitPerPage('newsletters');
|
$data['items_per_page'] = $this->listingPageLimit->getLimitPerPage('newsletters');
|
||||||
$segments = $this->segmentSubscribersRepository->getSimpleSegmentListWithSubscribersCounts();
|
$segments = $this->segmentsListRepository->getListWithSubscribedSubscribersCounts();
|
||||||
$data['segments'] = $segments;
|
$data['segments'] = $segments;
|
||||||
$data['settings'] = $this->settings->getAll();
|
$data['settings'] = $this->settings->getAll();
|
||||||
$data['mss_active'] = Bridge::isMPSendingServiceEnabled();
|
$data['mss_active'] = Bridge::isMPSendingServiceEnabled();
|
||||||
|
@@ -6,7 +6,7 @@ use MailPoet\AdminPages\PageRenderer;
|
|||||||
use MailPoet\Config\Installer;
|
use MailPoet\Config\Installer;
|
||||||
use MailPoet\Config\ServicesChecker;
|
use MailPoet\Config\ServicesChecker;
|
||||||
use MailPoet\Entities\SegmentEntity;
|
use MailPoet\Entities\SegmentEntity;
|
||||||
use MailPoet\Segments\SegmentSubscribersRepository;
|
use MailPoet\Segments\SegmentsSimpleListRepository;
|
||||||
use MailPoet\Settings\Hosts;
|
use MailPoet\Settings\Hosts;
|
||||||
use MailPoet\Settings\Pages;
|
use MailPoet\Settings\Pages;
|
||||||
use MailPoet\Settings\SettingsController;
|
use MailPoet\Settings\SettingsController;
|
||||||
@@ -38,8 +38,8 @@ class Settings {
|
|||||||
/** @var Installation */
|
/** @var Installation */
|
||||||
private $installation;
|
private $installation;
|
||||||
|
|
||||||
/** @var SegmentSubscribersRepository */
|
/** @var SegmentsSimpleListRepository */
|
||||||
private $segmentSubscribersRepository;
|
private $segmentsListRepository;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
PageRenderer $pageRenderer,
|
PageRenderer $pageRenderer,
|
||||||
@@ -49,7 +49,7 @@ class Settings {
|
|||||||
ServicesChecker $servicesChecker,
|
ServicesChecker $servicesChecker,
|
||||||
Installation $installation,
|
Installation $installation,
|
||||||
Captcha $captcha,
|
Captcha $captcha,
|
||||||
SegmentSubscribersRepository $segmentSubscribersRepository
|
SegmentsSimpleListRepository $segmentsListRepository
|
||||||
) {
|
) {
|
||||||
$this->pageRenderer = $pageRenderer;
|
$this->pageRenderer = $pageRenderer;
|
||||||
$this->settings = $settings;
|
$this->settings = $settings;
|
||||||
@@ -58,7 +58,7 @@ class Settings {
|
|||||||
$this->servicesChecker = $servicesChecker;
|
$this->servicesChecker = $servicesChecker;
|
||||||
$this->installation = $installation;
|
$this->installation = $installation;
|
||||||
$this->captcha = $captcha;
|
$this->captcha = $captcha;
|
||||||
$this->segmentSubscribersRepository = $segmentSubscribersRepository;
|
$this->segmentsListRepository = $segmentsListRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render() {
|
public function render() {
|
||||||
@@ -72,7 +72,7 @@ class Settings {
|
|||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'settings' => $settings,
|
'settings' => $settings,
|
||||||
'segments' => $this->segmentSubscribersRepository->getSimpleSegmentListWithSubscribersCounts(SegmentEntity::TYPE_DEFAULT),
|
'segments' => $this->segmentsListRepository->getListWithSubscribedSubscribersCounts([SegmentEntity::TYPE_DEFAULT]),
|
||||||
'premium_key_valid' => !empty($premiumKeyValid),
|
'premium_key_valid' => !empty($premiumKeyValid),
|
||||||
'mss_key_valid' => !empty($mpApiKeyValid),
|
'mss_key_valid' => !empty($mpApiKeyValid),
|
||||||
'pages' => Pages::getAll(),
|
'pages' => Pages::getAll(),
|
||||||
|
@@ -7,7 +7,7 @@ use MailPoet\Config\ServicesChecker;
|
|||||||
use MailPoet\Form\Block;
|
use MailPoet\Form\Block;
|
||||||
use MailPoet\Listing\PageLimit;
|
use MailPoet\Listing\PageLimit;
|
||||||
use MailPoet\Models\CustomField;
|
use MailPoet\Models\CustomField;
|
||||||
use MailPoet\Segments\SegmentSubscribersRepository;
|
use MailPoet\Segments\SegmentsSimpleListRepository;
|
||||||
use MailPoet\Services\Bridge;
|
use MailPoet\Services\Bridge;
|
||||||
use MailPoet\Subscribers\ConfirmationEmailMailer;
|
use MailPoet\Subscribers\ConfirmationEmailMailer;
|
||||||
use MailPoet\Util\License\Features\Subscribers as SubscribersFeature;
|
use MailPoet\Util\License\Features\Subscribers as SubscribersFeature;
|
||||||
@@ -33,8 +33,8 @@ class Subscribers {
|
|||||||
/** @var ServicesChecker */
|
/** @var ServicesChecker */
|
||||||
private $servicesChecker;
|
private $servicesChecker;
|
||||||
|
|
||||||
/** @var SegmentSubscribersRepository */
|
/** @var SegmentsSimpleListRepository */
|
||||||
private $segmentSubscribersRepository;
|
private $segmentsListRepository;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
PageRenderer $pageRenderer,
|
PageRenderer $pageRenderer,
|
||||||
@@ -43,7 +43,7 @@ class Subscribers {
|
|||||||
WPFunctions $wp,
|
WPFunctions $wp,
|
||||||
ServicesChecker $servicesChecker,
|
ServicesChecker $servicesChecker,
|
||||||
Block\Date $dateBlock,
|
Block\Date $dateBlock,
|
||||||
SegmentSubscribersRepository $segmentSubscribersRepository
|
SegmentsSimpleListRepository $segmentsListRepository
|
||||||
) {
|
) {
|
||||||
$this->pageRenderer = $pageRenderer;
|
$this->pageRenderer = $pageRenderer;
|
||||||
$this->listingPageLimit = $listingPageLimit;
|
$this->listingPageLimit = $listingPageLimit;
|
||||||
@@ -51,14 +51,14 @@ class Subscribers {
|
|||||||
$this->wp = $wp;
|
$this->wp = $wp;
|
||||||
$this->dateBlock = $dateBlock;
|
$this->dateBlock = $dateBlock;
|
||||||
$this->servicesChecker = $servicesChecker;
|
$this->servicesChecker = $servicesChecker;
|
||||||
$this->segmentSubscribersRepository = $segmentSubscribersRepository;
|
$this->segmentsListRepository = $segmentsListRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render() {
|
public function render() {
|
||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
$data['items_per_page'] = $this->listingPageLimit->getLimitPerPage('subscribers');
|
$data['items_per_page'] = $this->listingPageLimit->getLimitPerPage('subscribers');
|
||||||
$data['segments'] = $this->segmentSubscribersRepository->getSimpleSegmentListWithSubscribersCounts();
|
$data['segments'] = $this->segmentsListRepository->getListWithSubscribedSubscribersCounts();
|
||||||
|
|
||||||
$data['custom_fields'] = array_map(function($field) {
|
$data['custom_fields'] = array_map(function($field) {
|
||||||
$field['params'] = unserialize($field['params']);
|
$field['params'] = unserialize($field['params']);
|
||||||
|
@@ -257,6 +257,7 @@ class ContainerConfigurator implements IContainerConfigurator {
|
|||||||
$container->autowire(\MailPoet\Segments\SegmentsRepository::class)->setPublic(true);
|
$container->autowire(\MailPoet\Segments\SegmentsRepository::class)->setPublic(true);
|
||||||
$container->autowire(\MailPoet\Segments\SegmentSubscribersRepository::class)->setPublic(true);
|
$container->autowire(\MailPoet\Segments\SegmentSubscribersRepository::class)->setPublic(true);
|
||||||
$container->autowire(\MailPoet\Segments\SegmentListingRepository::class)->setPublic(true);
|
$container->autowire(\MailPoet\Segments\SegmentListingRepository::class)->setPublic(true);
|
||||||
|
$container->autowire(\MailPoet\Segments\SegmentsSimpleListRepository::class)->setPublic(true);
|
||||||
$container->autowire(\MailPoet\Segments\SegmentSaveController::class)->setPublic(true);
|
$container->autowire(\MailPoet\Segments\SegmentSaveController::class)->setPublic(true);
|
||||||
$container->autowire(\MailPoet\Segments\DynamicSegments\DynamicSegmentsListingRepository::class)->setPublic(true);
|
$container->autowire(\MailPoet\Segments\DynamicSegments\DynamicSegmentsListingRepository::class)->setPublic(true);
|
||||||
$container->autowire(\MailPoet\Segments\DynamicSegments\FilterHandler::class)->setPublic(true);
|
$container->autowire(\MailPoet\Segments\DynamicSegments\FilterHandler::class)->setPublic(true);
|
||||||
|
@@ -24,6 +24,7 @@ class SegmentEntity {
|
|||||||
const TYPE_WC_USERS = 'woocommerce_users';
|
const TYPE_WC_USERS = 'woocommerce_users';
|
||||||
const TYPE_DEFAULT = 'default';
|
const TYPE_DEFAULT = 'default';
|
||||||
const TYPE_DYNAMIC = 'dynamic';
|
const TYPE_DYNAMIC = 'dynamic';
|
||||||
|
const TYPE_WITHOUT_LIST = 'without-list';
|
||||||
|
|
||||||
const SEGMENT_ENABLED = 'active';
|
const SEGMENT_ENABLED = 'active';
|
||||||
const SEGMENT_DISABLED = 'disabled';
|
const SEGMENT_DISABLED = 'disabled';
|
||||||
|
@@ -73,61 +73,6 @@ class SegmentSubscribersRepository {
|
|||||||
->getQuery()->getSingleScalarResult();
|
->getQuery()->getSingleScalarResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is fetches list of all segments basic data and count of subscribers.
|
|
||||||
* @return array<array{id: string, name: string, type: string, subscribers: int}>
|
|
||||||
*/
|
|
||||||
public function getSimpleSegmentListWithSubscribersCounts(
|
|
||||||
string $segmentType = null,
|
|
||||||
string $subscriberStatus = SubscriberEntity::STATUS_SUBSCRIBED
|
|
||||||
): array {
|
|
||||||
$subscribersTable = $this->entityManager->getClassMetadata(SubscriberEntity::class)->getTableName();
|
|
||||||
$subscribersSegmentsTable = $this->entityManager->getClassMetadata(SubscriberSegmentEntity::class)->getTableName();
|
|
||||||
$segmentsTable = $this->entityManager->getClassMetadata(SegmentEntity::class)->getTableName();
|
|
||||||
|
|
||||||
$countCondition = "subscribers.deleted_at IS NULL";
|
|
||||||
if ($subscriberStatus) {
|
|
||||||
$countCondition .= " AND subscribers.status= :subscriberStatus AND subsegments.status = :subscriberStatus";
|
|
||||||
}
|
|
||||||
|
|
||||||
$segmentsDataQuery = $this->entityManager
|
|
||||||
->getConnection()
|
|
||||||
->createQueryBuilder()
|
|
||||||
->select(
|
|
||||||
"segments.id, segments.name, segments.type, COUNT(IF($countCondition, 1, NULL)) as subscribers"
|
|
||||||
)->from($segmentsTable, 'segments')
|
|
||||||
->leftJoin('segments', $subscribersSegmentsTable, 'subsegments', "subsegments.segment_id = segments.id")
|
|
||||||
->leftJoin('subsegments', $subscribersTable, 'subscribers', "subscribers.id = subsegments.subscriber_id")
|
|
||||||
->where('segments.deleted_at IS NULL')
|
|
||||||
->groupBy('segments.id')
|
|
||||||
->addGroupBy('segments.name')
|
|
||||||
->addGroupBy('segments.type')
|
|
||||||
->orderBy('segments.name');
|
|
||||||
|
|
||||||
if ($subscriberStatus) {
|
|
||||||
$segmentsDataQuery->setParameter('subscriberStatus', $subscriberStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($segmentType) {
|
|
||||||
$segmentsDataQuery
|
|
||||||
->andWhere('segments.type = :typeParam')
|
|
||||||
->setParameter('typeParam', $segmentType);
|
|
||||||
}
|
|
||||||
|
|
||||||
$statement = $this->executeQuery($segmentsDataQuery);
|
|
||||||
$segments = $statement->fetchAll();
|
|
||||||
|
|
||||||
// Fetch subscribers counts for dynamic segments and correct data types
|
|
||||||
foreach ($segments as $key => $segment) {
|
|
||||||
if ($segment['type'] === SegmentEntity::TYPE_DYNAMIC) {
|
|
||||||
$segments[$key]['subscribers'] = $this->getSubscribersCount((int)$segment['id'], SubscriberEntity::STATUS_SUBSCRIBED);
|
|
||||||
} else {
|
|
||||||
$segments[$key]['subscribers'] = (int)$segment['subscribers'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $segments;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function loadSubscriberIdsInSegment(int $segmentId, array $candidateIds = null): array {
|
private function loadSubscriberIdsInSegment(int $segmentId, array $candidateIds = null): array {
|
||||||
$segment = $this->getSegment($segmentId);
|
$segment = $this->getSegment($segmentId);
|
||||||
$subscribersTable = $this->entityManager->getClassMetadata(SubscriberEntity::class)->getTableName();
|
$subscribersTable = $this->entityManager->getClassMetadata(SubscriberEntity::class)->getTableName();
|
||||||
|
123
lib/Segments/SegmentsSimpleListRepository.php
Normal file
123
lib/Segments/SegmentsSimpleListRepository.php
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MailPoet\Segments;
|
||||||
|
|
||||||
|
use MailPoet\Entities\SegmentEntity;
|
||||||
|
use MailPoet\Entities\SubscriberEntity;
|
||||||
|
use MailPoet\Entities\SubscriberSegmentEntity;
|
||||||
|
use MailPoetVendor\Doctrine\DBAL\Connection;
|
||||||
|
use MailPoetVendor\Doctrine\DBAL\Driver\Statement;
|
||||||
|
use MailPoetVendor\Doctrine\ORM\EntityManager;
|
||||||
|
|
||||||
|
class SegmentsSimpleListRepository {
|
||||||
|
/** @var EntityManager */
|
||||||
|
private $entityManager;
|
||||||
|
|
||||||
|
/** @var SegmentSubscribersRepository */
|
||||||
|
private $segmentsSubscriberRepository;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
EntityManager $entityManager,
|
||||||
|
SegmentSubscribersRepository $segmentsSubscriberRepository
|
||||||
|
) {
|
||||||
|
$this->entityManager = $entityManager;
|
||||||
|
$this->segmentsSubscriberRepository = $segmentsSubscriberRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This fetches list of all segments basic data and count of subscribed subscribers.
|
||||||
|
* @return array<array{id: string, name: string, type: string, subscribers: int}>
|
||||||
|
*/
|
||||||
|
public function getListWithSubscribedSubscribersCounts(array $segmentTypes = []): array {
|
||||||
|
return $this->getList(
|
||||||
|
$segmentTypes,
|
||||||
|
SubscriberEntity::STATUS_SUBSCRIBED,
|
||||||
|
SubscriberEntity::STATUS_SUBSCRIBED
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This fetches list of all segments basic data and count of subscribers associated to a segment regardless their subscription status.
|
||||||
|
* @return array<array{id: string, name: string, type: string, subscribers: int}>
|
||||||
|
*/
|
||||||
|
public function getListWithAssociatedSubscribersCounts(array $segmentTypes = []): array {
|
||||||
|
return $this->getList(
|
||||||
|
$segmentTypes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a virtual segment with for subscribers without list
|
||||||
|
* @return array<array{id: string, name: string, type: string, subscribers: int}>
|
||||||
|
*/
|
||||||
|
public function addVirtualSubscribersWithoutListSegment(array $segments): array {
|
||||||
|
$segments[] = [
|
||||||
|
'id' => '0',
|
||||||
|
'type' => SegmentEntity::TYPE_WITHOUT_LIST,
|
||||||
|
'name' => __('Not in a List', 'mailpoet'),
|
||||||
|
'subscribers' => $this->segmentsSubscriberRepository->getSubscribersWithoutSegmentCount(),
|
||||||
|
];
|
||||||
|
return $segments;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<array{id: string, name: string, type: string, subscribers: int}>
|
||||||
|
*/
|
||||||
|
private function getList(
|
||||||
|
array $segmentTypes = [],
|
||||||
|
string $subscriberGlobalStatus = null,
|
||||||
|
string $subscriberSegmentStatus = null
|
||||||
|
): array {
|
||||||
|
$subscribersTable = $this->entityManager->getClassMetadata(SubscriberEntity::class)->getTableName();
|
||||||
|
$subscribersSegmentsTable = $this->entityManager->getClassMetadata(SubscriberSegmentEntity::class)->getTableName();
|
||||||
|
$segmentsTable = $this->entityManager->getClassMetadata(SegmentEntity::class)->getTableName();
|
||||||
|
|
||||||
|
$segmentsDataQuery = $this->entityManager
|
||||||
|
->getConnection()
|
||||||
|
->createQueryBuilder();
|
||||||
|
|
||||||
|
$countCondition = "subscribers.deleted_at IS NULL AND subsegments.id IS NOT NULL AND subscribers.id IS NOT NULL";
|
||||||
|
if ($subscriberGlobalStatus) {
|
||||||
|
$countCondition .= " AND subscribers.status= :subscriberGlobalStatus";
|
||||||
|
$segmentsDataQuery->setParameter('subscriberGlobalStatus', $subscriberGlobalStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($subscriberSegmentStatus) {
|
||||||
|
$countCondition .= " AND subsegments.status = :subscriberSegmentStatus";
|
||||||
|
$segmentsDataQuery->setParameter('subscriberSegmentStatus', $subscriberSegmentStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
$segmentsDataQuery->select(
|
||||||
|
"segments.id, segments.name, segments.type, COUNT(IF($countCondition, 1, NULL)) as subscribers"
|
||||||
|
)->from($segmentsTable, 'segments')
|
||||||
|
->leftJoin('segments', $subscribersSegmentsTable, 'subsegments', "subsegments.segment_id = segments.id")
|
||||||
|
->leftJoin('subsegments', $subscribersTable, 'subscribers', "subscribers.id = subsegments.subscriber_id")
|
||||||
|
->where('segments.deleted_at IS NULL')
|
||||||
|
->groupBy('segments.id')
|
||||||
|
->addGroupBy('segments.name')
|
||||||
|
->addGroupBy('segments.type')
|
||||||
|
->orderBy('segments.name');
|
||||||
|
|
||||||
|
if (!empty($segmentTypes)) {
|
||||||
|
$segmentsDataQuery
|
||||||
|
->andWhere('segments.type IN (:typesParam)')
|
||||||
|
->setParameter('typesParam', $segmentTypes, Connection::PARAM_STR_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
$statement = $segmentsDataQuery->execute();
|
||||||
|
if (!$statement instanceof Statement) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$segments = $statement->fetchAll();
|
||||||
|
|
||||||
|
// Fetch subscribers counts for dynamic segments and correct data types
|
||||||
|
foreach ($segments as $key => $segment) {
|
||||||
|
if ($segment['type'] === SegmentEntity::TYPE_DYNAMIC) {
|
||||||
|
$segments[$key]['subscribers'] = $this->segmentsSubscriberRepository->getSubscribersCount((int)$segment['id'], $subscriberGlobalStatus);
|
||||||
|
} else {
|
||||||
|
$segments[$key]['subscribers'] = (int)$segment['subscribers'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $segments;
|
||||||
|
}
|
||||||
|
}
|
@@ -5,7 +5,7 @@ namespace MailPoet\Subscribers\ImportExport;
|
|||||||
use MailPoet\DI\ContainerWrapper;
|
use MailPoet\DI\ContainerWrapper;
|
||||||
use MailPoet\Entities\SegmentEntity;
|
use MailPoet\Entities\SegmentEntity;
|
||||||
use MailPoet\Models\CustomField;
|
use MailPoet\Models\CustomField;
|
||||||
use MailPoet\Segments\SegmentSubscribersRepository;
|
use MailPoet\Segments\SegmentsSimpleListRepository;
|
||||||
use MailPoet\Util\Helpers;
|
use MailPoet\Util\Helpers;
|
||||||
|
|
||||||
class ImportExportFactory {
|
class ImportExportFactory {
|
||||||
@@ -15,34 +15,23 @@ class ImportExportFactory {
|
|||||||
/** @var string|null */
|
/** @var string|null */
|
||||||
public $action;
|
public $action;
|
||||||
|
|
||||||
/** @var SegmentSubscribersRepository */
|
/** @var SegmentsSimpleListRepository */
|
||||||
private $segmentSubscribersRepository;
|
private $segmentsListRepository;
|
||||||
|
|
||||||
public function __construct($action = null) {
|
public function __construct($action = null) {
|
||||||
$this->action = $action;
|
$this->action = $action;
|
||||||
$this->segmentSubscribersRepository = ContainerWrapper::getInstance()->get(SegmentSubscribersRepository::class);
|
$this->segmentsListRepository = ContainerWrapper::getInstance()->get(SegmentsSimpleListRepository::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSegments() {
|
public function getSegments() {
|
||||||
|
|
||||||
if ($this->action === self::IMPORT_ACTION) {
|
if ($this->action === self::IMPORT_ACTION) {
|
||||||
$segments = $this->segmentSubscribersRepository->getSimpleSegmentListWithSubscribersCounts();
|
$segments = $this->segmentsListRepository->getListWithSubscribedSubscribersCounts([SegmentEntity::TYPE_DEFAULT, SegmentEntity::TYPE_WP_USERS]);
|
||||||
$segments = array_values(array_filter($segments, function($segment) {
|
|
||||||
return in_array($segment['type'], [SegmentEntity::TYPE_DEFAULT, SegmentEntity::TYPE_WP_USERS]);
|
|
||||||
}));
|
|
||||||
} else {
|
} else {
|
||||||
$segments = $this->segmentSubscribersRepository->getSimpleSegmentListWithSubscribersCounts(null, '');
|
$segments = $this->segmentsListRepository->getListWithAssociatedSubscribersCounts();
|
||||||
|
$segments = $this->segmentsListRepository->addVirtualSubscribersWithoutListSegment($segments);
|
||||||
$segments = array_values(array_filter($segments, function($segment) {
|
$segments = array_values(array_filter($segments, function($segment) {
|
||||||
return $segment['subscribers'] > 0;
|
return $segment['subscribers'] > 0;
|
||||||
}));
|
}));
|
||||||
$withoutSegmentCount = $this->segmentSubscribersRepository->getSubscribersWithoutSegmentCount();
|
|
||||||
if ($withoutSegmentCount) {
|
|
||||||
$segments[] = [
|
|
||||||
'id' => 0,
|
|
||||||
'name' => __('Not in a List', 'mailpoet'),
|
|
||||||
'subscribers' => $withoutSegmentCount,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_map(function($segment) {
|
return array_map(function($segment) {
|
||||||
|
164
tests/integration/Segments/SegmentsSimpleListRepositoryTest.php
Normal file
164
tests/integration/Segments/SegmentsSimpleListRepositoryTest.php
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MailPoet\Segments;
|
||||||
|
|
||||||
|
use MailPoet\Config\Populator;
|
||||||
|
use MailPoet\Entities\DynamicSegmentFilterEntity;
|
||||||
|
use MailPoet\Entities\SegmentEntity;
|
||||||
|
use MailPoet\Entities\SubscriberEntity;
|
||||||
|
use MailPoet\Entities\SubscriberSegmentEntity;
|
||||||
|
use MailPoet\Subscribers\Source;
|
||||||
|
|
||||||
|
class SegmentsSimpleListRepositoryTest extends \MailPoetTest {
|
||||||
|
/** @var SegmentsSimpleListRepository */
|
||||||
|
private $segmentsListRepository;
|
||||||
|
|
||||||
|
public function _before() {
|
||||||
|
parent::_before();
|
||||||
|
$segmentRepository = $this->diContainer->get(SegmentsRepository::class);
|
||||||
|
$this->cleanup();
|
||||||
|
|
||||||
|
// Prepare Segments
|
||||||
|
$this->createDynamicSegmentEntityForEditorUsers();
|
||||||
|
$defaultSegment = $segmentRepository->createOrUpdate('Segment Default 1' . rand(0, 10000));
|
||||||
|
$segmentRepository->createOrUpdate('Segment Default 2' . rand(0, 10000));
|
||||||
|
$populator = $this->diContainer->get(Populator::class);
|
||||||
|
$populator->up(); // Prepare WooCommerce and WP Users segments
|
||||||
|
// Remove synced WP Users
|
||||||
|
$this->truncateEntity(SubscriberEntity::class);
|
||||||
|
$this->truncateEntity(SubscriberSegmentEntity::class);
|
||||||
|
|
||||||
|
// Prepare Subscribers
|
||||||
|
$wpUserEmail = 'user-role-test1@example.com';
|
||||||
|
$this->tester->deleteWordPressUser($wpUserEmail);
|
||||||
|
$this->tester->createWordPressUser($wpUserEmail, 'editor');
|
||||||
|
$wpUserSubscriber = $this->entityManager
|
||||||
|
->getRepository(SubscriberEntity::class)
|
||||||
|
->findOneBy(['email' => $wpUserEmail]);
|
||||||
|
assert($wpUserSubscriber instanceof SubscriberEntity);
|
||||||
|
$wpUserSubscriber->setStatus(SubscriberEntity::STATUS_SUBSCRIBED);
|
||||||
|
|
||||||
|
$subscriber1 = $this->createSubscriberEntity();
|
||||||
|
$subscriber2 = $this->createSubscriberEntity();
|
||||||
|
$subscriber2->setStatus(SubscriberEntity::STATUS_UNSUBSCRIBED);
|
||||||
|
$this->createSubscriberEntity(); // Subscriber without list
|
||||||
|
$this->createSubscriberSegmentEntity($defaultSegment, $subscriber1);
|
||||||
|
$this->createSubscriberSegmentEntity($defaultSegment, $subscriber2);
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
$this->segmentsListRepository = $this->diContainer->get(SegmentsSimpleListRepository::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItReturnsCorrectlyFormattedOutput() {
|
||||||
|
[$list] = $this->segmentsListRepository->getListWithAssociatedSubscribersCounts();
|
||||||
|
expect($list['id'])->string();
|
||||||
|
expect($list['name'])->string();
|
||||||
|
expect($list['type'])->string();
|
||||||
|
expect($list['subscribers'])->int();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItReturnsSegmentsWithSubscribedSubscribersCount() {
|
||||||
|
$segments = $this->segmentsListRepository->getListWithSubscribedSubscribersCounts();
|
||||||
|
expect($segments)->count(5);
|
||||||
|
// Default 1
|
||||||
|
expect($segments[0]['type'])->equals(SegmentEntity::TYPE_DEFAULT);
|
||||||
|
expect($segments[0]['subscribers'])->equals(1);
|
||||||
|
// Default 2
|
||||||
|
expect($segments[1]['type'])->equals(SegmentEntity::TYPE_DEFAULT);
|
||||||
|
expect($segments[1]['subscribers'])->equals(0);
|
||||||
|
// Dynamic
|
||||||
|
expect($segments[2]['type'])->equals(SegmentEntity::TYPE_DYNAMIC);
|
||||||
|
expect($segments[2]['subscribers'])->equals(1);
|
||||||
|
// WooCommerce Users Segment
|
||||||
|
expect($segments[3]['type'])->equals(SegmentEntity::TYPE_WC_USERS);
|
||||||
|
expect($segments[3]['subscribers'])->equals(0);
|
||||||
|
// WordPress Users
|
||||||
|
expect($segments[4]['type'])->equals(SegmentEntity::TYPE_WP_USERS);
|
||||||
|
expect($segments[4]['subscribers'])->equals(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItReturnsSegmentsWithSubscribedSubscribersCountFilteredBySegmentType() {
|
||||||
|
$segments = $this->segmentsListRepository->getListWithSubscribedSubscribersCounts([SegmentEntity::TYPE_DEFAULT, SegmentEntity::TYPE_WP_USERS]);
|
||||||
|
expect($segments)->count(3);
|
||||||
|
// Default 1
|
||||||
|
expect($segments[0]['type'])->equals(SegmentEntity::TYPE_DEFAULT);
|
||||||
|
expect($segments[0]['subscribers'])->equals(1);
|
||||||
|
// Default 2
|
||||||
|
expect($segments[1]['type'])->equals(SegmentEntity::TYPE_DEFAULT);
|
||||||
|
expect($segments[1]['subscribers'])->equals(0);
|
||||||
|
// WordPress Users
|
||||||
|
expect($segments[2]['type'])->equals(SegmentEntity::TYPE_WP_USERS);
|
||||||
|
expect($segments[2]['subscribers'])->equals(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItReturnsSegmentsWithAssociatedSubscribersCount() {
|
||||||
|
$segments = $this->segmentsListRepository->getListWithAssociatedSubscribersCounts();
|
||||||
|
expect($segments)->count(5);
|
||||||
|
// Default 1
|
||||||
|
expect($segments[0]['type'])->equals(SegmentEntity::TYPE_DEFAULT);
|
||||||
|
expect($segments[0]['subscribers'])->equals(2);
|
||||||
|
// Default 2
|
||||||
|
expect($segments[1]['type'])->equals(SegmentEntity::TYPE_DEFAULT);
|
||||||
|
expect($segments[1]['subscribers'])->equals(0);
|
||||||
|
// Dynamic
|
||||||
|
expect($segments[2]['type'])->equals(SegmentEntity::TYPE_DYNAMIC);
|
||||||
|
expect($segments[2]['subscribers'])->equals(1);
|
||||||
|
// WooCommerce Users Segment
|
||||||
|
expect($segments[3]['type'])->equals(SegmentEntity::TYPE_WC_USERS);
|
||||||
|
expect($segments[3]['subscribers'])->equals(0);
|
||||||
|
// WordPress Users
|
||||||
|
expect($segments[4]['type'])->equals(SegmentEntity::TYPE_WP_USERS);
|
||||||
|
expect($segments[4]['subscribers'])->equals(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItCanAddSegmentForSubscribersWithoutList() {
|
||||||
|
$segments = $this->segmentsListRepository->getListWithAssociatedSubscribersCounts();
|
||||||
|
$segments = $this->segmentsListRepository->addVirtualSubscribersWithoutListSegment($segments);
|
||||||
|
expect($segments)->count(6);
|
||||||
|
expect($segments[5]['type'])->equals(SegmentEntity::TYPE_WITHOUT_LIST);
|
||||||
|
expect($segments[5]['id'])->equals('0');
|
||||||
|
expect($segments[5]['subscribers'])->equals(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createSubscriberEntity(): SubscriberEntity {
|
||||||
|
$subscriber = new SubscriberEntity();
|
||||||
|
$rand = rand(0, 100000);
|
||||||
|
$subscriber->setEmail("john{$rand}@mailpoet.com");
|
||||||
|
$subscriber->setFirstName('John');
|
||||||
|
$subscriber->setLastName('Doe');
|
||||||
|
$subscriber->setStatus(SubscriberEntity::STATUS_SUBSCRIBED);
|
||||||
|
$subscriber->setSource(Source::API);
|
||||||
|
$this->entityManager->persist($subscriber);
|
||||||
|
return $subscriber;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createSubscriberSegmentEntity(SegmentEntity $segment, SubscriberEntity $subscriber): SubscriberSegmentEntity {
|
||||||
|
$subscriberSegment = new SubscriberSegmentEntity($segment, $subscriber, SubscriberEntity::STATUS_SUBSCRIBED);
|
||||||
|
$this->entityManager->persist($subscriberSegment);
|
||||||
|
return $subscriberSegment;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createDynamicSegmentEntityForEditorUsers(): SegmentEntity {
|
||||||
|
$segment = new SegmentEntity('Segment' . rand(0, 10000), SegmentEntity::TYPE_DYNAMIC, 'Segment description');
|
||||||
|
$dynamicFilter = new DynamicSegmentFilterEntity($segment, [
|
||||||
|
'wordpressRole' => 'editor',
|
||||||
|
'segmentType' => DynamicSegmentFilterEntity::TYPE_USER_ROLE,
|
||||||
|
]);
|
||||||
|
$segment->getDynamicFilters()->add($dynamicFilter);
|
||||||
|
$this->entityManager->persist($segment);
|
||||||
|
$this->entityManager->persist($dynamicFilter);
|
||||||
|
return $segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function cleanup() {
|
||||||
|
$this->truncateEntity(SegmentEntity::class);
|
||||||
|
$this->truncateEntity(SubscriberEntity::class);
|
||||||
|
$this->truncateEntity(SubscriberSegmentEntity::class);
|
||||||
|
$this->truncateEntity(DynamicSegmentFilterEntity::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function _after() {
|
||||||
|
parent::_after();
|
||||||
|
$this->cleanup();
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user