vendor/shopware/platform/src/Core/Checkout/Promotion/DataAbstractionLayer/PromotionRedemptionUpdater.php line 82

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Checkout\Promotion\DataAbstractionLayer;
  3. use Doctrine\DBAL\Connection;
  4. use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
  5. use Shopware\Core\Checkout\Promotion\Cart\PromotionProcessor;
  6. use Shopware\Core\Defaults;
  7. use Shopware\Core\Framework\Context;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Doctrine\RetryableQuery;
  9. use Shopware\Core\Framework\Uuid\Uuid;
  10. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  11. class PromotionRedemptionUpdater implements EventSubscriberInterface
  12. {
  13.     /**
  14.      * @var Connection
  15.      */
  16.     private $connection;
  17.     public function __construct(Connection $connection)
  18.     {
  19.         $this->connection $connection;
  20.     }
  21.     public static function getSubscribedEvents()
  22.     {
  23.         return [
  24.             CheckoutOrderPlacedEvent::class => 'orderPlaced',
  25.         ];
  26.     }
  27.     public function update(array $idsContext $context): void
  28.     {
  29.         $ids array_filter(array_unique($ids));
  30.         if (empty($ids) || $context->getVersionId() !== Defaults::LIVE_VERSION) {
  31.             return;
  32.         }
  33.         $sql = <<<SQL
  34.                 SELECT JSON_UNQUOTE(JSON_EXTRACT(`order_line_item`.`payload`, '$.promotionId')) as promotion_id,
  35.                        COUNT(DISTINCT order_line_item.id) as total,
  36.                        LOWER(HEX(order_customer.customer_id)) as customer_id
  37.                 FROM order_line_item
  38.                 INNER JOIN order_customer
  39.                     ON order_customer.order_id = order_line_item.order_id
  40.                     AND order_customer.version_id = order_line_item.version_id
  41.                 WHERE order_line_item.type = :type
  42.                 AND JSON_UNQUOTE(JSON_EXTRACT(`order_line_item`.`payload`, "$.promotionId")) IN (:ids)
  43.                 AND order_line_item.version_id = :versionId
  44.                 GROUP BY JSON_UNQUOTE(JSON_EXTRACT(`order_line_item`.`payload`, "$.promotionId")), order_customer.customer_id
  45. SQL;
  46.         $promotions $this->connection->fetchAll(
  47.             $sql,
  48.             ['type' => PromotionProcessor::LINE_ITEM_TYPE'ids' => $ids'versionId' => Uuid::fromHexToBytes(Defaults::LIVE_VERSION)],
  49.             ['ids' => Connection::PARAM_STR_ARRAY]
  50.         );
  51.         if (empty($promotions)) {
  52.             return;
  53.         }
  54.         $update = new RetryableQuery(
  55.             $this->connection->prepare('UPDATE promotion SET order_count = :count, orders_per_customer_count = :customerCount WHERE id = :id')
  56.         );
  57.         // group the promotions to update each promotion with a single update statement
  58.         $promotions $this->groupByPromotion($promotions);
  59.         foreach ($promotions as $id => $totals) {
  60.             $total array_sum($totals);
  61.             $update->execute([
  62.                 'id' => Uuid::fromHexToBytes($id),
  63.                 'count' => (int) $total,
  64.                 'customerCount' => json_encode($totals),
  65.             ]);
  66.         }
  67.     }
  68.     public function orderPlaced(CheckoutOrderPlacedEvent $event): void
  69.     {
  70.         $lineItems $event->getOrder()->getLineItems();
  71.         if (!$lineItems) {
  72.             return;
  73.         }
  74.         $promotionIds $lineItems
  75.             ->filterByType(PromotionProcessor::LINE_ITEM_TYPE)
  76.             ->getPayloadsProperty('promotionId');
  77.         // update redemption counts immediately
  78.         $this->update($promotionIds$event->getContext());
  79.     }
  80.     private function groupByPromotion(array $promotions): array
  81.     {
  82.         $grouped = [];
  83.         foreach ($promotions as $promotion) {
  84.             $id $promotion['promotion_id'];
  85.             $customerId $promotion['customer_id'];
  86.             $grouped[$id][$customerId] = (int) $promotion['total'];
  87.         }
  88.         return $grouped;
  89.     }
  90. }