Completed
Push — master ( 64c9c6...973681 )
by Michael
02:15
created

Image_Transform_Driver_NetPBM   D

Complexity

Total Complexity 141

Size/Duplication

Total Lines 479
Duplicated Lines 8.35 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
dl 40
loc 479
rs 4.8717
c 0
b 0
f 0
wmc 141
lcom 1
cbo 3

15 Methods

Rating   Name   Duplication   Size   Complexity  
A Image_Transform_Driver_NetPBM() 0 4 1
A __construct() 10 10 4
A load() 0 10 2
C _resize() 0 41 12
C rotate() 0 42 11
B crop() 0 18 8
A gamma() 0 11 4
A flip() 9 9 3
A mirror() 9 9 3
A greyscale() 9 9 3
A addText() 0 16 3
F _postProcess() 0 123 76
B save() 0 19 6
A display() 0 18 4
A free() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Image_Transform_Driver_NetPBM often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Image_Transform_Driver_NetPBM, and based on these observations, apply Extract Interface, too.

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 45 and the first side effect is on line 28.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
/* vim: set expandtab tabstop=4 shiftwidth=4: */
4
5
/**
6
 * NetPBM implementation for Image_Transform package
7
 *
8
 * PHP versions 4 and 5
9
 *
10
 * LICENSE: This source file is subject to version 3.0 of the PHP license
11
 * that is available through the world-wide-web at the following URI:
12
 * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
13
 * the PHP License and are unable to obtain it through the web, please
14
 * send a note to [email protected] so we can mail you a copy immediately.
15
 *
16
 * @category   Image
17
 * @package    Image_Transform
18
 * @author     Peter Bowyer <[email protected]>
19
 * @author     Philippe Jausions <[email protected]>
20
 * @copyright  2002-2005 The PHP Group
21
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
22
 * @version    CVS: $Id: NetPBM.php 236527 2007-05-28 16:36:09Z dufuz $
23
 * @link       http://pear.php.net/package/Image_Transform
24
 */
25
26
//require_once 'Image/Transform.php';
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% 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...
27
//require_once 'System.php';
28
require_once XOOPS_ROOT_PATH . '/modules/extgallery/class/pear/Image/Transform.php';
29
require_once XOOPS_ROOT_PATH . '/modules/extgallery/class/pear/System.php';
30
31
/**
32
 * NetPBM implementation for Image_Transform package
33
 *
34
 * @category   Image
35
 * @package    Image_Transform
36
 * @subpackage Image_Transform_Driver_NetPBM
37
 * @author     Peter Bowyer <[email protected]>
38
 * @author     Philippe Jausions <[email protected]>
39
 * @copyright  2002-2005 The PHP Group
40
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
41
 * @version    Release: @package_version@
42
 * @link       http://pear.php.net/package/Image_Transform
43
 * @link       http://netpbm.sourceforge.net/
44
 */
