Sin descripción

SubscribersFinder.php 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. <?php
  2. namespace MailPoet\Segments;
  3. if (!defined('ABSPATH')) exit;
  4. use MailPoet\Entities\SegmentEntity;
  5. use MailPoet\InvalidStateException;
  6. use MailPoet\Models\ScheduledTask;
  7. use MailPoet\Models\ScheduledTaskSubscriber;
  8. use MailPoet\Models\Segment;
  9. use MailPoet\Models\Subscriber;
  10. use MailPoetVendor\Idiorm\ORM;
  11. class SubscribersFinder {
  12. /** @var SegmentSubscribersRepository */
  13. private $segmentSubscriberRepository;
  14. public function __construct(
  15. SegmentSubscribersRepository $segmentSubscriberRepository
  16. ) {
  17. $this->segmentSubscriberRepository = $segmentSubscriberRepository;
  18. }
  19. public function findSubscribersInSegments($subscribersToProcessIds, $newsletterSegmentsIds) {
  20. $result = [];
  21. foreach ($newsletterSegmentsIds as $segmentId) {
  22. $segment = Segment::findOne($segmentId);
  23. if (!$segment instanceof Segment) {
  24. continue; // skip deleted segments
  25. }
  26. $result = array_merge($result, $this->findSubscribersInSegment($segment, $subscribersToProcessIds));
  27. }
  28. return $this->unique($result);
  29. }
  30. private function findSubscribersInSegment(Segment $segment, $subscribersToProcessIds): array {
  31. try {
  32. return $this->segmentSubscriberRepository->findSubscribersIdsInSegment((int)$segment->id, $subscribersToProcessIds);
  33. } catch (InvalidStateException $e) {
  34. return [];
  35. }
  36. }
  37. private function isStaticSegment(Segment $segment) {
  38. return in_array($segment->type, [Segment::TYPE_DEFAULT, Segment::TYPE_WP_USERS, Segment::TYPE_WC_USERS], true);
  39. }
  40. public function addSubscribersToTaskFromSegments(ScheduledTask $task, array $segments) {
  41. // Prepare subscribers on the DB side for performance reasons
  42. $staticSegments = [];
  43. $dynamicSegments = [];
  44. foreach ($segments as $segment) {
  45. if ($this->isStaticSegment($segment)) {
  46. $staticSegments[] = $segment;
  47. } elseif ($segment->type === SegmentEntity::TYPE_DYNAMIC) {
  48. $dynamicSegments[] = $segment;
  49. }
  50. }
  51. $count = 0;
  52. if (!empty($staticSegments)) {
  53. $count += $this->addSubscribersToTaskFromStaticSegments($task, $staticSegments);
  54. }
  55. if (!empty($dynamicSegments)) {
  56. $count += $this->addSubscribersToTaskFromDynamicSegments($task, $dynamicSegments);
  57. }
  58. return $count;
  59. }
  60. private function addSubscribersToTaskFromStaticSegments(ScheduledTask $task, array $segments) {
  61. $segmentIds = array_map(function($segment) {
  62. return $segment->id;
  63. }, $segments);
  64. Subscriber::rawExecute(
  65. 'INSERT IGNORE INTO ' . MP_SCHEDULED_TASK_SUBSCRIBERS_TABLE . '
  66. (task_id, subscriber_id, processed)
  67. SELECT DISTINCT ? as task_id, subscribers.`id` as subscriber_id, ? as processed
  68. FROM ' . MP_SUBSCRIBER_SEGMENT_TABLE . ' relation
  69. JOIN ' . MP_SUBSCRIBERS_TABLE . ' subscribers ON subscribers.id = relation.subscriber_id
  70. WHERE subscribers.`deleted_at` IS NULL
  71. AND subscribers.`status` = ?
  72. AND relation.`status` = ?
  73. AND relation.`segment_id` IN (' . join(',', array_map('intval', $segmentIds)) . ')',
  74. [
  75. $task->id,
  76. ScheduledTaskSubscriber::STATUS_UNPROCESSED,
  77. Subscriber::STATUS_SUBSCRIBED,
  78. Subscriber::STATUS_SUBSCRIBED,
  79. ]
  80. );
  81. return ORM::getLastStatement()->rowCount();
  82. }
  83. private function addSubscribersToTaskFromDynamicSegments(ScheduledTask $task, array $segments) {
  84. $count = 0;
  85. foreach ($segments as $segment) {
  86. $count += $this->addSubscribersToTaskFromDynamicSegment($task, $segment);
  87. }
  88. return $count;
  89. }
  90. private function addSubscribersToTaskFromDynamicSegment(ScheduledTask $task, Segment $segment) {
  91. $count = 0;
  92. $subscribers = $this->segmentSubscriberRepository->getSubscriberIdsInSegment((int)$segment->id);
  93. if ($subscribers) {
  94. $count += $this->addSubscribersToTaskByIds($task, $subscribers);
  95. }
  96. return $count;
  97. }
  98. private function addSubscribersToTaskByIds(ScheduledTask $task, array $subscriberIds) {
  99. Subscriber::rawExecute(
  100. 'INSERT IGNORE INTO ' . MP_SCHEDULED_TASK_SUBSCRIBERS_TABLE . '
  101. (task_id, subscriber_id, processed)
  102. SELECT DISTINCT ? as task_id, subscribers.`id` as subscriber_id, ? as processed
  103. FROM ' . MP_SUBSCRIBERS_TABLE . ' subscribers
  104. WHERE subscribers.`deleted_at` IS NULL
  105. AND subscribers.`status` = ?
  106. AND subscribers.`id` IN (' . join(',', array_map('intval', $subscriberIds)) . ')',
  107. [
  108. $task->id,
  109. ScheduledTaskSubscriber::STATUS_UNPROCESSED,
  110. Subscriber::STATUS_SUBSCRIBED,
  111. ]
  112. );
  113. return ORM::getLastStatement()->rowCount();
  114. }
  115. private function unique(array $subscriberIds) {
  116. $result = [];
  117. foreach ($subscriberIds as $id) {
  118. $result[$id] = $id;
  119. }
  120. return $result;
  121. }
  122. }