Campaign.php 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. <?php
  2. namespace Dotdigitalgroup\Email\Model\Sync;
  3. /**
  4. * Send email campaings.
  5. */
  6. class Campaign
  7. {
  8. //single call contact limit
  9. const SEND_EMAIL_CONTACT_LIMIT = 10;
  10. /**
  11. * @var \Dotdigitalgroup\Email\Helper\Data
  12. */
  13. private $helper;
  14. /**
  15. * @var \Dotdigitalgroup\Email\Model\ResourceModel\Campaign\CollectionFactory
  16. */
  17. private $campaignCollection;
  18. /**
  19. * @var \Magento\Store\Model\StoreManagerInterface
  20. */
  21. private $storeManager;
  22. /**
  23. * @var \Magento\Sales\Model\OrderFactory
  24. */
  25. private $salesOrderFactory;
  26. /**
  27. * @var \Magento\Store\Model\WebsiteFactory
  28. */
  29. private $websiteFactory;
  30. /**
  31. * @var \Dotdigitalgroup\Email\Model\ResourceModel\Campaign
  32. */
  33. private $campaignResourceModel;
  34. /**
  35. * Campaign constructor.
  36. *
  37. * @param \Dotdigitalgroup\Email\Model\ResourceModel\Campaign\CollectionFactory $campaignFactory
  38. * @param \Dotdigitalgroup\Email\Helper\Data $data
  39. * @param \Magento\Store\Model\StoreManagerInterface $storeManagerInterface
  40. * @param \Magento\Sales\Model\OrderFactory $salesOrderFactory
  41. * @param \Magento\Store\Model\WebsiteFactory $websiteFactory
  42. * @param \Dotdigitalgroup\Email\Model\ResourceModel\Campaign $campaignResourceModel
  43. */
  44. public function __construct(
  45. \Dotdigitalgroup\Email\Model\ResourceModel\Campaign\CollectionFactory $campaignFactory,
  46. \Dotdigitalgroup\Email\Helper\Data $data,
  47. \Magento\Store\Model\StoreManagerInterface $storeManagerInterface,
  48. \Magento\Sales\Model\OrderFactory $salesOrderFactory,
  49. \Magento\Store\Model\WebsiteFactory $websiteFactory,
  50. \Dotdigitalgroup\Email\Model\ResourceModel\Campaign $campaignResourceModel
  51. ) {
  52. $this->campaignResourceModel = $campaignResourceModel;
  53. $this->websiteFactory = $websiteFactory;
  54. $this->helper = $data;
  55. $this->campaignCollection = $campaignFactory;
  56. $this->storeManager = $storeManagerInterface;
  57. $this->salesOrderFactory = $salesOrderFactory;
  58. }
  59. /**
  60. * Sending the campaigns
  61. *
  62. * @throws \Magento\Framework\Exception\LocalizedException
  63. *
  64. * @return null
  65. */
  66. public function sendCampaigns()
  67. {
  68. /** @var \Magento\Store\Api\Data\WebsiteInterface $website */
  69. foreach ($this->storeManager->getWebsites(true) as $website) {
  70. $storeIds = $website->getStoreIds();
  71. //check send status for processing
  72. $this->_checkSendStatus($website, $storeIds);
  73. //start send process
  74. $emailsToSend = $this->_getEmailCampaigns($storeIds);
  75. $campaignsToSend = $this->getCampaignsToSend($emailsToSend, $website);
  76. $this->sendCampaignsViaDotmailer($campaignsToSend);
  77. }
  78. }
  79. /**
  80. * @param int $website
  81. * @param array $storeIds
  82. *
  83. * @return null
  84. */
  85. public function _checkSendStatus($website, $storeIds)
  86. {
  87. $campaigns = $this->_getEmailCampaigns(
  88. $storeIds,
  89. \Dotdigitalgroup\Email\Model\Campaign::PROCESSING,
  90. true
  91. );
  92. foreach ($campaigns as $campaign) {
  93. $client = $this->helper->getWebsiteApiClient($website);
  94. $response = $client->getSendStatus($campaign->getSendId());
  95. if (isset($response->message) || $response->status == 'Cancelled') {
  96. $message = isset($response->message) ? $response->message : $response->status;
  97. $this->campaignResourceModel->setMessageWithSendId($campaign->getSendId(), $message);
  98. } elseif ($response->status == 'Sent') {
  99. $this->campaignResourceModel->setSent($campaign->getSendId());
  100. }
  101. }
  102. }
  103. /**
  104. * Get campaigns to send.
  105. *
  106. * @param \Dotdigitalgroup\Email\Model\ResourceModel\Campaign\Collection $emailsToSend
  107. * @param \Magento\Store\Api\Data\WebsiteInterface $website
  108. *
  109. * @return array
  110. */
  111. private function getCampaignsToSend($emailsToSend, $website)
  112. {
  113. $campaignsToSend = [];
  114. foreach ($emailsToSend as $campaign) {
  115. $email = $campaign->getEmail();
  116. $campaignId = $campaign->getCampaignId();
  117. $websiteId = $website->getId();
  118. $client = false;
  119. if ($this->helper->isEnabled($websiteId)) {
  120. $client = $this->helper->getWebsiteApiClient($websiteId);
  121. }
  122. //Only if valid client is returned
  123. if ($client && $this->isCampaignValid($campaign)) {
  124. $campaignsToSend[$campaignId]['client'] = $client;
  125. $contact = $this->helper->getContact(
  126. $campaign->getEmail(),
  127. $websiteId
  128. );
  129. if ($contact && isset($contact->id)) {
  130. //update data fields
  131. if ($campaign->getEventName() == 'Order Review') {
  132. $this->updateDataFieldsForORderReviewCampaigns($campaign, $websiteId, $client, $email);
  133. } elseif ($campaign->getEventName() ==
  134. \Dotdigitalgroup\Email\Model\Campaign::CAMPAIGN_EVENT_LOST_BASKET
  135. ) {
  136. $campaignCollection = $this->campaignCollection->create();
  137. // If AC campaigns found with status processing for given email then skip for current cron run
  138. if ($campaignCollection->getNumberOfAcCampaignsWithStatusProcessingExistForContact($email)) {
  139. continue;
  140. }
  141. $this->helper->updateLastQuoteId($campaign->getQuoteId(), $email, $websiteId);
  142. }
  143. $campaignsToSend[$campaignId]['contacts'][] = $contact->id;
  144. $campaignsToSend[$campaignId]['ids'][] = $campaign->getId();
  145. } else {
  146. //update the failed to send email message error message
  147. $campaign->setSendStatus(\Dotdigitalgroup\Email\Model\Campaign::FAILED)
  148. ->setMessage('Send not permitted. Contact is suppressed.');
  149. $this->campaignResourceModel->saveItem($campaign);
  150. }
  151. }
  152. }
  153. return $campaignsToSend;
  154. }
  155. /**
  156. * Check if campaign item is valid
  157. *
  158. * @param \Dotdigitalgroup\Email\Model\Campaign $campaign
  159. *
  160. * @return bool
  161. */
  162. private function isCampaignValid($campaign)
  163. {
  164. if (! $campaign->getCampaignId()) {
  165. $campaign->setMessage('Missing campaign id: ' . $campaign->getCampaignId())
  166. ->setSendStatus(\Dotdigitalgroup\Email\Model\Campaign::FAILED);
  167. $this->campaignResourceModel->saveItem($campaign);
  168. return false;
  169. } elseif (! $campaign->getEmail()) {
  170. $campaign->setMessage('Missing email')
  171. ->setSendStatus(\Dotdigitalgroup\Email\Model\Campaign::FAILED);
  172. $this->campaignResourceModel->saveItem($campaign);
  173. return false;
  174. }
  175. return true;
  176. }
  177. /**
  178. * Send campaigns.
  179. *
  180. * @param array $campaignsToSend
  181. *
  182. * @return null
  183. */
  184. private function sendCampaignsViaDotmailer($campaignsToSend)
  185. {
  186. foreach ($campaignsToSend as $campaignId => $data) {
  187. if (isset($data['contacts']) && isset($data['client'])) {
  188. $contacts = $data['contacts'];
  189. /** @var \Dotdigitalgroup\Email\Model\Apiconnector\Client $client */
  190. $client = $data['client'];
  191. $response = $client->postCampaignsSend(
  192. $campaignId,
  193. $contacts
  194. );
  195. if (isset($response->message)) {
  196. //update the failed to send email message
  197. $this->campaignResourceModel->setMessage($data['ids'], $response->message);
  198. } elseif (isset($response->id)) {
  199. $this->campaignResourceModel->setProcessing($data['ids'], $response->id);
  200. } else {
  201. //update the failed to send email message
  202. $this->campaignResourceModel->setMessage($data['ids'], 'No send id returned.');
  203. }
  204. }
  205. }
  206. }
  207. /**
  208. * Get campaign collection.
  209. *
  210. * @param array $storeIds
  211. * @param int $sendStatus
  212. * @param bool $sendIdCheck
  213. *
  214. * @return mixed
  215. */
  216. public function _getEmailCampaigns($storeIds, $sendStatus = 0, $sendIdCheck = false)
  217. {
  218. return $this->campaignCollection->create()
  219. ->getEmailCampaignsByStoreIds($storeIds, $sendStatus, $sendIdCheck);
  220. }
  221. /**
  222. * @param \Dotdigitalgroup\Email\Model\Campaign $campaign
  223. * @param int $websiteId
  224. * @param \Dotdigitalgroup\Email\Model\Apiconnector\Client $client
  225. * @param string $email
  226. *
  227. * @return null
  228. */
  229. private function updateDataFieldsForORderReviewCampaigns($campaign, $websiteId, $client, $email)
  230. {
  231. $order = $this->salesOrderFactory->create()->loadByIncrementId(
  232. $campaign->getOrderIncrementId()
  233. );
  234. if ($lastOrderId = $this->helper->getWebsiteConfig(
  235. \Dotdigitalgroup\Email\Helper\Config::XML_PATH_CONNECTOR_CUSTOMER_LAST_ORDER_ID,
  236. $websiteId
  237. )
  238. ) {
  239. $data[] = [
  240. 'Key' => $lastOrderId,
  241. 'Value' => $order->getId(),
  242. ];
  243. }
  244. if ($orderIncrementId = $this->helper->getWebsiteConfig(
  245. \Dotdigitalgroup\Email\Helper\Config::
  246. XML_PATH_CONNECTOR_CUSTOMER_LAST_ORDER_INCREMENT_ID,
  247. $websiteId
  248. )
  249. ) {
  250. $data[] = [
  251. 'Key' => $orderIncrementId,
  252. 'Value' => $order->getIncrementId(),
  253. ];
  254. }
  255. if (!empty($data)) {
  256. //update data fields
  257. $client->updateContactDatafieldsByEmail(
  258. $email,
  259. $data
  260. );
  261. }
  262. }
  263. }