From 5c57dd2006b061753d93a563dd8b01bf40811f1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lys=C3=BD?= Date: Mon, 5 Sep 2022 16:41:29 +0200 Subject: [PATCH] Add saving tags for imported subscribers [MAILPOET-4558] --- mailpoet/lib/API/JSON/v1/ImportExport.php | 9 +++- .../ImportExport/Import/Import.php | 53 +++++++++++++++++++ .../tasks/phpstan/phpstan-7-baseline.neon | 2 +- .../tasks/phpstan/phpstan-8-baseline.neon | 2 +- .../tasks/phpstan/phpstan-8.1-baseline.neon | 2 +- .../ImportExport/Import/ImportTest.php | 6 +++ 6 files changed, 70 insertions(+), 4 deletions(-) diff --git a/mailpoet/lib/API/JSON/v1/ImportExport.php b/mailpoet/lib/API/JSON/v1/ImportExport.php index 606fca0e0a..8f38330c9a 100644 --- a/mailpoet/lib/API/JSON/v1/ImportExport.php +++ b/mailpoet/lib/API/JSON/v1/ImportExport.php @@ -20,6 +20,7 @@ use MailPoet\Subscribers\ImportExport\Import\Import; use MailPoet\Subscribers\ImportExport\Import\MailChimp; use MailPoet\Subscribers\ImportExport\ImportExportRepository; use MailPoet\Subscribers\SubscribersRepository; +use MailPoet\Tags\TagRepository; class ImportExport extends APIEndpoint { @@ -47,6 +48,9 @@ class ImportExport extends APIEndpoint { /** @var SegmentsResponseBuilder */ private $segmentsResponseBuilder; + /** @var TagRepository */ + private $tagRepository; + /** @var CronWorkerScheduler */ private $cronWorkerScheduler; @@ -63,7 +67,8 @@ class ImportExport extends APIEndpoint { SegmentSaveController $segmentSavecontroller, SegmentsResponseBuilder $segmentsResponseBuilder, CronWorkerScheduler $cronWorkerScheduler, - SubscribersRepository $subscribersRepository + SubscribersRepository $subscribersRepository, + TagRepository $tagRepository ) { $this->wpSegment = $wpSegment; $this->customFieldsRepository = $customFieldsRepository; @@ -74,6 +79,7 @@ class ImportExport extends APIEndpoint { $this->segmentSavecontroller = $segmentSavecontroller; $this->cronWorkerScheduler = $cronWorkerScheduler; $this->segmentsResponseBuilder = $segmentsResponseBuilder; + $this->tagRepository = $tagRepository; } public function getMailChimpLists($data) { @@ -124,6 +130,7 @@ class ImportExport extends APIEndpoint { $this->importExportRepository, $this->newsletterOptionsRepository, $this->subscriberRepository, + $this->tagRepository, json_decode($data, true) ); $process = $import->process(); diff --git a/mailpoet/lib/Subscribers/ImportExport/Import/Import.php b/mailpoet/lib/Subscribers/ImportExport/Import/Import.php index 7d82e6bbb8..149257c932 100644 --- a/mailpoet/lib/Subscribers/ImportExport/Import/Import.php +++ b/mailpoet/lib/Subscribers/ImportExport/Import/Import.php @@ -7,6 +7,7 @@ use MailPoet\Entities\CustomFieldEntity; use MailPoet\Entities\SubscriberCustomFieldEntity; use MailPoet\Entities\SubscriberEntity; use MailPoet\Entities\SubscriberSegmentEntity; +use MailPoet\Entities\SubscriberTagEntity; use MailPoet\Models\ModelValidator; use MailPoet\Newsletter\Options\NewsletterOptionsRepository; use MailPoet\Segments\WP; @@ -14,6 +15,7 @@ use MailPoet\Subscribers\ImportExport\ImportExportFactory; use MailPoet\Subscribers\ImportExport\ImportExportRepository; use MailPoet\Subscribers\Source; use MailPoet\Subscribers\SubscribersRepository; +use MailPoet\Tags\TagRepository; use MailPoet\Util\DateConverter; use MailPoet\Util\Helpers; use MailPoet\Util\Security; @@ -25,6 +27,8 @@ class Import { public $subscribersData; /** @var array */ public $segmentsIds; + /** @var string[] */ + public $tags; /** @var string */ public $newSubscribersStatus; /** @var string */ @@ -64,12 +68,16 @@ class Import { /** @var SubscribersRepository */ private $subscriberRepository; + /** @var TagRepository */ + private $tagRepository; + public function __construct( WP $wpSegment, CustomFieldsRepository $customFieldsRepository, ImportExportRepository $importExportRepository, NewsletterOptionsRepository $newsletterOptionsRepository, SubscribersRepository $subscriberRepository, + TagRepository $tagRepository, array $data ) { $this->wpSegment = $wpSegment; @@ -77,12 +85,14 @@ class Import { $this->importExportRepository = $importExportRepository; $this->newsletterOptionsRepository = $newsletterOptionsRepository; $this->subscriberRepository = $subscriberRepository; + $this->tagRepository = $tagRepository; $this->validateImportData($data); $this->subscribersData = $this->transformSubscribersData( $data['subscribers'], $data['columns'] ); $this->segmentsIds = $data['segments']; + $this->tags = $data['tags']; $this->newSubscribersStatus = $data['newSubscribersStatus']; $this->existingSubscribersStatus = $data['existingSubscribersStatus']; $this->updateSubscribers = $data['updateSubscribers']; @@ -112,6 +122,7 @@ class Import { 'newSubscribersStatus', 'existingSubscribersStatus', 'updateSubscribers', + 'tags', ]; // 1. data should contain all required fields // 2. column names should only contain alphanumeric & underscore characters @@ -527,6 +538,10 @@ class Import { $createdOrUpdatedSubscribersIds, $this->segmentsIds ); + $this->addTagsToSubscribers( + $createdOrUpdatedSubscribersIds, + $this->tags + ); return $createdOrUpdatedSubscribers; } @@ -619,4 +634,42 @@ class Import { ); } } + + /** + * @param int[] $subscribersIds + * @param string[] $tagNames + */ + public function addTagsToSubscribers(array $subscribersIds, array $tagNames): void { + $tagIds = []; + foreach ($tagNames as $tagName) { + $tag = $this->tagRepository->findOneBy(['name' => $tagName]); + if (!$tag) { + $tag = $this->tagRepository->createOrUpdate(['name' => $tagName]); + } + $tagIds[] = $tag->getId(); + } + + $columns = [ + 'subscriber_id', + 'tag_id', + 'created_at', + ]; + foreach (array_chunk($subscribersIds, self::DB_QUERY_CHUNK_SIZE) as $subscriberIdsChunk) { + $data = []; + foreach ($tagIds as $tagId) { + $data = array_merge($data, array_map(function ($subscriberId) use ($tagId): array { + return [ + $subscriberId, + $tagId, + $this->createdAt, + ]; + }, $subscriberIdsChunk)); + } + $this->importExportRepository->insertMultiple( + SubscriberTagEntity::class, + $columns, + $data + ); + } + } } diff --git a/mailpoet/tasks/phpstan/phpstan-7-baseline.neon b/mailpoet/tasks/phpstan/phpstan-7-baseline.neon index ca727042ef..9328ea5583 100644 --- a/mailpoet/tasks/phpstan/phpstan-7-baseline.neon +++ b/mailpoet/tasks/phpstan/phpstan-7-baseline.neon @@ -56,7 +56,7 @@ parameters: path: ../../lib/API/JSON/v1/ImportExport.php - - message: "#^Parameter \\#6 \\$data of class MailPoet\\\\Subscribers\\\\ImportExport\\\\Import\\\\Import constructor expects array, mixed given\\.$#" + message: "#^Parameter \\#7 \\$data of class MailPoet\\\\Subscribers\\\\ImportExport\\\\Import\\\\Import constructor expects array, mixed given\\.$#" count: 1 path: ../../lib/API/JSON/v1/ImportExport.php diff --git a/mailpoet/tasks/phpstan/phpstan-8-baseline.neon b/mailpoet/tasks/phpstan/phpstan-8-baseline.neon index abd284323c..e8bbbb5858 100644 --- a/mailpoet/tasks/phpstan/phpstan-8-baseline.neon +++ b/mailpoet/tasks/phpstan/phpstan-8-baseline.neon @@ -56,7 +56,7 @@ parameters: path: ../../lib/API/JSON/v1/ImportExport.php - - message: "#^Parameter \\#6 \\$data of class MailPoet\\\\Subscribers\\\\ImportExport\\\\Import\\\\Import constructor expects array, mixed given\\.$#" + message: "#^Parameter \\#7 \\$data of class MailPoet\\\\Subscribers\\\\ImportExport\\\\Import\\\\Import constructor expects array, mixed given\\.$#" count: 1 path: ../../lib/API/JSON/v1/ImportExport.php diff --git a/mailpoet/tasks/phpstan/phpstan-8.1-baseline.neon b/mailpoet/tasks/phpstan/phpstan-8.1-baseline.neon index 71cbd1e313..ae6278cdb3 100644 --- a/mailpoet/tasks/phpstan/phpstan-8.1-baseline.neon +++ b/mailpoet/tasks/phpstan/phpstan-8.1-baseline.neon @@ -55,7 +55,7 @@ parameters: path: ../../lib/API/JSON/v1/ImportExport.php - - message: "#^Parameter \\#6 \\$data of class MailPoet\\\\Subscribers\\\\ImportExport\\\\Import\\\\Import constructor expects array, mixed given\\.$#" + message: "#^Parameter \\#7 \\$data of class MailPoet\\\\Subscribers\\\\ImportExport\\\\Import\\\\Import constructor expects array, mixed given\\.$#" count: 1 path: ../../lib/API/JSON/v1/ImportExport.php diff --git a/mailpoet/tests/integration/Subscribers/ImportExport/Import/ImportTest.php b/mailpoet/tests/integration/Subscribers/ImportExport/Import/ImportTest.php index df0728ad63..2cd8266e64 100644 --- a/mailpoet/tests/integration/Subscribers/ImportExport/Import/ImportTest.php +++ b/mailpoet/tests/integration/Subscribers/ImportExport/Import/ImportTest.php @@ -16,6 +16,7 @@ use MailPoet\Subscribers\ImportExport\ImportExportRepository; use MailPoet\Subscribers\SubscriberCustomFieldRepository; use MailPoet\Subscribers\SubscriberSegmentRepository; use MailPoet\Subscribers\SubscribersRepository; +use MailPoet\Tags\TagRepository; use MailPoet\WP\Functions as WPFunctions; use MailPoetVendor\Carbon\Carbon; @@ -59,6 +60,9 @@ class ImportTest extends \MailPoetTest { /** @var SubscriberSegmentRepository */ private $subscriberSegmentRepository; + /** @var TagRepository */ + private $tagRepository; + public function _before(): void { $this->wpSegment = $this->diContainer->get(WP::class); $this->customFieldsRepository = $this->diContainer->get(CustomFieldsRepository::class); @@ -68,6 +72,7 @@ class ImportTest extends \MailPoetTest { $this->subscriberCustomFieldRepository = $this->diContainer->get(SubscriberCustomFieldRepository::class); $this->subscriberRepository = $this->diContainer->get(SubscribersRepository::class); $this->subscriberSegmentRepository = $this->diContainer->get(SubscriberSegmentRepository::class); + $this->tagRepository = $this->diContainer->get(TagRepository::class); $customField = $this->customFieldsRepository->createOrUpdate([ 'name' => 'country', 'type' => CustomFieldEntity::TYPE_TEXT, @@ -780,6 +785,7 @@ class ImportTest extends \MailPoetTest { $this->importExportRepository, $this->newsletterOptionsRepository, $this->subscriberRepository, + $this->tagRepository, $data ); }