references_utils   F
last analyzed

Complexity

Total Complexity 230

Size/Duplication

Total Lines 1532
Duplicated Lines 1.17 %

Coupling/Cohesion

Components 3
Dependencies 1

Importance

Changes 0
Metric Value
dl 18
loc 1532
rs 0.8
c 0
b 0
f 0
wmc 230
lcom 3
cbo 1

56 Methods

Rating   Name   Duplication   Size   Complexity  
A getInstance() 0 9 2
B getModuleOption() 0 29 11
A isX23() 0 10 2
C getWysiwygForm() 18 64 14
A javascriptLinkConfirm() 0 8 2
B IP() 0 27 11
B setMetas() 0 20 9
B sendEmailFromTpl() 0 58 10
B updateCache() 0 26 7
A redirect() 0 5 1
A getModule() 0 15 5
A getModuleName() 0 10 2
A makeHrefTitle() 0 7 1
A getUsersFromGroup() 0 8 1
A getUsersIdsFromGroups() 0 14 3
A getEmailsFromGroup() 0 10 2
A 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
A needsAsterisk() 0 17 5
A formMarkRequiredFields() 0 19 6
A htitle() 0 4 1
A createUploadName() 0 28 5
B unhtml() 0 138 2
B makeSeoUrl() 0 39 5
D createMetaKeywords() 0 68 13
B uploadFile() 0 41 8
A resizePicture() 0 12 2
A notify() 0 6 1
A addDaysToDate() 0 9 2
A breadcrumb() 0 21 5
B close_tags() 0 31 6
A truncate_tagsafe() 0 19 4
A makeInfotips() 0 11 2
A getMimeType() 0 18 3
A getUsersFromIds() 0 16 4
A getCurrentUserID() 0 7 2
B getMemberGroups() 0 20 6
A isMemberOfGroup() 0 18 4
A isMemberOfGroups() 0 16 5
A getGroupsCount() 0 15 3
A prepareFolder() 0 11 3
A loadLanguageFile() 0 13 3
B createThumb() 0 43 11
B htmlSelectOptions() 0 33 9
A htmlSelect() 0 16 3
A tableExists() 0 7 1
A fieldExists() 0 7 1
A getFieldDefinition() 0 10 2
A addField() 0 7 1
A maintainTablesCache() 0 19 3
A tagModuleExists() 0 15 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

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

Common duplication problems, and corresponding solutions are:

Complex Class

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

Complex classes like references_utils 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 references_utils, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * ****************************************************************************
4
 * references - MODULE FOR XOOPS
