From 2d1861caba60aacb57fd908fa600348e279ed913 Mon Sep 17 00:00:00 2001 From: Krzysiej Date: Mon, 26 Jan 2026 08:59:58 +0100 Subject: [PATCH] feature/category-tree Co-authored-by: Krzysiej Co-committed-by: Krzysiej --- src/Controller/CategoryController.php | 29 +++++++++++++++++++--- src/Twig/AppExtension.php | 35 ++++++++++++++++++++++++--- templates/productList.html.twig | 5 ++++ templates/template.html.twig | 2 +- 4 files changed, 63 insertions(+), 8 deletions(-) diff --git a/src/Controller/CategoryController.php b/src/Controller/CategoryController.php index 27c190b..3e872cb 100644 --- a/src/Controller/CategoryController.php +++ b/src/Controller/CategoryController.php @@ -11,10 +11,11 @@ final class CategoryController extends BaseController #[Route('/category/{category}', name: 'app_category')] public function __invoke(string $category): Response { - if($this->cache->getItem('list_category_'.$category)->isHit()) { - return $this->render('productList.html.twig', ['listType' => 'category_'.$category]); - } +// if($this->cache->getItem('list_category_'.$category)->isHit()) { +// return $this->render('productList.html.twig', ['listType' => 'category_'.$category]); +// } + /** @var Product[] $products */ $products = Product::with(['price', 'lowestPrice']) ->selectRaw('products.*') ->distinct('products.id') @@ -24,6 +25,26 @@ final class CategoryController extends BaseController ->orderByDesc('created_by') ->get(); - return $this->render('productList.html.twig', ['products' => $products, 'listType' => 'category_'.$category]); + $categoriesTree = []; + + foreach ($products as $product) { + $categoriesTree = $this->addToTree($product->categories, $categoriesTree); + } + + return $this->render('productList.html.twig', ['products' => $products, 'listType' => 'category_' . $category, 'category' => $category, 'categoryTree' => $categoriesTree]); + } + + private function addToTree(array $categories, mixed $categoriesTree) + { + $tmp = &$categoriesTree; + foreach ($categories as $category) { + if (empty($tmp[$category])) { + $tmp[$category] = ['count' => 0]; + } + $tmp = &$tmp[$category]; + $tmp['count']++; + } + + return $categoriesTree; } } diff --git a/src/Twig/AppExtension.php b/src/Twig/AppExtension.php index 1a08554..22bc991 100644 --- a/src/Twig/AppExtension.php +++ b/src/Twig/AppExtension.php @@ -2,11 +2,11 @@ namespace Krzysiej\RyobiCrawler\Twig; -use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; use Krzysiej\RyobiCrawler\Models\Price; use Krzysiej\RyobiCrawler\Models\Product; use Krzysiej\RyobiCrawler\Models\Stock; +use Symfony\Component\Routing\RouterInterface; use Twig\Extension\AbstractExtension; use Twig\TwigFilter; use Twig\TwigFunction; @@ -15,6 +15,10 @@ use function Symfony\Component\Clock\now; class AppExtension extends AbstractExtension { + public function __construct(public RouterInterface $route) + { + } + public function getFunctions(): array { return [ @@ -23,6 +27,7 @@ class AppExtension extends AbstractExtension new TwigFunction('newCount', [$this, 'newCount']), new TwigFunction('discontinuedCount', [$this, 'discontinuedCount']), new TwigFunction('lowestPriceCount', [$this, 'lowestPriceCount']), + new TwigFunction('renderCategoryTree', [$this, 'renderCategoryTree']), ]; } @@ -56,7 +61,7 @@ class AppExtension extends AbstractExtension public function lowestPriceCount(): int { return Product::whereRaw('priceCurrent = priceLowest') - ->whereRaw('lastSeen = "'.now()->format('Y-m-d').'"') + ->whereRaw('lastSeen = "' . now()->format('Y-m-d') . '"') ->whereRaw('priceCurrent < productStandardPrice') ->count(); } @@ -65,4 +70,28 @@ class AppExtension extends AbstractExtension { return $items->first(fn($item) => str_starts_with($item->created_at, $date)); } -} \ No newline at end of file + + public function renderCategoryTree($categories, $current, $level = 0): string + { + $tree = ''; + if ($level == 0) { + $tree .= '
    '; + } + foreach ($categories as $categoryName => $category) { + $currentClass = $categoryName == $current ? 'list-group-item-primary' : ''; + $tree .= '' . $categoryName . ' ' . $category['count'] . ''; + + unset($category['count']); + if (is_array($category) && count($category) >= 1) { + foreach ($category as $subcategoryName => $subCategory) { + $tree .= $this->renderCategoryTree([$subcategoryName => $subCategory], $current, $level + 1); + } + } + } + if ($level == 0) { + $tree .= '
'; + } + return $tree; + + } +} diff --git a/templates/productList.html.twig b/templates/productList.html.twig index 1d349f5..92436e6 100644 --- a/templates/productList.html.twig +++ b/templates/productList.html.twig @@ -2,6 +2,11 @@ {% block content %} {% cache 'list_' ~ listType %} + +{% if listType starts with 'category_' %} + {{ renderCategoryTree(categoryTree, category) | raw }} +{% endif %} +
diff --git a/templates/template.html.twig b/templates/template.html.twig index da00920..e7b7508 100644 --- a/templates/template.html.twig +++ b/templates/template.html.twig @@ -1,5 +1,5 @@ - +