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)) { |
||||||
0 ignored issues
–
show
The call to
GeneaLabs\LaravelImagery\Image::sourceIsUrl() has too many arguments starting with $source .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||||
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; |
||||||
0 ignored issues
–
show
|
|||||||
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) { |
||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Comprehensibility
Best Practice
introduced
by
|
|||||||
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 |