Skip to content

Instantly share code, notes, and snippets.

@viirre
Last active September 9, 2020 13:44
Show Gist options
  • Save viirre/56998afdb5fde19b0fe438db0ca62768 to your computer and use it in GitHub Desktop.
Save viirre/56998afdb5fde19b0fe438db0ca62768 to your computer and use it in GitHub Desktop.
Upgrade Script Medialibrary v6 to v7
<?php
// Blogpost: XXX
// Assumes you have created a new column on your `media` table called `converted` (boolean default false)
// app/Console/Commands/UpgradeMediaCommand.php
namespace App\Console\Commands;
use App\Jobs\UpgradeS3MediaJob;
use Illuminate\Console\Command;
use Illuminate\Console\ConfirmableTrait;
use Spatie\MediaLibrary\Models\Media;
class UpgradeMediaCommand extends Command
{
use ConfirmableTrait;
protected $signature = 'upgrade-media
{disk? : Disk to use}
{--d|dry-run : List files that will be renamed without renaming them}
{--f|force : Force the operation to run when in production}';
protected $description = 'Update the names of the version 6 files of spatie/laravel-medialibrary';
public function handle()
{
if (! $this->confirmToProceed()) {
return;
}
$isDryRun = $this->option('dry-run') ?? false;
$disk = $this->argument('disk') ?? config('medialibrary.disk_name');
$limit = 5000;
Media::query()
->where('converted', false)
->limit($limit)
->orderBy('created_at', 'desc')
->chunk(100, function ($mediaCollection) use ($isDryRun, $disk) {
dispatch(new UpgradeS3MediaJob($mediaCollection->toArray(), $isDryRun, $disk));
});
}
}
// app/Jobs/UpgradeS3MediaJob.php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Spatie\MediaLibrary\Models\Media;
class UpgradeS3MediaJob implements ShouldQueue
{
use Dispatchable, Queueable, SerializesModels;
private bool $isDryRun;
private array $mediaCollectionArray;
private array $mediaIdsToUpdate = [];
private Collection $mediaFilesToChange;
private string $disk;
public function __construct(array $mediaCollectionArray, $isDryRun, $disk)
{
$this->isDryRun = $isDryRun;
$this->mediaCollectionArray = $mediaCollectionArray;
$this->disk = $disk;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$this
->getMediaFilesToBeRenamed()
->renameMediaFiles();
if (! $this->isDryRun) {
Media::whereIn('id', $this->mediaIdsToUpdate)->update(['converted' => 1]);
info('Updated ' . count($this->mediaIdsToUpdate) . ' items as converted!');
} else {
info('Done dry run');
}
}
protected function getMediaFilesToBeRenamed(): self
{
$files = [];
foreach ($this->mediaCollectionArray as $mediaArray) {
$dir = './media/' . $mediaArray['id'];
$newFiles = $this->convert($dir)->toArray();
$files = array_merge($files, $newFiles);
}
$this->mediaFilesToChange = collect($files);
return $this;
}
protected function convert($directory)
{
return collect(Storage::disk($this->disk)->allFiles($directory))
->reject(function (string $file): bool {
return ! Str::startsWith($file, 'media') || strpos($file, '/') === false;
})
->filter(function (string $file): bool {
return $this->hasOriginal($file);
})
->filter(function (string $file): bool {
return $this->needsToBeConverted($file);
})
->map(function (string $file): array {
return $this->getReplaceArray($file);
});
}
protected function renameMediaFiles()
{
if ($this->mediaFilesToChange->count() === 0) {
info('There are no files to convert.');
}
if ($this->isDryRun) {
info('This is a dry-run and will not actually rename the files');
}
$this->mediaFilesToChange->each(function (array $filePaths) {
if (! $this->isDryRun) {
Storage::disk($this->disk)->move($filePaths['current'], $filePaths['replacement']);
$this->mediaIdsToUpdate[] = $this->getIdFromPath($filePaths['current']);
}
info("The file `{$filePaths['current']}` has become `{$filePaths['replacement']}`");
});
}
protected function hasOriginal(string $filePath): bool
{
$path = pathinfo($filePath, PATHINFO_DIRNAME);
$oneLevelHigher = dirname($path);
if ($oneLevelHigher === '.' || $oneLevelHigher === 'media') {
return false;
}
$original = Storage::disk($this->disk)->files($oneLevelHigher);
if (count($original) !== 1) {
return false;
}
return true;
}
protected function needsToBeConverted(string $file): bool
{
$currentFile = pathinfo($file);
$original = $this->getOriginal($currentFile['dirname']);
return strpos($currentFile['basename'], $original) === false;
}
protected function getReplaceArray(string $file): array
{
$currentFile = pathinfo($file);
$currentFilePath = $currentFile['dirname'];
$original = $this->getOriginal($currentFilePath);
return [
'current' => $file,
'replacement' => "{$currentFilePath}/{$original}-{$currentFile['basename']}",
];
}
protected function getOriginal(string $filePath): string
{
$oneLevelHigher = dirname($filePath);
$original = Storage::disk($this->disk)->files($oneLevelHigher);
return pathinfo($original[0], PATHINFO_FILENAME);
}
private function getIdFromPath($currentPath)
{
$parts = explode('/', $currentPath);
return $parts[1];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment