From ab96ca627840761daf4029eac8930a89d08d29c4 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Wed, 22 Apr 2026 11:10:09 +0700 Subject: [PATCH] refactor: streamline media import process across migration commands by replacing S3 checks with direct database inserts and enhancing mime type handling --- .../Commands/MigrateCompanyCommand.php | 162 ++++++++-------- .../Commands/MigrateContentRecapCommand.php | 68 +++---- .../Commands/MigrateJournalistCommand.php | 69 +++---- .../MigrateMediaCooperationCommand.php | 54 ++++-- .../MigrateMediaMonitoringCommand.php | 76 ++++---- .../Commands/MigrateMediaOrdersCommand.php | 122 ++++++------ app/Console/Commands/MigrateNewsCommand.php | 76 ++++---- .../Commands/MigrateReportsCommand.php | 66 ++++--- .../Partners/Infolists/PartnerInfolist.php | 173 +++++++++++------- app/MediaLibrary/CustomPathGenerator.php | 6 + 10 files changed, 475 insertions(+), 397 deletions(-) diff --git a/app/Console/Commands/MigrateCompanyCommand.php b/app/Console/Commands/MigrateCompanyCommand.php index 24440db..b1d0ec3 100644 --- a/app/Console/Commands/MigrateCompanyCommand.php +++ b/app/Console/Commands/MigrateCompanyCommand.php @@ -13,8 +13,6 @@ use Carbon\Carbon; use Illuminate\Console\Command; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Storage; -use Illuminate\Support\Str; class MigrateCompanyCommand extends Command { @@ -94,7 +92,7 @@ private function processCompany($legacy): void $idText = "[#{$legacy->id}]"; $idOutput = $legacy->deleted_at ? "{$idText}" : "{$idText}"; - $this->output->write("{$idOutput} Processing: ".Str::limit($legacy->name, 40).'... '); + $this->output->write("{$idOutput} Processing: ".str()->limit($legacy->name, 40).'... '); try { $legacyConn = DB::connection('mysql_second'); @@ -124,13 +122,13 @@ private function processCompany($legacy): void 'address' => $legacy->address, 'director_name' => $legacy->director, 'director_nik' => $legacy->nick_director, - 'deed_incorporation' => Str::limit($legacy->deed_of_establishment, 150, ''), - 'trade_license' => Str::limit($legacy->trade_license, 150, ''), - 'tax_id_number' => Str::limit($legacy->tax_id_number, 150, ''), - 'taxable_enterprise' => Str::limit($legacy->taxable_enterprise, 150, ''), - 'annual_tax_return' => Str::limit($legacy->annual_tax_statement, 150, ''), - 'domicile_certificate' => Str::limit($legacy->domicile, 150, ''), - 'profile' => Str::limit($legacy->profile ?? '-', 150, ''), + 'deed_incorporation' => str()->limit($legacy->deed_of_establishment, 150, ''), + 'trade_license' => str()->limit($legacy->trade_license, 150, ''), + 'tax_id_number' => str()->limit($legacy->tax_id_number, 150, ''), + 'taxable_enterprise' => str()->limit($legacy->taxable_enterprise, 150, ''), + 'annual_tax_return' => str()->limit($legacy->annual_tax_statement, 150, ''), + 'domicile_certificate' => str()->limit($legacy->domicile, 150, ''), + 'profile' => str()->limit($legacy->profile ?? '-', 150, ''), 'created_at' => $legacy->created_at ?? now(), 'updated_at' => $legacy->updated_at ?? now(), 'deleted_at' => $legacy->deleted_at, @@ -240,13 +238,13 @@ private function handlePartnerMedia($legacy): void private function migrateAllDocuments(Company $company, $legacy): void { $docMapping = [ - 'doc_of_nick_director' => 'director_nik', - 'doc_of_deed_of_establishment' => 'deed_incorporation', - 'doc_of_trade_license' => 'trade_license', - 'doc_of_tax_id_number' => 'tax_id_number', - 'doc_of_taxable_enterprise' => 'taxable_enterprise', - 'doc_of_annual_tax_statement' => 'annual_tax_return', - 'doc_of_domicile' => 'domicile_certificate', + 'doc_of_nick_director' => 'director-nik', + 'doc_of_deed_of_establishment' => 'deed-incorporation', + 'doc_of_trade_license' => 'trade-license', + 'doc_of_tax_id_number' => 'tax-id-number', + 'doc_of_taxable_enterprise' => 'taxable-enterprise', + 'doc_of_annual_tax_statement' => 'annual-tax-return', + 'doc_of_domicile' => 'domicile-certificate', 'doc_of_profile' => 'profile', ]; @@ -264,40 +262,37 @@ private function migrateAllDocuments(Company $company, $legacy): void } /** - * Import a single document to Media Library. + * Import a single document to Media Library (insert record only, no file copy). */ private function importOneDocument(Company $company, string $sourcePath, string $docType, $legacy): void { - $attempts = 0; - $maxAttempts = 3; - $exists = false; + $fileName = basename($sourcePath); + $legacyDir = dirname($sourcePath); // e.g. old-data/companies/subdir - while ($attempts < $maxAttempts) { - try { - $exists = Storage::disk('s3')->exists($sourcePath); - break; - } catch (\Exception $e) { - $attempts++; - usleep(200000); - } - } - - if (! $exists) { - return; - } - - try { - $company->addMediaFromDisk($sourcePath, 's3') - ->withCustomProperties([ - 'feature' => 'companies', - 'date' => Carbon::parse($legacy->created_at ?? now())->toDateString(), - 'doc_type' => $docType, // Match CompanySaveService slug pattern - ]) - ->preservingOriginal() - ->toMediaCollection('companies', 's3'); - } catch (\Exception $e) { - // Log quietly or handle error - } + DB::table('media')->insert([ + 'model_type' => Company::class, + 'model_id' => $company->id, + 'uuid' => (string) str()->uuid(), + 'collection_name' => 'companies', + 'name' => pathinfo($fileName, PATHINFO_FILENAME), + 'file_name' => $fileName, + 'mime_type' => $this->guessMime($fileName), + 'disk' => 's3', + 'conversions_disk' => 's3', + 'size' => 0, + 'manipulations' => '[]', + 'custom_properties' => json_encode([ + 'feature' => 'companies', + 'date' => Carbon::parse($legacy->created_at ?? now())->toDateString(), + 'doc_type' => $docType, + 'legacy_dir' => $legacyDir, + ]), + 'generated_conversions' => '[]', + 'responsive_images' => '[]', + 'order_column' => 1, + 'created_at' => now(), + 'updated_at' => now(), + ]); } /** @@ -324,40 +319,49 @@ private function migrateMediaDocuments(PartnerMedia $media, $legacyMedia): void } /** - * Import a single media document to Media Library. + * Import a single media document to Media Library (insert record only, no file copy). */ private function importOneMediaDocument(PartnerMedia $media, string $sourcePath, string $docType, $legacyMedia): void { - $attempts = 0; - $maxAttempts = 3; - $exists = false; + $fileName = basename($sourcePath); + $legacyDir = dirname($sourcePath); // e.g. old-data/media/subdir - while ($attempts < $maxAttempts) { - try { - $exists = Storage::disk('s3')->exists($sourcePath); - break; - } catch (\Exception $e) { - $attempts++; - usleep(200000); - } - } + DB::table('media')->insert([ + 'model_type' => PartnerMedia::class, + 'model_id' => $media->id, + 'uuid' => (string) str()->uuid(), + 'collection_name' => 'partnerMedia', + 'name' => pathinfo($fileName, PATHINFO_FILENAME), + 'file_name' => $fileName, + 'mime_type' => $this->guessMime($fileName), + 'disk' => 's3', + 'conversions_disk' => 's3', + 'size' => 0, + 'manipulations' => '[]', + 'custom_properties' => json_encode([ + 'feature' => 'media', + 'date' => Carbon::parse($legacyMedia->created_at ?? now())->toDateString(), + 'doc_type' => $docType, + 'legacy_dir' => $legacyDir, + ]), + 'generated_conversions' => '[]', + 'responsive_images' => '[]', + 'order_column' => 1, + 'created_at' => now(), + 'updated_at' => now(), + ]); + } - if (! $exists) { - return; - } - - try { - $media->addMediaFromDisk($sourcePath, 's3') - ->withCustomProperties([ - 'feature' => 'media', - 'date' => Carbon::parse($legacyMedia->created_at ?? now())->toDateString(), - 'doc_type' => $docType, // Match MediaSaveService slug pattern - ]) - ->preservingOriginal() - ->toMediaCollection('partnerMedia', 's3'); - } catch (\Exception $e) { - // Log quietly or handle error - } + private function guessMime(string $fileName): string + { + return match (strtolower(pathinfo($fileName, PATHINFO_EXTENSION))) { + 'pdf' => 'application/pdf', + 'jpg', 'jpeg' => 'image/jpeg', + 'png' => 'image/png', + 'doc' => 'application/msword', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + default => 'application/octet-stream', + }; } // ... mapping methods (mapVerificationStatus, mapDecision, mapMediaType, mapMediaClassification, extractMediaLink) remain as previously defined @@ -408,7 +412,7 @@ private function extractMediaLink(?string $link): ?string } preg_match_all('/(https?:\/\/[^\s]+)/i', $link, $matches); if (empty($matches[0])) { - return Str::limit($link, 255, ''); + return str()->limit($link, 255, ''); } foreach ($matches[0] as $url) { $url = rtrim($url, ','); @@ -416,9 +420,9 @@ private function extractMediaLink(?string $link): ?string continue; } - return Str::limit($url, 255, ''); + return str()->limit($url, 255, ''); } - return Str::limit($matches[0][0], 255, ''); + return str()->limit($matches[0][0], 255, ''); } } diff --git a/app/Console/Commands/MigrateContentRecapCommand.php b/app/Console/Commands/MigrateContentRecapCommand.php index 891a26c..e24d8ab 100644 --- a/app/Console/Commands/MigrateContentRecapCommand.php +++ b/app/Console/Commands/MigrateContentRecapCommand.php @@ -10,7 +10,6 @@ use Illuminate\Console\Command; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; class MigrateContentRecapCommand extends Command @@ -165,40 +164,45 @@ private function migrateMedia(ContentRecap $recap, $legacy): void { $filename = trim(basename($legacy->image)); $sourcePath = 'old-data/content-recaps/'.$filename; + $legacyDir = dirname($sourcePath); - $attempts = 0; - $maxAttempts = 3; - $exists = false; + DB::table('media')->insert([ + 'model_type' => ContentRecap::class, + 'model_id' => $recap->id, + 'uuid' => (string) Str::uuid(), + 'collection_name' => 'content-recaps', // Match typo in ContentRecapForm + 'name' => pathinfo($filename, PATHINFO_FILENAME), + 'file_name' => $filename, + 'mime_type' => $this->guessMime($filename), + 'disk' => 's3', + 'conversions_disk' => 's3', + 'size' => 0, + 'manipulations' => '[]', + 'custom_properties' => json_encode([ + 'feature' => 'content-recaps', + 'date' => Carbon::parse($legacy->created_at ?? now())->toDateString(), + 'legacy_dir' => $legacyDir, + ]), + 'generated_conversions' => '[]', + 'responsive_images' => '[]', + 'order_column' => 1, + 'created_at' => now(), + 'updated_at' => now(), + ]); - while ($attempts < $maxAttempts) { - try { - $exists = Storage::disk('s3')->exists($sourcePath); - break; - } catch (\Exception $e) { - $attempts++; - usleep(200000); - } - } + $this->output->writeln('DONE + IMG'); + } - if (! $exists) { - $this->output->writeln('IMAGE MISSING'); - - return; - } - - try { - $recap->addMediaFromDisk($sourcePath, 's3') - ->withCustomProperties([ - 'feature' => 'content-recaps', - 'date' => Carbon::parse($legacy->created_at ?? now())->toDateString(), - ]) - ->preservingOriginal() - ->toMediaCollection('content-recaps', 's3'); // Match typo in ContentRecapForm - - $this->output->writeln('DONE + IMG'); - } catch (\Exception $e) { - $this->output->writeln('S3 ERROR: '.Str::limit($e->getMessage(), 50).''); - } + private function guessMime(string $fileName): string + { + return match (strtolower(pathinfo($fileName, PATHINFO_EXTENSION))) { + 'pdf' => 'application/pdf', + 'jpg', 'jpeg' => 'image/jpeg', + 'png' => 'image/png', + 'doc' => 'application/msword', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + default => 'application/octet-stream', + }; } private function mapContentType(?string $legacyType): ?int diff --git a/app/Console/Commands/MigrateJournalistCommand.php b/app/Console/Commands/MigrateJournalistCommand.php index 06aadd5..6c5a865 100644 --- a/app/Console/Commands/MigrateJournalistCommand.php +++ b/app/Console/Commands/MigrateJournalistCommand.php @@ -6,7 +6,6 @@ use Illuminate\Console\Command; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; class MigrateJournalistCommand extends Command @@ -143,40 +142,46 @@ private function migrateJournalistDocuments(Journalist $journalist, $legacy): vo } } - /** - * Import a single document to Media Library. - */ private function importOneDocument(Journalist $journalist, string $sourcePath, string $docType, $legacy): void { - $attempts = 0; - $maxAttempts = 3; - $exists = false; + $fileName = basename($sourcePath); + $legacyDir = dirname($sourcePath); // e.g. old-data/companies/subdir - while ($attempts < $maxAttempts) { - try { - $exists = Storage::disk('s3')->exists($sourcePath); - break; - } catch (\Exception $e) { - $attempts++; - usleep(200000); - } - } + DB::table('media')->insert([ + 'model_type' => Journalist::class, + 'model_id' => $journalist->id, + 'uuid' => (string) Str::uuid(), + 'collection_name' => 'journalists', + 'name' => pathinfo($fileName, PATHINFO_FILENAME), + 'file_name' => $fileName, + 'mime_type' => $this->guessMime($fileName), + 'disk' => 's3', + 'conversions_disk' => 's3', + 'size' => 0, + 'manipulations' => '[]', + 'custom_properties' => json_encode([ + 'feature' => 'journalists', + 'date' => Carbon::parse($legacy->created_at ?? now())->toDateString(), + 'doc_type' => $docType, + 'legacy_dir' => $legacyDir, + ]), + 'generated_conversions' => '[]', + 'responsive_images' => '[]', + 'order_column' => 1, + 'created_at' => now(), + 'updated_at' => now(), + ]); + } - 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 - } + private function guessMime(string $fileName): string + { + return match (strtolower(pathinfo($fileName, PATHINFO_EXTENSION))) { + 'pdf' => 'application/pdf', + 'jpg', 'jpeg' => 'image/jpeg', + 'png' => 'image/png', + 'doc' => 'application/msword', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + default => 'application/octet-stream', + }; } } diff --git a/app/Console/Commands/MigrateMediaCooperationCommand.php b/app/Console/Commands/MigrateMediaCooperationCommand.php index 42393b6..dc2cf77 100644 --- a/app/Console/Commands/MigrateMediaCooperationCommand.php +++ b/app/Console/Commands/MigrateMediaCooperationCommand.php @@ -11,7 +11,6 @@ use Illuminate\Support\Carbon; use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; class MigrateMediaCooperationCommand extends Command @@ -279,23 +278,44 @@ private function importOfferFile(int $proposalId, object $legacy): void // Adjust path based on where these files are stored in S3 $sourcePath = 'old-data/proposals/'.$legacyPath; + $fileName = basename($sourcePath); + $legacyDir = dirname($sourcePath); - try { - if (Storage::disk('s3')->exists($sourcePath)) { - $proposal = CooperationProposal::find($proposalId); - if ($proposal) { - $proposal->addMediaFromDisk($sourcePath, 's3') - ->withCustomProperties([ - 'feature' => 'proposals', - 'date' => Carbon::parse($legacy->created_at ?? now())->toDateString(), - ]) - ->preservingOriginal() - ->toMediaCollection('proposals', 's3'); - } - } - } catch (\Exception $e) { - // Log silently - } + DB::table('media')->insert([ + 'model_type' => CooperationProposal::class, + 'model_id' => $proposalId, + 'uuid' => (string) Str::uuid(), + 'collection_name' => 'proposals', + 'name' => pathinfo($fileName, PATHINFO_FILENAME), + 'file_name' => $fileName, + 'mime_type' => $this->guessMime($fileName), + 'disk' => 's3', + 'conversions_disk' => 's3', + 'size' => 0, + 'manipulations' => '[]', + 'custom_properties' => json_encode([ + 'feature' => 'proposals', + 'date' => Carbon::parse($legacy->created_at ?? now())->toDateString(), + 'legacy_dir' => $legacyDir, + ]), + 'generated_conversions' => '[]', + 'responsive_images' => '[]', + 'order_column' => 1, + 'created_at' => now(), + 'updated_at' => now(), + ]); + } + + private function guessMime(string $fileName): string + { + return match (strtolower(pathinfo($fileName, PATHINFO_EXTENSION))) { + 'pdf' => 'application/pdf', + 'jpg', 'jpeg' => 'image/jpeg', + 'png' => 'image/png', + 'doc' => 'application/msword', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + default => 'application/octet-stream', + }; } private function mapApprovalStatus(string $legacyStatus): int diff --git a/app/Console/Commands/MigrateMediaMonitoringCommand.php b/app/Console/Commands/MigrateMediaMonitoringCommand.php index 5d4b839..bb4a5d7 100644 --- a/app/Console/Commands/MigrateMediaMonitoringCommand.php +++ b/app/Console/Commands/MigrateMediaMonitoringCommand.php @@ -8,7 +8,6 @@ use Illuminate\Console\Command; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; class MigrateMediaMonitoringCommand extends Command @@ -166,48 +165,45 @@ private function migrateMedia(MediaMonitoring $monitoring, $legacy): void { $filename = trim(basename($legacy->image)); $sourcePath = 'old-data/mediamonitorings/'.$filename; + $legacyDir = dirname($sourcePath); - $exists = false; - $attempts = 0; - $maxAttempts = 3; + DB::table('media')->insert([ + 'model_type' => MediaMonitoring::class, + 'model_id' => $monitoring->id, + 'uuid' => (string) Str::uuid(), + 'collection_name' => 'media-monitorings', + 'name' => pathinfo($filename, PATHINFO_FILENAME), + 'file_name' => $filename, + 'mime_type' => $this->guessMime($filename), + 'disk' => 's3', + 'conversions_disk' => 's3', + 'size' => 0, + 'manipulations' => '[]', + 'custom_properties' => json_encode([ + 'feature' => 'media-monitorings', + 'date' => Carbon::parse($legacy->created_at ?? now())->toDateString(), + 'legacy_dir' => $legacyDir, + ]), + 'generated_conversions' => '[]', + 'responsive_images' => '[]', + 'order_column' => 1, + 'created_at' => now(), + 'updated_at' => now(), + ]); - while ($attempts < $maxAttempts) { - try { - $exists = Storage::disk('s3')->exists($sourcePath); - break; - } catch (\Exception $e) { - $attempts++; - if ($attempts >= $maxAttempts) { - $actualError = $e->getPrevious() ? $e->getPrevious()->getMessage() : $e->getMessage(); - $this->output->writeln("S3 ERROR ({$attempts}x): ".Str::limit($actualError, 50).''); + $this->output->writeln('DONE + IMG'); + } - return; - } - usleep(200000); - } - } - - if (! $exists) { - $this->output->writeln('IMAGE MISSING'); - - return; - } - - try { - $date = Carbon::parse($legacy->created_at ?? now())->toDateString(); - - $monitoring->addMediaFromDisk($sourcePath, 's3') - ->withCustomProperties([ - 'feature' => 'media-monitorings', - 'date' => $date, - ]) - ->preservingOriginal() - ->toMediaCollection('media-monitorings', 's3'); - - $this->output->writeln('DONE + IMG'); - } catch (\Exception $e) { - $this->output->writeln('FAILED: '.$e->getMessage().''); - } + private function guessMime(string $fileName): string + { + return match (strtolower(pathinfo($fileName, PATHINFO_EXTENSION))) { + 'pdf' => 'application/pdf', + 'jpg', 'jpeg' => 'image/jpeg', + 'png' => 'image/png', + 'doc' => 'application/msword', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + default => 'application/octet-stream', + }; } /** diff --git a/app/Console/Commands/MigrateMediaOrdersCommand.php b/app/Console/Commands/MigrateMediaOrdersCommand.php index ff02076..a107feb 100644 --- a/app/Console/Commands/MigrateMediaOrdersCommand.php +++ b/app/Console/Commands/MigrateMediaOrdersCommand.php @@ -10,7 +10,6 @@ use Illuminate\Support\Carbon; use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; class MigrateMediaOrdersCommand extends Command @@ -278,36 +277,33 @@ private function migrateOfferFiles(Cooperation $cooperation, Collection $group): */ private function importOfferFile(Cooperation $cooperation, string $sourcePath, object $item): void { - $attempts = 0; - $maxAttempts = 3; - $exists = false; + $fileName = basename($sourcePath); + $legacyDir = dirname($sourcePath); - while ($attempts < $maxAttempts) { - try { - $exists = Storage::disk('s3')->exists($sourcePath); - break; - } catch (\Exception $e) { - $attempts++; - usleep(200000); - } - } - - if (! $exists) { - return; - } - - try { - $cooperation->addMediaFromDisk($sourcePath, 's3') - ->withCustomProperties([ - 'feature' => 'cooperations', - 'date' => Carbon::parse($item->created_at ?? now())->toDateString(), - 'doc_type' => 'proposal-template', - ]) - ->preservingOriginal() - ->toMediaCollection('cooperations', 's3'); - } catch (\Exception $e) { - // Log quietly or handle error - } + DB::table('media')->insert([ + 'model_type' => Cooperation::class, + 'model_id' => $cooperation->id, + 'uuid' => (string) Str::uuid(), + 'collection_name' => 'cooperations', + 'name' => pathinfo($fileName, PATHINFO_FILENAME), + 'file_name' => $fileName, + 'mime_type' => $this->guessMime($fileName), + 'disk' => 's3', + 'conversions_disk' => 's3', + 'size' => 0, + 'manipulations' => '[]', + 'custom_properties' => json_encode([ + 'feature' => 'cooperations', + 'date' => Carbon::parse($item->created_at ?? now())->toDateString(), + 'doc_type' => 'proposal-template', + 'legacy_dir' => $legacyDir, + ]), + 'generated_conversions' => '[]', + 'responsive_images' => '[]', + 'order_column' => 1, + 'created_at' => now(), + 'updated_at' => now(), + ]); } private function insertMediaTaskAssignment( @@ -470,37 +466,45 @@ private function migrateProof(Report $report, object $legacy): void } $sourcePath = 'old-data/reports/'.$legacyPath; + $fileName = basename($sourcePath); + $legacyDir = dirname($sourcePath); - $attempts = 0; - $maxAttempts = 3; - $exists = false; + DB::table('media')->insert([ + 'model_type' => Report::class, + 'model_id' => $report->id, + 'uuid' => (string) Str::uuid(), + 'collection_name' => 'reports', + 'name' => pathinfo($fileName, PATHINFO_FILENAME), + 'file_name' => $fileName, + 'mime_type' => $this->guessMime($fileName), + 'disk' => 's3', + 'conversions_disk' => 's3', + 'size' => 0, + 'manipulations' => '[]', + 'custom_properties' => json_encode([ + 'feature' => 'reports', + 'date' => Carbon::parse($legacy->created_at ?? now())->toDateString(), + 'doc_type' => 'proof', + 'legacy_dir' => $legacyDir, + ]), + 'generated_conversions' => '[]', + 'responsive_images' => '[]', + 'order_column' => 1, + 'created_at' => now(), + 'updated_at' => now(), + ]); + } - while ($attempts < $maxAttempts) { - try { - $exists = Storage::disk('s3')->exists($sourcePath); - break; - } catch (\Exception $e) { - $attempts++; - usleep(200000); - } - } - - if (! $exists) { - return; - } - - try { - $report->addMediaFromDisk($sourcePath, 's3') - ->withCustomProperties([ - 'feature' => 'reports', - 'date' => Carbon::parse($legacy->created_at ?? now())->toDateString(), - 'doc_type' => 'proof', - ]) - ->preservingOriginal() - ->toMediaCollection('reports', 's3'); - } catch (\Exception $e) { - // Log quietly or handle error - } + private function guessMime(string $fileName): string + { + return match (strtolower(pathinfo($fileName, PATHINFO_EXTENSION))) { + 'pdf' => 'application/pdf', + 'jpg', 'jpeg' => 'image/jpeg', + 'png' => 'image/png', + 'doc' => 'application/msword', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + default => 'application/octet-stream', + }; } /** diff --git a/app/Console/Commands/MigrateNewsCommand.php b/app/Console/Commands/MigrateNewsCommand.php index ece0ff0..446651a 100644 --- a/app/Console/Commands/MigrateNewsCommand.php +++ b/app/Console/Commands/MigrateNewsCommand.php @@ -7,7 +7,6 @@ use Illuminate\Console\Command; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; class MigrateNewsCommand extends Command @@ -131,47 +130,44 @@ private function migrateMedia(News $news, $legacy): void { $filename = trim(basename($legacy->image)); $sourcePath = 'old-data/news/'.$filename; + $legacyDir = dirname($sourcePath); - $exists = false; - $attempts = 0; - $maxAttempts = 3; + DB::table('media')->insert([ + 'model_type' => News::class, + 'model_id' => $news->id, + 'uuid' => (string) Str::uuid(), + 'collection_name' => 'news', + 'name' => pathinfo($filename, PATHINFO_FILENAME), + 'file_name' => $filename, + 'mime_type' => $this->guessMime($filename), + 'disk' => 's3', + 'conversions_disk' => 's3', + 'size' => 0, + 'manipulations' => '[]', + 'custom_properties' => json_encode([ + 'feature' => 'news', + 'date' => Carbon::parse($legacy->created_at ?? now())->toDateString(), + 'legacy_dir' => $legacyDir, + ]), + 'generated_conversions' => '[]', + 'responsive_images' => '[]', + 'order_column' => 1, + 'created_at' => now(), + 'updated_at' => now(), + ]); - while ($attempts < $maxAttempts) { - try { - $exists = Storage::disk('s3')->exists($sourcePath); - break; - } catch (\Exception $e) { - $attempts++; - if ($attempts >= $maxAttempts) { - $actualError = $e->getPrevious() ? $e->getPrevious()->getMessage() : $e->getMessage(); - $this->output->writeln("S3 ERROR ({$attempts}x): ".$actualError.''); + $this->output->writeln('DONE + IMG'); + } - return; - } - usleep(200000); - } - } - - if (! $exists) { - $this->output->writeln('IMAGE MISSING'); - - return; - } - - try { - $date = Carbon::parse($legacy->created_at ?? now())->toDateString(); - - $news->addMediaFromDisk($sourcePath, 's3') - ->withCustomProperties([ - 'feature' => 'news', - 'date' => $date, - ]) - ->preservingOriginal() - ->toMediaCollection('news', 's3'); - - $this->output->writeln('DONE + IMG'); - } catch (\Exception $e) { - $this->output->writeln("FAILED: {$e->getMessage()}"); - } + private function guessMime(string $fileName): string + { + return match (strtolower(pathinfo($fileName, PATHINFO_EXTENSION))) { + 'pdf' => 'application/pdf', + 'jpg', 'jpeg' => 'image/jpeg', + 'png' => 'image/png', + 'doc' => 'application/msword', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + default => 'application/octet-stream', + }; } } diff --git a/app/Console/Commands/MigrateReportsCommand.php b/app/Console/Commands/MigrateReportsCommand.php index 63e8be4..281b6fc 100644 --- a/app/Console/Commands/MigrateReportsCommand.php +++ b/app/Console/Commands/MigrateReportsCommand.php @@ -7,7 +7,6 @@ use Illuminate\Console\Command; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; class MigrateReportsCommand extends Command @@ -182,36 +181,45 @@ private function migrateProof(Report $report, object $legacy): void */ private function importProofFile(Report $report, string $sourcePath, object $legacy): void { - $attempts = 0; - $maxAttempts = 3; - $exists = false; + $fileName = basename($sourcePath); + $legacyDir = dirname($sourcePath); - while ($attempts < $maxAttempts) { - try { - $exists = Storage::disk('s3')->exists($sourcePath); - break; - } catch (\Exception $e) { - $attempts++; - usleep(200000); - } - } + DB::table('media')->insert([ + 'model_type' => Report::class, + 'model_id' => $report->id, + 'uuid' => (string) Str::uuid(), + 'collection_name' => 'reports', + 'name' => pathinfo($fileName, PATHINFO_FILENAME), + 'file_name' => $fileName, + 'mime_type' => $this->guessMime($fileName), + 'disk' => 's3', + 'conversions_disk' => 's3', + 'size' => 0, + 'manipulations' => '[]', + 'custom_properties' => json_encode([ + 'feature' => 'reports', + 'date' => Carbon::parse($legacy->created_at ?? now())->toDateString(), + 'doc_type' => 'proof', + 'legacy_dir' => $legacyDir, + ]), + 'generated_conversions' => '[]', + 'responsive_images' => '[]', + 'order_column' => 1, + 'created_at' => now(), + 'updated_at' => now(), + ]); + } - if (! $exists) { - return; - } - - try { - $report->addMediaFromDisk($sourcePath, 's3') - ->withCustomProperties([ - 'feature' => 'reports', - 'date' => Carbon::parse($legacy->created_at ?? now())->toDateString(), - 'doc_type' => 'proof', - ]) - ->preservingOriginal() - ->toMediaCollection('reports', 's3'); - } catch (\Exception $e) { - // Log quietly or handle error - } + private function guessMime(string $fileName): string + { + return match (strtolower(pathinfo($fileName, PATHINFO_EXTENSION))) { + 'pdf' => 'application/pdf', + 'jpg', 'jpeg' => 'image/jpeg', + 'png' => 'image/png', + 'doc' => 'application/msword', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + default => 'application/octet-stream', + }; } /** diff --git a/app/Filament/Resources/Manage/Partners/Infolists/PartnerInfolist.php b/app/Filament/Resources/Manage/Partners/Infolists/PartnerInfolist.php index 0d04ced..4f7f644 100644 --- a/app/Filament/Resources/Manage/Partners/Infolists/PartnerInfolist.php +++ b/app/Filament/Resources/Manage/Partners/Infolists/PartnerInfolist.php @@ -92,46 +92,7 @@ public static function configure(Schema $schema): Schema TextEntry::make('company.director_nik') ->hiddenLabel(), - TextEntry::make('company.director_nik_docs') - ->hiddenLabel() - ->html() - ->getStateUsing(function (User $record): string { - $media = $record->company - ?->getMedia('companies') - ->where('custom_properties.doc_type', 'director-nik') - ->sortByDesc('created_at') - ->first(); - - if (! $media) { - return ''; - } - - $url = $media->getUrl(); - $mime = $media->mime_type; - - $downloadLink = ' - - - - Unduh Dokumen - '; - - if (str_contains($mime, 'image')) { - return '
'. - 'Dokumen NIK Direktur'. - $downloadLink. - '
'; - } - - if (str_contains($mime, 'pdf')) { - return '
'. - ''. - $downloadLink. - '
'; - } - - return $downloadLink; - }), + ...self::fileEntries('company.director_nik'), ]), Section::make('Akta Pendirian') @@ -139,7 +100,7 @@ public static function configure(Schema $schema): Schema TextEntry::make('company.deed_incorporation') ->hiddenLabel(), - self::fileEntry('company.deed_incorporation'), + ...self::fileEntries('company.tax_id_number'), ]), Section::make('SIUP / NIB') @@ -147,7 +108,7 @@ public static function configure(Schema $schema): Schema TextEntry::make('company.trade_license') ->hiddenLabel(), - self::fileEntry('company.trade_license'), + ...self::fileEntries('company.trade_license'), ]), Section::make('NPWP') @@ -155,7 +116,7 @@ public static function configure(Schema $schema): Schema TextEntry::make('company.tax_id_number') ->hiddenLabel(), - self::fileEntry('company.tax_id_number'), + ...self::fileEntries('company.tax_id_number'), ]), Section::make('PKP') @@ -163,7 +124,7 @@ public static function configure(Schema $schema): Schema TextEntry::make('company.taxable_enterprise') ->hiddenLabel(), - self::fileEntry('company.taxable_enterprise'), + ...self::fileEntries('company.taxable_enterprise'), ]), Section::make('SPT Tahunan') @@ -171,7 +132,7 @@ public static function configure(Schema $schema): Schema TextEntry::make('company.annual_tax_return') ->hiddenLabel(), - self::fileEntry('company.annual_tax_return'), + ...self::fileEntries('company.annual_tax_return'), ]), Section::make('Suket Domisili') @@ -179,7 +140,7 @@ public static function configure(Schema $schema): Schema TextEntry::make('company.domicile_certificate') ->hiddenLabel(), - self::fileEntry('company.domicile_certificate'), + ...self::fileEntries('company.domicile_certificate'), ]), Section::make('Profil Perusahaan') @@ -187,7 +148,7 @@ public static function configure(Schema $schema): Schema TextEntry::make('company.profile') ->hiddenLabel(), - self::fileEntry('company.profile'), + ...self::fileEntries('company.profile'), ]), ]), ]), @@ -224,7 +185,7 @@ public static function configure(Schema $schema): Schema TextEntry::make('company.partnerMedia.journalism_organization') ->hiddenLabel(), - self::fileEntry('company.partnerMedia.journalism_organization', 'company.partnerMedia', 'partnerMedia'), + ...self::fileEntries('company.partnerMedia.journalism_organization', 'company.partnerMedia', 'partnerMedia'), ]), Section::make('Sertifikat Dewan Pers') @@ -232,7 +193,7 @@ public static function configure(Schema $schema): Schema TextEntry::make('company.partnerMedia.press_council_certificate') ->hiddenLabel(), - self::fileEntry('company.partnerMedia.press_council_certificate', 'company.partnerMedia', 'partnerMedia'), + ...self::fileEntries('company.partnerMedia.press_council_certificate', 'company.partnerMedia', 'partnerMedia'), ]), ]), ]), @@ -261,7 +222,7 @@ public static function configure(Schema $schema): Schema TextEntry::make('press_card') ->hiddenLabel(), - self::fileEntry('press_card', null, 'journalists'), + ...self::fileEntries('press_card', null, 'journalists'), ]), Section::make('Sertifikat UKW') @@ -269,7 +230,7 @@ public static function configure(Schema $schema): Schema TextEntry::make('ukw_certificate') ->hiddenLabel(), - self::fileEntry('ukw_certificate', null, 'journalists'), + ...self::fileEntries('ukw_certificate', null, 'journalists'), ]), ]), ]), @@ -278,29 +239,103 @@ public static function configure(Schema $schema): Schema ->columns(1); } - private static function fileEntry( + private static function fileEntries( string $name, ?string $mediaOwner = 'company', string $collection = 'companies' - ): PdfViewerEntry { - return PdfViewerEntry::make($name) - ->hiddenLabel() - ->getStateUsing(function (Model $record) use ($name, $mediaOwner, $collection): ?string { - $owner = $mediaOwner ? data_get($record, $mediaOwner) : $record; + ): array { + return [ + PdfViewerEntry::make($name.'_pdf') + ->hiddenLabel() + ->visible( + fn (Model $record) => self::isPdf($record, $name, $mediaOwner, $collection) + ) + ->getStateUsing( + fn (Model $record) => self::getFileUrl($record, $name, $mediaOwner, $collection) + ), - if (! $owner) { - return null; - } + TextEntry::make($name.'_image') + ->hiddenLabel() + ->html() + ->visible( + fn (Model $record) => self::isImage($record, $name, $mediaOwner, $collection) + ) + ->getStateUsing(function (Model $record) use ($name, $mediaOwner, $collection) { + $media = self::getMedia($record, $name, $mediaOwner, $collection); + $url = $media?->getUrl(); - $docType = str($name) - ->afterLast('.') - ->slug('-'); + if (! $url) { + return ''; + } - return $owner->getMedia($collection) - ->where('custom_properties.doc_type', (string) $docType) - ->sortByDesc('created_at') - ->first() - ?->getUrl(); - }); + $downloadUrl = $url; + + if ($media && in_array($media->disk, ['s3', 'minio'])) { + $downloadUrl = $media->getTemporaryUrl(now()->addMinutes(30), '', [ + 'ResponseContentDisposition' => 'attachment; filename="'.$media->file_name.'"', + ]); + } + + $downloadLink = ' + + + + Unduh Dokumen + '; + + return '
'. + 'Dokumen'. + $downloadLink. + '
'; + }), + ]; + } + + private static function getMedia( + Model $record, + string $name, + ?string $mediaOwner, + string $collection + ) { + $owner = $mediaOwner ? data_get($record, $mediaOwner) : $record; + + if (! $owner) { + return null; + } + + $docType = str($name)->afterLast('.')->slug('-'); + + return $owner->getMedia($collection) + ->where('custom_properties.doc_type', (string) $docType) + ->sortByDesc('created_at') + ->first(); + } + + private static function getFileUrl( + Model $record, + string $name, + ?string $mediaOwner, + string $collection + ): ?string { + return self::getMedia($record, $name, $mediaOwner, $collection)?->getUrl(); + } + + private static function getMime( + Model $record, + string $name, + ?string $mediaOwner, + string $collection + ): ?string { + return self::getMedia($record, $name, $mediaOwner, $collection)?->mime_type; + } + + private static function isPdf(...$args): bool + { + return str_contains(self::getMime(...$args) ?? '', 'pdf'); + } + + private static function isImage(...$args): bool + { + return str_contains(self::getMime(...$args) ?? '', 'image'); } } diff --git a/app/MediaLibrary/CustomPathGenerator.php b/app/MediaLibrary/CustomPathGenerator.php index 61c2445..a70b477 100644 --- a/app/MediaLibrary/CustomPathGenerator.php +++ b/app/MediaLibrary/CustomPathGenerator.php @@ -9,6 +9,12 @@ class CustomPathGenerator implements PathGenerator { public function getPath(Media $media): string { + // Data lama: arahkan ke path legacy di S3 + $legacyDir = $media->getCustomProperty('legacy_dir'); + if ($legacyDir) { + return rtrim($legacyDir, '/').'/'; + } + $feature = $media->getCustomProperty('feature', 'misc'); $date = $media->getCustomProperty('date', $media->created_at?->toDateString() ?? now()->toDateString()); $docType = $media->getCustomProperty('doc_type');