entityManager = $entityManager; $this->wcHelper = $wcHelper; $this->wooFilterHelper = $wooFilterHelper; $this->filterHelper = $filterHelper; } /** * @return SubscriberEntity[] */ public function getBatch(int $lastProcessedId = 0, int $batchSize = 100): array { $subscribers = $this->entityManager->createQueryBuilder() ->select('PARTIAL s.{id, email, lastPurchaseAt, lastClickAt, lastOpenAt, lastSendingAt}') ->from(SubscriberEntity::class, 's') ->where('s.id > :lastProcessedId') ->orderBy('s.id', 'ASC') ->setMaxResults($batchSize) ->setParameter('lastProcessedId', $lastProcessedId) ->getQuery() ->getResult(); if (!is_array($subscribers)) { return []; } return $subscribers; } /** * @param SubscriberEntity[] $subscribers * * @return void */ public function updateBatch(array $subscribers): void { $subscriberIds = array_map(function (SubscriberEntity $subscriber) { return $subscriber->getId(); }, $subscribers); $clickData = $this->getClickDataForBatch($subscriberIds); $openData = $this->getOpenDataForBatch($subscriberIds); $sendingData = $this->getSendingDataForBatch($subscriberIds); $purchaseData = $this->getPurchaseDataForBatch($subscriberIds); foreach ($subscribers as $subscriber) { if ($subscriber->getLastPurchaseAt() === null && isset($purchaseData[$subscriber->getId()]['last_purchase_at'])) { $purchaseDate = new Carbon($purchaseData[$subscriber->getId()]['last_purchase_at']); $subscriber->setLastPurchaseAt($purchaseDate); } if ($subscriber->getLastOpenAt() === null && isset($openData[$subscriber->getId()]['last_open_at'])) { $openDate = new Carbon($openData[$subscriber->getId()]['last_open_at']); $subscriber->setLastOpenAt($openDate); } if ($subscriber->getLastClickAt() === null && isset($clickData[$subscriber->getId()]['last_click_at'])) { $clickDate = new Carbon($clickData[$subscriber->getId()]['last_click_at']); $subscriber->setLastClickAt($clickDate); } if ($subscriber->getLastSendingAt() === null && isset($sendingData[$subscriber->getId()]['last_sending_at'])) { $sendingDate = new Carbon($sendingData[$subscriber->getId()]['last_sending_at']); $subscriber->setLastSendingAt($sendingDate); } if (is_int($subscriber->getId())) { $this->lastProcessedSubscriberId = $subscriber->getId(); } } $this->entityManager->flush(); } public function getClickDataForBatch(array $subscriberIds): array { $subscribersTable = $this->filterHelper->getSubscribersTable(); $clicksTable = $this->filterHelper->getTableForEntity(StatisticsClickEntity::class); $query = $this ->entityManager ->getConnection() ->createQueryBuilder() ->select("$subscribersTable.id, MAX(clicks.created_at) as last_click_at") ->from($subscribersTable) ->innerJoin($subscribersTable, $clicksTable, 'clicks', "$subscribersTable.id = clicks.subscriber_id") ->andWhere("$subscribersTable.id IN (:subscriberIds)") ->setParameter('subscriberIds', $subscriberIds, Connection::PARAM_INT_ARRAY) ->groupBy("$subscribersTable.id"); $result = $query->execute(); if ($result instanceof Result) { return $result->fetchAllAssociativeIndexed(); } return []; } public function getPurchaseDataForBatch(array $subscriberIds): array { if (!$this->wcHelper->isWooCommerceActive()) { return []; } $subscribersTable = $this->filterHelper->getSubscribersTable(); $query = $this ->entityManager ->getConnection() ->createQueryBuilder() // The orderStats alias comes from wooFilterHelper->applyOrderStatusFilter, which calls wooFilterHelper->applyCustomerOrderJoin ->select("$subscribersTable.id, MAX(orderStats.date_created) as last_purchase_at") ->from($subscribersTable) ->andWhere("$subscribersTable.id IN (:subscriberIds)") ->setParameter('subscriberIds', $subscriberIds, Connection::PARAM_INT_ARRAY); $this->wooFilterHelper->applyOrderStatusFilter($query); $query->groupBy("$subscribersTable.id"); $result = $query->execute(); if ($result instanceof Result) { return $result->fetchAllAssociativeIndexed(); } return []; } public function getOpenDataForBatch(array $subscriberIds): array { $subscribersTable = $this->filterHelper->getSubscribersTable(); $opensTable = $this->filterHelper->getTableForEntity(StatisticsOpenEntity::class); $query = $this ->entityManager ->getConnection() ->createQueryBuilder() ->select("$subscribersTable.id, MAX(opens.created_at) as last_open_at") ->from($subscribersTable) ->innerJoin($subscribersTable, $opensTable, 'opens', "$subscribersTable.id = opens.subscriber_id") ->andWhere("$subscribersTable.id IN (:subscriberIds)") ->setParameter('subscriberIds', $subscriberIds, Connection::PARAM_INT_ARRAY) ->groupBy("$subscribersTable.id"); $result = $query->execute(); if ($result instanceof Result) { return $result->fetchAllAssociativeIndexed(); } return []; } public function getSendingDataForBatch(array $subscriberIds): array { $subscribersTable = $this->filterHelper->getSubscribersTable(); $sendsTable = $this->filterHelper->getTableForEntity(StatisticsNewsletterEntity::class); $query = $this ->entityManager ->getConnection() ->createQueryBuilder() ->select("$subscribersTable.id, MAX(sends.sent_at) as last_sending_at") ->from($subscribersTable) ->innerJoin($subscribersTable, $sendsTable, 'sends', "$subscribersTable.id = sends.subscriber_id") ->andWhere("$subscribersTable.id IN (:subscriberIds)") ->setParameter('subscriberIds', $subscriberIds, Connection::PARAM_INT_ARRAY) ->groupBy("$subscribersTable.id"); $result = $query->execute(); if ($result instanceof Result) { return $result->fetchAllAssociativeIndexed(); } return []; } /** * @return int */ public function getLastProcessedSubscriberId(): int { return $this->lastProcessedSubscriberId; } public function setLastProcessedSubscriberId(int $id): void { $this->lastProcessedSubscriberId = $id; } }