Completed
Push — master ( 8ca430...3024c9 )
by Michael
03:12
created

XoopstubeUtilities   D

Complexity

Total Complexity 226

Size/Duplication

Total Lines 1835
Duplicated Lines 3.98 %

Coupling/Cohesion

Components 2
Dependencies 1

Importance

Changes 3
Bugs 0 Features 1
Metric Value
c 3
b 0
f 1
dl 73
loc 1835
rs 4
wmc 226
lcom 2
cbo 1

68 Methods

Rating   Name   Duplication   Size   Complexity  
A getInstance() 0 9 2
C getModuleOption() 0 29 11
A isX23() 10 10 2
A isX20() 10 10 2
A javascriptLinkConfirm() 0 8 2
C IP() 0 28 11
B setMetas() 0 20 9
C sendEmailFromTpl() 0 62 11
C updateCache() 0 26 7
A redirect() 0 5 1
B _getModule() 0 15 5
A getModuleName() 0 10 2
A makeHrefTitle() 0 7 1
A getUsersFromGroup() 0 8 1
A getEmailsFromGroup() 0 10 2
B isAdmin() 0 13 5
A getCurrentSQLDate() 0 4 1
A getCurrentSQLDateTime() 0 4 1
A SQLDateToHuman() 0 8 3
A timestampToMysqlDate() 0 4 1
A sqlDateTimeToFrench() 0 4 1
A timestampToMysqlDateTime() 0 4 1
B needsAsterisk() 0 17 5
B formMarkRequiredFields() 0 20 6
A htitle() 0 4 1
B createUploadName() 0 28 5
B unhtml() 0 263 2
B makeSeoUrl() 0 40 5
D createMetaKeywords() 0 67 13
C uploadFile() 0 41 8
C resizePicture() 0 30 7
A notify() 0 6 1
A addDaysToDate() 0 9 2
B breadcrumb() 0 21 5
B close_tags() 0 31 6
A truncate_tagsafe() 0 19 4
A makeInfotips() 0 11 2
A setCSS() 13 13 3
A setLocalCSS() 12 12 2
A getTTC() 0 10 2
A getVAT() 0 4 1
B getAmountWithVat() 0 22 5
A postIt() 0 17 3
A getMimeType() 0 16 3
A getThisMonthCriteria() 0 10 1
A getUsersFromIds() 0 16 4
A getCurrentUserID() 0 7 2
B getMemberGroups() 0 20 6
A isMemberOfGroup() 0 18 4
A prepareFolder() 0 8 2
A duplicateFile() 0 9 2
A loadLanguageFile() 0 13 3
A formatFloatForDB() 0 4 1
A callJavascriptFile() 0 19 3
B htmlSelectOptions() 0 21 5
A htmlSelect() 0 9 1
A getId() 9 9 2
A getName() 9 9 2
A doNotAcceptNegativeAmounts() 0 6 2
A getFromRequest() 0 4 2
A tableExists() 0 7 1
A fieldExists() 0 7 1
A getFieldDefinition() 0 10 2
A addField() 0 7 1
A packingHtmlSelect() 5 16 2
A deliveryHtmlSelect() 5 17 2
A paymentHtmlSelect() 0 11 1
A getCountriesList() 0 6 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 XoopstubeUtilities 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 XoopstubeUtilities, and based on these observations, apply Extract Interface, too.

1
<?php
2
/*
3
 You may not change or alter any portion of this comment or credits
4
 of supporting developers from this source code or any supporting source code
5
 which is considered copyrighted (c) material of the original comment or credit authors.
6
7
 This program is distributed in the hope that it will be useful,
8
 but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10
*/
11
12
/**
13
 * xoopstube
14
 *
15
 * @copyright   The XOOPS Project http://sourceforge.net/projects/xoops/
16
 * @license     http://www.fsf.org/copyleft/gpl.html GNU public license
17
 * @author      Hervé Thouzard (http://www.herve-thouzard.com/)
18
 * @version     $Id$
19
 */
20
21
/**
22
 * A set of useful and common functions
23
 *
24
 * @package       xoopstube
25
 * @author        Hervé Thouzard - Instant Zero (http://xoops.instant-zero.com)
26
 * @copyright (c) Instant Zero
27
 *
28
 * Note: You should be able to use it without the need to instantiate it.
29
 *
30
 */
31
// defined('XOOPS_ROOT_PATH') || die('XOOPS Root Path not defined');
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% 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...
32
33
/**
34
 * Class XoopstubeUtilities
35
 */
36
class XoopstubeUtilities
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...
37
{
38
39
    const MODULE_NAME = 'xoopstube';
40
41
    /**
42
     * Access the only instance of this class
43
     *
44
     * @return object
45
     *
46
     * @static
47
     * @staticvar   object
48
     */
49
    public function getInstance()
50
    {
51
        static $instance;
52
        if (!isset($instance)) {
53
            $instance = new oledrion_utils();
54
        }
55
56
        return $instance;
57
    }
58
59
    /**
60
     * Returns a module's option (with cache)
61
     *
62
     * @param string  $option    module option's name
63
     * @param boolean $withCache Do we have to use some cache ?
64
     *
65
     * @return mixed option's value
66
     */
67
    public static function getModuleOption($option, $withCache = true)
68
    {
69
        global $xoopsModuleConfig, $xoopsModule;
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...
70
        $repmodule = self::MODULE_NAME;
71
        static $options = array();
72
        if (is_array($options) && array_key_exists($option, $options) && $withCache) {
73
            return $options[$option];
74
        }
75
76
        $retval = false;
77
        if (isset($xoopsModuleConfig) && (is_object($xoopsModule) && $xoopsModule->getVar('dirname') == $repmodule && $xoopsModule->getVar('isactive'))) {
78
            if (isset($xoopsModuleConfig[$option])) {
79
                $retval = $xoopsModuleConfig[$option];
80
            }
81
        } else {
82
            $module_handler = xoops_gethandler('module');
83
            $module         = $module_handler->getByDirname($repmodule);
84
            $config_handler = xoops_gethandler('config');
85
            if ($module) {
86
                $moduleConfig = $config_handler->getConfigsByCat(0, $module->getVar('mid'));
87
                if (isset($moduleConfig[$option])) {
88
                    $retval = $moduleConfig[$option];
89
                }
90
            }
91
        }
92
        $options[$option] = $retval;
93
94
        return $retval;
95
    }
96
97
    /**
98
     * Is Xoops 2.3.x ?
99
     *
100
     * @return boolean
101
     */
102 View Code Duplication
    public function isX23()
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...
103
    {
104
        $x23 = false;
105
        $xv  = str_replace('XOOPS ', '', XOOPS_VERSION);
106
        if (intval(substr($xv, 2, 1)) >= 3) {
107
            $x23 = true;
108
        }
109
110
        return $x23;
111
    }
112
113
    /**
114
     * Is Xoops 2.0.x ?
115
     *
116
     * @return boolean
117
     */
118 View Code Duplication
    public static function isX20()
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...
119
    {
120
        $x20 = false;
121
        $xv  = str_replace('XOOPS ', '', XOOPS_VERSION);
122
        if (substr($xv, 2, 1) == '0') {
123
            $x20 = true;
124
        }
125
126
        return $x20;
127
    }
128
129
    /**
130
     * Create (in a link) a javascript confirmation's box
131
     *
132
     * @param string  $message Message to display
133
     * @param boolean $form    Is this a confirmation for a form ?
134
     *
135
     * @return string the javascript code to insert in the link (or in the form)
136
     */
137
    public static function javascriptLinkConfirm($message, $form = false)
138
    {
139
        if (!$form) {
140
            return "onclick=\"javascript:return confirm('" . str_replace("'", " ", $message) . "')\"";
141
        } else {
142
            return "onSubmit=\"javascript:return confirm('" . str_replace("'", " ", $message) . "')\"";
143
        }
144
    }
145
146
    /**
147
     * Get current user IP
148
     *
149
     * @return string IP address (format Ipv4)
150
     */
151
    public static function IP()
0 ignored issues
show
Coding Style introduced by
IP uses the super-global variable $_SERVER 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...
152
    {
153
        $proxy_ip = '';
154
        if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
155
            $proxy_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
156
        } elseif (!empty($_SERVER['HTTP_X_FORWARDED'])) {
157
            $proxy_ip = $_SERVER['HTTP_X_FORWARDED'];
158
        } elseif (!empty($_SERVER['HTTP_FORWARDED_FOR'])) {
159
            $proxy_ip = $_SERVER['HTTP_FORWARDED_FOR'];
160
        } elseif (!empty($_SERVER['HTTP_FORWARDED'])) {
161
            $proxy_ip = $_SERVER['HTTP_FORWARDED'];
162
        } elseif (!empty($_SERVER['HTTP_VIA'])) {
163
            $proxy_ip = $_SERVER['HTTP_VIA'];
164
        } elseif (!empty($_SERVER['HTTP_X_COMING_FROM'])) {
165
            $proxy_ip = $_SERVER['HTTP_X_COMING_FROM'];
166
        } elseif (!empty($_SERVER['HTTP_COMING_FROM'])) {
167
            $proxy_ip = $_SERVER['HTTP_COMING_FROM'];
168
        }
169
        $regs = array();
170
        //if (!empty($proxy_ip) && $is_ip = ereg('^([0-9]{1,3}\.){3,3}[0-9]{1,3}', $proxy_ip, $regs) && count($regs) > 0) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% 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...
171
        if (!empty($proxy_ip) && filter_var($proxy_ip, FILTER_VALIDATE_IP) && count($regs) > 0) {
172
            $the_IP = $regs[0];
173
        } else {
174
            $the_IP = $_SERVER['REMOTE_ADDR'];
175
        }
176
177
        return $the_IP;
178
    }
