141 lines
4.6 KiB
PHP
141 lines
4.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Directories;
|
|
|
|
use App\Contracts\Directories\RecipeDirectory;
|
|
use App\Models\Product;
|
|
use App\Models\Recipe;
|
|
use Domain\Models\Entities\Recipe as DomainRecipe;
|
|
use Domain\Models\ValueObjects\Entities\ProductId;
|
|
use Domain\Models\ValueObjects\Entities\RecipeId;
|
|
use Domain\Models\ValueObjects\Pagination;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Pagination\LengthAwarePaginator;
|
|
use Ramsey\Uuid\Uuid;
|
|
|
|
class EloquentRecipeDirectory implements RecipeDirectory
|
|
{
|
|
public function find(RecipeId $id): ?DomainRecipe
|
|
{
|
|
return Recipe::query()
|
|
->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<Recipe> $query */
|
|
$query->with(['products']);
|
|
|
|
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<array-key,DomainRecipe> */
|
|
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,
|
|
picture: $recipe->picture,
|
|
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()
|
|
->with(['products'])
|
|
->limit($limit)
|
|
->get()
|
|
->map(fn (Recipe $recipe) => $this->mapToEntity($recipe))
|
|
->all();
|
|
}
|
|
}
|