info('Starting optimized journalist migration with document support...'); $legacyConn = DB::connection('mysql_second'); $query = $legacyConn->table('journalists'); $totalCount = $query->count(); if ($totalCount === 0) { $this->warn('No journalists found in legacy database.'); return; } $this->info("Found {$totalCount} legacy journalist records."); // Pre-cache migrated IDs $this->migratedIds = DB::table('media') ->where('model_type', Journalist::class) ->where('collection_name', 'journalists') ->pluck('model_id') ->flip() ->all(); $query->orderBy('id')->chunk(50, function ($chunk) { foreach ($chunk as $legacy) { $this->processJournalist($legacy); } }); $this->newLine(); $this->info('Journalist migration completed successfully!'); } /** * Process a single legacy journalist record. */ private function processJournalist($legacy): void { $idText = "[#{$legacy->id}]"; $idOutput = $legacy->deleted_at ? "{$idText}" : "{$idText}"; $this->output->write("{$idOutput} Processing: ".Str::limit($legacy->name, 40).'... '); try { // Find corresponding partner media $partnerMedia = DB::table('partner_media')->where('id', $legacy->media)->first(); if (! $partnerMedia) { $this->output->writeln('OUTLET NOT FOUND'); return; } // 1. Update/Insert Journalist DB::table('journalists')->updateOrInsert( ['id' => $legacy->id], [ 'partner_media_id' => $partnerMedia->id, 'name' => Str::limit($legacy->name, 100), 'email' => Str::limit($legacy->email, 254), 'phone_number' => Str::limit($legacy->phone, 20), 'press_card' => Str::limit($legacy->press_card, 100), 'ukw_certificate' => Str::limit($legacy->certificate, 100), 'created_at' => $legacy->created_at ?? now(), 'updated_at' => $legacy->updated_at ?? now(), 'deleted_at' => $legacy->deleted_at, ] ); // 2. Media Documents Migration (Skip if already has media) if (isset($this->migratedIds[$legacy->id])) { $this->output->writeln('DONE (SKIP DOCS)'); return; } $journalist = Journalist::withTrashed()->find($legacy->id); if ($journalist) { $this->migrateJournalistDocuments($journalist, $legacy); } $this->output->writeln('DONE + DOCS'); } catch (\Exception $e) { $this->output->writeln('FAILED: '.$e->getMessage().''); } } /** * Migrate journalist documents from S3. */ private function migrateJournalistDocuments(Journalist $journalist, $legacy): void { $docMapping = [ 'doc_of_press_card' => 'press-card', 'doc_of_certificate' => 'ukw-certificate', ]; foreach ($docMapping as $legacyField => $docType) { $legacyPath = trim($legacy->{$legacyField} ?? ''); if (empty($legacyPath) || $legacyPath === '-' || $legacyPath === 'no-image.png') { continue; } // Path mapping: old-data/companies/ + path from db (based on legacy structure) $sourcePath = 'old-data/companies/'.$legacyPath; $this->importOneDocument($journalist, $sourcePath, $docType, $legacy); } } /** * Import a single document to Media Library. */ private function importOneDocument(Journalist $journalist, string $sourcePath, string $docType, $legacy): void { $attempts = 0; $maxAttempts = 3; $exists = false; while ($attempts < $maxAttempts) { try { $exists = Storage::disk('s3')->exists($sourcePath); break; } catch (\Exception $e) { $attempts++; usleep(200000); } } if (! $exists) { return; } try { $journalist->addMediaFromDisk($sourcePath, 's3') ->withCustomProperties([ 'feature' => 'journalists', 'date' => Carbon::parse($legacy->created_at ?? now())->toDateString(), 'doc_type' => $docType, ]) ->preservingOriginal() ->toMediaCollection('journalists', 's3'); } catch (\Exception $e) { // Log quietly } } }