179
180
    /**
181
     * Set the page's title, meta description and meta keywords
182
     * Datas are supposed to be sanitized
183
     *
184
     * @param string $pageTitle       Page's Title
185
     * @param string $metaDescription Page's meta description
186
     * @param string $metaKeywords    Page's meta keywords
187
     *
188
     * @return void
189
     */
190
    public static function setMetas($pageTitle = '', $metaDescription = '', $metaKeywords = '')
191
    {
192
        global $xoTheme, $xoTheme, $xoopsTpl;
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...
193
        $xoopsTpl->assign('xoops_pagetitle', $pageTitle);
194
        if (isset($xoTheme) && is_object($xoTheme)) {
195
            if (!empty($metaKeywords)) {
196
                $xoTheme->addMeta('meta', 'keywords', $metaKeywords);
197
            }
198
            if (!empty($metaDescription)) {
199
                $xoTheme->addMeta('meta', 'description', $metaDescription);
200
            }
201
        } elseif (isset($xoopsTpl) && is_object($xoopsTpl)) { // Compatibility for old Xoops versions
202
            if (!empty($metaKeywords)) {
203
                $xoopsTpl->assign('xoops_meta_keywords', $metaKeywords);
204
            }
205
            if (!empty($metaDescription)) {
206
                $xoopsTpl->assign('xoops_meta_description', $metaDescription);
207
            }
208
        }
209
    }
210
211
    /**
212
     * Send an email from a template to a list of recipients
213
     *
214
     * @param        $tplName
215
     * @param array  $recipients List of recipients
216
     * @param string $subject    Email's subject
217
     * @param array  $variables  Varirables to give to the template
218
     *
219
     * @internal param string $tpl_name Template's name
220
     * @return boolean Result of the send
221
     */
222
    public static function sendEmailFromTpl($tplName, $recipients, $subject, $variables)
223
    {
224
        global $xoopsConfig;
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...
225
        require_once XOOPS_ROOT_PATH . '/class/xoopsmailer.php';
226
        if (!is_array($recipients)) {
227
            if (trim($recipients) == '') {
228
                return false;
229
            }
230
        } else {
231
            if (count($recipients) == 0) {
232
                return false;
233
            }
234
        }
235
        if (function_exists('xoops_getMailer')) {
236
            $xoopsMailer = xoops_getMailer();
237
        } else {
238
            $xoopsMailer = getMailer();
239
        }
240
241
        $xoopsMailer->useMail();
242
        $templateDir = XOOPS_ROOT_PATH . '/modules/' . self::MODULE_NAME . '/language/' . $xoopsConfig['language'] . '/mail_template';
243
        if (!is_dir($templateDir)) {
244
            $templateDir = XOOPS_ROOT_PATH . '/modules/' . self::MODULE_NAME . '/language/english/mail_template';
245
        }
246
        $xoopsMailer->setTemplateDir($templateDir);
247
        $xoopsMailer->setTemplate($tplName);
248
        $xoopsMailer->setToEmails($recipients);
249
        // TODO: Change !
250
        // $xoopsMailer->setFromEmail('[email protected]');
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...
251
        //$xoopsMailer->setFromName('MonSite');
0 ignored issues
show
Unused Code Comprehensibility introduced by
86% 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...
252
        $xoopsMailer->setSubject($subject);
253
        foreach ($variables as $key => $value) {
254
            $xoopsMailer->assign($key, $value);
255
        }
256
        $res = $xoopsMailer->send();
257
        unset($xoopsMailer);
258
        $filename = XOOPS_UPLOAD_PATH . '/logmail_' . self::MODULE_NAME . '.php';
259
        if (!file_exists($filename)) {
260
            $fp = @fopen($filename, 'a');
261
            if ($fp) {
262
                fwrite($fp, "<?php exit(); ?>\n");
263
                fclose($fp);
264
            }
265
        }
266
        $fp = @fopen($filename, 'a');
267
268
        if ($fp) {
269
            fwrite($fp, str_repeat('-', 120) . "\n");
270
            fwrite($fp, date('d/m/Y H:i:s') . "\n");
271
            fwrite($fp, "Template name : " . $tplName . "\n");
272
            fwrite($fp, "Email subject : " . $subject . "\n");
273
            if (is_array($recipients)) {
274
                fwrite($fp, "Recipient(s) : " . implode(',', $recipients) . "\n");
275
            } else {
276
                fwrite($fp, "Recipient(s) : " . $recipients . "\n");
277
            }
278
            fwrite($fp, "Transmited variables : " . implode(',', $variables) . "\n");
279
            fclose($fp);
280
        }
281
282
        return $res;
283
    }
284
285
    /**
286
     * Remove module's cache
287
     */
288
    public static function updateCache()
289
    {
290
        global $xoopsModule;
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...
291
        $folder  = $xoopsModule->getVar('dirname');
292
        $tpllist = array();
0 ignored issues
show
Unused Code introduced by
$tpllist 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...
293
        require_once XOOPS_ROOT_PATH . '/class/xoopsblock.php';
294
        require_once XOOPS_ROOT_PATH . '/class/template.php';
295
        $tplfile_handler = xoops_gethandler('tplfile');
296
        $tpllist         = $tplfile_handler->find(null, null, null, $folder);
297
        xoops_template_clear_module_cache($xoopsModule->getVar('mid')); // Clear module's blocks cache
298
299
        foreach ($tpllist as $onetemplate) { // Remove cache for each page.
300
            if ($onetemplate->getVar('tpl_type') == 'module') {
301
                //	Note, I've been testing all the other methods (like the one of Smarty) and none of them run, that's why I have used this code
302
                $files_del = array();
0 ignored issues
show
Unused Code introduced by
$files_del 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...
303
                $files_del = glob(XOOPS_CACHE_PATH . '/*' . $onetemplate->getVar('tpl_file') . '*');
304
                if (count($files_del) > 0 && is_array($files_del)) {
305
                    foreach ($files_del as $one_file) {
306
                        if (is_file($one_file)) {
307
                            unlink($one_file);
308
                        }
309
                    }
310
                }
311
            }
312
        }
313
    }
314
315
    /**
316
     * Redirect user with a message
317
     *
318
     * @param string $message message to display
319
     * @param string $url     The place where to go
320
     * @param        integer  timeout Time to wait before to redirect
321
     */
322
    public static function redirect($message = '', $url = 'index.php', $time = 2)
323
    {
324
        redirect_header($url, $time, $message);
325
        exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method redirect() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
326
    }
327
328
    /**
329
     * Internal function used to get the handler of the current module
330
     *
331
     * @return object The module
332
     */
333
    protected function _getModule()
334
    {
335
        static $mymodule;
336
        if (!isset($mymodule)) {
337
            global $xoopsModule;
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...
338
            if (isset($xoopsModule) && is_object($xoopsModule) && $xoopsModule->getVar('dirname') == OLEDRION_DIRNAME) {
339
                $mymodule = $xoopsModule;
340
            } else {
341
                $hModule  = xoops_gethandler('module');
342
                $mymodule = $hModule->getByDirname(OLEDRION_DIRNAME);
343
            }
344
        }
345
346
        return $mymodule;
347
    }
348
349
    /**
350
     * Returns the module's name (as defined by the user in the module manager) with cache
351
     *
352
     * @return string Module's name
353
     */
354
    public static function getModuleName()
355
    {
356
        static $moduleName;
357
        if (!isset($moduleName)) {
358
            $mymodule   = self::_getModule();
359
            $moduleName = $mymodule->getVar('name');
360
        }
361
362
        return $moduleName;
363
    }
364
365
    /**
366
     * Create a title for the href tags inside html links
367
     *
368
     * @param string $title Text to use
369
     *
370
     * @return string Formated text
371
     */
372
    public static function makeHrefTitle($title)
373
    {
374
        $s = "\"'";
375
        $r = '  ';
376
377
        return strtr($title, $s, $r);
378
    }
379
380
    /**
381
     * Retourne la liste des utilisateurs appartenants à un groupe
382
     *
383
     * @param int $groupId Searched group
384
     *
385
     * @return array Array of XoopsUsers
386
     */
387
    public function getUsersFromGroup($groupId)
388
    {
389
        $users          = array();
0 ignored issues
show
Unused Code introduced by
$users 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...
390
        $member_handler = xoops_gethandler('member');
391
        $users          = $member_handler->getUsersByGroup($groupId, true);
392
393
        return $users;
394
    }
395
396
    /**
397
     * Retourne la liste des emails des utilisateurs membres d'un groupe
398
     *
399
     * @param $groupId
400
     *
401
     * @internal param int $group_id Group's number
402
     * @return array Emails list
403
     */
404
    public static function getEmailsFromGroup($groupId)
405
    {
406
        $ret   = array();
407
        $users = self::getUsersFromGroup($groupId);
408
        foreach ($users as $user) {
409
            $ret[] = $user->getVar('email');
410
        }
411
412
        return $ret;
413
    }
414
415
    /**
416
     * Vérifie que l'utilisateur courant fait partie du groupe des administrateurs
417
     *
418
     * @return booleean Admin or not
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...
419
     */
420
    public static function isAdmin()
421
    {
422
        global $xoopsUser, $xoopsModule;
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...
423
        if (is_object($xoopsUser)) {
424
            if (in_array(XOOPS_GROUP_ADMIN, $xoopsUser->getGroups())) {
425
                return true;
426
            } elseif (isset($xoopsModule) && $xoopsUser->isAdmin($xoopsModule->getVar('mid'))) {
427
                return true;
428
            }
429
        }
430
431
        return false;
432
    }
