src/Core/Content/Category/Service/NavigationLoader.php line 49

  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\Category\Service;
  3. use Shopware\Core\Content\Category\CategoryCollection;
  4. use Shopware\Core\Content\Category\CategoryEntity;
  5. use Shopware\Core\Content\Category\Event\NavigationLoadedEvent;
  6. use Shopware\Core\Content\Category\Exception\CategoryNotFoundException;
  7. use Shopware\Core\Content\Category\SalesChannel\AbstractNavigationRoute;
  8. use Shopware\Core\Content\Category\Tree\Tree;
  9. use Shopware\Core\Content\Category\Tree\TreeItem;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Util\AfterSort;
  12. use Shopware\Core\Framework\Log\Package;
  13. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  14. use Symfony\Component\HttpFoundation\Request;
  15. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  16. #[Package('content')]
  17. class NavigationLoader implements NavigationLoaderInterface
  18. {
  19.     private readonly TreeItem $treeItem;
  20.     /**
  21.      * @internal
  22.      */
  23.     public function __construct(
  24.         private readonly EventDispatcherInterface $eventDispatcher,
  25.         private readonly AbstractNavigationRoute $navigationRoute
  26.     ) {
  27.         $this->treeItem = new TreeItem(null, []);
  28.     }
  29.     /**
  30.      * {@inheritdoc}
  31.      *
  32.      * @throws CategoryNotFoundException
  33.      */
  34.     public function load(string $activeIdSalesChannelContext $contextstring $rootIdint $depth 2): Tree
  35.     {
  36.         $request = new Request();
  37.         $request->query->set('buildTree''false');
  38.         $request->query->set('depth', (string) $depth);
  39.         $criteria = new Criteria();
  40.         $criteria->setTitle('header::navigation');
  41.         $categories $this->navigationRoute
  42.             ->load($activeId$rootId$request$context$criteria)
  43.             ->getCategories();
  44.         $navigation $this->getTree($rootId$categories$categories->get($activeId));
  45.         $event = new NavigationLoadedEvent($navigation$context);
  46.         $this->eventDispatcher->dispatch($event);
  47.         return $event->getNavigation();
  48.     }
  49.     private function getTree(?string $rootIdCategoryCollection $categories, ?CategoryEntity $active): Tree
  50.     {
  51.         $parents = [];
  52.         $items = [];
  53.         foreach ($categories as $category) {
  54.             $item = clone $this->treeItem;
  55.             $item->setCategory($category);
  56.             $parents[$category->getParentId()][$category->getId()] = $item;
  57.             $items[$category->getId()] = $item;
  58.         }
  59.         foreach ($parents as $parentId => $children) {
  60.             if (empty($parentId)) {
  61.                 continue;
  62.             }
  63.             $sorted AfterSort::sort($children);
  64.             $filtered \array_filter($sorted, static fn (TreeItem $filter) => $filter->getCategory()->getActive() && $filter->getCategory()->getVisible());
  65.             if (!isset($items[$parentId])) {
  66.                 continue;
  67.             }
  68.             $item $items[$parentId];
  69.             $item->setChildren($filtered);
  70.         }
  71.         $root $parents[$rootId] ?? [];
  72.         $root AfterSort::sort($root);
  73.         $filtered = [];
  74.         /** @var TreeItem $item */
  75.         foreach ($root as $key => $item) {
  76.             if (!$item->getCategory()->getActive() || !$item->getCategory()->getVisible()) {
  77.                 continue;
  78.             }
  79.             $filtered[$key] = $item;
  80.         }
  81.         return new Tree($active$filtered);
  82.     }
  83. }