Use doctrine for exporting subscribers
[MAILPOET-3376]
This commit is contained in:
@ -9,7 +9,9 @@ use MailPoet\CustomFields\CustomFieldsRepository;
|
|||||||
use MailPoet\Models\ScheduledTask;
|
use MailPoet\Models\ScheduledTask;
|
||||||
use MailPoet\Models\Segment;
|
use MailPoet\Models\Segment;
|
||||||
use MailPoet\Newsletter\Options\NewsletterOptionsRepository;
|
use MailPoet\Newsletter\Options\NewsletterOptionsRepository;
|
||||||
|
use MailPoet\Segments\SegmentsRepository;
|
||||||
use MailPoet\Segments\WP;
|
use MailPoet\Segments\WP;
|
||||||
|
use MailPoet\Subscribers\ImportExport\Export\Export;
|
||||||
use MailPoet\Subscribers\ImportExport\Import\Import;
|
use MailPoet\Subscribers\ImportExport\Import\Import;
|
||||||
use MailPoet\Subscribers\ImportExport\Import\MailChimp;
|
use MailPoet\Subscribers\ImportExport\Import\MailChimp;
|
||||||
use MailPoet\Subscribers\ImportExport\ImportExportRepository;
|
use MailPoet\Subscribers\ImportExport\ImportExportRepository;
|
||||||
@ -30,6 +32,9 @@ class ImportExport extends APIEndpoint {
|
|||||||
/** @var NewsletterOptionsRepository */
|
/** @var NewsletterOptionsRepository */
|
||||||
private $newsletterOptionsRepository;
|
private $newsletterOptionsRepository;
|
||||||
|
|
||||||
|
/** @var SegmentsRepository */
|
||||||
|
private $segmentsRepository;
|
||||||
|
|
||||||
/** @var SubscribersRepository */
|
/** @var SubscribersRepository */
|
||||||
private $subscriberRepository;
|
private $subscriberRepository;
|
||||||
|
|
||||||
@ -42,12 +47,14 @@ class ImportExport extends APIEndpoint {
|
|||||||
CustomFieldsRepository $customFieldsRepository,
|
CustomFieldsRepository $customFieldsRepository,
|
||||||
ImportExportRepository $importExportRepository,
|
ImportExportRepository $importExportRepository,
|
||||||
NewsletterOptionsRepository $newsletterOptionsRepository,
|
NewsletterOptionsRepository $newsletterOptionsRepository,
|
||||||
|
SegmentsRepository $segmentsRepository,
|
||||||
SubscribersRepository $subscribersRepository
|
SubscribersRepository $subscribersRepository
|
||||||
) {
|
) {
|
||||||
$this->wpSegment = $wpSegment;
|
$this->wpSegment = $wpSegment;
|
||||||
$this->customFieldsRepository = $customFieldsRepository;
|
$this->customFieldsRepository = $customFieldsRepository;
|
||||||
$this->importExportRepository = $importExportRepository;
|
$this->importExportRepository = $importExportRepository;
|
||||||
$this->newsletterOptionsRepository = $newsletterOptionsRepository;
|
$this->newsletterOptionsRepository = $newsletterOptionsRepository;
|
||||||
|
$this->segmentsRepository = $segmentsRepository;
|
||||||
$this->subscriberRepository = $subscribersRepository;
|
$this->subscriberRepository = $subscribersRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +116,10 @@ class ImportExport extends APIEndpoint {
|
|||||||
|
|
||||||
public function processExport($data) {
|
public function processExport($data) {
|
||||||
try {
|
try {
|
||||||
$export = new \MailPoet\Subscribers\ImportExport\Export\Export(
|
$export = new Export(
|
||||||
|
$this->customFieldsRepository,
|
||||||
|
$this->importExportRepository,
|
||||||
|
$this->segmentsRepository,
|
||||||
json_decode($data, true)
|
json_decode($data, true)
|
||||||
);
|
);
|
||||||
$process = $export->process();
|
$process = $export->process();
|
||||||
|
@ -3,8 +3,11 @@
|
|||||||
namespace MailPoet\Subscribers\ImportExport\Export;
|
namespace MailPoet\Subscribers\ImportExport\Export;
|
||||||
|
|
||||||
use MailPoet\Config\Env;
|
use MailPoet\Config\Env;
|
||||||
use MailPoet\Models\CustomField;
|
use MailPoet\CustomFields\CustomFieldsRepository;
|
||||||
|
use MailPoet\Entities\SegmentEntity;
|
||||||
|
use MailPoet\Segments\SegmentsRepository;
|
||||||
use MailPoet\Subscribers\ImportExport\ImportExportFactory;
|
use MailPoet\Subscribers\ImportExport\ImportExportFactory;
|
||||||
|
use MailPoet\Subscribers\ImportExport\ImportExportRepository;
|
||||||
use MailPoet\Util\Security;
|
use MailPoet\Util\Security;
|
||||||
use MailPoet\WP\Functions as WPFunctions;
|
use MailPoet\WP\Functions as WPFunctions;
|
||||||
use MailPoetVendor\XLSXWriter;
|
use MailPoetVendor\XLSXWriter;
|
||||||
@ -19,24 +22,41 @@ class Export {
|
|||||||
public $exportPath;
|
public $exportPath;
|
||||||
public $exportFile;
|
public $exportFile;
|
||||||
public $exportFileURL;
|
public $exportFileURL;
|
||||||
public $defaultSubscribersGetter;
|
|
||||||
public $dynamicSubscribersGetter;
|
|
||||||
|
|
||||||
public function __construct($data) {
|
/** @var int */
|
||||||
|
private $subscribersOffset;
|
||||||
|
|
||||||
|
/** @var array<SegmentEntity|null> */
|
||||||
|
private $segments;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
private $segmentIndex;
|
||||||
|
|
||||||
|
/** @var CustomFieldsRepository */
|
||||||
|
private $customFieldsRepository;
|
||||||
|
|
||||||
|
/** @var ImportExportRepository */
|
||||||
|
private $importExportRepository;
|
||||||
|
|
||||||
|
/** @var SegmentsRepository */
|
||||||
|
private $segmentsRepository;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
CustomFieldsRepository $customFieldsRepository,
|
||||||
|
ImportExportRepository $importExportRepository,
|
||||||
|
SegmentsRepository $segmentsRepository,
|
||||||
|
array $data
|
||||||
|
) {
|
||||||
|
$this->customFieldsRepository = $customFieldsRepository;
|
||||||
|
$this->importExportRepository = $importExportRepository;
|
||||||
|
$this->segmentsRepository = $segmentsRepository;
|
||||||
if (strpos((string)@ini_get('disable_functions'), 'set_time_limit') === false) {
|
if (strpos((string)@ini_get('disable_functions'), 'set_time_limit') === false) {
|
||||||
set_time_limit(0);
|
set_time_limit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->defaultSubscribersGetter = new DefaultSubscribersGetter(
|
$this->subscribersOffset = 0;
|
||||||
$data['segments'],
|
$this->segmentIndex = 0;
|
||||||
self::SUBSCRIBER_BATCH_SIZE
|
$this->segments = $this->getSegments($data['segments']);
|
||||||
);
|
|
||||||
|
|
||||||
$this->dynamicSubscribersGetter = new DynamicSubscribersGetter(
|
|
||||||
$data['segments'],
|
|
||||||
self::SUBSCRIBER_BATCH_SIZE
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->exportFormatOption = $data['export_format_option'];
|
$this->exportFormatOption = $data['export_format_option'];
|
||||||
$this->subscriberFields = $data['subscriber_fields'];
|
$this->subscriberFields = $data['subscriber_fields'];
|
||||||
$this->subscriberCustomFields = $this->getSubscriberCustomFields();
|
$this->subscriberCustomFields = $this->getSubscriberCustomFields();
|
||||||
@ -57,9 +77,9 @@ class Export {
|
|||||||
return Env::$tempPath;
|
return Env::$tempPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function process() {
|
public function process(): array {
|
||||||
$processedSubscribers = 0;
|
$processedSubscribers = 0;
|
||||||
$this->defaultSubscribersGetter->reset();
|
$this->resetCounters();
|
||||||
try {
|
try {
|
||||||
if (is_writable($this->exportPath) === false) {
|
if (is_writable($this->exportPath) === false) {
|
||||||
throw new \Exception(__('The export file could not be saved on the server.', 'mailpoet'));
|
throw new \Exception(__('The export file could not be saved on the server.', 'mailpoet'));
|
||||||
@ -83,7 +103,7 @@ class Export {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generateCSV() {
|
public function generateCSV(): int {
|
||||||
$processedSubscribers = 0;
|
$processedSubscribers = 0;
|
||||||
$formattedSubscriberFields = $this->formattedSubscriberFields;
|
$formattedSubscriberFields = $this->formattedSubscriberFields;
|
||||||
$cSVFile = fopen($this->exportFile, 'w');
|
$cSVFile = fopen($this->exportFile, 'w');
|
||||||
@ -108,29 +128,26 @@ class Export {
|
|||||||
) . PHP_EOL
|
) . PHP_EOL
|
||||||
);
|
);
|
||||||
|
|
||||||
$subscribers = $this->getSubscribers();
|
while (($subscribers = $this->getSubscribers()) !== null) {
|
||||||
while ($subscribers !== false) {
|
|
||||||
$processedSubscribers += count($subscribers);
|
$processedSubscribers += count($subscribers);
|
||||||
foreach ($subscribers as $subscriber) {
|
foreach ($subscribers as $subscriber) {
|
||||||
$row = $this->formatSubscriberData($subscriber);
|
$row = $this->formatSubscriberData($subscriber);
|
||||||
$row[] = ucwords($subscriber['segment_name']);
|
$row[] = ucwords($subscriber['segment_name']);
|
||||||
fwrite($cSVFile, implode(',', array_map($formatCSV, $row)) . "\n");
|
fwrite($cSVFile, implode(',', array_map($formatCSV, $row)) . "\n");
|
||||||
}
|
}
|
||||||
$subscribers = $this->getSubscribers();
|
|
||||||
}
|
}
|
||||||
fclose($cSVFile);
|
|
||||||
return $processedSubscribers;
|
return $processedSubscribers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generateXLSX() {
|
public function generateXLSX(): int {
|
||||||
$processedSubscribers = 0;
|
$processedSubscribers = 0;
|
||||||
$xLSXWriter = new XLSXWriter();
|
$xLSXWriter = new XLSXWriter();
|
||||||
$xLSXWriter->setAuthor('MailPoet (www.mailpoet.com)');
|
$xLSXWriter->setAuthor('MailPoet (www.mailpoet.com)');
|
||||||
$lastSegment = false;
|
$lastSegment = false;
|
||||||
$processedSegments = [];
|
$processedSegments = [];
|
||||||
|
|
||||||
$subscribers = $this->getSubscribers();
|
while (($subscribers = $this->getSubscribers()) !== null) {
|
||||||
while ($subscribers !== false) {
|
|
||||||
$processedSubscribers += count($subscribers);
|
$processedSubscribers += count($subscribers);
|
||||||
foreach ($subscribers as $i => $subscriber) {
|
foreach ($subscribers as $i => $subscriber) {
|
||||||
$currentSegment = ucwords($subscriber['segment_name']);
|
$currentSegment = ucwords($subscriber['segment_name']);
|
||||||
@ -167,7 +184,6 @@ class Export {
|
|||||||
$this->formatSubscriberData($subscriber)
|
$this->formatSubscriberData($subscriber)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$subscribers = $this->getSubscribers();
|
|
||||||
}
|
}
|
||||||
$xLSXWriter->writeToFile($this->exportFile);
|
$xLSXWriter->writeToFile($this->exportFile);
|
||||||
return $processedSubscribers;
|
return $processedSubscribers;
|
||||||
@ -177,15 +193,28 @@ class Export {
|
|||||||
return $xLSXWriter->writeSheetRow(ucwords($segment), $data);
|
return $xLSXWriter->writeSheetRow(ucwords($segment), $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSubscribers() {
|
public function getSubscribers(): ?array {
|
||||||
$subscribers = $this->defaultSubscribersGetter->get();
|
$segment = array_key_exists($this->segmentIndex, $this->segments) ? $this->segments[$this->segmentIndex] : false;
|
||||||
if ($subscribers === false) {
|
if ($segment === false) {
|
||||||
$subscribers = $this->dynamicSubscribersGetter->get();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$subscribers = $this->importExportRepository->getSubscribersBatchBySegment(
|
||||||
|
$segment,
|
||||||
|
self::SUBSCRIBER_BATCH_SIZE,
|
||||||
|
$this->subscribersOffset
|
||||||
|
);
|
||||||
|
$this->subscribersOffset += count($subscribers);
|
||||||
|
|
||||||
|
if (count($subscribers) < self::SUBSCRIBER_BATCH_SIZE) {
|
||||||
|
$this->segmentIndex++;
|
||||||
|
$this->subscribersOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return $subscribers;
|
return $subscribers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getExportFileURL($file) {
|
public function getExportFileURL($file): string {
|
||||||
return sprintf(
|
return sprintf(
|
||||||
'%s/%s',
|
'%s/%s',
|
||||||
Env::$tempUrl,
|
Env::$tempUrl,
|
||||||
@ -193,7 +222,7 @@ class Export {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getExportFile($format) {
|
public function getExportFile($format): string {
|
||||||
return sprintf(
|
return sprintf(
|
||||||
$this->exportPath . '/' . self::getFilePrefix() . '%s.%s',
|
$this->exportPath . '/' . self::getFilePrefix() . '%s.%s',
|
||||||
Security::generateRandomString(15),
|
Security::generateRandomString(15),
|
||||||
@ -201,15 +230,46 @@ class Export {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSubscriberCustomFields() {
|
/**
|
||||||
return array_column(
|
* @return array<int, string>
|
||||||
CustomField::findArray(),
|
*/
|
||||||
'name',
|
public function getSubscriberCustomFields(): array {
|
||||||
'id'
|
$result = [];
|
||||||
);
|
foreach ($this->customFieldsRepository->findAll() as $customField) {
|
||||||
|
$result[(int)$customField->getId()] = $customField->getName();
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function formatSubscriberFields($subscriberFields, $subscriberCustomFields) {
|
/**
|
||||||
|
* @param array $segmentIds
|
||||||
|
* @return array<SegmentEntity|null>
|
||||||
|
*/
|
||||||
|
private function getSegments(array $segmentIds): array {
|
||||||
|
$segments = $this->segmentsRepository->findBy(['id' => $segmentIds]);
|
||||||
|
$result = [];
|
||||||
|
foreach ($segmentIds as $segmentId) {
|
||||||
|
$segmentId = (int)$segmentId;
|
||||||
|
$segment = current(array_filter($segments, function (SegmentEntity $segment) use ($segmentId): bool {
|
||||||
|
return $segment->getId() === $segmentId;
|
||||||
|
})) ?: null;
|
||||||
|
|
||||||
|
if (!$segment && $segmentId !== 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result[] = $segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function resetCounters(): void {
|
||||||
|
$this->segmentIndex = 0;
|
||||||
|
$this->subscribersOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function formatSubscriberFields($subscriberFields, $subscriberCustomFields): array {
|
||||||
$exportFactory = new ImportExportFactory('export');
|
$exportFactory = new ImportExportFactory('export');
|
||||||
$translatedFields = $exportFactory->getSubscriberFields();
|
$translatedFields = $exportFactory->getSubscriberFields();
|
||||||
return array_map(function($field) use (
|
return array_map(function($field) use (
|
||||||
@ -223,7 +283,7 @@ class Export {
|
|||||||
}, $subscriberFields);
|
}, $subscriberFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function formatSubscriberData($subscriber) {
|
public function formatSubscriberData($subscriber): array {
|
||||||
return array_map(function($field) use ($subscriber) {
|
return array_map(function($field) use ($subscriber) {
|
||||||
return $subscriber[$field];
|
return $subscriber[$field];
|
||||||
}, $this->subscriberFields);
|
}, $this->subscriberFields);
|
||||||
|
Reference in New Issue
Block a user