433
434
    /**
435
     * Returns the current date in the Mysql format
436
     *
437
     * @return string Date in the Mysql format
438
     */
439
    public static function getCurrentSQLDate()
440
    {
441
        return date('Y-m-d'); // 2007-05-02
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...
442
    }
443
444
    /**
445
     * @return bool|string
446
     */
447
    public function getCurrentSQLDateTime()
448
    {
449
        return date('Y-m-d H:i:s'); // 2007-05-02
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...
450
    }
451
452
    /**
453
     * Convert a Mysql date to the human's format
454
     *
455
     * @param string $date   The date to convert
456
     * @param string $format
457
     *
458
     * @return string The date in a human form
459
     */
460
    public function SQLDateToHuman($date, $format = 'l')
461
    {
462
        if ($date != '0000-00-00' && xoops_trim($date) != '') {
463
            return formatTimestamp(strtotime($date), $format);
464
        } else {
465
            return '';
466
        }
467
    }
468
469
    /**
470
     * Convert a timestamp to a Mysql date
471
     *
472
     * @param integer $timestamp The timestamp to use
473
     *
474
     * @return string The date in the Mysql format
475
     */
476
    public function timestampToMysqlDate($timestamp)
477
    {
478
        return date('Y-m-d', intval($timestamp));
479
    }
480
481
    /**
482
     * Conversion d'un dateTime Mysql en date lisible en français
483
     *
484
     * @param $dateTime
485
     *
486
     * @return bool|string
487
     */
488
    public function sqlDateTimeToFrench($dateTime)
489
    {
490
        return date('d/m/Y H:i:s', strtotime($dateTime));
491
    }
492
493
    /**
494
     * Convert a timestamp to a Mysql datetime form
495
     *
496
     * @param integer $timestamp The timestamp to use
497
     *
498
     * @return string The date and time in the Mysql format
499
     */
500
    public function timestampToMysqlDateTime($timestamp)
501
    {
502
        return date('Y-m-d H:i:s', $timestamp);
503
    }
504
505
    /**
506
     * This function indicates if the current Xoops version needs to add asterisks to required fields in forms
507
     *
508
     * @return boolean Yes = we need to add them, false = no
509
     */
510
    public function needsAsterisk()
511
    {
512
        if (self::isX23()) {
513
            return false;
514
        }
515
        if (strpos(strtolower(XOOPS_VERSION), 'impresscms') !== false) {
516
            return false;
517
        }
518
        if (strpos(strtolower(XOOPS_VERSION), 'legacy') === false) {
519
            $xv = xoops_trim(str_replace('XOOPS ', '', XOOPS_VERSION));
520
            if (intval(substr($xv, 4, 2)) >= 17) {
521
                return false;
522
            }
523
        }
524
525
        return true;
526
    }
527
528
    /**
529
     * Mark the mandatory fields of a form with a star
530
     *
531
     * @param object $sform The form to modify
532
     *
533
     * @internal param string $caracter The character to use to mark fields
534
     * @return object The modified form
535
     */
536
    public static function &formMarkRequiredFields(&$sform)
537
    {
538
        if (self::needsAsterisk()) {
539
            $required = array();
540
            foreach ($sform->getRequired() as $item) {
541
                $required[] = $item->_name;
542
            }
543
            $elements = array();
0 ignored issues
show
Unused Code introduced by
$elements 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...
544
            $elements = $sform->getElements();
545
            $cnt      = count($elements);
546
            for ($i = 0; $i < $cnt; ++$i) {
547
                if (is_object($elements[$i]) && in_array($elements[$i]->_name, $required)
548
                ) {
549
                    $elements[$i]->_caption .= ' *';
550
                }
551
            }
552
        }
553
554
        return $sform;
555
    }
556
557
    /**
558
     * Create an html heading (from h1 to h6)
559
     *
560
     * @param string  $title The text to use
561
     * @param integer $level Level to return
562
     *
563
     * @return string The heading
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

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...
564
     */
565
    public static function htitle($title = '', $level = 1)
566
    {
567
        printf("<h%01d>%s</h%01d>", $level, $title, $level);
568
    }
569
570
    /**
571
     * Create a unique upload filename
572
     *
573
     * @param string  $folder   The folder where the file will be saved
574
     * @param string  $fileName Original filename (coming from the user)
575
     * @param boolean $trimName Do we need to create a "short" unique name ?
576
     *
577
     * @return string The unique filename to use (with its extension)
578
     */
579
    public function createUploadName($folder, $fileName, $trimName = false)
0 ignored issues
show
Coding Style introduced by
createUploadName uses the super-global variable $_SERVER 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...
580
    {
581
        $workingfolder = $folder;
582
        if (xoops_substr($workingfolder, strlen($workingfolder) - 1, 1) != '/') {
583
            $workingfolder .= '/';
584
        }
585
        $ext  = basename($fileName);
586
        $ext  = explode('.', $ext);
587
        $ext  = '.' . $ext[count($ext) - 1];
588
        $true = true;
589
        while ($true) {
590
            $ipbits = explode('.', $_SERVER['REMOTE_ADDR']);
591
            list($usec, $sec) = explode(' ', microtime());
592
            $usec = (integer)($usec * 65536);
593
            $sec  = ((integer)$sec) & 0xFFFF;
594
595
            if ($trimName) {
596
                $uid = sprintf("%06x%04x%04x", ($ipbits[0] << 24) | ($ipbits[1] << 16) | ($ipbits[2] << 8) | $ipbits[3], $sec, $usec);
597
            } else {
598
                $uid = sprintf("%08x-%04x-%04x", ($ipbits[0] << 24) | ($ipbits[1] << 16) | ($ipbits[2] << 8) | $ipbits[3], $sec, $usec);
599
            }
600
            if (!file_exists($workingfolder . $uid . $ext)) {
601
                $true = false;
602
            }
603
        }
604
605
        return $uid . $ext;
0 ignored issues
show
Bug introduced by
The variable $uid does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
606
    }
607
608
    /**
609
     * Replace html entities with their ASCII equivalent
610
     *
611
     * @param string $chaine The string undecode
612
     *
613
     * @return string The undecoded string
614
     */
615
    public function unhtml($chaine)
