vendor/shopware/core/Content/Category/SalesChannel/CategoryRoute.php line 99

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\Category\SalesChannel;
  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\Category\Exception\CategoryNotFoundException;
  7. use Shopware\Core\Content\Cms\DataResolver\ResolverContext\EntityResolverContext;
  8. use Shopware\Core\Content\Cms\Exception\PageNotFoundException;
  9. use Shopware\Core\Content\Cms\SalesChannel\SalesChannelCmsPageLoaderInterface;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  12. use Shopware\Core\Framework\Plugin\Exception\DecorationPatternException;
  13. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  14. use Shopware\Core\Framework\Routing\Annotation\Since;
  15. use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
  16. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  17. use Symfony\Component\HttpFoundation\Request;
  18. use Symfony\Component\Routing\Annotation\Route;
  19. /**
  20.  * @Route(defaults={"_routeScope"={"store-api"}})
  21.  */
  22. class CategoryRoute extends AbstractCategoryRoute
  23. {
  24.     public const HOME 'home';
  25.     /**
  26.      * @var SalesChannelRepositoryInterface
  27.      */
  28.     private $categoryRepository;
  29.     /**
  30.      * @var SalesChannelCmsPageLoaderInterface
  31.      */
  32.     private $cmsPageLoader;
  33.     /**
  34.      * @var CategoryDefinition
  35.      */
  36.     private $categoryDefinition;
  37.     /**
  38.      * @internal
  39.      */
  40.     public function __construct(
  41.         SalesChannelRepositoryInterface $categoryRepository,
  42.         SalesChannelCmsPageLoaderInterface $cmsPageLoader,
  43.         CategoryDefinition $categoryDefinition
  44.     ) {
  45.         $this->categoryRepository $categoryRepository;
  46.         $this->cmsPageLoader $cmsPageLoader;
  47.         $this->categoryDefinition $categoryDefinition;
  48.     }
  49.     public function getDecorated(): AbstractCategoryRoute
  50.     {
  51.         throw new DecorationPatternException(self::class);
  52.     }
  53.     /**
  54.      * @Since("6.2.0.0")
  55.      * @OA\Post(
  56.      *     path="/category/{categoryId}",
  57.      *     summary="Fetch a single category",
  58.      *     description="This endpoint returns information about the category, as well as a fully resolved (hydrated with mapping values) CMS page, if one is assigned to the category. You can pass slots which should be resolved exclusively.",
  59.      *     operationId="readCategory",
  60.      *     tags={"Store API", "Category"},
  61.      *     @OA\RequestBody(
  62.      *         @OA\JsonContent(
  63.      *             description="The product listing criteria only has an effect, if the category contains a product listing.",
  64.      *             ref="#/components/schemas/ProductListingCriteria"
  65.      *         )
  66.      *     ),
  67.      *     @OA\Parameter(
  68.      *         name="categoryId",
  69.      *         description="Identifier of the category to be fetched",
  70.      *         @OA\Schema(type="string", pattern="^[0-9a-f]{32}$"),
  71.      *         in="path",
  72.      *         required=true
  73.      *     ),
  74.      *     @OA\Parameter(
  75.      *         name="slots",
  76.      *         description="Resolves only the given slot identifiers. The identifiers have to be seperated by a '|' character",
  77.      *         @OA\Schema(type="string"),
  78.      *         in="query",
  79.      *     ),
  80.      *     @OA\Parameter(name="Api-Basic-Parameters"),
  81.      *     @OA\Response(
  82.      *          response="200",
  83.      *          description="The loaded category with cms page",
  84.      *          @OA\JsonContent(ref="#/components/schemas/Category")
  85.      *     )
  86.      * )
  87.      *
  88.      * @Route("/store-api/category/{navigationId}", name="store-api.category.detail", methods={"GET","POST"})
  89.      */
  90.     public function load(string $navigationIdRequest $requestSalesChannelContext $context): CategoryRouteResponse
  91.     {
  92.         if ($navigationId === self::HOME) {
  93.             $navigationId $context->getSalesChannel()->getNavigationCategoryId();
  94.             $request->attributes->set('navigationId'$navigationId);
  95.             $routeParams $request->attributes->get('_route_params', []);
  96.             $routeParams['navigationId'] = $navigationId;
  97.             $request->attributes->set('_route_params'$routeParams);
  98.         }
  99.         $category $this->loadCategory($navigationId$context);
  100.         if (($category->getType() === CategoryDefinition::TYPE_FOLDER
  101.                 || $category->getType() === CategoryDefinition::TYPE_LINK)
  102.             && $context->getSalesChannel()->getNavigationCategoryId() !== $navigationId
  103.         ) {
  104.             throw new CategoryNotFoundException($navigationId);
  105.         }
  106.         $pageId $category->getCmsPageId();
  107.         $slotConfig $category->getTranslation('slotConfig');
  108.         $salesChannel $context->getSalesChannel();
  109.         if ($category->getId() === $salesChannel->getNavigationCategoryId() && $salesChannel->getHomeCmsPageId()) {
  110.             $pageId $salesChannel->getHomeCmsPageId();
  111.             $slotConfig $salesChannel->getTranslation('homeSlotConfig');
  112.         }
  113.         if (!$pageId) {
  114.             return new CategoryRouteResponse($category);
  115.         }
  116.         $resolverContext = new EntityResolverContext($context$request$this->categoryDefinition$category);
  117.         $pages $this->cmsPageLoader->load(
  118.             $request,
  119.             $this->createCriteria($pageId$request),
  120.             $context,
  121.             $slotConfig,
  122.             $resolverContext
  123.         );
  124.         if (!$pages->has($pageId)) {
  125.             throw new PageNotFoundException($pageId);
  126.         }
  127.         $category->setCmsPage($pages->get($pageId));
  128.         $category->setCmsPageId($pageId);
  129.         return new CategoryRouteResponse($category);
  130.     }
  131.     private function loadCategory(string $categoryIdSalesChannelContext $context): CategoryEntity
  132.     {
  133.         $criteria = new Criteria([$categoryId]);
  134.         $criteria->setTitle('category::data');
  135.         $criteria->addAssociation('media');
  136.         $category $this->categoryRepository
  137.             ->search($criteria$context)
  138.             ->get($categoryId);
  139.         if (!$category) {
  140.             throw new CategoryNotFoundException($categoryId);
  141.         }
  142.         return $category;
  143.     }
  144.     private function createCriteria(string $pageIdRequest $request): Criteria
  145.     {
  146.         $criteria = new Criteria([$pageId]);
  147.         $criteria->setTitle('category::cms-page');
  148.         $slots $request->get('slots');
  149.         if (\is_string($slots)) {
  150.             $slots explode('|'$slots);
  151.         }
  152.         if (!empty($slots) && \is_array($slots)) {
  153.             $criteria
  154.                 ->getAssociation('sections.blocks')
  155.                 ->addFilter(new EqualsAnyFilter('slots.id'$slots));
  156.         }
  157.         return $criteria;
  158.     }
  159. }