From df78126b12cdfb3d88341ad265b3102885bdadd4 Mon Sep 17 00:00:00 2001 From: ludo Date: Fri, 3 Jan 2025 14:09:22 +0100 Subject: [PATCH] refactor scopes --- app/Models/Shop/Article.php | 10 ++- app/Models/Shop/Tag.php | 116 ++++++++++++------------- app/Repositories/Botanic/Varieties.php | 1 + app/Repositories/Shop/TagGroups.php | 31 +------ 4 files changed, 66 insertions(+), 92 deletions(-) diff --git a/app/Models/Shop/Article.php b/app/Models/Shop/Article.php index d9c6bdfd..ce96725a 100644 --- a/app/Models/Shop/Article.php +++ b/app/Models/Shop/Article.php @@ -127,23 +127,25 @@ class Article extends Model implements HasMedia public function scopeByCategories($query, $categoriesId) { return $categoriesId ? $query->whereHas('categories', function ($query) use ($categoriesId) { - $query->whereIn('id', $categoriesId); + $query->whereIn('id', $categoriesId)->whereNull('deleted_at'); }) : $query; } public function scopeByCategoryParent($query, $categoryId) { $category = Category::find($categoryId); + $left = $category->_lft ?? 0; + $right = $category->_rgt ?? 0; - return $categoryId ? $query->whereHas('categories', function ($query) use ($category) { - $query->where('_lft', '>=', $category->_lft)->where('_rgt', '<=', $category->_rgt); + return $categoryId ? $query->whereHas('categories', function ($query) use ($left, $right) { + $query->where('_lft', '>=', $left)->where('_rgt', '<=', $right)->whereNull('deleted_at'); }) : $query; } public function scopeByCategory($query, $categoryId) { return $categoryId ? $query->whereHas('categories', function ($query) use ($categoryId) { - $query->where('id', $categoryId); + $query->where('id', $categoryId)->whereNull('deleted_at'); }) : $query; } diff --git a/app/Models/Shop/Tag.php b/app/Models/Shop/Tag.php index c2fb0869..70de6d5a 100644 --- a/app/Models/Shop/Tag.php +++ b/app/Models/Shop/Tag.php @@ -70,72 +70,72 @@ class Tag extends parentTag return $query->where($this->table.'.tag_group_id', $id); } - public function scopeWithCountArticlesByCategory($query, $category_id) + public function scopeWithCountArticlesByCategory($query, $categoryId) { return $query->withCount([ - 'articles' => function ($query) use ($category_id) { - $query->byCategoryParent($category_id); - }, - ]); - } - - public static function countArticles($categoryId) - { - DB::table('tags') - // Articles directement liés au tag, filtrés par catégorie - ->leftJoin('taggables as direct', function ($join) { - $join->on('tags.id', '=', 'direct.tag_id') - ->where('direct.taggable_type', '=', Article::class); - }) - ->leftJoin('shop_articles', 'direct.taggable_id', '=', 'shop_articles.id') - ->whereExists(function ($query) use ($categoryId) { - $query->select(DB::raw(1)) - ->from('categories') - ->whereColumn('categories.id', 'shop_articles.category_id') - ->where('_lft', '>=', DB::raw("(SELECT _lft FROM categories WHERE id = {$categoryId})")) - ->where('_rgt', '<=', DB::raw("(SELECT _rgt FROM categories WHERE id = {$categoryId})")); - }) - - // Articles liés via une variété ayant le tag, filtrés par catégorie - ->leftJoin('taggables as via_variety', function ($join) { - $join->on('tags.id', '=', 'via_variety.tag_id') - ->where('via_variety.taggable_type', '=', Variety::class); - }) - ->leftJoin('botanic_varieties', 'via_variety.taggable_id', '=', 'botanic_varieties.id') - ->leftJoin('shop_articles as indirect_articles', function ($join) { - $join->on('varieties.id', '=', 'indirect_articles.product_id') - ->where('indirect_articles.product_type', '=', Variety::class); - }) - ->whereExists(function ($query) use ($categoryId) { - $query->select(DB::raw(1)) - ->from('categories') - ->whereColumn('categories.id', 'indirect_articles.category_id') - ->where('_lft', '>=', DB::raw("(SELECT _lft FROM categories WHERE id = {$categoryId})")) - ->where('_rgt', '<=', DB::raw("(SELECT _rgt FROM categories WHERE id = {$categoryId})")); - }) - - // Combinaison des deux types de liens et comptage - ->select('tags.id', 'tags.name', DB::raw('COUNT(DISTINCT shop_articles.id) + COUNT(DISTINCT indirect_articles.id) as article_count')) - ->groupBy('tags.id', 'tags.name') - ->get(); - } - - public function scopeWithFilteredArticleCounts($query, $categoryId) - { - return $query->withCount([ - // Articles directement liés au tag et filtrés par catégorie 'articles as direct_article_count' => function ($query) use ($categoryId) { - $query->byCategoryParent($categoryId); + $query->byCategoryParent($categoryId)->withAvailableOffers(); }, - - // Articles liés via Variety et filtrés par catégorie sur les articles eux-mêmes 'articles as indirect_article_count' => function ($query) use ($categoryId) { - $query->whereHasMorph('product', [Variety::class], function ($subQuery) { - // Pas de catégorie sur Variety, pas de filtre ici + $query->byCategoryParent($categoryId)->withAvailableOffers()->whereHasMorph('product', [Variety::class], function () {}); + }, + ])->havingRaw('(COALESCE(direct_article_count, 0) + COALESCE(indirect_article_count, 0)) > 0'); + } + + public function scopeWithCountArticlesByProductByCategory($query, $categoryId) + { + return $query->select(['tags.*']) + ->selectRaw('(SELECT COUNT(*) + FROM shop_articles + WHERE EXISTS ( + SELECT 1 + FROM botanic_varieties + INNER JOIN taggables + ON taggables.taggable_id = botanic_varieties.id + AND taggables.taggable_type = ? + WHERE shop_articles.product_id = botanic_varieties.id + AND shop_articles.product_type = ? + AND taggables.tag_id = tags.id + ) + AND EXISTS ( + SELECT 1 + FROM categories + INNER JOIN categorizables + ON categorizables.category_id = categories.id + WHERE categorizables.categorizable_id = shop_articles.id + AND categorizables.categorizable_type = ? + AND categories._lft >= ? + AND categories._rgt <= ? + ) + AND shop_articles.id IN ( + SELECT id FROM shop_articles WHERE EXISTS ( + SELECT 1 FROM shop_offers + WHERE shop_offers.article_id = shop_articles.id + AND shop_offers.stock_current > 0 + ) + ) + ) AS indirect_article_count', [ + Variety::class, // Type des variétés dans taggables + Variety::class, // Type du produit dans articles + Article::class, // Type de l'article dans categorizables + optional(Category::find($categoryId))->_lft ?? 0, // Limite gauche + optional(Category::find($categoryId))->_rgt ?? PHP_INT_MAX, // Limite droite + ]) + ->having('indirect_article_count', '>', 0); + } + + public function scopeWithIndirectArticleCount($query, $categoryId = null) + { + return $query->withCount([ + 'articles as indirect_article_count' => function ($articleQuery) use ($categoryId) { + $articleQuery->whereHasMorph('product', [Variety::class], function ($varietyQuery) { + $varietyQuery->whereHas('tags', function ($tagQuery) { + $tagQuery->whereColumn('tags.id', 'taggables.tag_id'); + }); })->byCategoryParent($categoryId); }, ]) - ->havingRaw('(COALESCE(direct_article_count, 0) + COALESCE(indirect_article_count, 0)) > 0'); // Filtre les tags avec au moins un article + ->having('indirect_article_count', '>', 0); // Garde uniquement les tags ayant au moins un article indirect } public function scopeById($query, $id) diff --git a/app/Repositories/Botanic/Varieties.php b/app/Repositories/Botanic/Varieties.php index 8994e894..60790f72 100644 --- a/app/Repositories/Botanic/Varieties.php +++ b/app/Repositories/Botanic/Varieties.php @@ -4,6 +4,7 @@ namespace App\Repositories\Botanic; use App\Models\Botanic\Variety; use App\Repositories\Core\Tag; +use App\Repositories\Shop\TagGroups; use App\Traits\Model\Basic; use App\Traits\Repository\Imageable; diff --git a/app/Repositories/Shop/TagGroups.php b/app/Repositories/Shop/TagGroups.php index d2556e8b..894555d9 100644 --- a/app/Repositories/Shop/TagGroups.php +++ b/app/Repositories/Shop/TagGroups.php @@ -16,48 +16,19 @@ class TagGroups { $data = []; $tags = Tag::withCountArticlesByCategory($category_id)->get()->toArray(); - dump($tags); - exit; $tagGroups = TagGroup::pluck('name', 'id')->toArray(); foreach ($tags as $tag) { - if (! $tag['articles_count']) { - continue; - } $data[$tag['tag_group_id']]['name'] = $tagGroups[$tag['tag_group_id']]; $data[$tag['tag_group_id']]['tags'][] = [ 'id' => $tag['id'], 'name' => $tag['name'], - 'count' => $tag['articles_count'], + 'count' => $tag['direct_article_count'] + $tag['indirect_article_count'], ]; } return $data; } - public static function getWithTagsAndCountOffers2($categoryId = false) - { - return Tag::withCount([ - 'articles as direct_article_count' => function ($query) use ($categoryId) { - $query->byCategoryParent($categoryId); - }, - 'articles as indirect_article_count' => function ($query) use ($categoryId) { - $query->whereHasMorph('product', [Variety::class], function ($subQuery) use ($categoryId) { - $subQuery->whereHas('categories', function ($categoryQuery) use ($categoryId) { - $categoryQuery->byCategoryParent($categoryId); - }); - }); - }, - ]) - ->get() - ->map(function ($tag) { - $tag->total_articles = $tag->direct_article_count + $tag->indirect_article_count; - return $tag; - }) - ->filter(function ($tag) { - return $tag->total_articles > 0; // Garde uniquement les tags ayant des articles - }); - } - public static function isTagGroupHaveSelected($tagsSelected, $tags) { foreach ($tags as $tag) {