616
    {
617
        $search = $replace = array();
618
        $chaine = html_entity_decode($chaine);
619
620
        for ($i = 0; $i <= 255; ++$i) {
621
            $search[]  = '&#' . $i . ';';
622
            $replace[] = chr($i);
623
        }
624
        $replace[] = '...';
625
        $search[]  = '…';
626
        $replace[] = "'";
627
        $search[]  = '‘';
628
        $replace[] = "'";
629
        $search[]  = "’";
630
        $replace[] = '-';
631
        $search[]  = "&bull;"; // $replace[] = '•';
0 ignored issues
show
Unused Code Comprehensibility introduced by
56% 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...
632
        $replace[] = '—';
633
        $search[]  = '&mdash;';
634
        $replace[] = '-';
635
        $search[]  = '&ndash;';
636
        $replace[] = '-';
637
        $search[]  = '&shy;';
638
        $replace[] = '"';
639
        $search[]  = '&quot;';
640
        $replace[] = '&';
641
        $search[]  = '&amp;';
642
        $replace[] = 'ˆ';
643
        $search[]  = '&circ;';
644
        $replace[] = '¡';
645
        $search[]  = '&iexcl;';
646
        $replace[] = '¦';
647
        $search[]  = '&brvbar;';
648
        $replace[] = '¨';
649
        $search[]  = '&uml;';
650
        $replace[] = '¯';
651
        $search[]  = '&macr;';
652
        $replace[] = '´';
653
        $search[]  = '&acute;';
654
        $replace[] = '¸';
655
        $search[]  = '&cedil;';
656
        $replace[] = '¿';
657
        $search[]  = '&iquest;';
658
        $replace[] = '˜';
659
        $search[]  = '&tilde;';
660
        $replace[] = "'";
661
        $search[]  = '&lsquo;'; // $replace[]='‘';
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% 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...
662
        $replace[] = "'";
663
        $search[]  = '&rsquo;'; // $replace[]='’';
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% 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...
664
        $replace[] = '‚';
665
        $search[]  = '&sbquo;';
666
        $replace[] = "'";
667
        $search[]  = '&ldquo;'; // $replace[]='“';
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% 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...
668
        $replace[] = "'";
669
        $search[]  = '&rdquo;'; // $replace[]='”';
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% 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...
670
        $replace[] = '„';
671
        $search[]  = '&bdquo;';
672
        $replace[] = '‹';
673
        $search[]  = '&lsaquo;';
674
        $replace[] = '›';
675
        $search[]  = '&rsaquo;';
676
        $replace[] = '<';
677
        $search[]  = '&lt;';
678
        $replace[] = '>';
679
        $search[]  = '&gt;';
680
        $replace[] = '±';
681
        $search[]  = '&plusmn;';
682
        $replace[] = '«';
683
        $search[]  = '&laquo;';
684
        $replace[] = '»';
685
        $search[]  = '&raquo;';
686
        $replace[] = '×';
687
        $search[]  = '&times;';
688
        $replace[] = '÷';
689
        $search[]  = '&divide;';
690
        $replace[] = '¢';
691
        $search[]  = '&cent;';
692
        $replace[] = '£';
693
        $search[]  = '&pound;';
694
        $replace[] = '¤';
695
        $search[]  = '&curren;';
696
        $replace[] = '¥';
697
        $search[]  = '&yen;';
698
        $replace[] = '§';
699
        $search[]  = '&sect;';
700
        $replace[] = '©';
701
        $search[]  = '&copy;';
702
        $replace[] = '¬';
703
        $search[]  = '&not;';
704
        $replace[] = '®';
705
        $search[]  = '&reg;';
706
        $replace[] = '°';
707
        $search[]  = '&deg;';
708
        $replace[] = 'µ';
709
        $search[]  = '&micro;';
710
        $replace[] = '¶';
711
        $search[]  = '&para;';
712
        $replace[] = '·';
713
        $search[]  = '&middot;';
714
        $replace[] = '†';
715
        $search[]  = '&dagger;';
716
        $replace[] = '‡';
717
        $search[]  = '&Dagger;';
718
        $replace[] = '‰';
719
        $search[]  = '&permil;';
720
        $replace[] = 'Euro';
721
        $search[]  = '&euro;'; // $replace[]='€'
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...
722
        $replace[] = '¼';
723
        $search[]  = '&frac14;';
724
        $replace[] = '½';
725
        $search[]  = '&frac12;';
726
        $replace[] = '¾';
727
        $search[]  = '&frac34;';
728
        $replace[] = '¹';
729
        $search[]  = '&sup1;';
730
        $replace[] = '²';
731
        $search[]  = '&sup2;';
732
        $replace[] = '³';
733
        $search[]  = '&sup3;';
734
        $replace[] = 'á';
735
        $search[]  = '&aacute;';
736
        $replace[] = 'Á';
737
        $search[]  = '&Aacute;';
738
        $replace[] = 'â';
739
        $search[]  = '&acirc;';
740
        $replace[] = 'Â';
741
        $search[]  = '&Acirc;';
742
        $replace[] = 'à';
743
        $search[]  = '&agrave;';
744
        $replace[] = 'À';
745
        $search[]  = '&Agrave;';
746
        $replace[] = 'å';
747
        $search[]  = '&aring;';
748
        $replace[] = 'Å';
749
        $search[]  = '&Aring;';
750
        $replace[] = 'ã';
751
        $search[]  = '&atilde;';
752
        $replace[] = 'Ã';
753
        $search[]  = '&Atilde;';
754
        $replace[] = 'ä';
755
        $search[]  = '&auml;';
756
        $replace[] = 'Ä';
757
        $search[]  = '&Auml;';
758
        $replace[] = 'ª';
759
        $search[]  = '&ordf;';
760
        $replace[] = 'æ';
761
        $search[]  = '&aelig;';
762
        $replace[] = 'Æ';
763
        $search[]  = '&AElig;';
764
        $replace[] = 'ç';
765
        $search[]  = '&ccedil;';
766
        $replace[] = 'Ç';
767
        $search[]  = '&Ccedil;';
768
        $replace[] = 'ð';
769
        $search[]  = '&eth;';
770
        $replace[] = 'Ð';
771
        $search[]  = '&ETH;';
772
        $replace[] = 'é';
773
        $search[]  = '&eacute;';
774
        $replace[] = 'É';
775
        $search[]  = '&Eacute;';
776
        $replace[] = 'ê';
777
        $search[]  = '&ecirc;';
778
        $replace[] = 'Ê';
779
        $search[]  = '&Ecirc;';
780
        $replace[] = 'è';
781
        $search[]  = '&egrave;';
782
        $replace[] = 'È';
783
        $search[]  = '&Egrave;';
784
        $replace[] = 'ë';
785
        $search[]  = '&euml;';
786
        $replace[] = 'Ë';
787
        $search[]  = '&Euml;';
788
        $replace[] = 'ƒ';
789
        $search[]  = '&fnof;';
790
        $replace[] = 'í';
791
        $search[]  = '&iacute;';
792
        $replace[] = 'Í';
793
        $search[]  = '&Iacute;';
794
        $replace[] = 'î';
795
        $search[]  = '&icirc;';
796
        $replace[] = 'Î';
797
        $search[]  = '&Icirc;';
798
        $replace[] = 'ì';
799
        $search[]  = '&igrave;';
800
        $replace[] = 'Ì';
801
        $search[]  = '&Igrave;';
802
        $replace[] = 'ï';
803
        $search[]  = '&iuml;';
804
        $replace[] = 'Ï';
805
        $search[]  = '&Iuml;';
806
        $replace[] = 'ñ';
807
        $search[]  = '&ntilde;';
808
        $replace[] = 'Ñ';
809
        $search[]  = '&Ntilde;';
810
        $replace[] = 'ó';
811
        $search[]  = '&oacute;';
812
        $replace[] = 'Ó';
813
        $search[]  = '&Oacute;';
814
        $replace[] = 'ô';
815
        $search[]  = '&ocirc;';
816
        $replace[] = 'Ô';
817
        $search[]  = '&Ocirc;';
818
        $replace[] = 'ò';
819
        $search[]  = '&ograve;';
820
        $replace[] = 'Ò';
821
        $search[]  = '&Ograve;';
822
        $replace[] = 'º';
823
        $search[]  = '&ordm;';
824
        $replace[] = 'ø';
825
        $search[]  = '&oslash;';
826
        $replace[] = 'Ø';
827
        $search[]  = '&Oslash;';
828
        $replace[] = 'õ';
829
        $search[]  = '&otilde;';
830
        $replace[] = 'Õ';
831
        $search[]  = '&Otilde;';
832
        $replace[] = 'ö';
833
        $search[]  = '&ouml;';
834
        $replace[] = 'Ö';
835
        $search[]  = '&Ouml;';
836
        $replace[] = 'œ';
837
        $search[]  = '&oelig;';
838
        $replace[] = 'Œ';
839
        $search[]  = '&OElig;';
840
        $replace[] = 'š';
841
        $search[]  = '&scaron;';
842
        $replace[] = 'Š';
843
        $search[]  = '&Scaron;';
844
        $replace[] = 'ß';
845
        $search[]  = '&szlig;';
846
        $replace[] = 'þ';
847
        $search[]  = '&thorn;';
848
        $replace[] = 'Þ';
849
        $search[]  = '&THORN;';
850
        $replace[] = 'ú';
851
        $search[]  = '&uacute;';
852
        $replace[] = 'Ú';
853
        $search[]  = '&Uacute;';
854
        $replace[] = 'û';
855
        $search[]  = '&ucirc;';
856
        $replace[] = 'Û';
857
        $search[]  = '&Ucirc;';
858
        $replace[] = 'ù';
859
        $search[]  = '&ugrave;';
860
        $replace[] = 'Ù';
861
        $search[]  = '&Ugrave;';
862
        $replace[] = 'ü';
863
        $search[]  = '&uuml;';
864
        $replace[] = 'Ü';
865
        $search[]  = '&Uuml;';
866
        $replace[] = 'ý';
867
        $search[]  = '&yacute;';
868
        $replace[] = 'Ý';
869
        $search[]  = '&Yacute;';
870
        $replace[] = 'ÿ';
871
        $search[]  = '&yuml;';
872
        $replace[] = 'Ÿ';
873
        $search[]  = '&Yuml;';
874
        $chaine    = str_replace($search, $replace, $chaine);
875
876
        return $chaine;
877
    }
878
879
    /**
880
     * Création d'une titre pour être utilisé par l'url rewriting
881
     *
882
     * @param string  $content Le texte à utiliser pour créer l'url
883
     * @param integer $urw     La limite basse pour créer les mots
884
     *
885
     * @return string Le texte à utiliser pour l'url
886
     *                Note, some parts are from Solo's code
887
     */
888
    public static function makeSeoUrl($content, $urw = 1)
889
    {
890
        $s       = "ÀÁÂÃÄÅÒÓÔÕÖØÈÉÊËÇÌÍÎÏÙÚÛܟÑàáâãäåòóôõöøèéêëçìíîïùúûüÿñ '()";
891
        $r       = "AAAAAAOOOOOOEEEECIIIIUUUUYNaaaaaaooooooeeeeciiiiuuuuyn----";
892
        $content = self::unhtml($content); // First, remove html entities
893
        $content = strtr($content, $s, $r);
894
        $content = strip_tags($content);
895
        $content = strtolower($content);
896
        $content = htmlentities($content); // TODO: Vérifier
897
        $content = preg_replace('/&([a-zA-Z])(uml|acute|grave|circ|tilde);/', '$1', $content);
898
        $content = html_entity_decode($content);
899
        $content = preg_replace('/quot/i', ' ', $content);
900
        $content = preg_replace("/'/i", ' ', $content);
901
        $content = preg_replace('/-/i', ' ', $content);
902
        $content = preg_replace('/[[:punct:]]/i', '', $content);
903
904
        // Selon option mais attention au fichier .htaccess !
905
        // $content = eregi_replace('[[:digit:]]','', $content);
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% 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...
906
        $content = preg_replace("/[^a-z|A-Z|0-9]/", '-', $content);
907
908
        $words    = explode(' ', $content);
909
        $keywords = '';
910
        foreach ($words as $word) {
911
            if (strlen($word) >= $urw) {
912
                $keywords .= '-' . trim($word);
913
            }
914
        }
915
        if (!$keywords) {
916
            $keywords = '-';
917
        }
918
        // Supprime les tirets en double
919
        $keywords = str_replace('---', '-', $keywords);
920
        $keywords = str_replace('--', '-', $keywords);
921
        // Supprime un éventuel tiret à la fin de la chaine
922
        if (substr($keywords, strlen($keywords) - 1, 1) == '-') {
923
            $keywords = substr($keywords, 0, strlen($keywords) - 1);
924
        }
925
926
        return $keywords;
927
    }
