Completed
Push — master ( 5ee1ce...92b186 )
by Renato
05:42
created

ImagineImagick::rotate()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
c 0
b 0
f 0
cc 3
nc 2
nop 1
rs 9.8666
1
<?php
2
3
namespace NwLaravel\FileStorage;
4
5
use Imagick;
6
use ImagickPixel;
7
8
class ImagineImagick implements Imagine
9
{
10
    /**
11
     * @var Imagick
12
     */
13
    protected $image;
14
15
    /**
16
     * Construct
17
     *
18
     * @param string $path
19
     */
20
    public function __construct($path)
21
    {
22
        $this->image = new Imagick($path);
23
    }
24
25
    /**
26
     * Execute in Canvas
27
     *
28
     * @param \Closure $callback
29
     *
30
     * @return Imagine
31
     */
32
    protected function execute($callback)
33
    {
34
        $format = strtolower($this->image->getImageFormat());
35
36
        if ($format == 'gif') {
37
          $this->image = $this->image->coalesceImages();
38
          do {
39
              $callback($this->image);
40
          } while ($this->image->nextImage());
41
42
          $this->image = $this->image->deconstructImages();
43
        } else {
44
          $callback($this->image);
45
        }
46
47
        return $this;
48
    }
49
50
    /**
51
     * Filesize
52
     *
53
     * @return int
54
     */
55
    public function filesize()
56
    {
57
        return $this->image->getImageLength();
58
    }
59
60
    /**
61
     * Define Resize
62
     *
63
     * @param int     $maxWidth
64
     * @param int     $maxHeight
65
     * @param boolean $force
66
     *
67
     * @return Imagine
68
     */
69
    public function resize($maxWidth, $maxHeight, $force = false)
70
    {
71
        return $this->execute(function ($image) use ($maxWidth, $maxHeight, $force) {
72
            $width = $maxWidth;
73
            $height = $maxHeight;
74
            $imageWidth = $image->getImageWidth();
75
            $imageHeight = $image->getImageHeight();
76
77
            if(($maxWidth && $imageWidth > $maxWidth) || !$maxHeight) {
78
                $height = floor(($imageHeight/$imageWidth)*$maxWidth);
79
                if (!$height) {
80
                    $height = $imageHeight;
81
                }
82
83
            } else if(($maxHeight && $imageHeight > $maxHeight) || !$maxWidth) {
84
                $width = floor(($imageWidth/$imageHeight)*$maxHeight);
85
                if (!$width) {
86
                    $width = $imageWidth;
87
                }
88
            }
89
90
            $image->scaleImage($width, $height, !$force);
91
        });
92
    }
93
94
    /**
95
     * Opacity
96
     *
97
     * @return Imagine
98
     */
99
    public function opacity($opacity)
100
    {
101
        $opacity = intval($opacity);
102
103
        if ($opacity > 0 && $opacity < 100) {
104
            $this->execute(function ($image) use ($opacity) {
105
                $image->setImageOpacity($opacity/100);
106
            });
107
        }
108
109
        return $this;
110
    }
111
112
    /**
113
     * Watermark
114
     *
115
     * @param string  $path
116
     * @param string  $position
117
     * @param integer $opacity
118
     *
119
     * @return Imagine
120
     */
121
    public function watermark($path, $position = 'center', $opacity = null)
122
    {
123
        if ($this->isImage($path)) {
124
            $watermark = new \Imagick($path);
125
126
            $opacity = intval($opacity);
127
            if ($opacity > 0 && $opacity < 100) {
128
                $watermark->setImageOpacity($opacity/100);
129
            }
130
131
            $self = $this;
132
133
            $this->execute(function ($image) use ($watermark, $position, $self) {
134
                $self->watermarkCanvas($image, $watermark, $position);
135
            });
136
        }
137
138
        return $this;
139
    }
140
141
    protected function watermarkCanvas(Imagick $image, Imagick $watermark, $position = 'center')
142
    {
143
        // how big are the images?
144
        $iWidth = $image->getImageWidth();
145
        $iHeight = $image->getImageHeight();
146
        $wWidth = $watermark->getImageWidth();
147
        $wHeight = $watermark->getImageHeight();
148
149
        if ($iHeight < $wHeight || $iWidth < $wWidth) {
150
          // resize the watermark
151
          $watermark->scaleImage($iWidth, $iHeight, true);
152
153
          // get new size
154
          $wWidth = $watermark->getImageWidth();
155
          $wHeight = $watermark->getImageHeight();
156
        }
157
158
        $xOffset = 0;
0 ignored issues
show
Unused Code introduced by
$xOffset is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
159
        $yOffset = 0;
0 ignored issues
show
Unused Code introduced by
$yOffset is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
160
161
        switch ($position) {
162
          case 'center':
163
          default:
164
            $x = ($iWidth - $wWidth) / 2;
165
            $y = ($iHeight - $wHeight) / 2;
166
            break;
167
          case 'topLeft':
0 ignored issues
show
Unused Code introduced by
case 'topLeft': $x =... = $yOffset; break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
168
            $x = $xOffset;
169
            $y = $yOffset;
170
            break;
171
          case 'top':
172
          case 'topCenter':
173
            $x = ($iWidth - $wWidth) / 2;
174
            $y = $yOffset;
175
            break;
176
          case 'topRight':
177
            $x = $iWidth - $wWidth - $xOffset;
178
            $y = $yOffset;
179
            break;
180
          case 'right':
181
          case 'rightCenter':
182
            $x = $iWidth - $wWidth - $xOffset;
183
            $y = ($iHeight - $wHeight) / 2;
184
            break;
185
          case 'bottomRight':
186
            $x = $iWidth - $wWidth - $xOffset;
187
            $y = $iHeight - $wHeight - $yOffset;
188
            break;
189
          case 'bottom':
190
          case 'bottomCenter':
191
            $x = ($iWidth - $wWidth) / 2;
192
            $y = $iHeight - $wHeight - $yOffset;
193
            break;
194
          case 'bottomLeft':
195
            $x = $xOffset;
196
            $y = $iHeight - $wHeight - $yOffset;
197
            break;
198
          case 'left':
199
          case 'leftCenter':
200
            $x = $xOffset;
201
            $y = ($iHeight - $wHeight) / 2;
202
            break;
203
        }
204
205
        $image->compositeImage($watermark, Imagick::COMPOSITE_OVER, $x, $y);
206
    }
207
208
    /**
209
     * Is Image
210
     *
211
     * @param string $path
212
     *
213
     * @return boolean
214
     */
215
    protected function isImage($path)
216
    {
217
        return (bool) ($path && is_file($path) && strpos(mime_content_type($path), 'image/')===0);
218
    }
219
220
    /**
221
     * Crop
222
     *
223
     * @param integer $width
224
     * @param integer $height
225
     * @param integer $x
226
     * @param integer $y
227
     *
228
     * @return binary
229
     */
230
    public function crop($width, $height, $x, $y)
231
    {
232
        return $this->execute(function ($image) use ($width, $height, $x, $y) {
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->execute(fu..., $height, $x, $y); }); (NwLaravel\FileStorage\Imagine) is incompatible with the return type declared by the interface NwLaravel\FileStorage\Imagine::crop of type NwLaravel\FileStorage\binary.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
233
            $image->cropImage($width, $height, $x, $y);
234
        });
