Completed
Push — master ( c72eae...3c35ec )
by Freek
04:04 queued 01:53
created

FileManipulator   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 164
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 4
Bugs 0 Features 1
Metric Value
wmc 20
lcom 1
cbo 8
dl 0
loc 164
rs 10
c 4
b 0
f 1

8 Methods

Rating   Name   Duplication   Size   Complexity  
C createDerivedFiles() 0 24 7
B performConversions() 0 33 5
A performConversion() 0 15 2
A createTempDirectory() 0 8 1
A extractVideoThumbnail() 0 15 1
A convertPdfToImage() 0 8 1
A convertSvgToImage() 0 13 1
A dispatchQueuedConversions() 0 12 2
1
<?php
2
3
namespace Spatie\MediaLibrary;
4
5
use Illuminate\Support\Facades\File;
6
use ImagickPixel;
7
use Spatie\Glide\GlideImage;
8
use Spatie\MediaLibrary\Conversion\Conversion;
9
use Spatie\MediaLibrary\Conversion\ConversionCollection;
10
use Spatie\MediaLibrary\Events\ConversionHasBeenCompleted;
11
use Spatie\MediaLibrary\Helpers\File as MediaLibraryFileHelper;
12
use Spatie\MediaLibrary\Jobs\PerformConversions;
13
use Spatie\PdfToImage\Pdf;
14
15
class FileManipulator
16
{
17
    /**
18
     * Create all derived files for the given media.
19
     *
20
     * @param \Spatie\MediaLibrary\Media $media
21
     */
22
    public function createDerivedFiles(Media $media)
23
    {
24
        if ($media->type === Media::TYPE_OTHER) {
25
            return;
26
        }
27
28
        if ($media->type === Media::TYPE_VIDEO && !class_exists('\\FFMpeg\\FFMpeg')) {
29
            return;
30
        }
31
32
        if (in_array($media->type, [Media::TYPE_PDF, Media::TYPE_SVG]) && !class_exists('Imagick')) {
33
            return;
34
        }
35
36
        $profileCollection = ConversionCollection::createForMedia($media);
37
38
        $this->performConversions($profileCollection->getNonQueuedConversions($media->collection_name), $media);
39
40
        $queuedConversions = $profileCollection->getQueuedConversions($media->collection_name);
41
42
        if (count($queuedConversions)) {
43
            $this->dispatchQueuedConversions($media, $queuedConversions);
44
        }
45
    }
46
47
    /**
48
     * Perform the given conversions for the given media.
49
     *
50
     * @param \Spatie\MediaLibrary\Conversion\ConversionCollection $conversions
51
     * @param \Spatie\MediaLibrary\Media                           $media
52
     */
53
    public function performConversions(ConversionCollection $conversions, Media $media)
54
    {
55
        $tempDirectory = $this->createTempDirectory();
56
57
        $copiedOriginalFile = $tempDirectory.'/'.str_random(16).'.'.$media->extension;
58
59
        app(Filesystem::class)->copyFromMediaLibrary($media, $copiedOriginalFile);
60
61
        if ($media->type == Media::TYPE_PDF) {
62
            $copiedOriginalFile = $this->convertPdfToImage($copiedOriginalFile);
63
        }
64
65
        if ($media->type == Media::TYPE_SVG) {
66
            $copiedOriginalFile = $this->convertSvgToImage($copiedOriginalFile);
67
        }
68
69
        foreach ($conversions as $conversion) {
70
            if ($media->type == Media::TYPE_VIDEO) {
71
                $copiedOriginalFile = $this->extractVideoThumbnail($copiedOriginalFile, $conversion);
72
            }
73
74
            $conversionResult = $this->performConversion($media, $conversion, $copiedOriginalFile);
75
76
            $renamedFile = MediaLibraryFileHelper::renameInDirectory($conversionResult, $conversion->getName().'.'.
77
                $conversion->getResultExtension(pathinfo($copiedOriginalFile, PATHINFO_EXTENSION)));
78
79
            app(Filesystem::class)->copyToMediaLibrary($renamedFile, $media, true);
80
81
            event(new ConversionHasBeenCompleted($media, $conversion));
82
        }
83
84
        File::deleteDirectory($tempDirectory);
85
    }
86
87
    /**
88
     * Perform the conversion.
89
     *
90
     * @param \Spatie\MediaLibrary\Media $media
91
     * @param Conversion                 $conversion
92
     * @param string                     $copiedOriginalFile
93
     *
94
     * @return string
95
     */
96
    public function performConversion(Media $media, Conversion $conversion, string $copiedOriginalFile)
97
    {
98
        $conversionTempFile = pathinfo($copiedOriginalFile, PATHINFO_DIRNAME).'/'.string()->random(16).
99
            $conversion->getName().'.'.$media->extension;
100
101
        File::copy($copiedOriginalFile, $conversionTempFile);
102
103
        foreach ($conversion->getManipulations() as $manipulation) {
104
            GlideImage::create($conversionTempFile)
105
                ->modify($manipulation)
106
                ->save($conversionTempFile);
107
        }
108
109
        return $conversionTempFile;
110
    }
111
112
    /*
113
     * Create a directory to store some working files.
114
     */
115
    public function createTempDirectory() : string
116
    {
117
        $tempDirectory = storage_path('medialibrary/temp/'.str_random(16));
118
119
        File::makeDirectory($tempDirectory, 493, true);
120
121
        return $tempDirectory;
122
    }
123
124
    protected function extractVideoThumbnail(string $videoFile, Conversion $conversion) : string
125
    {
126
        $imageFile = pathinfo($videoFile, PATHINFO_FILENAME).'.jpg';
127
128
        $ffmpeg = \FFMpeg\FFMpeg::create([
129
            'ffmpeg.binaries' => config('laravel-medialibrary.ffmpeg_binaries'),
130
            'ffprobe.binaries' => config('laravel-medialibrary.ffprobe_binaries'),
131
        ]);
132
        $video = $ffmpeg->open($videoFile);
133
134
        $frame = $video->frame(\FFMpeg\Coordinate\TimeCode::fromSeconds($conversion->getExtractVideoFrameAtSecond()));
135
        $frame->save($imageFile);
136
137
        return $imageFile;
138
    }
139
140
    protected function convertPdfToImage(string $pdfFile) : string
141
    {
142
        $imageFile = pathinfo($pdfFile, PATHINFO_FILENAME).'.jpg';
143
144
        (new Pdf($pdfFile))->saveImage($imageFile);
145
146
        return $imageFile;
147
    }
148
149
    protected function convertSvgToImage(string $svgFile) : string
150
    {
151
        $imageFile = pathinfo($svgFile, PATHINFO_FILENAME).'.png';
152
153
        $image = new \Imagick();
154
        $image->readImage($svgFile);
155
        $image->setBackgroundColor(new ImagickPixel('none'));
156
        $image->setImageFormat('png32');
157
158
        file_put_contents($imageFile, $image);
159
160
        return $imageFile;
161
    }
162
163
    /*
164
     * Dispatch the given conversions.
165
     */
166
    protected function dispatchQueuedConversions(Media $media, ConversionCollection $queuedConversions)
167
    {
168
        $job = new PerformConversions($queuedConversions, $media);
169
170
        $customQueue = config('laravel-medialibrary.queue_name');
171
172
        if ($customQueue != '') {
173
            $job->onQueue($customQueue);
174
        }
175
176
        app('Illuminate\Contracts\Bus\Dispatcher')->dispatch($job);
177
    }
178
}
179