custom/plugins/ProcDisableCategories/src/Decorator/NavigationRouteDecorator.php line 76

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Proc\DisableCategories\Decorator;
  3. use Shopware\Core\Content\Category\CategoryCollection;
  4. use Shopware\Core\Content\Category\CategoryEntity;
  5. use Shopware\Core\Content\Category\SalesChannel\AbstractNavigationRoute;
  6. use Shopware\Core\Content\Category\SalesChannel\NavigationRouteResponse;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
  10. use Shopware\Core\Framework\Routing\Annotation\Entity;
  11. use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
  12. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  13. use Shopware\Core\System\SystemConfig\SystemConfigService;
  14. use Symfony\Component\HttpFoundation\Request;
  15. use Symfony\Component\Routing\Annotation\Route;
  16. /**
  17.  * @Route(defaults={"_routeScope"={"store-api"}})
  18.  */
  19. class NavigationRouteDecorator extends AbstractNavigationRoute
  20. {
  21.     /**
  22.      * @var SalesChannelRepositoryInterface
  23.      */
  24.     protected SalesChannelRepositoryInterface $categoryRepository;
  25.     private AbstractNavigationRoute $decorated;
  26.     private SystemConfigService $systemConfigService;
  27.     public function __construct(SalesChannelRepositoryInterface $categoryRepositoryAbstractNavigationRoute $navigationRouteSystemConfigService $systemConfigService)
  28.     {
  29.         $this->categoryRepository $categoryRepository;
  30.         $this->decorated $navigationRoute;
  31.         $this->systemConfigService $systemConfigService;
  32.     }
  33.     public function getDecorated(): AbstractNavigationRoute
  34.     {
  35.         return $this->decorated;
  36.     }
  37.     /**
  38.      * @Entity("category")
  39.      * @Route("/store-api/navigation/{activeId}/{rootId}", name="store-api.navigation", methods={"GET", "POST"})
  40.      */
  41.     public function load(string              $activeId,
  42.                          string              $rootId,
  43.                          Request             $request,
  44.                          SalesChannelContext $context,
  45.                          Criteria            $criteria): NavigationRouteResponse
  46.     {
  47.         $this->decorated->load($activeId$rootId$request$context$criteria);
  48.         $criteria->addAssociation('products');
  49.         if (!$context->getCustomer()) {
  50.             if ($categoriesIds $this->systemConfigService->get('ProcDisableCategories.config.categoriesGuestsConfig'))
  51.                 $criteria->addFilter(new NotFilter(NotFilter::CONNECTION_AND, [new EqualsAnyFilter('category.id'$categoriesIds)]));
  52.             if ($productIds $this->systemConfigService->get('ProcDisableCategories.config.productsGuestsConfig')) {
  53.                 $criteria->getAssociation('products')->addFilter(new NotFilter(NotFilter::CONNECTION_AND, [new EqualsAnyFilter('product.id'$productIds)]));
  54.             }
  55.         } elseif (isset($context->getCustomer()->getCustomFields()['custom_product_listing_numbers'])) {
  56.             $productArray explode(','$context->getCustomer()->getCustomFields()['custom_product_listing_numbers']);
  57.         } else {
  58.             $productArray null;
  59.         }
  60.         $criteria->addAssociation('children');
  61.         $criteria->addAssociation('cmsPage');
  62.         
  63.         $context->addState('noLivePrice');
  64.         $categories $this->categoryRepository->search($criteria$context)->getEntities()->getElements();
  65.         $context->removeState('noLivePrice');
  66.         if ($this->getEmptyCategoryConfig()) {
  67.             $categoriesResponse = new CategoryCollection();
  68.             /**
  69.              * @var CategoryEntity $category
  70.              */
  71.             $depth $context->getSalesChannel()->getNavigationCategoryDepth();
  72.             $hasProducts $this->getCategoriesHasProducts($categories$depth)['hasProducts'];
  73.             $parentIds $this->getCategoriesHasProducts($categories$depth)['parentIds'];
  74.             if ($context->getCustomer()) $showCategoryIds $this->setCategoriesForCustomer($categories$hasProducts$productArray);
  75.             else $showCategoryIds = (array_unique(array_merge($hasProducts$parentIds)));
  76.             foreach ($categories as $category) {
  77.                 if (!$this->isCategoryTypePage($category) || $this->isCategoryTypePage($category) && $category->getCmsPage() !== null && $category->getCmsPage()->getType() !== "product_list") {
  78.                     $categoriesResponse->add($category);
  79.                     continue;
  80.                 }
  81.                 if (in_array($category->getId(), $showCategoryIds)) $categoriesResponse->add($category);
  82.             }
  83.         } else {
  84.             $categoriesResponse = new CategoryCollection($categories);
  85.         }
  86.         $this->setVisibleChildCountForOffcanvasNavigation($categoriesResponse);
  87.         return new NavigationRouteResponse($categoriesResponse);
  88.     }
  89.     private function getCategoriesHasProducts($categories$depth): array
  90.     {
  91.         $hasProducts null;
  92.         $parentIds null;
  93.         for ($lvl $depth 1$lvl >= 2$lvl--) {
  94.             $currentHasProducts null;
  95.             $currentLevel null;
  96.             $currentLevel $this->getCategoriesByLevel($categories$lvl);
  97.             $currentHasProducts $this->hasProducts($currentLevel);
  98.             if ($currentHasProducts != null) {
  99.                 $hasProducts array_merge_recursive($this->getCategoryIds($currentHasProducts), (array)$hasProducts);
  100.                 $parentIds array_merge_recursive($this->getCategoryParentId($currentHasProducts), (array)$parentIds);
  101.             }
  102.         }
  103.         return [
  104.             'hasProducts' => $hasProducts,
  105.             'parentIds' => $parentIds
  106.         ];
  107.     }
  108.     private function setCategoriesForCustomer($categories$hasProducts$productArray null): array
  109.     {
  110.         $hasProductsCategories $this->getCategoryByIds($categories$hasProducts);
  111.         $customerHasProducts = [];
  112.         $parentIds = [];
  113.         foreach ($hasProductsCategories as $category) {
  114.             $categoryProducts $category->getProducts()->getElements();
  115.             //DH: add filter also for products state....
  116.             $categoryProductsarray_filter($categoryProducts, function($v$k) {
  117.                 return $v->getActive()== 1;
  118.             }, ARRAY_FILTER_USE_BOTH);
  119.             
  120.             if ($productArray != null AND !empty(array_intersect(array_column($categoryProducts'productNumber'), $productArray)))
  121.             {
  122.                 $customerHasProducts[] = $category->getId();
  123.                     $parentIds[] = $category->getParentId();
  124.             }
  125.         }
  126.         return array_unique(array_merge($customerHasProducts$parentIds));
  127.     }
  128.     private function getCategoryParentId($categories): array
  129.     {
  130.         $parentId = [];
  131.         foreach ($categories as $category) {
  132.             $parentId[] = $category->getParentId();
  133.         }
  134.         return $parentId;
  135.     }
  136.     private function getCategoriesByLevel($categories$lvl): array
  137.     {
  138.         $categoriesByLevel = [];
  139.         foreach ($categories as $category) {
  140.             if ($category->getLevel() == $lvl) {
  141.                 $categoriesByLevel[] = $category;
  142.             }
  143.         }
  144.         return $categoriesByLevel;
  145.     }
  146.     private function getCategoryIds($categories): array
  147.     {
  148.         $categoryIds = [];
  149.         foreach ($categories as $category) {
  150.             $categoryIds[] = $category->getId();
  151.         }
  152.         return $categoryIds;
  153.     }
  154.     private function getCategoryByIds($categories$categoryIds): array
  155.     {
  156.         $currentCategories = [];
  157.         foreach ($categories as $category) {
  158.             if (in_array($category->getId(), $categoryIds)) {
  159.                 $currentCategories[] = $category;
  160.             }
  161.         }
  162.         return $currentCategories;
  163.     }
  164.     private function hasProducts($categories): array
  165.     {
  166.         $categoriesHaveProducts = [];
  167.         foreach ($categories as $category) {
  168.             if ($category->getProducts()->getElements()) $categoriesHaveProducts[] = $category;
  169.         }
  170.         return $categoriesHaveProducts;
  171.     }
  172.     private function isCategoryTypePage($category): ?bool
  173.     {
  174.         if ($category->get('type') == 'page')
  175.             return true;
  176.         else return null;
  177.     }
  178.     private function getEmptyCategoryConfig()
  179.     {
  180.         return $this->systemConfigService->get('ProcDisableCategories.config.emptyCategoriesConfig');
  181.     }
  182.     private function setVisibleChildCountForOffcanvasNavigation(CategoryCollection $categoriesResponse)
  183.     {
  184.         foreach ($categoriesResponse->getElements() as $element) {
  185.             $childCount 0;
  186.             foreach ($element->getChildren() as $child) {
  187.                 if ($child->getVisible()) {
  188.                     $childCount++;
  189.                 }
  190.             }
  191.             $element->setVisibleChildCount($childCount);
  192.         }
  193.     }
  194. }