Image_Transform_Driver_IM   A
last analyzed

Complexity

Total Complexity 40

Size/Duplication

Total Lines 354
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 105
dl 0
loc 354
rs 9.2
c 0
b 0
f 0
wmc 40

16 Methods

Rating   Name   Duplication   Size   Complexity  
A Image_Transform_Driver_IM() 0 3 1
A addText() 0 16 2
A __construct() 0 11 4
A _init() 0 3 1
A gamma() 0 7 2
A save() 0 22 6
A _get_image_details() 0 24 5
A load() 0 13 3
A free() 0 5 1
A greyscale() 0 5 1
A display() 0 24 5
A mirror() 0 10 2
A _resize() 0 11 2
A crop() 0 12 1
A flip() 0 10 2
A rotate() 0 8 2

How to fix   Complexity   

Complex Class

Complex classes like Image_Transform_Driver_IM 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.

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_IM, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/* vim: set expandtab tabstop=4 shiftwidth=4: */
4
5
/**
6
 * ImageMagick binaries 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: IM.php 266859 2008-09-30 22:28:47Z dufuz $
23
 * @link       http://pear.php.net/package/Image_Transform
24
 */
25
26
//require_once __DIR__ . '/Image/Transform.php';
27
//require_once __DIR__ . '/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
 * ImageMagick binaries implementation for Image_Transform package
33
 *
34
 * @category   Image
35
 * @package    Image_Transform
36
 * @subpackage Image_Transform_Driver_IM
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://www.imagemagick.org/
44
 **/
