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