Completed
Push — master ( 85a536...0a5a36 )
by Freek
02:46
created

CleanCommand::deleteOrphanedFiles()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 8.7624
c 0
b 0
f 0
cc 6
eloc 12
nc 4
nop 0
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 Spatie\MediaLibrary\Conversion\ConversionCollection;
10
use Spatie\MediaLibrary\Exceptions\FileCannotBeAdded;
11
use Spatie\MediaLibrary\FileManipulator;
12
use Spatie\MediaLibrary\Media;
13
use Spatie\MediaLibrary\MediaRepository;
14
use Spatie\MediaLibrary\PathGenerator\BasePathGenerator;
15
16
class CleanCommand extends Command
17
{
18
    use ConfirmableTrait;
19
20
    /**
21
     * The console command name.
22
     *
23
     * @var string
24
     */
25
    protected $signature = 'medialibrary:clean {modelType?} {collectionName?} {disk?} {--dry-run}';
26
27
    /**
28
     * The console command description.
29
     *
30
     * @var string
31
     */
32
    protected $description = 'Clean deprecated conversions and files without related model.';
33
34
    /**
35
     * @var \Spatie\MediaLibrary\MediaRepository
36
     */
37
    protected $mediaRepository;
38
39
    /**
40
     * @var \Spatie\MediaLibrary\FileManipulator
41
     */
42
    protected $fileManipulator;
43
44
    /**
45
     * @var \Illuminate\Contracts\Filesystem\Factory
46
     */
47
    private $fileSystem;
48
49
    /**
50
     * @var \Spatie\MediaLibrary\PathGenerator\BasePathGenerator
51
     */
52
    private $basePathGenerator;
53
54
    /**
55
     * @var bool
56
     */
57
    protected $isDryRun = false;
58
59
    /**
60
     * @param \Spatie\MediaLibrary\MediaRepository                 $mediaRepository
61
     * @param \Spatie\MediaLibrary\FileManipulator                 $fileManipulator
62
     * @param \Illuminate\Contracts\Filesystem\Factory             $fileSystem
63
     * @param \Spatie\MediaLibrary\PathGenerator\BasePathGenerator $basePathGenerator
64
     */
65
    public function __construct(
66
        MediaRepository $mediaRepository,
67
        FileManipulator $fileManipulator,
68
        Factory $fileSystem,
69
        BasePathGenerator $basePathGenerator
70
    ) {
71
        parent::__construct();
72
        $this->mediaRepository = $mediaRepository;
73
        $this->fileManipulator = $fileManipulator;
74
        $this->fileSystem = $fileSystem;
75
        $this->basePathGenerator = $basePathGenerator;
76
    }
77
78
    /**
79
     * Handle command.
80
     */
81
    public function handle()
82
    {
83
        if (!$this->confirmToProceed()) {
84
            return;
85
        }
86
87
        $this->isDryRun = $this->option('dry-run');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->option('dry-run') of type string or array is incompatible with the declared type boolean of property $isDryRun.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
88
89
        $this->deleteFilesGeneratedForDeprecatedConversions();
90
91
        $this->deleteOrphanedFiles();
92
93
        $this->info('All done!');
94
    }
95
96
    public function getMediaItems() : Collection
97
    {
98
        $modelType = $this->argument('modelType');
99
        $collectionName = $this->argument('collectionName');
100
101
        if (!is_null($modelType) && !is_null($collectionName)) {
102
            return $this->mediaRepository->getByModelTypeAndCollectionName(
103
                $modelType,
0 ignored issues
show
Bug introduced by
It seems like $modelType defined by $this->argument('modelType') on line 98 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...
104
                $collectionName
0 ignored issues
show
Bug introduced by
It seems like $collectionName defined by $this->argument('collectionName') on line 99 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...
105
            );
106
        }
107
108
        if (!is_null($modelType)) {
109
            return $this->mediaRepository->getByModelType($modelType);
0 ignored issues
show
Bug introduced by
It seems like $modelType defined by $this->argument('modelType') on line 98 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...
110
        }
111
112
        if (!is_null($collectionName)) {
113
            return $this->mediaRepository->getByCollectionName($collectionName);
0 ignored issues
show
Bug introduced by
It seems like $collectionName defined by $this->argument('collectionName') on line 99 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...
114
        }
115
116
        return $this->mediaRepository->all();
117
    }
118
119
    protected function deleteFilesGeneratedForDeprecatedConversions()
120
    {
121
        $this->getMediaItems()->each(function (Media $media) {
122
123
            $conversionFilePaths = ConversionCollection::createForMedia($media)->getConversionsFiles($media->collection_name);
124
125
            $path = $this->basePathGenerator->getPathForConversions($media);
126
            $currentFilePaths = $this->fileSystem->disk($media->disk)->files($path);
127
128
            collect($currentFilePaths)
129
                ->filter(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
137
                    $this->info("Deprecated conversion file `{$currentFilePath}` ".($this->isDryRun ? 'found' : 'has been removed'));
138
                });
139
140
        });
141
    }
142
143
    protected function deleteOrphanedFiles()
144
    {
145
        $diskName = $this->argument('disk') ?: config('laravel-medialibrary.defaultFilesystem');
146
147
        if (is_null(config("filesystems.disks.{$diskName}"))) {
148
            throw FileCannotBeAdded::diskDoesNotExist($diskName);
149
        }
150
151
        $mediaIds = $this->mediaRepository->all()->pluck('id');
152
153
        collect($this->fileSystem->disk($diskName)->directories())
154
            ->filter(function (string $directory) use ($mediaIds) {
155
                return is_numeric($directory) ? !$mediaIds->contains((int) $directory) : false;
156
            })->each(function (string $directory) use ($diskName) {
157
                if (!$this->isDryRun) {
158
                    $this->fileSystem->disk($diskName)->deleteDirectory($directory);
159
                }
160
161
                $this->info("Orphaned media directory `{$directory}` ".($this->isDryRun ? 'found' : 'has been removed'));
162
            });
163
    }
164
}
165