Completed
Pull Request — master (#17)
by Mike
09:01 queued 05:49
created

Image::getPathAttribute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
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
    //TODO: this class needs serious refactoring!!!
11
    public function __construct(
12
        string $source,
13
        string $width = null,
14
        string $height = null,
15
        Collection $htmlAttributes = null,
16
        Collection $options = null
17
    ) {
18
        parent::__construct();
19
20
        $this->createCacheFolderIfMissing();
21
22
        $this->originalHeight = $height;
0 ignored issues
show
Bug Best Practice introduced by
The property originalHeight does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
23
        $this->originalWidth = $width;
0 ignored issues
show
Bug Best Practice introduced by
The property originalWidth does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
24
        $this->htmlAttributes = $htmlAttributes;
0 ignored issues
show
Bug Best Practice introduced by
The property htmlAttributes does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
25
        $this->heightIsPercentage = str_contains($height, '%');
0 ignored issues
show
Bug Best Practice introduced by
The property heightIsPercentage does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
26
        $this->widthIsPercentage = str_contains($width, '%');
0 ignored issues
show
Bug Best Practice introduced by
The property widthIsPercentage does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
27
        $this->source = $source;
0 ignored issues
show
Bug Best Practice introduced by
The property source does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
28
        $this->image = (new ImageManager)->make($source);
0 ignored issues
show
Bug Best Practice introduced by
The property image does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
29
        $this->height = intval($height);
0 ignored issues
show
Bug Best Practice introduced by
The property height does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
30
        $this->width = intval($width);
0 ignored issues
show
Bug Best Practice introduced by
The property width does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
31
        $this->originalPath = public_path(config('genealabs-laravel-imagery.storage-folder') . basename($source));
0 ignored issues
show
Bug Best Practice introduced by
The property originalPath does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
32
        $this->alwaysPreserveAspectRatio = $options->get('alwaysPreserveAspectRatio', true);
0 ignored issues
show
Bug Best Practice introduced by
The property alwaysPreserveAspectRatio does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
Bug introduced by
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 ignore-call  annotation

32
        /** @scrutinizer ignore-call */ 
33
        $this->alwaysPreserveAspectRatio = $options->get('alwaysPreserveAspectRatio', true);

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.

Loading history...
33
        $this->doNotCreateDerivativeImages = $options->get('doNotCreateDerivativeImages', false);
0 ignored issues
show
Bug Best Practice introduced by
The property doNotCreateDerivativeImages does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
34
        $this->overrideScreenConstraint = $options->get('overrideScreenConstraint', false);
0 ignored issues
show
Bug Best Practice introduced by
The property overrideScreenConstraint does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
35
        $this->screenConstraintMethod = $options->get('screenConstraintMethod', 'contain');
0 ignored issues
show
Bug Best Practice introduced by
The property screenConstraintMethod does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
36
37
        if ($this->sourceIsUrl($source)) {
0 ignored issues
show
Unused Code introduced by
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 ignore-call  annotation

37
        if ($this->/** @scrutinizer ignore-call */ sourceIsUrl($source)) {

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.

Loading history...
38
            $this->image->save($this->originalPath);
39
        }
40
41
        $this->resizeImage($this->width, $this->height, $this->alwaysPreserveAspectRatio);
42
43
        if (! $this->doNotCreateDerivativeImages) {
44
            $job = (new RenderDerivativeImages($this->source))->onQueue('imagery');
45
            dispatch($job);
46
        }
47
    }
48
49
    protected function resizeImage(int $width, int $height, bool $alwaysPreserveAspect = false)
50
    {
51
        if (! $height || ! $width) {
52
            $height = $height ?: $this->image->getHeight();
53
            $width = $width ?: $this->image->getWidth();
54
        }
55
56
        $screenHeight = $_COOKIE['screenWidth'] ?? null;
0 ignored issues
show
Unused Code introduced by
The assignment to $screenHeight is dead and can be removed.
Loading history...
57
        $screenWidth = $_COOKIE['screenHeight'] ?? null;
58
        $screenHeight = $screenWidth ? intval($screenWidth) : null;
59
        $screenWidth = $screenWidth ? intval($screenWidth) : null;
60
        $height = $this->determineHeight($height, $screenHeight);
61
        $width = $this->determineWidth($width, $screenWidth);
62
63
        if (! $height && ! $width) {
64
            $height = $this->image->height();
65
            $width = $this->image->width();
66
        }
67
68
        $maxHeight = $this->determineMaxHeight($height, $screenHeight, $screenWidth);
69
        $maxWidth = $this->determineMaxWidth($width, $screenHeight, $screenWidth);
70
71
        $this->image->resize($maxWidth, $maxHeight, function ($constraint) use ($alwaysPreserveAspect) {
72
            if ($alwaysPreserveAspect || ! $width || ! $height) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $height seems to be never defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable $width seems to be never defined.
Loading history...
73
                $constraint->aspectRatio();
74
            }
75
76
            $constraint->upsize();
77
        });
78
79
        $this->height = $this->image->height();
0 ignored issues
show
Bug Best Practice introduced by
The property height does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
80
        $this->width = $this->image->width();
0 ignored issues
show
Bug Best Practice introduced by
The property width does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
81
        $this->storeImage();
82
    }
83
84
    //TODO: refactor to have a single return type, instead of null or int
85 View Code Duplication
    protected function determineMaxHeight($height, $screenHeight, $screenWidth)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
86
    {
87
        if (! $screenHeight || ! $screenWidth) {
88
            return $height;
89
        }
90
91
        $maxHeight = $height ?: $this->image->height();
92
93
        if (! $this->overrideScreenConstraint) {
94
            $maxHeight = $screenHeight < $maxHeight ? $screenHeight : $maxHeight;
95
96
            if ($this->screenConstraintMethod === 'cover') {
97
                $imageToScreenHeight = $screenHeight / $this->image->height();
98
                $imageToScreenWidth = $screenWidth / $this->image->width();
99
100
                if ($imageToScreenHeight < $imageToScreenWidth) {
101
                    $maxHeight = null;
102
                }
103
            }
104
        }
105
106
        return $maxHeight;
107
    }
108
109
    //TODO: refactor to have a single return type, instead of null or int
110 View Code Duplication
    protected function determineMaxWidth($width, $screenHeight, $screenWidth)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
111
    {
112
        if (! $screenHeight || ! $screenWidth) {
113
            return $width;
114
        }
115
116
        $maxWidth = $width ?: $this->image->width();
117
118
        if (! $this->overrideScreenConstraint) {
119
            $maxWidth = $screenWidth < $maxWidth ? $screenWidth : $maxWidth;
120
121
            if ($this->screenConstraintMethod === 'cover') {
122
                $imageToScreenHeight = $screenHeight / $this->image->height();
123
                $imageToScreenWidth = $screenWidth / $this->image->width();
124
                if ($imageToScreenHeight > $imageToScreenWidth) {
125
                    $maxWidth = null;
126
                }
127
            }
128
        }
129
130
        return $maxWidth;
131
    }
132
133
    protected function determineHeight($height, $screenHeight) : int
134
    {
135
        if ($screenHeight && $height && $this->heightIsPercentage) {
136
            return $screenHeight * ($height / 100);
137
        }
138
139
        return $height;
140
    }
141
142
    protected function determineWidth($width, $screenWidth) : int
143
    {
144
        if ($screenWidth && $width && $this->widthIsPercentage) {
145
            return $screenWidth * ($width / 100);
146
        }
147
148
        return $width;
149
    }
150
151
    protected function sourceIsUrl() : bool
152
    {
153
        return collect(parse_url($this->source))->has('scheme');
154
    }
155
156
    protected function storeImage()
157
    {
158
        $this->image
159
            ->save(public_path(config('genealabs-laravel-imagery.storage-folder') . $this->fileName));
0 ignored issues
show
Bug Best Practice introduced by
The property fileName does not exist on GeneaLabs\LaravelImagery\Image. Since you implemented __get, consider adding a @property annotation.
Loading history...
160
    }
161
162
    public function getFileNameAttribute() : string
163
    {
164
        $pathParts = pathinfo($this->source);
165
        $fileName = $pathParts['filename'];
166
        $extension = $pathParts['extension'] ?? '';
167
        $extension = $extension ? ".{$extension}" : '';
168
169
        if ($this->width || $this->height) {
170
            $fileName .= "_{$this->width}x{$this->height}";
171
        }
172
173
        return "{$fileName}{$extension}";
174
    }
175
176
    public function getImgAttribute() : string
177
    {
178
        $scriptUrl = mix('js/cookie.js', 'genealabs-laravel-imagery');
179
        $attributes = '';
180
181
        $attributes = $this->htmlAttributes->map(function ($value, $attribute) use (&$attributes) {
0 ignored issues
show
Bug introduced by
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 ignore-call  annotation

181
        $attributes = $this->htmlAttributes->/** @scrutinizer ignore-call */ map(function ($value, $attribute) use (&$attributes) {

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.

Loading history...
Unused Code introduced by
The import $attributes is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
182
            return " {$attribute}=\"{$value}\"";
183
        })->implode('');
184
185
        return "<img src=\"{$this->url}\"
0 ignored issues
show
Bug Best Practice introduced by
The property url does not exist on GeneaLabs\LaravelImagery\Image. Since you implemented __get, consider adding a @property annotation.
Loading history...
186
            width=\"{$this->originalWidth}\"
187
            height=\"{$this->originalHeight}\"{{ $attributes }}
188
        ><script src=\"{$scriptUrl}\"></script>";
189
    }
190
191
    public function getOriginalUrlAttribute() : string
192
    {
193
        return asset(config('genealabs-laravel-imagery.storage-folder') . $this->fileName);
0 ignored issues
show
Bug Best Practice introduced by
The property fileName does not exist on GeneaLabs\LaravelImagery\Image. Since you implemented __get, consider adding a @property annotation.
Loading history...
194
    }
195
196
    public function getPathAttribute() : string
197
    {
198
        return public_path(config('genealabs-laravel-imagery.storage-folder') . $this->fileName);
0 ignored issues
show
Bug Best Practice introduced by
The property fileName does not exist on GeneaLabs\LaravelImagery\Image. Since you implemented __get, consider adding a @property annotation.
Loading history...
199
    }
200
201
    public function getPictureAttribute() : string
202
    {
203
        //TODO: implement img tag attributes, move script to middleware injector
204
        $scriptUrl = mix('js/cookie.js', 'genealabs-laravel-imagery');
205
        $sources = '';
206
207
        foreach (array_reverse(config('genealabs-laravel-imagery.size-presets')) as $sizePreset) {
208
            $image = (new Imagery)->conjure(
209
                $this->source,
210
                $sizePreset,
211
                $sizePreset,
212
                [],
213
                ['doNotCreateDerivativeImages' => true]
214
            );
215
216
            if ($sizePreset < $this->width || $sizePreset < $this->height) {
217
                $sources .= "<source srcset=\"{$image->url}\" media=\"(min-width: {$sizePreset}px)\">";
0 ignored issues
show
Bug Best Practice introduced by
The property url does not exist on GeneaLabs\LaravelImagery\Image. Since you implemented __get, consider adding a @property annotation.
Loading history...
218
            }
219
        }
220
221
        return "
222
            <picture>
223
                {$sources}
224
                <img src=\"{$this->url}\">
225
            </picture>
226
            <script src=\"{$scriptUrl}\"></script>
227
        ";
228
    }
229
230
    public function getUrlAttribute() : string
231
    {
232
        return asset(config('genealabs-laravel-imagery.storage-folder') . $this->fileName);
0 ignored issues
show
Bug Best Practice introduced by
The property fileName does not exist on GeneaLabs\LaravelImagery\Image. Since you implemented __get, consider adding a @property annotation.
Loading history...
233
    }
234
235
    protected function createCacheFolderIfMissing()
236
    {
237
        app('filesystem')->disk('public')->makeDirectory(config('genealabs-laravel-imagery.storage-folder'));
238
239
        if (! file_exists(public_path(config('genealabs-laravel-imagery.storage-folder')))) {
240
            symlink(
241
                rtrim(storage_path('app/public/' . config('genealabs-laravel-imagery.storage-folder')), '/'),
242
                rtrim(public_path(config('genealabs-laravel-imagery.storage-folder')), '/')
243
            );
244
        }
245
    }
246
}
247