MediaReplaceDomainCommand.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <?php
  2. namespace App\Console\Commands;
  3. use App\Media;
  4. use App\Services\MediaService;
  5. use App\Services\StatusService;
  6. use Illuminate\Console\Command;
  7. use Illuminate\Support\Facades\DB;
  8. class MediaReplaceDomainCommand extends Command
  9. {
  10. protected $signature = 'media:replacedomain {--original= : Original domain to replace} {--new= : New domain to use}';
  11. protected $description = 'Replace CDN domain in media URLs and clear associated caches';
  12. public function handle()
  13. {
  14. $originalDomain = $this->option('original');
  15. $newDomain = $this->option('new');
  16. if (! $originalDomain || ! $newDomain) {
  17. $this->error('Both --original and --new options are required');
  18. return 1;
  19. }
  20. if (! str_starts_with($originalDomain, 'https://')) {
  21. $this->error('Original domain must start with https://');
  22. return 1;
  23. }
  24. if (! str_starts_with($newDomain, 'https://')) {
  25. $this->error('New domain must start with https://');
  26. return 1;
  27. }
  28. $originalDomain = rtrim($originalDomain, '/');
  29. $newDomain = rtrim($newDomain, '/');
  30. if (preg_match('/[^a-zA-Z0-9\-\._\/:]/', $originalDomain) ||
  31. preg_match('/[^a-zA-Z0-9\-\._\/:]/', $newDomain)) {
  32. $this->error('Domains contain invalid characters');
  33. return 1;
  34. }
  35. $sampleMedia = Media::where('cdn_url', 'LIKE', $originalDomain.'%')->first();
  36. if (! $sampleMedia) {
  37. $this->error('No media entries found with the specified domain.');
  38. return 1;
  39. }
  40. $sampleNewUrl = str_replace($originalDomain, $newDomain, $sampleMedia->cdn_url);
  41. $this->info('Please verify this URL transformation:');
  42. $this->newLine();
  43. $this->info('Original URL:');
  44. $this->line($sampleMedia->cdn_url);
  45. $this->info('Will be changed to:');
  46. $this->line($sampleNewUrl);
  47. $this->newLine();
  48. $this->info('Please verify in your browser that both URLs are accessible.');
  49. if (! $this->confirm('Do you want to proceed with the replacement?')) {
  50. $this->info('Operation cancelled.');
  51. return 0;
  52. }
  53. $query = Media::where('cdn_url', 'LIKE', $originalDomain.'%');
  54. $count = $query->count();
  55. $this->info("Found {$count} media entries to update.");
  56. $bar = $this->output->createProgressBar($count);
  57. $errors = [];
  58. $query->chunkById(1000, function ($medias) use ($originalDomain, $newDomain, $bar, &$errors) {
  59. foreach ($medias as $media) {
  60. try {
  61. if (! str_starts_with($media->cdn_url, 'https://')) {
  62. $errors[] = "Media ID {$media->id} has invalid URL format: {$media->cdn_url}";
  63. $bar->advance();
  64. continue;
  65. }
  66. DB::transaction(function () use ($media, $originalDomain, $newDomain) {
  67. $media->cdn_url = str_replace($originalDomain, $newDomain, $media->cdn_url);
  68. $media->save();
  69. if ($media->status_id) {
  70. MediaService::del($media->status_id);
  71. StatusService::del($media->status_id);
  72. }
  73. });
  74. $bar->advance();
  75. } catch (\Exception $e) {
  76. $errors[] = "Failed to update Media ID {$media->id}: {$e->getMessage()}";
  77. $bar->advance();
  78. }
  79. }
  80. });
  81. $bar->finish();
  82. $this->newLine();
  83. if (! empty($errors)) {
  84. $this->newLine();
  85. $this->warn('Completed with errors:');
  86. foreach ($errors as $error) {
  87. $this->error($error);
  88. }
  89. return 1;
  90. }
  91. $this->info('Domain replacement completed successfully.');
  92. return 0;
  93. }
  94. }