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'); |
||
0 ignored issues
–
show
|
|||
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, |
||
0 ignored issues
–
show
It seems like
$modelType defined by $this->argument('modelType') on line 86 can also be of type array ; however, Spatie\MediaLibrary\Medi...TypeAndCollectionName() does only seem to accept string , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.
Loading history...
|
|||
92 | $collectionName |
||
0 ignored issues
–
show
It seems like
$collectionName defined by $this->argument('collectionName') on line 87 can also be of type array ; however, Spatie\MediaLibrary\Medi...TypeAndCollectionName() does only seem to accept string , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.
Loading history...
|
|||
93 | ); |
||
94 | } |
||
95 | |||
96 | if (! is_null($modelType)) { |
||
97 | return $this->mediaRepository->getByModelType($modelType); |
||
0 ignored issues
–
show
It seems like
$modelType defined by $this->argument('modelType') on line 86 can also be of type array ; however, Spatie\MediaLibrary\Medi...itory::getByModelType() does only seem to accept string , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.
Loading history...
|
|||
98 | } |
||
99 | |||
100 | if (! is_null($collectionName)) { |
||
101 | return $this->mediaRepository->getByCollectionName($collectionName); |
||
0 ignored issues
–
show
It seems like
$collectionName defined by $this->argument('collectionName') on line 87 can also be of type array ; however, Spatie\MediaLibrary\Medi...::getByCollectionName() does only seem to accept string , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.
Loading history...
|
|||
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); |
||
0 ignored issues
–
show
The method
diskDoesNotExist() does not seem to exist on object<Spatie\MediaLibra...ions\FileCannotBeAdded> .
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed.
Loading history...
|
|||
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
$generatedConversionName is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
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 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.