Completed
Push — master ( 5982d9...78edbd )
by Renato
08:50
created

ImagineImagick::watermarkCanvas()   C

Complexity

Conditions 16
Paths 4

Size

Total Lines 66
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 66
c 0
b 0
f 0
cc 16
eloc 54
nc 4
nop 3
rs 5.8516

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace NwLaravel\FileStorage;
4
5
use Imagick;
6
7
class ImagineImagick implements Imagine
8
{
9
    /**
10
     * @var Imagick
11
     */
12
    protected $image;
13
14
    /**
15
     * Construct
16
     *
17
     * @param string $path
18
     */
19
    public function __construct($path)
20
    {
21
        $this->image = new Imagick($path);
22
    }
23
24
    /**
25
     * Execute in Canvas
26
     *
27
     * @param \Closure $callback
28
     *
29
     * @return Imagine
30
     */
31
    protected function execute($callback)
32
    {
33
        $format = strtolower($this->image->getImageFormat());
34
35
        if ($format == 'gif') {
36
          $this->image = $this->image->coalesceImages();
37
          do {
38
              $callback($this->image);
39
          } while ($this->image->nextImage());
40
41
          $this->image = $this->image->deconstructImages();
42
        } else {
43
          $callback($this->image);
44
        }
45
46
        return $this;
47
    }
48
49
    /**
50
     * Filesize
51
     *
52
     * @return int
53
     */
54
    public function filesize()
55
    {
56
        return $this->image->getImageLength();
57
    }
58
59
    /**
60
     * Define Resize
61
     *
62
     * @param int     $width
63
     * @param int     $height
64
     * @param boolean $force
65
     *
66
     * @return Imagine
67
     */
68
    public function resize($width, $height, $force = false)
69
    {
70
        return $this->execute(function ($image) use ($width, $height, $force) {
71
            $image->scaleImage($width, $height, !$force);
72
        });
73
    }
74
75
    /**
76
     * Opacity
77
     *
78
     * @return Imagine
79
     */
80
    public function opacity($opacity)
81
    {
82
        $opacity = intval($opacity);
83
84
        if ($opacity > 0 && $opacity < 100) {
85
            $this->execute(function ($image) use ($opacity) {
86
                $image->setImageOpacity($opacity/100);
87
            });
88
        }
89
90
        return $this;
91
    }
92
93
    /**
94
     * Watermark
95
     *
96
     * @param string  $path
97
     * @param string  $position
98
     * @param integer $opacity
99
     *
100
     * @return Imagine
101
     */
102
    public function watermark($path, $position = 'center', $opacity = null)
103
    {
104
        if ($this->isImage($path)) {
105
            $watermark = new \Imagick($path);
106
107
            $opacity = intval($opacity);
108
            if ($opacity > 0 && $opacity < 100) {
109
                $watermark->setImageOpacity($opacity/100);
110
            }
111
112
            $self = $this;
113
114
            $this->execute(function ($image) use ($watermark, $position, $self) {
115
                $self->watermarkCanvas($image, $watermark, $position);
116
            });
117
        }
118
119
        return $this;
120
    }
121
122
    protected function watermarkCanvas(Imagick $image, Imagick $watermark, $position = 'center')
123
    {
124
        // how big are the images?
125
        $iWidth = $image->getImageWidth();
126
        $iHeight = $image->getImageHeight();
127
        $wWidth = $watermark->getImageWidth();
128
        $wHeight = $watermark->getImageHeight();
129
130
        if ($iHeight < $wHeight || $iWidth < $wWidth) {
131
          // resize the watermark
132
          $watermark->scaleImage($iWidth, $iHeight, true);
133
134
          // get new size
135
          $wWidth = $watermark->getImageWidth();
136
          $wHeight = $watermark->getImageHeight();
137
        }
138
139
        $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...
140
        $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...
141
142
        switch ($position) {
143
          case 'center':
144
          default:
145
            $x = ($iWidth - $wWidth) / 2;
146
            $y = ($iHeight - $wHeight) / 2;
147
            break;
148
          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...
149
            $x = $xOffset;
150
            $y = $yOffset;
151
            break;
152
          case 'top':
153
          case 'topCenter':
154
            $x = ($iWidth - $wWidth) / 2;
155
            $y = $yOffset;
156
            break;
157
          case 'topRight':
158
            $x = $iWidth - $wWidth - $xOffset;
159
            $y = $yOffset;
160
            break;
161
          case 'right':
162
          case 'rightCenter':
163
            $x = $iWidth - $wWidth - $xOffset;
164
            $y = ($iHeight - $wHeight) / 2;
165
            break;
166
          case 'bottomRight':
167
            $x = $iWidth - $wWidth - $xOffset;
168
            $y = $iHeight - $wHeight - $yOffset;
169
            break;
170
          case 'bottom':
171
          case 'bottomCenter':
172
            $x = ($iWidth - $wWidth) / 2;
173
            $y = $iHeight - $wHeight - $yOffset;
174
            break;
175
          case 'bottomLeft':
176
            $x = $xOffset;
177
            $y = $iHeight - $wHeight - $yOffset;
178
            break;
179
          case 'left':
180
          case 'leftCenter':
181
            $x = $xOffset;
182
            $y = ($iHeight - $wHeight) / 2;
183
            break;
184
        }
185
186
        $image->compositeImage($watermark, Imagick::COMPOSITE_OVER, $x, $y);
187
    }
188
189
    /**
190
     * Is Image
191
     *
192
     * @param string $path
193
     *
194
     * @return boolean
195
     */
196
    protected function isImage($path)
197
    {
198
        return (bool) ($path && is_file($path) && strpos(mime_content_type($path), 'image/')===0);
199
    }
200
201
    /**
202
     * Crop
203
     *
204
     * @param integer $width
205
     * @param integer $height
206
     * @param integer $x
207
     * @param integer $y
208
     *
209
     * @return binary
210
     */
211
    public function crop($width, $height, $x, $y)
212
    {
213
        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...
214
            $image->cropImage($width, $height, $x, $y);
215
        });
216
    }
217
218
    /**
219
     * Encode
220
     *
221
     * @param string  $format
222
     * @param integer $quality
223
     *
224
     * @return binary
225
     */
226
    public function encode($format = null, $quality = null)
227
    {
228
        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...
229
    }
230
231
    /**
232
     * Save
233
     *
234
     * @param string  $path
235
     * @param integer $quality
236
     *
237
     * @return binary
238
     */
239
    public function save($path, $quality = null)
240
    {
241
        // $this->image = $this->image->writeImage($path);
0 ignored issues
show
Unused Code Comprehensibility introduced by
57% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
242
        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...
243
    }
244
}
245