928
929
    /**
930
     * Create the meta keywords based on the content
931
     *
932
     * @param string $content Content from which we have to create metakeywords
933
     *
934
     * @return string The list of meta keywords
935
     */
936
    public static function createMetaKeywords($content)
0 ignored issues
show
Coding Style introduced by
createMetaKeywords uses the super-global variable $_SESSION 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...
937
    {
938
        $keywordscount = self::getModuleOption('metagen_maxwords');
939
        $keywordsorder = self::getModuleOption('metagen_order');
940
941
        $tmp = array();
942
        // Search for the "Minimum keyword length"
943
        if (isset($_SESSION['oledrion_keywords_limit'])) {
944
            $limit = $_SESSION['oledrion_keywords_limit'];
945
        } else {
946
            $config_handler                      = xoops_gethandler('config');
947
            $xoopsConfigSearch                   = $config_handler->getConfigsByCat(XOOPS_CONF_SEARCH);
948
            $limit                               = $xoopsConfigSearch['keyword_min'];
949
            $_SESSION['oledrion_keywords_limit'] = $limit;
950
        }
951
        $myts            = MyTextSanitizer::getInstance();
952
        $content         = str_replace("<br />", " ", $content);
953
        $content         = $myts->undoHtmlSpecialChars($content);
954
        $content         = strip_tags($content);
955
        $content         = strtolower($content);
956
        $search_pattern  = array("&nbsp;", "\t", "\r\n", "\r", "\n", ",", ".", "'", ";", ":", ")", "(", '"', '?', '!', '{', '}', '[', ']', '<', '>', '/', '+', '-', '_', '\\', '*');
957
        $replace_pattern = array(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '');
958
        $content         = str_replace($search_pattern, $replace_pattern, $content);
959
        $keywords        = explode(' ', $content);
960
        switch ($keywordsorder) {
961
            case 0: // Ordre d'apparition dans le texte
962
                $keywords = array_unique($keywords);
963
                break;
964
            case 1: // Ordre de fréquence des mots
965
                $keywords = array_count_values($keywords);
966
                asort($keywords);
967
                $keywords = array_keys($keywords);
968
                break;
969
            case 2: // Ordre inverse de la fréquence des mots
970
                $keywords = array_count_values($keywords);
971
                arsort($keywords);
972
                $keywords = array_keys($keywords);
973
                break;
974
        }
975
        // Remove black listed words
976
        if (xoops_trim(self::getModuleOption('metagen_blacklist')) != '') {
977
            $metagen_blacklist = str_replace("\r", '', self::getModuleOption('metagen_blacklist'));
978
            $metablack         = explode("\n", $metagen_blacklist);
979
            array_walk($metablack, 'trim');
980
            $keywords = array_diff($keywords, $metablack);
981
        }
982
983
        foreach ($keywords as $keyword) {
984
            if (strlen($keyword) >= $limit && !is_numeric($keyword)) {
985
                $tmp[] = $keyword;
986
            }
987
        }
988
        $tmp = array_slice($tmp, 0, $keywordscount);
989
        if (count($tmp) > 0) {
990
            return implode(',', $tmp);
991
        } else {
992
            if (!isset($config_handler) || !is_object($config_handler)) {
993
                $config_handler = xoops_gethandler('config');
994
            }
995
            $xoopsConfigMetaFooter = $config_handler->getConfigsByCat(XOOPS_CONF_METAFOOTER);
996
            if (isset($xoopsConfigMetaFooter['meta_keywords'])) {
997
                return $xoopsConfigMetaFooter['meta_keywords'];
998
            } else {
999
                return '';
1000
            }
1001
        }
1002
    }
1003
1004
    /**
1005
     * Fonction chargée de gérer l'upload
1006
     *
1007
     * @param integer $indice        L'indice du fichier à télécharger
1008
     * @param string  $dstpath
1009
     * @param null    $mimeTypes
1010
     * @param null    $uploadMaxSize
1011
     * @param null    $maxWidth
1012
     * @param null    $maxHeight
1013
     *
1014
     * @return mixed True si l'upload s'est bien déroulé sinon le message d'erreur correspondant
1015
     */
1016
    public static function uploadFile($indice, $dstpath = XOOPS_UPLOAD_PATH, $mimeTypes = null, $uploadMaxSize = null, $maxWidth = null, $maxHeight = null)
0 ignored issues
show
Coding Style introduced by
uploadFile 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...
Coding Style introduced by
uploadFile 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...
1017
    {
1018
        require_once XOOPS_ROOT_PATH . '/class/uploader.php';
1019
        global $destname;
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...
1020
        if (isset($_POST['xoops_upload_file'])) {
1021
            require_once XOOPS_ROOT_PATH . '/class/uploader.php';
1022
            $fldname = '';
0 ignored issues
show
Unused Code introduced by
$fldname 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...
1023
            $fldname = $_FILES[$_POST['xoops_upload_file'][$indice]];
1024
            $fldname = (get_magic_quotes_gpc()) ? stripslashes($fldname['name']) : $fldname['name'];
1025
            if (xoops_trim($fldname != '')) {
1026
                $destname = self::createUploadName($dstpath, $fldname, true);
1027
                if ($mimeTypes === null) {
1028
                    $permittedtypes = explode("\n", str_replace("\r", '', self::getModuleOption('mimetypes')));
1029
                    array_walk($permittedtypes, 'trim');
1030
                } else {
1031
                    $permittedtypes = $mimeTypes;
1032
                }
1033
                if ($uploadMaxSize === null) {
1034
                    $uploadSize = self::getModuleOption('maxuploadsize');
1035
                } else {
1036
                    $uploadSize = $uploadMaxSize;
1037
                }
1038
                $uploader = new XoopsMediaUploader($dstpath, $permittedtypes, $uploadSize, $maxWidth, $maxHeight);
0 ignored issues
show
Documentation introduced by
$permittedtypes is of type array|null, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1039
                //$uploader->allowUnknownTypes = true;
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...
1040
                $uploader->setTargetFileName($destname);
1041
                if ($uploader->fetchMedia($_POST['xoops_upload_file'][$indice])) {
1042
                    if ($uploader->upload()) {
1043
                        return true;
1044
                    } else {
1045
                        return _ERRORS . ' ' . htmlentities($uploader->getErrors());
1046
                    }
1047
                } else {
1048
                    return htmlentities($uploader->getErrors());
1049
                }
1050
            } else {
1051
                return false;
1052
            }
1053
        } else {
1054
            return false;
1055
        }
1056
    }
1057
1058
    /**
1059
     * Resize a Picture to some given dimensions (using the wideImage library)
1060
     *
1061
     * @param string  $src_path      Picture's source
1062
     * @param string  $dst_path      Picture's destination
1063
     * @param integer $param_width   Maximum picture's width
1064
     * @param integer $param_height  Maximum picture's height
1065
     * @param boolean $keep_original Do we have to keep the original picture ?
1066
     * @param string  $fit           Resize mode (see the wideImage library for more information)
1067
     *
1068
     * @return bool
1069
     */
1070
    public function resizePicture($src_path, $dst_path, $param_width, $param_height, $keep_original = false, $fit = 'inside')
1071
    {
1072
        require_once OLEDRION_PATH . 'class/wideimage/WideImage.inc.php';
1073
        $resize = true;
1074
        if (OLEDRION_DONT_RESIZE_IF_SMALLER) {
1075
            $pictureDimensions = getimagesize($src_path);
1076
            if (is_array($pictureDimensions)) {
1077
                $width  = $pictureDimensions[0];
1078
                $height = $pictureDimensions[1];
1079
                if ($width < $param_width && $height < $param_height) {
1080
                    $resize = false;
1081
                }
1082
            }
1083
1084
        }
1085
1086
        $img = wiImage::load($src_path);
1087
        if ($resize) {
1088
            $result = $img->resize($param_width, $param_height, $fit);
1089
            $result->saveToFile($dst_path);
1090
        } else {
1091
            @copy($src_path, $dst_path);
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...
1092
        }
1093
1094
        if (!$keep_original) {
1095
            @unlink($src_path);
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...
1096
        }
1097
1098
        return true;
1099
    }
1100
1101
    /**
1102
     * Déclenchement d'une alerte Xoops suite à un évènement
1103
     *
1104
     * @param string       $category La catégorie de l'évènement
1105
     * @param integer      $itemId   L'ID de l'élément (trop général pour être décris précisément)
1106
     * @param unknown_type $event    L'évènement qui est déclencé
1107
     * @param unknown_type $tags     Les variables à passer au template
1108
     */
1109
    public function notify($category, $itemId, $event, $tags)
1110
    {
1111
        $notification_handler = xoops_gethandler('notification');
1112
        $tags['X_MODULE_URL'] = OLEDRION_URL;
1113
        $notification_handler->triggerEvent($category, $itemId, $event, $tags);
1114
    }
1115
1116
    /**
1117
     * Ajoute des jours à une date et retourne la nouvelle date au format Date de Mysql
1118
     *
1119
     * @param int     $duration
1120
     * @param integer $startingDate Date de départ (timestamp)
1121
     *
1122
     * @internal param int $durations Durée en jours
1123
     * @return bool|string
1124
     */
1125
    public function addDaysToDate($duration = 1, $startingDate = 0)
1126
    {
1127
        if ($startingDate == 0) {
1128
            $startingDate = time();
1129
        }
1130
        $endingDate = $startingDate + ($duration * 86400);
1131
1132
        return date('Y-m-d', $endingDate);
1133
    }
