vendor/ibexa/product-catalog/src/lib/Personalization/Event/Subscriber/ProductEventSubscriber.php line 108

Open in your IDE?
  1. <?php
  2. /**
  3.  * @copyright Copyright (C) Ibexa AS. All rights reserved.
  4.  * @license For full copyright and license information view LICENSE file distributed with this source code.
  5.  */
  6. declare(strict_types=1);
  7. namespace Ibexa\ProductCatalog\Personalization\Event\Subscriber;
  8. use Ibexa\Contracts\Core\Repository\Iterator\BatchIterator;
  9. use Ibexa\Contracts\ProductCatalog\Events\CreatePriceEvent;
  10. use Ibexa\Contracts\ProductCatalog\Events\DeletePriceEvent;
  11. use Ibexa\Contracts\ProductCatalog\Events\ExecutePriceStructsEvent;
  12. use Ibexa\Contracts\ProductCatalog\Events\UpdatePriceEvent;
  13. use Ibexa\Contracts\ProductCatalog\Iterator\BatchIteratorAdapter\VariantFetchAdapter;
  14. use Ibexa\Contracts\ProductCatalog\Local\Events\BeforeDeleteBaseProductVariantsEvent;
  15. use Ibexa\Contracts\ProductCatalog\Local\Events\CreateProductVariantsEvent;
  16. use Ibexa\Contracts\ProductCatalog\Local\Events\DeleteProductEvent;
  17. use Ibexa\Contracts\ProductCatalog\Local\Events\UpdateProductEvent;
  18. use Ibexa\Contracts\ProductCatalog\Local\Events\UpdateProductVariantEvent;
  19. use Ibexa\Contracts\ProductCatalog\Permission\Policy\Product\Delete;
  20. use Ibexa\Contracts\ProductCatalog\PermissionResolverInterface;
  21. use Ibexa\Contracts\ProductCatalog\ProductServiceInterface as APIProductServiceInterface;
  22. use Ibexa\Contracts\ProductCatalog\Values\ContentAwareProductInterface;
  23. use Ibexa\Contracts\ProductCatalog\Values\ProductInterface;
  24. use Ibexa\Contracts\ProductCatalog\Values\ProductVariantInterface;
  25. use Ibexa\Personalization\Exception\InvalidArgumentException;
  26. use Ibexa\Personalization\Service\Content\ContentServiceInterface;
  27. use Ibexa\ProductCatalog\Personalization\Service\Product\ProductServiceInterface;
  28. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  29. final class ProductEventSubscriber implements EventSubscriberInterface
  30. {
  31.     private const PRIORITY = -10;
  32.     private ContentServiceInterface $contentService;
  33.     private ProductServiceInterface $productService;
  34.     private APIProductServiceInterface $apiProductService;
  35.     private PermissionResolverInterface $permissionResolver;
  36.     public function __construct(
  37.         ContentServiceInterface $contentService,
  38.         ProductServiceInterface $productService,
  39.         APIProductServiceInterface $apiProductService,
  40.         PermissionResolverInterface $permissionResolver
  41.     ) {
  42.         $this->contentService $contentService;
  43.         $this->productService $productService;
  44.         $this->apiProductService $apiProductService;
  45.         $this->permissionResolver $permissionResolver;
  46.     }
  47.     public static function getSubscribedEvents(): array
  48.     {
  49.         return [
  50.             CreatePriceEvent::class => ['onCreatePrice'self::PRIORITY],
  51.             UpdatePriceEvent::class => ['onUpdatePrice'self::PRIORITY],
  52.             DeletePriceEvent::class => ['onDeletePrice'self::PRIORITY],
  53.             UpdateProductEvent::class => ['onUpdateProduct'self::PRIORITY],
  54.             DeleteProductEvent::class => ['onDeleteProduct'self::PRIORITY],
  55.             BeforeDeleteBaseProductVariantsEvent::class => ['onBeforeDeleteBaseProductVariants'self::PRIORITY],
  56.             CreateProductVariantsEvent::class => ['onCreateProductVariants'self::PRIORITY],
  57.             UpdateProductVariantEvent::class => ['onUpdateProductVariant'self::PRIORITY],
  58.             ExecutePriceStructsEvent::class => ['onExecutePriceStructs'self::PRIORITY],
  59.         ];
  60.     }
  61.     public function onCreatePrice(CreatePriceEvent $event): void
  62.     {
  63.         $this->sendNotificationForProduct($event->getCreateStruct()->getProduct());
  64.     }
  65.     public function onDeletePrice(DeletePriceEvent $event): void
  66.     {
  67.         $this->sendNotificationForProduct($event->getDeleteStruct()->getProduct());
  68.     }
  69.     public function onUpdateProduct(UpdateProductEvent $event): void
  70.     {
  71.         $product $event->getProduct();
  72.         if (!$product->isBaseProduct()) {
  73.             return;
  74.         }
  75.         $variantIterator = new BatchIterator(
  76.             new VariantFetchAdapter($this->apiProductService$product),
  77.             25
  78.         );
  79.         $this->productService->updateVariants(iterator_to_array($variantIterator));
  80.     }
  81.     public function onDeleteProduct(DeleteProductEvent $event): void
  82.     {
  83.         $product $event->getProduct();
  84.         if ($product->isVariant()) {
  85.             /** @var \Ibexa\Contracts\ProductCatalog\Values\ProductVariantInterface $product */
  86.             $this->sendNotificationForDeleteVariant($product);
  87.         }
  88.     }
  89.     public function onBeforeDeleteBaseProductVariants(BeforeDeleteBaseProductVariantsEvent $event): void
  90.     {
  91.         $baseProduct $event->getBaseProduct();
  92.         if (!$this->permissionResolver->canUser(new Delete($baseProduct)) || !$baseProduct->isBaseProduct()) {
  93.             return;
  94.         }
  95.         $variantIterator = new BatchIterator(
  96.             new VariantFetchAdapter($this->apiProductService$baseProduct),
  97.             25
  98.         );
  99.         $this->productService->deleteVariants(iterator_to_array($variantIterator));
  100.     }
  101.     public function onCreateProductVariants(CreateProductVariantsEvent $event): void
  102.     {
  103.         $createStructs $event->getCreateStructs();
  104.         $variants = [];
  105.         foreach ($createStructs as $createStruct) {
  106.             $code $createStruct->getCode();
  107.             if ($code === null) {
  108.                 throw new InvalidArgumentException('ProductVariant code must be provided');
  109.             }
  110.             $variants[] = $this->apiProductService->getProductVariant($code);
  111.         }
  112.         $this->productService->updateVariants($variants);
  113.     }
  114.     public function onUpdateProductVariant(UpdateProductVariantEvent $event): void
  115.     {
  116.         $productVariant $event->getProductVariant();
  117.         $this->sendNotificationForUpdateVariant($productVariant);
  118.     }
  119.     public function onUpdatePrice(UpdatePriceEvent $event): void
  120.     {
  121.         $this->sendNotificationForProduct($event->getUpdateStruct()->getProduct());
  122.     }
  123.     public function onExecutePriceStructs(ExecutePriceStructsEvent $event): void
  124.     {
  125.         $productCodes = [];
  126.         $products = [];
  127.         foreach ($event->getPriceStructs() as $struct) {
  128.             $product $struct->getProduct();
  129.             $productCode $product->getCode();
  130.             if (
  131.                 $product instanceof ContentAwareProductInterface
  132.                 && !in_array($productCode$productCodestrue)
  133.             ) {
  134.                 $productCodes[] = $productCode;
  135.                 $products[] = $product->getContent();
  136.             }
  137.         }
  138.         $this->contentService->updateContentItems($products);
  139.     }
  140.     private function sendNotificationForProduct(ProductInterface $product): void
  141.     {
  142.         if (!$product instanceof ContentAwareProductInterface) {
  143.             return;
  144.         }
  145.         $this->contentService->updateContent($product->getContent());
  146.     }
  147.     private function sendNotificationForDeleteVariant(ProductVariantInterface $productVariant): void
  148.     {
  149.         if (!$productVariant instanceof ContentAwareProductInterface) {
  150.             return;
  151.         }
  152.         $this->productService->deleteVariant($productVariant);
  153.     }
  154.     private function sendNotificationForUpdateVariant(
  155.         ProductVariantInterface $productVariant
  156.     ): void {
  157.         if (!$productVariant instanceof ContentAwareProductInterface) {
  158.             return;
  159.         }
  160.         $this->productService->updateVariant($productVariant);
  161.     }
  162. }