platform/src/Core/Content/Product/Cart/ProductLineItemCommandValidator.php line 37

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