/** * Builds a category tree with all the categories and subcategories * * cost O(n) * * @return array */ public function buildCategoryTree() { $categories = $this->categoryRepository->getAllCategoriesSortedByParentAndPositionAsc(); $categoryTree = [0 => null, 'children' => []]; /** * @var CategoryInterface $category */ foreach ($categories as $category) { $parentCategoryId = 0; $categoryId = $category->getId(); if (!$category->isRoot()) { if ($category->getParent() instanceof CategoryInterface) { $parentCategoryId = $category->getParent()->getId(); } else { /** * If category is not root and has no parent, * don't insert it into the tree */ continue; } } if ($parentCategoryId && !isset($categoryTree[$parentCategoryId])) { $categoryTree[$parentCategoryId] = ['entity' => null, 'children' => []]; } if (!isset($categoryTree[$categoryId])) { $categoryTree[$categoryId] = ['entity' => null, 'children' => []]; } $categoryTree[$categoryId]['entity'] = $category; $categoryTree[$parentCategoryId]['children'][] =& $categoryTree[$categoryId]; } return $categoryTree[0]['children'] ?: []; }
/** * Test the repository to check that the get children categories returns * all the children categories (Recursively). */ public function testGetChildrenCategoriesRecursively() { /** * @var $rootCategory CategoryInterface */ $rootCategory = $this->categoryRepository->findOneBy(['slug' => 'root-category']); $childrenCategories = $this->categoryRepository->getChildrenCategories($rootCategory, true); $this->assertCount(2, $childrenCategories, 'It should only return two categories on recursive mode'); }
/** * Test that the principal category is assigned as category when a product * is saved only with principal category. */ public function testProductIsSavedOnlyWithPrincipalCategory() { $category = $this->categoryRepository->findOneBy(['slug' => 'category']); /** * @var ProductInterface $product */ $product = $this->getNewProduct(); $product->setPrincipalCategory($category); $product->setSlug('new-product-2'); $product->setName('New product 2'); $this->productDirector->save($product); $product = $this->productDirector->findOneBy(['slug' => 'new-product-2']); $this->assertEquals(1, $product->getCategories()->count(), 'The product is expected to have one category'); $this->assertEquals($category, $product->getCategories()->first(), 'The returned category should be the principal category'); }
/** * Sort a category tree based on the received order recursively. * * @param array $categoriesOrder The category order * @param Category|null $parentCategory The parent category in case is not a root category. * * @return bool If the order process has finished right. */ protected function sortCategoriesTree(array $categoriesOrder, $parentCategory = null) { $counter = 0; foreach ($categoriesOrder as $categoryInfo) { $category = $this->categoryRepository->findOneBy(['id' => $categoryInfo['id']]); if (is_null($category)) { return false; } $category->setPosition($counter); if ($parentCategory) { $category->setPosition($counter); $category->setRoot(false); $category->setParent($parentCategory); } else { $category->setPosition($counter); $category->setRoot(true); $category->setParent(null); } ++$counter; if (isset($categoryInfo['subtree']) && !$this->sortCategoriesTree($categoryInfo['subtree'], $category)) { return false; } } return true; }
/** * Build category tree from doctrine * * cost O(n) * * @return Array Category tree */ protected function buildCategoryTree() { $categories = $this->categoryRepository->getAllCategoriesSortedByParentAndPositionAsc($this->loadOnlyCategoriesWithProducts); $categoryTree = [0 => null, 'children' => []]; /** * @var CategoryInterface $category */ foreach ($categories as $category) { $parentCategoryId = 0; $categoryId = $category->getId(); if (!$category->isRoot()) { if ($category->getParent() instanceof CategoryInterface) { $parentCategoryId = $category->getParent()->getId(); } else { /** * If category is not root and has no parent, * don't insert it into the tree */ continue; } } if ($parentCategoryId && !isset($categoryTree[$parentCategoryId])) { $categoryTree[$parentCategoryId] = array('entity' => null, 'children' => array()); } if (!isset($categoryTree[$categoryId])) { $categoryTree[$categoryId] = array('entity' => null, 'children' => array()); } $categoryTree[$categoryId]['entity'] = array('id' => $category->getId(), 'name' => $category->getName(), 'slug' => $category->getSlug(), 'productsCount' => $this->loadOnlyCategoriesWithProducts ? count($category->getProducts()) : 0); $categoryTree[$parentCategoryId]['children'][] =& $categoryTree[$categoryId]; } return $categoryTree[0]['children'] ?: []; }
/** * Test when getting purchasables from multiple categories. */ public function testGettingPurchasablesFromMultipleCategories() { /** * @var $rootCategory CategoryInterface */ $rootCategory = $this->categoryRepository->findOneBy(['slug' => 'root-category']); $category = $this->categoryRepository->findOneBy(['slug' => 'category']); $purchasables = $this->purchasableRepository->getAllFromCategories([$rootCategory, $category]); $this->assertCount(5, $purchasables); }
/** * Test when getting products from multiple categories. */ public function testGettingProductsFromMultipleCategories() { /** * @var $rootCategory CategoryInterface */ $rootCategory = $this->categoryRepository->findOneBy(['slug' => 'root-category']); $category = $this->categoryRepository->findOneBy(['slug' => 'category']); $products = $this->productRepository->getAllFromCategories([$rootCategory, $category]); $this->assertCount(3, $products, 'It should only return one product on the root category'); }