Completed
Branch master (954431)
by Michael
06:30 queued 03:05
created

XtubeThumbsNails::createThumbnail()   D

Complexity

Conditions 16
Paths 192

Size

Total Lines 48
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 16
eloc 25
c 3
b 0
f 0
nc 192
nop 5
dl 0
loc 48
rs 4.6845

How to fix   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
 * Module: XoopsTube
4
 *
5
 * You may not change or alter any portion of this comment or credits
6
 * of supporting developers from this source code or any supporting source code
7
 * which is considered copyrighted (c) material of the original comment or credit authors.
8
 *
9
 * PHP version 5
10
 *
11
 * @category        Module
12
 * @package         Xoopstube
13
 * @author          XOOPS Development Team
14
 * @copyright       2001-2016 XOOPS Project (http://xoops.org)
15
 * @license         GNU GPL 2 or later (http://www.gnu.org/licenses/gpl-2.0.html)
16
 * @link            http://xoops.org/
17
 * @since           1.0.6
18
 */
19
20
if (!defined('_PATH')) {
21
    define('_PATH', XOOPS_ROOT_PATH);
22
}
23
24
if (!defined('DEFAULT_PATH')) {
25
    define('DEFAULT_PATH', XOOPS_UPLOAD_URL . '/blank.gif');
26
}
27
28
/**
29
 * Class XtubeThumbsNails
30
 */
31
class XtubeThumbsNails
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...
32
{
33
    public $_imgName      = 'blank.gif';
34
    public $_img_path     = 'uploads';
35
    public $_img_savepath = 'thumbs';
36
37
    public $_source_path  = '';
38
    public $_save_path    = '';
39
    public $_source_url   = '';
40
    public $_source_image = '';
41
    public $_save_image   = '';
42
43
    public $_usethumbs       = 0;
44
    public $_image_type      = 'gd2';
45
    public $_return_fullpath = 0;
46
47
    public $img_width   = 100;
48
    public $img_height  = 100;
49
    public $img_quality = 100;
50
    public $img_update  = 1;
51
    public $img_aspect  = 1;
52
53
    // @access private
54
    public $_img_info = array();
55
56
    /**
57
     * Constructor
58
     *
59
     * @param null $img_name
60
     * @param null $img_path
61
     * @param null $img_savepath
62
     *
63
     * @internal param string $_imgName
64
     * @internal param string $_img_path
65
     * @internal param string $_img_savepath
66
     */
67
    public function __construct($img_name = null, $img_path = null, $img_savepath = null)
68
    {
69
        if (!preg_match("/\.(jpg|gif|png|jpeg)$/i", $img_name)) {
70
            return false;
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
71
        }
72
73
        // The actual image we will be processing
74
        if (!null === $img_name) {
75
            $this->_imgName = (string)trim($img_name);
76
        }
77
78
        // The image path
79
        if (!null === $img_path) {
80
            $this->_img_path = (string)trim($img_path);
81
        }
82
83
        // The image save path
84
        if (!null === $img_savepath) {
85
            $this->_img_savepath = (string)trim($img_savepath);
86
        }
87
88
        $path_to_check = XOOPS_ROOT_PATH . "/$img_path/$img_savepath";
89
90
        if (!is_dir($path_to_check)) {
91
            if (false === mkdir("$path_to_check", 0777)) {
92
                return false;
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
93
            }
94
        }
95
96
        return null;
97
    }
98
99
    /**
100
     * wfThumbsNails::setUseThumbs()
101
     *
102
     * @param integer $value
103
     *
104
     * @return void
105
     */
106
    public function setUseThumbs($value = 1)
107
    {
108
        $this->_usethumbs = $value;
109
    }
110
111
    /**
112
     * XtubeThumbsNails::setImageType()
113
     *
114
     * @param string $value
115
     *
116
     * @return void
117
     */
118
    public function setImageType($value = 'gd2')
119
    {
120
        $this->_image_type = $value;
121
    }
122
123
    /**
124
     * ThumbsNails::createThumbnail()
125
     *
126
     * @param int $img_width
0 ignored issues
show
Documentation introduced by
Should the type for parameter $img_width 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...
127
     * @param int $img_height
0 ignored issues
show
Documentation introduced by
Should the type for parameter $img_height 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...
128
     * @param int $img_quality
0 ignored issues
show
Documentation introduced by
Should the type for parameter $img_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...
129
     * @param int $img_update
0 ignored issues
show
Documentation introduced by
Should the type for parameter $img_update 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...
130
     * @param int $img_aspect
0 ignored issues
show
Documentation introduced by
Should the type for parameter $img_aspect 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...
131
     *
132
     * @return bool|string
133
     */
134
    public function createThumbnail($img_width = null, $img_height = null, $img_quality = null, $img_update = null, $img_aspect = null)
135
    {
136
        $this->_source_path  = XOOPS_ROOT_PATH . "/{$this->_img_path}";
137
        $this->_save_path    = XOOPS_ROOT_PATH . "/{$this->_img_path}/{$this->_img_savepath}";
138
        $this->_source_url   = XOOPS_URL . "/{$this->_img_path}";
139
        $this->_source_image = "{$this->_source_path}/{$this->_imgName}";
140
141
        if (isset($img_width) && !null === $img_width) {
142
            $this->img_width = (int)$img_width;
143
        }
144
145
        if (isset($img_height) && !null === $img_height) {
146
            $this->img_height = (int)$img_height;
147
        }
148
149
        if (isset($img_quality) && !null === $img_quality) {
150
            $this->img_quality = (int)$img_quality;
151
        }
152
153
        if (isset($img_update) && !null === $img_update) {
154
            $this->img_update = (int)$img_update;
155
        }
156
157
        if (isset($img_aspect) && !null === $img_aspect) {
158
            $this->img_aspect = (int)$img_aspect;
159
        }
160
161
        // Return false if we are not using thumb nails
162
        if (!$this->useThumbs()) {
163
            return $this->_source_url . '/' . $this->_imgName;
164
        }
165
        // Return false if the server does not have gd lib installed or activated
166
        if (!$this->checkGdLibrary()) {
167
            return $this->_source_url . '/' . $this->_imgName;
168
        }
169
170
        // Return false if the paths to the file are wrong
171
        if (!$this->checkPaths()) {
172
            return DEFAULT_PATH;
173
        }
174
175
        if (!$this->checkImage()) {
176
            return DEFAULT_PATH;
177
        }
178
179
        $image = $this->resizeThumbnail();
180
        return false === $image ? DEFAULT_PATH : $image;
181
    }
182
183
    /**
184
     * @param $value
185
     */
186
    public function setImageName($value)
187
    {
188
        $this->_imgName = (string)trim($value);
189
    }
190
191
    /**
192
     * @param $value
193
     */
194
    public function setImagePath($value)
195
    {
196
        $this->_img_path = (string)trim($value);
197
    }
198
199
    /**
200
     * @param $value
201
     */
202
    public function setImgSavePath($value)
203
    {
204
        $this->_img_savepath = (string)trim($value);
205
    }
206
207
    // ThumbsNails::resizeThumbnail()
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...
208
    // @return
209
    /**
210
     * @return bool|string
211
     */
212
    public function resizeThumbnail()
0 ignored issues
show
Coding Style introduced by
resizeThumbnail uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
213
    {
214
        // Get image size and scale ratio
215
        $scale = min($this->img_width / $this->_img_info[0], $this->img_height / $this->_img_info[1]);
216
        // If the image is larger than the max shrink it
217
        $newWidth  = $this->img_width;
218
        $newHeight = $this->img_height;
219
        if ($scale < 1 && 1 == $this->img_aspect) {
220
            $newWidth  = floor($scale * $this->_img_info[0]);
221
            $newHeight = floor($scale * $this->_img_info[1]);
222
        }
223
        $newWidth  = ($newWidth > $this->_img_info[0]) ? $this->_img_info[0] : $newWidth;
224
        $newHeight = ($newHeight > $this->_img_info[0]) ? $this->_img_info[0] : $newHeight;
225
226
        $savefile          = "{$newWidth}x{$newHeight}_{$this->_imgName}";
227
        $this->_save_image = "{$this->_save_path}/{$savefile}";
228
229
        if (0 == $this->img_update && file_exists($this->_save_image)) {
230
            return $this->_return_fullpath == 1 ? $this->_source_url . "/{$this->_img_savepath}/{$savefile}" : "{$this->_img_savepath}/{$savefile}";
231
        }
232
233
        switch ($this->_image_type) {
234
            case 'im':
235
                if (!empty($GLOBALS['xoopsModuleConfig']['path_magick']) && is_dir($GLOBALS['xoopsModuleConfig']['path_magick'])) {
236
                    if (preg_match("#[A-Z]:|\\\\#Ai", __FILE__)) {
237
                        $cur_dir     = __DIR__;
238
                        $src_file_im = '"' . $cur_dir . '\\' . strtr($this->_source_image, '/', '\\') . '"';
0 ignored issues
show
Unused Code introduced by
$src_file_im 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...
239
                        $new_file_im = '"' . $cur_dir . '\\' . strtr($this->_save_image, '/', '\\') . '"';
240
                    } else {
241
                        $src_file_im = escapeshellarg($this->_source_image);
0 ignored issues
show
Unused Code introduced by
$src_file_im 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...
242
                        $new_file_im = escapeshellarg($this->_save_image);
243
                    }
244
                    $magick_command = $GLOBALS['xoopsModuleConfig']['path_magick']
245
                                      . '/convert -quality {$GLOBALS["xoopsModuleConfig"]["imagequality"]} -antialias -sample {$newWidth}x{$newHeight} {$src_file_im} +profile "*" ' . str_replace('\\',
246
                                                                                                                                                                                                   '/',
247
                                                                                                                                                                                                   $new_file_im)
248
                                      . '';
249
                    passthru($magick_command);
250
251
                    return $this->_source_url . "/{$this->_img_savepath}/{$savefile}";
252
                } else {
253
                    return false;
254
                }
255
256
                break;
0 ignored issues
show
Unused Code introduced by
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...
257
258
            case 'gd1':
259
            case 'gd2':
260
            default :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a DEFAULT statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in the default statement.

switch ($expr) {
    default : //wrong
        doSomething();
        break;
}

switch ($expr) {
    default: //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
The default body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a default statement must start on the line immediately following the statement.

switch ($expr) {
    default:
        doSomething(); //right
        break;
}


switch ($expr) {
    default:

        doSomething(); //wrong
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
261
262
                $imageCreateFunction = (function_exists('imagecreatetruecolor') && 'gd2' == $this->_image_type) ? 'imagecreatetruecolor' : 'imagecreate';
263
                $imageCopyfunction   = (function_exists('ImageCopyResampled') && 'gd2' == $this->_image_type) ? 'imagecopyresampled' : 'imagecopyresized';
264
265
                switch ($this->_img_info[2]) {
266 View Code Duplication
                    case 1:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
267
                        // GIF image
268
                        $img     = function_exists('imagecreatefromgif') ? imagecreatefromgif($this->_source_image) : imagecreatefrompng($this->_source_image);
269
                        $tmp_img = $imageCreateFunction($newWidth, $newHeight);
270
                        $imageCopyfunction($tmp_img, $img, 0, 0, 0, 0, $newWidth, $newHeight, $this->_img_info[0], $this->_img_info[1]);
271
                        if (function_exists('imagegif')) {
272
                            imagegif($tmp_img, $this->_save_image);
273
                        } else {
274
                            imagepng($tmp_img, $this->_save_image);
275
                        }
276
                        imagedestroy($tmp_img);
277
                        break;
278
279 View Code Duplication
                    case 2:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
280
                        // echo $this->_save_image;
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% 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...
281
                        $img     = function_exists('imagecreatefromjpeg') ? imagecreatefromjpeg($this->_source_image) : imagecreatefrompng($this->_source_image);
282
                        $tmp_img = $imageCreateFunction($newWidth, $newHeight);
283
                        $imageCopyfunction($tmp_img, $img, 0, 0, 0, 0, $newWidth, $newHeight, $this->_img_info[0], $this->_img_info[1]);
284
                        if (function_exists('imagejpeg')) {
285
                            imagejpeg($tmp_img, $this->_save_image, $this->img_quality);
286
                        } else {
287
                            imagepng($tmp_img, $this->_save_image);
288
                        }
289
                        imagedestroy($tmp_img);
290
                        break;
291
292
                    case 3:
293
                        // PNG image
294
                        $img     = imagecreatefrompng($this->_source_image);
295
                        $tmp_img = $imageCreateFunction($newWidth, $newHeight);
296
                        $imageCopyfunction($tmp_img, $img, 0, 0, 0, 0, $newWidth, $newHeight, $this->_img_info[0], $this->_img_info[1]);
297
                        imagepng($tmp_img, $this->_save_image);
298
                        imagedestroy($tmp_img);
299
                        break;
300
                    default:
301
                        return false;
302
                }
303
                if (1 == $this->_return_fullpath) {
304
                    return $this->_source_url . "/{$this->_img_savepath}/{$savefile}";
305
                } else {
306
                    return "{$this->_img_savepath}/{$savefile}";
307
                }
308
                break;
0 ignored issues
show
Unused Code introduced by
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...
309
        }
310
        //        return FALSE;
311
    }
312
313
    // ThumbsNails::checkPaths()
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...
314
    // @return
315
    /**
316
     * @return bool
317
     */
318
    public function checkPaths()
319
    {
320
        if (file_exists($this->_source_image) || is_readable($this->_source_image)) {
321
            return true;
322
        }
323
        if (is_dir($this->_save_image) || is_writable($this->_save_image)) {
324
            return true;
325
        }
326
327
        return false;
328
    }
329
330
    /**
331
     * @return bool
332
     */
333
    public function checkImage()
334
    {
335
        $this->_img_info = getimagesize($this->_source_image, $imageinfo);
336
        if (null === $this->_img_info) {
337
            return false;
338
        }
339
340
        return true;
341
    }
342
343
    // wfsThumbs::checkGdLibrary()
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...
344
    // Private function
345
    // @return false if gd lib not found on the system
346
    /**
347
     * @return array|bool
348
     */
349
    public function checkGdLibrary()
350
    {
351
        if (!extension_loaded('gd')) {
352
            return false;
353
        }
354
        $gdlib = function_exists('gd_info');
0 ignored issues
show
Unused Code introduced by
$gdlib 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...
355
        if (false === $gdlib = gd_info()) {
356
            return false;
357
        }
358
359
        return $gdlib;
360
    }
361
362
    // ThumbsNails::useThumbs()
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...
363
    //
364
    // @return
365
    /**
366
     * @return bool
367
     */
368
    public function useThumbs()
369
    {
370
        if ($this->_usethumbs) {
371
            return true;
372
        }
373
374
        return false;
375
    }
376
}
377