5
 * Copyright (c) Hervé Thouzard of Instant Zero (http://www.instant-zero.com)
6
 *
7
 * You may not change or alter any portion of this comment or credits
8
 * of supporting developers from this source code or any supporting source code
9
 * which is considered copyrighted (c) material of the original comment or credit authors.
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
 *
14
 * @copyright       Hervé Thouzard of Instant Zero (http://www.instant-zero.com)
15
 * @license         http://www.fsf.org/copyleft/gpl.html GNU public license
16
 * @package         references
17
 * @author          Hervé Thouzard of Instant Zero (http://www.instant-zero.com)
18
 *
19
 * ****************************************************************************
20
 */
21
22
/**
23
 * A set of useful and common functions
24
 *
25
 * @package       references
26
 * @author        Hervé Thouzard - Instant Zero (http://xoops.instant-zero.com)
27
 * @copyright (c) Instant Zero
28
 *
29
 * Note: You should be able to use it without the need to instanciate it.
30
 *
31
 */
32
33
use WideImage\WideImage;
34
35
defined('XOOPS_ROOT_PATH') || exit('XOOPS root path not defined');
36
37
class references_utils
38
{
39
    // Pour la portabilité de module à module
40
    const MODULE_NAME    = 'references';
41
    const MODULE_DIRNAME = REFERENCES_DIRNAME;
42
    const MODULE_PATH    = REFERENCES_PATH;
43
    const MODULE_URL     = REFERENCES_URL;
44
    const MODULE_JS_URL  = REFERENCES_JS_URL;
45
46
    /**
47
     * Access the only instance of this class
48
     *
49
     * @return object
50
     *
51
     * @static
52
     * @staticvar   object
53
     */
54
    public static function getInstance()
55
    {
56
        static $instance;
57
        if (null === $instance) {
58
            $instance = new static();
59
        }
60
61
        return $instance;
62
    }
63
64
    /**
65
     * Returns a module's option (with cache)
66
     *
67
     * @param  string  $option    module option's name
68
     * @param  boolean $withCache Do we have to use some cache ?
69
     * @return mixed   option's value
70
     */
71
    public static function getModuleOption($option, $withCache = true)
72
    {
73
        global $xoopsModuleConfig, $xoopsModule;
74
        $repmodule = self::MODULE_NAME;
75
        static $options = array();
76
        if (is_array($options) && array_key_exists($option, $options) && $withCache) {
77
            return $options[$option];
78
        }
79
80
        $retval = false;
81
        if (isset($xoopsModuleConfig) && (is_object($xoopsModule) && $xoopsModule->getVar('dirname') == $repmodule && $xoopsModule->getVar('isactive'))) {
82
            if (isset($xoopsModuleConfig[$option])) {
83
                $retval = $xoopsModuleConfig[$option];
84
            }
85
        } else {
86
            $module_handler = xoops_getHandler('module');
87
            $module         = $module_handler->getByDirname($repmodule);
88
            $config_handler = xoops_getHandler('config');
89
            if ($module) {
90
                $moduleConfig = $config_handler->getConfigsByCat(0, $module->getVar('mid'));
91
                if (isset($moduleConfig[$option])) {
92
                    $retval = $moduleConfig[$option];
93
                }
94
            }
95
        }
96
        $options[$option] = $retval;
97
98
        return $retval;
99
    }
100
101
    /**
102
     * Is Xoops 2.3.x ?
103
     *
104
     * @return boolean need to say it ?
105
     */
106
    public static function isX23()
107
    {
108
        $x23 = false;
109
        $xv  = str_replace('XOOPS ', '', XOOPS_VERSION);
110
        if ((int)substr($xv, 2, 1) >= 3) {
111
            $x23 = true;
112
        }
113
114
        return $x23;
115
    }
116
117
    /**
118
     * Retreive an editor according to the module's option "form_options"
119
     *
120
     * @param  string $caption Caption to give to the editor
121
     * @param  string $name    Editor's name
122
     * @param  string $value   Editor's value
123
     * @param  string $width   Editor's width
124
     * @param  string $height  Editor's height
125
     * @param string  $supplemental
126
     * @return object The editor to use
0 ignored issues
show
Documentation introduced by
Should the return type not be XoopsFormEditor|XoopsFor...rmWysiwygTextArea|false?

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...
127
     */
128
    public static function getWysiwygForm($caption, $name, $value = '', $width = '100%', $height = '400px', $supplemental = '')
129
    {
130
        $editor                   = false;
131
        $editor_configs           = array();
132
        $editor_configs['name']   = $name;
133
        $editor_configs['value']  = $value;
134
        $editor_configs['rows']   = 35;
135
        $editor_configs['cols']   = 60;
136
        $editor_configs['width']  = '100%';
137
        $editor_configs['height'] = '400px';
138
139
        $editor_option = strtolower(self::getModuleOption('form_options'));
140
141
        if (self::isX23()) {
142
            $editor = new XoopsFormEditor($caption, $editor_option, $editor_configs);
143
144
            return $editor;
145
        }
146
147
        // Only for Xoops 2.0.x
148
        switch ($editor_option) {
149 View Code Duplication
            case 'fckeditor':
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...
150
                if (is_readable(XOOPS_ROOT_PATH . '/class/fckeditor/formfckeditor.php')) {
151
                    require_once(XOOPS_ROOT_PATH . '/class/fckeditor/formfckeditor.php');
152
                    $editor = new XoopsFormFckeditor($caption, $name, $value);
153
                }
154
                break;
155
156 View Code Duplication
            case 'htmlarea':
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...
157
                if (is_readable(XOOPS_ROOT_PATH . '/class/htmlarea/formhtmlarea.php')) {
158
                    require_once(XOOPS_ROOT_PATH . '/class/htmlarea/formhtmlarea.php');
159
                    $editor = new XoopsFormHtmlarea($caption, $name, $value);
160
                }
161
                break;
162
163
            case 'dhtmltextarea':
164
                $editor = new XoopsFormDhtmlTextArea($caption, $name, $value, 10, 50, $supplemental);
165
                break;
166
167
            case 'textarea':
168
                $editor = new XoopsFormTextArea($caption, $name, $value);
169
                break;
170
171
            case 'tinyeditor':
172
            case 'tinymce':
173
                if (is_readable(XOOPS_ROOT_PATH . '/class/xoopseditor/tinyeditor/formtinyeditortextarea.php')) {
174
                    require_once XOOPS_ROOT_PATH . '/class/xoopseditor/tinyeditor/formtinyeditortextarea.php';
175
                    $editor = new XoopsFormTinyeditorTextArea(array('caption' => $caption, 'name' => $name, 'value' => $value, 'width' => '100%', 'height' => '400px'));
176
                }
177
                break;
178
179 View Code Duplication
            case 'koivi':
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...
180
                if (is_readable(XOOPS_ROOT_PATH . '/class/wysiwyg/formwysiwygtextarea.php')) {
181
                    require_once(XOOPS_ROOT_PATH . '/class/wysiwyg/formwysiwygtextarea.php');
182
                    $editor = new XoopsFormWysiwygTextArea($caption, $name, $value, $width, $height, '');
183
                }
184
                break;
185
        }
186
        if (!is_object($editor)) {
187
            trigger_error('Error, impossible to get the requested text editor', E_USER_ERROR);
188
        }
189
190
        return $editor;
191
    }
192
193
    /**
194
     * Create (in a link) a javascript confirmation's box
195
     *
196
     * @param  string  $message Message to display
197
     * @param  boolean $form    Is this a confirmation for a form ?
198
     * @return string  the javascript code to insert in the link (or in the form)
199
     */
200
    public static function javascriptLinkConfirm($message, $form = false)
201
    {
202
        if (!$form) {
203
            return "onclick=\"javascript:return confirm('" . str_replace("'", ' ', $message) . "')\"";
204
        } else {
205
            return "onSubmit=\"javascript:return confirm('" . str_replace("'", ' ', $message) . "')\"";
206
        }
207
    }
208
209
    /**
210
     * Get current user IP
211
     *
212
     * @return string IP address (format Ipv4)
213
     */
214
    public static function IP()
215
    {
216
        $proxy_ip = '';
217
        if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
218
            $proxy_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
219
        } elseif (!empty($_SERVER['HTTP_X_FORWARDED'])) {
220
            $proxy_ip = $_SERVER['HTTP_X_FORWARDED'];
221
        } elseif (!empty($_SERVER['HTTP_FORWARDED_FOR'])) {
222
            $proxy_ip = $_SERVER['HTTP_FORWARDED_FOR'];
223
        } elseif (!empty($_SERVER['HTTP_FORWARDED'])) {
224
            $proxy_ip = $_SERVER['HTTP_FORWARDED'];
225
        } elseif (!empty($_SERVER['HTTP_VIA'])) {
226
            $proxy_ip = $_SERVER['HTTP_VIA'];
227
        } elseif (!empty($_SERVER['HTTP_X_COMING_FROM'])) {
228
            $proxy_ip = $_SERVER['HTTP_X_COMING_FROM'];
229
        } elseif (!empty($_SERVER['HTTP_COMING_FROM'])) {
230
            $proxy_ip = $_SERVER['HTTP_COMING_FROM'];
231
        }
232
        $regs = array();
233
        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
Comprehensibility introduced by
Consider adding parentheses for clarity. Current Interpretation: $is_ip = (ereg('^([0-9]{...s) && count($regs) > 0), Probably Intended Meaning: ($is_ip = ereg('^([0-9]{...s)) && count($regs) > 0
Loading history...
234
            $the_IP = $regs[0];
235
        } else {
236
            $the_IP = $_SERVER['REMOTE_ADDR'];
237
        }
238
239
        return $the_IP;
240
    }
241
242
    /**
243
     * Set the page's title, meta description and meta keywords
244
     * Datas are supposed to be sanitized
245
     *
246
     * @param  string $pageTitle       Page's Title
247
     * @param  string $metaDescription Page's meta description
248
     * @param  string $metaKeywords    Page's meta keywords
249
     * @return void
250
     */
251
    public static function setMetas($pageTitle = '', $metaDescription = '', $metaKeywords = '')
252
    {
253
        global $xoTheme, $xoTheme, $xoopsTpl;
254
        $xoopsTpl->assign('xoops_pagetitle', $pageTitle);
255
        if (isset($xoTheme) && is_object($xoTheme)) {
256
            if (!empty($metaKeywords)) {
257
                $xoTheme->addMeta('meta', 'keywords', $metaKeywords);
258
            }
259
            if (!empty($metaDescription)) {
260
                $xoTheme->addMeta('meta', 'description', $metaDescription);
261
            }
262
        } elseif (isset($xoopsTpl) && is_object($xoopsTpl)) {    // Compatibility for old Xoops versions
263
            if (!empty($metaKeywords)) {
264
                $xoopsTpl->assign('xoops_meta_keywords', $metaKeywords);
265
            }
266
            if (!empty($metaDescription)) {
267
                $xoopsTpl->assign('xoops_meta_description', $metaDescription);
268
            }
269
        }
270
    }
271
272
    /**
273
     * Send an email from a template to a list of recipients
274
     *
275
     * @param         $tplName
276
     * @param  array  $recipients List of recipients
277
     * @param  string $subject    Email's subject
278
     * @param  array  $variables  Varirables to give to the template
279
     * @return bool Result of the send
280
     * @internal param string $tpl_name Template's name
281
     */
282
    public static function sendEmailFromTpl($tplName, $recipients, $subject, $variables)
283
    {
284
        global $xoopsConfig;
285
        require_once XOOPS_ROOT_PATH . '/class/xoopsmailer.php';
286
        if (!is_array($recipients)) {
287
            if (trim($recipients) == '') {
288
                return false;
289
            }
290
        } else {
291
            if (count($recipients) == 0) {
292
                return false;
293
            }
294
        }
295
        if (function_exists('xoops_getMailer')) {
296
            $xoopsMailer = xoops_getMailer();
297
        } else {
298
            $xoopsMailer =& getMailer();
299
        }
300
301
        $xoopsMailer->useMail();
302
        $xoopsMailer->setTemplateDir(XOOPS_ROOT_PATH . '/modules/' . self::MODULE_NAME . '/language/' . $xoopsConfig['language'] . '/mail_template');
303
        $xoopsMailer->setTemplate($tplName);
304
        $xoopsMailer->setToEmails($recipients);
305
        // TODO: Change !
306
        // $xoopsMailer->setFromEmail('[email protected]');
307
        //$xoopsMailer->setFromName('MonSite');
308
        $xoopsMailer->setSubject($subject);
309
        foreach ($variables as $key => $value) {
310
            $xoopsMailer->assign($key, $value);
311
        }
312
        $res = $xoopsMailer->send();
313
        unset($xoopsMailer);
314
        $filename = XOOPS_UPLOAD_PATH . '/logmail_' . self::MODULE_NAME . '.php';
315
        if (!file_exists($filename)) {
316
            $fp = @fopen($filename, 'a');
317
            if ($fp) {
318
                fwrite($fp, '<?php exit(); ?>');
319
                fclose($fp);
320
            }
321
        }
322
        $fp = @fopen($filename, 'a');
323
324
        if ($fp) {
325
            fwrite($fp, str_repeat('-', 120) . "\n");
326
            fwrite($fp, date('d/m/Y H:i:s') . "\n");
327
            fwrite($fp, 'Template name : ' . $tplName . "\n");
328
            fwrite($fp, 'Email subject : ' . $subject . "\n");
329
            if (is_array($recipients)) {
330
                fwrite($fp, 'Recipient(s) : ' . implode(',', $recipients) . "\n");
331
            } else {
332
                fwrite($fp, 'Recipient(s) : ' . $recipients . "\n");
333
            }
334
            fwrite($fp, 'Transmited variables : ' . implode(',', $variables) . "\n");
335
            fclose($fp);
336
        }
337
338
        return $res;
339
    }
340
341
    /**
342
     * Remove module's cache
343
     */
344
    public static function updateCache()
345
    {
346
        global $xoopsModule;
347
        $folder  = $xoopsModule->getVar('dirname');
348
        $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...
349
        require_once XOOPS_ROOT_PATH . '/class/xoopsblock.php';
350
        require_once XOOPS_ROOT_PATH . '/class/template.php';
351
        $tplfile_handler = xoops_getHandler('tplfile');
352
        $tpllist         = $tplfile_handler->find(null, null, null, $folder);
353
        xoops_template_clear_module_cache($xoopsModule->getVar('mid'));            // Clear module's blocks cache
354
355
        foreach ($tpllist as $onetemplate) {    // Remove cache for each page.
356
            if ($onetemplate->getVar('tpl_type') === 'module') {
357
                //  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
358
                $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...
359
                $files_del = glob(XOOPS_CACHE_PATH . '/*' . $onetemplate->getVar('tpl_file') . '*');
360
                if (count($files_del) > 0 && is_array($files_del)) {
361
                    foreach ($files_del as $one_file) {
362
                        if (is_file($one_file)) {
363
                            unlink($one_file);
364
                        }
365
                    }
366
                }
367
            }
368
        }
369
    }
370
371
    /**
372
     * Redirect user with a message
373
     *
374
     * @param string $message message to display
375
     * @param string $url     The place where to go
376
     * @param        integer  timeout Time to wait before to redirect
377
     */
378
    public static function redirect($message = '', $url = 'index.php', $time = 2)
379
    {
380
        redirect_header($url, $time, $message);
381
        exit();
382
    }
383
384
    /**
385
     * Internal function used to get the handler of the current module
386
     *
387
     * @return object The module
388
     */
389
    public static function getModule()
390
    {
391
        static $mymodule;
392
        if (!isset($mymodule)) {
393
            global $xoopsModule;
394
            if (isset($xoopsModule) && is_object($xoopsModule) && $xoopsModule->getVar('dirname') == REFERENCES_DIRNAME) {
395
                $mymodule =& $xoopsModule;
396
            } else {
397
                $hModule  = xoops_getHandler('module');
398
                $mymodule = $hModule->getByDirname(REFERENCES_DIRNAME);
399
            }
400
        }
401
402
        return $mymodule;
403
    }
404
405
    /**
406
     * Returns the module's name (as defined by the user in the module manager) with cache
407
     * @return string Module's name
408
     */
409
    public static function getModuleName()
410
    {
411
        static $moduleName;
412
        if (!isset($moduleName)) {
413
            $mymodule   = self::getModule();
414
            $moduleName = $mymodule->getVar('name');
415
        }
416
417
        return $moduleName;
418
    }
419
420
    /**
421
     * Create a title for the href tags inside html links
422
     *
423
     * @param  string $title Text to use
424
     * @return string Formated text
425
     */
426
    public static function makeHrefTitle($title)
427
    {
428
        $s = "\"'";
429
        $r = '  ';
430
431
        return strtr($title, $s, $r);
432
    }
433
434
    /**
435
     * Retourne la liste des utilisateurs appartenants � un groupe
436
     *
437
     * @param  int $groupId Searched group
438
     * @return array Array of XoopsUsers
439
     */
440
    public static function getUsersFromGroup($groupId)
441
    {
442
        $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...
443
        $member_handler = xoops_getHandler('member');
444
        $users          = $member_handler->getUsersByGroup($groupId, true);
445
446
        return $users;
447
    }
448
449
    /**
450
     * Retourne les ID des utilisateurs faisant partie de plusieurs groupes
451
     * @param  array $groups Les ID des groupes dont on recherche les ID utilisateurs
452
     * @return array Les ID utilisateurs
453
     */
454
    public static function getUsersIdsFromGroups($groups)
455
    {
456
        $usersIds       = array();
457
        $member_handler = xoops_getHandler('member');
458
        foreach ($groups as $groupId) {
459
            $temporaryGroup = array();
0 ignored issues
show
Unused Code introduced by
$temporaryGroup 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...
460
            $temporaryGroup = $member_handler->getUsersByGroup($groupId);
461
            if (count($temporaryGroup) > 0) {
462
                $usersIds = array_merge($usersIds, $temporaryGroup);
463
            }
464
        }
465
466
        return array_unique($usersIds);
467
    }
468
469
    /**
470
     * Retourne la liste des emails des utilisateurs membres d'un groupe
471
     *
472
     * @param $groupId
473
     * @return array Emails list
474
     * @internal param int $group_id Group's number
475
     */
476
    public static function getEmailsFromGroup($groupId)
477
    {
478
        $ret   = array();
479
        $users = self::getUsersFromGroup($groupId);
480
        foreach ($users as $user) {
481
            $ret[] = $user->getVar('email');
482
        }
483
484
        return $ret;
485
    }
486
487
    /**
488
     * V�rifie que l'utilisateur courant fait partie du groupe des administrateurs
489
     *
490
     * @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...
491
     */
492
    public static function isAdmin()
493
    {
494
        global $xoopsUser, $xoopsModule;
495
        if (is_object($xoopsUser)) {
496
            if (in_array(XOOPS_GROUP_ADMIN, $xoopsUser->getGroups())) {
497
                return true;
498
            } elseif (isset($xoopsModule) && $xoopsUser->isAdmin($xoopsModule->getVar('mid'))) {
499
                return true;
500
            }
501
        }
502
503
        return false;
504
    }
505
506
    /**
507
     * Returns the current date in the Mysql format
508
     *
509
     * @return string Date in the Mysql format
510
     */
511
    public static function getCurrentSQLDate()
512
    {
513
        return date('Y-m-d');    // 2007-05-02
514
    }
515
516
    public static function getCurrentSQLDateTime()
517
    {
518
        return date('Y-m-d H:i:s');    // 2007-05-02
519
    }
520
521
    /**
522
     * Convert a Mysql date to the human's format
523
     *
524
     * @param  string $date The date to convert
525
     * @param string  $format
526
     * @return string The date in a human form
527
     */
528
    public static function SQLDateToHuman($date, $format = 'l')
529
    {
530
        if ($date != '0000-00-00' && xoops_trim($date) != '') {
531
            return formatTimestamp(strtotime($date), $format);
532
        } else {
533
            return '';
534
        }
535
    }
536
537
    /**
538
     * Convert a timestamp to a Mysql date
539
     *
540
     * @param  integer $timestamp The timestamp to use
541
     * @return string  The date in the Mysql format
542
     */
543
    public static function timestampToMysqlDate($timestamp)
544
    {
545
        return date('Y-m-d', (int)$timestamp);
546
    }
547
548
    /**
549
     * Conversion d'un dateTime Mysql en date lisible en fran�ais
550
     * @param $dateTime
551
     * @return bool|string
552
     */
553
    public static function sqlDateTimeToFrench($dateTime)
554
    {
555
        return date('d/m/Y H:i:s', strtotime($dateTime));
556
    }
557
558
    /**
559
     * Convert a timestamp to a Mysql datetime form
560
     * @param  integer $timestamp The timestamp to use
561
     * @return string  The date and time in the Mysql format
562
     */
563
    public static function timestampToMysqlDateTime($timestamp)
564
    {
565
        return date('Y-m-d H:i:s', $timestamp);
566
    }
567
568
    /**
569
     * This function indicates if the current Xoops version needs to add asterisks to required fields in forms
570
     *
571
     * @return boolean Yes = we need to add them, false = no
572
     */
573
    public static function needsAsterisk()
574
    {
575
        if (self::isX23()) {
576
            return false;
577
        }
578
        if (strpos(strtolower(XOOPS_VERSION), 'impresscms') !== false) {
579
            return false;
580
        }
581
        if (strpos(strtolower(XOOPS_VERSION), 'legacy') === false) {
582
            $xv = xoops_trim(str_replace('XOOPS ', '', XOOPS_VERSION));
583
            if ((int)substr($xv, 4, 2) >= 17) {
584
                return false;
585
            }
586
        }
587
588
        return true;
589
    }
590
591
    /**
592
     * Mark the mandatory fields of a form with a star
593
     *
594
     * @param  object $sform The form to modify
595
     * @return object The modified form
596
     * @internal param string $caracter The character to use to mark fields
597
     */
598
    public static function &formMarkRequiredFields(&$sform)
599
    {
600
        if (self::needsAsterisk()) {
601
            $required = array();
602
            foreach ($sform->getRequired() as $item) {
603
                $required[] = $item->_name;
604
            }
605
            $elements = array();
606
            $elements = &$sform->getElements();
607
            $cnt      = count($elements);
608
            for ($i = 0; $i < $cnt; ++$i) {
609
                if (is_object($elements[$i]) && in_array($elements[$i]->_name, $required)) {
610
                    $elements[$i]->_caption .= ' *';
611
                }
612
            }
613
        }
614
615
        return $sform;
616
    }
617
618
    /**
619
     * Create an html heading (from h1 to h6)
620
     *
621
     * @param  string  $title The text to use
622
     * @param  integer $level Level to return
623
     * @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...
624
     */
625
    public static function htitle($title = '', $level = 1)
626
    {
627
        printf('<h%01d>%s</h%01d>', $level, $title, $level);
628
    }
629
630
    /**
631
     * Create a unique upload filename
632
     *
633
     * @param  string  $folder   The folder where the file will be saved
634
     * @param  string  $fileName Original filename (coming from the user)
635
     * @param  boolean $trimName Do we need to create a short unique name ?
636
     * @return string  The unique filename to use (with its extension)
637
     */
638
    public static function createUploadName($folder, $fileName, $trimName = false)
639
    {
640
        $workingfolder = $folder;
641
        if (substr($workingfolder, strlen($workingfolder) - 1, 1) !== '/') {
642
            $workingfolder .= '/';
643
        }
644
        $ext  = basename($fileName);
645
        $ext  = explode('.', $ext);
646
        $ext  = '.' . $ext[count($ext) - 1];
647
        $true = true;
648
        while ($true) {
649
            $ipbits = explode('.', $_SERVER['REMOTE_ADDR']);
650
            list($usec, $sec) = explode(' ', microtime());
651
            $usec = (integer)($usec * 65536);
652
            $sec  = ((integer)$sec) & 0xFFFF;
653
654
            if ($trimName) {
655
                $uid = sprintf('%06x%04x%04x', ($ipbits[0] << 24) | ($ipbits[1] << 16) | ($ipbits[2] << 8) | $ipbits[3], $sec, $usec);
656
            } else {
657
                $uid = sprintf('%08x-%04x-%04x', ($ipbits[0] << 24) | ($ipbits[1] << 16) | ($ipbits[2] << 8) | $ipbits[3], $sec, $usec);
658
            }
659
            if (!file_exists($workingfolder . $uid . $ext)) {
660
                $true = false;
661
            }
662
        }
663
664
        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...
665
    }
666
667
    /**
668
     * Replace html entities with their ASCII equivalent
669
     *
670
     * @param  string $chaine The string undecode
671
     * @return string The undecoded string
672
     */
673
    public static function unhtml($chaine)
674
    {
675
        $search = $replace = array();
676
        $chaine = html_entity_decode($chaine);
677
678
        for ($i = 0; $i <= 255; ++$i) {
679
            $search[]  = '&#' . $i . ';';
680
            $replace[] = chr($i);
681
        }
682
        $replace[]='...'; $search[]='…';
683
        $replace[]="'"; $search[]='‘';
684
        $replace[]="'"; $search[]= '’';
685
        $replace[]='-'; $search[] = '&bull;';   // $replace[] = '•';
686
        $replace[]='—'; $search[]='&mdash;';
687
        $replace[]='-'; $search[]='&ndash;';
688
        $replace[]='-'; $search[]='&shy;';
689
        $replace[]='"'; $search[]='&quot;';
690
        $replace[]='&'; $search[]='&amp;';
691
        $replace[]='ˆ'; $search[]='&circ;';
692
        $replace[]='¡'; $search[]='&iexcl;';
693
        $replace[]='¦'; $search[]='&brvbar;';
694
        $replace[]='¨'; $search[]='&uml;';
695
        $replace[]='¯'; $search[]='&macr;';
696
        $replace[]='´'; $search[]='&acute;';
697
        $replace[]='¸'; $search[]='&cedil;';
698
        $replace[]='¿'; $search[]='&iquest;';
699
        $replace[]='˜'; $search[]='&tilde;';
700
        $replace[]="'"; $search[]='&lsquo;';    // $replace[]='‘';
701
        $replace[]="'"; $search[]='&rsquo;';    // $replace[]='’';
702
        $replace[]='‚'; $search[]='&sbquo;';
703
        $replace[]="'"; $search[]='&ldquo;';    // $replace[]='“';
704
        $replace[]="'"; $search[]='&rdquo;';    // $replace[]='”';
705
        $replace[]='„'; $search[]='&bdquo;';
706
        $replace[]='‹'; $search[]='&lsaquo;';
707
        $replace[]='›'; $search[]='&rsaquo;';
708
        $replace[]='<'; $search[]='&lt;';
709
        $replace[]='>'; $search[]='&gt;';
710
        $replace[]='±'; $search[]='&plusmn;';
711
        $replace[]='«'; $search[]='&laquo;';
712
        $replace[]='»'; $search[]='&raquo;';
713
        $replace[]='×'; $search[]='&times;';
714
        $replace[]='÷'; $search[]='&divide;';
715
        $replace[]='¢'; $search[]='&cent;';
716
        $replace[]='£'; $search[]='&pound;';
717
        $replace[]='¤'; $search[]='&curren;';
718
        $replace[]='¥'; $search[]='&yen;';
719
        $replace[]='§'; $search[]='&sect;';
720
        $replace[]='©'; $search[]='&copy;';
721
        $replace[]='¬'; $search[]='&not;';
722
        $replace[]='®'; $search[]='&reg;';
723
        $replace[]='°'; $search[]='&deg;';
724
        $replace[]='µ'; $search[]='&micro;';
725
        $replace[]='¶'; $search[]='&para;';
726
        $replace[]='·'; $search[]='&middot;';
727
        $replace[]='†'; $search[]='&dagger;';
728
        $replace[]='‡'; $search[]='&Dagger;';
729
        $replace[]='‰'; $search[]='&permil;';
730
        $replace[]='Euro'; $search[]='&euro;';      // $replace[]='€'
731
        $replace[]='¼'; $search[]='&frac14;';
732
        $replace[]='½'; $search[]='&frac12;';
733
        $replace[]='¾'; $search[]='&frac34;';
734
        $replace[]='¹'; $search[]='&sup1;';
735
        $replace[]='²'; $search[]='&sup2;';
736
        $replace[]='³'; $search[]='&sup3;';
737
        $replace[]='á'; $search[]='&aacute;';
738
        $replace[]='Á'; $search[]='&Aacute;';
739
        $replace[]='â'; $search[]='&acirc;';
740
        $replace[]='Â'; $search[]='&Acirc;';
741
        $replace[]='à'; $search[]='&agrave;';
742
        $replace[]='À'; $search[]='&Agrave;';
743
        $replace[]='å'; $search[]='&aring;';
744
        $replace[]='Å'; $search[]='&Aring;';
745
        $replace[]='ã'; $search[]='&atilde;';
746
        $replace[]='Ã'; $search[]='&Atilde;';
747
        $replace[]='ä'; $search[]='&auml;';
748
        $replace[]='Ä'; $search[]='&Auml;';
749
        $replace[]='ª'; $search[]='&ordf;';
750
        $replace[]='æ'; $search[]='&aelig;';
751
        $replace[]='Æ'; $search[]='&AElig;';
752
        $replace[]='ç'; $search[]='&ccedil;';
753
        $replace[]='Ç'; $search[]='&Ccedil;';
754
        $replace[]='ð'; $search[]='&eth;';
755
        $replace[]='Ð'; $search[]='&ETH;';
756
        $replace[]='é'; $search[]='&eacute;';
757
        $replace[]='É'; $search[]='&Eacute;';
758
        $replace[]='ê'; $search[]='&ecirc;';
759
        $replace[]='Ê'; $search[]='&Ecirc;';
760
        $replace[]='è'; $search[]='&egrave;';
761
        $replace[]='È'; $search[]='&Egrave;';
762
        $replace[]='ë'; $search[]='&euml;';
763
        $replace[]='Ë'; $search[]='&Euml;';
764
        $replace[]='ƒ'; $search[]='&fnof;';
765
        $replace[]='í'; $search[]='&iacute;';
766
        $replace[]='Í'; $search[]='&Iacute;';
767
        $replace[]='î'; $search[]='&icirc;';
768
        $replace[]='Î'; $search[]='&Icirc;';
769
        $replace[]='ì'; $search[]='&igrave;';
770
        $replace[]='Ì'; $search[]='&Igrave;';
771
        $replace[]='ï'; $search[]='&iuml;';
772
        $replace[]='Ï'; $search[]='&Iuml;';
773
        $replace[]='ñ'; $search[]='&ntilde;';
774
        $replace[]='Ñ'; $search[]='&Ntilde;';
775
        $replace[]='ó'; $search[]='&oacute;';
776
        $replace[]='Ó'; $search[]='&Oacute;';
777
        $replace[]='ô'; $search[]='&ocirc;';
778
        $replace[]='Ô'; $search[]='&Ocirc;';
779
        $replace[]='ò'; $search[]='&ograve;';
780
        $replace[]='Ò'; $search[]='&Ograve;';
781
        $replace[]='º'; $search[]='&ordm;';
782
        $replace[]='ø'; $search[]='&oslash;';
783
        $replace[]='Ø'; $search[]='&Oslash;';
784
        $replace[]='õ'; $search[]='&otilde;';
785
        $replace[]='Õ'; $search[]='&Otilde;';
786
        $replace[]='ö'; $search[]='&ouml;';
787
        $replace[]='Ö'; $search[]='&Ouml;';
788
        $replace[]='œ'; $search[]='&oelig;';
789
        $replace[]='Œ'; $search[]='&OElig;';
790
        $replace[]='š'; $search[]='&scaron;';
791
        $replace[]='Š'; $search[]='&Scaron;';
792
        $replace[]='ß'; $search[]='&szlig;';
793
        $replace[]='þ'; $search[]='&thorn;';
794
        $replace[]='Þ'; $search[]='&THORN;';
795
        $replace[]='ú'; $search[]='&uacute;';
796
        $replace[]='Ú'; $search[]='&Uacute;';
797
        $replace[]='û'; $search[]='&ucirc;';
798
        $replace[]='Û'; $search[]='&Ucirc;';
799
        $replace[]='ù'; $search[]='&ugrave;';
800
        $replace[]='Ù'; $search[]='&Ugrave;';
801
        $replace[]='ü'; $search[]='&uuml;';
802
        $replace[]='Ü'; $search[]='&Uuml;';
803
        $replace[]='ý'; $search[]='&yacute;';
804
        $replace[]='Ý'; $search[]='&Yacute;';
805
        $replace[]='ÿ'; $search[]='&yuml;';
806
        $replace[]='Ÿ'; $search[]='&Yuml;';
807
        $chaine    = str_replace($search, $replace, $chaine);
808
809
        return $chaine;
810
    }
811
812
    /**
813
     * Création d'une titre pour être utilisé par l'url rewriting
814
     *
815
     * @param string  $content  Le texte à utiliser pour créer l'url
816
     * @param integer $urw      La limite basse pour créer les mots
817
     * @return string Le texte à utiliser pour l'url
818
     *                          Note, some parts are from Solo's code
819
     */
820
    public static function makeSeoUrl($content, $urw = 1)
821
    {
822
        $s       = "ÀÁÂÃÄÅÒÓÔÕÖØÈÉÊËÇÌÍÎÏÙÚÛÜŸÑàáâãäåòóôõöøèéêëçìíîïùúûüÿñ '()";
823
        $r       = 'AAAAAAOOOOOOEEEECIIIIUUUUYNaaaaaaooooooeeeeciiiiuuuuyn----';
824
        $content = self::unhtml($content);    // First, remove html entities
825
        $content = strtr($content, $s, $r);
826
        $content = strip_tags($content);
827
        $content = strtolower($content);
828
        $content = htmlentities($content);    // TODO: Vérifier
829
        $content = preg_replace('/&([a-zA-Z])(uml|acute|grave|circ|tilde);/', '$1', $content);
830
        $content = html_entity_decode($content);
831
        $content = eregi_replace('quot', ' ', $content);
832
        $content = eregi_replace("'", ' ', $content);
833
        $content = eregi_replace('-', ' ', $content);
834
        $content = eregi_replace('[[:punct:]]', '', $content);
835
        // Selon option mais attention au fichier .htaccess !
836
        // $content = eregi_replace('[[:digit:]]','', $content);
837
        $content = preg_replace('/[^a-z|A-Z|0-9]/', '-', $content);
838
839
        $words    = explode(' ', $content);
840
        $keywords = '';
841
        foreach ($words as $word) {
842
            if (strlen($word) >= $urw) {
843
                $keywords .= '-' . trim($word);
844
            }
845
        }
846
        if (!$keywords) {
847
            $keywords = '-';
848
        }
849
        // Supprime les tirets en double
850
        $keywords = str_replace('---', '-', $keywords);
851
        $keywords = str_replace('--', '-', $keywords);
852
        // Supprime un éventuel tiret à la fin de la chaine
853
        if (substr($keywords, strlen($keywords) - 1, 1) == '-') {
854
            $keywords = substr($keywords, 0, strlen($keywords) - 1);
855
        }
856
857
        return $keywords;
858
    }
859
860
    /**
861
     * Create the meta keywords based on the content
862
     *
863
     * @param  string $content Content from which we have to create metakeywords
864
     * @return string The list of meta keywords
865
     */
866
    public static function createMetaKeywords($content)
867
    {
868
        $keywordscount = REFERENCES_METAGEN_MAX_KEYWORDS;
869
        $keywordsorder = REFERENCES_METAGEN_KEYWORDS_ORDER;
870
871
        $tmp = array();
872
        // Search for the "Minimum keyword length"
873
        // TODO: Remplacer references_keywords_limit par une constante
874
        if (isset($_SESSION['references_keywords_limit'])) {
875
            $limit = $_SESSION['references_keywords_limit'];
876
        } else {
877
            $config_handler                        = xoops_getHandler('config');
878
            $xoopsConfigSearch                     =& $config_handler->getConfigsByCat(XOOPS_CONF_SEARCH);
879
            $limit                                 = $xoopsConfigSearch['keyword_min'];
880
            $_SESSION['references_keywords_limit'] = $limit;
881
        }
882
        $myts            = MyTextSanitizer::getInstance();
883
        $content         = str_replace('<br>', ' ', $content);
884
        $content         = $myts->undoHtmlSpecialChars($content);
885
        $content         = strip_tags($content);
886
        $content         = strtolower($content);
887
        $search_pattern  = array('&nbsp;', "\t", "\r\n", "\r", "\n", ',', '.', "'", ';', ':', ')', '(', '"', '?', '!', '{', '}', '[', ']', '<', '>', '/', '+', '-', '_', '\\', '*');
888
        $replace_pattern = array(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '');
889
        $content         = str_replace($search_pattern, $replace_pattern, $content);
890
        $keywords        = explode(' ', $content);
891
        switch ($keywordsorder) {
892
            case 0:    // Ordre d'apparition dans le texte
893
                $keywords = array_unique($keywords);
894
                break;
895
            case 1:    // Ordre de fréquence des mots
896
                $keywords = array_count_values($keywords);
897
                asort($keywords);
898
                $keywords = array_keys($keywords);
899
                break;
900
            case 2:    // Ordre inverse de la fréquence des mots
901
                $keywords = array_count_values($keywords);
902
                arsort($keywords);
903
                $keywords = array_keys($keywords);
904
                break;
905
        }
906
        // Remove black listed words
907
        if (xoops_trim(self::getModuleOption('metagen_blacklist')) != '') {
908
            $metagen_blacklist = str_replace("\r", '', self::getModuleOption('metagen_blacklist'));
909
            $metablack         = explode("\n", $metagen_blacklist);
910
            array_walk($metablack, 'trim');
911
            $keywords = array_diff($keywords, $metablack);
912
        }
913
914
        foreach ($keywords as $keyword) {
915
            if (strlen($keyword) >= $limit && !is_numeric($keyword)) {
916
                $tmp[] = $keyword;
917
            }
918
        }
919
        $tmp = array_slice($tmp, 0, $keywordscount);
920
        if (count($tmp) > 0) {
921
            return implode(',', $tmp);
922
        } else {
923
            if (!isset($config_handler) || !is_object($config_handler)) {
924
                $config_handler = xoops_getHandler('config');
925
            }
926
            $xoopsConfigMetaFooter =& $config_handler->getConfigsByCat(XOOPS_CONF_METAFOOTER);
927
            if (isset($xoopsConfigMetaFooter['meta_keywords'])) {
928
                return $xoopsConfigMetaFooter['meta_keywords'];
929
            } else {
930
                return '';
931
            }
932
        }
933
    }
934
935
    /**
936
     * Fonction chargée de gérer l'upload
937
     *
938
     * @param integer $indice L'indice du fichier à télécharger
939
     * @param string  $dstpath
940
     * @param null    $mimeTypes
941
     * @param null    $uploadMaxSize
942
     * @param null    $maxWidth
943
     * @param null    $maxHeight
944
     * @return mixed True si l'upload s'est bien déroulé sinon le message d'erreur correspondant
945
     */
946
    public static function uploadFile($indice, $dstpath = XOOPS_UPLOAD_PATH, $mimeTypes = null, $uploadMaxSize = null, $maxWidth = null, $maxHeight = null)
947
    {
948
        require_once XOOPS_ROOT_PATH . '/class/uploader.php';
949
        global $destname;
950
        if (isset($_POST['xoops_upload_file'])) {
951
            require_once XOOPS_ROOT_PATH . '/class/uploader.php';
952
            $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...
953
            $fldname = $_FILES[$_POST['xoops_upload_file'][$indice]];
954
            $fldname = get_magic_quotes_gpc() ? stripslashes($fldname['name']) : $fldname['name'];
955
            if (xoops_trim($fldname != '')) {
956
                $destname = self::createUploadName($dstpath, $fldname, true);
957
                if ($mimeTypes === null) {
958
                    $permittedtypes = explode("\n", str_replace("\r", '', self::getModuleOption('mimetypes')));
959
                    array_walk($permittedtypes, 'trim');
960
                } else {
961
                    $permittedtypes = $mimeTypes;
962
                }
963
                if ($uploadMaxSize === null) {
964
                    $uploadSize = self::getModuleOption('maxuploadsize');
965
                } else {
966
                    $uploadSize = $uploadMaxSize;
967
                }
968
                $uploader = new XoopsMediaUploader($dstpath, $permittedtypes, $uploadSize, $maxWidth, $maxHeight);
969
                //$uploader->allowUnknownTypes = true;
970
                $uploader->setTargetFileName($destname);
971
                if ($uploader->fetchMedia($_POST['xoops_upload_file'][$indice])) {
972
                    if ($uploader->upload()) {
973
                        return true;
974
                    } else {
975
                        return _ERRORS . ' ' . htmlentities($uploader->getErrors());
976
                    }
977
                } else {
978
                    return htmlentities($uploader->getErrors());
979
                }
980
            } else {
981
                return false;
982
            }
983
        } else {
984
            return false;
985
        }
986
    }
987
988
    /**
989
     * Resize a Picture to some given dimensions (using the wideImage library)
990
     *
991
     * @param string  $src_path      Picture's source
992
     * @param string  $dst_path      Picture's destination
993
     * @param integer $param_width   Maximum picture's width
994
     * @param integer $param_height  Maximum picture's height
995
     * @param boolean $keep_original Do we have to keep the original picture ?
996
     * @param string  $fit           Resize mode (see the wideImage library for more information)
997
     * @return bool
998
     */
999
    public static function resizePicture($src_path, $dst_path, $param_width, $param_height, $keep_original = false, $fit = 'inside')
1000
    {
1001
        //        require_once self::MODULE_PATH . 'class/wideimage/WideImage.php';
1002
        $img    = WideImage::load($src_path);
1003
        $result = $img->resize($param_width, $param_height, $fit);
1004
        $result->saveToFile($dst_path, null);
1005
        if (!$keep_original) {
1006
            @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...
1007
        }
1008
1009
        return true;
1010
    }
1011
1012
    /**
1013
     * Déclenchement d'une alerte Xoops suite à un évènement
1014
     *
1015
     * @param string       $category La catégorie de l'évènement
1016
     * @param integer      $itemId   L'ID de l'élément (trop général pour être décris précisément)
1017
     * @param unknown_type $event    L'évènement qui est déclencé
1018
     * @param unknown_type $tags     Les variables à passer au template
1019
     */
1020
    public static function notify($category, $itemId, $event, $tags)
1021
    {
1022
        $notification_handler = xoops_getHandler('notification');
1023
        $tags['X_MODULE_URL'] = REFERENCES_URL;
1024
        $notification_handler->triggerEvent($category, $itemId, $event, $tags);
1025
    }
1026
1027
    /**
1028
     * Ajoute des jours à une date et retourne la nouvelle date au format Date de Mysql
1029
     *
1030
     * @param int     $duration
1031
     * @param integer $startingDate Date de départ (timestamp)
1032
     * @return bool|string
1033
     * @internal param int $durations Durée en jours
1034
     */
1035
    public static function addDaysToDate($duration = 1, $startingDate = 0)
1036
    {
1037
        if ($startingDate == 0) {
1038
            $startingDate = time();
1039
        }
1040
        $endingDate = $startingDate + ($duration * 86400);
1041
1042
        return date('Y-m-d', $endingDate);
1043
    }
1044
1045
    /**
1046
     * Retourne un breadcrumb en fonction des paramètres passés et en partant (d'office) de la racine du module
1047
     *
1048
     * @param array  $path  Le chemin complet (excepté la racine) du breadcrumb sous la forme clé=url valeur=titre
1049
     * @param string $raquo Le séparateur par défaut à utiliser
1050
     * @return string le breadcrumb
1051
     */
1052
    public static function breadcrumb($path, $raquo = ' &raquo; ')
1053
    {
1054
        $breadcrumb        = '';
1055
        $workingBreadcrumb = array();
1056
        if (is_array($path)) {
1057
            $moduleName          = self::getModuleName();
1058
            $workingBreadcrumb[] = "<a href='" . REFERENCES_URL . "' title='" . self::makeHrefTitle($moduleName) . "'>" . $moduleName . '</a>';
1059
            foreach ($path as $url => $title) {
1060
                $workingBreadcrumb[] = "<a href='" . $url . "'>" . $title . '</a>';
1061
            }
1062
            $cnt = count($workingBreadcrumb);
1063
            for ($i = 0; $i < $cnt; ++$i) {
1064
                if ($i == $cnt - 1) {
1065
                    $workingBreadcrumb[$i] = strip_tags($workingBreadcrumb[$i]);
1066
                }
1067
            }
1068
            $breadcrumb = implode($raquo, $workingBreadcrumb);
1069
        }
1070
1071
        return $breadcrumb;
1072
    }
1073
1074
    public static function close_tags($string)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
1075
    {
1076
        // match opened tags
1077
        if (preg_match_all('/<([a-z\:\-]+)[^\/]>/', $string, $start_tags)) {
1078
            $start_tags = $start_tags[1];
1079
1080
            // match closed tags
1081
            if (preg_match_all('/<\/([a-z]+)>/', $string, $end_tags)) {
1082
                $complete_tags = array();
1083
                $end_tags      = $end_tags[1];
1084
1085
                foreach ($start_tags as $key => $val) {
1086
                    $posb = array_search($val, $end_tags);
1087
                    if (is_int($posb)) {
1088
                        unset($end_tags[$posb]);
1089
                    } else {
1090
                        $complete_tags[] = $val;
1091
                    }
1092
                }
1093
            } else {
1094
                $complete_tags = $start_tags;
1095
            }
1096
1097
            $complete_tags = array_reverse($complete_tags);
1098
            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...
1099
                $string .= '</' . $complete_tags[$i] . '>';
1100
            }
1101
        }
1102
1103
        return $string;
1104
    }
1105
1106
    public static function truncate_tagsafe($string, $length = 80, $etc = '...', $break_words = false)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
1107
    {
1108
        if ($length == 0) {
1109
            return '';
1110
        }
1111
1112
        if (strlen($string) > $length) {
1113
            $length -= strlen($etc);
1114
            if (!$break_words) {
1115
                $string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length + 1));
1116
                $string = preg_replace('/<[^>]*$/', '', $string);
1117
                $string = self::close_tags($string);
1118
            }
1119
1120
            return $string . $etc;
1121
        } else {
1122
            return $string;
1123
        }
1124
    }
1125
1126
    /**
1127
     * Create an infotip
1128
     * @param $text
1129
     * @return string
1130
     */
1131
    public static function makeInfotips($text)
1132
    {
1133
        $ret      = '';
1134
        $infotips = self::getModuleOption('infotips');
1135
        if ($infotips > 0) {
1136
            $myts = MyTextSanitizer::getInstance();
1137
            $ret  = $myts->htmlSpecialChars(substr(strip_tags($text), 0, $infotips));
1138
        }
1139
1140
        return $ret;
1141
    }
1142
1143
    /**
1144
     * Retourne le type Mime d'un fichier en utilisant d'abord finfo puis mime_content
1145
     *
1146
     * @param string $filename Le fichier (avec son chemin d'accès complet) dont on veut connaître le type mime
1147
     * @return string
1148
     */
1149
    public static function getMimeType($filename)
1150
    {
1151
        if (function_exists('finfo_open')) {
1152
            $pathToMagic = REFERENCES_PATH . 'mime/magic';
1153
            $finfo       = new finfo(FILEINFO_MIME, $pathToMagic);
1154
            $mimetype    = $finfo->file($filename);
1155
            finfo_close($finfo);
1156
            unset($finfo);
1157
1158
            return $mimetype;
1159
        } else {
1160
            if (function_exists('mime_content_type')) {
1161
                return mime_content_type($filename);
1162
            } else {
1163
                return '';
1164
            }
1165
        }
1166
    }
1167
1168
    /**
1169
     * Retourne une liste d'objets XoopsUsers à partir d'une liste d'identifiants
1170
     *
1171
     * @param  array $xoopsUsersIDs La liste des ID
1172
     * @return array Les objets XoopsUsers
1173
     */
1174
    public static function getUsersFromIds($xoopsUsersIDs)
1175
    {
1176
        $users = array();
1177
        if (is_array($xoopsUsersIDs) && count($xoopsUsersIDs) > 0) {
1178
            $xoopsUsersIDs = array_unique($xoopsUsersIDs);
1179
            sort($xoopsUsersIDs);
1180
            if (count($xoopsUsersIDs) > 0) {
1181
                $member_handler = xoops_getHandler('user');
1182
                $criteria       = new Criteria('uid', '(' . implode(',', $xoopsUsersIDs) . ')', 'IN');
1183
                $criteria->setSort('uid');
1184
                $users = $member_handler->getObjects($criteria, true);
1185
            }
1186
        }
1187
1188
        return $users;
1189
    }
1190
1191
    /**
1192
     * Retourne l'ID de l'utilisateur courant (s'il est connecté)
1193
     * @return integer L'uid ou 0
1194
     */
1195
    public static function getCurrentUserID()
1196
    {
1197
        global $xoopsUser;
1198
        $uid = is_object($xoopsUser) ? $xoopsUser->getVar('uid') : 0;
1199
1200
        return $uid;
1201
    }
1202
1203
    /**
1204
     * Retourne la liste des groupes de l'utilisateur courant (avec cache)
1205
     * @param int $uid
1206
     * @return array Les ID des groupes auquel l'utilisateur courant appartient
1207
     */
1208
    public static function getMemberGroups($uid = 0)
1209
    {
1210
        static $buffer = array();
1211
        if ($uid == 0) {
1212
            $uid = self::getCurrentUserID();
1213
        }
1214
1215
        if (is_array($buffer) && count($buffer) > 0 && isset($buffer[$uid])) {
1216
            return $buffer[$uid];
1217
        } else {
1218
            if ($uid > 0) {
1219
                $member_handler = xoops_getHandler('member');
1220
                $buffer[$uid]   = $member_handler->getGroupsByUser($uid, false);    // Renvoie un tableau d'ID (de groupes)
1221
            } else {
1222
                $buffer[$uid] = array(XOOPS_GROUP_ANONYMOUS);
1223
            }
1224
        }
1225
1226
        return $buffer[$uid];
1227
    }
1228
1229
    /**
1230
     * Indique si l'utilisateur courant fait partie d'une groupe donné (avec gestion de cache)
1231
     *
1232
     * @param integer $group Groupe recherché
1233
     * @param int     $uid
1234
     * @return bool vrai si l'utilisateur fait partie du groupe, faux sinon
1235
     */
1236
    public static function isMemberOfGroup($group = 0, $uid = 0)
1237
    {
1238
        static $buffer = array();
1239
        $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...
1240
        if ($uid == 0) {
1241
            $uid = self::getCurrentUserID();
1242
        }
1243
        if (is_array($buffer) && array_key_exists($group, $buffer)) {
1244
            $retval = $buffer[$group];
1245
        } else {
1246
            $member_handler = xoops_getHandler('member');
1247
            $groups         = $member_handler->getGroupsByUser($uid, false);    // Renvoie un tableau d'ID (de groupes)
1248
            $retval         = in_array($group, $groups);
1249
            $buffer[$group] = $retval;
1250
        }
1251
1252
        return $retval;
1253
    }
1254
1255
    /**
1256
     * Indique si un utilisateur fait partie de plusieurs groupes
1257
     * La fonction renvoie vrai dès qu'on trouve que le membre fait partir d'un des groupes
1258
     * @param array    $groups La liste des groupes à vérifier
1259
     * @param  integer $uid    L'ID de l'utilisateur
1260
     * @return boolean
1261
     */
1262
    public static function isMemberOfGroups($groups, $uid = 0)
1263
    {
1264
        if (count($groups) == 0) {
1265
            return false;
1266
        }
1267
        if ($uid == 0) {
1268
            $uid = self::getCurrentUserID();
1269
        }
1270
        foreach ($groups as $groupId) {
1271
            if (self::isMemberOfGroup($groupId, $uid)) {
1272
                return true;
1273
            }
1274
        }
1275
1276
        return false;
1277
    }
1278
1279
    /**
1280
     * Retourne le nombre total de groupes (y compris les anonymes)
1281
     */
1282
    public static function getGroupsCount()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
1283
    {
1284
        static $cache = -1;
1285
        if ($cache == -1) {
1286
            global $xoopsDB;
1287
            $sql    = 'SELECT COUNT(*) FROM ' . $xoopsDB->prefix('groups');
1288
            $result = $xoopsDB->query($sql);
1289
            if (!$result) {
1290
                return false;
1291
            }
1292
            list($cache) = $xoopsDB->fetchRow($result);
1293
        }
1294
1295
        return $cache;
1296
    }
1297
1298
    /**
1299
     * Fonction chargée de vérifier qu'un répertoire existe, qu'on peut écrire dedans et création d'un fichier index.html
1300
     *
1301
     * @param string $folder Le chemin complet du répertoire à vérifier
1302
     * @return void
1303
     */
1304
    public static function prepareFolder($folder)
1305
    {
1306
        if (!is_dir($folder)) {
1307
            mkdir($folder, 0777);
1308
            file_put_contents($folder . '/index.html', '<script>history.go(-1);</script>');
1309
        } else {
1310
            if (!is_writable($folder)) {
1311
                chmod($folder, 0777);
1312
            }
1313
        }
1314
    }
1315
1316
    /**
1317
     * Load a language file
1318
     *
1319
     * @param string $languageFile     The required language file
1320
     * @param string $defaultExtension Default extension to use
1321
     */
1322
    public static function loadLanguageFile($languageFile, $defaultExtension = '.php')
1323
    {
1324
        global $xoopsConfig;
1325
        $root = self::MODULE_PATH;
1326
        if (strstr($languageFile, $defaultExtension) === false) {
1327
            $languageFile .= $defaultExtension;
1328
        }
1329
        if (file_exists($root . 'language' . DIRECTORY_SEPARATOR . $xoopsConfig['language'] . DIRECTORY_SEPARATOR . $languageFile)) {
1330
            require_once $root . 'language' . DIRECTORY_SEPARATOR . $xoopsConfig['language'] . DIRECTORY_SEPARATOR . $languageFile;
1331
        } else {    // Fallback
1332
            require_once $root . 'language' . DIRECTORY_SEPARATOR . 'english' . DIRECTORY_SEPARATOR . $languageFile;
1333
        }
1334
    }
1335
1336
    /**
1337
     * Création d'une vignette en tenant compte des options du module concernant le mode de création des vignettes
1338
     *
1339
     * @param  string  $src_path
1340
     * @param  string  $dst_path
1341
     * @param  integer $param_width
1342
     * @param  integer $param_height
1343
     * @param  boolean $keep_original
1344
     * @param string   $fit Utilisé uniquement pour la méthode 0 (redimensionnement)
1345
     * @return boolean
1346
     */
1347
    public static function createThumb($src_path, $dst_path, $param_width, $param_height, $keep_original = false, $fit = 'inside')
1348
    {
1349
        //        require_once self::MODULE_PATH . 'class/wideimage/WideImage.php';
1350
        $resize = true;
1351
        // On commence par vérifier que l'image originale n'est pas plus petite que les dimensions demandées auquel cas il n'y a rien à faire
1352
        $pictureDimensions = getimagesize($src_path);
1353
        if (is_array($pictureDimensions)) {
1354
            $pictureWidth  = $pictureDimensions[0];
1355
            $pictureHeight = $pictureDimensions[1];
1356
            if ($pictureWidth < $param_width && $pictureHeight < $param_height) {
1357
                $resize = false;
1358
            }
1359
        }
1360
        $img = WideImage::load($src_path);
1361
        if ($resize) { // L'image est suffisament grande pour être réduite
1362
            $thumbMethod = 0;
1363
            if ($thumbMethod == 0) { // Redimensionnement de l'image
1364
                $result = $img->resize($param_width, $param_height, $fit);
1365
            } else { // Récupération d'une partie de l'image depuis le centre
1366
                // Calcul de left et top
1367
                $left = $top = 0;
1368
                if (is_array($pictureDimensions)) {
1369
                    if ($pictureWidth > $param_width) {
1370
                        $left = (int)(($pictureWidth / 2) - ($param_width / 2));
0 ignored issues
show
Bug introduced by
The variable $pictureWidth 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...
1371
                    }
1372
                    if ($pictureHeight > $param_height) {
1373
                        $top = (int)(($pictureHeight / 2) - ($param_height / 2));
0 ignored issues
show
Bug introduced by
The variable $pictureHeight 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...
1374
                    }
1375
                }
1376
                $result = $img->crop($left, $top, $param_width, $param_height);
1377
            }
1378
            $result->saveToFile($dst_path, null);
1379
        } else {
1380
            if ($src_path != $dst_path) {
1381
                @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...
1382
            }
1383
        }
1384
        if (!$keep_original) {
1385
            @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...
1386
        }
1387
1388
        return true;
1389
    }
1390
1391
    /**
1392
     * Create the <option> of an html select
1393
     *
1394
     * @param  array $array   Array of index and labels
1395
     * @param  mixed $default the default value
1396
     * @param bool   $withNull
1397
     * @return string
1398
     */
1399
    private static function htmlSelectOptions($array, $default = 0, $withNull = true)
1400
    {
1401
        $ret      = array();
1402
        $selected = '';
1403
        if ($withNull) {
1404
            if (!is_array($default)) {
1405
                if ($default === 0) {
1406
                    $selected = " selected = 'selected'";
1407
                }
1408
            } else {
1409
                if (in_array(0, $default)) {
1410
                    $selected = " selected = 'selected'";
1411
                }
1412
            }
1413
            $ret[] = '<option value=0' . $selected . '>---</option>';
1414
        }
1415
1416
        foreach ($array as $index => $label) {
1417
            $selected = '';
1418
            if (!is_array($default)) {
1419
                if ($index == $default) {
1420
                    $selected = " selected = 'selected'";
1421
                }
1422
            } else {
1423
                if (in_array($index, $default)) {
1424
                    $selected = " selected = 'selected'";
1425
                }
1426
            }
1427
            $ret[] = "<option value=\"" . $index . "\"" . $selected . '>' . $label . '</option>';
1428
        }
1429
1430
        return implode("\n", $ret);
1431
    }
1432
1433
    /**
1434
     * Creates an html select an returns its code
1435
     *
1436
     * @param  string  $selectName Select's name
1437
     * @param  array   $array      Key = value of each option, value = label of each option
1438
     * @param  mixed   $default    Default's value
1439
     * @param  boolean $withNull   Do we want a null option
1440
     * @param  string  $style      Is there a style to apply ?
1441
     * @param  boolean $multiple   Can we select multiple elements ?
1442
     * @param  integer $size       Size of the selectbox, only used with multiple selectboxes
1443
     * @param string   $extra
1444
     * @return string
1445
     */
1446
    public static function htmlSelect($selectName, $array, $default, $withNull = true, $style = '', $multiple = false, $size = 1, $extra = '')
1447
    {
1448
        $ret = '';
1449
        $ret .= "<select name='" . $selectName . "' id='" . $selectName . "'";
1450
        if (xoops_trim($style) != '') {
1451
            $ret .= " style='" . $style . "' ";
1452
        }
1453
        if (xoops_trim($multiple) != '') {
1454
            $ret .= " multiple = 'multiple' size='" . $size . "' ";
1455
        }
1456
        $ret .= $extra . ">\n";
1457
        $ret .= self::htmlSelectOptions($array, $default, $withNull);
1458
        $ret .= "</select>\n";
1459
1460
        return $ret;
1461
    }
1462
1463
    /**
1464
     * Verify that a mysql table exists
1465
     * @param $tablename
1466
     * @return bool
1467
     */
1468
    public static function tableExists($tablename)
1469
    {
1470
        global $xoopsDB;
1471
        $result = $xoopsDB->queryF("SHOW TABLES LIKE '$tablename'");
1472
1473
        return ($xoopsDB->getRowsNum($result) > 0);
1474
    }
1475
1476
    /**
1477
     * Verify that a field exists inside a mysql table
1478
     * @param $fieldname
1479
     * @param $table
1480
     * @return bool
1481
     */
1482
    public static function fieldExists($fieldname, $table)
1483
    {
1484
        global $xoopsDB;
1485
        $result = $xoopsDB->queryF("SHOW COLUMNS FROM $table LIKE '$fieldname'");
1486
1487
        return ($xoopsDB->getRowsNum($result) > 0);
1488
    }
1489
1490
    /**
1491
     * Retourne la définition d'un champ
1492
     *
1493
     * @param  string $fieldname
1494
     * @param  string $table
1495
     * @return array
1496
     */
1497
    public static function getFieldDefinition($fieldname, $table)
1498
    {
1499
        global $xoopsDB;
1500
        $result = $xoopsDB->queryF("SHOW COLUMNS FROM $table LIKE '$fieldname'");
1501
        if ($result) {
1502
            return $xoopsDB->fetchArray($result);
1503
        }
1504
1505
        return '';
0 ignored issues
show
Bug Best Practice introduced by
The return type of return ''; (string) is incompatible with the return type documented by references_utils::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...
1506
    }
1507
1508
    /**
1509
     * Add a field to a mysql table
1510
     * @param $field
1511
     * @param $table
1512
     * @return resource
1513
     */
1514
    public static function addField($field, $table)
1515
    {
1516
        global $xoopsDB;
1517
        $result = $xoopsDB->queryF("ALTER TABLE $table ADD $field;");
1518
1519
        return $result;
1520
    }
1521
1522
    /**
1523
     * Maintenance des tables du module et de son cache de requêtes
1524
     *
1525
     * @return void
1526
     */
1527
    public static function maintainTablesCache()
1528
    {
1529
        global $xoopsDB;
1530
        define('REFERENCES_MAINTAIN', true);
1531
        require self::MODULE_PATH . 'xoops_version.php';
1532
        $tables = array();
1533
        foreach ($modversion['tables'] as $table) {
0 ignored issues
show
Bug introduced by
The variable $modversion does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1534
            $tables[] = $xoopsDB->prefix($table);
1535
        }
1536
        if (count($tables) > 0) {
1537
            $list = implode(',', $tables);
1538
            $xoopsDB->queryF('CHECK TABLE ' . $list);
1539
            $xoopsDB->queryF('ANALYZE TABLE ' . $list);
1540
            $xoopsDB->queryF('OPTIMIZE TABLE ' . $list);
1541
        }
1542
        self::updateCache();
1543
        $handlers = references_handler::getInstance();
1544
        $handlers->h_references_articles->forceCacheClean();
1545
    }
1546
1547
    /**
1548
     * Indique si le module Tag existe et est activé
1549
     *
1550
     * @return boolean
1551
     * @credit: smartfactory
1552
     */
1553
    public static function tagModuleExists()
1554
    {
1555
        static $moduleExistsAndIsActive;
1556
        if (!isset($moduleExistsAndIsActive)) {
1557
            $modules_handler = xoops_getHandler('module');
1558
            $tagModule       = $modules_handler->getByDirName('tag');
1559
            if (!$tagModule) {
1560
                $moduleExistsAndIsActive = false;
1561
            } else {
1562
                $moduleExistsAndIsActive = $tagModule->getVar('isactive') == 1;
1563
            }
1564
        }
1565
1566
        return $moduleExistsAndIsActive;
1567
    }
1568
}
1569