Passed
Pull Request — master (#1)
by compolom
02:43
created

AbstractImage::resizeByHeight()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Compolomus\Compomage;
4
5
use Compolomus\Compomage\Interfaces\ImageInterface;
6
use Exception;
7
use InvalidArgumentException;
8
use LogicException;
9
use RuntimeException;
10
use SplFileObject;
11
12
abstract class AbstractImage implements ImageInterface
13
{
14
    protected const POSITIONS = [
15
        'NORTHWEST' => ['x' => 0, 'y' => 0, 'padX' => 10, 'padY' => 10],
16
        'NORTH' => ['x' => 1, 'y' => 0, 'padX' => 0, 'padY' => 10],
17
        'NORTHEAST' => ['x' => 2, 'y' => 0, 'padX' => -10, 'padY' => 10],
18
        'WEST' => ['x' => 0, 'y' => 1, 'padX' => 10, 'padY' => 0],
19
        'CENTER' => ['x' => 1, 'y' => 1, 'padX' => 0, 'padY' => 0],
20
        'EAST' => ['x' => 2, 'y' => 1, 'padX' => -10, 'padY' => 0],
21
        'SOUTHWEST' => ['x' => 0, 'y' => 2, 'padX' => 10, 'padY' => -10],
22
        'SOUTH' => ['x' => 1, 'y' => 2, 'padX' => 0, 'padY' => -10],
23
        'SOUTHEAST' => ['x' => 2, 'y' => 2, 'padX' => -10, 'padY' => -10]
24
    ];
25
26
    protected $image;
27
28
    protected $width;
29
30
    protected $height;
31
32
    protected $orientation;
33
34
    /**
35
     * @param int $value
36
     * @param int $range
37
     * @return bool
38
     */
39
    protected function compareRangeValue(int $value, int $range): bool
40
    {
41
        return in_array(abs($value), range(0, $range), true);
42
    }
43
44
    /**
45
     * @param int $width
46
     * @param int $height
47
     * @param Image $background
48
     * @return ImageInterface
49
     */
50
    protected function setBackground(int $width, int $height, $background): ImageInterface
51
    {
52
        $this->orientation === 'vertical'
53
            ? $this->resizeByHeight($height)
54
            : $this->resizeByWidth($width);
55
56
        $background->watermark($this, 'CENTER');
57
58
        $this->setImage($background->getImage());
59
        $this->setSizes();
60
61
        return $this;
62
    }
63
64 13
    protected function setOrientation(): void
65
    {
66 13
        $this->orientation = $this->getWidth() < $this->getHeight() ? 'vertical' : 'horizontal';
67 13
    }
68
69
    public function getOrientation(): string
70
    {
71
        return $this->orientation;
72
    }
73
74
    /**
75
     * @param string $mode
76
     * @param int $param
77
     * @return ImageInterface
78
     * @throws InvalidArgumentException
79
     */
80 2
    public function resizeBy(string $mode, int $param): ImageInterface
81
    {
82 2
        switch ($mode) {
83 2
            case 'width':
84 1
                return $this->resizeByWidth($param);
85 2
            case 'height':
86 1
                return $this->resizeByHeight($param);
87 2
            case 'percent':
88 1
                return $this->resizeByPercent($param);
89
            default:
90 1
                throw new InvalidArgumentException('Unsupported mode type by resize');
91
        }
92
    }
93
94
    /**
95
     * @param int $width
96
     * @return ImageInterface
97
     */
98 1
    public function resizeByWidth(int $width): ImageInterface
99
    {
100 1
        return $this->resize($width, $this->getHeight() * ($width / $this->getWidth()));
101
    }
102
103
    /**
104
     * @return int
105
     */
106 14
    public function getHeight(): int
107
    {
108 14
        return $this->height;
109
    }
110
111
    /**
112
     * @param int $height
113
     */
114 13
    protected function setHeight(int $height): void
115
    {
116 13
        $this->height = $height;
117 13
    }
118
119
    /**
120
     * @return int
121
     */
122 14
    public function getWidth(): int
123
    {
124 14
        return $this->width;
125
    }
126
127
    /**
128
     * @param int $width
129
     */
130 13
    protected function setWidth(int $width): void
131
    {
132 13
        $this->width = $width;
133 13
    }
134
135
    /**
136
     * @param int $height
137
     * @return ImageInterface
138
     */
139 1
    public function resizeByHeight(int $height): ImageInterface
140
    {
141 1
        return $this->resize($this->getWidth() * ($height / $this->getHeight()), $height);
142
    }
143
144
    /**
145
     * @param int $percent
146
     * @return ImageInterface
147
     */
148 1
    public function resizeByPercent(int $percent): ImageInterface
149
    {
150 1
        $width = $this->getWidth() * ($percent / 100);
151 1
        $height = $this->getHeight() * ($percent / 100);
152 1
        return $this->resize($width, $height);
153
    }
154
155
    abstract protected function newImage(int $width, int $height);
156
157
    /**
158
     * @param ImageInterface|Image $watermark
159
     * @param string $position
160
     * @return ImageInterface
161
     * @throws InvalidArgumentException
162
     */
163 1
    public function watermark($watermark, string $position): ImageInterface
164
    {
165 1
        if (!array_key_exists(strtoupper($position), self::POSITIONS)) {
166 1
            throw new InvalidArgumentException('Wrong position');
167
        }
168
169
        return $this->prepareWatermark(
170
            $watermark,
171
            (int) ((($this->getWidth() - $watermark->getWidth()) / 2) * self::POSITIONS[strtoupper($position)]['x']) + self::POSITIONS[strtoupper($position)]['padX'],
0 ignored issues
show
Bug introduced by
The method getWidth does only exist in Compolomus\Compomage\Image, but not in Compolomus\Compomage\Interfaces\ImageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
172
            (int) ((($this->getHeight() - $watermark->getHeight()) / 2) * self::POSITIONS[strtoupper($position)]['y']) + self::POSITIONS[strtoupper($position)]['padY']
0 ignored issues
show
Bug introduced by
The method getHeight does only exist in Compolomus\Compomage\Image, but not in Compolomus\Compomage\Interfaces\ImageInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
173
        );
174
    }
175
176
    /**
177
     * @param ImageInterface|Image $watermark
178
     * @param int $x
179
     * @param int $y
180
     * @return ImageInterface
181
     */
182
    abstract protected function prepareWatermark($watermark, int $x, int $y): ImageInterface;
183
184
    /**
185
     * @param int $width
186
     * @param int $height
187
     * @return ImageInterface
188
     */
189 2
    public function thumbnail(int $width, int $height): ImageInterface
190
    {
191 2
        $newHeight = $height;
192 2
        $newWidth = $width;
193
194 2
        $this->getWidth() / $this->getHeight() >= $width / $height
195 1
            ? $newWidth = (int) ($this->getWidth() / ($this->getHeight() / $height))
196 1
            : $newHeight = (int) ($this->getHeight() / ($this->getWidth() / $width));
197
198 2
        return $this->prepareThumbnail($width, $height, $newWidth, $newHeight);
0 ignored issues
show
Unused Code introduced by
The call to AbstractImage::prepareThumbnail() has too many arguments starting with $newWidth.

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.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
199
    }
200
201
    /**
202
     * @param int $width
203
     * @param int $height
204
     * @return ImageInterface
205
     */
206
    abstract protected function prepareThumbnail(int $width, int $height): ImageInterface;
207
208
    /**
209
     * @return string chunked base64
210
     */
211 1
    public function getBase64(): string
212
    {
213 1
        return base64_encode((string) $this);
214
215
    }
216
217
    /**
218
     * @param $image
219
     */
220 13
    protected function setImage($image): void
221
    {
222 13
        $this->image = $image;
223 13
    }
224
225 16
    public function getImage()
226
    {
227 16
        return $this->image;
228
    }
229
230
    /**
231
     * System method
232
     *
233
     * @param void
234
     */
235
    abstract protected function setSizes(): void;
236
237
    /**
238
     * @param string $image
239
     * @throws Exception
240
     */
241 14
    protected function init(string $image): void
242
    {
243
        switch ($image) {
244
            // base64
245 14
            case base64_encode(base64_decode($image, true)) === $image:
246 4
                $this->getImageByBase64($image);
247 3
                break;
248
            // URL
249 12
            case (0 === strpos($image, 'http')):
250 3
                $this->getImageByURL($image);
251 2
                break;
252
            // Local file
253
            default:
254 11
                $this->tmp(file_get_contents($image));
255
        }
256 12
    }
257
258
    /**
259
     * @param string $base64
260
     * @return void
261
     * @throws Exception
262
     */
263 4
    protected function getImageByBase64(string $base64): void
264
    {
265 4
        $this->tmp(base64_decode($base64));
266 3
    }
267
268
    /**
269
     * @param string $source
270
     * @return ImageInterface
271
     */
272
    abstract protected function tmp(string $source): ImageInterface;
273
274
    /**
275
     * @param string $url
276
     * @return InvalidArgumentException|null
277
     * @throws Exception
278
     * @throws InvalidArgumentException
279
     * @throws LogicException
280
     * @throws RuntimeException
281
     */
282 3
    protected function getImageByURL(string $url): ?InvalidArgumentException
283
    {
284 3
        if (@!getimagesize($url)) {
285 1
            throw new InvalidArgumentException('Unsupported image type');
286
        }
287 2
        $upload = new SplFileObject($url, 'rb');
288 2
        $image = '';
289 2
        while (!$upload->eof()) {
290 2
            $image .= $upload->fgets();
291
        }
292 2
        $this->tmp($image);
293
294 2
        return null;
295
    }
296
}
297