vendor/shopware/core/Content/Product/SalesChannel/Listing/ProductListingRoute.php line 93

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\Product\SalesChannel\Listing;
  3. use OpenApi\Annotations as OA;
  4. use Shopware\Core\Content\Category\CategoryDefinition;
  5. use Shopware\Core\Content\Category\CategoryEntity;
  6. use Shopware\Core\Content\Product\Aggregate\ProductVisibility\ProductVisibilityDefinition;
  7. use Shopware\Core\Content\Product\Events\ProductListingResultEvent;
  8. use Shopware\Core\Content\Product\SalesChannel\ProductAvailableFilter;
  9. use Shopware\Core\Content\ProductStream\Service\ProductStreamBuilderInterface;
  10. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  13. use Shopware\Core\Framework\Plugin\Exception\DecorationPatternException;
  14. use Shopware\Core\Framework\Routing\Annotation\Entity;
  15. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  16. use Shopware\Core\Framework\Routing\Annotation\Since;
  17. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  18. use Symfony\Component\HttpFoundation\Request;
  19. use Symfony\Component\Routing\Annotation\Route;
  20. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  21. /**
  22.  * @Route(defaults={"_routeScope"={"store-api"}})
  23.  */
  24. class ProductListingRoute extends AbstractProductListingRoute
  25. {
  26.     /**
  27.      * @var ProductListingLoader
  28.      */
  29.     private $listingLoader;
  30.     /**
  31.      * @var EventDispatcherInterface
  32.      */
  33.     private $eventDispatcher;
  34.     /**
  35.      * @var EntityRepositoryInterface
  36.      */
  37.     private $categoryRepository;
  38.     /**
  39.      * @var ProductStreamBuilderInterface
  40.      */
  41.     private $productStreamBuilder;
  42.     /**
  43.      * @internal
  44.      */
  45.     public function __construct(
  46.         ProductListingLoader $listingLoader,
  47.         EventDispatcherInterface $eventDispatcher,
  48.         EntityRepositoryInterface $categoryRepository,
  49.         ProductStreamBuilderInterface $productStreamBuilder
  50.     ) {
  51.         $this->eventDispatcher $eventDispatcher;
  52.         $this->listingLoader $listingLoader;
  53.         $this->categoryRepository $categoryRepository;
  54.         $this->productStreamBuilder $productStreamBuilder;
  55.     }
  56.     public function getDecorated(): AbstractProductListingRoute
  57.     {
  58.         throw new DecorationPatternException(self::class);
  59.     }
  60.     /**
  61.      * @Since("6.2.0.0")
  62.      * @Entity("product")
  63.      * @OA\Post(
  64.      *      path="/product-listing/{categoryId}",
  65.      *      summary="Fetch a product listing by category",
  66.      *      description="Fetches a product listing for a specific category. It also provides filters, sortings and property aggregations, analogous to the /search endpoint.",
  67.      *      operationId="readProductListing",
  68.      *      tags={"Store API","Product"},
  69.      *      @OA\Parameter(
  70.      *          name="categoryId",
  71.      *          description="Identifier of a category.",
  72.      *          @OA\Schema(type="string"),
  73.      *          in="path",
  74.      *          required=true
  75.      *      ),
  76.      *      @OA\Response(
  77.      *          response="200",
  78.      *          description="Returns a product listing containing all products and additional fields to display a listing.",
  79.      *          @OA\JsonContent(ref="#/components/schemas/ProductListingResult")
  80.      *     )
  81.      * )
  82.      * @Route("/store-api/product-listing/{categoryId}", name="store-api.product.listing", methods={"POST"})
  83.      */
  84.     public function load(string $categoryIdRequest $requestSalesChannelContext $contextCriteria $criteria): ProductListingRouteResponse
  85.     {
  86.         $criteria->addFilter(
  87.             new ProductAvailableFilter($context->getSalesChannel()->getId(), ProductVisibilityDefinition::VISIBILITY_ALL)
  88.         );
  89.         $criteria->setTitle('product-listing-route::loading');
  90.         $categoryCriteria = new Criteria([$categoryId]);
  91.         $categoryCriteria->setTitle('product-listing-route::category-loading');
  92.         /** @var CategoryEntity $category */
  93.         $category $this->categoryRepository->search($categoryCriteria$context->getContext())->first();
  94.         $streamId $this->extendCriteria($context$criteria$category);
  95.         $entities $this->listingLoader->load($criteria$context);
  96.         /** @var ProductListingResult $result */
  97.         $result ProductListingResult::createFrom($entities);
  98.         $result->addState(...$entities->getStates());
  99.         $result->addCurrentFilter('navigationId'$categoryId);
  100.         $this->eventDispatcher->dispatch(
  101.             new ProductListingResultEvent($request$result$context)
  102.         );
  103.         $result->setStreamId($streamId);
  104.         return new ProductListingRouteResponse($result);
  105.     }
  106.     private function extendCriteria(SalesChannelContext $salesChannelContextCriteria $criteriaCategoryEntity $category): ?string
  107.     {
  108.         if ($category->getProductAssignmentType() === CategoryDefinition::PRODUCT_ASSIGNMENT_TYPE_PRODUCT_STREAM && $category->getProductStreamId() !== null) {
  109.             $filters $this->productStreamBuilder->buildFilters(
  110.                 $category->getProductStreamId(),
  111.                 $salesChannelContext->getContext()
  112.             );
  113.             $criteria->addFilter(...$filters);
  114.             return $category->getProductStreamId();
  115.         }
  116.         $criteria->addFilter(
  117.             new EqualsFilter('product.categoriesRo.id'$category->getId())
  118.         );
  119.         return null;
  120.     }
  121. }