Completed
Push — master ( c2f76d...03586b )
by Freek
11:35
created

ResponsiveImageGenerator   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 135
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 0
Metric Value
wmc 11
lcom 1
cbo 10
dl 0
loc 135
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 1
A generateResponsiveImages() 0 17 2
A generateResponsiveImagesForConversion() 0 12 2
B generateResponsiveImage() 0 29 1
B generateTinyJpg() 0 28 1
A appendToFileName() 0 8 1
A guardAgainstInvalidTinyPlaceHolder() 0 12 3
1
<?php
2
3
namespace Spatie\MediaLibrary\ResponsiveImages;
4
5
use Spatie\MediaLibrary\Models\Media;
6
use Spatie\MediaLibrary\Filesystem\Filesystem;
7
use Spatie\MediaLibrary\Helpers\TemporaryDirectory;
8
use Spatie\MediaLibrary\PathGenerator\PathGenerator;
9
use Spatie\MediaLibrary\ResponsiveImages\WidthCalculator\WidthCalculator;
10
use Spatie\Image\Image;
11
use Spatie\MediaLibrary\PathGenerator\PathGeneratorFactory;
12
use Spatie\TemporaryDirectory\TemporaryDirectory as BaseTemporaryDirectory;
13
use Spatie\MediaLibrary\Conversion\Conversion;
14
use Spatie\MediaLibrary\ResponsiveImages\ResponsiveImage;
15
use Spatie\MediaLibrary\ResponsiveImages\TinyPlaceholderGenerator\TinyPlaceholderGenerator;
16
use Spatie\MediaLibrary\ResponsiveImages\Exceptions\InvalidTinyJpg;
17
use Spatie\MediaLibrary\Helpers\File;
18
19
class ResponsiveImageGenerator
20
{
21
    /** \Spatie\MediaLibrary\Filesystem\Filesystem */
22
    protected $filesystem;
23
24
    /** \Spatie\MediaLibrary\ResponsiveImages\WidthCalculator\WidthCalculator */
25
    protected $widthCalculator;
26
27
    /** \Spatie\MediaLibrary\ResponsiveImages\TinyPlaceHolderGenerator\TinyPlaceHolderGenerator */
28
    protected $tinyPlaceholderGenerator;
29
30
    public function __construct(
31
        Filesystem $filesystem,
32
        WidthCalculator $widthCalculator,
33
        TinyPlaceholderGenerator $tinyPlaceholderGenerator
34
    ) {
35
        $this->filesystem = $filesystem;
36
37
        $this->widthCalculator = $widthCalculator;
38
39
        $this->tinyPlaceholderGenerator = $tinyPlaceholderGenerator;
40
    }
41
42
    public function generateResponsiveImages(Media $media)
43
    {
44
        $temporaryDirectory = TemporaryDirectory::create();
45
46
        $baseImage = app(Filesystem::class)->copyFromMediaLibrary(
47
            $media,
48
            $temporaryDirectory->path(str_random(16) . '.' . $media->extension)
49
        );
50
51
        foreach ($this->widthCalculator->calculateWidthsFromFile($baseImage) as $width) {
52
            $this->generateResponsiveImage($media, $baseImage, 'medialibrary_original', $width, $temporaryDirectory);
53
        }
54
55
        $this->generateTinyJpg($media, $baseImage, 'medialibrary_original', $temporaryDirectory);
56
57
        $temporaryDirectory->delete();
58
    }
59
60
    public function generateResponsiveImagesForConversion(Media $media, Conversion $conversion, string $baseImage)
61
    {
62
        $temporaryDirectory = TemporaryDirectory::create();
63
64
        foreach ($this->widthCalculator->calculateWidthsFromFile($baseImage) as $width) {
65
            $this->generateResponsiveImage($media, $baseImage, $conversion->getName(), $width, $temporaryDirectory);
66
        }
67
68
        $this->generateTinyJpg($media, $baseImage, $conversion->getName(), $temporaryDirectory);
69
70
        $temporaryDirectory->delete();
71
    }
72
73
    public function generateResponsiveImage(
74
        Media $media,
75
        string $baseImage,
76
        string $conversionName,
77
        int $targetWidth,
78
        BaseTemporaryDirectory $temporaryDirectory
79
    ) {
80
        $responsiveImagePath = $this->appendToFileName($media->file_name, "___{$conversionName}_{$targetWidth}");
81
82
        $tempDestination = $temporaryDirectory->path($responsiveImagePath);
83
84
        Image::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...
85
            ->useImageDriver(config('medialibrary.image_driver'))
86
            ->optimize()
87
            ->width($targetWidth)
88
            ->save($tempDestination);
89
90
        $responsiveImageHeight = Image::load($tempDestination)->getHeight();
91
92
        $finalImageFileName = $this->appendToFileName($responsiveImagePath, "_{$responsiveImageHeight}");
93
94
        $finalResponsiveImagePath = $temporaryDirectory->path($finalImageFileName);
95
96
        rename($tempDestination, $finalResponsiveImagePath);
97
98
        $this->filesystem->copyToMediaLibrary($finalResponsiveImagePath, $media, 'responsiveImages');
99
100
        ResponsiveImage::register($media, $finalImageFileName, $conversionName);
101
    }
102
103
    public function generateTinyJpg(Media $media, string $originalImagePath, string $conversionName, BaseTemporaryDirectory $temporaryDirectory)
104
    {
105
        $tempDestination = $temporaryDirectory->path('tiny.jpg');
106
107
        $this->tinyPlaceholderGenerator->generateTinyPlaceholder($originalImagePath, $tempDestination);
108
109
        $this->guardAgainstInvalidTinyPlaceHolder($tempDestination);
110
111
        $tinyImageDataBase64 = base64_encode(file_get_contents($tempDestination));
112
113
        $tinyImageBase64 = 'data:image/jpeg;base64,' . $tinyImageDataBase64;
114
115
        $originalImage = Image::load($originalImagePath);
116
117
        $originalImageWidth = $originalImage->getWidth();
118
119
        $originalImageHeight = $originalImage->getHeight();
120
121
        $svg = view('medialibrary::placeholderSvg', compact(
122
            'originalImageWidth',
123
            'originalImageHeight',
124
            'tinyImageBase64'
125
        ));
126
127
        $base64Svg = 'data:image/svg+xml;base64,' . base64_encode($svg);
128
129
        ResponsiveImage::registerTinySvg($media, $base64Svg, $conversionName);
130
    }
131
132
    protected function appendToFileName(string $filePath, string $suffix): string
133
    {
134
        $baseName = pathinfo($filePath, PATHINFO_FILENAME);
135
136
        $extension = pathinfo($filePath, PATHINFO_EXTENSION);
137
138
        return $baseName . $suffix . '.' . $extension;
139
    }
140
141
    protected function guardAgainstInvalidTinyPlaceHolder(string $tinyPlaceholderPath)
142
    {
143
        if (! file_exists($tinyPlaceholderPath)) {
144
            throw InvalidTinyJpg::doesNotExist($tinyPlaceholderPath);
145
        }
146
147
        $mimeType = File::getMimetype($tinyPlaceholderPath);
148
149
        if ($mimeType !== 'image/jpeg') {
150
            throw InvalidTinyJpg::hasWrongMimeType($tinyPlaceholderPath);
151
        }
152
    }
153
}
154