Issues (608)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

class/Utility.php (1 issue)

1
<?php
2
3
namespace XoopsModules\Oledrion;
4
5
/*
6
 You may not change or alter any portion of this comment or credits
7
 of supporting developers from this source code or any supporting source code
8
 which is considered copyrighted (c) material of the original comment or credit authors.
9
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
15
/**
16
 * oledrion
17
 *
18
 * @copyright   {@link https://xoops.org/ XOOPS Project}
19
 * @license     {@link http://www.fsf.org/copyleft/gpl.html GNU public license}
20
 * @author      Hervé Thouzard (http://www.herve-thouzard.com/)
21
 */
22
23
/**
24
 * A set of useful and common functions
25
 *
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
use WideImage\WideImage;
33
use Xmf\Request;
34
use XoopsModules\Oledrion;
35
36
// defined('XOOPS_ROOT_PATH') || die('Restricted access');
37
38
/**
39
 * Class Oledrion\Utility
40
 */
41
class Utility extends \XoopsObject
42
{
43
    const MODULE_NAME = 'oledrion';
44
45
    use Common\VersionChecks; //checkVerXoops, checkVerPhp Traits
46
47
    use Common\ServerStats; // getServerStats Trait
48
49
    use Common\FilesManagement; // Files Management Trait
50
51
    //--------------- Custom module methods -----------------------------
52
53
    /**
54
     * Access the only instance of this class
55
     *
56
     * @return Oledrion\Utility
57
     *
58
     * @static
59
     * @staticvar   object
60
     */
61
    public static function getInstance()
62
    {
63
        static $instance;
64
        if (null === $instance) {
65
            $instance = new static();
66
        }
67
68
        return $instance;
69
    }
70
71
    /**
72
     * Returns a module's option (with cache)
73
     *
74
     * @param  string $option    module option's name
75
     * @param  bool   $withCache Do we have to use some cache ?
76
     * @return mixed   option's value
77
     */
78
    public static function getModuleOption($option, $withCache = true)
79
    {
80
        global $xoopsModuleConfig, $xoopsModule;
81
        $repmodule = static::MODULE_NAME;
82
        static $options = [];
83
        if (is_array($options) && array_key_exists($option, $options) && $withCache) {
84
            return $options[$option];
85
        }
86
87
        $retval = null;
88
        if (null !== $xoopsModuleConfig && (is_object($xoopsModule) && $xoopsModule->getVar('dirname') == $repmodule && $xoopsModule->getVar('isactive'))) {
89
            if (isset($xoopsModuleConfig[$option])) {
90
                $retval = $xoopsModuleConfig[$option];
91
            }
92
        } else {
93
            /** @var \XoopsModuleHandler $moduleHandler */
94
            $moduleHandler = xoops_getHandler('module');
95
            $module        = $moduleHandler->getByDirname($repmodule);
96
            $configHandler = xoops_getHandler('config');
97
            if ($module) {
98
                $moduleConfig = $configHandler->getConfigsByCat(0, $module->getVar('mid'));
99
                if (isset($moduleConfig[$option])) {
100
                    $retval = $moduleConfig[$option];
101
                }
102
            }
103
        }
104
        $options[$option] = $retval;
105
106
        return $retval;
107
    }
108
109
    /**
110
     * Is Xoops 2.3.x ?
111
     *
112
     * @return bool
113
     */
114
    public static function isX23()
115
    {
116
        $x23 = false;
117
        $xv  = str_replace('XOOPS ', '', XOOPS_VERSION);
118
        if ((int)mb_substr($xv, 2, 1) >= 3) {
119
            $x23 = true;
120
        }
121
122
        return $x23;
123
    }
124
125
    /**
126
     * Is Xoops 2.0.x ?
127
     *
128
     * @return bool
129
     */
130
    public static function isX20()
131
    {
132
        $x20 = false;
133
        $xv  = str_replace('XOOPS ', '', XOOPS_VERSION);
134
        if ('0' == mb_substr($xv, 2, 1)) {
135
            $x20 = true;
136
        }
137
138
        return $x20;
139
    }
140
141
    /**
142
     * Retreive an editor according to the module's option "form_options"
143
     *
144
     * @param  string $caption Caption to give to the editor
145
     * @param  string $name    Editor's name
146
     * @param  string $value   Editor's value
147
     * @param  string $width   Editor's width
148
     * @param  string $height  Editor's height
149
     * @param  string $supplemental
150
     * @return bool|\XoopsFormEditor The editor to use
151
     */
152
    public static function getWysiwygForm(
153
        $caption,
154
        $name,
155
        $value = '',
156
        $width = '100%',
157
        $height = '400px',
158
        $supplemental = '')
159
    {
160
        /** @var Oledrion\Helper $helper */
161
        $helper                   = Oledrion\Helper::getInstance();
162
        $editor                   = false;
163
        $editor_configs           = [];
164
        $editor_configs['name']   = $name;
165
        $editor_configs['value']  = $value;
166
        $editor_configs['rows']   = 35;
167
        $editor_configs['cols']   = 60;
168
        $editor_configs['width']  = '100%';
169
        $editor_configs['height'] = '400px';
170
171
        $editor_option = mb_strtolower(static::getModuleOption('editorAdmin'));
172
        //        $editor = new \XoopsFormEditor($caption, $editor_option, $editor_configs);
173
        //        public function __construct($caption, $name, $configs = null, $nohtml = false, $OnFailure = '')
174
175
        if ($helper->isUserAdmin()) {
176
            $editor = new \XoopsFormEditor($caption, $helper->getConfig('editorAdmin'), $editor_configs, $nohtml = false, $onfailure = 'textarea');
177
        } else {
178
            $editor = new \XoopsFormEditor($caption, $helper->getConfig('editorUser'), $editor_configs, $nohtml = false, $onfailure = 'textarea');
179
        }
180
181
        return $editor;
182
    }
183
184
    /**
185
     * Create (in a link) a javascript confirmation's box
186
     *
187
     * @param  string $message Message to display
188
     * @param  bool   $form    Is this a confirmation for a form ?
189
     * @return string  the javascript code to insert in the link (or in the form)
190
     */
191
    public static function javascriptLinkConfirm($message, $form = false)
192
    {
193
        if (!$form) {
194
            return "onclick=\"javascript:return confirm('" . str_replace("'", ' ', $message) . "')\"";
195
        }
196
197
        return "onSubmit=\"javascript:return confirm('" . str_replace("'", ' ', $message) . "')\"";
198
    }
199
200
    /**
201
     * Get current user IP
202
     *
203
     * @return string IP address (format Ipv4)
204
     */
205
    public static function IP()
206
    {
207
        $proxy_ip = '';
208
        if (\Xmf\Request::hasVar('HTTP_X_FORWARDED_FOR', 'SERVER')) {
209
            $proxy_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
210
        } elseif (!empty($_SERVER['HTTP_X_FORWARDED'])) {
211
            $proxy_ip = $_SERVER['HTTP_X_FORWARDED'];
212
        } elseif (!empty($_SERVER['HTTP_FORWARDED_FOR'])) {
213
            $proxy_ip = $_SERVER['HTTP_FORWARDED_FOR'];
214
        } elseif (!empty($_SERVER['HTTP_FORWARDED'])) {
215
            $proxy_ip = $_SERVER['HTTP_FORWARDED'];
216
        } elseif (!empty($_SERVER['HTTP_VIA'])) {
217
            $proxy_ip = $_SERVER['HTTP_VIA'];
218
        } elseif (!empty($_SERVER['HTTP_X_COMING_FROM'])) {
219
            $proxy_ip = $_SERVER['HTTP_X_COMING_FROM'];
220
        } elseif (!empty($_SERVER['HTTP_COMING_FROM'])) {
221
            $proxy_ip = $_SERVER['HTTP_COMING_FROM'];
222
        }
223
        $regs = [];
224
        //if (!empty($proxy_ip) && $is_ip = ereg('^([0-9]{1,3}\.){3,3}[0-9]{1,3}', $proxy_ip, $regs) && count($regs) > 0) {
225
        if (!empty($proxy_ip) && filter_var($proxy_ip, FILTER_VALIDATE_IP) && count($regs) > 0) {
226
            $the_IP = $regs[0];
227
        } else {
228
            $the_IP = $_SERVER['REMOTE_ADDR'];
229
        }
230
231
        return $the_IP;
232
    }
233
234
    /**
235
     * Set the page's title, meta description and meta keywords
236
     * Datas are supposed to be sanitized
237
     *
238
     * @param  string $pageTitle       Page's Title
239
     * @param  string $metaDescription Page's meta description
240
     * @param  string $metaKeywords    Page's meta keywords
241
     */
242
    public static function setMetas($pageTitle = '', $metaDescription = '', $metaKeywords = '')
243
    {
244
        global $xoTheme, $xoTheme, $xoopsTpl;
245
        $xoopsTpl->assign('xoops_pagetitle', $pageTitle);
246
        if (null !== $xoTheme && is_object($xoTheme)) {
247
            if (!empty($metaKeywords)) {
248
                $xoTheme->addMeta('meta', 'keywords', $metaKeywords);
249
            }
250
            if (!empty($metaDescription)) {
251
                $xoTheme->addMeta('meta', 'description', $metaDescription);
252
            }
253
        } elseif (null !== $xoopsTpl && is_object($xoopsTpl)) {
254
            // Compatibility for old Xoops versions
255
            if (!empty($metaKeywords)) {
256
                $xoopsTpl->assign('xoops_meta_keywords', $metaKeywords);
257
            }
258
            if (!empty($metaDescription)) {
259
                $xoopsTpl->assign('xoops_meta_description', $metaDescription);
260
            }
261
        }
262
    }
263
264
    /**
265
     * Send an email from a template to a list of recipients
266
     *
267
     * @param         $tplName
268
     * @param  array  $recipients List of recipients
269
     * @param  string $subject    Email's subject
270
     * @param  array  $variables  Varirables to give to the template
271
     * @return bool   Result of the send
272
     * @internal param string $tpl_name Template's name
273
     */
274
    public static function sendEmailFromTpl($tplName, $recipients, $subject, $variables)
275
    {
276
        global $xoopsConfig;
277
        require_once XOOPS_ROOT_PATH . '/class/xoopsmailer.php';
278
        if (!is_array($recipients)) {
279
            if ('' === trim($recipients)) {
280
                return false;
281
            }
282
        } else {
283
            if (0 === count($recipients)) {
284
                return false;
285
            }
286
        }
287
        if (function_exists('xoops_getMailer')) {
288
            $xoopsMailer = xoops_getMailer();
289
        } else {
290
            $xoopsMailer = xoops_getMailer();
291
        }
292
293
        $xoopsMailer->useMail();
294
        $templateDir = XOOPS_ROOT_PATH . '/modules/' . static::MODULE_NAME . '/language/' . $xoopsConfig['language'] . '/mail_template';
295
        if (!is_dir($templateDir)) {
296
            $templateDir = XOOPS_ROOT_PATH . '/modules/' . static::MODULE_NAME . '/language/english/mail_template';
297
        }
298
        $xoopsMailer->setTemplateDir($templateDir);
299
        $xoopsMailer->setTemplate($tplName);
300
        $xoopsMailer->setToEmails($recipients);
301
        // TODO: Change !
302
        // $xoopsMailer->setFromEmail('[email protected]');
303
        //$xoopsMailer->setFromName('MonSite');
304
        $xoopsMailer->setSubject($subject);
305
        foreach ($variables as $key => $value) {
306
            $xoopsMailer->assign($key, $value);
307
        }
308
        $res = $xoopsMailer->send();
309
        unset($xoopsMailer);
310
        // B.R. $filename = XOOPS_UPLOAD_PATH . '/logmail_' . static::MODULE_NAME . '.php';
311
        $filename = OLEDRION_UPLOAD_PATH . '/logmail_' . static::MODULE_NAME . '.php';
312
        if (!file_exists($filename)) {
313
            $fp = @fopen($filename, 'ab');
314
            if ($fp) {
315
                fwrite($fp, "<?php exit(); ?>\n");
316
                fclose($fp);
317
            }
318
        }
319
        $fp = @fopen($filename, 'ab');
320
321
        if ($fp) {
322
            fwrite($fp, str_repeat('-', 120) . "\n");
323
            fwrite($fp, date('d/m/Y H:i:s') . "\n");
324
            fwrite($fp, 'Template name : ' . $tplName . "\n");
325
            fwrite($fp, 'Email subject : ' . $subject . "\n");
326
            if (is_array($recipients)) {
327
                fwrite($fp, 'Recipient(s) : ' . implode(',', $recipients) . "\n");
328
            } else {
329
                fwrite($fp, 'Recipient(s) : ' . $recipients . "\n");
330
            }
331
            fwrite($fp, 'Transmited variables : ' . implode(',', $variables) . "\n");
332
            fclose($fp);
333
        }
334
335
        return $res;
336
    }
337
338
    /**
339
     * Remove module's cache
340
     */
341
    public static function updateCache()
342
    {
343
        global $xoopsModule;
344
        $folder  = $xoopsModule->getVar('dirname');
345
        $tpllist = [];
346
        require_once XOOPS_ROOT_PATH . '/class/xoopsblock.php';
347
        require_once XOOPS_ROOT_PATH . '/class/template.php';
348
        /** @var \XoopsTplfileHandler $tplfileHandler */
349
        $tplfileHandler = xoops_getHandler('tplfile');
350
        $tpllist        = $tplfileHandler->find(null, null, null, $folder);
351
        xoops_template_clear_module_cache($xoopsModule->getVar('mid')); // Clear module's blocks cache
352
353
        /** @var \XoopsTplfile $onetemplate */
354
        foreach ($tpllist as $onetemplate) {
355
            // Remove cache for each page.
356
            if ('module' === $onetemplate->getVar('tpl_type')) {
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 = [];
359
                $files_del = glob(XOOPS_CACHE_PATH . '/*' . $onetemplate->getVar('tpl_file') . '*');
360
                if ($files_del && is_array($files_del)) {
361
                    foreach ($files_del as $one_file) {
362
                        if (is_file($one_file)) {
363
                            if (false === @unlink($one_file)) {
364
                                throw new \RuntimeException('The file ' . $one_file . ' could not be deleted.');
365
                            }
366
                        }
367
                    }
368
                }
369
            }
370
        }
371
    }
372
373
    /**
374
     * Redirect user with a message
375
     *
376
     * @param string $message message to display
377
     * @param string $url     The place where to go
378
     * @param mixed  $time
379
     */
380
    public static function redirect($message = '', $url = 'index.php', $time = 2)
381
    {
382
        redirect_header($url, $time, $message);
383
    }
384
385
    /**
386
     * Internal function used to get the handler of the current module
387
     *
388
     * @return \XoopsModule The module
389
     */
390
    protected static function _getModule()
391
    {
392
        static $mymodule;
393
        if (null === $mymodule) {
394
            global $xoopsModule;
395
            if (null !== $xoopsModule && is_object($xoopsModule) && OLEDRION_DIRNAME == $xoopsModule->getVar('dirname')) {
396
                $mymodule = $xoopsModule;
397
            } else {
398
                /** @var \XoopsModuleHandler $moduleHandler */
399
                $moduleHandler = xoops_getHandler('module');
400
                $mymodule      = $moduleHandler->getByDirname(OLEDRION_DIRNAME);
401
            }
402
        }
403
404
        return $mymodule;
405
    }
406
407
    /**
408
     * Returns the module's name (as defined by the user in the module manager) with cache
409
     * @return string Module's name
410
     */
411
    public static function getModuleName()
412
    {
413
        static $moduleName;
414
        if (null === $moduleName) {
415
            $mymodule   = static::_getModule();
416
            $moduleName = $mymodule->getVar('name');
417
        }
418
419
        return $moduleName;
420
    }
421
422
    /**
423
     * Create a title for the href tags inside html links
424
     *
425
     * @param  string $title Text to use
426
     * @return string Formated text
427
     */
428
    public static function makeHrefTitle($title)
429
    {
430
        $s = "\"'";
431
        $r = '  ';
432
433
        return strtr($title, $s, $r);
434
    }
435
436
    /**
437
     * Retourne la liste des utilisateurs appartenants à un groupe
438
     *
439
     * @param  int $groupId Searched group
440
     * @return array Array of XoopsUsers
441
     */
442
    public static function getUsersFromGroup($groupId)
443
    {
444
        $users = [];
445
        /** @var \XoopsMemberHandler $memberHandler */
446
        $memberHandler = xoops_getHandler('member');
447
        $users         = $memberHandler->getUsersByGroup($groupId, true);
448
449
        return $users;
450
    }
451
452
    /**
453
     * Retourne la liste des emails des utilisateurs membres d'un groupe
454
     *
455
     * @param $groupId
456
     * @return array Emails list
457
     * @internal param int $group_id Group's number
458
     */
459
    public static function getEmailsFromGroup($groupId)
460
    {
461
        $ret   = [];
462
        $users = static::getUsersFromGroup($groupId);
463
        foreach ($users as $user) {
464
            $ret[] = $user->getVar('email');
465
        }
466
467
        return $ret;
468
    }
469
470
    /**
471
     * Vérifie que l'utilisateur courant fait partie du groupe des administrateurs
472
     *
473
     * @return bool Admin or not
474
     */
475
    public static function isAdmin()
476
    {
477
        global $xoopsUser, $xoopsModule;
478
        if (is_object($xoopsUser)) {
479
            if (in_array(XOOPS_GROUP_ADMIN, $xoopsUser->getGroups())) {
480
                return true;
481
            }
482
483
            if (null !== $xoopsModule && $xoopsUser->isAdmin($xoopsModule->getVar('mid'))) {
484
                return true;
485
            }
486
        }
487
488
        return false;
489
    }
490
491
    /**
492
     * Returns the current date in the Mysql format
493
     *
494
     * @return string Date in the Mysql format
495
     */
496
    public static function getCurrentSQLDate()
497
    {
498
        return date('Y-m-d'); // 2007-05-02
499
    }
500
501
    /**
502
     * @return bool|string
503
     */
504
    public static function getCurrentSQLDateTime()
505
    {
506
        return date('Y-m-d H:i:s'); // 2007-05-02
507
    }
508
509
    /**
510
     * Convert a Mysql date to the human's format
511
     *
512
     * @param  string $date The date to convert
513
     * @param  string $format
514
     * @return string The date in a human form
515
     */
516
    public static function SQLDateToHuman($date, $format = 'l')
517
    {
518
        if ('0000-00-00' !== $date && '' !== xoops_trim($date)) {
519
            return formatTimestamp(strtotime($date), $format);
520
        }
521
522
        return '';
523
    }
524
525
    /**
526
     * Convert a timestamp to a Mysql date
527
     *
528
     * @param int $timestamp The timestamp to use
529
     * @return string  The date in the Mysql format
530
     */
531
    public static function timestampToMysqlDate($timestamp)
532
    {
533
        return date('Y-m-d', (int)$timestamp);
534
    }
535
536
    /**
537
     * Conversion d'un dateTime Mysql en date lisible en français
538
     * @param $dateTime
539
     * @return bool|string
540
     */
541
    public static function sqlDateTimeToFrench($dateTime)
542
    {
543
        return date('d/m/Y H:i:s', strtotime($dateTime));
544
    }
545
546
    /**
547
     * Convert a timestamp to a Mysql datetime form
548
     * @param int $timestamp The timestamp to use
549
     * @return string  The date and time in the Mysql format
550
     */
551
    public static function timestampToMysqlDateTime($timestamp)
552
    {
553
        return date('Y-m-d H:i:s', $timestamp);
554
    }
555
556
    /**
557
     * This function indicates if the current Xoops version needs to add asterisks to required fields in forms
558
     *
559
     * @return bool Yes = we need to add them, false = no
560
     */
561
    public static function needsAsterisk()
562
    {
563
        if (static::isX23()) {
564
            return false;
565
        }
566
        if (false !== mb_stripos(XOOPS_VERSION, 'impresscms')) {
567
            return false;
568
        }
569
        if (false === mb_stripos(XOOPS_VERSION, 'legacy')) {
570
            $xv = xoops_trim(str_replace('XOOPS ', '', XOOPS_VERSION));
571
            if ((int)mb_substr($xv, 4, 2) >= 17) {
572
                return false;
573
            }
574
        }
575
576
        return true;
577
    }
578
579
    /**
580
     * Mark the mandatory fields of a form with a star
581
     *
582
     * @param  \XoopsForm $sform The form to modify
583
     * @return \XoopsForm The modified form
584
     * @internal param string $character The character to use to mark fields
585
     */
586
    public static function &formMarkRequiredFields(&$sform)
587
    {
588
        if (static::needsAsterisk()) {
589
            $required = [];
590
            foreach ($sform->getRequired() as $item) {
591
                $required[] = $item->_name;
592
            }
593
            $elements = [];
594
            $elements = $sform->getElements();
595
            $cnt      = count($elements);
596
            foreach ($elements as $i => $iValue) {
597
                if (is_object($elements[$i]) && in_array($iValue->_name, $required)) {
598
                    $iValue->_caption .= ' *';
599
                }
600
            }
601
        }
602
603
        return $sform;
604
    }
605
606
    /**
607
     * Create an html heading (from h1 to h6)
608
     *
609
     * @param  string $title The text to use
610
     * @param int     $level Level to return
611
     * @return string  The heading
612
     */
613
    public static function htitle($title = '', $level = 1)
614
    {
615
        printf('<h%01d>%s</h%01d>', $level, $title, $level);
616
    }
617
618
    /**
619
     * Create a unique upload filename
620
     *
621
     * @param  string $folder   The folder where the file will be saved
622
     * @param  string $fileName Original filename (coming from the user)
623
     * @param  bool   $trimName Do we need to create a "short" unique name ?
624
     * @return string  The unique filename to use (with its extension)
625
     */
626
    public static function createUploadName($folder, $fileName, $trimName = false)
627
    {
628
        $uid           = '';
629
        $workingfolder = $folder;
630
        if ('/' !== xoops_substr($workingfolder, mb_strlen($workingfolder) - 1, 1)) {
631
            $workingfolder .= '/';
632
        }
633
        $ext  = basename($fileName);
634
        $ext  = explode('.', $ext);
635
        $ext  = '.' . $ext[count($ext) - 1];
636
        $true = true;
637
        while ($true) {
638
            $ipbits = explode('.', $_SERVER['REMOTE_ADDR']);
639
            list($usec, $sec) = explode(' ', microtime());
640
            $usec *= 65536;
641
            $sec  = ((int)$sec) & 0xFFFF;
642
643
            if ($trimName) {
644
                $uid = sprintf('%06x%04x%04x', ($ipbits[0] << 24) | ($ipbits[1] << 16) | ($ipbits[2] << 8) | $ipbits[3], $sec, $usec);
645
            } else {
646
                $uid = sprintf('%08x-%04x-%04x', ($ipbits[0] << 24) | ($ipbits[1] << 16) | ($ipbits[2] << 8) | $ipbits[3], $sec, $usec);
647
            }
648
            if (!file_exists($workingfolder . $uid . $ext)) {
649
                $true = false;
650
            }
651
        }
652
653
        return $uid . $ext;
654
    }
655
656
    /**
657
     * Replace html entities with their ASCII equivalent
658
     *
659
     * @param  string $chaine The string undecode
660
     * @return string The undecoded string
661
     */
662
    public static function unhtml($chaine)
663
    {
664
        $search = $replace = [];
665
        $chaine = html_entity_decode($chaine);
666
667
        for ($i = 0; $i <= 255; ++$i) {
668
            $search[]  = '&#' . $i . ';';
669
            $replace[] = chr($i);
670
        }
671
        $replace[] = '...';
672
        $search[]  = '…';
673
        $replace[] = "'";
674
        $search[]  = '‘';
675
        $replace[] = "'";
676
        $search[]  = '’';
677
        $replace[] = '-';
678
        $search[]  = '&bull;'; // $replace[] = '•';
679
        $replace[] = '—';
680
        $search[]  = '&mdash;';
681
        $replace[] = '-';
682
        $search[]  = '&ndash;';
683
        $replace[] = '-';
684
        $search[]  = '&shy;';
685
        $replace[] = '"';
686
        $search[]  = '&quot;';
687
        $replace[] = '&';
688
        $search[]  = '&amp;';
689
        $replace[] = 'ˆ';
690
        $search[]  = '&circ;';
691
        $replace[] = '¡';
692
        $search[]  = '&iexcl;';
693
        $replace[] = '¦';
694
        $search[]  = '&brvbar;';
695
        $replace[] = '¨';
696
        $search[]  = '&uml;';
697
        $replace[] = '¯';
698
        $search[]  = '&macr;';
699
        $replace[] = '´';
700
        $search[]  = '&acute;';
701
        $replace[] = '¸';
702
        $search[]  = '&cedil;';
703
        $replace[] = '¿';
704
        $search[]  = '&iquest;';
705
        $replace[] = '˜';
706
        $search[]  = '&tilde;';
707
        $replace[] = "'";
708
        $search[]  = '&lsquo;'; // $replace[]='‘';
709
        $replace[] = "'";
710
        $search[]  = '&rsquo;'; // $replace[]='’';
711
        $replace[] = '‚';
712
        $search[]  = '&sbquo;';
713
        $replace[] = "'";
714
        $search[]  = '&ldquo;'; // $replace[]='“';
715
        $replace[] = "'";
716
        $search[]  = '&rdquo;'; // $replace[]='”';
717
        $replace[] = '„';
718
        $search[]  = '&bdquo;';
719
        $replace[] = '‹';
720
        $search[]  = '&lsaquo;';
721
        $replace[] = '›';
722
        $search[]  = '&rsaquo;';
723
        $replace[] = '<';
724
        $search[]  = '&lt;';
725
        $replace[] = '>';
726
        $search[]  = '&gt;';
727
        $replace[] = '±';
728
        $search[]  = '&plusmn;';
729
        $replace[] = '«';
730
        $search[]  = '&laquo;';
731
        $replace[] = '»';
732
        $search[]  = '&raquo;';
733
        $replace[] = '×';
734
        $search[]  = '&times;';
735
        $replace[] = '÷';
736
        $search[]  = '&divide;';
737
        $replace[] = '¢';
738
        $search[]  = '&cent;';
739
        $replace[] = '£';
740
        $search[]  = '&pound;';
741
        $replace[] = '¤';
742
        $search[]  = '&curren;';
743
        $replace[] = '¥';
744
        $search[]  = '&yen;';
745
        $replace[] = '§';
746
        $search[]  = '&sect;';
747
        $replace[] = '©';
748
        $search[]  = '&copy;';
749
        $replace[] = '¬';
750
        $search[]  = '&not;';
751
        $replace[] = '®';
752
        $search[]  = '&reg;';
753
        $replace[] = '°';
754
        $search[]  = '&deg;';
755
        $replace[] = 'µ';
756
        $search[]  = '&micro;';
757
        $replace[] = '¶';
758
        $search[]  = '&para;';
759
        $replace[] = '·';
760
        $search[]  = '&middot;';
761
        $replace[] = '†';
762
        $search[]  = '&dagger;';
763
        $replace[] = '‡';
764
        $search[]  = '&Dagger;';
765
        $replace[] = '‰';
766
        $search[]  = '&permil;';
767
        $replace[] = 'Euro';
768
        $search[]  = '&euro;'; // $replace[]='€'
769
        $replace[] = '¼';
770
        $search[]  = '&frac14;';
771
        $replace[] = '½';
772
        $search[]  = '&frac12;';
773
        $replace[] = '¾';
774
        $search[]  = '&frac34;';
775
        $replace[] = '¹';
776
        $search[]  = '&sup1;';
777
        $replace[] = '²';
778
        $search[]  = '&sup2;';
779
        $replace[] = '³';
780
        $search[]  = '&sup3;';
781
        $replace[] = 'á';
782
        $search[]  = '&aacute;';
783
        $replace[] = 'Á';
784
        $search[]  = '&Aacute;';
785
        $replace[] = 'â';
786
        $search[]  = '&acirc;';
787
        $replace[] = 'Â';
788
        $search[]  = '&Acirc;';
789
        $replace[] = 'à';
790
        $search[]  = '&agrave;';
791
        $replace[] = 'À';
792
        $search[]  = '&Agrave;';
793
        $replace[] = 'å';
794
        $search[]  = '&aring;';
795
        $replace[] = 'Å';
796
        $search[]  = '&Aring;';
797
        $replace[] = 'ã';
798
        $search[]  = '&atilde;';
799
        $replace[] = 'Ã';
800
        $search[]  = '&Atilde;';
801
        $replace[] = 'ä';
802
        $search[]  = '&auml;';
803
        $replace[] = 'Ä';
804
        $search[]  = '&Auml;';
805
        $replace[] = 'ª';
806
        $search[]  = '&ordf;';
807
        $replace[] = 'æ';
808
        $search[]  = '&aelig;';
809
        $replace[] = 'Æ';
810
        $search[]  = '&AElig;';
811
        $replace[] = 'ç';
812
        $search[]  = '&ccedil;';
813
        $replace[] = 'Ç';
814
        $search[]  = '&Ccedil;';
815
        $replace[] = 'ð';
816
        $search[]  = '&eth;';
817
        $replace[] = 'Ð';
818
        $search[]  = '&ETH;';
819
        $replace[] = 'é';
820
        $search[]  = '&eacute;';
821
        $replace[] = 'É';
822
        $search[]  = '&Eacute;';
823
        $replace[] = 'ê';
824
        $search[]  = '&ecirc;';
825
        $replace[] = 'Ê';
826
        $search[]  = '&Ecirc;';
827
        $replace[] = 'è';
828
        $search[]  = '&egrave;';
829
        $replace[] = 'È';
830
        $search[]  = '&Egrave;';
831
        $replace[] = 'ë';
832
        $search[]  = '&euml;';
833
        $replace[] = 'Ë';
834
        $search[]  = '&Euml;';
835
        $replace[] = 'ƒ';
836
        $search[]  = '&fnof;';
837
        $replace[] = 'í';
838
        $search[]  = '&iacute;';
839
        $replace[] = 'Í';
840
        $search[]  = '&Iacute;';
841
        $replace[] = 'î';
842
        $search[]  = '&icirc;';
843
        $replace[] = 'Î';
844
        $search[]  = '&Icirc;';
845
        $replace[] = 'ì';
846
        $search[]  = '&igrave;';
847
        $replace[] = 'Ì';
848
        $search[]  = '&Igrave;';
849
        $replace[] = 'ï';
850
        $search[]  = '&iuml;';
851
        $replace[] = 'Ï';
852
        $search[]  = '&Iuml;';
853
        $replace[] = 'ñ';
854
        $search[]  = '&ntilde;';
855
        $replace[] = 'Ñ';
856
        $search[]  = '&Ntilde;';
857
        $replace[] = 'ó';
858
        $search[]  = '&oacute;';
859
        $replace[] = 'Ó';
860
        $search[]  = '&Oacute;';
861
        $replace[] = 'ô';
862
        $search[]  = '&ocirc;';
863
        $replace[] = 'Ô';
864
        $search[]  = '&Ocirc;';
865
        $replace[] = 'ò';
866
        $search[]  = '&ograve;';
867
        $replace[] = 'Ò';
868
        $search[]  = '&Ograve;';
869
        $replace[] = 'º';
870
        $search[]  = '&ordm;';
871
        $replace[] = 'ø';
872
        $search[]  = '&oslash;';
873
        $replace[] = 'Ø';
874
        $search[]  = '&Oslash;';
875
        $replace[] = 'õ';
876
        $search[]  = '&otilde;';
877
        $replace[] = 'Õ';
878
        $search[]  = '&Otilde;';
879
        $replace[] = 'ö';
880
        $search[]  = '&ouml;';
881
        $replace[] = 'Ö';
882
        $search[]  = '&Ouml;';
883
        $replace[] = 'œ';
884
        $search[]  = '&oelig;';
885
        $replace[] = 'Œ';
886
        $search[]  = '&OElig;';
887
        $replace[] = 'š';
888
        $search[]  = '&scaron;';
889
        $replace[] = 'Š';
890
        $search[]  = '&Scaron;';
891
        $replace[] = 'ß';
892
        $search[]  = '&szlig;';
893
        $replace[] = 'þ';
894
        $search[]  = '&thorn;';
895
        $replace[] = 'Þ';
896
        $search[]  = '&THORN;';
897
        $replace[] = 'ú';
898
        $search[]  = '&uacute;';
899
        $replace[] = 'Ú';
900
        $search[]  = '&Uacute;';
901
        $replace[] = 'û';
902
        $search[]  = '&ucirc;';
903
        $replace[] = 'Û';
904
        $search[]  = '&Ucirc;';
905
        $replace[] = 'ù';
906
        $search[]  = '&ugrave;';
907
        $replace[] = 'Ù';
908
        $search[]  = '&Ugrave;';
909
        $replace[] = 'ü';
910
        $search[]  = '&uuml;';
911
        $replace[] = 'Ü';
912
        $search[]  = '&Uuml;';
913
        $replace[] = 'ý';
914
        $search[]  = '&yacute;';
915
        $replace[] = 'Ý';
916
        $search[]  = '&Yacute;';
917
        $replace[] = 'ÿ';
918
        $search[]  = '&yuml;';
919
        $replace[] = 'Ÿ';
920
        $search[]  = '&Yuml;';
921
        $chaine    = str_replace($search, $replace, $chaine);
922
923
        return $chaine;
924
    }
925
926
    /**
927
     * Création d'une titre pour être utilisé par l'url rewriting
928
     *
929
     * @param  string $content  Le texte à utiliser pour créer l'url
930
     * @param int     $urw      La limite basse pour créer les mots
931
     * @return string  Le texte à utiliser pour l'url
932
     *                          Note, some parts are from Solo's code
933
     */
934
    public static function makeSeoUrl($content, $urw = 1)
935
    {
936
        $s       = "ÀÁÂÃÄÅÒÓÔÕÖØÈÉÊËÇÌÍÎÏÙÚÛܟÑàáâãäåòóôõöøèéêëçìíîïùúûüÿñ '()";
937
        $r       = 'AAAAAAOOOOOOEEEECIIIIUUUUYNaaaaaaooooooeeeeciiiiuuuuyn----';
938
        $content = static::unhtml($content); // First, remove html entities
939
        $content = strtr($content, $s, $r);
940
        $content = strip_tags($content);
941
        $content = mb_strtolower($content);
942
        $content = htmlentities($content, ENT_QUOTES | ENT_HTML5); // TODO: Vérifier
943
        $content = preg_replace('/&([a-zA-Z])(uml|acute|grave|circ|tilde);/', '$1', $content);
944
        $content = html_entity_decode($content);
945
        $content = str_ireplace('quot', ' ', $content);
946
        $content = preg_replace("/'/i", ' ', $content);
947
        $content = preg_replace('/-/i', ' ', $content);
948
        $content = preg_replace('/[[:punct:]]/i', '', $content);
949
950
        // Selon option mais attention au fichier .htaccess !
951
        // $content = eregi_replace('[[:digit:]]','', $content);
952
        $content = preg_replace('/[^a-z|A-Z|0-9]/', '-', $content);
953
954
        $words    = explode(' ', $content);
955
        $keywords = '';
956
        foreach ($words as $word) {
957
            if (mb_strlen($word) >= $urw) {
958
                $keywords .= '-' . trim($word);
959
            }
960
        }
961
        if (!$keywords) {
962
            $keywords = '-';
963
        }
964
        // Supprime les tirets en double
965
        $keywords = str_replace('---', '-', $keywords);
966
        $keywords = str_replace('--', '-', $keywords);
967
        // Supprime un éventuel tiret à la fin de la chaine
968
        if ('-' == mb_substr($keywords, mb_strlen($keywords) - 1, 1)) {
969
            $keywords = mb_substr($keywords, 0, -1);
970
        }
971
972
        return $keywords;
973
    }
974
975
    /**
976
     * Create the meta keywords based on the content
977
     *
978
     * @param  string $content Content from which we have to create metakeywords
979
     * @return string The list of meta keywords
980
     */
981
    public static function createMetaKeywords($content)
982
    {
983
        $keywordscount = static::getModuleOption('metagen_maxwords');
984
        $keywordsorder = static::getModuleOption('metagen_order');
985
986
        $tmp = [];
987
        // Search for the "Minimum keyword length"
988
        if (\Xmf\Request::hasVar('oledrion_keywords_limit', 'SESSION')) {
989
            $limit = $_SESSION['oledrion_keywords_limit'];
990
        } else {
991
            $configHandler                       = xoops_getHandler('config');
992
            $xoopsConfigSearch                   = $configHandler->getConfigsByCat(XOOPS_CONF_SEARCH);
993
            $limit                               = $xoopsConfigSearch['keyword_min'];
994
            $_SESSION['oledrion_keywords_limit'] = $limit;
995
        }
996
        $myts            = \MyTextSanitizer::getInstance();
997
        $content         = str_replace('<br>', ' ', $content);
998
        $content         = $myts->undoHtmlSpecialChars($content);
999
        $content         = strip_tags($content);
1000
        $content         = mb_strtolower($content);
1001
        $search_pattern  = [
1002
            '&nbsp;',
1003
            "\t",
1004
            "\r\n",
1005
            "\r",
1006
            "\n",
1007
            ',',
1008
            '.',
1009
            "'",
1010
            ';',
1011
            ':',
1012
            ')',
1013
            '(',
1014
            '"',
1015
            '?',
1016
            '!',
1017
            '{',
1018
            '}',
1019
            '[',
1020
            ']',
1021
            '<',
1022
            '>',
1023
            '/',
1024
            '+',
1025
            '-',
1026
            '_',
1027
            '\\',
1028
            '*',
1029
        ];
1030
        $replace_pattern = [
1031
            ' ',
1032
            ' ',
1033
            ' ',
1034
            ' ',
1035
            ' ',
1036
            ' ',
1037
            ' ',
1038
            ' ',
1039
            '',
1040
            '',
1041
            '',
1042
            '',
1043
            '',
1044
            '',
1045
            '',
1046
            '',
1047
            '',
1048
            '',
1049
            '',
1050
            '',
1051
            '',
1052
            '',
1053
            '',
1054
            '',
1055
            '',
1056
            '',
1057
            '',
1058
        ];
1059
        $content         = str_replace($search_pattern, $replace_pattern, $content);
1060
        $keywords        = explode(' ', $content);
1061
        switch ($keywordsorder) {
1062
            case 0: // Ordre d'apparition dans le texte
1063
1064
                $keywords = array_unique($keywords);
1065
1066
                break;
1067
            case 1: // Ordre de fréquence des mots
1068
1069
                $keywords = array_count_values($keywords);
1070
                asort($keywords);
1071
                $keywords = array_keys($keywords);
1072
1073
                break;
1074
            case 2: // Ordre inverse de la fréquence des mots
1075
1076
                $keywords = array_count_values($keywords);
1077
                arsort($keywords);
1078
                $keywords = array_keys($keywords);
1079
1080
                break;
1081
        }
1082
        // Remove black listed words
1083
        if ('' !== xoops_trim(static::getModuleOption('metagen_blacklist'))) {
1084
            $metagen_blacklist = str_replace("\r", '', static::getModuleOption('metagen_blacklist'));
1085
            $metablack         = explode("\n", $metagen_blacklist);
1086
            array_walk($metablack, 'trim');
1087
            $keywords = array_diff($keywords, $metablack);
1088
        }
1089
1090
        foreach ($keywords as $keyword) {
1091
            if (!is_numeric($keyword) && mb_strlen($keyword) >= $limit) {
1092
                $tmp[] = $keyword;
1093
            }
1094
        }
1095
        $tmp = array_slice($tmp, 0, $keywordscount);
1096
        if (count($tmp) > 0) {
1097
            return implode(',', $tmp);
1098
        }
1099
1100
        if (null === $configHandler || !is_object($configHandler)) {
1101
            $configHandler = xoops_getHandler('config');
1102
        }
1103
        $xoopsConfigMetaFooter = $configHandler->getConfigsByCat(XOOPS_CONF_METAFOOTER);
1104
        if (isset($xoopsConfigMetaFooter['meta_keywords'])) {
1105
            return $xoopsConfigMetaFooter['meta_keywords'];
1106
        }
1107
1108
        return '';
1109
    }
1110
1111
    /**
1112
     * Fonction chargée de gérer l'upload
1113
     *
1114
     * @param int       $indice L'indice du fichier à télécharger
1115
     * @param  string   $dstpath
1116
     * @param  null     $mimeTypes
1117
     * @param  null|int $uploadMaxSize
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $mimeTypes is correct as it would always require null to be passed?
Loading history...
1118
     * @param  null|int $maxWidth
1119
     * @param  null|int $maxHeight
1120
     * @return mixed   True si l'upload s'est bien déroulé sinon le message d'erreur correspondant
1121
     */
1122
    public static function uploadFile(
1123
        $indice,
1124
        $dstpath = XOOPS_UPLOAD_PATH,
1125
        $mimeTypes = null,
1126
        $uploadMaxSize = null,
1127
        $maxWidth = null,
1128
        $maxHeight = null)
1129
    {
1130
        //        require_once XOOPS_ROOT_PATH . '/class/uploader.php';
1131
        global $destname;
1132
        if (\Xmf\Request::hasVar('xoops_upload_file', 'POST')) {
1133
            require_once XOOPS_ROOT_PATH . '/class/uploader.php';
1134
            $fldname = '';
1135
            $fldname = $_FILES[$_POST['xoops_upload_file'][$indice]];
1136
            $fldname = get_magic_quotes_gpc() ? stripslashes($fldname['name']) : $fldname['name'];
1137
            if (xoops_trim('' !== $fldname)) {
1138
                $destname = static::createUploadName($dstpath, $fldname, true);
1139
                if (null === $mimeTypes) {
1140
                    $permittedtypes = explode("\n", str_replace("\r", '', static::getModuleOption('mimetypes')));
1141
                    array_walk($permittedtypes, 'trim');
1142
                } else {
1143
                    $permittedtypes = $mimeTypes;
1144
                }
1145
                $uploadSize = $uploadMaxSize;
1146
                if (null === $uploadMaxSize) {
1147
                    $uploadSize = static::getModuleOption('maxuploadsize');
1148
                }
1149
                $uploader = new \XoopsMediaUploader($dstpath, $permittedtypes, $uploadSize, $maxWidth, $maxHeight);
1150
                //$uploader->allowUnknownTypes = true;
1151
                $uploader->setTargetFileName($destname);
1152
                if ($uploader->fetchMedia($_POST['xoops_upload_file'][$indice])) {
1153
                    if ($uploader->upload()) {
1154
                        return true;
1155
                    }
1156
1157
                    return _ERRORS . ' ' . htmlentities($uploader->getErrors(), ENT_QUOTES | ENT_HTML5);
1158
                }
1159
1160
                return htmlentities($uploader->getErrors(), ENT_QUOTES | ENT_HTML5);
1161
            }
1162
1163
            return false;
1164
        }
1165
1166
        return false;
1167
    }
1168
1169
    /**
1170
     * Resize a Picture to some given dimensions (using the wideImage library)
1171
     *
1172
     * @param  string $src_path      Picture's source
1173
     * @param  string $dst_path      Picture's destination
1174
     * @param int     $param_width   Maximum picture's width
1175
     * @param int     $param_height  Maximum picture's height
1176
     * @param  bool   $keep_original Do we have to keep the original picture ?
1177
     * @param  string $fit           Resize mode (see the wideImage library for more information)
1178
     * @return bool
1179
     */
1180
    public static function resizePicture(
1181
        $src_path,
1182
        $dst_path,
1183
        $param_width,
1184
        $param_height,
1185
        $keep_original = false,
1186
        $fit = 'inside')
1187
    {
1188
        //        require_once OLEDRION_PATH . 'class/wideimage/WideImage.inc.php';
1189
        $resize = true;
1190
        if (OLEDRION_DONT_RESIZE_IF_SMALLER) {
1191
            if (false === @getimagesize($src_path)) {
1192
                $message = 'The picture ' . $src_path . ' could not be found and resized.';
1193
                //                throw new \RuntimeException($message);
1194
                self::redirect($message);
1195
1196
                return false;
1197
            }
1198
            $pictureDimensions = getimagesize($src_path);
1199
            if (is_array($pictureDimensions)) {
1200
                $width  = $pictureDimensions[0];
1201
                $height = $pictureDimensions[1];
1202
                if ($width < $param_width && $height < $param_height) {
1203
                    $resize = false;
1204
                }
1205
            }
1206
        }
1207
1208
        $img = WideImage::load($src_path);
1209
        if ($resize) {
1210
            $result = $img->resize($param_width, $param_height, $fit);
1211
            $result->saveToFile($dst_path);
1212
        } else {
1213
            if (false === @copy($src_path, $dst_path)) {
1214
                throw new \RuntimeException('The file ' . $src_path . ' could not be copied.');
1215
            }
1216
        }
1217
1218
        if (!$keep_original) {
1219
            if (false === @unlink($src_path)) {
1220
                throw new \RuntimeException('The file ' . $src_path . ' could not be deleted.');
1221
            }
1222
        }
1223
1224
        return true;
1225
    }
1226
1227
    /**
1228
     * Triggering a Xoops alert after an event
1229
     *
1230
     * @param int   $category The category ID of the event
1231
     * @param int   $itemId   The ID of the element (too general to be precisely described)
1232
     * @param mixed $event    The event that is triggered
1233
     * @param mixed $tags     Variables to pass to the template
1234
     */
1235
    public static function notify($category, $itemId, $event, $tags)
1236
    {
1237
        /** @var \XoopsNotificationHandler $notificationHandler */
1238
        $notificationHandler  = xoops_getHandler('notification');
1239
        $tags['X_MODULE_URL'] = OLEDRION_URL;
1240
        $notificationHandler->triggerEvent($category, $itemId, $event, $tags);
1241
    }
1242
1243
    /**
1244
     * Ajoute des jours à une date et retourne la nouvelle date au format Date de Mysql
1245
     *
1246
     * @param  int $duration
1247
     * @param int  $startingDate Date de départ (timestamp)
1248
     * @return bool|string
1249
     * @internal param int $durations Durée en jours
1250
     */
1251
    public static function addDaysToDate($duration = 1, $startingDate = 0)
1252
    {
1253
        if (0 == $startingDate) {
1254
            $startingDate = time();
1255
        }
1256
        $endingDate = $startingDate + ($duration * 86400);
1257
1258
        return date('Y-m-d', $endingDate);
1259
    }
1260
1261
    /**
1262
     * Returns a breadcrumb based on the parameters passed and starting (automatically) from the root of the module     *
1263
     * @param array  $path  The complete path (except root) of the breadcrumb as key = url value = title
1264
     * @param string $raquo The default separator to use
1265
     * @return string the breadcrumb
1266
     */
1267
    public static function breadcrumb($path, $raquo = ' &raquo; ')
1268
    {
1269
        $breadcrumb        = '';
1270
        $workingBreadcrumb = [];
1271
        if (is_array($path)) {
1272
            $moduleName          = static::getModuleName();
1273
            $workingBreadcrumb[] = "<a href='" . OLEDRION_URL . "' title='" . static::makeHrefTitle($moduleName) . "'>" . $moduleName . '</a>';
1274
            foreach ($path as $url => $title) {
1275
                $workingBreadcrumb[] = "<a href='" . $url . "'>" . $title . '</a>';
1276
            }
1277
            $cnt = count($workingBreadcrumb);
1278
            foreach ($workingBreadcrumb as $i => $iValue) {
1279
                if ($i == $cnt - 1) {
1280
                    $workingBreadcrumb[$i] = strip_tags($workingBreadcrumb[$i]);
1281
                }
1282
            }
1283
            $breadcrumb = implode($raquo, $workingBreadcrumb);
1284
        }
1285
1286
        return $breadcrumb;
1287
    }
1288
1289
    /**
1290
     * @param $string
1291
     * @return string
1292
     */
1293
    public static function close_tags($string)
1294
    {
1295
        // match opened tags
1296
        if (preg_match_all('/<([a-z\:\-]+)[^\/]>/', $string, $start_tags)) {
1297
            $start_tags = $start_tags[1];
1298
1299
            // match closed tags
1300
            if (preg_match_all('/<\/([a-z]+)>/', $string, $end_tags)) {
1301
                $complete_tags = [];
1302
                $end_tags      = $end_tags[1];
1303
1304
                foreach ($start_tags as $key => $val) {
1305
                    $posb = array_search($val, $end_tags, true);
1306
                    if (is_int($posb)) {
1307
                        unset($end_tags[$posb]);
1308
                    } else {
1309
                        $complete_tags[] = $val;
1310
                    }
1311
                }
1312
            } else {
1313
                $complete_tags = $start_tags;
1314
            }
1315
1316
            $complete_tags = array_reverse($complete_tags);
1317
            for ($i = 0, $iMax = count($complete_tags); $i < $iMax; ++$i) {
1318
                $string .= '</' . $complete_tags[$i] . '>';
1319
            }
1320
        }
1321
1322
        return $string;
1323
    }
1324
1325
    /**
1326
     * @param               $string
1327
     * @param  int          $length
1328
     * @param  string       $etc
1329
     * @param  bool         $break_words
1330
     * @return mixed|string
1331
     */
1332
    public static function truncate_tagsafe($string, $length = 80, $etc = '...', $break_words = false)
1333
    {
1334
        if (0 == $length) {
1335
            return '';
1336
        }
1337
1338
        if (mb_strlen($string) > $length) {
1339
            $length -= mb_strlen($etc);
1340
            if (!$break_words) {
1341
                $string = preg_replace('/\s+?(\S+)?$/', '', mb_substr($string, 0, $length + 1));
1342
                $string = preg_replace('/<[^>]*$/', '', $string);
1343
                $string = static::close_tags($string);
1344
            }
1345
1346
            return $string . $etc;
1347
        }
1348
1349
        return $string;
1350
    }
1351
1352
    /**
1353
     * Create an infotip
1354
     * @param $text
1355
     * @return string
1356
     */
1357
    public static function makeInfotips($text)
1358
    {
1359
        $ret      = '';
1360
        $infotips = static::getModuleOption('infotips');
1361
        if ($infotips > 0) {
1362
            $myts = \MyTextSanitizer::getInstance();
1363
            $ret  = $myts->htmlSpecialChars(xoops_substr(strip_tags($text), 0, $infotips));
1364
        }
1365
1366
        return $ret;
1367
    }
1368
1369
    /**
1370
     * Mise en place de l'appel à la feuille de style du module dans le template
1371
     * @param string $url
1372
     */
1373
    public static function setCSS($url = '')
1374
    {
1375
        global $xoopsTpl, $xoTheme;
1376
        if ('' == $url) {
1377
            $url = OLEDRION_URL . 'assets/css/oledrion.css';
1378
        }
1379
1380
        if (!is_object($xoTheme)) {
1381
            $xoopsTpl->assign('xoops_module_header', $xoopsTpl->get_template_vars('xoops_module_header') . "<link rel=\"stylesheet\" type=\"text/css\" href=\"$url\">");
1382
        } else {
1383
            $xoTheme->addStylesheet($url);
1384
        }
1385
    }
1386
1387
    /**
1388
     * Mise en place de l'appel à la feuille de style du module dans le template
1389
     * @param string $language
1390
     */
1391
    public static function setLocalCSS($language = 'english')
1392
    {
1393
        global $xoopsTpl, $xoTheme;
1394
1395
        $localcss = OLEDRION_URL . 'language/' . $language . '/style.css';
1396
1397
        if (!is_object($xoTheme)) {
1398
            $xoopsTpl->assign('xoops_module_header', $xoopsTpl->get_template_vars('xoops_module_header') . "<link rel=\"stylesheet\" type=\"text/css\" href=\"$localcss\">");
1399
        } else {
1400
            $xoTheme->addStylesheet($localcss);
1401
        }
1402
    }
1403
1404
    /**
1405
     * Calcul du TTC à partir du HT et de la TVA
1406
     *
1407
     * @param int     $ht     Montant HT
1408
     * @param int     $vat    Taux de TVA
1409
     * @param  bool   $edit   Si faux alors le montant est formaté pour affichage sinon il reste tel quel
1410
     * @param  string $format Format d'affichage du résultat (long ou court)
1411
     * @return mixed   Soit une chaine soit un flottant
1412
     */
1413
    public static function getTTC($ht = 0, $vat = 0, $edit = false, $format = 's')
1414
    {
1415
        $ht               = (int)$ht;
1416
        $vat              = (int)$vat;
1417
        $oledrionCurrency = Oledrion\Currency::getInstance();
1418
        $ttc              = $ht * (1 + ($vat / 100));
1419
        if (!$edit) {
1420
            return $oledrionCurrency->amountForDisplay($ttc, $format);
1421
        }
1422
1423
        return $ttc;
1424
    }
1425
1426
    /**
1427
     * Renvoie le montant de la tva à partir du montant HT
1428
     * @param $ht
1429
     * @param $vat
1430
     * @return float
1431
     */
1432
    public static function getVAT($ht, $vat)
1433
    {
1434
        return (($ht * $vat) / 100);
1435
    }
1436
1437
    /**
1438
     * Retourne le montant TTC
1439
     *
1440
     * @param  float $product_price Le montant du produit
1441
     * @param int    $vat_id        Le numéro de TVA
1442
     * @return float Le montant TTC si on a trouvé sa TVA sinon
1443
     */
1444
    public static function getAmountWithVat($product_price, $vat_id)
1445
    {
1446
        $vat = null;
1447
        static $vats = [];
1448
        $vat_rate   = null;
1449
        $vatHandler = new Oledrion\VatHandler(\XoopsDatabaseFactory::getDatabaseConnection());
1450
        if (is_array($vats) && in_array($vat_id, $vats)) {
1451
            $vat_rate = $vats[$vat_id];
1452
        } else {
1453
            //            $handlers = \HandlerManager::getInstance();
1454
            require_once dirname(__DIR__) . '/include/common.php';
1455
            $vat = $vatHandler->get($vat_id);
1456
            if (is_object($vat)) {
1457
                $vat_rate      = $vat->getVar('vat_rate', 'e');
1458
                $vats[$vat_id] = $vat_rate;
1459
            }
1460
        }
1461
1462
        if (null !== $vat_rate) {
1463
            return ((float)$product_price * (float)$vat_rate / 100) + (float)$product_price;
1464
        }
1465
1466
        return $product_price;
1467
    }
1468
1469
    /**
1470
     * @param $datastream
1471
     * @param $url
1472
     * @return string
1473
     */
1474
    public static function postIt($datastream, $url)
1475
    {
1476
        $url     = preg_replace('@^http://@i', '', $url);
1477
        $host    = mb_substr($url, 0, mb_strpos($url, '/'));
1478
        $uri     = mb_strstr($url, '/');
1479
        $reqbody = '';
1480
        foreach ($datastream as $key => $val) {
1481
            if (!empty($reqbody)) {
1482
                $reqbody .= '&';
1483
            }
1484
            $reqbody .= $key . '=' . urlencode($val);
1485
        }
1486
        $contentlength = mb_strlen($reqbody);
1487
        $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";
1488
1489
        return $reqheader;
1490
    }
1491
1492
    /**
1493
     * Retourne le type Mime d'un fichier en utilisant d'abord finfo puis mime_content
1494
     *
1495
     * @param  string $filename Le fichier (avec son chemin d'accès complet) dont on veut connaître le type mime
1496
     * @return string
1497
     */
1498
    public static function getMimeType($filename)
1499
    {
1500
        if (function_exists('finfo_open')) {
1501
            $finfo    = finfo_open();
1502
            $mimetype = finfo_file($finfo, $filename, FILEINFO_MIME_TYPE);
1503
            finfo_close($finfo);
1504
1505
            return $mimetype;
1506
        }
1507
1508
        if (function_exists('mime_content_type')) {
1509
            return mime_content_type($filename);
1510
        }
1511
1512
        return '';
1513
    }
1514
1515
    /**
1516
     * Retourne un criteria compo qui permet de filtrer les produits sur le mois courant
1517
     *
1518
     * @return \CriteriaCompo
1519
     */
1520
    public static function getThisMonthCriteria()
1521
    {
1522
        $start             = mktime(0, 1, 0, date('n'), date('j'), date('Y'));
1523
        $end               = mktime(0, 0, 0, date('n'), date('t'), date('Y'));
1524
        $criteriaThisMonth = new \CriteriaCompo();
1525
        $criteriaThisMonth->add(new \Criteria('product_submitted', $start, '>='));
1526
        $criteriaThisMonth->add(new \Criteria('product_submitted', $end, '<='));
1527
1528
        return $criteriaThisMonth;
1529
    }
1530
1531
    /**
1532
     * Retourne une liste d'objets XoopsUsers à partir d'une liste d'identifiants
1533
     *
1534
     * @param  array $xoopsUsersIDs La liste des ID
1535
     * @return array Les objets XoopsUsers
1536
     */
1537
    public static function getUsersFromIds($xoopsUsersIDs)
1538
    {
1539
        $users = [];
1540
        if ($xoopsUsersIDs && is_array($xoopsUsersIDs)) {
1541
            $xoopsUsersIDs = array_unique($xoopsUsersIDs);
1542
            sort($xoopsUsersIDs);
1543
            if (count($xoopsUsersIDs) > 0) {
1544
                /** @var \XoopsUserHandler $userHandler */
1545
                $userHandler = xoops_getHandler('user');
1546
                $criteria    = new \Criteria('uid', '(' . implode(',', $xoopsUsersIDs) . ')', 'IN');
1547
                $criteria->setSort('uid');
1548
                $users = $userHandler->getObjects($criteria, true);
1549
            }
1550
        }
1551
1552
        return $users;
1553
    }
1554
1555
    /**
1556
     * Retourne l'ID de l'utilisateur courant (s'il est connecté)
1557
     * @return int L'uid ou 0
1558
     */
1559
    public static function getCurrentUserID()
1560
    {
1561
        global $xoopsUser;
1562
        $uid = is_object($xoopsUser) ? $xoopsUser->getVar('uid') : 0;
1563
1564
        return $uid;
1565
    }
1566
1567
    /**
1568
     * Retourne la liste des groupes de l'utilisateur courant (avec cache)
1569
     * @param  int $uid
1570
     * @return array Les ID des groupes auquel l'utilisateur courant appartient
1571
     */
1572
    public function getMemberGroups($uid = 0)
1573
    {
1574
        static $buffer = [];
1575
        if (0 == $uid) {
1576
            $uid = static::getCurrentUserID();
1577
        }
1578
1579
        if (is_array($buffer) && count($buffer) > 0 && isset($buffer[$uid])) {
1580
            return $buffer[$uid];
1581
        }
1582
1583
        if ($uid > 0) {
1584
            /** @var \XoopsMemberHandler $memberHandler */
1585
            $memberHandler = xoops_getHandler('member');
1586
            $buffer[$uid]  = $memberHandler->getGroupsByUser($uid, false); // Renvoie un tableau d'ID (de groupes)
1587
        } else {
1588
            $buffer[$uid] = [XOOPS_GROUP_ANONYMOUS];
1589
        }
1590
1591
        return $buffer[$uid];
1592
    }
1593
1594
    /**
1595
     * Indique si l'utilisateur courant fait partie d'une groupe donné (avec gestion de cache)
1596
     *
1597
     * @param int  $group Groupe recherché
1598
     * @param  int $uid
1599
     * @return bool    vrai si l'utilisateur fait partie du groupe, faux sinon
1600
     */
1601
    public static function isMemberOfGroup($group = 0, $uid = 0)
1602
    {
1603
        static $buffer = [];
1604
        $retval = false;
1605
        if (0 == $uid) {
1606
            $uid = static::getCurrentUserID();
1607
        }
1608
        if (is_array($buffer) && array_key_exists($group, $buffer)) {
1609
            $retval = $buffer[$group];
1610
        } else {
1611
            /** @var \XoopsMemberHandler $memberHandler */
1612
            $memberHandler  = xoops_getHandler('member');
1613
            $groups         = $memberHandler->getGroupsByUser($uid, false); // Renvoie un tableau d'ID (de groupes)
1614
            $retval         = in_array($group, $groups);
1615
            $buffer[$group] = $retval;
1616
        }
1617
1618
        return $retval;
1619
    }
1620
1621
    /**
1622
     * Fonction chargée de vérifier qu'un répertoire existe, qu'on peut écrire dedans et création d'un fichier index.html
1623
     *
1624
     * @param  string $folder Le chemin complet du répertoire à vérifier
1625
     */
1626
    public static function prepareFolder($folder)
1627
    {
1628
        if (!is_dir($folder)) {
1629
            if (!mkdir($folder, 0777) && !is_dir($folder)) {
1630
                throw new \RuntimeException(sprintf('Directory "%s" was not created', $folder));
1631
            }
1632
            file_put_contents($folder . '/index.html', '<script>history.go(-1);</script>');
1633
        }
1634
        chmod($folder, 0777);
1635
    }
1636
1637
    /**
1638
     * Duplicate a file in local
1639
     *
1640
     * @param  string $path     The file's path
1641
     * @param  string $filename The filename
1642
     * @return mixed  If the copy succeed, the new filename else false
1643
     * @since 2.1
1644
     */
1645
    public static function duplicateFile($path, $filename)
1646
    {
1647
        $newName = static::createUploadName($path, $filename);
1648
        if (copy($path . '/' . $filename, $path . '/' . $newName)) {
1649
            return $newName;
1650
        }
1651
1652
        return false;
1653
    }
1654
1655
    /**
1656
     * Load a language file
1657
     *
1658
     * @param string $languageFile     The required language file
1659
     * @param string $defaultExtension Default extension to use
1660
     * @since 2.2.2009.02.13
1661
     */
1662
    public static function loadLanguageFile($languageFile, $defaultExtension = '.php')
1663
    {
1664
        global $xoopsConfig;
1665
        $root = OLEDRION_PATH;
1666
        if (false === mb_strpos($languageFile, $defaultExtension)) {
1667
            $languageFile .= $defaultExtension;
1668
        }
1669
        /** @var Oledrion\Helper $helper */
1670
        $helper = Oledrion\Helper::getInstance();
1671
        $helper->loadLanguage($languageFile);
1672
    }
1673
1674
    /**
1675
     * Formatage d'un floattant pour la base de données
1676
     *
1677
     * @param mixed $amount
1678
     * @return string le montant formaté
1679
     * @since 2.2.2009.02.25
1680
     */
1681
    public static function formatFloatForDB($amount)
1682
    {
1683
        return number_format($amount, 2, '.', '');
1684
    }
1685
1686
    /**
1687
     * Appelle un fichier Javascript à la manière de Xoops
1688
     *
1689
     * @note, l'url complète ne doit pas être fournie, la méthode se charge d'ajouter
1690
     * le chemin vers le répertoire js en fonction de la requête, c'est à dire que si
1691
     * on appelle un fichier de langue, la méthode ajoute l'url vers le répertoire de
1692
     * langue, dans le cas contraire on ajoute l'url vers le répertoire JS du module.
1693
     *
1694
     * @param string $javascriptFile
1695
     * @param bool   $inLanguageFolder
1696
     * @param bool   $oldWay
1697
     * @since 2.3.2009.03.14
1698
     */
1699
    public static function callJavascriptFile($javascriptFile, $inLanguageFolder = false, $oldWay = false)
1700
    {
1701
        global $xoopsConfig, $xoTheme;
1702
        $fileToCall = $javascriptFile;
1703
        if ($inLanguageFolder) {
1704
            $root    = OLEDRION_PATH;
1705
            $rootUrl = OLEDRION_URL;
1706
            if (file_exists($root . 'language/' . $xoopsConfig['language'] . '/' . $javascriptFile)) {
1707
                $fileToCall = $rootUrl . 'language/' . $xoopsConfig['language'] . '/' . $javascriptFile;
1708
            } else {
1709
                // Fallback
1710
                $fileToCall = $rootUrl . 'language/english/' . $javascriptFile;
1711
            }
1712
        } else {
1713
            $fileToCall = OLEDRION_JS_URL . $javascriptFile;
1714
        }
1715
1716
        $xoTheme->addScript('browse.php?Frameworks/jquery/jquery.js');
1717
        $xoTheme->addScript($fileToCall);
1718
    }
1719
1720
    /**
1721
     * Create the <option> of an html select
1722
     *
1723
     * @param  array $array   Array of index and labels
1724
     * @param  mixed $default the default value
1725
     * @param  bool  $withNull
1726
     * @return string
1727
     * @since 2.3.2009.03.13
1728
     */
1729
    public static function htmlSelectOptions($array, $default = 0, $withNull = true)
1730
    {
1731
        $ret      = [];
1732
        $selected = '';
1733
        if ($withNull) {
1734
            if (0 === $default) {
1735
                $selected = " selected = 'selected'";
1736
            }
1737
            $ret[] = '<option value=0' . $selected . '>---</option>';
1738
        }
1739
1740
        foreach ($array as $index => $label) {
1741
            $selected = '';
1742
            if ($index == $default) {
1743
                $selected = " selected = 'selected'";
1744
            }
1745
            $ret[] = '<option value="' . $index . '"' . $selected . '>' . $label . '</option>';
1746
        }
1747
1748
        return implode("\n", $ret);
1749
    }
1750
1751
    /**
1752
     * Creates an html select
1753
     *
1754
     * @param  string $selectName Selector's name
1755
     * @param  array  $array      Options
1756
     * @param  mixed  $default    Default's value
1757
     * @param  bool   $withNull   Do we include a null option ?
1758
     * @return string
1759
     * @since 2.3.2009.03.13
1760
     */
1761
    public static function htmlSelect($selectName, $array, $default, $withNull = true)
1762
    {
1763
        $ret = '';
1764
        $ret .= "<select name='" . $selectName . "' id='" . $selectName . "'>\n";
1765
        $ret .= static::htmlSelectOptions($array, $default, $withNull);
1766
        $ret .= "</select>\n";
1767
1768
        return $ret;
1769
    }
1770
1771
    /**
1772
     * Extrait l'id d'une chaine formatée sous la forme xxxx-99 (duquel on récupère 99)
1773
     *
1774
     * @note: utilisé par les attributs produits
1775
     * @param  string $string    La chaine de travail
1776
     * @param  string $separator Le séparateur
1777
     * @return string
1778
     */
1779
    public static function getId($string, $separator = '_')
1780
    {
1781
        $pos = mb_strrpos($string, $separator);
1782
        if (false === $pos) {
1783
            return $string;
1784
        }
1785
1786
        return (int)mb_substr($string, $pos + 1);
1787
    }
1788
1789
    /**
1790
     * Fonction "inverse" de getId (depuis xxxx-99 on récupère xxxx)
1791
     *
1792
     * @note: utilisé par les attributs produits
1793
     * @param  string $string    La chaine de travail
1794
     * @param  string $separator Le séparateur
1795
     * @return string
1796
     */
1797
    public static function getName($string, $separator = '_')
1798
    {
1799
        $pos = mb_strrpos($string, $separator);
1800
        if (false === $pos) {
1801
            return $string;
1802
        }
1803
1804
        return mb_substr($string, 0, $pos);
1805
    }
1806
1807
    /**
1808
     * Renvoie un montant nul si le montant est négatif
1809
     *
1810
     * @param  float $amount
1811
     */
1812
    public static function doNotAcceptNegativeAmounts(&$amount)
1813
    {
1814
        if ($amount < 0) {
1815
            $amount = 0.0;
1816
        }
1817
    }
1818
1819
    /**
1820
     * Returns a string from the request
1821
     *
1822
     * @param  string $valueName    Name of the parameter you want to get
1823
     * @param  mixed  $defaultValue Default value to return if the parameter is not set in the request
1824
     * @return mixed
1825
     */
1826
    public static function getFromRequest($valueName, $defaultValue = '')
1827
    {
1828
        return isset($_REQUEST[$valueName]) ? $_REQUEST[$valueName] : $defaultValue;
1829
    }
1830
1831
    /**
1832
     * Verify that a mysql table exists
1833
     *
1834
     * @author        Instant Zero (http://xoops.instant-zero.com)
1835
     * @copyright (c) Instant Zero
1836
     * @param $tablename
1837
     * @return bool
1838
     */
1839
    public static function tableExists($tablename)
1840
    {
1841
        global $xoopsDB;
1842
        $result = $xoopsDB->queryF("SHOW TABLES LIKE '$tablename'");
1843
1844
        return ($xoopsDB->getRowsNum($result) > 0);
1845
    }
1846
1847
    /**
1848
     * Verify that a field exists inside a mysql table
1849
     *
1850
     * @author        Instant Zero (http://xoops.instant-zero.com)
1851
     * @copyright (c) Instant Zero
1852
     * @param $fieldname
1853
     * @param $table
1854
     * @return bool
1855
     */
1856
    public static function fieldExists($fieldname, $table)
1857
    {
1858
        global $xoopsDB;
1859
        $result = $xoopsDB->queryF("SHOW COLUMNS FROM $table LIKE '$fieldname'");
1860
1861
        return ($xoopsDB->getRowsNum($result) > 0);
1862
    }
1863
1864
    /**
1865
     * Retourne la définition d'un champ
1866
     *
1867
     * @param  string $fieldname
1868
     * @param  string $table
1869
     * @return array|string
1870
     */
1871
    public static function getFieldDefinition($fieldname, $table)
1872
    {
1873
        global $xoopsDB;
1874
        $result = $xoopsDB->queryF("SHOW COLUMNS FROM $table LIKE '$fieldname'");
1875
        if ($result) {
1876
            return $xoopsDB->fetchArray($result);
1877
        }
1878
1879
        return '';
1880
    }
1881
1882
    /**
1883
     * Add a field to a mysql table
1884
     *
1885
     * @author        Instant Zero (http://xoops.instant-zero.com)
1886
     * @copyright (c) Instant Zero
1887
     * @param $field
1888
     * @param $table
1889
     * @return bool|\mysqli_result
1890
     */
1891
    public static function addField($field, $table)
1892
    {
1893
        global $xoopsDB;
1894
        $result = $xoopsDB->queryF("ALTER TABLE $table ADD $field;");
1895
1896
        return $result;
1897
    }
1898
1899
    /**
1900
     * @param $info
1901
     * @return string
1902
     */
1903
    public static function packingHtmlSelect($info)
1904
    {
1905
        $ret = '';
1906
        $ret .= '<div class="oledrion_htmlform">';
1907
        $ret .= '<img class="oledrion_htmlimage" src="' . $info['packing_image_url'] . '" alt="' . $info['packing_title'] . '">';
1908
        $ret .= '<h3>' . $info['packing_title'] . '</h3>';
1909
        if ($info['packing_price'] > 0) {
1910
            $ret .= '<p><span class="bold">' . _OLEDRION_PRICE . '</span> : ' . $info['packing_price_fordisplay'] . '</p>';
1911
        } else {
1912
            $ret .= '<p><span class="bold">' . _OLEDRION_PRICE . '</span> : ' . _OLEDRION_FREE . '</p>';
1913
        }
1914
        $ret .= '<p>' . $info['packing_description'] . '</p>';
1915
        $ret .= '</div>';
1916
1917
        return $ret;
1918
    }
1919
1920
    /**
1921
     * @param $info
1922
     * @return string
1923
     */
1924
    public static function deliveryHtmlSelect($info)
1925
    {
1926
        $ret = '';
1927
        $ret .= '<div class="oledrion_htmlform">';
1928
        $ret .= '<img class="oledrion_htmlimage" src="' . $info['delivery_image_url'] . '" alt="' . $info['delivery_title'] . '">';
1929
        $ret .= '<h3>' . $info['delivery_title'] . '</h3>';
1930
        if ($info['delivery_price'] > 0) {
1931
            $ret .= '<p><span class="bold">' . _OLEDRION_PRICE . '</span> : ' . $info['delivery_price_fordisplay'] . '</p>';
1932
        } else {
1933
            $ret .= '<p><span class="bold">' . _OLEDRION_PRICE . '</span> : ' . _OLEDRION_FREE . '</p>';
1934
        }
1935
        $ret .= '<p><span class="bold">' . _OLEDRION_DELIVERY_TIME . '</span> : ' . $info['delivery_time'] . _OLEDRION_DELIVERY_DAY . '</p>';
1936
        $ret .= '<p>' . $info['delivery_description'] . '</p>';
1937
        $ret .= '</div>';
1938
1939
        return $ret;
1940
    }
1941
1942
    /**
1943
     * @param $info
1944
     * @return string
1945
     */
1946
    public static function paymentHtmlSelect($info)
1947
    {
1948
        $ret = '';
1949
        $ret .= '<div class="oledrion_htmlform">';
1950
        $ret .= '<img class="oledrion_htmlimage" src="' . $info['payment_image_url'] . '" alt="' . $info['payment_title'] . '">';
1951
        $ret .= '<h3>' . $info['payment_title'] . '</h3>';
1952
        $ret .= '<p>' . $info['payment_description'] . '</p>';
1953
        $ret .= '</div>';
1954
1955
        return $ret;
1956
    }
1957
1958
    /**
1959
     * @return array
1960
     */
1961
    public static function getCountriesList()
1962
    {
1963
        require_once XOOPS_ROOT_PATH . '/class/xoopslists.php';
1964
1965
        return \XoopsLists::getCountryList();
1966
    }
1967
1968
    /**
1969
     * Retourne la liste des groupes de l'utlisateur courant (avec cache)
1970
     * @return array Les ID des groupes auquel l'utilisateur courant appartient
1971
     */
1972
    public static function getCurrentMemberGroups()
1973
    {
1974
        static $buffer = [];
1975
1976
        if ($buffer && is_array($buffer)) {
1977
            return $buffer;
1978
        }
1979
        $uid = self::getCurrentUserID();
1980
        if ($uid > 0) {
1981
            /** @var \XoopsMemberHandler $memberHandler */
1982
            $memberHandler = xoops_getHandler('member');
1983
            $buffer        = $memberHandler->getGroupsByUser($uid, false);    // Renvoie un tableau d'ID (de groupes)
1984
        } else {
1985
            $buffer = [XOOPS_GROUP_ANONYMOUS];
1986
        }
1987
1988
        return $buffer;
1989
    }
1990
}
1991