$validCategoryIds */ $validCategoryIds = InstitutionCategory::query()->pluck('id')->map(intval(...))->all(); if ($validCategoryIds === []) { $summary->warn('Lookup institution_categories vuoto: esegui prima `db:seed`. Import saltato.'); return $summary; } $rows = DB::connection(self::SOURCE) ->table('institution') ->orderBy('id') ->get(); DB::transaction(function () use ($rows, $dryRun, $summary, $validCategoryIds): void { foreach ($rows as $row) { $this->importRow($row, $dryRun, $validCategoryIds, $summary); } }); return $summary; } /** * Importa (upsert) una singola istituzione legacy. Categoria assente nel * lookup v2 → skip con warning. * * @param list $validCategoryIds */ private function importRow(object $row, bool $dryRun, array $validCategoryIds, ImportSummary $summary): void { $categoryId = (int) $row->category; if (! in_array($categoryId, $validCategoryIds, true)) { $summary->warn(sprintf( "Institution legacy #%d ('%s'): category %d assente nel lookup v2 → saltata.", $row->id, trim((string) $row->name), $categoryId, )); $summary->skipped++; return; } if ($dryRun) { Institution::query()->where('legacy_id', (int) $row->id)->exists() ? $summary->updated++ : $summary->created++; return; } $institution = Institution::updateOrCreate( ['legacy_id' => (int) $row->id], $this->mapAttributes($row, $categoryId), ); $institution->wasRecentlyCreated ? $summary->created++ : $summary->updated++; $this->syncOfficialLink($institution, (string) ($row->url ?? '')); } /** * Mappa una riga legacy sugli attributi del model v2 (con pulizia dei dati). * * @return array */ private function mapAttributes(object $row, int $categoryId): array { return [ 'category_id' => $categoryId, 'name' => trim((string) $row->name), 'abbreviation' => trim((string) $row->abbreviation), 'address' => trim((string) $row->address), 'city' => trim((string) $row->city), 'lat' => $row->lat, 'lon' => $row->lon, 'logo' => trim((string) $row->logo), 'color' => $this->cleanColor($row->color), 'is_storage_place' => (bool) $row->is_storage_place, ]; } /** * Colore valido o fallback al default v2. */ private function cleanColor(mixed $color): string { $color = trim((string) ($color ?? '')); return $color !== '' ? $color : '#c5cae9'; } /** * Sincronizza il link "official" dall'unico `url` legacy. Idempotente * (upsert su institution_id + type). URL vuoto/blank → nessun link. */ private function syncOfficialLink(Institution $institution, string $url): void { $url = trim($url); if ($url === '') { return; } InstitutionLink::updateOrCreate( [ 'institution_id' => $institution->id, 'type' => InstitutionLinkType::Official, ], [ 'url' => $url, 'sort_order' => 0, ], ); } }