ResponsiveImageGenerator   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 151
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 13

Importance

Changes 0
Metric Value
wmc 12
lcom 1
cbo 13
dl 0
loc 151
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 1
A generateResponsiveImages() 0 21 2
A generateResponsiveImagesForConversion() 0 14 2
A generateResponsiveImage() 0 28 1
A generateTinyJpg() 0 28 1
A appendToFileName() 0 8 1
A guardAgainstInvalidTinyPlaceHolder() 0 12 3
A cleanResponsiveImages() 0 10 1
1
<?php
2
3
namespace Spatie\MediaLibrary\ResponsiveImages;
4
5
use Illuminate\Support\Str;
6
use Spatie\MediaLibrary\Conversion\Conversion;
7
use Spatie\MediaLibrary\Events\ResponsiveImagesGenerated;
8
use Spatie\MediaLibrary\Filesystem\Filesystem;
9
use Spatie\MediaLibrary\Helpers\File;
10
use Spatie\MediaLibrary\Helpers\ImageFactory;
11
use Spatie\MediaLibrary\Helpers\TemporaryDirectory;
12
use Spatie\MediaLibrary\Models\Media;
13
use Spatie\MediaLibrary\ResponsiveImages\Exceptions\InvalidTinyJpg;
14
use Spatie\MediaLibrary\ResponsiveImages\TinyPlaceholderGenerator\TinyPlaceholderGenerator;
15
use Spatie\MediaLibrary\ResponsiveImages\WidthCalculator\WidthCalculator;
16
use Spatie\TemporaryDirectory\TemporaryDirectory as BaseTemporaryDirectory;
17
18
class ResponsiveImageGenerator
19
{
20
    /** \Spatie\MediaLibrary\Filesystem\Filesystem */
21
    protected $filesystem;
22
23
    /** \Spatie\MediaLibrary\ResponsiveImages\WidthCalculator\WidthCalculator */
24
    protected $widthCalculator;
25
26
    /** \Spatie\MediaLibrary\ResponsiveImages\TinyPlaceHolderGenerator\TinyPlaceHolderGenerator */
27
    protected $tinyPlaceholderGenerator;
28
29
    public function __construct(
30
        Filesystem $filesystem,
31
        WidthCalculator $widthCalculator,
32
        TinyPlaceholderGenerator $tinyPlaceholderGenerator
33
    ) {
34
        $this->filesystem = $filesystem;
35
36
        $this->widthCalculator = $widthCalculator;
37
38
        $this->tinyPlaceholderGenerator = $tinyPlaceholderGenerator;
39
    }
40
41
    public function generateResponsiveImages(Media $media)
42
    {
43
        $temporaryDirectory = TemporaryDirectory::create();
44
45
        $baseImage = app(Filesystem::class)->copyFromMediaLibrary(
46
            $media,
47
            $temporaryDirectory->path(Str::random(16).'.'.$media->extension)
48
        );
49
50
        $media = $this->cleanResponsiveImages($media);
51
52
        foreach ($this->widthCalculator->calculateWidthsFromFile($baseImage) as $width) {
53
            $this->generateResponsiveImage($media, $baseImage, 'medialibrary_original', $width, $temporaryDirectory);
54
        }
55
56
        event(new ResponsiveImagesGenerated($media));
57
58
        $this->generateTinyJpg($media, $baseImage, 'medialibrary_original', $temporaryDirectory);
59
60
        $temporaryDirectory->delete();
61
    }
62
63
    public function generateResponsiveImagesForConversion(Media $media, Conversion $conversion, string $baseImage)
64
    {
65
        $temporaryDirectory = TemporaryDirectory::create();
66
67
        $media = $this->cleanResponsiveImages($media, $conversion->getName());
68
69
        foreach ($this->widthCalculator->calculateWidthsFromFile($baseImage) as $width) {
70
            $this->generateResponsiveImage($media, $baseImage, $conversion->getName(), $width, $temporaryDirectory);
71
        }
72
73
        $this->generateTinyJpg($media, $baseImage, $conversion->getName(), $temporaryDirectory);
74
75
        $temporaryDirectory->delete();
76
    }
77
78
    public function generateResponsiveImage(
79
        Media $media,
80
        string $baseImage,
81
        string $conversionName,
82
        int $targetWidth,
83
        BaseTemporaryDirectory $temporaryDirectory
84
    ) {
85
        $responsiveImagePath = $this->appendToFileName($media->file_name, "___{$conversionName}_{$targetWidth}");
86
87
        $tempDestination = $temporaryDirectory->path($responsiveImagePath);
88
89
        ImageFactory::load($baseImage)
0 ignored issues
show
Bug introduced by
The method optimize() does not exist on Spatie\Image\Image. Did you maybe mean shouldOptimize()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
90
            ->optimize()
91
            ->width($targetWidth)
92
            ->save($tempDestination);
93
94
        $responsiveImageHeight = ImageFactory::load($tempDestination)->getHeight();
95
96
        $finalImageFileName = $this->appendToFileName($responsiveImagePath, "_{$responsiveImageHeight}");
97
98
        $finalResponsiveImagePath = $temporaryDirectory->path($finalImageFileName);
99
100
        rename($tempDestination, $finalResponsiveImagePath);
101
102
        $this->filesystem->copyToMediaLibrary($finalResponsiveImagePath, $media, 'responsiveImages');
103
104
        ResponsiveImage::register($media, $finalImageFileName, $conversionName);
105
    }
106
107
    public function generateTinyJpg(Media $media, string $originalImagePath, string $conversionName, BaseTemporaryDirectory $temporaryDirectory)
108
    {
109
        $tempDestination = $temporaryDirectory->path('tiny.jpg');
110
111
        $this->tinyPlaceholderGenerator->generateTinyPlaceholder($originalImagePath, $tempDestination);
112
113
        $this->guardAgainstInvalidTinyPlaceHolder($tempDestination);
114
115
        $tinyImageDataBase64 = base64_encode(file_get_contents($tempDestination));
116
117
        $tinyImageBase64 = 'data:image/jpeg;base64,'.$tinyImageDataBase64;
118
119
        $originalImage = ImageFactory::load($originalImagePath);
120
121
        $originalImageWidth = $originalImage->getWidth();
122
123
        $originalImageHeight = $originalImage->getHeight();
124
125
        $svg = view('medialibrary::placeholderSvg', compact(
126
            'originalImageWidth',
127
            'originalImageHeight',
128
            'tinyImageBase64'
129
        ));
130
131
        $base64Svg = 'data:image/svg+xml;base64,'.base64_encode($svg);
132
133
        ResponsiveImage::registerTinySvg($media, $base64Svg, $conversionName);
134
    }
135
136
    protected function appendToFileName(string $filePath, string $suffix): string
137
    {
138
        $baseName = pathinfo($filePath, PATHINFO_FILENAME);
139
140
        $extension = pathinfo($filePath, PATHINFO_EXTENSION);
141
142
        return $baseName.$suffix.'.'.$extension;
143
    }
144
145
    protected function guardAgainstInvalidTinyPlaceHolder(string $tinyPlaceholderPath)
146
    {
147
        if (! file_exists($tinyPlaceholderPath)) {
148
            throw InvalidTinyJpg::doesNotExist($tinyPlaceholderPath);
149
        }
150
151
        $mimeType = File::getMimetype($tinyPlaceholderPath);
152
153
        if ($mimeType !== 'image/jpeg') {
154
            throw InvalidTinyJpg::hasWrongMimeType($tinyPlaceholderPath);
155
        }
156
    }
157
158
    protected function cleanResponsiveImages(Media $media, string $conversionName = 'medialibrary_original'): Media
159
    {
160
        $responsiveImages = $media->responsive_images;
161
        $responsiveImages[$conversionName]['urls'] = [];
162
        $media->responsive_images = $responsiveImages;
163
164
        $this->filesystem->removeResponsiveImages($media, $conversionName);
165
166
        return $media;
167
    }
168
}
169