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

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.     public function __construct(Connection $connection)
  22.     {
  23.         $this->connection $connection;
  24.     }
  25.     /**
  26.      * @return array<string, string|array{0: string, 1: int}|list<array{0: string, 1?: int}>>
  27.      */
  28.     public static function getSubscribedEvents()
  29.     {
  30.         return [
  31.             PreWriteValidationEvent::class => 'preValidate',
  32.         ];
  33.     }
  34.     public function preValidate(PreWriteValidationEvent $event): void
  35.     {
  36.         if ($event->getContext()->getVersionId() !== Defaults::LIVE_VERSION) {
  37.             return;
  38.         }
  39.         $products $this->findProducts($event->getCommands());
  40.         foreach ($event->getCommands() as $command) {
  41.             if ($command->getDefinition()->getClass() !== OrderLineItemDefinition::class) {
  42.                 continue;
  43.             }
  44.             if ($command instanceof SetNullOnDeleteCommand) {
  45.                 continue;
  46.             }
  47.             $payload $command->getPayload();
  48.             $lineItemId Uuid::fromBytesToHex($command->getPrimaryKey()['id']);
  49.             $productIdChanged = \array_key_exists('product_id'$payload);
  50.             $referenceIdChanged = \array_key_exists('referenced_id'$payload);
  51.             $lineItemPayload = isset($payload['payload']) ? json_decode($payload['payload'], true) : [];
  52.             $orderNumberChanged = \array_key_exists('productNumber'$lineItemPayload);
  53.             if (!$this->isProduct($products$payload$lineItemId)) {
  54.                 continue;
  55.             }
  56.             $somethingChanged $productIdChanged || $referenceIdChanged || $orderNumberChanged;
  57.             $allChanged $productIdChanged && $referenceIdChanged && $orderNumberChanged;
  58.             // has a field changed?
  59.             if (!$somethingChanged) {
  60.                 continue;
  61.             }
  62.             $productId = isset($payload['product_id']) ? Uuid::fromBytesToHex($payload['product_id']) : null;
  63.             $referenceId $payload['referenced_id'] ?? null;
  64.             if ($productId !== $referenceId) {
  65.                 $event->getExceptions()->add(
  66.                     new ProductLineItemDifferentIdException($lineItemId)
  67.                 );
  68.             }
  69.             // all fields updated? everything is consistent
  70.             if ($allChanged) {
  71.                 continue;
  72.             }
  73.             $event->getExceptions()->add(
  74.                 new ProductLineItemInconsistentException($lineItemId)
  75.             );
  76.         }
  77.     }
  78.     private function findProducts(array $commands)
  79.     {
  80.         $ids array_map(function (WriteCommand $command) {
  81.             if ($command->getDefinition()->getClass() !== OrderLineItemDefinition::class) {
  82.                 return null;
  83.             }
  84.             if ($command instanceof UpdateCommand) {
  85.                 return $command->getPrimaryKey()['id'];
  86.             }
  87.             return null;
  88.         }, $commands);
  89.         $ids array_values(array_filter($ids));
  90.         $products $this->connection->fetchAll(
  91.             'SELECT LOWER(HEX(id)) as id FROM order_line_item WHERE id IN (:ids) AND type = \'product\'',
  92.             ['ids' => $ids],
  93.             ['ids' => Connection::PARAM_STR_ARRAY]
  94.         );
  95.         return array_flip(array_column($products'id'));
  96.     }
  97.     private function isProduct(array $products, array $payloadstring $lineItemId): bool
  98.     {
  99.         if (isset($payload['type'])) {
  100.             return $payload['type'] === LineItem::PRODUCT_LINE_ITEM_TYPE;
  101.         }
  102.         return isset($products[$lineItemId]);
  103.     }
  104. }