These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | namespace Spatie\MediaLibrary\Commands; |
||
| 4 | |||
| 5 | use Illuminate\Console\Command; |
||
| 6 | use Spatie\MediaLibrary\Models\Media; |
||
| 7 | use Illuminate\Console\ConfirmableTrait; |
||
| 8 | use Spatie\MediaLibrary\FileManipulator; |
||
| 9 | use Spatie\MediaLibrary\MediaRepository; |
||
| 10 | use Illuminate\Contracts\Filesystem\Factory; |
||
| 11 | use Illuminate\Database\Eloquent\Collection; |
||
| 12 | use Spatie\MediaLibrary\Conversion\Conversion; |
||
| 13 | use Spatie\MediaLibrary\Exceptions\FileCannotBeAdded; |
||
| 14 | use Spatie\MediaLibrary\Conversion\ConversionCollection; |
||
| 15 | use Spatie\MediaLibrary\PathGenerator\BasePathGenerator; |
||
| 16 | use Spatie\MediaLibrary\ResponsiveImages\RegisteredResponsiveImages; |
||
| 17 | |||
| 18 | class CleanCommand extends Command |
||
| 19 | { |
||
| 20 | use ConfirmableTrait; |
||
| 21 | |||
| 22 | protected $signature = 'medialibrary:clean {modelType?} {collectionName?} {disk?} |
||
| 23 | {--dry-run : List files that will be removed without removing them}, |
||
| 24 | {--force : Force the operation to run when in production}, |
||
| 25 | {--rate-limit= : Limit the number of request per second }'; |
||
| 26 | |||
| 27 | protected $description = 'Clean deprecated conversions and files without related model.'; |
||
| 28 | |||
| 29 | /** @var \Spatie\MediaLibrary\MediaRepository */ |
||
| 30 | protected $mediaRepository; |
||
| 31 | |||
| 32 | /** @var \Spatie\MediaLibrary\FileManipulator */ |
||
| 33 | protected $fileManipulator; |
||
| 34 | |||
| 35 | /** @var \Illuminate\Contracts\Filesystem\Factory */ |
||
| 36 | protected $fileSystem; |
||
| 37 | |||
| 38 | /** @var \Spatie\MediaLibrary\PathGenerator\BasePathGenerator */ |
||
| 39 | protected $basePathGenerator; |
||
| 40 | |||
| 41 | /** @var bool */ |
||
| 42 | protected $isDryRun = false; |
||
| 43 | |||
| 44 | /** @var int */ |
||
| 45 | protected $rateLimit = 0; |
||
| 46 | |||
| 47 | /** |
||
| 48 | * @param \Spatie\MediaLibrary\MediaRepository $mediaRepository |
||
| 49 | * @param \Spatie\MediaLibrary\FileManipulator $fileManipulator |
||
| 50 | * @param \Illuminate\Contracts\Filesystem\Factory $fileSystem |
||
| 51 | * @param \Spatie\MediaLibrary\PathGenerator\BasePathGenerator $basePathGenerator |
||
| 52 | */ |
||
| 53 | public function __construct( |
||
| 54 | MediaRepository $mediaRepository, |
||
| 55 | FileManipulator $fileManipulator, |
||
| 56 | Factory $fileSystem, |
||
| 57 | BasePathGenerator $basePathGenerator |
||
| 58 | ) { |
||
| 59 | parent::__construct(); |
||
| 60 | |||
| 61 | $this->mediaRepository = $mediaRepository; |
||
| 62 | $this->fileManipulator = $fileManipulator; |
||
| 63 | $this->fileSystem = $fileSystem; |
||
| 64 | $this->basePathGenerator = $basePathGenerator; |
||
| 65 | } |
||
| 66 | |||
| 67 | public function handle() |
||
| 68 | { |
||
| 69 | if (! $this->confirmToProceed()) { |
||
| 70 | return; |
||
| 71 | } |
||
| 72 | |||
| 73 | $this->isDryRun = $this->option('dry-run'); |
||
| 74 | $this->rateLimit = (int) $this->option('rate-limit'); |
||
| 75 | |||
| 76 | $this->deleteFilesGeneratedForDeprecatedConversions(); |
||
| 77 | |||
| 78 | $this->deleteOrphanedDirectories(); |
||
| 79 | |||
| 80 | $this->info('All done!'); |
||
| 81 | } |
||
| 82 | |||
| 83 | public function getMediaItems(): Collection |
||
| 84 | { |
||
| 85 | $modelType = $this->argument('modelType'); |
||
| 86 | $collectionName = $this->argument('collectionName'); |
||
| 87 | |||
| 88 | if (! is_null($modelType) && ! is_null($collectionName)) { |
||
| 89 | return $this->mediaRepository->getByModelTypeAndCollectionName( |
||
| 90 | $modelType, |
||
| 91 | $collectionName |
||
| 92 | ); |
||
| 93 | } |
||
| 94 | |||
| 95 | if (! is_null($modelType)) { |
||
| 96 | return $this->mediaRepository->getByModelType($modelType); |
||
| 97 | } |
||
| 98 | |||
| 99 | if (! is_null($collectionName)) { |
||
| 100 | return $this->mediaRepository->getByCollectionName($collectionName); |
||
| 101 | } |
||
| 102 | |||
| 103 | return $this->mediaRepository->all(); |
||
| 104 | } |
||
| 105 | |||
| 106 | protected function deleteFilesGeneratedForDeprecatedConversions() |
||
| 107 | { |
||
| 108 | $this->getMediaItems()->each(function (Media $media) { |
||
| 109 | $this->deleteConversionFilesForDeprecatedConversions($media); |
||
| 110 | |||
| 111 | if ($media->responsive_images) { |
||
| 112 | $this->deleteResponsiveImagesForDeprecatedConversions($media); |
||
| 113 | } |
||
| 114 | |||
| 115 | if ($this->rateLimit) { |
||
| 116 | usleep((1 / $this->rateLimit) * 1000000 * 2); |
||
| 117 | } |
||
| 118 | }); |
||
| 119 | } |
||
| 120 | |||
| 121 | protected function deleteConversionFilesForDeprecatedConversions(Media $media) |
||
| 122 | { |
||
| 123 | $conversionFilePaths = ConversionCollection::createForMedia($media)->getConversionsFiles($media->collection_name); |
||
| 124 | |||
| 125 | $conversionPath = $this->basePathGenerator->getPathForConversions($media); |
||
| 126 | $currentFilePaths = $this->fileSystem->disk($media->disk)->files($conversionPath); |
||
| 127 | |||
| 128 | collect($currentFilePaths) |
||
| 129 | ->reject(function (string $currentFilePath) use ($conversionFilePaths) { |
||
| 130 | return $conversionFilePaths->contains(basename($currentFilePath)); |
||
| 131 | }) |
||
| 132 | ->each(function (string $currentFilePath) use ($media) { |
||
| 133 | if (! $this->isDryRun) { |
||
| 134 | $this->fileSystem->disk($media->disk)->delete($currentFilePath); |
||
| 135 | |||
| 136 | $this->markConversionAsRemoved($media, $currentFilePath); |
||
| 137 | } |
||
| 138 | |||
| 139 | $this->info("Deprecated conversion file `{$currentFilePath}` ".($this->isDryRun ? 'found' : 'has been removed')); |
||
| 140 | }); |
||
| 141 | } |
||
| 142 | |||
| 143 | protected function deleteResponsiveImagesForDeprecatedConversions(Media $media) |
||
| 144 | { |
||
| 145 | $conversionNames = ConversionCollection::createForMedia($media) |
||
| 146 | ->map(function (Conversion $conversion) { |
||
| 147 | return $conversion->getName(); |
||
| 148 | }) |
||
| 149 | ->push('medialibrary_original'); |
||
| 150 | |||
| 151 | $responsiveImagesGeneratedFor = array_keys($media->responsive_images); |
||
| 152 | |||
| 153 | collect($responsiveImagesGeneratedFor) |
||
| 154 | ->map(function (string $generatedFor) use ($media) { |
||
| 155 | return $media->responsiveImages($generatedFor); |
||
| 156 | }) |
||
| 157 | ->reject(function (RegisteredResponsiveImages $responsiveImages) use ($conversionNames) { |
||
| 158 | return $conversionNames->contains($responsiveImages->generatedFor); |
||
| 159 | }) |
||
| 160 | ->each(function (RegisteredResponsiveImages $responsiveImages) { |
||
| 161 | if (! $this->isDryRun) { |
||
| 162 | $responsiveImages->delete(); |
||
| 163 | } |
||
| 164 | }); |
||
| 165 | } |
||
| 166 | |||
| 167 | protected function deleteOrphanedDirectories() |
||
| 168 | { |
||
| 169 | $diskName = $this->argument('disk') ?: config('medialibrary.disk_name'); |
||
| 170 | |||
| 171 | if (is_null(config("filesystems.disks.{$diskName}"))) { |
||
| 172 | throw FileCannotBeAdded::diskDoesNotExist($diskName); |
||
| 173 | } |
||
| 174 | |||
| 175 | $mediaIds = collect($this->mediaRepository->all()->pluck('id')->toArray()); |
||
| 176 | |||
| 177 | collect($this->fileSystem->disk($diskName)->directories()) |
||
| 178 | ->filter(function (string $directory) { |
||
| 179 | return is_numeric($directory); |
||
| 180 | }) |
||
| 181 | ->reject(function (string $directory) use ($mediaIds) { |
||
| 182 | return $mediaIds->contains((int) $directory); |
||
| 183 | })->each(function (string $directory) use ($diskName) { |
||
| 184 | if (! $this->isDryRun) { |
||
| 185 | $this->fileSystem->disk($diskName)->deleteDirectory($directory); |
||
| 186 | } |
||
| 187 | |||
| 188 | if ($this->rateLimit) { |
||
| 189 | usleep((1 / $this->rateLimit) * 1000000); |
||
| 190 | } |
||
| 191 | |||
| 192 | $this->info("Orphaned media directory `{$directory}` ".($this->isDryRun ? 'found' : 'has been removed')); |
||
| 193 | }); |
||
| 194 | } |
||
| 195 | |||
| 196 | protected function markConversionAsRemoved(Media $media, string $conversionPath) |
||
| 197 | { |
||
| 198 | $conversionFile = pathinfo($conversionPath, PATHINFO_FILENAME); |
||
| 199 | |||
| 200 | $generatedConversionName = null; |
||
| 201 | |||
| 202 | $media->getGeneratedConversions() |
||
| 203 | ->filter(function (bool $isGenerated, string $generatedConversionName) use ($conversionFile) { |
||
| 204 | return str_contains($conversionFile, $generatedConversionName); |
||
|
0 ignored issues
–
show
|
|||
| 205 | }) |
||
| 206 | ->each(function (bool $isGenerated, string $generatedConversionName) use ($media) { |
||
| 207 | $media->markAsConversionGenerated($generatedConversionName, false); |
||
| 208 | }); |
||
| 209 | |||
| 210 | $media->save(); |
||
| 211 | } |
||
| 212 | } |
||
| 213 |
This function has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.