123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604 |
- <?php
- namespace Dotdigitalgroup\Email\Model;
- /**
- * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
- */
- class Importer extends \Magento\Framework\Model\AbstractModel
- {
- const NOT_IMPORTED = 0;
- const IMPORTING = 1;
- const IMPORTED = 2;
- const FAILED = 3;
- //import mode
- const MODE_BULK = 'Bulk';
- const MODE_SINGLE = 'Single';
- const MODE_SINGLE_DELETE = 'Single_Delete';
- const MODE_CONTACT_DELETE = 'Contact_Delete';
- const MODE_SUBSCRIBER_UPDATE = 'Subscriber_Update';
- const MODE_CONTACT_EMAIL_UPDATE = 'Contact_Email_Update';
- const MODE_SUBSCRIBER_RESUBSCRIBED = 'Subscriber_Resubscribed';
- //import type
- const IMPORT_TYPE_GUEST = 'Guest';
- const IMPORT_TYPE_ORDERS = 'Orders';
- const IMPORT_TYPE_CONTACT = 'Contact';
- const IMPORT_TYPE_REVIEWS = 'Reviews';
- const IMPORT_TYPE_WISHLIST = 'Wishlist';
- const IMPORT_TYPE_CONTACT_UPDATE = 'Contact';
- const IMPORT_TYPE_SUBSCRIBERS = 'Subscriber';
- const IMPORT_TYPE_SUBSCRIBER_UPDATE = 'Subscriber';
- const IMPORT_TYPE_SUBSCRIBER_RESUBSCRIBED = 'Subscriber';
- //sync limits
- const SYNC_SINGLE_LIMIT_NUMBER = 100;
- /**
- * @var ResourceModel\Importer
- */
- private $importerResource;
- /**
- * @var \Dotdigitalgroup\Email\Helper\Data
- */
- private $helper;
- /**
- * @var array
- */
- public $reasons
- = [
- 'Globally Suppressed',
- 'Blocked',
- 'Unsubscribed',
- 'Hard Bounced',
- 'Isp Complaints',
- 'Domain Suppressed',
- 'Failures',
- 'Invalid Entries',
- 'Mail Blocked',
- 'Suppressed by you',
- ];
- /**
- * @var array
- */
- public $importStatuses
- = [
- 'RejectedByWatchdog',
- 'InvalidFileFormat',
- 'Unknown',
- 'Failed',
- 'ExceedsAllowedContactLimit',
- 'NotAvailableInThisVersion',
- ];
- /**
- * @var array
- */
- public $bulkPriority;
- /**
- * @var array
- */
- public $singlePriority;
- /**
- * @var int
- */
- public $totalItems;
-
- /**
- * @var int
- */
- public $bulkSyncLimit;
- /**
- * @var \Magento\Framework\Stdlib\DateTime
- */
- public $dateTime;
-
- /**
- * @var \Magento\Framework\ObjectManagerInterface
- */
- public $objectManager;
- /**
- * @var Config\Json
- */
- public $serializer;
- /**
- * Importer constructor.
- * @param \Magento\Framework\Model\Context $context
- * @param \Magento\Framework\Registry $registry
- * @param \Dotdigitalgroup\Email\Helper\Data $helper
- * @param ResourceModel\Importer $importerResource
- * @param \Magento\Framework\ObjectManagerInterface $objectManager
- * @param \Magento\Framework\Stdlib\DateTime $dateTime
- * @param Config\Json $serializer
- * @param array $data
- * @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource
- * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection
- */
- public function __construct(
- \Magento\Framework\Model\Context $context,
- \Magento\Framework\Registry $registry,
- \Dotdigitalgroup\Email\Helper\Data $helper,
- \Dotdigitalgroup\Email\Model\ResourceModel\Importer $importerResource,
- \Magento\Framework\ObjectManagerInterface $objectManager,
- \Magento\Framework\Stdlib\DateTime $dateTime,
- \Dotdigitalgroup\Email\Model\Config\Json $serializer,
- array $data = [],
- \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
- \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null
- ) {
- $this->helper = $helper;
- $this->dateTime = $dateTime;
- $this->serializer = $serializer;
- $this->objectManager = $objectManager;
- $this->importerResource = $importerResource;
- parent::__construct($context, $registry, $resource, $resourceCollection, $data);
- }
- /**
- * Constructor.
- *
- * @return null
- */
- public function _construct()
- {
- $this->_init(\Dotdigitalgroup\Email\Model\ResourceModel\Importer::class);
- }
- /**
- * @return $this
- */
- public function beforeSave()
- {
- parent::beforeSave();
- if ($this->isObjectNew()) {
- $this->setCreatedAt($this->dateTime->formatDate(true));
- }
- $this->setUpdatedAt($this->dateTime->formatDate(true));
- return $this;
- }
- /**
- * Register import in queue.
- *
- * @param string $importType
- * @param array|string|null $importData
- * @param string $importMode
- * @param int $websiteId
- * @param bool $file
- *
- * @return bool
- */
- public function registerQueue(
- $importType,
- $importData,
- $importMode,
- $websiteId,
- $file = false
- ) {
- try {
- if (! empty($importData)) {
- $importData = $this->serializer->serialize($importData);
- }
- if ($file) {
- $this->setImportFile($file);
- }
- if ($importData || $file) {
- $this->setImportType($importType)
- ->setImportData($importData)
- ->setWebsiteId($websiteId)
- ->setImportMode($importMode);
- $this->importerResource->save($this);
- return true;
- }
- } catch (\Exception $e) {
- $this->helper->debug((string)$e, []);
- }
- if ($this->serializer->jsonError) {
- $jle = $this->serializer->jsonError;
- $format = "Json error ($jle) for Import type ($importType) / mode ($importMode) for website ($websiteId)";
- $this->helper->log($format);
- }
- return false;
- }
- /**
- * Proccess the data from queue.
- *
- * @return null
- */
- public function processQueue()
- {
- //Set items to 0
- $this->totalItems = 0;
- //Set bulk sync limit
- $this->bulkSyncLimit = 5;
- //Set priority
- $this->_setPriority();
- //Check previous import status
- $this->_checkImportStatus();
- //Bulk priority. Process group 1 first
- foreach ($this->bulkPriority as $bulk) {
- if ($this->totalItems < $bulk['limit']) {
- $collection = $this->_getQueue(
- $bulk['type'],
- $bulk['mode'],
- $bulk['limit'] - $this->totalItems
- );
- if ($collection->getSize()) {
- $this->totalItems += $collection->getSize();
- $bulkModel = $this->objectManager->create($bulk['model']);
- $bulkModel->sync($collection);
- }
- }
- }
- //reset total items to 0
- $this->totalItems = 0;
- //Single/Update priority.
- foreach ($this->singlePriority as $single) {
- if ($this->totalItems < $single['limit']) {
- $collection = $this->_getQueue(
- $single['type'],
- $single['mode'],
- $single['limit'] - $this->totalItems
- );
- if ($collection->getSize()) {
- $this->totalItems += $collection->getSize();
- $singleModel = $this->objectManager->create(
- $single['model']
- );
- $singleModel->sync($collection);
- }
- }
- }
- }
- /**
- * Set importing priority.
- *
- * @return null
- *
- * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
- */
- public function _setPriority()
- {
- /*
- * Bulk
- */
- $defaultBulk = [
- 'model' => '',
- 'mode' => self::MODE_BULK,
- 'type' => '',
- 'limit' => $this->bulkSyncLimit,
- ];
- //Contact Bulk
- $contact = $defaultBulk;
- $contact['model'] = \Dotdigitalgroup\Email\Model\Sync\Contact\Bulk::class;
- $contact['type'] = [
- self::IMPORT_TYPE_CONTACT,
- self::IMPORT_TYPE_GUEST,
- self::IMPORT_TYPE_SUBSCRIBERS,
- ];
- //Bulk Order
- $order = $defaultBulk;
- $order['model'] = \Dotdigitalgroup\Email\Model\Sync\Td\Bulk::class;
- $order['type'] = self::IMPORT_TYPE_ORDERS;
- //Bulk Other TD
- $other = $defaultBulk;
- $other['model'] = \Dotdigitalgroup\Email\Model\Sync\Td\Bulk::class;
- $other['type'] = [
- 'Catalog',
- self::IMPORT_TYPE_REVIEWS,
- self::IMPORT_TYPE_WISHLIST,
- ];
- /*
- * Update
- */
- $defaultSingleUpdate = [
- 'model' => \Dotdigitalgroup\Email\Model\Sync\Contact\Update::class,
- 'mode' => '',
- 'type' => '',
- 'limit' => self::SYNC_SINGLE_LIMIT_NUMBER,
- ];
- //Subscriber resubscribe
- $subscriberResubscribe = $defaultSingleUpdate;
- $subscriberResubscribe['mode'] = self::MODE_SUBSCRIBER_RESUBSCRIBED;
- $subscriberResubscribe['type'] = self::IMPORT_TYPE_SUBSCRIBER_RESUBSCRIBED;
- //Subscriber update/suppressed
- $subscriberUpdate = $defaultSingleUpdate;
- $subscriberUpdate['mode'] = self::MODE_SUBSCRIBER_UPDATE;
- $subscriberUpdate['type'] = self::IMPORT_TYPE_SUBSCRIBER_UPDATE;
- //Email Change
- $emailChange = $defaultSingleUpdate;
- $emailChange['mode'] = self::MODE_CONTACT_EMAIL_UPDATE;
- $emailChange['type'] = self::IMPORT_TYPE_CONTACT_UPDATE;
- //Order Update
- $orderUpdate = $defaultSingleUpdate;
- $orderUpdate['model'] = \Dotdigitalgroup\Email\Model\Sync\Td\Update::class;
- $orderUpdate['mode'] = self::MODE_SINGLE;
- $orderUpdate['type'] = self::IMPORT_TYPE_ORDERS;
- //Update Other TD
- $updateOtherTd = $defaultSingleUpdate;
- $updateOtherTd['model'] = \Dotdigitalgroup\Email\Model\Sync\Td\Update::class;
- $updateOtherTd['mode'] = self::MODE_SINGLE;
- $updateOtherTd['type'] = [
- 'Catalog',
- self::IMPORT_TYPE_WISHLIST,
- ];
- /*
- * Delete
- */
- $defaultSingleDelete = [
- 'model' => '',
- 'mode' => '',
- 'type' => '',
- 'limit' => self::SYNC_SINGLE_LIMIT_NUMBER,
- ];
- //Contact Delete
- $contactDelete = $defaultSingleDelete;
- $contactDelete['model'] = \Dotdigitalgroup\Email\Model\Sync\Contact\Delete::class;
- $contactDelete['mode'] = self::MODE_CONTACT_DELETE;
- $contactDelete['type'] = self::IMPORT_TYPE_CONTACT;
- //TD Delete
- $tdDelete = $defaultSingleDelete;
- $tdDelete['model'] = \Dotdigitalgroup\Email\Model\Sync\Td\Delete::class;
- $tdDelete['mode'] = self::MODE_SINGLE_DELETE;
- $tdDelete['type'] = [
- 'Catalog',
- self::IMPORT_TYPE_REVIEWS,
- self::IMPORT_TYPE_WISHLIST,
- self::IMPORT_TYPE_ORDERS,
- ];
- //Bulk Priority
- $this->bulkPriority = [
- $contact,
- $order,
- $other,
- ];
- $this->singlePriority = [
- $subscriberResubscribe,
- $subscriberUpdate,
- $emailChange,
- $orderUpdate,
- $updateOtherTd,
- $contactDelete,
- $tdDelete,
- ];
- }
- /**
- * Check importing status for pending import.
- *
- * @return null
- */
- public function _checkImportStatus()
- {
- if ($items = $this->_getImportingItems($this->bulkSyncLimit)) {
- foreach ($items as $item) {
- $websiteId = $item->getWebsiteId();
- $client = false;
- if ($this->helper->isEnabled($websiteId)) {
- $client = $this->helper->getWebsiteApiClient(
- $websiteId
- );
- }
- if ($client) {
- try {
- if ($item->getImportType() == self::IMPORT_TYPE_CONTACT ||
- $item->getImportType() == self::IMPORT_TYPE_SUBSCRIBERS ||
- $item->getImportType() == self::IMPORT_TYPE_GUEST
- ) {
- $response = $client->getContactsImportByImportId($item->getImportId());
- } else {
- $response = $client->getContactsTransactionalDataImportByImportId(
- $item->getImportId()
- );
- }
- } catch (\Exception $e) {
- $item->setMessage($e->getMessage())
- ->setImportStatus(self::FAILED);
- $this->saveItem($item);
- continue;
- }
- $this->processResponse($response, $item, $websiteId);
- }
- }
- }
- }
- /**
- * @param Object $response
- * @param \Dotdigitalgroup\Email\Model\Importer $item
- * @param int $websiteId
- *
- * @return null
- */
- private function processResponse($response, $item, $websiteId)
- {
- if (isset($response->message)) {
- $item->setImportStatus(self::FAILED)
- ->setMessage($response->message);
- } else {
- if ($response->status == 'Finished') {
- $item = $this->processFinishedItem($item, $websiteId);
- } elseif (in_array($response->status, $this->importStatuses)) {
- $item->setImportStatus(self::FAILED)
- ->setMessage('Import failed with status ' . $response->status);
- } else {
- //Not finished
- $this->totalItems += 1;
- }
- }
- //Save item
- $this->saveItem($item);
- }
- /**
- * @param Importer $item
- * @param int $websiteId
- *
- * @return $this
- *
- * @throws \Magento\Framework\Exception\LocalizedException
- */
- private function processFinishedItem($item, $websiteId)
- {
- $now = gmdate('Y-m-d H:i:s');
- $item->setImportStatus(self::IMPORTED)
- ->setImportFinished($now)
- ->setMessage('');
- if ($item->getImportType() == self::IMPORT_TYPE_CONTACT ||
- $item->getImportType() == self::IMPORT_TYPE_SUBSCRIBERS ||
- $item->getImportType() == self::IMPORT_TYPE_GUEST
- ) {
- //if file
- if ($file = $item->getImportFile()) {
- //remove the consent data for contacts before arhiving the file
- $log = $this->helper->fileHelper->cleanProcessedConsent(
- $this->helper->fileHelper->getFilePathWithFallback($file)
- );
- if ($log) {
- $this->helper->log($log);
- }
- if (! $this->helper->fileHelper->isFileAlreadyArchived($file)) {
- $this->helper->fileHelper->archiveCSV($file);
- }
- }
- if ($item->getImportId()) {
- $this->_processContactImportReportFaults($item->getImportId(), $websiteId);
- }
- }
- return $item;
- }
- /**
- * @param \Dotdigitalgroup\Email\Model\Importer $itemToSave
- *
- * @return null
- */
- private function saveItem($itemToSave)
- {
- $this->importerResource->save($itemToSave);
- }
- /**
- * Get imports marked as importing.
- *
- * @param int $limit
- *
- * @return \Dotdigitalgroup\Email\Model\ResourceModel\Importer\Collection|bool
- */
- public function _getImportingItems($limit)
- {
- return $this->getCollection()
- ->getItemsWithImportingStatus($limit);
- }
- /**
- * Get report info for contacts sync.
- *
- * @param int $id
- * @param int $websiteId
- *
- * @throws \Magento\Framework\Exception\LocalizedException
- *
- * @return null
- */
- public function _processContactImportReportFaults($id, $websiteId)
- {
- $client = $this->helper->getWebsiteApiClient($websiteId);
- $report = $client->getContactImportReportFaults($id);
- if ($report) {
- $reportData = explode(PHP_EOL, $this->_removeUtf8Bom($report));
- //unset header
- unset($reportData[0]);
- //no data in report
- if (! empty($reportData)) {
- $contacts = [];
- foreach ($reportData as $row) {
- $row = explode(',', $row);
- //reason
- if (in_array($row[0], $this->reasons)) {
- //email
- $contacts[] = $row[1];
- }
- }
- //unsubscribe from email contact and newsletter subscriber tables
- $this->helper->contactResource->unsubscribe($contacts);
- }
- }
- }
- /**
- * Convert utf8 data.
- *
- * @param string $text
- *
- * @return string
- */
- public function _removeUtf8Bom($text)
- {
- $bom = pack('H*', 'EFBBBF');
- $text = preg_replace("/^$bom/", '', $text);
- return $text;
- }
- /**
- * Get the imports by type.
- *
- * @param string $importType
- * @param string $importMode
- * @param int $limit
- *
- * @return \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
- */
- public function _getQueue($importType, $importMode, $limit)
- {
- return $this->getCollection()
- ->getQueueByTypeAndMode($importType, $importMode, $limit);
- }
- }
|