153 lines
5.7 KiB
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,
|
|
};
|
|
}
|
|
}
|