- <?php declare(strict_types=1);
- namespace Shopware\Core\Content\Category\Service;
- use Shopware\Core\Content\Category\CategoryCollection;
- use Shopware\Core\Content\Category\CategoryEntity;
- use Shopware\Core\Content\Category\Event\NavigationLoadedEvent;
- use Shopware\Core\Content\Category\Exception\CategoryNotFoundException;
- use Shopware\Core\Content\Category\SalesChannel\AbstractNavigationRoute;
- use Shopware\Core\Content\Category\Tree\Tree;
- use Shopware\Core\Content\Category\Tree\TreeItem;
- use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
- use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
- use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
- use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
- use Shopware\Core\System\SalesChannel\SalesChannelContext;
- use Symfony\Component\HttpFoundation\Request;
- use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
- class NavigationLoader implements NavigationLoaderInterface
- {
-     /**
-      * @var SalesChannelRepositoryInterface
-      */
-     private $categoryRepository;
-     /**
-      * @var TreeItem
-      */
-     private $treeItem;
-     /**
-      * @var EventDispatcherInterface
-      */
-     private $eventDispatcher;
-     /**
-      * @var AbstractNavigationRoute
-      */
-     private $navigationRoute;
-     public function __construct(
-         SalesChannelRepositoryInterface $repository,
-         EventDispatcherInterface $eventDispatcher,
-         AbstractNavigationRoute $navigationRoute
-     ) {
-         $this->categoryRepository = $repository;
-         $this->treeItem = new TreeItem(null, []);
-         $this->eventDispatcher = $eventDispatcher;
-         $this->navigationRoute = $navigationRoute;
-     }
-     /**
-      * {@inheritdoc}
-      *
-      * @throws CategoryNotFoundException
-      */
-     public function load(string $activeId, SalesChannelContext $context, string $rootId, int $depth = 2): Tree
-     {
-         $request = new Request();
-         $request->query->set('buildTree', false);
-         $request->query->set('depth', $depth);
-         $categories = $this->navigationRoute->load($activeId, $rootId, $request, $context)->getCategories();
-         $navigation = $this->getTree($rootId, $categories, $categories->get($activeId));
-         $event = new NavigationLoadedEvent($navigation, $context);
-         $this->eventDispatcher->dispatch($event);
-         return $event->getNavigation();
-     }
-     /**
-      * {@inheritdoc}
-      *
-      * @throws CategoryNotFoundException
-      */
-     public function loadLevel(string $categoryId, SalesChannelContext $context): Tree
-     {
-         $active = $this->loadCategories([$categoryId], $context)
-             ->get($categoryId);
-         if (!$active) {
-             throw new CategoryNotFoundException($categoryId);
-         }
-         $criteria = new Criteria();
-         $criteria->addFilter(new EqualsFilter('category.parentId', $categoryId));
-         $criteria->addAssociation('media');
-         /** @var CategoryCollection $categories */
-         $categories = $this->categoryRepository->search($criteria, $context)->getEntities();
-         $categories->add($active);
-         $navigation = $this->getTree($active->getId(), $categories, $active);
-         $event = new NavigationLoadedEvent($navigation, $context);
-         $this->eventDispatcher->dispatch($event);
-         return $event->getNavigation();
-     }
-     private function getTree(?string $parentId, CategoryCollection $categories, ?CategoryEntity $active): Tree
-     {
-         $tree = $this->buildTree($parentId, $categories->getElements());
-         return new Tree($active, $tree);
-     }
-     /**
-      * @param CategoryEntity[] $categories
-      *
-      * @return TreeItem[]
-      */
-     private function buildTree(?string $parentId, array $categories): array
-     {
-         $children = new CategoryCollection();
-         foreach ($categories as $key => $category) {
-             if ($category->getParentId() !== $parentId) {
-                 continue;
-             }
-             unset($categories[$key]);
-             $children->add($category);
-         }
-         $children->sortByPosition();
-         $items = [];
-         foreach ($children as $child) {
-             if (!$child->getActive() || !$child->getVisible()) {
-                 continue;
-             }
-             $item = clone $this->treeItem;
-             $item->setCategory($child);
-             $item->setChildren(
-                 $this->buildTree($child->getId(), $categories)
-             );
-             $items[$child->getId()] = $item;
-         }
-         return $items;
-     }
-     private function loadCategories(array $ids, SalesChannelContext $context): CategoryCollection
-     {
-         $criteria = new Criteria();
-         $criteria->addFilter(new EqualsAnyFilter('id', $ids));
-         $criteria->addAssociation('media');
-         /** @var CategoryCollection $missing */
-         $missing = $this->categoryRepository->search($criteria, $context)->getEntities();
-         return $missing;
-     }
- }
-