Image   A
last analyzed

Complexity

Total Complexity 30

Size/Duplication

Total Lines 272
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 30
lcom 1
cbo 3
dl 0
loc 272
ccs 83
cts 83
cp 1
rs 10
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A save() 0 15 2
A __construct() 0 10 3
A getImage() 0 4 1
A setImage() 0 4 1
A getWidth() 0 4 1
A getHeight() 0 4 1
A getFileSize() 0 4 1
A getInfo() 0 10 1
A scale_and_crop() 0 19 3
B scale() 0 18 6
A resize() 0 4 1
A rotate() 0 15 3
B crop() 0 20 5
A desaturate() 0 4 1
1
<?php
2
3
/**
4
 * An image to run through imagecache
5
 */
6
namespace Onigoetz\Imagecache;
7
8
use Intervention\Image\ImageManagerStatic as InterventionImage;
9
10
/**
11
 * An image to run through imagecache
12
 */
13
class Image
14
{
15
    /**
16
     * File source
17
     * @var string
18
     */
19
    public $source;
20
21
    /**
22
     * Informations about the image
23
     * @var array
24
     */
25
    protected $info;
26
27
    /**
28
     * Image resource
29
     * @var \Intervention\Image\Image
30
     */
31
    protected $image;
32
33
    /**
34
     * Create an image and get informations about it
35
     *
36
     * @param string $source
37
     *
38
     * @throws \Exception if cannot find or load the file
39
     */
40 105
    public function __construct($source)
41
    {
42 105
        $this->source = $source;
43
44 105
        if (!is_file($this->source) && !is_uploaded_file($this->source)) {
45 3
            throw new Exceptions\NotFoundException('file not found');
46
        }
47
48 102
        $this->image = InterventionImage::make($source);
49 96
    }
50
51
    /**
52
     * @return \Intervention\Image\Image
53
     */
54 18
    public function getImage()
55
    {
56 18
        return $this->image;
57
    }
58
59
    /**
60
     * @param \Intervention\Image\Image $image
61
     * used mainly for unit tests, we cannot typehint as we get a mockery object
62
     */
63 18
    public function setImage($image)
64
    {
65 18
        $this->image = $image;
66 18
    }
67
68
    /**
69
     * File's width
70
     *
71
     * @return int
72
     */
73 54
    public function getWidth()
74
    {
75 54
        return $this->image->getWidth();
76
    }
77
78
    /**
79
     * File's height
80
     *
81
     * @return int
82
     */
83 51
    public function getHeight()
84
    {
85 51
        return $this->image->getHeight();
86
    }
87
88
    /**
89
     * File's size
90
     *
91
     * @return int
92
     */
93 6
    public function getFileSize()
94
    {
95 6
        return filesize($this->source);
96
    }
97
98
    /**
99
     * Get details about an image.
100
     *
101
     * @return bool|array false, if the file could not be found or is not an image. Otherwise, a keyed array containing information about the image:
102
     *   - "width": Width, in pixels.
103
     *   - "height": Height, in pixels.
104
     *   - "file_size": File size in bytes.
105
     */
106 3
    public function getInfo()
107
    {
108 3
        $this->info = [
109 3
            'width' => $this->getWidth(),
110 3
            'height' => $this->getHeight(),
111 3
            'file_size' => $this->getFileSize(),
112
        ];
113
114 3
        return $this->info;
115
    }
116
117
    /**
118
     * Scales an image to the exact width and height given.
119
     *
120
     * This function achieves the target aspect ratio by cropping the original image
121
     * equally on both sides, or equally on the top and bottom. This function is
122
     * useful to create uniform sized avatars from larger images.
123
     *
124
     * The resulting image always has the exact target dimensions.
125
     *
126
     * @param int $width The target width, in pixels.
127
     * @param int $height The target height, in pixels.
128
     *
129
     * @throws \LogicException if the parameters are wrong
130
     *
131
     * @see resize()
132
     * @see crop()
133
     */
134 33
    public function scale_and_crop($width, $height)
135
    {
136 33
        if ($width === null) {
137 3
            throw new \LogicException('"width" must not be null for "scale_and_crop"');
138
        }
139
140 30
        if ($height === null) {
141 3
            throw new \LogicException('"height" must not be null for "scale_and_crop"');
142
        }
143
144 27
        $scale = max($width / $this->getWidth(), $height / $this->getHeight());
145 27
        $w = ceil($this->getWidth() * $scale);
146 27
        $h = ceil($this->getHeight() * $scale);
147 27
        $x = ($w - $width) / 2;
148 27
        $y = ($h - $height) / 2;
149
150 27
        $this->resize($w, $h);
151 27
        $this->crop($x, $y, $width, $height);
152 27
    }
153
154
    /**
155
     * Scales an image to the given width and height while maintaining aspect ratio.
156
     *
157
     * The resulting image can be smaller for one or both target dimensions.
158
     *
159
     * @param int $width
160
     *   The target width, in pixels. This value is omitted then the scaling will
161
     *   based only on the height value.
162
     * @param int $height
163
     *   The target height, in pixels. This value is omitted then the scaling will
164
     *   based only on the width value.
165
     */
166 15
    public function scale($width = null, $height = null)
167
    {
168 15
        if ($width === null && $height === null) {
169 3
            throw new \LogicException('one of "width" or "height" must be set for "scale"');
170
        }
171
172 12
        if ($width !== null && $height !== null) {
173 3
            $this->resize($width, $height);
174 3
            return;
175
        }
176
177 9
        if ($width !== null) {
178 6
            $this->image->widen($width);
179 6
            return;
180
        }
181
182 3
        $this->image->heighten($height);
183 3
    }
184
185
    /**
186
     * Resize an image to the given dimensions (ignoring aspect ratio).
187
     *
188
     * @param int $width The target width, in pixels.
189
     * @param int $height The target height, in pixels.
190
     */
191 36
    public function resize($width, $height)
192
    {
193 36
        $this->image->resize($width, $height);
194 36
    }
195
196
    /**
197
     * Rotate an image by the given number of degrees.
198
     *
199
     * @param  int $degrees The number of (clockwise) degrees to rotate the image.
200
     * @param  string|null $background hexadecimal background color
201
     * @param  bool $random
202
     */
203 9
    public function rotate($degrees, $background = null, $random = false)
204
    {
205 9
        if ($background) {
0 ignored issues
show
Bug Best Practice introduced by Stéphane Goetz
The expression $background of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
206 3
            $background = trim($background);
207 1
        } else {
208 6
            $background = "ffffff";
209
        }
210
211 9
        if ($random) {
212 3
            $deg = abs((float) $degrees);
213 3
            $degrees = rand(-1 * $deg, $deg);
214 1
        }
215
216 9
        $this->image->rotate($degrees, $background);
217 9
    }
218
219
    /**
220
     * Crop an image to the rectangle specified by the given rectangle.
221
     *
222
     * @param int $xoffset
223
     *   The top left coordinate, in pixels, of the crop area (x axis value).
224
     * @param int $yoffset
225
     *   The top left coordinate, in pixels, of the crop area (y axis value).
226
     * @param int $width
227
     *   The target width, in pixels.
228
     * @param int $height
229
     *   The target height, in pixels.
230
     *
231
     * @throws \LogicException if the parameters are wrong
232
     */
233 48
    public function crop($xoffset, $yoffset, $width, $height)
234
    {
235 48
        if ($xoffset === null) {
236 3
            throw new \LogicException('"xoffset" must not be null for "crop"');
237
        }
238
239 45
        if ($yoffset === null) {
240 3
            throw new \LogicException('"yoffset" must not be null for "crop"');
241
        }
242
243 42
        if ($width === null) {
244 3
            throw new \LogicException('"width" must not be null for "crop"');
245
        }
246
247 39
        if ($height === null) {
248 3
            throw new \LogicException('"height" must not be null for "crop"');
249
        }
250
251 36
        $this->image->crop($width, $height, $xoffset, $yoffset);
252 36
    }
253
254
    /**
255
     * Convert an image to grayscale.
256
     */
257 3
    public function desaturate()
258
    {
259 3
        $this->image->greyscale();
260 3
    }
261
262
    /**
263
     * Close the image and save the changes to a file.
264
     *
265
     * @param  string|null $destination Destination path where the image should be saved. If it is empty the original image file will be overwritten.
266
     * @throws \RuntimeException
267
     * @return Image  image or false, based on success.
268
     */
269 54
    public function save($destination = null)
270
    {
271 54
        if (empty($destination)) {
272 6
            $destination = $this->source;
273 2
        }
274
275 54
        $this->image->save($destination);
276
277
        // Clear the cached file size and refresh the image information.
278 51
        clearstatcache();
279
280 51
        chmod($destination, 0644);
281
282 51
        return new self($destination);
283
    }
284
}
285