Test Failed
Push — develop ( 32ca41...230235 )
by Brent
04:59
created

ImageFactory   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 157
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 67.19%

Importance

Changes 0
Metric Value
dl 0
loc 157
ccs 43
cts 64
cp 0.6719
rs 10
c 0
b 0
f 0
wmc 17
lcom 1
cbo 8

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 16 1
A make() 0 8 1
A createScaledImage() 0 22 3
A createScaledFileName() 0 8 1
A copySourceImageToDestination() 0 6 1
A enableCaching() 0 6 1
A create() 0 30 5
A createCachedImage() 0 24 2
A optimize() 0 8 2
1
<?php
2
3
namespace Pageon\Html\Image;
4
5
use Intervention\Image\ImageManager;
6
use Intervention\Image\Image as ScaleableImage;
7
use Spatie\ImageOptimizer\OptimizerChain;
8
use Stitcher\File;
9
use Symfony\Component\Filesystem\Filesystem;
10
use Symfony\Component\Finder\Finder;
11
12
class ImageFactory
13
{
14
    /** @var \Pageon\Html\Image\Scaler */
15
    private $scaler;
16
17
    /** @var string */
18
    private $sourceDirectory;
19
20
    /** @var string */
21
    private $publicDirectory;
22
23
    /** @var \Intervention\Image\ImageManager */
24
    private $imageManager;
25
26
    /** @var \Spatie\ImageOptimizer\OptimizerChain */
27
    protected $optimizer;
28
29
    /** @var bool */
30
    private $cache = false;
31
32 4
    public function __construct(
33
        string $sourceDirectory,
34
        string $publicDirectory,
35
        Scaler $scaler,
36
        OptimizerChain $optimizer = null
37
    ) {
38 4
        $this->sourceDirectory = rtrim($sourceDirectory, '/');
39 4
        $this->publicDirectory = rtrim($publicDirectory, '/');
40 4
        $this->scaler = $scaler;
41
42 4
        $this->imageManager = new ImageManager([
43 4
            'driver' => 'gd',
44
        ]);
45
46 4
        $this->optimizer = $optimizer;
47 4
    }
48
49 4
    public static function make(
50
        string $sourceDirectory,
51
        string $publicDirectory,
52
        Scaler $scaler
53
    ): ImageFactory
54
    {
55 4
        return new self($sourceDirectory, $publicDirectory, $scaler);
56
    }
57
58
    public function enableCaching(bool $cache): ImageFactory
59
    {
60
        $this->cache = $cache;
61
62
        return $this;
63
    }
64
65 4
    public function create($src): Image
66
    {
67 4
        $srcPath = ltrim($src, '/');
68
69 4
        if ($this->cache && file_exists("{$this->publicDirectory}/{$srcPath}")) {
70
            return $this->createCachedImage($srcPath);
71
        }
72
73 4
        $image = Image::make($srcPath);
74
75 4
        $this->copySourceImageToDestination($srcPath);
76
77 4
        $scaleableImage = $this->imageManager->make("{$this->publicDirectory}/{$srcPath}");
78
79 4
        $this->optimize($scaleableImage->basePath());
80
81 4
        $variations = $this->scaler->getVariations($scaleableImage);
82
83 4
        $image->addSrcset($image->src(), $scaleableImage->getWidth());
84
85 4
        foreach ($variations as $width => $height) {
86 4
            if (!$width) {
87
                continue;
88
            }
89
90 4
            $this->createScaledImage($image, $width, $height, $scaleableImage);
91
        }
92
93 4
        return $image;
94
    }
95
96 4
    private function createScaledImage(
97
        Image $image,
98
        int $width,
99
        int $height,
100
        ScaleableImage $scaleableImage
101
    ): void {
102 4
        $scaleableImageClone = clone $scaleableImage;
103
104 4
        $scaledFileName = $this->createScaledFileName($image, $width, $height);
105
106 4
        $image->addSrcset($scaledFileName, $width);
107
108 4
        if ($this->cache && file_exists("{$this->publicDirectory}/{$scaledFileName}")) {
109
            return;
110
        }
111
112
        $scaleableImageClone
113 4
            ->resize($width, $height)
114 4
            ->save("{$this->publicDirectory}/{$scaledFileName}");
115
116 4
        $this->optimize("{$this->publicDirectory}/{$scaledFileName}");
117 4
    }
118
119 4
    private function createScaledFileName(Image $image, int $width, int $height): string
120
    {
121 4
        $srcPath = ltrim($image->src(), '/');
122
123 4
        $extension = pathinfo($srcPath, PATHINFO_EXTENSION);
124
125 4
        return str_replace(".{$extension}", "-{$width}x{$height}.{$extension}", $srcPath);
126
    }
127
128 4
    private function copySourceImageToDestination(string $srcPath): void
129
    {
130 4
        $fs = new Filesystem();
131
132 4
        $fs->copy(File::path($srcPath), "{$this->publicDirectory}/{$srcPath}");
133 4
    }
134
135
    private function createCachedImage(string $path): Image
136
    {
137
        $image = Image::make($path);
138
139
        $extension = pathinfo($path, PATHINFO_EXTENSION);
140
141
        $imageFilePath = pathinfo($image->src(), PATHINFO_DIRNAME);
142
143
        $imageFileName = pathinfo($image->src(), PATHINFO_FILENAME);
144
145
        $srcsetFiles = Finder::create()->files()
146
            ->in($this->publicDirectory . $imageFilePath)
147
            ->name("{$imageFileName}-*.{$extension}");
148
149
        foreach ($srcsetFiles->getIterator() as $srcsetFile) {
150
            $cachedFilename = $srcsetFile->getFilename();
151
152
            $size = (int) str_replace(".{$extension}", '', str_replace("{$imageFileName}-", '', $cachedFilename));
153
154
            $image->addSrcset("{$imageFilePath}/{$cachedFilename}", $size);
155
        }
156
157
        return $image;
158
    }
159
160 4
    private function optimize(string $path): void
161
    {
162 4
        if (! $this->optimizer) {
163 4
            return;
164
        }
165
166
        $this->optimizer->optimize($path);
167
    }
168
}
169