vendor/shopware/core/Content/Product/Cart/ProductLineItemCommandValidator.php line 43

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\Product\Cart;
  3. use Doctrine\DBAL\Connection;
  4. use Shopware\Core\Checkout\Cart\LineItem\LineItem;
  5. use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemDefinition;
  6. use Shopware\Core\Content\Product\Exception\ProductLineItemDifferentIdException;
  7. use Shopware\Core\Content\Product\Exception\ProductLineItemInconsistentException;
  8. use Shopware\Core\Defaults;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\SetNullOnDeleteCommand;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\UpdateCommand;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\WriteCommand;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Write\Validation\PreWriteValidationEvent;
  13. use Shopware\Core\Framework\Uuid\Uuid;
  14. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  15. class ProductLineItemCommandValidator implements EventSubscriberInterface
  16. {
  17.     /**
  18.      * @var Connection
  19.      */
  20.     private $connection;
  21.     /**
  22.      * @internal
  23.      */
  24.     public function __construct(Connection $connection)
  25.     {
  26.         $this->connection $connection;
  27.     }
  28.     /**
  29.      * @return array<string, string|array{0: string, 1: int}|list<array{0: string, 1?: int}>>
  30.      */
  31.     public static function getSubscribedEvents()
  32.     {
  33.         return [
  34.             PreWriteValidationEvent::class => 'preValidate',
  35.         ];
  36.     }
  37.     public function preValidate(PreWriteValidationEvent $event): void
  38.     {
  39.         if ($event->getContext()->getVersionId() !== Defaults::LIVE_VERSION) {
  40.             return;
  41.         }
  42.         $products $this->findProducts($event->getCommands());
  43.         foreach ($event->getCommands() as $command) {
  44.             if ($command->getDefinition()->getClass() !== OrderLineItemDefinition::class) {
  45.                 continue;
  46.             }
  47.             if ($command instanceof SetNullOnDeleteCommand) {
  48.                 continue;
  49.             }
  50.             $payload $command->getPayload();
  51.             $lineItemId Uuid::fromBytesToHex($command->getPrimaryKey()['id']);
  52.             $productIdChanged = \array_key_exists('product_id'$payload);
  53.             $referenceIdChanged = \array_key_exists('referenced_id'$payload);
  54.             $lineItemPayload = isset($payload['payload']) ? json_decode($payload['payload'], true) : [];
  55.             $orderNumberChanged = \array_key_exists('productNumber'$lineItemPayload);
  56.             if (!$this->isProduct($products$payload$lineItemId)) {
  57.                 continue;
  58.             }
  59.             $somethingChanged $productIdChanged || $referenceIdChanged || $orderNumberChanged;
  60.             $allChanged $productIdChanged && $referenceIdChanged && $orderNumberChanged;
  61.             // has a field changed?
  62.             if (!$somethingChanged) {
  63.                 continue;
  64.             }
  65.             $productId = isset($payload['product_id']) ? Uuid::fromBytesToHex($payload['product_id']) : null;
  66.             $referenceId $payload['referenced_id'] ?? null;
  67.             if ($productId !== $referenceId) {
  68.                 $event->getExceptions()->add(
  69.                     new ProductLineItemDifferentIdException($lineItemId)
  70.                 );
  71.             }
  72.             // all fields updated? everything is consistent
  73.             if ($allChanged) {
  74.                 continue;
  75.             }
  76.             $event->getExceptions()->add(
  77.                 new ProductLineItemInconsistentException($lineItemId)
  78.             );
  79.         }
  80.     }
  81.     private function findProducts(array $commands)
  82.     {
  83.         $ids array_map(function (WriteCommand $command) {
  84.             if ($command->getDefinition()->getClass() !== OrderLineItemDefinition::class) {
  85.                 return null;
  86.             }
  87.             if ($command instanceof UpdateCommand) {
  88.                 return $command->getPrimaryKey()['id'];
  89.             }
  90.             return null;
  91.         }, $commands);
  92.         $ids array_values(array_filter($ids));
  93.         if (empty($ids)) {
  94.             return $ids;
  95.         }
  96.         $products $this->connection->fetchAll(
  97.             'SELECT LOWER(HEX(id)) as id FROM order_line_item WHERE id IN (:ids) AND type = \'product\'',
  98.             ['ids' => $ids],
  99.             ['ids' => Connection::PARAM_STR_ARRAY]
  100.         );
  101.         return array_flip(array_column($products'id'));
  102.     }
  103.     private function isProduct(array $products, array $payloadstring $lineItemId): bool
  104.     {
  105.         if (isset($payload['type'])) {
  106.             return $payload['type'] === LineItem::PRODUCT_LINE_ITEM_TYPE;
  107.         }
  108.         return isset($products[$lineItemId]);
  109.     }
  110. }