Completed
Push — master ( 840ad0...271674 )
by Freek
01:54
created

Filesystem::removeResponsiveImages()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
3
namespace Spatie\MediaLibrary\Filesystem;
4
5
use Spatie\MediaLibrary\Helpers\File;
6
use Spatie\MediaLibrary\Models\Media;
7
use Spatie\MediaLibrary\FileManipulator;
8
use Illuminate\Contracts\Filesystem\Factory;
9
use Spatie\MediaLibrary\Events\MediaHasBeenAdded;
10
use Spatie\MediaLibrary\Conversion\ConversionCollection;
11
use Spatie\MediaLibrary\PathGenerator\PathGeneratorFactory;
12
13
class Filesystem
14
{
15
    /** @var \Illuminate\Contracts\Filesystem\Factory */
16
    protected $filesystem;
17
18
    /** @var array */
19
    protected $customRemoteHeaders = [];
20
21
    public function __construct(Factory $filesystem)
22
    {
23
        $this->filesystem = $filesystem;
24
    }
25
26
    public function add(string $file, Media $media, ?string $targetFileName = null)
27
    {
28
        $this->copyToMediaLibrary($file, $media, null, $targetFileName);
29
30
        event(new MediaHasBeenAdded($media));
31
32
        app(FileManipulator::class)->createDerivedFiles($media);
33
    }
34
35
    public function copyToMediaLibrary(string $pathToFile, Media $media, ?string $type = null, ?string $targetFileName = null)
36
    {
37
        $destinationFileName = $targetFileName ?: pathinfo($pathToFile, PATHINFO_BASENAME);
38
39
        $destination = $this->getMediaDirectory($media, $type).$destinationFileName;
40
41
        $file = fopen($pathToFile, 'r');
42
43
        if ($media->getDiskDriverName() === 'local') {
44
            $this->filesystem
45
                ->disk($media->disk)
46
                ->put($destination, $file);
47
48
            fclose($file);
49
50
            return;
51
        }
52
53
        $this->filesystem
54
            ->disk($media->disk)
55
            ->put($destination, $file, $this->getRemoteHeadersForFile($pathToFile, $media->getCustomHeaders()));
56
57
        if (is_resource($file)) {
58
            fclose($file);
59
        }
60
    }
61
62
    public function addCustomRemoteHeaders(array $customRemoteHeaders)
63
    {
64
        $this->customRemoteHeaders = $customRemoteHeaders;
65
    }
66
67
    public function getRemoteHeadersForFile(string $file, array $mediaCustomHeaders = []) : array
68
    {
69
        $mimeTypeHeader = ['ContentType' => File::getMimeType($file)];
70
71
        $extraHeaders = config('medialibrary.remote.extra_headers');
72
73
        return array_merge($mimeTypeHeader, $extraHeaders, $this->customRemoteHeaders, $mediaCustomHeaders);
74
    }
75
76
    public function getStream(Media $media)
77
    {
78
        $sourceFile = $this->getMediaDirectory($media).'/'.$media->file_name;
79
80
        return $this->filesystem->disk($media->disk)->readStream($sourceFile);
81
    }
82
83
    public function copyFromMediaLibrary(Media $media, string $targetFile): string
84
    {
85
        touch($targetFile);
86
87
        $stream = $this->getStream($media);
88
89
        $targetFileStream = fopen($targetFile, 'a');
90
91
        while (! feof($stream)) {
92
            $chunk = fread($stream, 1024);
93
            fwrite($targetFileStream, $chunk);
94
        }
95
96
        fclose($stream);
97
98
        fclose($targetFileStream);
99
100
        return $targetFile;
101
    }
102
103
    public function removeAllFiles(Media $media)
104
    {
105
        $mediaDirectory = $this->getMediaDirectory($media);
106
107
        $conversionsDirectory = $this->getMediaDirectory($media, 'conversions');
108
109
        $responsiveImagesDirectory = $this->getMediaDirectory($media, 'responsiveImages');
110
111
        collect([$mediaDirectory, $conversionsDirectory, $responsiveImagesDirectory])
112
113
            ->each(function ($directory) use ($media) {
114
                $this->filesystem->disk($media->disk)->deleteDirectory($directory);
115
            });
116
    }
117
118
    public function removeFile(Media $media, string $path)
119
    {
120
        $this->filesystem->disk($media->disk)->delete($path);
121
    }
122
123
    public function removeResponsiveImages(Media $media, string $conversionName = 'medialibrary_original') {
124
        $responsiveImagesDirectory = $this->getResponsiveImagesDirectory($media);
125
126
        $allFilePaths = $this->filesystem->allFiles($responsiveImagesDirectory);
0 ignored issues
show
Bug introduced by
The method allFiles() does not seem to exist on object<Illuminate\Contracts\Filesystem\Factory>.

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...
127
128
        $responsiveImagePaths = array_filter(
129
            $allFilePaths,
130
            function (string $path) use ($conversionName) {
131
                return str_contains($path, $conversionName);
132
            }
133
        );
134
135
        $this->filesystem->delete($responsiveImagePaths);
0 ignored issues
show
Bug introduced by
The method delete() does not seem to exist on object<Illuminate\Contracts\Filesystem\Factory>.

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...
136
    }
137
138
    public function syncFileNames(Media $media)
139
    {
140
        $this->renameMediaFile($media);
141
142
        $this->renameConversionFiles($media);
143
    }
144
145
    protected function renameMediaFile(Media $media)
146
    {
147
        $newFileName = $media->file_name;
148
        $oldFileName = $media->getOriginal('file_name');
149
150
        $mediaDirectory = $this->getMediaDirectory($media);
151
152
        $oldFile = $mediaDirectory.'/'.$oldFileName;
153
        $newFile = $mediaDirectory.'/'.$newFileName;
154
155
        $this->filesystem->disk($media->disk)->move($oldFile, $newFile);
156
    }
157
158
    protected function renameConversionFiles(Media $media)
159
    {
160
        $newFileName = $media->file_name;
161
        $oldFileName = $media->getOriginal('file_name');
162
163
        $conversionDirectory = $this->getConversionDirectory($media);
164
165
        $conversionCollection = ConversionCollection::createForMedia($media);
166
167
        foreach ($media->getMediaConversionNames() as $conversionName) {
168
            $conversion = $conversionCollection->getByName($conversionName);
169
170
            $oldFile = $conversionDirectory.$conversion->getConversionFile($oldFileName);
171
            $newFile = $conversionDirectory.$conversion->getConversionFile($newFileName);
172
173
            $disk = $this->filesystem->disk($media->disk);
174
175
            // A media conversion file might be missing, waiting to be generated, failed etc.
176
            if (! $disk->exists($oldFile)) {
177
                continue;
178
            }
179
180
            $disk->move($oldFile, $newFile);
181
        }
182
    }
183
184
    public function getMediaDirectory(Media $media, ?string $type = null) : string
185
    {
186
        $pathGenerator = PathGeneratorFactory::create();
187
188
        if (! $type) {
189
            $directory = $pathGenerator->getPath($media);
190
        }
191
192
        if ($type === 'conversions') {
193
            $directory = $pathGenerator->getPathForConversions($media);
194
        }
195
196
        if ($type === 'responsiveImages') {
197
            $directory = $pathGenerator->getPathForResponsiveImages($media);
198
        }
199
200
        if (! in_array($media->getDiskDriverName(), ['s3'], true)) {
201
            $this->filesystem->disk($media->disk)->makeDirectory($directory);
0 ignored issues
show
Bug introduced by
The variable $directory does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
202
        }
203
204
        return $directory;
205
    }
206
207
    public function getConversionDirectory(Media $media) : string
208
    {
209
        return $this->getMediaDirectory($media, 'conversions');
210
    }
211
212
    public function getResponsiveImagesDirectory(Media $media) : string
213
    {
214
        return $this->getMediaDirectory($media, 'responsiveImages');
215
    }
216
}
217