with(['products']) ->where('id', (string) $id->value) ->limit(1) ->get() ->map(fn (Recipe $recipe) => $this->mapToEntity($recipe)) ->first(); } public function findBySlug(string $slug): ?DomainRecipe { return Recipe::query() ->with(['products']) ->where('slug', $slug) ->limit(1) ->get() ->map(fn (Recipe $recipe) => $this->mapToEntity($recipe)) ->first(); } public function getPaginatedRecipes( Pagination $pagination, array $productRanges = [], array $consumptionTimes = [], array $inspirations = [], array $seasons = [], string $search = '' ): LengthAwarePaginator { $dbQueryCallback = function (Builder $query) use ($productRanges, $consumptionTimes, $inspirations, $seasons) { /** @var \Illuminate\Database\Eloquent\Builder $query */ $query->with(['products']) ->where('is_published', true); if (! empty($productRanges)) { $rangesValues = array_map(fn ($r) => $r->value, $productRanges); $query->whereIn('product_category', $rangesValues); } if (! empty($consumptionTimes)) { $timesValues = array_map(fn ($t) => $t->value, $consumptionTimes); $query->whereIn('consomption_time', $timesValues); } if (! empty($inspirations)) { $inspValues = array_map(fn ($i) => $i->value, $inspirations); $query->whereIn('inspiration', $inspValues); } if (! empty($seasons)) { $seasonValues = array_map(fn ($s) => $s->value, $seasons); $query->whereIn('season', $seasonValues); } }; $query = Recipe::query(); if (! empty($search)) { $scout = Recipe::search($search); $matchingIds = $scout->keys(); if ($matchingIds->isEmpty()) { /** @var \Illuminate\Pagination\LengthAwarePaginator */ return $query->whereIn('id', [])->paginate( perPage: $pagination->pageSize(), page: $pagination->pageNumber() ); } $query->whereIn('id', $matchingIds); } $dbQueryCallback($query); return $query->paginate( perPage: $pagination->pageSize(), page: $pagination->pageNumber() )->through(fn (Recipe $recipe) => $this->mapToEntity($recipe)); } private function mapToEntity(Recipe $recipe): DomainRecipe { return new DomainRecipe( id: new RecipeId(Uuid::fromString($recipe->id)), name: $recipe->name, slug: $recipe->slug, isPublished: (bool) $recipe->is_published, picture: $recipe->picture?->value, seoTitle: $recipe->seo_title, seoDescription: $recipe->seo_description, productRange: $recipe->product_category, consomptionTime: $recipe->consomption_time, inspiration: $recipe->inspiration, season: $recipe->season, description: $recipe->description, details: $recipe->details, preparationTime: '15 min de préparation', guestsCount: 4, ingredientsList: $recipe->ingredients_list, preparationSteps: $recipe->preparation_steps, tipsAndAdvices: $recipe->tips_and_advices, associatedProducts: [] ); } public function getRelatedRecipes(ProductId $productId, int $limit = 4): array { $product = Product::query() ->where('id', (string) $productId->value) ->first(); if (! $product) { return []; } return $product->recipes() ->where('is_published', true) ->limit($limit) ->get() ->map(fn (Recipe $recipe) => $this->mapToEntity($recipe)) ->all(); } }