1134
1135
    /**
1136
     * Retourne un breadcrumb en fonction des paramètres passés et en partant (d'office) de la racine du module
1137
     *
1138
     * @param array  $path  Le chemin complet (excepté la racine) du breadcrumb sous la forme clé=url valeur=titre
1139
     * @param string $raquo Le séparateur par défaut à utiliser
1140
     *
1141
     * @return string le breadcrumb
1142
     */
1143
    public static function breadcrumb($path, $raquo = ' &raquo; ')
1144
    {
1145
        $breadcrumb        = '';
1146
        $workingBreadcrumb = array();
1147
        if (is_array($path)) {
1148
            $moduleName          = self::getModuleName();
1149
            $workingBreadcrumb[] = "<a href='" . OLEDRION_URL . "' title='" . self::makeHrefTitle($moduleName) . "'>" . $moduleName . '</a>';
1150
            foreach ($path as $url => $title) {
1151
                $workingBreadcrumb[] = "<a href='" . $url . "'>" . $title . '</a>';
1152
            }
1153
            $cnt = count($workingBreadcrumb);
1154
            for ($i = 0; $i < $cnt; ++$i) {
1155
                if ($i == $cnt - 1) {
1156
                    $workingBreadcrumb[$i] = strip_tags($workingBreadcrumb[$i]);
1157
                }
1158
            }
1159
            $breadcrumb = implode($raquo, $workingBreadcrumb);
1160
        }
1161
1162
        return $breadcrumb;
1163
    }
1164
1165
    /**
1166
     * @param $string
1167
     *
1168
     * @return string
1169
     */
1170
    public function close_tags($string)
1171
    {
1172
        // match opened tags
1173
        if (preg_match_all('/<([a-z\:\-]+)[^\/]>/', $string, $start_tags)) {
1174
            $start_tags = $start_tags[1];
1175
1176
            // match closed tags
1177
            if (preg_match_all('/<\/([a-z]+)>/', $string, $end_tags)) {
1178
                $complete_tags = array();
1179
                $end_tags      = $end_tags[1];
1180
1181
                foreach ($start_tags as $key => $val) {
1182
                    $posb = array_search($val, $end_tags);
1183
                    if (is_integer($posb)) {
1184
                        unset($end_tags[$posb]);
1185
                    } else {
1186
                        $complete_tags[] = $val;
1187
                    }
1188
                }
1189
            } else {
1190
                $complete_tags = $start_tags;
1191
            }
1192
1193
            $complete_tags = array_reverse($complete_tags);
1194
            for ($i = 0; $i < count($complete_tags); ++$i) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
1195
                $string .= '</' . $complete_tags[$i] . '>';
1196
            }
1197
        }
1198
1199
        return $string;
1200
    }
1201
1202
    /**
1203
     * @param        $string
1204
     * @param int    $length
1205
     * @param string $etc
1206
     * @param bool   $break_words
1207
     *
1208
     * @return mixed|string
1209
     */
1210
    public function truncate_tagsafe($string, $length = 80, $etc = '...', $break_words = false)
1211
    {
1212
        if ($length == 0) {
1213
            return '';
1214
        }
1215
1216
        if (strlen($string) > $length) {
1217
            $length -= strlen($etc);
1218
            if (!$break_words) {
1219
                $string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length + 1));
1220
                $string = preg_replace('/<[^>]*$/', '', $string);
1221
                $string = self::close_tags($string);
1222
            }
1223
1224
            return $string . $etc;
1225
        } else {
1226
            return $string;
1227
        }
1228
    }
1229
1230
    /**
1231
     * Create an infotip
1232
     * @param $text
1233
     * @return string
1234
*/
1235
    public function makeInfotips($text)
1236
    {
1237
        $ret      = '';
1238
        $infotips = self::getModuleOption('infotips');
1239
        if ($infotips > 0) {
1240
            $myts = MyTextSanitizer::getInstance();
1241
            $ret  = $myts->htmlSpecialChars(xoops_substr(strip_tags($text), 0, $infotips));
1242
        }
1243
1244
        return $ret;
1245
    }
1246
1247
    /**
1248
     * Mise en place de l'appel à la feuille de style du module dans le template
1249
     * @param string $url
1250
*/
1251 View Code Duplication
    public static function setCSS($url = '')
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...
1252
    {
1253
        global $xoopsTpl, $xoTheme;
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...
1254
        if ($url == '') {
1255
            $url = OLEDRION_URL . 'css/oledrion.css';
1256
        }
1257
1258
        if (!is_object($xoTheme)) {
1259
            $xoopsTpl->assign('xoops_module_header', $xoopsTpl->get_template_vars('xoops_module_header') . "<link rel=\"stylesheet\" type=\"text/css\" href=\"$url\" />");
1260
        } else {
1261
            $xoTheme->addStylesheet($url);
1262
        }
1263
    }
1264
1265
    /**
1266
     * Mise en place de l'appel à la feuille de style du module dans le template
1267
     * @param string $language
1268
*/
1269 View Code Duplication
    public static function setLocalCSS($language = 'english')
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...
1270
    {
1271
        global $xoopsTpl, $xoTheme;
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...
1272
1273
        $localcss = OLEDRION_URL . 'language/' . $language . '/style.css';
1274
1275
        if (!is_object($xoTheme)) {
1276
            $xoopsTpl->assign('xoops_module_header', $xoopsTpl->get_template_vars('xoops_module_header') . "<link rel=\"stylesheet\" type=\"text/css\" href=\"$localcss\" />");
1277
        } else {
1278
            $xoTheme->addStylesheet($localcss);
1279
        }
1280
    }
1281
1282
    /**
1283
     * Calcul du TTC à partir du HT et de la TVA
1284
     *
1285
     * @param float   $ht     Montant HT
1286
     * @param float   $vat    Taux de TVA
1287
     * @param boolean $edit   Si faux alors le montant est formaté pour affichage sinon il reste tel quel
1288
     * @param string  $format Format d'affichage du résultat (long ou court)
1289
     *
1290
     * @return mixed Soit une chaine soit un flottant
1291
     */
1292
    public static function getTTC($ht, $vat, $edit = false, $format = 's')
1293
    {
1294
        $oledrion_Currency = oledrion_Currency::getInstance();
1295
        $ttc               = $ht * (1 + ($vat / 100));
1296
        if (!$edit) {
1297
            return $oledrion_Currency->amountForDisplay($ttc, $format);
1298
        } else {
1299
            return $ttc;
1300
        }
1301
    }
1302
1303
    /**
1304
     * Renvoie le montant de la tva à partir du montant HT
1305
     * @param $ht
1306
     * @param $vat
1307
     * @return float
1308
*/
1309
    public function getVAT($ht, $vat)
1310
    {
1311
        return floatval(($ht * $vat) / 100);
1312
    }
1313
1314
    /**
1315
     * Retourne le montant TTC
1316
     *
1317
     * @param floatval $product_price Le montant du produit
1318
     * @param integer  $vat_id        Le numéro de TVA
1319
     *
1320
     * @return floatval Le montant TTC si on a trouvé sa TVA sinon
1321
     */
1322
    public static function getAmountWithVat($product_price, $vat_id)
