vendor/shopware/core/Checkout/Customer/Subscriber/CustomerMetaFieldSubscriber.php line 41

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Checkout\Customer\Subscriber;
  3. use Doctrine\DBAL\Connection;
  4. use Shopware\Core\Checkout\Order\OrderDefinition;
  5. use Shopware\Core\Checkout\Order\OrderStates;
  6. use Shopware\Core\Defaults;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Doctrine\RetryableQuery;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\DeleteCommand;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Write\Validation\PreWriteValidationEvent;
  10. use Shopware\Core\Framework\Log\Package;
  11. use Shopware\Core\Framework\Uuid\Uuid;
  12. use Shopware\Core\System\StateMachine\Event\StateMachineTransitionEvent;
  13. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  14. /**
  15.  * @deprecated tag:v6.5.0 - reason:becomes-internal - EventSubscribers will become internal in v6.5.0
  16.  */
  17. #[Package('customer-order')]
  18. class CustomerMetaFieldSubscriber implements EventSubscriberInterface
  19. {
  20.     private Connection $connection;
  21.     /**
  22.      * @internal
  23.      */
  24.     public function __construct(Connection $connection)
  25.     {
  26.         $this->connection $connection;
  27.     }
  28.     public static function getSubscribedEvents(): array
  29.     {
  30.         return [
  31.             StateMachineTransitionEvent::class => 'fillCustomerMetaDataFields',
  32.             PreWriteValidationEvent::class => 'deleteOrder',
  33.         ];
  34.     }
  35.     public function fillCustomerMetaDataFields(StateMachineTransitionEvent $event): void
  36.     {
  37.         if ($event->getContext()->getVersionId() !== Defaults::LIVE_VERSION) {
  38.             return;
  39.         }
  40.         if ($event->getEntityName() !== 'order') {
  41.             return;
  42.         }
  43.         if ($event->getToPlace()->getTechnicalName() !== OrderStates::STATE_COMPLETED && $event->getFromPlace()->getTechnicalName() !== OrderStates::STATE_COMPLETED) {
  44.             return;
  45.         }
  46.         $this->updateCustomer([$event->getEntityId()]);
  47.     }
  48.     public function deleteOrder(PreWriteValidationEvent $event): void
  49.     {
  50.         if ($event->getContext()->getVersionId() !== Defaults::LIVE_VERSION) {
  51.             return;
  52.         }
  53.         $orderIds = [];
  54.         foreach ($event->getCommands() as $command) {
  55.             if ($command->getDefinition()->getClass() === OrderDefinition::class
  56.                 && $command instanceof DeleteCommand
  57.             ) {
  58.                 $orderIds[] = Uuid::fromBytesToHex($command->getPrimaryKey()['id']);
  59.             }
  60.         }
  61.         $this->updateCustomer($orderIdstrue);
  62.     }
  63.     /**
  64.      * @param array<string> $orderIds
  65.      */
  66.     private function updateCustomer(array $orderIdsbool $isDelete false): void
  67.     {
  68.         if (empty($orderIds)) {
  69.             return;
  70.         }
  71.         $customerIds $this->connection->fetchFirstColumn(
  72.             'SELECT DISTINCT LOWER(HEX(customer_id)) FROM `order_customer` WHERE order_id IN (:ids) AND order_version_id = :version AND customer_id IS NOT NULL',
  73.             ['ids' => Uuid::fromHexToBytesList($orderIds), 'version' => Uuid::fromHexToBytes(Defaults::LIVE_VERSION)],
  74.             ['ids' => Connection::PARAM_STR_ARRAY]
  75.         );
  76.         if (empty($customerIds)) {
  77.             return;
  78.         }
  79.         $parameters = [
  80.             'customerIds' => Uuid::fromHexToBytesList($customerIds),
  81.             'version' => Uuid::fromHexToBytes(Defaults::LIVE_VERSION),
  82.             'state' => OrderStates::STATE_COMPLETED,
  83.         ];
  84.         $types = [
  85.             'customerIds' => Connection::PARAM_STR_ARRAY,
  86.         ];
  87.         $whereOrder '';
  88.         if ($isDelete) {
  89.             $whereOrder 'AND `order`.id NOT IN (:exceptOrderIds)';
  90.             $parameters['exceptOrderIds'] = Uuid::fromHexToBytesList($orderIds);
  91.             $types['exceptOrderIds'] = Connection::PARAM_STR_ARRAY;
  92.         }
  93.         $select '
  94.             SELECT `order_customer`.customer_id as id,
  95.                    COUNT(`order`.id) as order_count,
  96.                    SUM(`order`.amount_total) as order_total_amount,
  97.                    MAX(`order`.order_date_time) as last_order_date
  98.             FROM `order_customer`
  99.             INNER JOIN `order`
  100.                 ON `order`.id = `order_customer`.order_id
  101.                 AND `order`.version_id = `order_customer`.order_version_id
  102.                 AND `order`.version_id = :version
  103.                 ' $whereOrder '
  104.             INNER JOIN `state_machine_state`
  105.                 ON `state_machine_state`.id = `order`.state_id
  106.                 AND `state_machine_state`.technical_name = :state
  107.             WHERE `order_customer`.customer_id IN (:customerIds)
  108.             GROUP BY `order_customer`.customer_id
  109.         ';
  110.         $data $this->connection->fetchAllAssociative($select$parameters$types);
  111.         if (empty($data)) {
  112.             foreach ($customerIds as $customerId) {
  113.                 $data[] = [
  114.                     'id' => Uuid::fromHexToBytes($customerId),
  115.                     'order_count' => 0,
  116.                     'order_total_amount' => 0,
  117.                     'last_order_date' => null,
  118.                 ];
  119.             }
  120.         }
  121.         $update = new RetryableQuery(
  122.             $this->connection,
  123.             $this->connection->prepare('UPDATE `customer` SET order_count = :order_count, order_total_amount = :order_total_amount, last_order_date = :last_order_date WHERE id = :id')
  124.         );
  125.         foreach ($data as $record) {
  126.             $update->execute($record);
  127.         }
  128.     }
  129. }