custom/plugins/SEMKNOX/src/Content/SiteSearchCategoryRoute.php line 138

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace semknox\search\Content;
  3. use OpenApi\Annotations as OA;
  4. use semknox\search\Framework\SemknoxsearchHelper;
  5. use Shopware\Core\Content\Category\CategoryDefinition;
  6. use Shopware\Core\Content\Category\CategoryEntity;
  7. use Shopware\Core\Content\Category\Exception\CategoryNotFoundException;
  8. use Shopware\Core\Content\Category\SalesChannel\AbstractCategoryRoute;
  9. use Shopware\Core\Content\Category\SalesChannel\CategoryRouteResponse;
  10. use Shopware\Core\Content\Cms\DataResolver\ResolverContext\EntityResolverContext;
  11. use Shopware\Core\Content\Cms\Exception\PageNotFoundException;
  12. use Shopware\Core\Content\Cms\SalesChannel\SalesChannelCmsPageLoaderInterface;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  15. use Shopware\Core\Framework\Plugin\Exception\DecorationPatternException;
  16. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  17. use Shopware\Core\Framework\Routing\Annotation\Since;
  18. use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
  19. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  20. use Symfony\Component\HttpFoundation\Request;
  21. use Symfony\Component\Routing\Annotation\Route;
  22. use Shopware\Core\Framework\Struct\ArrayEntity;
  23. use Shopware\Core\Content\Category\SalesChannel\CategoryRoute;
  24. /**
  25.  * @RouteScope(scopes={"store-api"})
  26.  */
  27. class SiteSearchCategoryRoute extends AbstractCategoryRoute
  28. {
  29.     public const HOME 'home';
  30.     /**
  31.      * @var SalesChannelRepositoryInterface
  32.      */
  33.     private $categoryRepository;
  34.     /**
  35.      * @var SalesChannelCmsPageLoaderInterface
  36.      */
  37.     private $cmsPageLoader;
  38.     /**
  39.      * @var CategoryDefinition
  40.      */
  41.     private $categoryDefinition;
  42.     /**
  43.      * @var SemknoxsearchHelper
  44.      */
  45.     private $helper;
  46.     /**
  47.      *
  48.      * @var CategoryRoute
  49.      */
  50.     private $decorated;
  51.     public function __construct(
  52.         SalesChannelRepositoryInterface $categoryRepository,
  53.         SalesChannelCmsPageLoaderInterface $cmsPageLoader,
  54.         CategoryDefinition $categoryDefinition,
  55.         SemknoxsearchHelper $helper,
  56.         CategoryRoute $deco
  57.     ) {
  58.         $this->categoryRepository $categoryRepository;
  59.         $this->cmsPageLoader $cmsPageLoader;
  60.         $this->categoryDefinition $categoryDefinition;
  61.         $this->helper $helper;        
  62.         $this->decorated $deco;
  63.     }
  64.     public function getDecorated(): AbstractCategoryRoute
  65.     {
  66.         throw new DecorationPatternException(self::class);
  67.     }
  68.     /**
  69.      * @Since("6.2.0.0")
  70.      * @OA\Post(
  71.      *     path="/category/{categoryId}",
  72.      *     summary="Fetch a single category",
  73.      *     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.",
  74.      *     operationId="readCategory",
  75.      *     tags={"Store API", "Category"},
  76.      *     @OA\RequestBody(
  77.      *         @OA\JsonContent(
  78.      *             description="The product listing criteria only has an effect, if the category contains a product listing.",
  79.      *             ref="#/components/schemas/ProductListingCriteria"
  80.      *         )
  81.      *     ),
  82.      *     @OA\Parameter(
  83.      *         name="categoryId",
  84.      *         description="Identifier of the category to be fetched",
  85.      *         @OA\Schema(type="string", pattern="^[0-9a-f]{32}$"),
  86.      *         in="path",
  87.      *         required=true
  88.      *     ),
  89.      *     @OA\Parameter(
  90.      *         name="slots",
  91.      *         description="Resolves only the given slot identifiers. The identifiers have to be seperated by a '|' character",
  92.      *         @OA\Schema(type="string"),
  93.      *         in="query",
  94.      *     ),
  95.      *     @OA\Parameter(name="Api-Basic-Parameters"),
  96.      *     @OA\Response(
  97.      *          response="200",
  98.      *          description="The loaded category with cms page",
  99.      *          @OA\JsonContent(ref="#/components/schemas/Category")
  100.      *     )
  101.      * )
  102.      *
  103.      * @Route("/store-api/category/{navigationId}", name="store-api.category.detail", methods={"GET","POST"})
  104.      */
  105.     public function load(string $navigationIdRequest $requestSalesChannelContext $context): CategoryRouteResponse
  106.     {
  107.         if ($navigationId === self::HOME) {
  108.             $navigationId $context->getSalesChannel()->getNavigationCategoryId();
  109.             $request->attributes->set('navigationId'$navigationId);
  110.             $routeParams $request->attributes->get('_route_params', []);
  111.             $routeParams['navigationId'] = $navigationId;
  112.             $request->attributes->set('_route_params'$routeParams);
  113.         }
  114.         $category $this->loadCategory($navigationId$context);
  115.         if (($category->getType() === CategoryDefinition::TYPE_FOLDER
  116.                 || $category->getType() === CategoryDefinition::TYPE_LINK)
  117.             && $context->getSalesChannel()->getNavigationCategoryId() !== $navigationId
  118.         ) {
  119.             throw new CategoryNotFoundException($navigationId);
  120.         }
  121.         $pageId $category->getCmsPageId();
  122.         $slotConfig $category->getTranslation('slotConfig');
  123.         $salesChannel $context->getSalesChannel();
  124.         if ($category->getId() === $salesChannel->getNavigationCategoryId() && $salesChannel->getHomeCmsPageId()) {
  125.             $pageId $salesChannel->getHomeCmsPageId();
  126.             $slotConfig $salesChannel->getTranslation('homeSlotConfig');
  127.         }
  128.         if (!$pageId) {
  129.             return new CategoryRouteResponse($category);
  130.         }
  131.         $resolverContext = new EntityResolverContext($context$request$this->categoryDefinition$category);
  132.         $foundBreadcrumb 0;
  133.         $newCriteria $this->createCriteria($pageId$request$category$context$foundBreadcrumb);
  134.         if ($foundBreadcrumb<=0) { 
  135.             return $this->decorated->load($navigationId$request$context);
  136.         }
  137.         $pages $this->cmsPageLoader->load(
  138.             $request,
  139.             $newCriteria,
  140.             $context,
  141.             $slotConfig,
  142.             $resolverContext
  143.         );
  144.         if (!$pages->has($pageId)) {
  145.             throw new PageNotFoundException($pageId);
  146.         }
  147.         $category->setCmsPage($pages->get($pageId));
  148.         $category->setCmsPageId($pageId);
  149.         return new CategoryRouteResponse($category);
  150.     }
  151.     private function loadCategory(string $categoryIdSalesChannelContext $context): CategoryEntity
  152.     {
  153.         $criteria = new Criteria([$categoryId]);
  154.         $criteria->setTitle('category::data');
  155.         $criteria->addAssociation('media');
  156.         $category $this->categoryRepository
  157.             ->search($criteria$context)
  158.             ->get($categoryId);
  159.         if (!$category) {
  160.             throw new CategoryNotFoundException($categoryId);
  161.         }
  162.         return $category;
  163.     }
  164.     private function createCriteria(string $pageIdRequest $requestCategoryEntity $category$contextint &$foundBreadcrumb): Criteria
  165.     {
  166.         $foundBreadcrumb 0;
  167.         $criteria = new Criteria([$pageId]);
  168.         $criteria->setTitle('category::cms-page');
  169.         $slots $request->get('slots');
  170.         if (\is_string($slots)) {
  171.             $slots explode('|'$slots);
  172.         }
  173.         if (!empty($slots) && \is_array($slots)) {
  174.             $criteria
  175.                  ->getAssociation('sections.blocks')
  176.                 ->addFilter(new EqualsAnyFilter('slots.id'$slots));
  177.         }
  178.         $bc $category->getBreadcrumb();
  179.         if (count($bc)) {
  180.             $foundBreadcrumb 1;
  181.             $term "_#".implode('#',str_replace('#''\#'$bc));
  182.             $scID=$this->helper->getSalesChannelFromSCContext($context);
  183.             $langID $this->helper->getLanguageFromSCContext($context);
  184.             $domainID $this->helper->getDomainFromSCContext($context);
  185.             $contr 'siteSearchCMSController';
  186.             $criteria->addExtension('semknoxData', new ArrayEntity(
  187.                 [
  188.                     'salesChannelID' => $scID,
  189.                     'languageID' => $langID,
  190.                     'domainID' => $domainID,
  191.                     'controller' => $contr,
  192.                     'term' => $term
  193.                 ]
  194.                 ));
  195.         }
  196.         return $criteria;
  197.     }
  198. }