1 | <?php namespace GeneaLabs\LaravelImagery; |
||||||
2 | |||||||
3 | use GeneaLabs\LaravelImagery\Jobs\RenderDerivativeImages; |
||||||
4 | use Intervention\Image\ImageManager; |
||||||
5 | use Jenssegers\Model\Model; |
||||||
6 | use Illuminate\Support\Collection; |
||||||
7 | |||||||
8 | class Image extends Model |
||||||
9 | { |
||||||
10 | protected $originalHeight; |
||||||
11 | protected $originalWidth; |
||||||
12 | // protected $htmlAttributes; |
||||||
13 | protected $heightIsPercentage; |
||||||
14 | protected $widthIsPercentage; |
||||||
15 | // protected $source; |
||||||
16 | // protected $height; |
||||||
17 | // protected $width; |
||||||
18 | // protected $originalPath; |
||||||
19 | protected $alwaysPreserveAspectRatio; |
||||||
20 | protected $doNotCreateDerivativeImages; |
||||||
21 | protected $overrideScreenConstraint; |
||||||
22 | protected $screenConstraintMethod; |
||||||
23 | |||||||
24 | //TODO: this class needs serious refactoring!!! |
||||||
25 | public function __construct( |
||||||
26 | string $source, |
||||||
27 | string $width = null, |
||||||
28 | string $height = null, |
||||||
29 | Collection $htmlAttributes = null, |
||||||
30 | Collection $options = null |
||||||
31 | ) { |
||||||
32 | parent::__construct(); |
||||||
33 | |||||||
34 | $this->createCacheFolderIfMissing(); |
||||||
35 | |||||||
36 | $this->originalHeight = $height; |
||||||
37 | $this->originalWidth = $width; |
||||||
38 | $this->htmlAttributes = $htmlAttributes; |
||||||
0 ignored issues
–
show
Bug
Best Practice
introduced
by
![]() |
|||||||
39 | $this->heightIsPercentage = str_contains($height, '%'); |
||||||
40 | $this->widthIsPercentage = str_contains($width, '%'); |
||||||
41 | $this->source = $source; |
||||||
0 ignored issues
–
show
|
|||||||
42 | $this->image = (new ImageManager)->make($source); |
||||||
0 ignored issues
–
show
|
|||||||
43 | $this->height = intval($height); |
||||||
0 ignored issues
–
show
|
|||||||
44 | $this->width = intval($width); |
||||||
0 ignored issues
–
show
|
|||||||
45 | $this->originalPath = public_path(config('genealabs-laravel-imagery.storage-folder') . basename($source)); |
||||||
0 ignored issues
–
show
|
|||||||
46 | $this->alwaysPreserveAspectRatio = $options->get('alwaysPreserveAspectRatio', true); |
||||||
0 ignored issues
–
show
The method
get() does not exist on null .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
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. ![]() |
|||||||
47 | $this->doNotCreateDerivativeImages = $options->get('doNotCreateDerivativeImages', false); |
||||||
48 | $this->overrideScreenConstraint = $options->get('overrideScreenConstraint', false); |
||||||
49 | $this->screenConstraintMethod = $options->get('screenConstraintMethod', 'contain'); |
||||||
50 | |||||||
51 | if ($this->sourceIsUrl($source)) { |
||||||
52 | $this->image->save($this->originalPath); |
||||||
53 | } |
||||||
54 | |||||||
55 | $this->resizeImage($this->width, $this->height, $this->alwaysPreserveAspectRatio); |
||||||
56 | |||||||
57 | if (! $this->doNotCreateDerivativeImages) { |
||||||
58 | $job = (new RenderDerivativeImages($this->source))->onQueue('imagery'); |
||||||
59 | dispatch($job); |
||||||
60 | } |
||||||
61 | } |
||||||
62 | |||||||
63 | protected function resizeImage(int $width, int $height, bool $alwaysPreserveAspect = false) |
||||||
64 | { |
||||||
65 | if (! $height || ! $width) { |
||||||
66 | $height = $height ?: $this->image->getHeight(); |
||||||
67 | $width = $width ?: $this->image->getWidth(); |
||||||
68 | } |
||||||
69 | |||||||
70 | $screenHeight = $_COOKIE['screenWidth'] ?? null; |
||||||
71 | $screenWidth = $_COOKIE['screenHeight'] ?? null; |
||||||
72 | $screenHeight = $screenWidth ? intval($screenWidth) : null; |
||||||
73 | $screenWidth = $screenWidth ? intval($screenWidth) : null; |
||||||
74 | $height = $this->determineHeight($height, $screenHeight); |
||||||
75 | $width = $this->determineWidth($width, $screenWidth); |
||||||
76 | |||||||
77 | if (! $height && ! $width) { |
||||||
78 | $height = $this->image->height(); |
||||||
79 | $width = $this->image->width(); |
||||||
80 | } |
||||||
81 | |||||||
82 | $maxHeight = $this->determineMaxHeight($height, $screenHeight, $screenWidth); |
||||||
83 | $maxWidth = $this->determineMaxWidth($width, $screenHeight, $screenWidth); |
||||||
84 | |||||||
85 | $this->image->resize($maxWidth, $maxHeight, function ($constraint) use ($alwaysPreserveAspect) { |
||||||
86 | if ($alwaysPreserveAspect || ! $width || ! $height) { |
||||||
87 | $constraint->aspectRatio(); |
||||||
88 | } |
||||||
89 | |||||||
90 | $constraint->upsize(); |
||||||
91 | }); |
||||||
92 | |||||||
93 | $this->height = $this->image->height(); |
||||||
0 ignored issues
–
show
|
|||||||
94 | $this->width = $this->image->width(); |
||||||
0 ignored issues
–
show
|
|||||||
95 | $this->storeImage(); |
||||||
96 | } |
||||||
97 | |||||||
98 | //TODO: refactor to have a single return type, instead of null or int |
||||||
99 | protected function determineMaxHeight($height, $screenHeight, $screenWidth) |
||||||
100 | { |
||||||
101 | if (! $screenHeight || ! $screenWidth) { |
||||||
102 | return $height; |
||||||
103 | } |
||||||
104 | |||||||
105 | $maxHeight = $height ?: $this->image->height(); |
||||||
106 | |||||||
107 | if (! $this->overrideScreenConstraint) { |
||||||
108 | $maxHeight = $screenHeight < $maxHeight ? $screenHeight : $maxHeight; |
||||||
109 | |||||||
110 | if ($this->screenConstraintMethod === 'cover') { |
||||||
111 | $imageToScreenHeight = $screenHeight / $this->image->height(); |
||||||
112 | $imageToScreenWidth = $screenWidth / $this->image->width(); |
||||||
113 | |||||||
114 | if ($imageToScreenHeight < $imageToScreenWidth) { |
||||||
115 | $maxHeight = null; |
||||||
116 | } |
||||||
117 | } |
||||||
118 | } |
||||||
119 | |||||||
120 | return $maxHeight; |
||||||
121 | } |
||||||
122 | |||||||
123 | //TODO: refactor to have a single return type, instead of null or int |
||||||
124 | protected function determineMaxWidth($width, $screenHeight, $screenWidth) |
||||||
125 | { |
||||||
126 | if (! $screenHeight || ! $screenWidth) { |
||||||
127 | return $width; |
||||||
128 | } |
||||||
129 | |||||||
130 | $maxWidth = $width ?: $this->image->width(); |
||||||
131 | |||||||
132 | if (! $this->overrideScreenConstraint) { |
||||||
133 | $maxWidth = $screenWidth < $maxWidth ? $screenWidth : $maxWidth; |
||||||
134 | |||||||
135 | if ($this->screenConstraintMethod === 'cover') { |
||||||
136 | $imageToScreenHeight = $screenHeight / $this->image->height(); |
||||||
137 | $imageToScreenWidth = $screenWidth / $this->image->width(); |
||||||
138 | if ($imageToScreenHeight > $imageToScreenWidth) { |
||||||
139 | $maxWidth = null; |
||||||
140 | } |
||||||
141 | } |
||||||
142 | } |
||||||
143 | |||||||
144 | return $maxWidth; |
||||||
145 | } |
||||||
146 | |||||||
147 | protected function determineHeight($height, $screenHeight) : int |
||||||
148 | { |
||||||
149 | if ($screenHeight && $height && $this->heightIsPercentage) { |
||||||
150 | return $screenHeight * ($height / 100); |
||||||
151 | } |
||||||
152 | |||||||
153 | return $height; |
||||||
154 | } |
||||||
155 | |||||||
156 | protected function determineWidth($width, $screenWidth) : int |
||||||
157 | { |
||||||
158 | if ($screenWidth && $width && $this->widthIsPercentage) { |
||||||
159 | return $screenWidth * ($width / 100); |
||||||
160 | } |
||||||
161 | |||||||
162 | return $width; |
||||||
163 | } |
||||||
164 | |||||||
165 | protected function sourceIsUrl() : bool |
||||||
166 | { |
||||||
167 | return collect(parse_url($this->source))->has('scheme'); |
||||||
168 | } |
||||||
169 | |||||||
170 | protected function storeImage() |
||||||
171 | { |
||||||
172 | $this->image |
||||||
173 | ->save(public_path(config('genealabs-laravel-imagery.storage-folder') . $this->fileName)); |
||||||
0 ignored issues
–
show
The property
fileName does not exist on GeneaLabs\LaravelImagery\Image . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||||
174 | } |
||||||
175 | |||||||
176 | public function getFileNameAttribute() : string |
||||||
177 | { |
||||||
178 | $pathParts = pathinfo($this->source); |
||||||
179 | $fileName = $pathParts['filename']; |
||||||
180 | $extension = $pathParts['extension'] ?? ''; |
||||||
181 | $extension = $extension ? ".{$extension}" : ''; |
||||||
182 | |||||||
183 | if ($this->width || $this->height) { |
||||||
184 | $fileName .= "_{$this->width}x{$this->height}"; |
||||||
185 | } |
||||||
186 | |||||||
187 | return "{$fileName}{$extension}"; |
||||||
188 | } |
||||||
189 | |||||||
190 | public function getImgAttribute() : string |
||||||
191 | { |
||||||
192 | $scriptUrl = mix('js/cookie.js', 'genealabs-laravel-imagery'); |
||||||
193 | $attributes = ''; |
||||||
194 | |||||||
195 | $attributes = $this->htmlAttributes->map(function ($value, $attribute) use (&$attributes) { |
||||||
0 ignored issues
–
show
The method
map() does not exist on null .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
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. ![]() |
|||||||
196 | return " {$attribute}=\"{$value}\""; |
||||||
197 | })->implode(''); |
||||||
198 | |||||||
199 | return "<img src=\"{$this->url}\" |
||||||
0 ignored issues
–
show
The property
url does not exist on GeneaLabs\LaravelImagery\Image . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||||
200 | width=\"{$this->originalWidth}\" |
||||||
201 | height=\"{$this->originalHeight}\"{{ $attributes }} |
||||||
202 | ><script src=\"{$scriptUrl}\"></script>"; |
||||||
203 | } |
||||||
204 | |||||||
205 | public function getOriginalUrlAttribute() : string |
||||||
206 | { |
||||||
207 | return asset(config('genealabs-laravel-imagery.storage-folder') . $this->fileName); |
||||||
0 ignored issues
–
show
The property
fileName does not exist on GeneaLabs\LaravelImagery\Image . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||||
208 | } |
||||||
209 | |||||||
210 | public function getPathAttribute() : string |
||||||
211 | { |
||||||
212 | return public_path(config('genealabs-laravel-imagery.storage-folder') . $this->fileName); |
||||||
0 ignored issues
–
show
The property
fileName does not exist on GeneaLabs\LaravelImagery\Image . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||||
213 | } |
||||||
214 | |||||||
215 | public function getPictureAttribute() : string |
||||||
216 | { |
||||||
217 | //TODO: implement img tag attributes, move script to middleware injector |
||||||
218 | $scriptUrl = mix('js/cookie.js', 'genealabs-laravel-imagery'); |
||||||
219 | $sources = ''; |
||||||
220 | |||||||
221 | foreach (array_reverse(config('genealabs-laravel-imagery.size-presets')) as $sizePreset) { |
||||||
222 | $image = (new Imagery)->conjure( |
||||||
223 | $this->source, |
||||||
224 | $sizePreset, |
||||||
225 | $sizePreset, |
||||||
226 | [], |
||||||
227 | ['doNotCreateDerivativeImages' => true] |
||||||
228 | ); |
||||||
229 | |||||||
230 | if ($sizePreset < $this->width || $sizePreset < $this->height) { |
||||||
231 | $sources .= "<source srcset=\"{$image->url}\" media=\"(min-width: {$sizePreset}px)\">"; |
||||||
0 ignored issues
–
show
The property
url does not exist on GeneaLabs\LaravelImagery\Image . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||||
232 | } |
||||||
233 | } |
||||||
234 | |||||||
235 | return " |
||||||
236 | <picture> |
||||||
237 | {$sources} |
||||||
238 | <img src=\"{$this->url}\"> |
||||||
239 | </picture> |
||||||
240 | <script src=\"{$scriptUrl}\"></script> |
||||||
241 | "; |
||||||
242 | } |
||||||
243 | |||||||
244 | public function getUrlAttribute() : string |
||||||
245 | { |
||||||
246 | return asset(config('genealabs-laravel-imagery.storage-folder') . $this->fileName); |
||||||
0 ignored issues
–
show
The property
fileName does not exist on GeneaLabs\LaravelImagery\Image . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||||
247 | } |
||||||
248 | |||||||
249 | protected function createCacheFolderIfMissing() |
||||||
250 | { |
||||||
251 | app('filesystem')->disk('public')->makeDirectory(config('genealabs-laravel-imagery.storage-folder')); |
||||||
252 | |||||||
253 | if (! file_exists(public_path(config('genealabs-laravel-imagery.storage-folder')))) { |
||||||
254 | symlink( |
||||||
255 | rtrim(storage_path('app/public/' . config('genealabs-laravel-imagery.storage-folder')), '/'), |
||||||
256 | rtrim(public_path(config('genealabs-laravel-imagery.storage-folder')), '/') |
||||||
257 | ); |
||||||
258 | } |
||||||
259 | } |
||||||
260 | } |
||||||
261 |