vendor/shopware/core/Content/Category/Service/NavigationLoader.php line 72

Open in your IDE?
  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\Search\Filter\EqualsAnyFilter;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  13. use Shopware\Core\System\Annotation\Concept\ExtensionPattern\Decoratable;
  14. use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
  15. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  16. use Symfony\Component\HttpFoundation\Request;
  17. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  18. /**
  19.  * @Decoratable()
  20.  */
  21. class NavigationLoader implements NavigationLoaderInterface
  22. {
  23.     /**
  24.      * @var SalesChannelRepositoryInterface
  25.      */
  26.     private $categoryRepository;
  27.     /**
  28.      * @var TreeItem
  29.      */
  30.     private $treeItem;
  31.     /**
  32.      * @var EventDispatcherInterface
  33.      */
  34.     private $eventDispatcher;
  35.     /**
  36.      * @var AbstractNavigationRoute
  37.      */
  38.     private $navigationRoute;
  39.     public function __construct(
  40.         SalesChannelRepositoryInterface $repository,
  41.         EventDispatcherInterface $eventDispatcher,
  42.         AbstractNavigationRoute $navigationRoute
  43.     ) {
  44.         $this->categoryRepository $repository;
  45.         $this->treeItem = new TreeItem(null, []);
  46.         $this->eventDispatcher $eventDispatcher;
  47.         $this->navigationRoute $navigationRoute;
  48.     }
  49.     /**
  50.      * {@inheritdoc}
  51.      *
  52.      * @throws CategoryNotFoundException
  53.      */
  54.     public function load(string $activeIdSalesChannelContext $contextstring $rootIdint $depth 2): Tree
  55.     {
  56.         $request = new Request();
  57.         $request->query->set('buildTree'false);
  58.         $request->query->set('depth'$depth);
  59.         $criteria = new Criteria();
  60.         $criteria->setTitle('header::navigation');
  61.         $categories $this->navigationRoute
  62.             ->load($activeId$rootId$request$context$criteria)
  63.             ->getCategories();
  64.         $navigation $this->getTree($rootId$categories$categories->get($activeId));
  65.         $event = new NavigationLoadedEvent($navigation$context);
  66.         $this->eventDispatcher->dispatch($event);
  67.         return $event->getNavigation();
  68.     }
  69.     /**
  70.      * @deprecated tag:v6.4.0 - use load with $depth 1 instead
  71.      * {@inheritdoc}
  72.      *
  73.      * @throws CategoryNotFoundException
  74.      */
  75.     public function loadLevel(string $categoryIdSalesChannelContext $context): Tree
  76.     {
  77.         $active $this->loadCategories([$categoryId], $context)
  78.             ->get($categoryId);
  79.         if (!$active) {
  80.             throw new CategoryNotFoundException($categoryId);
  81.         }
  82.         $criteria = new Criteria();
  83.         $criteria->addFilter(new EqualsFilter('category.parentId'$categoryId));
  84.         $criteria->addAssociation('media');
  85.         /** @var CategoryCollection $categories */
  86.         $categories $this->categoryRepository->search($criteria$context)->getEntities();
  87.         $categories->add($active);
  88.         $navigation $this->getTree($active->getId(), $categories$active);
  89.         $event = new NavigationLoadedEvent($navigation$context);
  90.         $this->eventDispatcher->dispatch($event);
  91.         return $event->getNavigation();
  92.     }
  93.     private function getTree(?string $parentIdCategoryCollection $categories, ?CategoryEntity $active): Tree
  94.     {
  95.         $tree $this->buildTree($parentId$categories->getElements());
  96.         return new Tree($active$tree);
  97.     }
  98.     /**
  99.      * @param CategoryEntity[] $categories
  100.      *
  101.      * @return TreeItem[]
  102.      */
  103.     private function buildTree(?string $parentId, array $categories): array
  104.     {
  105.         $children = new CategoryCollection();
  106.         foreach ($categories as $key => $category) {
  107.             if ($category->getParentId() !== $parentId) {
  108.                 continue;
  109.             }
  110.             unset($categories[$key]);
  111.             $children->add($category);
  112.         }
  113.         $children->sortByPosition();
  114.         $items = [];
  115.         foreach ($children as $child) {
  116.             if (!$child->getActive() || !$child->getVisible()) {
  117.                 continue;
  118.             }
  119.             $item = clone $this->treeItem;
  120.             $item->setCategory($child);
  121.             $item->setChildren(
  122.                 $this->buildTree($child->getId(), $categories)
  123.             );
  124.             $items[$child->getId()] = $item;
  125.         }
  126.         return $items;
  127.     }
  128.     private function loadCategories(array $idsSalesChannelContext $context): CategoryCollection
  129.     {
  130.         $criteria = new Criteria();
  131.         $criteria->addFilter(new EqualsAnyFilter('id'$ids));
  132.         $criteria->addAssociation('media');
  133.         /** @var CategoryCollection $missing */
  134.         $missing $this->categoryRepository->search($criteria$context)->getEntities();
  135.         return $missing;
  136.     }
  137. }