45
class Image_Transform_Driver_NetPBM extends Image_Transform
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
46
{
47
    /**
48
     * associative array commands to be executed
49
     * @var array
50
     */
51
    public $command = array();
52
53
    /**
54
     * Class Constructor
55
     */
56
    public function Image_Transform_Driver_NetPBM()
57
    {
58
        $this->__construct();
59
    } // End function Image_NetPBM
60
61
    /**
62
     * Class Constructor
63
     */
64 View Code Duplication
    public function __construct()
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...
65
    {
66
        if (!defined('IMAGE_TRANSFORM_NETPBM_PATH')) {
67
            $path = dirname(System::which('pnmscale')) . DIRECTORY_SEPARATOR;
68
            define('IMAGE_TRANSFORM_NETPBM_PATH', $path);
69
        }
70
        if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pnmscale' . ((OS_WINDOWS) ? '.exe' : ''))) {
71
            $this->isError(PEAR::raiseError('Couldn\'t find "pnmscale" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED));
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
72
        }
73
    } // End function Image_NetPBM
74
75
    /**
76
     * Load image
77
     *
78
     * @param string filename
79
     * @return bool|PEAR_Error TRUE or a PEAR_Error object on error
80
     * @access public
81
     */
82
    public function load($image)
83
    {
84
        $this->image = $image;
85
        $result      = $this->_get_image_details($image);
86
        if (PEAR::isError($result)) {
87
            return $result;
88
        }
89
90
        return true;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return true; (boolean) is incompatible with the return type of the parent method Image_Transform::load of type PEAR_Error.

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...
91
    } // End load
92
93
    /**
94
     * Resize the image.
95
     *
96
     * @access private
97
     *
98
     * @param int   $new_x   New width
99
     * @param int   $new_y   New height
100
     * @param mixed $options Optional parameters
101
     *
102
     * @return true on success or PEAR Error object on error
103
     * @see    PEAR::isError()
104
     */
105
    public function _resize($new_x, $new_y, $options = null)
106
    {
107
        // there's no technical reason why resize can't be called multiple
108
        // times...it's just silly to do so
109
        $scaleMethod = $this->_getOption('scaleMethod', $options, 'smooth');
110
        switch ($scaleMethod) {
111
            case 'pixel':
112
                $scale_x = $new_x / $this->img_x;
113
                if ($scale_x == $new_y / $this->img_x
114
                    && $scale_x > 1
115
                    && floor($scale_x) == $scale_x) {
116
                    if (System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pnmenlarge' . ((OS_WINDOWS) ? '.exe' : ''))) {
117
                        $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmenlarge', $scale_x);
118
                    } else {
119
                        return PEAR::raiseError('Couldn\'t find "pnmenlarge" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED);
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
120
                    }
121
                } else {
122
                    $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmscale', '-nomix -width ' . ((int)$new_x) . ' -height ' . ((int)$new_y));
123
                }
124
                break;
125
126
            case 'smooth':
127
            default:
128
                $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmscale', '-width ' . ((int)$new_x) . ' -height ' . ((int)$new_y));
129
                // Smooth things if scaling by a factor more than 3
130
                // (see pnmscale man page)
131
                if ($new_x / $this->img_x > 3
132
                    || $new_y / $this->img_y > 3) {
133
                    if (System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pnmsmooth' . ((OS_WINDOWS) ? '.exe' : ''))) {
134
                        $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmsmooth');
135
                    } else {
136
                        return PEAR::raiseError('Couldn\'t find "pnmsmooth" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED);
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
137
                    }
138
                }
139
        } // End [SWITCH]
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
140
141
        $this->_set_new_x($new_x);
142
        $this->_set_new_y($new_y);
143
144
        return true;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return true; (boolean) is incompatible with the return type documented by Image_Transform_Driver_NetPBM::_resize of type TRUE.

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...
145
    } // End resize
146
147
    /**
148
     * Rotates the image
149
     *
150
     * @param int   $angle The angle to rotate the image through
151
     * @param array $options
0 ignored issues
show
Documentation introduced by
Should the type for parameter $options not be array|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
152
     * @return bool|PEAR_Error TRUE on success, PEAR_Error object on error
153
     */
154
    public function rotate($angle, $options = null)
155
    {
156
        if (!($angle == $this->_rotation_angle($angle))) {
157
            // No rotation needed
158
            return true;
159
        }
160
161
        // For pnmrotate, we want to limit rotations from -45 to +45 degrees
162
        // even if acceptable range is -90 to +90 (see pnmrotate man page)
163
        // Bring image to that range by using pamflip
164
        if ($angle > 45 && $angle < 315) {
165
            if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pamflip' . ((OS_WINDOWS) ? '.exe' : ''))) {
166
                return PEAR::raiseError('Couldn\'t find "pamflip" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED);
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
167
            }
168
169
            $quarters        = floor(ceil($angle / 45) / 2);
170
            $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pamflip', '-rotate' . (360 - $quarters * 90));
171
            $angle           -= $quarters * 90;
172
        }
173
174
        if ($angle != 0) {
175
            if ($angle > 45) {
176
                $angle -= 360;
177
            }
178
179
            if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pnmrotate' . ((OS_WINDOWS) ? '.exe' : ''))) {
180
                return PEAR::raiseError('Couldn\'t find "pnmrotate" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED);
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
181
            }
182
183
            $bgcolor = $this->_getColor('canvasColor', $options, array(255, 255, 255));
0 ignored issues
show
Bug introduced by
It seems like $options defined by parameter $options on line 154 can also be of type null; however, Image_Transform::_getColor() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
184
            $bgcolor = $this->colorarray2colorhex($bgcolor);
185
186
            $scaleMethod = $this->_getOption('scaleMethod', $options, 'smooth');
0 ignored issues
show
Bug introduced by
It seems like $options defined by parameter $options on line 154 can also be of type null; however, Image_Transform::_getOption() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
187
            if ($scaleMethod != 'pixel') {
188
                $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmrotate', '-background=' . $bgcolor . ' -' . (float)$angle);
189
            } else {
190
                $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmrotate', '-background=' . $bgcolor . ' -noantialias -' . (float)$angle);
191
            }
192
        }
193
194
        return true;
195
    } // End rotate
196
197
    /**
198
     * Crop an image
199
     *
200
     * @param int $width  Cropped image width
201
     * @param int $height Cropped image height
202
     * @param int $x      positive X-coordinate to crop at
203
     * @param int $y      positive Y-coordinate to crop at
204
     *
205
     * @return mixed TRUE or a PEAR error object on error
206
     * @todo keep track of the new cropped size
207
     **/
208
    public function crop($width, $height, $x = 0, $y = 0)
209
    {
210
        // Sanity check
211
        if (!$this->intersects($width, $height, $x, $y)) {
212
            return PEAR::raiseError('Nothing to crop', IMAGE_TRANSFORM_ERROR_OUTOFBOUND);
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
213
        }
214
        if ($x != 0 || $y != 0
215
            || $width != $this->img_x
216
            || $height != $this->img_y) {
217
            if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pnmcut' . ((OS_WINDOWS) ? '.exe' : ''))) {
218
                return PEAR::raiseError('Couldn\'t find "pnmcut" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED);
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
219
            }
220
221
            $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmcut', '-left ' . ((int)$x) . ' -top ' . ((int)$y) . ' -width ' . ((int)$width) . ' -height ' . ((int)$height));
222
        }
223
224
        return true;
225
    } // End crop
226
227
    /**
228
     * Adjust the image gamma
229
     *
230
     * @param float $outputgamma
231
     *
232
     * @return mixed TRUE or a PEAR error object on error
233
     */
234
    public function gamma($outputgamma = 1.0)
235
    {
236
        if ($outputgamme != 1.0) {
0 ignored issues
show
Bug introduced by
The variable $outputgamme does not exist. Did you mean $outputgamma?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
237
            if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pnmgamma' . ((OS_WINDOWS) ? '.exe' : ''))) {
238
                return PEAR::raiseError('Couldn\'t find "pnmgamma" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED);
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
239
            }
240
            $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pnmgamma', (float)$outputgamma);
241
        }
242
243
        return true;
244
    }
245
246
    /**
247
     * Vertical mirroring
248
     *
249
     * @see mirror()
250
     * @return TRUE or PEAR Error object on error
251
     **/
252 View Code Duplication
    public function flip()
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...
253
    {
254
        if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pamflip' . ((OS_WINDOWS) ? '.exe' : ''))) {
255
            return PEAR::raiseError('Couldn\'t find "pamflip" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED);
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
256
        }
257
        $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pamflip', '-topbottom');
258
259
        return true;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return true; (boolean) is incompatible with the return type documented by Image_Transform_Driver_NetPBM::flip of type TRUE.

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...
260
    }
261
262
    /**
263
     * Horizontal mirroring
264
     *
265
     * @see flip()
266
     * @return TRUE or PEAR Error object on error
267
     **/
268 View Code Duplication
    public function mirror()
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...
269
    {
270
        if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'pamflip' . ((OS_WINDOWS) ? '.exe' : ''))) {
271
            return PEAR::raiseError('Couldn\'t find "pamflip" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED);
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
272
        }
273
        $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'pamflip', '-leftright');
274
275
        return true;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return true; (boolean) is incompatible with the return type documented by Image_Transform_Driver_NetPBM::mirror of type TRUE.

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...
276
    }
277
278
    /**
279
     * Converts an image into greyscale colors
280
     *
281
     * @access public
282
     * @return mixed TRUE or a PEAR error object on error
283
     **/
284 View Code Duplication
    public function greyscale()
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...
285
    {
286
        if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'ppmtopgm' . ((OS_WINDOWS) ? '.exe' : ''))) {
287
            return PEAR::raiseError('Couldn\'t find "ppmtopgm" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED);
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
288
        }
289
        $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'ppmtopgm');
290
291
        return true;
292
    }