235
    }
236
237
    /**
238
     * Rotate Image
239
     *
240
     * @param integer $angle
241
     *
242
     * @return binary
243
     */
244
    public function rotate($angle)
245
    {
246
        $angle = intval($angle);
247
248
        if ($angle > -360 && $angle < 360) {
249
            $this->execute(function ($image) use ($angle) {
250
                $image->rotateImage('#ffffff', $angle);
251
            });
252
        }
253
254
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (NwLaravel\FileStorage\ImagineImagick) is incompatible with the return type declared by the interface NwLaravel\FileStorage\Imagine::rotate of type NwLaravel\FileStorage\binary.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
255
    }
256
257
    /**
258
     * Encode
259
     *
260
     * @param string  $format
261
     * @param integer $quality
262
     *
263
     * @return binary
264
     */
265
    public function encode($format = null, $quality = null)
266
    {
267
        return $this->image->getImagesBlob();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->image->getImagesBlob(); (string) is incompatible with the return type declared by the interface NwLaravel\FileStorage\Imagine::encode of type NwLaravel\FileStorage\binary.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
268
    }
269
270
    /**
271
     * Save
272
     *
273
     * @param string  $path
274
     * @param integer $quality
275
     *
276
     * @return binary
277
     */
278
    public function save($path, $quality = null)
279
    {
280
        $quality = intval($quality);
281
        if ($quality > 0 && $quality <= 100) {
282
            $this->image->setImageCompressionQuality($quality);
283
        }
284
        $this->image->writeImage($path);
285
286
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (NwLaravel\FileStorage\ImagineImagick) is incompatible with the return type declared by the interface NwLaravel\FileStorage\Imagine::save of type NwLaravel\FileStorage\binary.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
287
    }
288
}
289