Queue.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Newsletter\Model;
  7. use Magento\Framework\App\TemplateTypesInterface;
  8. use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
  9. use Magento\Framework\Stdlib\DateTime\Timezone\LocalizedDateToUtcConverterInterface;
  10. /**
  11. * Newsletter queue model.
  12. *
  13. * @method int getTemplateId()
  14. * @method \Magento\Newsletter\Model\Queue setTemplateId(int $value)
  15. * @method int getNewsletterType()
  16. * @method \Magento\Newsletter\Model\Queue setNewsletterType(int $value)
  17. * @method string getNewsletterText()
  18. * @method \Magento\Newsletter\Model\Queue setNewsletterText(string $value)
  19. * @method string getNewsletterStyles()
  20. * @method \Magento\Newsletter\Model\Queue setNewsletterStyles(string $value)
  21. * @method string getNewsletterSubject()
  22. * @method \Magento\Newsletter\Model\Queue setNewsletterSubject(string $value)
  23. * @method string getNewsletterSenderName()
  24. * @method \Magento\Newsletter\Model\Queue setNewsletterSenderName(string $value)
  25. * @method string getNewsletterSenderEmail()
  26. * @method \Magento\Newsletter\Model\Queue setNewsletterSenderEmail(string $value)
  27. * @method int getQueueStatus()
  28. * @method \Magento\Newsletter\Model\Queue setQueueStatus(int $value)
  29. * @method string getQueueStartAt()
  30. * @method \Magento\Newsletter\Model\Queue setQueueStartAt(string $value)
  31. * @method string getQueueFinishAt()
  32. * @method \Magento\Newsletter\Model\Queue setQueueFinishAt(string $value)
  33. * @SuppressWarnings(PHPMD.LongVariable)
  34. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  35. *
  36. * @api
  37. * @since 100.0.2
  38. */
  39. class Queue extends \Magento\Framework\Model\AbstractModel implements TemplateTypesInterface
  40. {
  41. /**
  42. * Newsletter Template object
  43. *
  44. * @var \Magento\Newsletter\Model\Template
  45. */
  46. protected $_template;
  47. /**
  48. * Subscribers collection
  49. *
  50. * @var \Magento\Newsletter\Model\ResourceModel\Subscriber\Collection
  51. */
  52. protected $_subscribersCollection;
  53. /**
  54. * Save stores flag.
  55. *
  56. * @var boolean
  57. */
  58. protected $_saveStoresFlag = false;
  59. /**
  60. * Stores assigned to queue.
  61. *
  62. * @var array
  63. */
  64. protected $_stores = [];
  65. const STATUS_NEVER = 0;
  66. const STATUS_SENDING = 1;
  67. const STATUS_CANCEL = 2;
  68. const STATUS_SENT = 3;
  69. const STATUS_PAUSE = 4;
  70. /**
  71. * Filter for newsletter text
  72. *
  73. * @var \Magento\Newsletter\Model\Template\Filter
  74. */
  75. protected $_templateFilter;
  76. /**
  77. * Date
  78. *
  79. * @var \Magento\Framework\Stdlib\DateTime\DateTime
  80. */
  81. protected $_date;
  82. /**
  83. * Problem factory
  84. *
  85. * @var \Magento\Newsletter\Model\ProblemFactory
  86. */
  87. protected $_problemFactory;
  88. /**
  89. * Template factory
  90. *
  91. * @var \Magento\Newsletter\Model\TemplateFactory
  92. */
  93. protected $_templateFactory;
  94. /**
  95. * @var \Magento\Newsletter\Model\Queue\TransportBuilder
  96. */
  97. protected $_transportBuilder;
  98. /**
  99. * Timezone library.
  100. *
  101. * @var TimezoneInterface
  102. */
  103. private $timezone;
  104. /**
  105. * @var LocalizedDateToUtcConverterInterface
  106. */
  107. private $utcConverter;
  108. /**
  109. * @param \Magento\Framework\Model\Context $context
  110. * @param \Magento\Framework\Registry $registry
  111. * @param \Magento\Newsletter\Model\Template\Filter $templateFilter
  112. * @param \Magento\Framework\Stdlib\DateTime\DateTime $date
  113. * @param \Magento\Newsletter\Model\TemplateFactory $templateFactory
  114. * @param \Magento\Newsletter\Model\ProblemFactory $problemFactory
  115. * @param \Magento\Newsletter\Model\ResourceModel\Subscriber\CollectionFactory $subscriberCollectionFactory
  116. * @param \Magento\Newsletter\Model\Queue\TransportBuilder $transportBuilder
  117. * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
  118. * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
  119. * @param array $data
  120. * @param TimezoneInterface $timezone
  121. * @param LocalizedDateToUtcConverterInterface $utcConverter
  122. * @SuppressWarnings(PHPMD.ExcessiveParameterList)
  123. */
  124. public function __construct(
  125. \Magento\Framework\Model\Context $context,
  126. \Magento\Framework\Registry $registry,
  127. \Magento\Newsletter\Model\Template\Filter $templateFilter,
  128. \Magento\Framework\Stdlib\DateTime\DateTime $date,
  129. \Magento\Newsletter\Model\TemplateFactory $templateFactory,
  130. \Magento\Newsletter\Model\ProblemFactory $problemFactory,
  131. \Magento\Newsletter\Model\ResourceModel\Subscriber\CollectionFactory $subscriberCollectionFactory,
  132. \Magento\Newsletter\Model\Queue\TransportBuilder $transportBuilder,
  133. \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
  134. \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
  135. array $data = [],
  136. TimezoneInterface $timezone = null,
  137. LocalizedDateToUtcConverterInterface $utcConverter = null
  138. ) {
  139. parent::__construct(
  140. $context,
  141. $registry,
  142. $resource,
  143. $resourceCollection,
  144. $data
  145. );
  146. $this->_templateFilter = $templateFilter;
  147. $this->_date = $date;
  148. $this->_templateFactory = $templateFactory;
  149. $this->_problemFactory = $problemFactory;
  150. $this->_subscribersCollection = $subscriberCollectionFactory->create();
  151. $this->_transportBuilder = $transportBuilder;
  152. $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
  153. $this->timezone = $timezone ?: $objectManager->get(TimezoneInterface::class);
  154. $this->utcConverter = $utcConverter ?? $objectManager->get(LocalizedDateToUtcConverterInterface::class);
  155. }
  156. /**
  157. * Initialize resource model
  158. *
  159. * @return void
  160. */
  161. protected function _construct()
  162. {
  163. parent::_construct();
  164. $this->_init(\Magento\Newsletter\Model\ResourceModel\Queue::class);
  165. }
  166. /**
  167. * Return: is this queue newly created or not.
  168. *
  169. * @return boolean
  170. */
  171. public function isNew()
  172. {
  173. return $this->getQueueStatus() === null;
  174. }
  175. /**
  176. * Set $_data['queue_start'] based on string from backend, which based on locale.
  177. *
  178. * @param string|null $startAt start date of the mailing queue
  179. * @return $this
  180. */
  181. public function setQueueStartAtByString($startAt)
  182. {
  183. if ($startAt === null || $startAt == '') {
  184. $this->setQueueStartAt(null);
  185. } else {
  186. $this->setQueueStartAt($this->utcConverter->convertLocalizedDateToUtc($startAt));
  187. }
  188. return $this;
  189. }
  190. /**
  191. * Send messages to subscribers for this queue
  192. *
  193. * @param int $count
  194. * @return $this
  195. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  196. */
  197. public function sendPerSubscriber($count = 20)
  198. {
  199. if ($this->getQueueStatus() != self::STATUS_SENDING &&
  200. ($this->getQueueStatus() != self::STATUS_NEVER &&
  201. $this->getQueueStartAt())
  202. ) {
  203. return $this;
  204. }
  205. if (!$this->_subscribersCollection->getQueueJoinedFlag()) {
  206. $this->_subscribersCollection->useQueue($this);
  207. }
  208. if ($this->_subscribersCollection->getSize() == 0) {
  209. $this->_finishQueue();
  210. return $this;
  211. }
  212. $collection = $this->_subscribersCollection->useOnlyUnsent()->showCustomerInfo()->setPageSize(
  213. $count
  214. )->setCurPage(
  215. 1
  216. )->load();
  217. $this->_transportBuilder->setTemplateData(
  218. [
  219. 'template_subject' => $this->getNewsletterSubject(),
  220. 'template_text' => $this->getNewsletterText(),
  221. 'template_styles' => $this->getNewsletterStyles(),
  222. 'template_filter' => $this->_templateFilter,
  223. 'template_type' => self::TYPE_HTML,
  224. ]
  225. );
  226. /** @var \Magento\Newsletter\Model\Subscriber $item */
  227. foreach ($collection->getItems() as $item) {
  228. $transport = $this->_transportBuilder->setTemplateOptions(
  229. ['area' => \Magento\Framework\App\Area::AREA_FRONTEND, 'store' => $item->getStoreId()]
  230. )->setTemplateVars(
  231. ['subscriber' => $item]
  232. )->setFrom(
  233. ['name' => $this->getNewsletterSenderName(), 'email' => $this->getNewsletterSenderEmail()]
  234. )->addTo(
  235. $item->getSubscriberEmail(),
  236. $item->getSubscriberFullName()
  237. )->getTransport();
  238. try {
  239. $transport->sendMessage();
  240. } catch (\Magento\Framework\Exception\MailException $e) {
  241. /** @var \Magento\Newsletter\Model\Problem $problem */
  242. $problem = $this->_problemFactory->create();
  243. $problem->addSubscriberData($item);
  244. $problem->addQueueData($this);
  245. $problem->addErrorData($e);
  246. $problem->save();
  247. }
  248. $item->received($this);
  249. }
  250. if (count($collection->getItems()) < $count - 1 || count($collection->getItems()) == 0) {
  251. $this->_finishQueue();
  252. }
  253. return $this;
  254. }
  255. /**
  256. * Finish queue: set status SENT and update finish date
  257. *
  258. * @return $this
  259. */
  260. protected function _finishQueue()
  261. {
  262. $this->setQueueFinishAt($this->_date->gmtDate());
  263. $this->setQueueStatus(self::STATUS_SENT);
  264. $this->save();
  265. return $this;
  266. }
  267. /**
  268. * Getter data for saving
  269. *
  270. * @return array
  271. */
  272. public function getDataForSave()
  273. {
  274. $data = [];
  275. $data['template_id'] = $this->getTemplateId();
  276. $data['queue_status'] = $this->getQueueStatus();
  277. $data['queue_start_at'] = $this->getQueueStartAt();
  278. $data['queue_finish_at'] = $this->getQueueFinishAt();
  279. return $data;
  280. }
  281. /**
  282. * Add subscribers to queue.
  283. *
  284. * @param array $subscriberIds
  285. * @return $this
  286. */
  287. public function addSubscribersToQueue(array $subscriberIds)
  288. {
  289. $this->_getResource()->addSubscribersToQueue($this, $subscriberIds);
  290. return $this;
  291. }
  292. /**
  293. * Setter for save stores flag.
  294. *
  295. * @param boolean|integer|string $value
  296. * @return $this
  297. */
  298. public function setSaveStoresFlag($value)
  299. {
  300. $this->_saveStoresFlag = (bool)$value;
  301. return $this;
  302. }
  303. /**
  304. * Getter for save stores flag.
  305. *
  306. * @return boolean
  307. * @SuppressWarnings(PHPMD.BooleanGetMethodName)
  308. */
  309. public function getSaveStoresFlag()
  310. {
  311. return $this->_saveStoresFlag;
  312. }
  313. /**
  314. * Setter for stores of queue.
  315. *
  316. * @param array $storesIds
  317. * @return $this
  318. */
  319. public function setStores(array $storesIds)
  320. {
  321. $this->setSaveStoresFlag(true);
  322. $this->_stores = $storesIds;
  323. return $this;
  324. }
  325. /**
  326. * Getter for stores of queue.
  327. *
  328. * @return array
  329. */
  330. public function getStores()
  331. {
  332. if (!$this->_stores) {
  333. $this->_stores = $this->_getResource()->getStores($this);
  334. }
  335. return $this->_stores;
  336. }
  337. /**
  338. * Retrieve Newsletter Template object
  339. *
  340. * @return \Magento\Newsletter\Model\Template
  341. */
  342. public function getTemplate()
  343. {
  344. if ($this->_template === null) {
  345. $this->_template = $this->_templateFactory->create()->load($this->getTemplateId());
  346. }
  347. return $this->_template;
  348. }
  349. /**
  350. * Return true if template type eq text
  351. *
  352. * @return boolean
  353. */
  354. public function isPlain()
  355. {
  356. return $this->getType() == self::TYPE_TEXT;
  357. }
  358. /**
  359. * Getter for template type
  360. *
  361. * @return int|string
  362. */
  363. public function getType()
  364. {
  365. return $this->getNewsletterType();
  366. }
  367. }