45
class Image_Transform_Driver_IM extends Image_Transform
46
{
47
    /**
48
     * associative array commands to be executed
49
     * @var array
50
     * @access private
51
     */
52
    public $command;
53
54
    /**
55
     * Class constructor
56
     */
57
    public function Image_Transform_Driver_IM()
58
    {
59
        $this->__construct();
60
    }
61
62
    // End Image_IM
63
64
    /**
65
     * Class constructor
66
     */
67
    public function __construct()
68
    {
69
        $this->_init();
70
        if (!defined('IMAGE_TRANSFORM_IM_PATH')) {
71
            $path = \dirname(System::which('convert')) . DIRECTORY_SEPARATOR;
0 ignored issues
show
Bug introduced by
It seems like System::which('convert') can also be of type false; however, parameter $path of dirname() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

71
            $path = \dirname(/** @scrutinizer ignore-type */ System::which('convert')) . DIRECTORY_SEPARATOR;
Loading history...
72
            define('IMAGE_TRANSFORM_IM_PATH', $path);
73
        }
74
        if (System::which(IMAGE_TRANSFORM_IM_PATH . 'convert' . (OS_WINDOWS ? '.exe' : ''))) {
75
            require_once __DIR__ . '/Image/Transform/Driver/Imagick/ImageTypes.php';
76
        } else {
77
            $this->isError(PEAR::raiseError('Couldn\'t find "convert" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED));
0 ignored issues
show
Bug introduced by
The method raiseError() does not exist on PEAR. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

77
            $this->isError(PEAR::/** @scrutinizer ignore-call */ raiseError('Couldn\'t find "convert" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED));
Loading history...
78
        }
79
    }
80
81
    // End Image_IM
82
83
    /**
84
     * Initialize the state of the object
85
     **/
86
    public function _init()
87
    {
88
        $this->command = [];
89
    }
90
91
    /**
92
     * Load an image.
93
     *
94
     * This method doesn't support remote files.
95
     *
96
     * @param mixed $image
97
     *
98
     * @return mixed TRUE or a PEAR error object on error
99
     * @see PEAR::isError()
100
     */
101
    public function load($image)
102
    {
103
        $this->_init();
104
        if (!file_exists($image)) {
105
            return PEAR::raiseError('The image file ' . $image . ' doesn\'t exist', IMAGE_TRANSFORM_ERROR_IO);
106
        }
107
        $this->image = $image;
108
        $result      = $this->_get_image_details($image);
109
        if (PEAR::isError($result)) {
110
            return $result;
111
        }
112
113
        return true;
114
    }
115
116
    // End load
117
118
    /**
119
     * Image_Transform_Driver_IM::_get_image_details()
120
     *
121
     * @param string $image the path and name of the image file
122
     * @return none
0 ignored issues
show
Bug introduced by
The type none was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
123
     */
124
    public function _get_image_details($image)
125
    {
126
        $retval = Image_Transform::_get_image_details($image);
127
        if (PEAR::isError($retval)) {
128
            unset($retval);
129
130
            if (!System::which(IMAGE_TRANSFORM_IM_PATH . 'identify' . (OS_WINDOWS ? '.exe' : ''))) {
131
                $this->isError(PEAR::raiseError('Couldn\'t find "identify" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED));
132
            }
133
            $cmd = $this->_prepare_cmd(IMAGE_TRANSFORM_IM_PATH, 'identify', '-format %w:%h:%m ' . escapeshellarg($image));
134
            exec($cmd, $res, $exit);
135
136
            if (0 != $exit) {
137
                return PEAR::raiseError('Cannot fetch image or images details.', true);
138
            }
139
140
            $data        = explode(':', $res[0]);
141
            $this->img_x = $data[0];
0 ignored issues
show
Documentation Bug introduced by
The property $img_x was declared of type integer, but $data[0] is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
142
            $this->img_y = $data[1];
0 ignored issues
show
Documentation Bug introduced by
The property $img_y was declared of type integer, but $data[1] is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
143
            $this->type  = mb_strtolower($data[2]);
144
            $retval      = true;
145
        }
146
147
        return $retval;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $retval also could return the type true which is incompatible with the documented return type none.
Loading history...
148
    }
149
150
    /**
151
     * Resize the image.
152
     *
153
     * @access private
154
     *
155
     * @param int   $new_x   New width
156
     * @param int   $new_y   New height
157
     * @param mixed $options Optional parameters
158
     *
159
     * @return true on success or PEAR Error object on error
160
     * @see    PEAR::isError()
161
     */
162
    public function _resize($new_x, $new_y, $options = null)
0 ignored issues
show
Unused Code introduced by
The parameter $options is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

162
    public function _resize($new_x, $new_y, /** @scrutinizer ignore-unused */ $options = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
163
    {
164
        if (isset($this->command['resize'])) {
165
            return PEAR::raiseError('You cannot scale or resize an image more than once without calling save() or display()', true);
166
        }
167
        $this->command['resize'] = '-geometry ' . ((int)$new_x) . 'x' . ((int)$new_y) . '!';
168
169
        $this->new_x = $new_x;
170
        $this->new_y = $new_y;
171
172
        return true;
173
    }
174
175
    // End resize
176
177
    /**
178
     * rotate
179
     *
180
     * @param      $angle
181
     * @param null $options
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $options is correct as it would always require null to be passed?
Loading history...
182
     * @return mixed TRUE or a PEAR error object on error
183
     */
184
    public function rotate($angle, $options = null)
185
    {
186
        $angle = $this->_rotation_angle($angle);
187
        if ($angle % 360) {
188
            $this->command['rotate'] = '-rotate ' . (float)$angle;
189
        }
190
191
        return true;
192
    }
193
194
    // End rotate
195
196
    /**
197
     * Crop image
198
     *
199
     * @param mixed $width
200
     * @param mixed $height
201
     * @param mixed $x
202
     * @param mixed $y
203
     *
204
     * @return mixed TRUE or a PEAR error object on error
205
     * @since  0.8
206
     *
207
     * @author Ian Eure <[email protected]>
208
     */
209
    public function crop($width, $height, $x = 0, $y = 0)
210
    {
211
        // Do we want a safety check - i.e. if $width+$x > $this->img_x then we
212
        // raise a warning? [and obviously same for $height+$y]
213
        $this->command['crop'] = '-crop ' . ((int)$width) . 'x' . ((int)$height) . '+' . ((int)$x) . '+' . ((int)$y) . '!';
214
215
        // I think that setting img_x/y is wrong, but scaleByLength() & friends
216
        // mess up the aspect after a crop otherwise.
217
        $this->new_x = $this->img_x = $width - $x;
218
        $this->new_y = $this->img_y = $height - $y;
219
220
        return true;
221
    }
222
223
    /**
224
     * addText
225
     *
226
     * @param mixed $params
227
     *
228
     * @return mixed TRUE or a PEAR error object on error
229
     * @see PEAR::isError()
230
     */
231
    public function addText($params)
232
    {
233
        $this->old_image = $this->imageHandle;
0 ignored issues
show
Bug introduced by
The property imageHandle does not exist on Image_Transform_Driver_IM. Did you mean image?
Loading history...
Bug Best Practice introduced by
The property old_image does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
234
        $params          = array_merge($this->_get_default_text_params(), $params);
235
        extract($params);
236
237
        if (true === $resize_first) {
238
            // Set the key so that this will be the last item in the array
239
            $key = 'ztext';
240
        } else {
241
            $key = 'text';
242
        }
243
        $this->command[$key] = '-font ' . escapeshellarg($font) . ' -fill ' . escapeshellarg($color) . ' -draw \'text ' . escapeshellarg($x . ',' . $y) . ' "' . escapeshellarg($text) . '"\'';
244
245
        // Producing error: gs: not found gs: not found convert: Postscript delegate failed [No such file or directory].
246
        return true;
247
    }
248
249
    // End addText
250
251
    /**
252
     * Adjust the image gamma
253
     *
254
     * @access public
255
     * @param float $outputgamma
256
     * @return mixed TRUE or a PEAR error object on error
257
     */
258
    public function gamma($outputgamma = 1.0)
259
    {
260
        if (1.0 != $outputgamme) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $outputgamme does not exist. Did you maybe mean $outputgamma?
Loading history...
261
            $this->command['gamma'] = '-gamma ' . (float)$outputgamma;
262
        }
263
264
        return true;
265
    }
266
267
    /**
268
     * Convert the image to greyscale
269
     *
270
     * @access public
271
     * @return mixed TRUE or a PEAR error object on error
272
     */
273
    public function greyscale()
274
    {
275
        $this->command['type'] = '-type Grayscale';
276
277
        return true;
278
    }
279
280
    /**
281
     * Horizontal mirroring
282
     *
283
     * @access public
284
     * @return true or PEAR Error object on error
285
     */
286
    public function mirror()
287
    {
288
        // We can only apply "flop" once
289
        if (isset($this->command['flop'])) {
290
            unset($this->command['flop']);
291
        } else {
292
            $this->command['flop'] = '-flop';
293
        }
294
295
        return true;
296
    }
297
298
    /**
299
     * Vertical mirroring
300
     *
301
     * @access public
302
     * @return true or PEAR Error object on error
303
     */
304
    public function flip()
305
    {
306
        // We can only apply "flip" once
307
        if (isset($this->command['flip'])) {
308
            unset($this->command['flip']);
309
        } else {
310
            $this->command['flip'] = '-flip';
311
        }
312
313
        return true;
314
    }
315
316
    /**
317
     * Save the image file
318
     *
319
     * @access public
320
     *
321
     * @param string  $filename the name of the file to write to
322
     * @param quality $quality  image dpi, default=75
0 ignored issues
show
Bug introduced by
The type quality was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
323
     * @param string  $type     (JPEG, PNG...)
324
     *
325
     * @return mixed TRUE or a PEAR error object on error
326
     */
327
    public function save($filename, $type = '', $quality = null)
328
    {
329
        $type = mb_strtoupper(('' == $type) ? $this->type : $type);
330
        switch ($type) {
331
            case 'JPEG':
332
                $type = 'JPG';
333
                break;
334
        }
335
        $options = [];
336
        if (null !== $quality) {
337
            $options['quality'] = $quality;
338
        }
339
        $quality = $this->_getOption('quality', $options, 75);
340
341
        $cmd = $this->_prepare_cmd(IMAGE_TRANSFORM_IM_PATH, 'convert', implode(' ', $this->command) . ' -quality ' . ((int)$quality) . ' ' . escapeshellarg($this->image) . ' ' . $type . ':' . escapeshellarg($filename) . ' 2>&1');
342
        exec($cmd, $res, $exit);
343
344
        if (!$this->keep_settings_on_save) {
345
            $this->free();
346
        }
347
348
        return (0 == $exit) ? true : PEAR::raiseError(implode('. ', $res), IMAGE_TRANSFORM_ERROR_IO);
349
    }
350
351
    // End save
352
353
    /**
354
     * Display image without saving and lose changes
355
     *
356
     * This method adds the Content-type HTTP header
357
     *
358
     * @access public
359
     *
360
     * @param mixed      $type
361
     * @param null|mixed $quality
362
     *
363
     * @return mixed TRUE or a PEAR error object on error
364
     */
365
    public function display($type = '', $quality = null)
366
    {
367
        $type = mb_strtoupper(('' == $type) ? $this->type : $type);
368
        switch ($type) {
369
            case 'JPEG':
370
                $type = 'JPG';
371
                break;
372
        }
373
        $options = [];
374
        if (null !== $quality) {
375
            $options['quality'] = $quality;
376
        }
377
        $quality = $this->_getOption('quality', $options, 75);
378
379
        $this->_send_display_headers($type);
380
381
        $cmd = $this->_prepare_cmd(IMAGE_TRANSFORM_IM_PATH, 'convert', implode(' ', $this->command) . " -quality $quality " . $this->image . ' ' . $type . ':-');
382
        passthru($cmd);
383
384
        if (!$this->keep_settings_on_save) {
385
            $this->free();
386
        }
387
388
        return true;
389
    }
390
391
    /**
392
     * Destroy image handle
393
     */
394
    public function free()
395
    {
396
        $this->command = [];
397
        $this->image   = '';
398
        $this->type    = '';
399
    }
400
} // End class ImageIM
401