293
294
    /**
295
     * adds text to an image
296
     *
297
     * @param   array                   options     Array contains options
298
     *                                  array(
299
     *                                  'text'          // The string to draw
300
     *                                  'x'             // Horizontal position
301
     *                                  'y'             // Vertical Position
302
     *                                  'color'         // Font color
303
     *                                  'font'          // Font to be used
304
     *                                  'size'          // Size of the fonts in pixel
305
     *                                  'resize_first'  // Tell if the image has to be resized
306
     *                                  // before drawing the text
307
     *                                  )
308
     *
309
     * @return void
310
     */
311
    public function addText($params)
312
    {
313
        if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'ppmlabel' . ((OS_WINDOWS) ? '.exe' : ''))) {
314
            return PEAR::raiseError('Couldn\'t find "ppmlabel" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED);
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
315
        }
316
317
        // we ignore 'resize_first' since the more logical approach would be
318
        // for the user to just call $this->_resize() _first_ ;)
319
        extract(array_merge($this->_get_default_text_params(), $params));
0 ignored issues
show
Bug introduced by
array_merge($this->_get_...text_params(), $params) cannot be passed to extract() as the parameter $var_array expects a reference.
Loading history...
320
321
        $options = array('colorFont' => $color);
322
        $color   = $this->_getColor('colorFont', $options, array(0, 0, 0));
323
        $color   = $this->colorarray2colorhex($color);
324
325
        $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'ppmlabel', '-angle ' . ((int)$angle) . ' -colour ' . escapeshellarg($color) . ' -size ' . ((float)$size) . ' -x ' . ((int)$x) . ' -y ' . ((int)($y + $size)) . ' -text ' . escapeshellarg($text));
