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

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