vendor/shopware/core/Content/Category/SalesChannel/TreeBuildingNavigationRoute.php line 102

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\CategoryCollection;
  5. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  6. use Shopware\Core\Framework\Routing\Annotation\Entity;
  7. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  8. use Shopware\Core\Framework\Routing\Annotation\Since;
  9. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  10. use Shopware\Core\System\SalesChannel\SalesChannelEntity;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\Routing\Annotation\Route;
  13. /**
  14.  * @Route(defaults={"_routeScope"={"store-api"}})
  15.  */
  16. class TreeBuildingNavigationRoute extends AbstractNavigationRoute
  17. {
  18.     private AbstractNavigationRoute $decorated;
  19.     /**
  20.      * @internal
  21.      */
  22.     public function __construct(AbstractNavigationRoute $decorated)
  23.     {
  24.         $this->decorated $decorated;
  25.     }
  26.     public function getDecorated(): AbstractNavigationRoute
  27.     {
  28.         return $this->decorated;
  29.     }
  30.     /**
  31.      * @Since("6.2.0.0")
  32.      * @Entity("category")
  33.      * @OA\Post(
  34.      *      path="/navigation/{requestActiveId}/{requestRootId}",
  35.      *      summary="Fetch a navigation menu",
  36.      *      description="This endpoint returns categories that can be used as a page navigation. You can either return them as a tree or as a flat list. You can also control the depth of the tree.
  37.     Instead of passing uuids, you can also use one of the following aliases for the activeId and rootId parameters to get the respective navigations of your sales channel.
  38.      * main-navigation
  39.      * service-navigation
  40.      * footer-navigation",
  41.      *      operationId="readNavigation",
  42.      *      tags={"Store API", "Category"},
  43.      *      @OA\Parameter(name="Api-Basic-Parameters"),
  44.      *      @OA\Parameter(
  45.      *          name="sw-include-seo-urls",
  46.      *          description="Instructs Shopware to try and resolve SEO URLs for the given navigation item",
  47.      *          @OA\Schema(type="boolean"),
  48.      *          in="header",
  49.      *          required=false
  50.      *      ),
  51.      *      @OA\Parameter(
  52.      *          name="requestActiveId",
  53.      *          description="Identifier of the active category in the navigation tree (if not used, just set to the same as rootId).",
  54.      *          @OA\Schema(type="string", pattern="^[0-9a-f]{32}$"),
  55.      *          in="path",
  56.      *          required=true
  57.      *      ),
  58.      *      @OA\Parameter(
  59.      *          name="requestRootId",
  60.      *          description="Identifier of the root category for your desired navigation tree. You can use it to fetch sub-trees of your navigation tree.",
  61.      *          @OA\Schema(type="string", pattern="^[0-9a-f]{32}$"),
  62.      *          in="path",
  63.      *          required=true
  64.      *      ),
  65.      *      @OA\RequestBody(
  66.      *          required=true,
  67.      *          @OA\JsonContent(
  68.      *              @OA\Property(
  69.      *                  property="depth",
  70.      *                  description="Determines the depth of fetched navigation levels.",
  71.      *                  @OA\Schema(type="integer", default="2")
  72.      *              ),
  73.      *              @OA\Property(
  74.      *                  property="buildTree",
  75.      *                  description="Return the categories as a tree or as a flat list.",
  76.      *                  @OA\Schema(type="boolean", default="true")
  77.      *              )
  78.      *          )
  79.      *      ),
  80.      *      @OA\Response(
  81.      *          response="200",
  82.      *          description="All available navigations",
  83.      *          @OA\JsonContent(ref="#/components/schemas/NavigationRouteResponse")
  84.      *     )
  85.      * )
  86.      * @Route("/store-api/navigation/{activeId}/{rootId}", name="store-api.navigation", methods={"GET", "POST"})
  87.      */
  88.     public function load(string $activeIdstring $rootIdRequest $requestSalesChannelContext $contextCriteria $criteria): NavigationRouteResponse
  89.     {
  90.         $activeId $this->resolveAliasId($activeId$context->getSalesChannel());
  91.         $rootId $this->resolveAliasId($rootId$context->getSalesChannel());
  92.         $response $this->getDecorated()->load($activeId$rootId$request$context$criteria);
  93.         $buildTree $request->query->getBoolean('buildTree'$request->request->getBoolean('buildTree'true));
  94.         if (!$buildTree) {
  95.             return $response;
  96.         }
  97.         $categories $this->buildTree($rootId$response->getCategories()->getElements());
  98.         return new NavigationRouteResponse($categories);
  99.     }
  100.     private function buildTree(?string $parentId, array $categories): CategoryCollection
  101.     {
  102.         $children = new CategoryCollection();
  103.         foreach ($categories as $key => $category) {
  104.             if ($category->getParentId() !== $parentId) {
  105.                 continue;
  106.             }
  107.             unset($categories[$key]);
  108.             $children->add($category);
  109.         }
  110.         $children->sortByPosition();
  111.         $items = new CategoryCollection();
  112.         foreach ($children as $child) {
  113.             if (!$child->getActive() || !$child->getVisible()) {
  114.                 continue;
  115.             }
  116.             $child->setChildren($this->buildTree($child->getId(), $categories));
  117.             $items->add($child);
  118.         }
  119.         return $items;
  120.     }
  121.     private function resolveAliasId(string $idSalesChannelEntity $salesChannelEntity): string
  122.     {
  123.         switch ($id) {
  124.             case 'main-navigation':
  125.                 return $salesChannelEntity->getNavigationCategoryId();
  126.             case 'service-navigation':
  127.                 if ($salesChannelEntity->getServiceCategoryId() === null) {
  128.                     throw new \RuntimeException(\sprintf('Service category, for sales channel %s, is not set'$salesChannelEntity->getTranslation('name')));
  129.                 }
  130.                 return $salesChannelEntity->getServiceCategoryId();
  131.             case 'footer-navigation':
  132.                 if ($salesChannelEntity->getFooterCategoryId() === null) {
  133.                     throw new \RuntimeException('Footer category, for sales channel %s, is not set'$salesChannelEntity->getTranslation('name'));
  134.                 }
  135.                 return $salesChannelEntity->getFooterCategoryId();
  136.             default:
  137.                 return $id;
  138.         }
  139.     }
  140. }