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

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. //        $criteria->addAssociation('productStream');
  63. //        $criteria->addAssociation('productStream.productExports');
  64.         $categories $this->categoryRepository->search($criteria$context)->getEntities()->getElements();
  65.         if ($this->getEmptyCategoryConfig()) {
  66.             $categoriesResponse = new CategoryCollection();
  67.             /**
  68.              * @var CategoryEntity $category
  69.              */
  70.             $depth $context->getSalesChannel()->getNavigationCategoryDepth();
  71.             $hasProducts $this->getCategoriesHasProducts($categories$depth)['hasProducts'];
  72.             $parentIds $this->getCategoriesHasProducts($categories$depth)['parentIds'];
  73.             if ($context->getCustomer()) $showCategoryIds $this->setCategoriesForCustomer($categories$hasProducts$productArray);
  74.             else $showCategoryIds = (array_unique(array_merge($hasProducts$parentIds)));
  75.             foreach ($categories as $category) {
  76.                 if (!$this->isCategoryTypePage($category) || $this->isCategoryTypePage($category) && $category->getCmsPage() !== null && $category->getCmsPage()->getType() !== "product_list") {
  77.                     $categoriesResponse->add($category);
  78.                     continue;
  79.                 }
  80.                 if (in_array($category->getId(), $showCategoryIds)) $categoriesResponse->add($category);
  81.             }
  82.         } else {
  83.             $categoriesResponse = new CategoryCollection($categories);
  84.         }
  85.         $this->setVisibleChildCountForOffcanvasNavigation($categoriesResponse);
  86.         return new NavigationRouteResponse($categoriesResponse);
  87.     }
  88.     private function getCategoriesHasProducts($categories$depth): array
  89.     {
  90.         $hasProducts null;
  91.         $parentIds null;
  92.         for ($lvl $depth 1$lvl >= 2$lvl--) {
  93.             $currentHasProducts null;
  94.             $currentLevel null;
  95.             $currentLevel $this->getCategoriesByLevel($categories$lvl);
  96.             $currentHasProducts $this->hasProducts($currentLevel);
  97.             if ($currentHasProducts != null) {
  98.                 $hasProducts array_merge_recursive($this->getCategoryIds($currentHasProducts), (array)$hasProducts);
  99.                 $parentIds array_merge_recursive($this->getCategoryParentId($currentHasProducts), (array)$parentIds);
  100.             }
  101.         }
  102.         return [
  103.             'hasProducts' => $hasProducts,
  104.             'parentIds' => $parentIds
  105.         ];
  106.     }
  107.     private function setCategoriesForCustomer($categories$hasProducts$productArray null): array
  108.     {
  109.         $hasProductsCategories $this->getCategoryByIds($categories$hasProducts);
  110.         $customerHasProducts = [];
  111.         $parentIds = [];
  112.         foreach ($hasProductsCategories as $category) {
  113.             $categoryProducts $category->getProducts()->getElements();
  114.             //DH: add filter also for products state....
  115.             $categoryProductsarray_filter($categoryProducts, function($v$k) {
  116.                 return $v->getActive()== 1;
  117.             }, ARRAY_FILTER_USE_BOTH);
  118.             
  119.             if ($productArray != null AND !empty(array_intersect(array_column($categoryProducts'productNumber'), $productArray)))
  120.             {
  121.                 $customerHasProducts[] = $category->getId();
  122.                     $parentIds[] = $category->getParentId();
  123.             }
  124.         }
  125.         return array_unique(array_merge($customerHasProducts$parentIds));
  126.     }
  127.     private function getCategoryParentId($categories): array
  128.     {
  129.         $parentId = [];
  130.         foreach ($categories as $category) {
  131.             $parentId[] = $category->getParentId();
  132.         }
  133.         return $parentId;
  134.     }
  135.     private function getCategoriesByLevel($categories$lvl): array
  136.     {
  137.         $categoriesByLevel = [];
  138.         foreach ($categories as $category) {
  139.             if ($category->getLevel() == $lvl) {
  140.                 $categoriesByLevel[] = $category;
  141.             }
  142.         }
  143.         return $categoriesByLevel;
  144.     }
  145.     private function getCategoryIds($categories): array
  146.     {
  147.         $categoryIds = [];
  148.         foreach ($categories as $category) {
  149.             $categoryIds[] = $category->getId();
  150.         }
  151.         return $categoryIds;
  152.     }
  153.     private function getCategoryByIds($categories$categoryIds): array
  154.     {
  155.         $currentCategories = [];
  156.         foreach ($categories as $category) {
  157.             if (in_array($category->getId(), $categoryIds)) {
  158.                 $currentCategories[] = $category;
  159.             }
  160.         }
  161.         return $currentCategories;
  162.     }
  163.     private function hasProducts($categories): array
  164.     {
  165.         $categoriesHaveProducts = [];
  166.         foreach ($categories as $category) {
  167.             if ($category->getProducts()->getElements()) $categoriesHaveProducts[] = $category;
  168.         }
  169.         return $categoriesHaveProducts;
  170.     }
  171.     private function isCategoryTypePage($category): ?bool
  172.     {
  173.         if ($category->get('type') == 'page')
  174.             return true;
  175.         else return null;
  176.     }
  177.     private function getEmptyCategoryConfig()
  178.     {
  179.         return $this->systemConfigService->get('ProcDisableCategories.config.emptyCategoriesConfig');
  180.     }
  181.     private function setVisibleChildCountForOffcanvasNavigation(CategoryCollection $categoriesResponse)
  182.     {
  183.         foreach ($categoriesResponse->getElements() as $element) {
  184.             $childCount 0;
  185.             foreach ($element->getChildren() as $child) {
  186.                 if ($child->getVisible()) {
  187.                     $childCount++;
  188.                 }
  189.             }
  190.             $element->setVisibleChildCount($childCount);
  191.         }
  192.     }
  193. }