init
This commit is contained in:
+33
@@ -0,0 +1,33 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\API\JSON\ResponseBuilders;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Entities\CustomFieldEntity;
|
||||
|
||||
class CustomFieldsResponseBuilder {
|
||||
/**
|
||||
* @param CustomFieldEntity[] $customFields
|
||||
* @return array
|
||||
*/
|
||||
public function buildBatch(array $customFields) {
|
||||
return array_map([$this, 'build'], $customFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CustomFieldEntity $customField
|
||||
* @return array
|
||||
*/
|
||||
public function build(CustomFieldEntity $customField) {
|
||||
return [
|
||||
'id' => $customField->getId(),
|
||||
'name' => $customField->getName(),
|
||||
'type' => $customField->getType(),
|
||||
'params' => $customField->getParams(),
|
||||
'created_at' => ($createdAt = $customField->getCreatedAt()) ? $createdAt->format('Y-m-d H:i:s') : null,
|
||||
'updated_at' => $customField->getUpdatedAt()->format('Y-m-d H:i:s'),
|
||||
];
|
||||
}
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\API\JSON\ResponseBuilders;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Entities\DynamicSegmentFilterData;
|
||||
use MailPoet\Entities\SegmentEntity;
|
||||
use MailPoet\Entities\SubscriberEntity;
|
||||
use MailPoet\Segments\SegmentDependencyValidator;
|
||||
use MailPoet\Segments\SegmentSubscribersRepository;
|
||||
use MailPoet\Subscribers\SubscribersCountsController;
|
||||
use MailPoet\WP\Functions;
|
||||
|
||||
class DynamicSegmentsResponseBuilder {
|
||||
const DATE_FORMAT = 'Y-m-d H:i:s';
|
||||
|
||||
/** @var SegmentsResponseBuilder */
|
||||
private $segmentsResponseBuilder;
|
||||
|
||||
/** @var Functions */
|
||||
private $wp;
|
||||
|
||||
/** @var SegmentSubscribersRepository */
|
||||
private $segmentSubscriberRepository;
|
||||
|
||||
/** @var SegmentDependencyValidator */
|
||||
private $segmentDependencyValidator;
|
||||
|
||||
/** @var SubscribersCountsController */
|
||||
private $subscribersCountsController;
|
||||
|
||||
public function __construct(
|
||||
Functions $wp,
|
||||
SegmentSubscribersRepository $segmentSubscriberRepository,
|
||||
SegmentsResponseBuilder $segmentsResponseBuilder,
|
||||
SegmentDependencyValidator $segmentDependencyValidator,
|
||||
SubscribersCountsController $subscribersCountsController
|
||||
) {
|
||||
$this->segmentsResponseBuilder = $segmentsResponseBuilder;
|
||||
$this->segmentSubscriberRepository = $segmentSubscriberRepository;
|
||||
$this->wp = $wp;
|
||||
$this->segmentDependencyValidator = $segmentDependencyValidator;
|
||||
$this->subscribersCountsController = $subscribersCountsController;
|
||||
}
|
||||
|
||||
public function build(SegmentEntity $segmentEntity) {
|
||||
$data = $this->segmentsResponseBuilder->build($segmentEntity);
|
||||
$data = $this->addMissingPluginProperties($segmentEntity, $data);
|
||||
$dynamicFilters = $segmentEntity->getDynamicFilters();
|
||||
$filters = [];
|
||||
foreach ($dynamicFilters as $dynamicFilter) {
|
||||
$filter = $dynamicFilter->getFilterData()->getData();
|
||||
$filter['id'] = $dynamicFilter->getId();
|
||||
$filter['segmentType'] = $dynamicFilter->getFilterData()->getFilterType(); // We need to add filterType with key segmentType due to BC
|
||||
$filter['action'] = $dynamicFilter->getFilterData()->getAction();
|
||||
if (isset($filter['country_code']) && !is_array($filter['country_code'])) {
|
||||
// Convert to multiple values filter
|
||||
$filter['country_code'] = [$filter['country_code']];
|
||||
}
|
||||
if (isset($filter['wordpressRole']) && !is_array($filter['wordpressRole'])) {
|
||||
// new filters are always array, they support multiple values, the old didn't convert old filters to new format
|
||||
$filter['wordpressRole'] = [$filter['wordpressRole']];
|
||||
}
|
||||
if (($filter['segmentType'] === DynamicSegmentFilterData::TYPE_EMAIL) && isset($filter['newsletter_id'])) {
|
||||
$filter['newsletter_id'] = intval($filter['newsletter_id']);
|
||||
}
|
||||
$filters[] = $filter;
|
||||
}
|
||||
$data['filters'] = $filters;
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function buildForListing(array $segments): array {
|
||||
$data = [];
|
||||
foreach ($segments as $segment) {
|
||||
$data[] = $this->buildListingItem($segment);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function addMissingPluginProperties(SegmentEntity $segment, array $data): array {
|
||||
$missingPlugins = $this->segmentDependencyValidator->getMissingPluginsBySegment($segment);
|
||||
if ($missingPlugins) {
|
||||
$missingPlugin = reset($missingPlugins);
|
||||
$data['is_plugin_missing'] = true;
|
||||
|
||||
$missingPluginMessage = $this->segmentDependencyValidator->getCustomErrorMessage($missingPlugin);
|
||||
|
||||
if ($missingPluginMessage) {
|
||||
$data['missing_plugin_message'] = $missingPluginMessage;
|
||||
} else {
|
||||
$data['missing_plugin_message']['message'] =
|
||||
sprintf(
|
||||
// translators: %s is the name of the missing plugin.
|
||||
__('Activate the %s plugin to see the number of subscribers and enable the editing of this segment.', 'mailpoet'),
|
||||
$missingPlugin
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$data['is_plugin_missing'] = false;
|
||||
$data['missing_plugin_message'] = null;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function buildListingItem(SegmentEntity $segment): array {
|
||||
$data = $this->segmentsResponseBuilder->build($segment);
|
||||
$data = $this->addMissingPluginProperties($segment, $data);
|
||||
$data['subscribers_url'] = $this->wp->adminUrl(
|
||||
'admin.php?page=mailpoet-subscribers#/filter[segment=' . $segment->getId() . ']'
|
||||
);
|
||||
|
||||
$segmentStatisticsCount = $this->subscribersCountsController->getSegmentStatisticsCount($segment);
|
||||
$data['count_all'] = $segmentStatisticsCount['all'];
|
||||
$data['count_subscribed'] = $segmentStatisticsCount[SubscriberEntity::STATUS_SUBSCRIBED];
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\API\JSON\ResponseBuilders;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Entities\FormEntity;
|
||||
use MailPoet\Statistics\StatisticsFormsRepository;
|
||||
|
||||
class FormsResponseBuilder {
|
||||
const DATE_FORMAT = 'Y-m-d H:i:s';
|
||||
|
||||
/** @var StatisticsFormsRepository */
|
||||
private $statisticsFormsRepository;
|
||||
|
||||
public function __construct(
|
||||
StatisticsFormsRepository $statisticsFormsRepository
|
||||
) {
|
||||
$this->statisticsFormsRepository = $statisticsFormsRepository;
|
||||
}
|
||||
|
||||
public function build(FormEntity $form) {
|
||||
return [
|
||||
'id' => (string)$form->getId(), // (string) for BC
|
||||
'name' => $form->getName(),
|
||||
'status' => $form->getStatus(),
|
||||
'body' => $form->getBody(),
|
||||
'settings' => $form->getSettings(),
|
||||
'styles' => $form->getStyles(),
|
||||
'created_at' => ($createdAt = $form->getCreatedAt()) ? $createdAt->format(self::DATE_FORMAT) : null,
|
||||
'updated_at' => $form->getUpdatedAt()->format(self::DATE_FORMAT),
|
||||
'deleted_at' => ($deletedAt = $form->getDeletedAt()) ? $deletedAt->format(self::DATE_FORMAT) : null,
|
||||
];
|
||||
}
|
||||
|
||||
public function buildForListing(array $forms) {
|
||||
$data = [];
|
||||
|
||||
foreach ($forms as $form) {
|
||||
$form = $this->build($form);
|
||||
$form['signups'] = $this->statisticsFormsRepository->getTotalSignups($form['id']);
|
||||
$form['segments'] = (
|
||||
!empty($form['settings']['segments'])
|
||||
? $form['settings']['segments']
|
||||
: []
|
||||
);
|
||||
|
||||
$data[] = $form;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\API\JSON\ResponseBuilders;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Entities\NewsletterTemplateEntity;
|
||||
|
||||
class NewsletterTemplatesResponseBuilder {
|
||||
const DATE_FORMAT = 'Y-m-d H:i:s';
|
||||
|
||||
public function build(NewsletterTemplateEntity $template): array {
|
||||
return [
|
||||
'id' => $template->getId(),
|
||||
'categories' => $template->getCategories(),
|
||||
'thumbnail' => $template->getThumbnail(),
|
||||
'name' => $template->getName(),
|
||||
'readonly' => $template->getReadonly(),
|
||||
'body' => $template->getBody(),
|
||||
'created_at' => ($createdAt = $template->getCreatedAt()) ? $createdAt->format(self::DATE_FORMAT) : null,
|
||||
'updated_at' => $template->getUpdatedAt()->format(self::DATE_FORMAT),
|
||||
'newsletter_id' => ($newsletter = $template->getNewsletter()) ? $newsletter->getId() : null,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NewsletterTemplateEntity[] $newsletterTemplates
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function buildForListing(array $newsletterTemplates): array {
|
||||
$data = [];
|
||||
foreach ($newsletterTemplates as $template) {
|
||||
$data[] = [
|
||||
'id' => $template->getId(),
|
||||
'categories' => $template->getCategories(),
|
||||
'thumbnail' => $template->getThumbnail(),
|
||||
'name' => $template->getName(),
|
||||
'readonly' => $template->getReadonly(),
|
||||
];
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
+328
@@ -0,0 +1,328 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\API\JSON\ResponseBuilders;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Entities\DynamicSegmentFilterEntity;
|
||||
use MailPoet\Entities\NewsletterEntity;
|
||||
use MailPoet\Entities\SegmentEntity;
|
||||
use MailPoet\Entities\SendingQueueEntity;
|
||||
use MailPoet\Logging\LoggerFactory;
|
||||
use MailPoet\Logging\LogRepository;
|
||||
use MailPoet\Newsletter\NewslettersRepository;
|
||||
use MailPoet\Newsletter\Sending\SendingQueuesRepository;
|
||||
use MailPoet\Newsletter\Statistics\NewsletterStatistics;
|
||||
use MailPoet\Newsletter\Statistics\NewsletterStatisticsRepository;
|
||||
use MailPoet\Newsletter\Url as NewsletterUrl;
|
||||
use MailPoetVendor\Doctrine\ORM\EntityManager;
|
||||
|
||||
class NewslettersResponseBuilder {
|
||||
const DATE_FORMAT = 'Y-m-d H:i:s';
|
||||
|
||||
const RELATION_QUEUE = 'queue';
|
||||
const RELATION_SEGMENTS = 'segments';
|
||||
const RELATION_OPTIONS = 'options';
|
||||
const RELATION_TOTAL_SENT = 'total_sent';
|
||||
const RELATION_CHILDREN_COUNT = 'children_count';
|
||||
const RELATION_SCHEDULED = 'scheduled';
|
||||
const RELATION_STATISTICS = 'statistics';
|
||||
|
||||
/** @var NewsletterStatisticsRepository */
|
||||
private $newslettersStatsRepository;
|
||||
|
||||
/** @var NewslettersRepository */
|
||||
private $newslettersRepository;
|
||||
|
||||
/** @var EntityManager */
|
||||
private $entityManager;
|
||||
|
||||
/** @var NewsletterUrl */
|
||||
private $newsletterUrl;
|
||||
|
||||
/** @var SendingQueuesRepository */
|
||||
private $sendingQueuesRepository;
|
||||
|
||||
/*** @var LogRepository */
|
||||
private $logRepository;
|
||||
|
||||
public function __construct(
|
||||
EntityManager $entityManager,
|
||||
NewslettersRepository $newslettersRepository,
|
||||
NewsletterStatisticsRepository $newslettersStatsRepository,
|
||||
NewsletterUrl $newsletterUrl,
|
||||
SendingQueuesRepository $sendingQueuesRepository,
|
||||
LogRepository $logRepository
|
||||
) {
|
||||
$this->newslettersStatsRepository = $newslettersStatsRepository;
|
||||
$this->newslettersRepository = $newslettersRepository;
|
||||
$this->entityManager = $entityManager;
|
||||
$this->newsletterUrl = $newsletterUrl;
|
||||
$this->sendingQueuesRepository = $sendingQueuesRepository;
|
||||
$this->logRepository = $logRepository;
|
||||
}
|
||||
|
||||
public function build(NewsletterEntity $newsletter, $relations = []) {
|
||||
$data = [
|
||||
'id' => (string)$newsletter->getId(), // (string) for BC
|
||||
'hash' => $newsletter->getHash(),
|
||||
'subject' => $newsletter->getSubject(),
|
||||
'type' => $newsletter->getType(),
|
||||
'sender_address' => $newsletter->getSenderAddress(),
|
||||
'sender_name' => $newsletter->getSenderName(),
|
||||
'status' => $newsletter->getStatus(),
|
||||
'reply_to_address' => $newsletter->getReplyToAddress(),
|
||||
'reply_to_name' => $newsletter->getReplyToName(),
|
||||
'preheader' => $newsletter->getPreheader(),
|
||||
'body' => $newsletter->getBody(),
|
||||
'sent_at' => ($sentAt = $newsletter->getSentAt()) ? $sentAt->format(self::DATE_FORMAT) : null,
|
||||
'created_at' => ($createdAt = $newsletter->getCreatedAt()) ? $createdAt->format(self::DATE_FORMAT) : null,
|
||||
'updated_at' => $newsletter->getUpdatedAt()->format(self::DATE_FORMAT),
|
||||
'deleted_at' => ($deletedAt = $newsletter->getDeletedAt()) ? $deletedAt->format(self::DATE_FORMAT) : null,
|
||||
'parent_id' => ($parent = $newsletter->getParent()) ? $parent->getId() : null,
|
||||
'unsubscribe_token' => $newsletter->getUnsubscribeToken(),
|
||||
'ga_campaign' => $newsletter->getGaCampaign(),
|
||||
'wp_post_id' => $newsletter->getWpPostId(),
|
||||
'campaign_name' => $newsletter->getCampaignName(),
|
||||
];
|
||||
|
||||
foreach ($relations as $relation) {
|
||||
if ($relation === self::RELATION_QUEUE) {
|
||||
$data['queue'] = ($queue = $newsletter->getLatestQueue()) ? $this->buildQueue($queue) : false; // false for BC
|
||||
}
|
||||
if ($relation === self::RELATION_SEGMENTS) {
|
||||
$data['segments'] = $this->buildSegments($newsletter);
|
||||
}
|
||||
if ($relation === self::RELATION_OPTIONS) {
|
||||
$data['options'] = $this->buildOptions($newsletter);
|
||||
}
|
||||
if ($relation === self::RELATION_TOTAL_SENT) {
|
||||
$data['total_sent'] = $this->newslettersStatsRepository->getTotalSentCount($newsletter);
|
||||
}
|
||||
if ($relation === self::RELATION_CHILDREN_COUNT) {
|
||||
$data['children_count'] = $this->newslettersStatsRepository->getChildrenCount($newsletter);
|
||||
}
|
||||
if ($relation === self::RELATION_SCHEDULED) {
|
||||
$data['total_scheduled'] = $this->sendingQueuesRepository->countAllToProcessByNewsletter(
|
||||
$newsletter
|
||||
);
|
||||
}
|
||||
|
||||
if ($relation === self::RELATION_STATISTICS) {
|
||||
$data['statistics'] = $this->newslettersStatsRepository->getStatistics($newsletter)->asArray();
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function processPersonalizationTags(?string $content): ?string {
|
||||
if (is_null($content) || strlen($content) === 0) {
|
||||
return $content;
|
||||
}
|
||||
if (strpos($content, '<!--') === false) {
|
||||
// we don't need to parse anything if there are no personalization tags
|
||||
return $content;
|
||||
}
|
||||
if (!class_exists('\MailPoet\EmailEditor\Engine\PersonalizationTags\HTML_Tag_Processor')) {
|
||||
// editor is not active, we cannot process personalization tags
|
||||
return $content;
|
||||
}
|
||||
|
||||
$content_processor = new \MailPoet\EmailEditor\Engine\PersonalizationTags\HTML_Tag_Processor($content);
|
||||
while ($content_processor->next_token()) {
|
||||
$type = $content_processor->get_token_type();
|
||||
if ($type === '#comment') {
|
||||
$token = $content_processor->get_modifiable_text();
|
||||
$content_processor->replace_token($token);
|
||||
}
|
||||
}
|
||||
$content_processor->flush_updates();
|
||||
return $content_processor->get_updated_html();
|
||||
}
|
||||
|
||||
public function buildForListing(array $newsletters): array {
|
||||
$statistics = $this->newslettersStatsRepository->getBatchStatistics($newsletters);
|
||||
$latestQueues = $this->getBatchLatestQueuesWithTasks($newsletters);
|
||||
$this->newslettersRepository->prefetchOptions($newsletters);
|
||||
$this->newslettersRepository->prefetchSegments($newsletters);
|
||||
|
||||
$data = [];
|
||||
foreach ($newsletters as $newsletter) {
|
||||
$id = $newsletter->getId();
|
||||
$data[] = $this->buildListingItem($newsletter, $statistics[$id] ?? null, $latestQueues[$id] ?? null);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NewsletterEntity $newsletter
|
||||
* @param NewsletterStatistics|null $statistics
|
||||
* @param SendingQueueEntity|null $latestQueue
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function buildListingItem(NewsletterEntity $newsletter, NewsletterStatistics $statistics = null, SendingQueueEntity $latestQueue = null): array {
|
||||
$couponBlockLogs = array_map(function ($item) {
|
||||
return "Coupon block: $item";
|
||||
}, $this->logRepository->getRawMessagesForNewsletter($newsletter, LoggerFactory::TOPIC_COUPONS));
|
||||
$data = [
|
||||
'id' => (string)$newsletter->getId(), // (string) for BC
|
||||
'hash' => $newsletter->getHash(),
|
||||
'subject' => $this->processPersonalizationTags($newsletter->getSubject()),
|
||||
'type' => $newsletter->getType(),
|
||||
'status' => $newsletter->getStatus(),
|
||||
'sent_at' => ($sentAt = $newsletter->getSentAt()) ? $sentAt->format(self::DATE_FORMAT) : null,
|
||||
'updated_at' => $newsletter->getUpdatedAt()->format(self::DATE_FORMAT),
|
||||
'deleted_at' => ($deletedAt = $newsletter->getDeletedAt()) ? $deletedAt->format(self::DATE_FORMAT) : null,
|
||||
'segments' => [],
|
||||
'queue' => false,
|
||||
'wp_post_id' => $newsletter->getWpPostId(),
|
||||
'statistics' => ($statistics && $newsletter->getType() !== NewsletterEntity::TYPE_NOTIFICATION)
|
||||
? $statistics->asArray()
|
||||
: false,
|
||||
'preview_url' => $this->newsletterUrl->getViewInBrowserUrl(
|
||||
$newsletter,
|
||||
null,
|
||||
in_array($newsletter->getStatus(), [NewsletterEntity::STATUS_SENT, NewsletterEntity::STATUS_SENDING], true)
|
||||
? $latestQueue
|
||||
: null
|
||||
),
|
||||
'logs' => $couponBlockLogs,
|
||||
'campaign_name' => $newsletter->getCampaignName(),
|
||||
];
|
||||
|
||||
if ($newsletter->getType() === NewsletterEntity::TYPE_STANDARD) {
|
||||
$data['segments'] = $this->buildSegments($newsletter);
|
||||
$data['queue'] = $latestQueue ? $this->buildQueue($latestQueue) : false; // false for BC
|
||||
$data['options'] = $this->buildOptions($newsletter);
|
||||
} elseif (in_array($newsletter->getType(), [NewsletterEntity::TYPE_WELCOME, NewsletterEntity::TYPE_AUTOMATIC], true)) {
|
||||
$data['segments'] = [];
|
||||
$data['options'] = $this->buildOptions($newsletter);
|
||||
$data['total_sent'] = $statistics ? $statistics->getTotalSentCount() : 0;
|
||||
$data['total_scheduled'] = $this->sendingQueuesRepository->countAllToProcessByNewsletter(
|
||||
$newsletter
|
||||
);
|
||||
} elseif ($newsletter->getType() === NewsletterEntity::TYPE_NOTIFICATION) {
|
||||
$data['segments'] = $this->buildSegments($newsletter);
|
||||
$data['children_count'] = $this->newslettersStatsRepository->getChildrenCount($newsletter);
|
||||
$data['options'] = $this->buildOptions($newsletter);
|
||||
} elseif ($newsletter->getType() === NewsletterEntity::TYPE_NOTIFICATION_HISTORY) {
|
||||
$data['segments'] = $this->buildSegments($newsletter);
|
||||
$data['queue'] = $latestQueue ? $this->buildQueue($latestQueue) : false; // false for BC
|
||||
} elseif ($newsletter->getType() === NewsletterEntity::TYPE_RE_ENGAGEMENT) {
|
||||
$data['segments'] = $this->buildSegments($newsletter);
|
||||
$data['options'] = $this->buildOptions($newsletter);
|
||||
$data['total_sent'] = $statistics ? $statistics->getTotalSentCount() : 0;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function buildSegments(NewsletterEntity $newsletter) {
|
||||
$output = [];
|
||||
foreach ($newsletter->getNewsletterSegments() as $newsletterSegment) {
|
||||
$segment = $newsletterSegment->getSegment();
|
||||
if (!$segment || $segment->getDeletedAt()) {
|
||||
continue;
|
||||
}
|
||||
$output[] = $this->buildSegment($segment);
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
private function buildOptions(NewsletterEntity $newsletter) {
|
||||
$output = [];
|
||||
foreach ($newsletter->getOptions() as $option) {
|
||||
$optionField = $option->getOptionField();
|
||||
if (!$optionField) {
|
||||
continue;
|
||||
}
|
||||
$output[$optionField->getName()] = $option->getValue();
|
||||
}
|
||||
|
||||
// convert 'afterTimeNumber' string to integer
|
||||
if (isset($output['afterTimeNumber']) && is_numeric($output['afterTimeNumber'])) {
|
||||
$output['afterTimeNumber'] = (int)$output['afterTimeNumber'];
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
private function buildSegment(SegmentEntity $segment) {
|
||||
$filters = $segment->getType() === SegmentEntity::TYPE_DYNAMIC ? $segment->getDynamicFilters()->toArray() : [];
|
||||
return [
|
||||
'id' => (string)$segment->getId(), // (string) for BC
|
||||
'name' => $segment->getName(),
|
||||
'type' => $segment->getType(),
|
||||
'filters' => array_map(function(DynamicSegmentFilterEntity $filter) {
|
||||
return [
|
||||
'action' => $filter->getFilterData()->getAction(),
|
||||
'type' => $filter->getFilterData()->getFilterType(),
|
||||
];
|
||||
}, $filters),
|
||||
'description' => $segment->getDescription(),
|
||||
'created_at' => ($createdAt = $segment->getCreatedAt()) ? $createdAt->format(self::DATE_FORMAT) : null,
|
||||
'updated_at' => $segment->getUpdatedAt()->format(self::DATE_FORMAT),
|
||||
'deleted_at' => ($deletedAt = $segment->getDeletedAt()) ? $deletedAt->format(self::DATE_FORMAT) : null,
|
||||
];
|
||||
}
|
||||
|
||||
private function buildQueue(SendingQueueEntity $queue) {
|
||||
$task = $queue->getTask();
|
||||
if ($task === null) {
|
||||
return null;
|
||||
}
|
||||
return [
|
||||
'id' => (string)$queue->getId(), // (string) for BC
|
||||
'type' => $task->getType(),
|
||||
'status' => $task->getStatus(),
|
||||
'priority' => (string)$task->getPriority(), // (string) for BC
|
||||
'scheduled_at' => ($scheduledAt = $task->getScheduledAt()) ? $scheduledAt->format(self::DATE_FORMAT) : null,
|
||||
'processed_at' => ($processedAt = $task->getProcessedAt()) ? $processedAt->format(self::DATE_FORMAT) : null,
|
||||
'created_at' => ($createdAt = $queue->getCreatedAt()) ? $createdAt->format(self::DATE_FORMAT) : null,
|
||||
'updated_at' => $queue->getUpdatedAt()->format(self::DATE_FORMAT),
|
||||
'deleted_at' => ($deletedAt = $queue->getDeletedAt()) ? $deletedAt->format(self::DATE_FORMAT) : null,
|
||||
'meta' => $queue->getMeta(),
|
||||
'task_id' => (string)$task->getId(), // (string) for BC
|
||||
'newsletter_id' => ($newsletter = $queue->getNewsletter()) ? (string)$newsletter->getId() : null, // (string) for BC
|
||||
'newsletter_rendered_subject' => $this->processPersonalizationTags($queue->getNewsletterRenderedSubject()),
|
||||
'count_total' => (string)$queue->getCountTotal(), // (string) for BC
|
||||
'count_processed' => (string)$queue->getCountProcessed(), // (string) for BC
|
||||
'count_to_process' => (string)$queue->getCountToProcess(), // (string) for BC
|
||||
];
|
||||
}
|
||||
|
||||
private function getBatchLatestQueuesWithTasks(array $newsletters): array {
|
||||
// this implements the same logic as NewsletterEntity::getLatestQueue() but for a batch of $newsletters
|
||||
|
||||
$subqueryQueryBuilder = $this->entityManager->createQueryBuilder();
|
||||
$subquery = $subqueryQueryBuilder
|
||||
->select('MAX(subSq.id) AS maxId')
|
||||
->from(SendingQueueEntity::class, 'subSq')
|
||||
->where('subSq.newsletter IN (:newsletters)')
|
||||
->setParameter('newsletters', $newsletters)
|
||||
->groupBy('subSq.newsletter')
|
||||
->getQuery();
|
||||
$latestQueueIds = array_column($subquery->getResult(), 'maxId');
|
||||
if (empty($latestQueueIds)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$queryBuilder = $this->entityManager->createQueryBuilder();
|
||||
$results = $queryBuilder
|
||||
->select('PARTIAL sq.{id, createdAt, updatedAt, deletedAt, meta, newsletterRenderedSubject, countTotal, countProcessed, countToProcess}')
|
||||
->addSelect('PARTIAL t.{id, type, status, priority, scheduledAt, processedAt}')
|
||||
->addSelect('IDENTITY(sq.newsletter)')
|
||||
->from(SendingQueueEntity::class, 'sq')
|
||||
->join('sq.task', 't')
|
||||
->where('sq.id IN (:sub)')
|
||||
->setParameter('sub', $latestQueueIds)
|
||||
->getQuery()
|
||||
->getResult();
|
||||
|
||||
$latestQueues = [];
|
||||
foreach ($results as $result) {
|
||||
$latestQueues[(int)$result[1]] = $result[0];
|
||||
}
|
||||
return $latestQueues;
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\API\JSON\ResponseBuilders;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Entities\ScheduledTaskSubscriberEntity;
|
||||
|
||||
class ScheduledTaskSubscriberResponseBuilder {
|
||||
public function build(ScheduledTaskSubscriberEntity $scheduledSubscriber) {
|
||||
$subscriber = $scheduledSubscriber->getSubscriber();
|
||||
$task = $scheduledSubscriber->getTask();
|
||||
return [
|
||||
'processed' => $scheduledSubscriber->getProcessed(),
|
||||
'failed' => $scheduledSubscriber->getFailed(),
|
||||
'error' => $scheduledSubscriber->getError(),
|
||||
'taskId' => $task ? $task->getId() : null,
|
||||
'email' => $subscriber ? $subscriber->getEmail() : null,
|
||||
'subscriberId' => $subscriber ? $subscriber->getId() : null,
|
||||
'firstName' => $subscriber ? $subscriber->getFirstName() : null,
|
||||
'lastName' => $subscriber ? $subscriber->getLastName() : null,
|
||||
];
|
||||
}
|
||||
|
||||
public function buildForListing(array $scheduledSubscribers) {
|
||||
$data = [];
|
||||
foreach ($scheduledSubscribers as $scheduledSubscriber) {
|
||||
$data[] = $this->build($scheduledSubscriber);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\API\JSON\ResponseBuilders;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Entities\SegmentEntity;
|
||||
use MailPoet\Subscribers\SubscribersCountsController;
|
||||
use MailPoet\WP\Functions;
|
||||
|
||||
class SegmentsResponseBuilder {
|
||||
const DATE_FORMAT = 'Y-m-d H:i:s';
|
||||
|
||||
/** @var Functions */
|
||||
private $wp;
|
||||
|
||||
/** @var SubscribersCountsController */
|
||||
private $subscribersCountsController;
|
||||
|
||||
public function __construct(
|
||||
Functions $wp,
|
||||
SubscribersCountsController $subscribersCountsController
|
||||
) {
|
||||
$this->wp = $wp;
|
||||
$this->subscribersCountsController = $subscribersCountsController;
|
||||
}
|
||||
|
||||
public function build(SegmentEntity $segment): array {
|
||||
return [
|
||||
'id' => (string)$segment->getId(), // (string) for BC
|
||||
'name' => $segment->getName(),
|
||||
'type' => $segment->getType(),
|
||||
'description' => $segment->getDescription(),
|
||||
'created_at' => ($createdAt = $segment->getCreatedAt()) ? $createdAt->format(self::DATE_FORMAT) : null,
|
||||
'updated_at' => $segment->getUpdatedAt()->format(self::DATE_FORMAT),
|
||||
'deleted_at' => ($deletedAt = $segment->getDeletedAt()) ? $deletedAt->format(self::DATE_FORMAT) : null,
|
||||
'average_engagement_score' => $segment->getAverageEngagementScore(),
|
||||
'filters_connect' => $segment->getFiltersConnectOperator(),
|
||||
'showInManageSubscriptionPage' => (int)$segment->getDisplayInManageSubscriptionPage(),
|
||||
];
|
||||
}
|
||||
|
||||
public function buildForListing(array $segments): array {
|
||||
$data = [];
|
||||
foreach ($segments as $segment) {
|
||||
$data[] = $this->buildListingItem($segment);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function buildListingItem(SegmentEntity $segment): array {
|
||||
$data = $this->build($segment);
|
||||
|
||||
$data['subscribers_count'] = $this->subscribersCountsController->getSegmentStatisticsCount($segment);
|
||||
$data['subscribers_url'] = $this->wp->adminUrl(
|
||||
'admin.php?page=mailpoet-subscribers#/filter[segment=' . $segment->getId() . ']'
|
||||
);
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\API\JSON\ResponseBuilders;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Entities\NewsletterEntity;
|
||||
use MailPoet\Entities\ScheduledTaskEntity;
|
||||
use MailPoet\Entities\SendingQueueEntity;
|
||||
|
||||
class SendingQueuesResponseBuilder {
|
||||
public function build(SendingQueueEntity $sendingQueue): array {
|
||||
if (!$sendingQueue->getTask() instanceof ScheduledTaskEntity) {
|
||||
throw new \RuntimeException('Invalid state. SendingQueue has no ScheduledTask associated.');
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => $sendingQueue->getId(),
|
||||
'type' => $sendingQueue->getTask()->getType(),
|
||||
'status' => $sendingQueue->getTask()->getStatus(),
|
||||
'priority' => $sendingQueue->getTask()->getPriority(),
|
||||
'scheduled_at' => $this->getFormattedDateOrNull($sendingQueue->getTask()->getScheduledAt()),
|
||||
'processed_at' => $this->getFormattedDateOrNull($sendingQueue->getTask()->getProcessedAt()),
|
||||
'created_at' => $this->getFormattedDateOrNull($sendingQueue->getTask()->getCreatedAt()),
|
||||
'updated_at' => $this->getFormattedDateOrNull($sendingQueue->getTask()->getUpdatedAt()),
|
||||
'deleted_at' => $this->getFormattedDateOrNull($sendingQueue->getTask()->getDeletedAt()),
|
||||
'in_progress' => $sendingQueue->getTask()->getInProgress(),
|
||||
'reschedule_count' => $sendingQueue->getTask()->getRescheduleCount(),
|
||||
'meta' => $sendingQueue->getMeta(),
|
||||
'task_id' => $sendingQueue->getTask()->getId(),
|
||||
'newsletter_id' => ($sendingQueue->getNewsletter() instanceof NewsletterEntity) ? $sendingQueue->getNewsletter()->getId() : null,
|
||||
'newsletter_rendered_body' => $sendingQueue->getNewsletterRenderedBody(),
|
||||
'newsletter_rendered_subject' => $sendingQueue->getNewsletterRenderedSubject(),
|
||||
'count_total' => $sendingQueue->getCountTotal(),
|
||||
'count_processed' => $sendingQueue->getCountProcessed(),
|
||||
'count_to_process' => $sendingQueue->getCountToProcess(),
|
||||
];
|
||||
}
|
||||
|
||||
private function getFormattedDateOrNull(?\DateTimeInterface $date): ?string {
|
||||
return $date ? $date->format('Y-m-d H:i:s') : null;
|
||||
}
|
||||
}
|
||||
+199
@@ -0,0 +1,199 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\API\JSON\ResponseBuilders;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\CustomFields\CustomFieldsRepository;
|
||||
use MailPoet\Entities\NewsletterEntity;
|
||||
use MailPoet\Entities\SegmentEntity;
|
||||
use MailPoet\Entities\SubscriberCustomFieldEntity;
|
||||
use MailPoet\Entities\SubscriberEntity;
|
||||
use MailPoet\Statistics\StatisticsUnsubscribesRepository;
|
||||
use MailPoet\Subscribers\SubscriberCustomFieldRepository;
|
||||
use MailPoetVendor\Doctrine\ORM\EntityManager;
|
||||
|
||||
class SubscribersResponseBuilder {
|
||||
const DATE_FORMAT = 'Y-m-d H:i:s';
|
||||
|
||||
/** @var StatisticsUnsubscribesRepository */
|
||||
private $statisticsUnsubscribesRepository;
|
||||
|
||||
/** @var CustomFieldsRepository */
|
||||
private $customFieldsRepository;
|
||||
|
||||
/** @var SubscriberCustomFieldRepository */
|
||||
private $subscriberCustomFieldRepository;
|
||||
|
||||
/** @var EntityManager */
|
||||
private $entityManager;
|
||||
|
||||
public function __construct(
|
||||
EntityManager $entityManager,
|
||||
CustomFieldsRepository $customFieldsRepository,
|
||||
SubscriberCustomFieldRepository $subscriberCustomFieldRepository,
|
||||
StatisticsUnsubscribesRepository $statisticsUnsubscribesRepository
|
||||
) {
|
||||
$this->statisticsUnsubscribesRepository = $statisticsUnsubscribesRepository;
|
||||
$this->customFieldsRepository = $customFieldsRepository;
|
||||
$this->subscriberCustomFieldRepository = $subscriberCustomFieldRepository;
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function buildForListing(array $subscribers): array {
|
||||
$this->prefetchRelations($subscribers);
|
||||
$data = [];
|
||||
foreach ($subscribers as $subscriber) {
|
||||
$data[] = $this->buildListingItem($subscriber);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function buildListingItem(SubscriberEntity $subscriber): array {
|
||||
return [
|
||||
'id' => (string)$subscriber->getId(), // (string) for BC
|
||||
'email' => $subscriber->getEmail(),
|
||||
'first_name' => $subscriber->getFirstName(),
|
||||
'last_name' => $subscriber->getLastName(),
|
||||
'subscriptions' => $this->buildSubscriptions($subscriber),
|
||||
'status' => $subscriber->getStatus(),
|
||||
'count_confirmations' => $subscriber->getConfirmationsCount(),
|
||||
'wp_user_id' => $subscriber->getWpUserId(),
|
||||
'is_woocommerce_user' => $subscriber->getIsWoocommerceUser(),
|
||||
'created_at' => ($createdAt = $subscriber->getCreatedAt()) ? $createdAt->format(self::DATE_FORMAT) : null,
|
||||
'last_subscribed_at' => ($lastSubscribedAt = $subscriber->getLastSubscribedAt()) ? $lastSubscribedAt->format(self::DATE_FORMAT) : null,
|
||||
'engagement_score' => $subscriber->getEngagementScore(),
|
||||
'tags' => $this->buildTags($subscriber),
|
||||
];
|
||||
}
|
||||
|
||||
public function build(SubscriberEntity $subscriberEntity): array {
|
||||
$data = [
|
||||
'id' => (string)$subscriberEntity->getId(),
|
||||
'wp_user_id' => $subscriberEntity->getWpUserId(),
|
||||
'is_woocommerce_user' => $subscriberEntity->getIsWoocommerceUser(),
|
||||
'subscriptions' => $this->buildSubscriptions($subscriberEntity),
|
||||
'unsubscribes' => $this->buildUnsubscribes($subscriberEntity),
|
||||
'status' => $subscriberEntity->getStatus(),
|
||||
'last_name' => $subscriberEntity->getLastName(),
|
||||
'first_name' => $subscriberEntity->getFirstName(),
|
||||
'email' => $subscriberEntity->getEmail(),
|
||||
'created_at' => ($createdAt = $subscriberEntity->getCreatedAt()) ? $createdAt->format(self::DATE_FORMAT) : null,
|
||||
'updated_at' => ($updatedAt = $subscriberEntity->getUpdatedAt()) ? $updatedAt->format(self::DATE_FORMAT) : null,
|
||||
'deleted_at' => ($deletedAt = $subscriberEntity->getDeletedAt()) ? $deletedAt->format(self::DATE_FORMAT) : null,
|
||||
'subscribed_ip' => $subscriberEntity->getSubscribedIp(),
|
||||
'confirmed_ip' => $subscriberEntity->getConfirmedIp(),
|
||||
'confirmed_at' => ($confirmedAt = $subscriberEntity->getConfirmedAt()) ? $confirmedAt->format(self::DATE_FORMAT) : null,
|
||||
'last_subscribed_at' => ($lastSubscribedAt = $subscriberEntity->getLastSubscribedAt()) ? $lastSubscribedAt->format(self::DATE_FORMAT) : null,
|
||||
'unconfirmed_data' => $subscriberEntity->getUnconfirmedData(),
|
||||
'source' => $subscriberEntity->getSource(),
|
||||
'count_confirmations' => $subscriberEntity->getConfirmationsCount(),
|
||||
'unsubscribe_token' => $subscriberEntity->getUnsubscribeToken(),
|
||||
'link_token' => $subscriberEntity->getLinkToken(),
|
||||
'tags' => $this->buildTags($subscriberEntity),
|
||||
];
|
||||
|
||||
return $this->buildCustomFields($subscriberEntity, $data);
|
||||
}
|
||||
|
||||
private function buildSubscriptions(SubscriberEntity $subscriberEntity): array {
|
||||
$result = [];
|
||||
foreach ($subscriberEntity->getSubscriberSegments() as $subscriberSegment) {
|
||||
$segment = $subscriberSegment->getSegment();
|
||||
if ($segment instanceof SegmentEntity) {
|
||||
$result[] = [
|
||||
'id' => $subscriberSegment->getId(),
|
||||
'subscriber_id' => (string)$subscriberEntity->getId(),
|
||||
'created_at' => ($createdAt = $subscriberSegment->getCreatedAt()) ? $createdAt->format(self::DATE_FORMAT) : null,
|
||||
'segment_id' => (string)$segment->getId(),
|
||||
'status' => $subscriberSegment->getStatus(),
|
||||
'updated_at' => $subscriberSegment->getUpdatedAt()->format(self::DATE_FORMAT),
|
||||
];
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function buildUnsubscribes(SubscriberEntity $subscriberEntity): array {
|
||||
$unsubscribes = $this->statisticsUnsubscribesRepository->findBy([
|
||||
'subscriber' => $subscriberEntity,
|
||||
], [
|
||||
'createdAt' => 'desc',
|
||||
]);
|
||||
$result = [];
|
||||
foreach ($unsubscribes as $unsubscribe) {
|
||||
$mapped = [
|
||||
'source' => $unsubscribe->getSource(),
|
||||
'meta' => $unsubscribe->getMeta(),
|
||||
'createdAt' => $unsubscribe->getCreatedAt(),
|
||||
];
|
||||
$newsletter = $unsubscribe->getNewsletter();
|
||||
if ($newsletter instanceof NewsletterEntity) {
|
||||
$mapped['newsletterId'] = $newsletter->getId();
|
||||
$mapped['newsletterSubject'] = $newsletter->getSubject();
|
||||
}
|
||||
$result[] = $mapped;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function buildCustomFields(SubscriberEntity $subscriberEntity, array $data): array {
|
||||
$customFields = $this->customFieldsRepository->findAll();
|
||||
|
||||
foreach ($customFields as $customField) {
|
||||
$subscriberCustomField = $this->subscriberCustomFieldRepository->findOneBy(
|
||||
['subscriber' => $subscriberEntity, 'customField' => $customField]
|
||||
);
|
||||
if ($subscriberCustomField instanceof SubscriberCustomFieldEntity) {
|
||||
$data['cf_' . $customField->getId()] = $subscriberCustomField->getValue();
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function buildTags(SubscriberEntity $subscriber): array {
|
||||
$result = [];
|
||||
foreach ($subscriber->getSubscriberTags() as $subscriberTag) {
|
||||
$tag = $subscriberTag->getTag();
|
||||
if (!$tag) {
|
||||
continue;
|
||||
}
|
||||
$result[] = [
|
||||
'id' => $subscriberTag->getId(),
|
||||
'subscriber_id' => (string)$subscriber->getId(),
|
||||
'tag_id' => (string)$tag->getId(),
|
||||
'created_at' => ($createdAt = $subscriberTag->getCreatedAt()) ? $createdAt->format(self::DATE_FORMAT) : null,
|
||||
'updated_at' => $subscriberTag->getUpdatedAt()->format(self::DATE_FORMAT),
|
||||
'name' => $tag->getName(),
|
||||
];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SubscriberEntity[] $subscribers
|
||||
*/
|
||||
private function prefetchRelations(array $subscribers): void {
|
||||
// Prefetch subscriptions
|
||||
$this->entityManager->createQueryBuilder()
|
||||
->select('PARTIAL s.{id}, ssg, sg')
|
||||
->from(SubscriberEntity::class, 's')
|
||||
->leftJoin('s.subscriberSegments', 'ssg')
|
||||
->leftJoin('ssg.segment', 'sg')
|
||||
->where('s.id IN (:subscribers)')
|
||||
->setParameter('subscribers', $subscribers)
|
||||
->getQuery()
|
||||
->getResult();
|
||||
// Prefetch tags
|
||||
$this->entityManager->createQueryBuilder()
|
||||
->select('PARTIAL s.{id}, st, t')
|
||||
->from(SubscriberEntity::class, 's')
|
||||
->leftJoin('s.subscriberTags', 'st')
|
||||
->leftJoin('st.tag', 't')
|
||||
->where('s.id IN (:subscribers)')
|
||||
->setParameter('subscribers', $subscribers)
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<?php
|
||||
Reference in New Issue
Block a user