326
    } // End addText
327
328
    /**
329
     * Image_Transform_Driver_NetPBM::_postProcess()
330
     *
331
     * @param $type
332
     * @param $quality
333
     * @return string A chain of shell command
334
     * @link http://netpbm.sourceforge.net/doc/directory.html
335
     */
336
    public function _postProcess($type, $quality)
337
    {
338
        array_unshift($this->command, $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, strtolower($this->type) . 'topnm', escapeshellarg($this->image)));
339
        $arg     = '';
0 ignored issues
show
Unused Code introduced by
$arg 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...
340
        $type    = strtolower($type);
341
        $program = '';
342
        switch ($type) {
343
            // ppmto* converters
344
            case 'gif':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
345
                if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . 'ppmquant' . ((OS_WINDOWS) ? '.exe' : ''))) {
346
                    return PEAR::raiseError('Couldn\'t find "ppmquant" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED);
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
347
                }
348
                $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, 'ppmquant', 256);
349
            case 'acad':
350
            case 'bmp':
351
            case 'eyuv':
352
            case 'ilbm':
353
            case 'leaf':
354
            case 'lj':
355
            case 'mitsu':
356
            case 'mpeg':
357
            case 'neo':
358
            case 'pcx':
359
            case 'pi1':
360
            case 'pict':
361
            case 'pj':
362
            case 'pjxl':
363
            case 'puzz':
364
            case 'sixel':
365
            case 'tga':
366
            case 'uil':
367
            case 'xpm':
368
            case 'yuv':
369
                $program = 'ppmto' . $type;
370
                break;
371
372
            // Windows icon
373
            case 'winicon':
374
            case 'ico':
375
                $type    = 'winicon';
376
                $program = 'ppmto' . $type;
377
                break;
378
379
            // pbmto* converters
380
            case 'ascii':
381
            case 'text':
382
            case 'txt':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
383
                $type = 'ascii';
384
            case 'atk':
385
            case 'bbubg':
386
            case 'epsi':
387
            case 'epson':
388
            case 'escp2':
389
            case 'icon':    // Sun icon
390
            case 'gem':
391
            case 'go':
392
            case 'lj':
393
            case 'ln03':
394
            case 'lps':
395
            case 'macp':
396
            case 'mda':
397
            case 'mgr':
398
            case 'pi3':
399
            case 'pk':
400
            case 'plot':
401
            case 'ptx':
402
            case 'wbp':
403
            case 'xbm':
404
            case 'x10bm':
405
            case 'ybm':
406
            case 'zinc':
407
            case '10x':
408
                $program = 'pbmto' . $type;
409
                break;
410
411
            // pamto* converters
412
            case 'jpc':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
413
                $type = 'jpeg2k';
