Completed
Pull Request — master (#10)
by Michael
02:01
created

XfguestbookUtil   D

Complexity

Total Complexity 58

Size/Duplication

Total Lines 307
Duplicated Lines 5.21 %

Coupling/Cohesion

Components 0
Dependencies 0

Importance

Changes 0
Metric Value
dl 16
loc 307
rs 4.8387
c 0
b 0
f 0
wmc 58
lcom 0
cbo 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
B createFolder() 0 14 5
A copyFile() 0 14 1
B recurseCopy() 0 15 5
C checkVerXoops() 0 33 7
A checkVerPhp() 0 16 4
C upload() 0 30 8
A getCountry() 16 16 4
A getAllCountry() 0 17 4
C get_user_data() 0 27 8
B clear_tmp_files() 0 19 5
A get_badips() 0 18 4
A email_exist() 0 10 3

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

1
<?php
2
3
/**
4
 * Class MyalbumUtil
5
 */
6
class XfguestbookUtil extends XoopsObject
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...
7
{
8
    /**
9
     * Function responsible for checking if a directory exists, we can also write in and create an index.html file
10
     *
11
     * @param string $folder The full path of the directory to check
12
     *
13
     * @return void
14
     */
15
    public static function createFolder($folder)
16
    {
17
        try {
18
            if (!file_exists($folder)) {
19
                if (!mkdir($folder) && !is_dir($folder)) {
20
                    throw new \RuntimeException(sprintf('Unable to create the %s directory', $folder));
21
                } else {
22
                    file_put_contents($folder . '/index.html', '<script>history.go(-1);</script>');
23
                }
24
            }
25
        } catch (Exception $e) {
26
            echo 'Caught exception: ', $e->getMessage(), "\n", '<br/>';
27
        }
28
    }
29
30
    /**
31
     * @param $file
32
     * @param $folder
33
     * @return bool
34
     */
35
    public static function copyFile($file, $folder)
36
    {
37
        return copy($file, $folder);
38
        //        try {
39
        //            if (!is_dir($folder)) {
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...
40
        //                throw new \RuntimeException(sprintf('Unable to copy file as: %s ', $folder));
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% 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...
41
        //            } else {
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...
42
        //                return copy($file, $folder);
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% 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...
43
        //            }
44
        //        } catch (Exception $e) {
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...
45
        //            echo 'Caught exception: ', $e->getMessage(), "\n", "<br/>";
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...
46
        //        }
47
        //        return false;
48
    }
49
50
    /**
51
     * @param $src
52
     * @param $dst
53
     */
54
    public static function recurseCopy($src, $dst)
55
    {
56
        $dir = opendir($src);
57
        //    @mkdir($dst);
58
        while (false !== ($file = readdir($dir))) {
59
            if (($file !== '.') && ($file !== '..')) {
60
                if (is_dir($src . '/' . $file)) {
61
                    self::recurseCopy($src . '/' . $file, $dst . '/' . $file);
62
                } else {
63
                    copy($src . '/' . $file, $dst . '/' . $file);
64
                }
65
            }
66
        }
67
        closedir($dir);
68
    }
69
70
    /**
71
     *
72
     * Verifies XOOPS version meets minimum requirements for this module
73
     * @static
74
     * @param XoopsModule $module
75
     *
76
     * @return bool true if meets requirements, false if not
77
     */
78
    public static function checkVerXoops(XoopsModule $module)
79
    {
80
        xoops_loadLanguage('admin', $module->dirname());
81
        //check for minimum XOOPS version
82
        $currentVer  = substr(XOOPS_VERSION, 6); // get the numeric part of string
83
        $currArray   = explode('.', $currentVer);
84
        $requiredVer = '' . $module->getInfo('min_xoops'); //making sure it's a string
85
        $reqArray    = explode('.', $requiredVer);
86
        $success     = true;
87
        foreach ($reqArray as $k => $v) {
88
            if (isset($currArray[$k])) {
89
                if ($currArray[$k] > $v) {
90
                    break;
91
                } elseif ($currArray[$k] == $v) {
92
                    continue;
93
                } else {
94
                    $success = false;
95
                    break;
96
                }
97
            } else {
98
                if ((int)$v > 0) { // handles things like x.x.x.0_RC2
99
                    $success = false;
100
                    break;
101
                }
102
            }
103
        }
104
105
        if (!$success) {
106
            $module->setErrors(sprintf(_AM_XFGUESTBOOK_ERROR_BAD_XOOPS, $requiredVer, $currentVer));
107
        }
108
109
        return $success;
110
    }
111
112
    /**
113
     *
114
     * Verifies PHP version meets minimum requirements for this module
115
     * @static
116
     * @param XoopsModule $module
117
     *
118
     * @return bool true if meets requirements, false if not
119
     */
120
    public static function checkVerPhp(XoopsModule $module)
121
    {
122
        xoops_loadLanguage('admin', $module->dirname());
123
        // check for minimum PHP version
124
        $success = true;
125
        $verNum  = phpversion();
126
        $reqVer  =& $module->getInfo('min_php');
127
        if (false !== $reqVer && '' !== $reqVer) {
128
            if (version_compare($verNum, $reqVer, '<')) {
129
                $module->setErrors(sprintf(_AM_XFGUESTBOOK_ERROR_BAD_PHP, $reqVer, $verNum));
130
                $success = false;
131
            }
132
        }
133
134
        return $success;
135
    }
136
137
    public static function upload()
0 ignored issues
show
Coding Style introduced by
upload uses the super-global variable $_FILES 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...
Coding Style introduced by
upload uses the super-global variable $_POST 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...
138
    {
139
        global $xoopsModule, $xoopsModuleConfig, $preview_name, $msgstop;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
140
        $created = time();
141
        $ext     = preg_replace("/^.+\.([^.]+)$/sU", "\\1", $_FILES['photo']['name']);
0 ignored issues
show
Unused Code introduced by
$ext 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...
142
        include_once XOOPS_ROOT_PATH . '/class/uploader.php';
143
        $field = $_POST['xoops_upload_file'][0];
144
        if (!empty($field) || $field !== '') {
145
            // Check if file uploaded
146
            if ($_FILES[$field]['tmp_name'] === '' || !is_readable($_FILES[$field]['tmp_name'])) {
147
                $msgstop .= sprintf(MD_XFGUESTBOOK_FILEERROR, $xoopsModuleConfig['photo_maxsize']);
148
            } else {
149
                $photos_dir              = XOOPS_UPLOAD_PATH . '/' . $xoopsModule->getVar('dirname');
150
                $array_allowed_mimetypes = ['image/gif', 'image/pjpeg', 'image/jpeg', 'image/x-png'];
151
                $uploader                = new XoopsMediaUploader($photos_dir, $array_allowed_mimetypes, $xoopsModuleConfig['photo_maxsize'], $xoopsModuleConfig['photo_maxwidth'],
152
                                                                  $xoopsModuleConfig['photo_maxheight']);
153
                if ($uploader->fetchMedia($field) && $uploader->upload()) {
154
                    if (isset($preview_name)) {
155
                        @unlink("$photos_dir/" . $preview_name);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
156
                    }
157
                    $tmp_name     = $uploader->getSavedFileName();
158
                    $ext          = preg_replace("/^.+\.([^.]+)$/sU", "\\1", $tmp_name);
159
                    $preview_name = 'tmp_' . $created . '.' . $ext;
160
                    rename("$photos_dir/$tmp_name", "$photos_dir/$preview_name");
161
                } else {
162
                    $msgstop .= $uploader->getErrors();
163
                }
164
            }
165
        }
166
    }
167
168
    /**
169
     * @param  null $criteria
170
     * @param  int  $limit
171
     * @param  int  $start
172
     * @return array
173
     */
174 View Code Duplication
    public static function getCountry($criteria = null, $limit = 0, $start = 0)
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...
175
    {
176
        global $xoopsDB, $action;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
177
        $ret = [];
178
        $sql = 'SELECT * FROM ' . $xoopsDB->prefix('xfguestbook_country');
179
        if (isset($criteria) && $criteria !== '') {
180
            $sql .= ' WHERE ' . $criteria;
181
        }
182
        $sql    .= ' ORDER BY country_code ASC';
183
        $result = $xoopsDB->query($sql, $limit, $start);
184
        while ($myrow = $xoopsDB->fetchArray($result)) {
185
            array_push($ret, $myrow);
186
        }
187
188
        return $ret;
189
    }
190
191
    /**
192
     * @param  null $criteria
193
     * @param  int  $limit
194
     * @param  int  $start
195
     * @return array
196
     */
197
    public static function getAllCountry($criteria = null, $limit = 0, $start = 0)
198
    {
199
        global $xoopsDB, $action, $xoopsModuleConfig;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
200
        $ret = [];
201
        $sql = 'SELECT country_code, country_name FROM ' . $xoopsDB->prefix('xfguestbook_country');
202
        if (isset($criteria) && $criteria !== '') {
203
            $sql .= ' WHERE ' . $criteria;
204
        }
205
        $sql    .= ' ORDER BY country_code ASC';
206
        $result = $xoopsDB->query($sql, $limit, $start);
207
        while ($myrow = $xoopsDB->fetchArray($result)) {
208
            //      $ret[$myrow['country_code']] = $myrow['country_name'];
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% 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...
209
            $ret[$xoopsModuleConfig['flagdir'] . '/' . $myrow['country_code']] = $myrow['country_name'];
210
        }
211
212
        return $ret;
213
    }
214
215
    /**
216
     * @param $user_id
217
     * @return bool
0 ignored issues
show
Documentation introduced by
Should the return type not be false|array?

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...
218
     */
219
    public static function get_user_data($user_id)
220
    {
221
        global $xoopsUser, $xoopsModuleConfig;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
222
223
        if (!(int)$user_id) {
224
            return false;
225
        }
226
227
        $poster = new XoopsUser($user_id);
228
        if ($poster->isActive()) {
229
            $xoopsUser ? $a_poster['poster'] = "<a href='../../userinfo.php?uid=$user_id'>" . $poster->uname() . '</a>' : $a_poster['poster'] = $poster->uname();
0 ignored issues
show
Coding Style Comprehensibility introduced by
$a_poster was never initialized. Although not strictly required by PHP, it is generally a good practice to add $a_poster = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
230
            if ($xoopsModuleConfig['display_avatar']) {
231
                $rank = $poster->rank();
232
                $rank['title'] ? $a_poster['rank'] = $rank['title'] : $a_poster['rank'] = '';
233
                $rank['image'] ? $a_poster['rank_img'] = "<img src='" . XOOPS_URL . '/uploads/' . $rank['image'] . '\' alt=\'\' />' : $a_poster['rank_img'] = '';
234
                $poster->user_avatar() ? $a_poster['avatar'] = "<img src='" . XOOPS_URL . '/uploads/' . $poster->user_avatar() . '\' alt=\'\' />' : $a_poster['avatar'] = '';
235
            } else {
236
                $a_poster['rank']     = '';
237
                $a_poster['avatar']   = '';
238
                $a_poster['rank_img'] = '';
239
            }
240
241
            return $a_poster;
242
        } else {
243
            return false;
244
        }
245
    }
246
247
    // Effacement fichiers temporaires
248
    /**
249
     * @param         $dir_path
250
     * @param  string $prefix
251
     * @return int
252
     */
253
    public static function clear_tmp_files($dir_path, $prefix = 'tmp_')
254
    {
255
        if (!($dir = @opendir($dir_path))) {
256
            return 0;
257
        }
258
        $ret        = 0;
259
        $prefix_len = strlen($prefix);
0 ignored issues
show
Unused Code introduced by
$prefix_len 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...
260
        while (($file = readdir($dir)) !== false) {
261
            //        if (strncmp($file, $prefix, $prefix_len) === 0) {
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...
262
            if (0 === strpos($file, $prefix)) {
263
                if (@unlink("$dir_path/$file")) {
264
                    $ret++;
265
                }
266
            }
267
        }
268
        closedir($dir);
269
270
        return $ret;
271
    }
272
273
    // IP bannies (modérés automatiquement)
274
    /**
275
     * @param  null $all
276
     * @return array
277
     */
278
    public static function get_badips($all = null)
279
    {
280
        global $xoopsDB;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
281
        $ret    = [];
282
        $sql    = 'SELECT * FROM ' . $xoopsDB->prefix('xfguestbook_badips');
283
        $result = $xoopsDB->query($sql);
284
        if ($all) {
285
            while ($myrow = $xoopsDB->fetchArray($result)) {
286
                array_push($ret, $myrow);
287
            }
288
        } else {
289
            while (list($ip_id, $ip_value) = $xoopsDB->fetchRow($result)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $ip_id is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
290
                $ret[] = $ip_value;
291
            }
292
        }
293
294
        return $ret;
295
    }
296
297
    /**
298
     * @param $email
299
     * @return bool
300
     */
301
    public static function email_exist($email)
302
    {
303
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
304
            return false;
305
        } elseif (!checkdnsrr(array_pop(explode('@', $email)), 'MX')) {
0 ignored issues
show
Bug introduced by
explode('@', $email) cannot be passed to array_pop() as the parameter $array expects a reference.
Loading history...
306
            return false;
307
        } else {
308
            return true;
309
        }
310
    }
311
312
}
313