1323
    {
1324
        static $vats = array();
1325
        $vat_rate = null;
1326
        if (is_array($vats) && in_array($vat_id, $vats)) {
1327
            $vat_rate = $vats[$vat_id];
1328
        } else {
1329
            $handlers = oledrion_handler::getInstance();
1330
            $vat      = null;
0 ignored issues
show
Unused Code introduced by
$vat 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...
1331
            $vat      = $handlers->h_oledrion_vat->get($vat_id);
1332
            if (is_object($vat)) {
1333
                $vat_rate      = $vat->getVar('vat_rate', 'e');
1334
                $vats[$vat_id] = $vat_rate;
1335
            }
1336
        }
1337
1338
        if (!is_null($vat_rate)) {
1339
            return (floatval($product_price) * floatval($vat_rate) / 100) + floatval($product_price);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return floatval($product...oatval($product_price); (double) is incompatible with the return type documented by XoopstubeUtilities::getAmountWithVat of type floatval.

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...
1340
        } else {
1341
            return $product_price;
1342
        }
1343
    }
1344
1345
    /**
1346
     * @param $datastream
1347
     * @param $url
1348
     *
1349
     * @return string
1350
     */
1351
    public function postIt($datastream, $url)
1352
    {
1353
        $url     = preg_replace("@^http://@i", "", $url);
1354
        $host    = substr($url, 0, strpos($url, "/"));
1355
        $uri     = strstr($url, "/");
1356
        $reqbody = '';
1357
        foreach ($datastream as $key => $val) {
1358
            if (!empty($reqbody)) {
1359
                $reqbody .= "&";
1360
            }
1361
            $reqbody .= $key . "=" . urlencode($val);
1362
        }
1363
        $contentlength = strlen($reqbody);
1364
        $reqheader     = "POST $uri HTTP/1.1\r\n" . "Host: $host\n" . "Content-Type: application/x-www-form-urlencoded\r\n" . "Content-Length: $contentlength\r\n\r\n" . "$reqbody\r\n";
1365
1366
        return $reqheader;
1367
    }
1368
1369
    /**
1370
     * Retourne le type Mime d'un fichier en utilisant d'abord finfo puis mime_content
1371
     *
1372
     * @param string $filename Le fichier (avec son chemin d'accès complet) dont on veut connaître le type mime
1373
     *
1374
     * @return string
1375
     */
1376
    public static function getMimeType($filename)
1377
    {
1378
        if (function_exists('finfo_open')) {
1379
            $finfo    = finfo_open();
1380
            $mimetype = finfo_file($finfo, $filename, FILEINFO_MIME_TYPE);
1381
            finfo_close($finfo);
1382
1383
            return $mimetype;
1384
        } else {
1385
            if (function_exists('mime_content_type')) {
1386
                return mime_content_type($filename);
1387
            } else {
1388
                return '';
1389
            }
1390
        }
1391
    }
1392
1393
    /**
1394
     * Retourne un criteria compo qui permet de filtrer les produits sur le mois courant
1395
     *
1396
     * @return object
1397
     */
1398
    public function getThisMonthCriteria()
1399
    {
1400
        $start             = mktime(0, 1, 0, date('n'), date('j'), date('Y'));
1401
        $end               = mktime(0, 0, 0, date('n'), date('t'), date('Y'));
1402
        $criteriaThisMonth = new CriteriaCompo();
1403
        $criteriaThisMonth->add(new Criteria('product_submitted', $start, '>='));
1404
        $criteriaThisMonth->add(new Criteria('product_submitted', $end, '<='));
1405
1406
        return $criteriaThisMonth;
1407
    }
1408
1409
    /**
1410
     * Retourne une liste d'objets XoopsUsers à partir d'une liste d'identifiants
1411
     *
1412
     * @param array $xoopsUsersIDs La liste des ID
1413
     *
1414
     * @return array Les objets XoopsUsers
1415
     */
1416
    public static function getUsersFromIds($xoopsUsersIDs)
1417
    {
1418
        $users = array();
1419
        if (is_array($xoopsUsersIDs) && count($xoopsUsersIDs) > 0) {
1420
            $xoopsUsersIDs = array_unique($xoopsUsersIDs);
1421
            sort($xoopsUsersIDs);
1422
            if (count($xoopsUsersIDs) > 0) {
1423
                $member_handler = xoops_gethandler('user');
1424
                $criteria       = new Criteria('uid', '(' . implode(',', $xoopsUsersIDs) . ')', 'IN');
1425
                $criteria->setSort('uid');
1426
                $users = $member_handler->getObjects($criteria, true);
1427
            }
1428
        }
1429
1430
        return $users;
1431
    }
1432
1433
    /**
1434
     * Retourne l'ID de l'utilisateur courant (s'il est connecté)
1435
     *
1436
     * @return integer L'uid ou 0
1437
     */
1438
    public static function getCurrentUserID()
1439
    {
1440
        global $xoopsUser;
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...
1441
        $uid = is_object($xoopsUser) ? $xoopsUser->getVar('uid') : 0;
1442
1443
        return $uid;
1444
    }
1445
1446
    /**
1447
     * Retourne la liste des groupes de l'utilisateur courant (avec cache)
1448
     *
1449
     * @param int $uid
1450
     *
1451
     * @return array Les ID des groupes auquel l'utilisateur courant appartient
1452
     */
1453
    public function getMemberGroups($uid = 0)
1454
    {
1455
        static $buffer = array();
1456
        if ($uid == 0) {
1457
            $uid = self::getCurrentUserID();
1458
        }
1459
1460
        if (is_array($buffer) && count($buffer) > 0 && isset($buffer[$uid])) {
1461
            return $buffer[$uid];
1462
        } else {
1463
            if ($uid > 0) {
1464
                $member_handler = xoops_gethandler('member');
1465
                $buffer[$uid]   = $member_handler->getGroupsByUser($uid, false); // Renvoie un tableau d'ID (de groupes)
1466
            } else {
1467
                $buffer[$uid] = array(XOOPS_GROUP_ANONYMOUS);
1468
            }
1469
        }
1470
1471
        return $buffer[$uid];
1472
    }
1473
1474
    /**
1475
     * Indique si l'utilisateur courant fait partie d'une groupe donné (avec gestion de cache)
1476
     *
1477
     * @param integer $group Groupe recherché
1478
     * @param int     $uid
1479
     *
1480
     * @return boolean vrai si l'utilisateur fait partie du groupe, faux sinon
1481
     */
1482
    public static function isMemberOfGroup($group = 0, $uid = 0)
1483
    {
1484
        static $buffer = array();
1485
        $retval = false;
0 ignored issues
show
Unused Code introduced by
$retval 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...
1486
        if ($uid == 0) {
1487
            $uid = self::getCurrentUserID();
1488
        }
1489
        if (is_array($buffer) && array_key_exists($group, $buffer)) {
1490
            $retval = $buffer[$group];
1491
        } else {
1492
            $member_handler = xoops_gethandler('member');
1493
            $groups         = $member_handler->getGroupsByUser($uid, false); // Renvoie un tableau d'ID (de groupes)
1494
            $retval         = in_array($group, $groups);
1495
            $buffer[$group] = $retval;
1496
        }
1497
1498
        return $retval;
1499
    }
1500
1501
    /**
1502
     * Fonction chargée de vérifier qu'un répertoire existe, qu'on peut écrire dedans et création d'un fichier index.html
1503
     *
1504
     * @param string $folder Le chemin complet du répertoire à vérifier
1505
     *
1506
     * @return void
1507
     */
1508
    public static function prepareFolder($folder)
1509
    {
1510
        if (!is_dir($folder)) {
1511
            mkdir($folder, 0777);
1512
            file_put_contents($folder . '/index.html', '<script>history.go(-1);</script>');
1513
        }
1514
        chmod($folder, 0777);
1515
    }
1516
1517
    /**
1518
     * Duplicate a file in local
1519
     *
1520
     * @param string $path     The file's path
1521
     * @param string $filename The filename
1522
     *
1523
     * @return mixed If the copy succeed, the new filename else false
1524
     * @since 2.1
1525
     */
1526
    public function duplicateFile($path, $filename)
1527
    {
1528
        $newName = self::createUploadName($path, $filename);
1529
        if (copy($path . DIRECTORY_SEPARATOR . $filename, $path . DIRECTORY_SEPARATOR . $newName)) {
1530
            return $newName;
1531
        } else {
1532
            return false;
1533
        }
1534
    }
1535
1536
    /**
1537
     * Load a language file
1538
     *
1539
     * @param string $languageFile     The required language file
1540
     * @param string $defaultExtension Default extension to use
1541
     *
1542
     * @since 2.2.2009.02.13
1543
     */
1544
    public static function loadLanguageFile($languageFile, $defaultExtension = '.php')
1545
    {
1546
        global $xoopsConfig;
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...
1547
        $root = OLEDRION_PATH;
1548
        if (strstr($languageFile, $defaultExtension) === false) {
1549
            $languageFile .= $defaultExtension;
1550
        }
1551
        if (file_exists($root . 'language' . DIRECTORY_SEPARATOR . $xoopsConfig['language'] . DIRECTORY_SEPARATOR . $languageFile)) {
1552
            require_once $root . 'language' . DIRECTORY_SEPARATOR . $xoopsConfig['language'] . DIRECTORY_SEPARATOR . $languageFile;
1553
        } else { // Fallback
1554
            require_once $root . 'language' . DIRECTORY_SEPARATOR . 'english' . DIRECTORY_SEPARATOR . $languageFile;
1555
        }
1556
    }
1557
1558
    /**
1559
     * Formatage d'un floattant pour la base de données
1560
     *
1561
     * @param float    Le montant à formater
1562
     *
1563
     * @return string le montant formaté
1564
     * @since 2.2.2009.02.25
1565
     */
1566
    public static function formatFloatForDB($amount)
1567
    {
1568
        return number_format($amount, 2, '.', '');
1569
    }
1570
1571
    /**
1572
     * Appelle un fichier Javascript à la manière de Xoops
1573
     *
1574
     * @note, l'url complète ne doit pas être fournie, la méthode se charge d'ajouter
1575
     * le chemin vers le répertoire js en fonction de la requête, c'est à dire que si
1576
     * on appelle un fichier de langue, la méthode ajoute l'url vers le répertoire de
1577
     * langue, dans le cas contraire on ajoute l'url vers le répertoire JS du module.
1578
     *
1579
     * @param string $javascriptFile
1580
     * @param bool   $inLanguageFolder
1581
     * @param bool   $oldWay
1582
     *
1583
     * @return void
1584
     * @since 2.3.2009.03.14
1585
     */
1586
    public static function callJavascriptFile($javascriptFile, $inLanguageFolder = false, $oldWay = false)
0 ignored issues
show
Unused Code introduced by
The parameter $oldWay is not used and could be removed.

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

Loading history...
1587
    {
1588
        global $xoopsConfig, $xoTheme;
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...
1589
        $fileToCall = $javascriptFile;
0 ignored issues
show
Unused Code introduced by
$fileToCall 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...
1590
        if ($inLanguageFolder) {
1591
            $root    = OLEDRION_PATH;
1592
            $rootUrl = OLEDRION_URL;
1593
            if (file_exists($root . 'language' . DIRECTORY_SEPARATOR . $xoopsConfig['language'] . DIRECTORY_SEPARATOR . $javascriptFile)) {
1594
                $fileToCall = $rootUrl . 'language/' . $xoopsConfig['language'] . '/' . $javascriptFile;
1595
            } else { // Fallback
1596
                $fileToCall = $rootUrl . 'language/english/' . $javascriptFile;
1597
            }
1598
        } else {
1599
            $fileToCall = OLEDRION_JS_URL . $javascriptFile;
1600
        }
1601
1602
        $xoTheme->addScript("browse.php?Frameworks/jquery/jquery.js");
1603
        $xoTheme->addScript($fileToCall);
1604
    }
1605
1606
    /**
1607
     * Create the <option> of an html select
1608
     *
1609
     * @param array $array    Array of index and labels
1610
     * @param mixed $default  the default value
1611
     * @param bool  $withNull
1612
     *
1613
     * @return string
1614
     * @since 2.3.2009.03.13
1615
     */
1616
    public function htmlSelectOptions($array, $default = 0, $withNull = true)
1617
    {
1618
        $ret      = array();
1619
        $selected = '';
1620
        if ($withNull) {
1621
            if ($default === 0) {
1622
                $selected = " selected = 'selected'";
1623
            }
1624
            $ret[] = "<option value=0" . $selected . ">---</option>";
1625
        }
1626
1627
        foreach ($array as $index => $label) {
1628
            $selected = '';
1629
            if ($index == $default) {
1630
                $selected = " selected = 'selected'";
1631
            }
1632
            $ret[] = "<option value=\"" . $index . "\"" . $selected . ">" . $label . '</option>';
1633
        }
1634
1635
        return implode("\n", $ret);
1636
    }
1637
1638
    /**
1639
     * Creates an html select
1640
     *
1641
     * @param string  $selectName Selector's name
1642
     * @param array   $array      Options
1643
     * @param mixed   $default    Default's value
1644
     * @param boolean $withNull   Do we include a null option ?
1645
     *
1646
     * @return string
1647
     * @since 2.3.2009.03.13
1648
     */
1649
    public static function htmlSelect($selectName, $array, $default, $withNull = true)
1650
    {
1651
        $ret = '';
1652
        $ret .= "<select name='" . $selectName . "' id='" . $selectName . "'>\n";
1653
        $ret .= self::htmlSelectOptions($array, $default, $withNull);
1654
        $ret .= "</select>\n";
1655
1656
        return $ret;
1657
    }
1658
1659
    /**
1660
     * Extrait l'id d'une chaine formatée sous la forme xxxx-99 (duquel on récupère 99)
1661
     *
1662
     * @note: utilisé par les attributs produits
1663
     *
1664
     * @param string $string    La chaine de travail
1665
     * @param string $separator Le séparateur
1666
     *
1667
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|integer?

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...
1668
     */
1669 View Code Duplication
    public function getId($string, $separator = '_')
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...
1670
    {
1671
        $pos = strrpos($string, $separator);
1672
        if ($pos === false) {
1673
            return $string;
1674
        } else {
1675
            return intval(substr($string, $pos + 1));
1676
        }
1677
    }
1678
1679
    /**
1680
     * Fonction "inverse" de getId (depuis xxxx-99 on récupère xxxx)
1681
     *
1682
     * @note: utilisé par les attributs produits
1683
     *
1684
     * @param string $string    La chaine de travail
1685
     * @param string $separator Le séparateur
1686
     *
1687
     * @return string
1688
     */
1689 View Code Duplication
    public function getName($string, $separator = '_')
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...
1690
    {
1691
        $pos = strrpos($string, $separator);
1692
        if ($pos === false) {
1693
            return $string;
1694
        } else {
1695
            return substr($string, 0, $pos);
1696
        }
1697
    }
1698
1699
    /**
1700
     * Renvoie un montant nul si le montant est négatif
1701
     *
1702
     * @param float $amount
1703
     *
1704
     * @return float
0 ignored issues
show
Documentation introduced by
Should the return type not be double|null?

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...
1705
     */
1706
    public static function doNotAcceptNegativeAmounts(&$amount)
1707
    {
1708
        if ($amount < 0) {
1709
            $amount = 0;
1710
        }
1711
    }
1712
1713
    /**
1714
     * Returns a string from the request
1715
     *
1716
     * @param string $valueName    Name of the parameter you want to get
1717
     * @param mixed  $defaultValue Default value to return if the parameter is not set in the request
1718
     *
1719
     * @return mixed
1720
     */
1721
    public function getFromRequest($valueName, $defaultValue = '')
0 ignored issues
show
Coding Style introduced by
getFromRequest uses the super-global variable $_REQUEST 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...
1722
    {
1723
        return isset($_REQUEST[$valueName]) ? $_REQUEST[$valueName] : $defaultValue;
1724
    }
1725
1726
    /**
1727
     * Verify that a mysql table exists
1728
     *
1729
     * @package       Oledrion
1730
     * @author        Instant Zero (http://xoops.instant-zero.com)
1731
     * @copyright (c) Instant Zero
1732
     * @param $tablename
1733
     * @return bool
1734
*/
1735
    public static function tableExists($tablename)
1736
    {
1737
        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...
1738
        $result = $xoopsDB->queryF("SHOW TABLES LIKE '$tablename'");
1739
1740
        return ($xoopsDB->getRowsNum($result) > 0);
1741
    }
1742
1743
    /**
1744
     * Verify that a field exists inside a mysql table
1745
     *
1746
     * @package       Oledrion
1747
     * @author        Instant Zero (http://xoops.instant-zero.com)
1748
     * @copyright (c) Instant Zero
1749
     * @param $fieldname
1750
     * @param $table
1751
     * @return bool
1752
*/
1753
    public static function fieldExists($fieldname, $table)
1754
    {
1755
        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...
1756
        $result = $xoopsDB->queryF("SHOW COLUMNS FROM $table LIKE '$fieldname'");
1757
1758
        return ($xoopsDB->getRowsNum($result) > 0);
1759
    }
1760
1761
    /**
1762
     * Retourne la définition d'un champ
1763
     *
1764
     * @param string $fieldname
1765
     * @param string $table
1766
     *
1767
     * @return array
1768
     */
1769
    public function getFieldDefinition($fieldname, $table)
1770
    {
1771
        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...
1772
        $result = $xoopsDB->queryF("SHOW COLUMNS FROM $table LIKE '$fieldname'");
1773
        if ($result) {
1774
            return $xoopsDB->fetchArray($result);
1775
        }
1776
1777
        return '';
0 ignored issues
show
Bug Best Practice introduced by
The return type of return ''; (string) is incompatible with the return type documented by XoopstubeUtilities::getFieldDefinition of type array.

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...
1778
    }
1779
1780
    /**
1781
     * Add a field to a mysql table
1782
     *
1783
     * @package       Oledrion
1784
     * @author        Instant Zero (http://xoops.instant-zero.com)
1785
     * @copyright (c) Instant Zero
1786
     * @param $field
1787
     * @param $table
1788
     * @return mixed
1789
*/
1790
    public static function addField($field, $table)
1791
    {
1792
        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...
1793
        $result = $xoopsDB->queryF("ALTER TABLE $table ADD $field;");
1794
1795
        return $result;
1796
    }
1797
1798
    /**
1799
     * @param $info
1800
     *
1801
     * @return string
1802
     */
1803
    public function packingHtmlSelect($info)
1804
    {
1805
        $ret = '';
1806
        $ret .= '<div class="oledrion_htmlform">';
1807
        $ret .= '<img class="oledrion_htmlimage" src="' . $info['packing_image_url'] . '" alt="' . $info['packing_title'] . '" />';
1808
        $ret .= '<h3>' . $info['packing_title'] . '</h3>';
1809 View Code Duplication
        if ($info['packing_price'] > 0) {
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...
1810
            $ret .= '<p><span class="bold">' . _OLEDRION_PRICE . '</span> : ' . $info['packing_price_fordisplay'] . '</p>';
1811
        } else {
1812
            $ret .= '<p><span class="bold">' . _OLEDRION_PRICE . '</span> : ' . _OLEDRION_FREE . '</p>';
1813
        }
1814
        $ret .= '<p>' . $info['packing_description'] . '</p>';
1815
        $ret .= '</div>';
1816
1817
        return $ret;
1818
    }
1819
1820
    /**
1821
     * @param $info
1822
     *
1823
     * @return string
1824
     */
1825
    public function deliveryHtmlSelect($info)
1826
    {
1827
        $ret = '';
1828
        $ret .= '<div class="oledrion_htmlform">';
1829
        $ret .= '<img class="oledrion_htmlimage" src="' . $info['delivery_image_url'] . '" alt="' . $info['delivery_title'] . '" />';
1830
        $ret .= '<h3>' . $info['delivery_title'] . '</h3>';
1831 View Code Duplication
        if ($info['delivery_price'] > 0) {
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...
1832
            $ret .= '<p><span class="bold">' . _OLEDRION_PRICE . '</span> : ' . $info['delivery_price_fordisplay'] . '</p>';
1833
        } else {
1834
            $ret .= '<p><span class="bold">' . _OLEDRION_PRICE . '</span> : ' . _OLEDRION_FREE . '</p>';
1835
        }
1836
        $ret .= '<p><span class="bold">' . _OLEDRION_DELIVERY_TIME . '</span> : ' . $info['delivery_time'] . _OLEDRION_DELIVERY_DAY . '</p>';
1837
        $ret .= '<p>' . $info['delivery_description'] . '</p>';
1838
        $ret .= '</div>';
1839
1840
        return $ret;
1841
    }
1842
1843
    /**
1844
     * @param $info
1845
     *
1846
     * @return string
1847
     */
1848
    public function paymentHtmlSelect($info)
1849
    {
1850
        $ret = '';
1851
        $ret .= '<div class="oledrion_htmlform">';
1852
        $ret .= '<img class="oledrion_htmlimage" src="' . $info['payment_image_url'] . '" alt="' . $info['payment_title'] . '" />';
1853
        $ret .= '<h3>' . $info['payment_title'] . '</h3>';
1854
        $ret .= '<p>' . $info['payment_description'] . '</p>';
1855
        $ret .= '</div>';
1856
1857
        return $ret;
1858
    }
1859
1860
    /**
1861
     * @return array
1862
     */
1863
    public function getCountriesList()
1864
    {
1865
        require_once XOOPS_ROOT_PATH . '/class/xoopslists.php';
1866
1867
        return XoopsLists::getCountryList();
1868
    }
1869
1870
}
1871