414
            case 'html':
415
            case 'pfm':
416
            case 'tga':
417
                $program = 'pamto' . $type;
418
                break;
419
420
            // pnmto* converters
421
            case 'jpc':
422
                $type = 'jpeg2k';
423
                break;
424
            case 'wfa':
425
                $type = 'fiasco';
426
                break;
427
            case 'jpg':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
428
                $type = 'jpeg';
429
            case 'jpeg':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
430
                $arg = '--quality=' . $quality;
0 ignored issues
show
Unused Code introduced by
$arg 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...
431
            case 'jbig':
432
            case 'fits':
433
            case 'palm':
434
            case 'pclxl':
435
            case 'png':
436
            case 'ps':
437
            case 'rast':
438
            case 'rle':
439
            case 'sgi':
440
            case 'sir':
441
            case 'tiff':
442
            case 'xwd':
443
                $program = 'pnmto' . $type;
444
                break;
445
446
        } // switch
447
448
        if ($program == '') {
449
            $program = 'pnmto' . $type;
450
        }
451
452
        if (!System::which(IMAGE_TRANSFORM_NETPBM_PATH . $program . ((OS_WINDOWS) ? '.exe' : ''))) {
453
            return PEAR::raiseError("Couldn't find \"$program\" binary", IMAGE_TRANSFORM_ERROR_UNSUPPORTED);
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
454
        }
455
        $this->command[] = $this->_prepare_cmd(IMAGE_TRANSFORM_NETPBM_PATH, $program);
456
457
        return implode('|', $this->command);
458
    }
459
460
    /**
461
     * Save the image file
462
     *
463
     * @param        $filename string the name of the file to write to
464
     * @param string $type     (jpeg,png...);
0 ignored issues
show
Documentation introduced by
Should the type for parameter $type not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
465
     * @param int    $quality  75
466
     * @return TRUE or PEAR Error object on error
467
     */
468
    public function save($filename, $type = null, $quality = 75)
469
    {
470
        $type    = (is_null($type)) ? $this->type : $type;
471
        $options = array();
472
        if (!is_null($quality)) {
473
            $options['quality'] = $quality;
474
        }
475
        $quality = $this->_getOption('quality', $options, $quality);
476
477
        $nullDevice = (OS_WINDOWS) ? 'nul' : '/dev/null';
478
479
        $cmd = $this->_postProcess($type, $quality) . '> "' . $filename . '"';
480
        exec($cmd . ' 2>  ' . $nullDevice, $res, $exit);
481
        if (!$this->keep_settings_on_save) {
482
            $this->free();
483
        }
484
485
        return ($exit == 0) ? true : PEAR::raiseError(implode('. ', $res), IMAGE_TRANSFORM_ERROR_IO);
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Did you maybe mean _raiseError()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
Bug introduced by
It seems like you are loosely comparing $exit of type integer|null to 0; this is ambiguous as not only 0 == 0 is true, but null == 0 is true, too. Consider using a strict comparison ===.
Loading history...
486
    } // End save
487
488
    /**
489
     * Display image without saving and lose changes
490
     *
491
     * @param string $type    (jpeg,png...);
0 ignored issues
show
Documentation introduced by
Should the type for parameter $type not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
492
     * @param int    $quality 75
0 ignored issues
show
Documentation introduced by
Should the type for parameter $quality not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
493
     * @return TRUE or PEAR Error object on error
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
494
     */
495
    public function display($type = null, $quality = null)
496
    {
497
        $type    = (is_null($type)) ? $this->type : $type;
498
        $options = array();
499
        if (!is_null($quality)) {
500
            $options['quality'] = $quality;
501
        }
502
        $quality = $this->_getOption('quality', $options, 75);
503
504
        header('Content-type: ' . $this->getMimeType($type));
505
        $cmd = $this->_postProcess($type, $quality);
506
        passthru($cmd . ' 2>&1');
507
        if (!$this->keep_settings_on_save) {
508
            $this->free();
509
        }
510
511
        return true;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return true; (boolean) is incompatible with the return type of the parent method Image_Transform::display of type PEAR_Error.

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...
512
    }
513
514
    /**
515
     * Destroy image handle
516
     *
517
     * @return void
518
     */
519
    public function free()
520
    {
521
        $this->command = array();
522
    }
523
} // End class ImageIM
524