ldc-ovoteam/database/seeders/Mandatory/ImportRecipeSeeder.php

153 lines
5.7 KiB
PHP

<?php
declare(strict_types=1);
namespace Database\Seeders;
use App\Models\Product;
use App\Models\Recipe;
use Domain\Models\ValueObjects\Products\ProductRange;
use Domain\Models\ValueObjects\Recipes\ConsumptionTime;
use Domain\Models\ValueObjects\Recipes\Inspiration;
use Domain\Models\ValueObjects\Recipes\Season;
use Illuminate\Database\Seeder;
class ImportRecipesCsvSeeder extends Seeder
{
public function run(): void
{
$filePathName = database_path('seeders/data/recipes.csv');
$resource = new \SplFileObject($filePathName, 'r');
$rowCount = 0;
while (!$resource->eof()) {
$line = $resource->fgetcsv(';');
if ($line === false || ($line[0] ?? null) === null) {
continue;
}
// Ignore les deux premières lignes (En-tête + Explications)
if ($rowCount++ <= 1) {
continue;
}
// Assure 16 colonnes minimum pour éviter les erreurs d'offset
$paddedRow = array_pad($line, 16, '');
$samplePicture = new \SplFileInfo(__DIR__ . '/../data/800x800.png');
$recipe = Recipe::create([
'seo_title' => $this->cleanString($paddedRow[0]),
'seo_description' => $this->cleanString($paddedRow[1]),
'picture' => $samplePicture,
'picture_alt' => $this->cleanString($paddedRow[3]),
'picture_title' => $this->cleanString($paddedRow[4]),
'name' => $this->cleanString($paddedRow[5]),
// Utilisation des méthodes de mapping robustes
'product_range' => $this->mapProductRange($paddedRow[6]),
'consomption_time' => $this->mapConsumptionTime($paddedRow[7]),
'inspiration' => $this->mapInspiration($paddedRow[8]),
'season' => $this->mapSeason($paddedRow[9]),
'description' => $this->cleanString($paddedRow[10]),
'details' => $this->cleanString($paddedRow[11]),
'ingredients_list' => $this->cleanString($paddedRow[12]),
'preparation_steps' => $this->cleanString($paddedRow[13]),
'tips_and_advices' => $this->cleanString($paddedRow[14]),
]);
$associatedProductName = $this->cleanString($paddedRow[15]);
if ($associatedProductName !== null) {
$product = Product::query()
->where('name', 'LIKE', '%' . $associatedProductName . '%')
->first();
if ($product) {
$recipe->products()->attach($product->id);
}
}
}
}
/**
* Nettoie la chaîne et retourne null si elle est vide.
*/
private function cleanString(?string $value): ?string
{
if ($value === null) {
return null;
}
$value = trim($value);
return $value === '' ? null : $value;
}
/**
* Mapping explicite pour ProductRange
*/
private function mapProductRange(string $value): ?string
{
$normalized = mb_strtolower(trim($value));
return match (true) {
str_contains($normalized, 'poché') => ProductRange::POACHED_EGGS->value,
str_contains($normalized, 'dur') => ProductRange::HARD_BOILED_EGGS->value,
str_contains($normalized, 'brouillé') => ProductRange::SCRAMBLED_EGGS->value,
str_contains($normalized, 'omelette') => ProductRange::OMELETS_AND_DELI_AND_DESSERT_LINES->value,
str_contains($normalized, 'dessert') => ProductRange::OMELETS_AND_DELI_AND_DESSERT_LINES->value,
str_contains($normalized, 'liquide') => ProductRange::SMALL_PACKAGED_LIQUID_EGGS->value,
default => null,
};
}
/**
* Mapping explicite pour ConsumptionTime
*/
private function mapConsumptionTime(string $value): ?string
{
$normalized = mb_strtolower(trim($value));
return match (true) {
str_contains($normalized, 'déjeuner/dîner') || str_contains($normalized, 'déjeuner / dîner') => ConsumptionTime::LUNCH_DINNER->value,
str_contains($normalized, 'petit déjeuner') || str_contains($normalized, 'brunch') => ConsumptionTime::BREAK_FAST_BRUNCH->value,
str_contains($normalized, 'snack') => ConsumptionTime::SNACKING->value,
str_contains($normalized, 'dessert') || str_contains($normalized, 'pâtisserie') => ConsumptionTime::DESERT_BAKERY->value,
default => null,
};
}
/**
* Mapping explicite pour Inspiration
*/
private function mapInspiration(string $value): ?string
{
$normalized = mb_strtolower(trim($value));
return match (true) {
str_contains($normalized, 'monde') => Inspiration::WORLD_COOKING->value,
str_contains($normalized, 'française') => Inspiration::FRENCH_COOKING->value,
str_contains($normalized, 'protéinée') => Inspiration::PROTEINIC_COOKING->value,
default => null,
};
}
/**
* Mapping explicite pour Season
*/
private function mapSeason(string $value): ?string
{
$normalized = mb_strtolower(trim($value));
return match (true) {
str_contains($normalized, 'année') => Season::ALL_YEAR->value,
str_contains($normalized, 'automne') || str_contains($normalized, 'hiver') => Season::AUTUMN_WINTER->value,
str_contains($normalized, 'printemps') || str_contains($normalized, 'été') => Season::SPRING_SUMMER->value,
default => null,
};
}
}