Passed
Push — master ( 65bdac...4e88da )
by Alxarafe
32:38
created

DolUtils::dol_print_phone()   F

Complexity

Conditions 116
Paths > 20000

Size

Total Lines 255
Code Lines 196

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 116
eloc 196
nc 231108145
nop 9
dl 0
loc 255
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/* Copyright (C) 2000-2007	Rodolphe Quiedeville			<[email protected]>
3
 * Copyright (C) 2003		Jean-Louis Bergamo			<[email protected]>
4
 * Copyright (C) 2004-2018	Laurent Destailleur			<[email protected]>
5
 * Copyright (C) 2004		Sebastien Di Cintio			<[email protected]>
6
 * Copyright (C) 2004		Benoit Mortier				<[email protected]>
7
 * Copyright (C) 2004		Christophe Combelles			<[email protected]>
8
 * Copyright (C) 2005-2017	Regis Houssin				<[email protected]>
9
 * Copyright (C) 2008		Raphael Bertrand (Resultic)	<[email protected]>
10
 * Copyright (C) 2010-2018	Juanjo Menent				<[email protected]>
11
 * Copyright (C) 2013		Cédric Salvador				<[email protected]>
12
 * Copyright (C) 2013-2017	Alexandre Spangaro			<[email protected]>
13
 * Copyright (C) 2014		Cédric GROSS					<[email protected]>
14
 * Copyright (C) 2014-2015	Marcos García				<[email protected]>
15
 * Copyright (C) 2015		Jean-François Ferry			<[email protected]>
16
 * Copyright (C) 2018       Frédéric France             <[email protected]>
17
 * Copyright (C) 2018-2019  Alxarafe                    <[email protected]>
18
 *
19
 * This program is free software; you can redistribute it and/or modify
20
 * it under the terms of the GNU General Public License as published by
21
 * the Free Software Foundation; either version 3 of the License, or
22
 * (at your option) any later version.
23
 *
24
 * This program is distributed in the hope that it will be useful,
25
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
 * GNU General Public License for more details.
28
 *
29
 * You should have received a copy of the GNU General Public License
30
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
31
 * or see http://www.gnu.org/
32
 */
33
namespace Alixar\Helpers;
34
35
// include_once DOL_BASE_PATH . '/core/lib/json.lib.php';
36
use Alixar\Helpers\Security;
37
use Mobile_Detect;
38
39
class DolUtils
40
{
41
42
    /**
43
     * Function to return value of a static property when class
44
     * name is dynamically defined (not hard coded).
45
     * This is because $myclass::$myvar works from PHP 5.3.0+ only
46
     *
47
     * @param	string 	$class		Class name
48
     * @param 	string 	$member		Name of property
49
     * @return 	mixed				Return value of static property
50
     * @deprecated Dolibarr now requires 5.3.0+, use $class::$property syntax
51
     * @see https://php.net/manual/language.oop5.static.php
52
     */
53
    static function getStaticMember($class, $member)
54
    {
55
        dol_syslog(__FUNCTION__ . " is deprecated", LOG_WARNING);
56
57
        // This part is deprecated. Uncomment if for php 5.2.*, and comment next isset class::member
58
        /* if (version_compare(phpversion(), '5.3.0', '<'))
59
          {
60
          if (is_object($class)) $class = get_class($class);
61
          $classObj = new ReflectionClass($class);
62
          $result = null;
63
64
          $found=0;
65
          foreach($classObj->getStaticProperties() as $prop => $value)
66
          {
67
          if ($prop == $member)
68
          {
69
          $result = $value;
70
          $found++;
71
          break;
72
          }
73
          }
74
75
          if ($found) return $result;
76
          } */
77
78
        if (isset($class::$member))
0 ignored issues
show
Bug introduced by
The property member does not exist on string.
Loading history...
79
            return $class::$member;
80
        dol_print_error('', 'Try to get a static member "' . $member . '" in class "' . $class . '" that does not exists or is not static.');
81
        return null;
82
    }
83
84
    /**
85
     * Return a DoliDB instance (database handler).
86
     *
87
     * @param   string	$type		Type of database (mysql, pgsql...)
88
     * @param	string	$host		Address of database server
89
     * @param	string	$user		Nom de l'utilisateur autorise
90
     * @param	string	$pass		Mot de passe
91
     * @param	string	$name		Nom de la database
92
     * @param	int		$port		Port of database server
93
     * @return	DoliDB				A DoliDB instance
0 ignored issues
show
Bug introduced by
The type Alixar\Helpers\DoliDB was not found. Did you mean DoliDB? If so, make sure to prefix the type with \.
Loading history...
94
     */
95
    static function getDoliDBInstance($type, $host, $user, $pass, $name, $port)
96
    {
97
        require_once DOL_BASE_PATH . "/core/db/" . $type . '.class.php';
98
99
        $class = 'DoliDB' . ucfirst($type);
100
        $dolidb = new $class($type, $host, $user, $pass, $name, $port);
101
        return $dolidb;
102
    }
103
104
    /**
105
     * 	Get list of entity id to use.
106
     *
107
     * 	@param	string	$element		Current element
108
     * 									'societe', 'socpeople', 'actioncomm', 'agenda', 'resource',
109
     * 									'product', 'productprice', 'stock',
110
     * 									'propal', 'supplier_proposal', 'invoice', 'facture_fourn', 'payment_various',
111
     * 									'categorie', 'bank_account', 'bank_account', 'adherent', 'user',
112
     * 									'commande', 'commande_fournisseur', 'expedition', 'intervention', 'survey',
113
     * 									'contract', 'tax', 'expensereport', 'holiday', 'multicurrency', 'project',
114
     * 									'email_template', 'event', 'donation'
115
     * 									'c_paiement', 'c_payment_term', ...
116
     * 	@param	int		$shared			0=Return id of current entity only,
117
     * 									1=Return id of current entity + shared entities (default)
118
     *  @param	object	$currentobject	Current object if needed
119
     * 	@return	mixed				Entity id(s) to use
120
     */
121
    static function getEntity($element, $shared = 1, $currentobject = null)
122
    {
123
        //// global Globals::$conf, $mc;
124
125
        if (is_object($mc)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mc seems to be never defined.
Loading history...
126
            return $mc->getEntity($element, $shared, $currentobject);
127
        } else {
128
            $out = '';
129
            $addzero = array('user', 'usergroup', 'c_email_templates', 'email_template', 'default_values');
130
            if (in_array($element, $addzero))
131
                $out .= '0,';
132
            $out .= Globals::$conf->entity;
133
            return $out;
134
        }
135
    }
136
137
    /**
138
     * Return information about user browser
139
     *
140
     * Returns array with the following format:
141
     * array(
142
     *  'browsername' => Browser name (firefox|chrome|iceweasel|epiphany|safari|opera|ie|unknown)
143
     *  'browserversion' => Browser version. Empty if unknown
144
     *  'browseros' => Set with mobile OS (android|blackberry|ios|palm|symbian|webos|maemo|windows|unknown)
145
     *  'layout' => (tablet|phone|classic)
146
     *  'phone' => empty if not mobile, (android|blackberry|ios|palm|unknown) if mobile
147
     *  'tablet' => true/false
148
     * )
149
     *
150
     * @param string $user_agent Content of $_SERVER["HTTP_USER_AGENT"] variable
151
     * @return	array Check function documentation
152
     */
153
    static function getBrowserInfo($user_agent)
154
    {
155
        //include_once BASE_PATH . '/vendor/mobiledetect/mobiledetectlib/Mobile_Detect.php';
156
157
        $name = 'unknown';
158
        $version = '';
159
        $os = 'unknown';
160
        $phone = '';
161
162
        $detectmobile = new Mobile_Detect(null, $user_agent);
163
        $tablet = $detectmobile->isTablet();
164
165
        if ($detectmobile->isMobile()) {
166
167
            $phone = 'unknown';
168
169
            // If phone/smartphone, we set phone os name.
170
            if ($detectmobile->is('AndroidOS')) {
171
                $os = $phone = 'android';
172
            } elseif ($detectmobile->is('BlackBerryOS')) {
173
                $os = $phone = 'blackberry';
174
            } elseif ($detectmobile->is('iOS')) {
175
                $os = 'ios';
176
                $phone = 'iphone';
177
            } elseif ($detectmobile->is('PalmOS')) {
178
                $os = $phone = 'palm';
179
            } elseif ($detectmobile->is('SymbianOS')) {
180
                $os = 'symbian';
181
            } elseif ($detectmobile->is('webOS')) {
182
                $os = 'webos';
183
            } elseif ($detectmobile->is('MaemoOS')) {
184
                $os = 'maemo';
185
            } elseif ($detectmobile->is('WindowsMobileOS') || $detectmobile->is('WindowsPhoneOS')) {
186
                $os = 'windows';
187
            }
188
        }
189
190
        // OS
191
        if (preg_match('/linux/i', $user_agent)) {
192
            $os = 'linux';
193
        } elseif (preg_match('/macintosh/i', $user_agent)) {
194
            $os = 'macintosh';
195
        } elseif (preg_match('/windows/i', $user_agent)) {
196
            $os = 'windows';
197
        }
198
199
        // Name
200
        if (preg_match('/firefox(\/|\s)([\d\.]*)/i', $user_agent, $reg)) {
201
            $name = 'firefox';
202
            $version = $reg[2];
203
        } elseif (preg_match('/edge(\/|\s)([\d\.]*)/i', $user_agent, $reg)) {
204
            $name = 'edge';
205
            $version = $reg[2];
206
        } elseif (preg_match('/chrome(\/|\s)([\d\.]+)/i', $user_agent, $reg)) {
207
            $name = 'chrome';
208
            $version = $reg[2];
209
        }    // we can have 'chrome (Mozilla...) chrome x.y' in one string
210
        elseif (preg_match('/chrome/i', $user_agent, $reg)) {
211
            $name = 'chrome';
212
        } elseif (preg_match('/iceweasel/i', $user_agent)) {
213
            $name = 'iceweasel';
214
        } elseif (preg_match('/epiphany/i', $user_agent)) {
215
            $name = 'epiphany';
216
        } elseif (preg_match('/safari(\/|\s)([\d\.]*)/i', $user_agent, $reg)) {
217
            $name = 'safari';
218
            $version = $reg[2];
219
        } // Safari is often present in string for mobile but its not.
220
        elseif (preg_match('/opera(\/|\s)([\d\.]*)/i', $user_agent, $reg)) {
221
            $name = 'opera';
222
            $version = $reg[2];
223
        } elseif (preg_match('/(MSIE\s([0-9]+\.[0-9]))|.*(Trident\/[0-9]+.[0-9];.*rv:([0-9]+\.[0-9]+))/i', $user_agent, $reg)) {
224
            $name = 'ie';
225
            $version = end($reg);
226
        }    // MS products at end
227
        elseif (preg_match('/(Windows NT\s([0-9]+\.[0-9])).*(Trident\/[0-9]+.[0-9];.*rv:([0-9]+\.[0-9]+))/i', $user_agent, $reg)) {
228
            $name = 'ie';
229
            $version = end($reg);
230
        }    // MS products at end
231
        elseif (preg_match('/l(i|y)n(x|ks)(\(|\/|\s)*([\d\.]+)/i', $user_agent, $reg)) {
232
            $name = 'lynxlinks';
233
            $version = $reg[4];
234
        }
235
236
        if ($tablet) {
237
            $layout = 'tablet';
238
        } elseif ($phone) {
239
            $layout = 'phone';
240
        } else {
241
            $layout = 'classic';
242
        }
243
244
        return array(
245
            'browsername' => $name,
246
            'browserversion' => $version,
247
            'browseros' => $os,
248
            'layout' => $layout,
249
            'phone' => $phone,
250
            'tablet' => $tablet
251
        );
252
    }
253
254
    /**
255
     *  Function called at end of web php process
256
     *
257
     *  @return	void
258
     */
259
    static function dol_shutdown()
260
    {
261
       // global Globals::$conf, $user, $langs, $db;
262
        $disconnectdone = false;
263
        $depth = 0;
264
        if (is_object($db) && !empty($db->connected)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $db seems to be never defined.
Loading history...
265
            $depth = $db->transaction_opened;
266
            $disconnectdone = $db->close();
267
        }
268
        dol_syslog("--- End access to " . $_SERVER["PHP_SELF"] . (($disconnectdone && $depth) ? ' (Warn: db disconnection forced, transaction depth was ' . $depth . ')' : ''), (($disconnectdone && $depth) ? LOG_WARNING : LOG_INFO));
269
    }
270
271
    /**
272
     * Return true if we are in a context of submitting a parameter
273
     *
274
     * @param 	string	$paramname		Name or parameter to test
275
     * @return 	boolean					True if we have just submit a POST or GET request with the parameter provided (even if param is empty)
276
     */
277
    static function GETPOSTISSET($paramname)
278
    {
279
        return (isset($_POST[$paramname]) || isset($_GET[$paramname]));
280
    }
281
282
    /**
283
     *  Return value of a param into GET or POST supervariable.
284
     *  Use the property $user->default_values[path]['creatform'] and/or $user->default_values[path]['filters'] and/or $user->default_values[path]['sortorder']
285
     *  Note: The property $user->default_values is loaded by main.php when loading the user.
286
     *
287
     *  @param  string  $paramname   Name of parameter to found
288
     *  @param  string  $check	     Type of check
289
     *                               ''=no check (deprecated)
290
     *                               'none'=no check (only for param that should have very rich content)
291
     *                               'int'=check it's numeric (integer or float)
292
     *                               'intcomma'=check it's integer+comma ('1,2,3,4...')
293
     *                               'alpha'=check it's text and sign
294
     *                               'aZ'=check it's a-z only
295
     *                               'aZ09'=check it's simple alpha string (recommended for keys)
296
     *                               'array'=check it's array
297
     *                               'san_alpha'=Use filter_var with FILTER_SANITIZE_STRING (do not use this for free text string)
298
     *                               'nohtml', 'alphanohtml'=check there is no html content
299
     *                               'custom'= custom filter specify $filter and $options)
300
     *  @param	int		$method	     Type of method (0 = get then post, 1 = only get, 2 = only post, 3 = post then get, 4 = post then get then cookie)
301
     *  @param  int     $filter      Filter to apply when $check is set to 'custom'. (See http://php.net/manual/en/filter.filters.php for détails)
302
     *  @param  mixed   $options     Options to pass to filter_var when $check is set to 'custom'
303
     *  @param	string	$noreplace	 Force disable of replacement of __xxx__ strings.
304
     *  @return string|string[]      Value found (string or array), or '' if check fails
305
     */
306
    static function GETPOST($paramname, $check = 'none', $method = 0, $filter = null, $options = null, $noreplace = 0)
307
    {
308
       // global $mysoc, $user, Globals::$conf;
309
310
        if (empty($paramname))
311
            return 'BadFirstParameterForDolUtils::GETPOST';
312
        if (empty($check)) {
313
            dol_syslog("Deprecated use of DolUtils::GETPOST, called with 1st param = " . $paramname . " and 2nd param is '', when calling page " . $_SERVER["PHP_SELF"], LOG_WARNING);
314
        // Enable this line to know who call the DolUtils::GETPOST with '' $check parameter.
315
        //var_dump(debug_backtrace()[0]);
316
        }
317
318
        if (empty($method))
319
            $out = isset($_GET[$paramname]) ? $_GET[$paramname] : (isset($_POST[$paramname]) ? $_POST[$paramname] : '');
320
        elseif ($method == 1)
321
            $out = isset($_GET[$paramname]) ? $_GET[$paramname] : '';
322
        elseif ($method == 2)
323
            $out = isset($_POST[$paramname]) ? $_POST[$paramname] : '';
324
        elseif ($method == 3)
325
            $out = isset($_POST[$paramname]) ? $_POST[$paramname] : (isset($_GET[$paramname]) ? $_GET[$paramname] : '');
326
        elseif ($method == 4)
327
            $out = isset($_POST[$paramname]) ? $_POST[$paramname] : (isset($_GET[$paramname]) ? $_GET[$paramname] : (isset($_COOKIE[$paramname]) ? $_COOKIE[$paramname] : ''));
328
        else
329
            return 'BadThirdParameterForDolUtils::GETPOST';
330
331
        if (empty($method) || $method == 3 || $method == 4) {
332
            $relativepathstring = $_SERVER["PHP_SELF"];
333
            // Clean $relativepathstring
334
            if (constant('DOL_BASE_URI'))
335
                $relativepathstring = preg_replace('/^' . preg_quote(constant('DOL_BASE_URI'), '/') . '/', '', $relativepathstring);
336
            $relativepathstring = preg_replace('/^\//', '', $relativepathstring);
337
            $relativepathstring = preg_replace('/^custom\//', '', $relativepathstring);
338
            //var_dump($relativepathstring);
339
            //var_dump($user->default_values);
340
            // Code for search criteria persistence.
341
            // Retrieve values if restore_lastsearch_values
342
            if (!empty($_GET['restore_lastsearch_values'])) {        // Use $_GET here and not DolUtils::GETPOST
343
                if (!empty($_SESSION['lastsearch_values_' . $relativepathstring])) { // If there is saved values
344
                    $tmp = json_decode($_SESSION['lastsearch_values_' . $relativepathstring], true);
345
                    if (is_array($tmp)) {
346
                        foreach ($tmp as $key => $val) {
347
                            if ($key == $paramname) { // We are on the requested parameter
348
                                $out = $val;
349
                                break;
350
                            }
351
                        }
352
                    }
353
                }
354
                // If there is saved contextpage, page or limit
355
                if ($paramname == 'contextpage' && !empty($_SESSION['lastsearch_contextpage_' . $relativepathstring])) {
356
                    $out = $_SESSION['lastsearch_contextpage_' . $relativepathstring];
357
                } elseif ($paramname == 'page' && !empty($_SESSION['lastsearch_page_' . $relativepathstring])) {
358
                    $out = $_SESSION['lastsearch_page_' . $relativepathstring];
359
                } elseif ($paramname == 'limit' && !empty($_SESSION['lastsearch_limit_' . $relativepathstring])) {
360
                    $out = $_SESSION['lastsearch_limit_' . $relativepathstring];
361
                }
362
            }
363
            // Else, retreive default values if we are not doing a sort
364
            elseif (!isset($_GET['sortfield'])) { // If we did a click on a field to sort, we do no apply default values. Same if option MAIN_ENABLE_DEFAULT_VALUES is not set
365
                if (!empty($_GET['action']) && $_GET['action'] == 'create' && !isset($_GET[$paramname]) && !isset($_POST[$paramname])) {
366
                    // Search default value from $object->field
367
                   // global $object;
368
                    if (is_object($object) && isset($object->fields[$paramname]['default'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $object seems to be never defined.
Loading history...
369
                        $out = $object->fields[$paramname]['default'];
370
                    }
371
                }
372
                if (!empty(Globals::$conf->global->MAIN_ENABLE_DEFAULT_VALUES)) {
373
                    if (!empty($_GET['action']) && $_GET['action'] == 'create' && !isset($_GET[$paramname]) && !isset($_POST[$paramname])) {
374
                        // Now search in setup to overwrite default values
375
                        if (!empty($user->default_values)) {  // $user->default_values defined from menu 'Setup - Default values'
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $user seems to be never defined.
Loading history...
376
                            if (isset($user->default_values[$relativepathstring]['createform'])) {
377
                                foreach ($user->default_values[$relativepathstring]['createform'] as $defkey => $defval) {
378
                                    $qualified = 0;
379
                                    if ($defkey != '_noquery_') {
380
                                        $tmpqueryarraytohave = explode('&', $defkey);
381
                                        $tmpqueryarraywehave = explode('&', dol_string_nohtmltag($_SERVER['QUERY_STRING']));
382
                                        $foundintru = 0;
383
                                        foreach ($tmpqueryarraytohave as $tmpquerytohave) {
384
                                            if (!in_array($tmpquerytohave, $tmpqueryarraywehave))
385
                                                $foundintru = 1;
386
                                        }
387
                                        if (!$foundintru)
388
                                            $qualified = 1;
389
                                        //var_dump($defkey.'-'.$qualified);
390
                                    } else
391
                                        $qualified = 1;
392
393
                                    if ($qualified) {
394
                                        //var_dump($user->default_values[$relativepathstring][$defkey]['createform']);
395
                                        if (isset($user->default_values[$relativepathstring]['createform'][$defkey][$paramname])) {
396
                                            $out = $user->default_values[$relativepathstring]['createform'][$defkey][$paramname];
397
                                            break;
398
                                        }
399
                                    }
400
                                }
401
                            }
402
                        }
403
                    }
404
                    // Management of default search_filters and sort order
405
                    //elseif (preg_match('/list.php$/', $_SERVER["PHP_SELF"]) && ! empty($paramname) && ! isset($_GET[$paramname]) && ! isset($_POST[$paramname]))
406
                    elseif (!empty($paramname) && !isset($_GET[$paramname]) && !isset($_POST[$paramname])) {
407
                        if (!empty($user->default_values)) {  // $user->default_values defined from menu 'Setup - Default values'
408
                            //var_dump($user->default_values[$relativepathstring]);
409
                            if ($paramname == 'sortfield' || $paramname == 'sortorder') {   // Sorted on which fields ? ASC or DESC ?
410
                                if (isset($user->default_values[$relativepathstring]['sortorder'])) { // Even if paramname is sortfield, data are stored into ['sortorder...']
411
                                    foreach ($user->default_values[$relativepathstring]['sortorder'] as $defkey => $defval) {
412
                                        $qualified = 0;
413
                                        if ($defkey != '_noquery_') {
414
                                            $tmpqueryarraytohave = explode('&', $defkey);
415
                                            $tmpqueryarraywehave = explode('&', dol_string_nohtmltag($_SERVER['QUERY_STRING']));
416
                                            $foundintru = 0;
417
                                            foreach ($tmpqueryarraytohave as $tmpquerytohave) {
418
                                                if (!in_array($tmpquerytohave, $tmpqueryarraywehave))
419
                                                    $foundintru = 1;
420
                                            }
421
                                            if (!$foundintru)
422
                                                $qualified = 1;
423
                                            //var_dump($defkey.'-'.$qualified);
424
                                        } else
425
                                            $qualified = 1;
426
427
                                        if ($qualified) {
428
                                            $forbidden_chars_to_replace = array(" ", "'", "/", "\\", ":", "*", "?", "\"", "<", ">", "|", "[", "]", ";", "=");  // we accept _, -, . and ,
429
                                            foreach ($user->default_values[$relativepathstring]['sortorder'][$defkey] as $key => $val) {
430
                                                if ($out)
431
                                                    $out .= ', ';
432
                                                if ($paramname == 'sortfield') {
433
                                                    $out .= dol_string_nospecial($key, '', $forbidden_chars_to_replace);
434
                                                }
435
                                                if ($paramname == 'sortorder') {
436
                                                    $out .= dol_string_nospecial($val, '', $forbidden_chars_to_replace);
437
                                                }
438
                                            }
439
                                            //break;	// No break for sortfield and sortorder so we can cumulate fields (is it realy usefull ?)
440
                                        }
441
                                    }
442
                                }
443
                            } elseif (isset($user->default_values[$relativepathstring]['filters'])) {
444
                                foreach ($user->default_values[$relativepathstring]['filters'] as $defkey => $defval) { // $defkey is a querystring like 'a=b&c=d', $defval is key of user
445
                                    $qualified = 0;
446
                                    if ($defkey != '_noquery_') {
447
                                        $tmpqueryarraytohave = explode('&', $defkey);
448
                                        $tmpqueryarraywehave = explode('&', dol_string_nohtmltag($_SERVER['QUERY_STRING']));
449
                                        $foundintru = 0;
450
                                        foreach ($tmpqueryarraytohave as $tmpquerytohave) {
451
                                            if (!in_array($tmpquerytohave, $tmpqueryarraywehave))
452
                                                $foundintru = 1;
453
                                        }
454
                                        if (!$foundintru)
455
                                            $qualified = 1;
456
                                        //var_dump($defkey.'-'.$qualified);
457
                                    } else
458
                                        $qualified = 1;
459
460
                                    if ($qualified) {
461
                                        if (isset($_POST['sall']) || isset($_POST['search_all']) || isset($_GET['sall']) || isset($_GET['search_all'])) {
462
                                            // We made a search from quick search menu, do we still use default filter ?
463
                                            if (empty(Globals::$conf->global->MAIN_DISABLE_DEFAULT_FILTER_FOR_QUICK_SEARCH)) {
464
                                                $forbidden_chars_to_replace = array(" ", "'", "/", "\\", ":", "*", "?", "\"", "<", ">", "|", "[", "]", ";", "=");  // we accept _, -, . and ,
465
                                                $out = dol_string_nospecial($user->default_values[$relativepathstring]['filters'][$defkey][$paramname], '', $forbidden_chars_to_replace);
466
                                            }
467
                                        } else {
468
                                            $forbidden_chars_to_replace = array(" ", "'", "/", "\\", ":", "*", "?", "\"", "<", ">", "|", "[", "]", ";", "=");  // we accept _, -, . and ,
469
                                            $out = dol_string_nospecial($user->default_values[$relativepathstring]['filters'][$defkey][$paramname], '', $forbidden_chars_to_replace);
470
                                        }
471
                                        break;
472
                                    }
473
                                }
474
                            }
475
                        }
476
                    }
477
                }
478
            }
479
        }
480
481
        // Substitution variables for DolUtils::GETPOST (used to get final url with variable parameters or final default value with variable paramaters)
482
        // Example of variables: __DAY__, __MONTH__, __YEAR__, __MYCOMPANY_COUNTRY_ID__, __USER_ID__, ...
483
        // We do this only if var is a GET. If it is a POST, may be we want to post the text with vars as the setup text.
484
        if (!is_array($out) && empty($_POST[$paramname]) && empty($noreplace)) {
485
            $maxloop = 20;
486
            $loopnb = 0;    // Protection against infinite loop
487
            while (preg_match('/__([A-Z0-9]+_?[A-Z0-9]+)__/i', $out, $reg) && ($loopnb < $maxloop)) {    // Detect '__ABCDEF__' as key 'ABCDEF' and '__ABC_DEF__' as key 'ABC_DEF'. Detection is also correct when 2 vars are side by side.
488
                $loopnb++;
489
                $newout = '';
490
491
                if ($reg[1] == 'DAY') {
492
                    $tmp = dol_getdate(dol_now(), true);
493
                    $newout = $tmp['mday'];
494
                } elseif ($reg[1] == 'MONTH') {
495
                    $tmp = dol_getdate(dol_now(), true);
496
                    $newout = $tmp['mon'];
497
                } elseif ($reg[1] == 'YEAR') {
498
                    $tmp = dol_getdate(dol_now(), true);
499
                    $newout = $tmp['year'];
500
                } elseif ($reg[1] == 'PREVIOUS_DAY') {
501
                    $tmp = dol_getdate(dol_now(), true);
502
                    $tmp2 = dol_get_prev_day($tmp['mday'], $tmp['mon'], $tmp['year']);
503
                    $newout = $tmp2['day'];
504
                } elseif ($reg[1] == 'PREVIOUS_MONTH') {
505
                    $tmp = dol_getdate(dol_now(), true);
506
                    $tmp2 = dol_get_prev_month($tmp['mon'], $tmp['year']);
507
                    $newout = $tmp2['month'];
508
                } elseif ($reg[1] == 'PREVIOUS_YEAR') {
509
                    $tmp = dol_getdate(dol_now(), true);
510
                    $newout = ($tmp['year'] - 1);
511
                } elseif ($reg[1] == 'NEXT_DAY') {
512
                    $tmp = dol_getdate(dol_now(), true);
513
                    $tmp2 = dol_get_next_day($tmp['mday'], $tmp['mon'], $tmp['year']);
514
                    $newout = $tmp2['day'];
515
                } elseif ($reg[1] == 'NEXT_MONTH') {
516
                    $tmp = dol_getdate(dol_now(), true);
517
                    $tmp2 = dol_get_next_month($tmp['mon'], $tmp['year']);
518
                    $newout = $tmp2['month'];
519
                } elseif ($reg[1] == 'NEXT_YEAR') {
520
                    $tmp = dol_getdate(dol_now(), true);
521
                    $newout = ($tmp['year'] + 1);
522
                } elseif ($reg[1] == 'MYCOMPANY_COUNTRY_ID' || $reg[1] == 'MYCOUNTRY_ID' || $reg[1] == 'MYCOUNTRYID') {
523
                    $newout = $mysoc->country_id;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mysoc seems to be never defined.
Loading history...
524
                } elseif ($reg[1] == 'USER_ID' || $reg[1] == 'USERID') {
525
                    $newout = $user->id;
526
                } elseif ($reg[1] == 'USER_SUPERVISOR_ID' || $reg[1] == 'SUPERVISOR_ID' || $reg[1] == 'SUPERVISORID') {
527
                    $newout = $user->fk_user;
528
                } elseif ($reg[1] == 'ENTITY_ID' || $reg[1] == 'ENTITYID') {
529
                    $newout = Globals::$conf->entity;
530
                } else
531
                    $newout = '';     // Key not found, we replace with empty string
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
                    
565
//var_dump('__'.$reg[1].'__ -> '.$newout);
566
                $out = preg_replace('/__' . preg_quote($reg[1], '/') . '__/', $newout, $out);
567
            }
568
        }
569
570
        // Check is done after replacement
571
        switch ($check) {
572
            case 'none':
573
                break;
574
            case 'int':    // Check param is a numeric value (integer but also float or hexadecimal)
575
                if (!is_numeric($out)) {
576
                    $out = '';
577
                }
578
                break;
579
            case 'intcomma':
580
                if (preg_match('/[^0-9,-]+/i', $out))
581
                    $out = '';
582
                break;
583
            case 'alpha':
584
                if (!is_array($out)) {
585
                    $out = trim($out);
586
                    // '"' is dangerous because param in url can close the href= or src= and add javascript functions.
587
                    // '../' is dangerous because it allows dir transversals
588
                    if (preg_match('/"/', $out))
589
                        $out = '';
590
                    else if (preg_match('/\.\.\//', $out))
591
                        $out = '';
592
                }
593
                break;
594
            case 'san_alpha':
595
                $out = filter_var($out, FILTER_SANITIZE_STRING);
596
                break;
597
            case 'aZ':
598
                if (!is_array($out)) {
599
                    $out = trim($out);
600
                    if (preg_match('/[^a-z]+/i', $out))
601
                        $out = '';
602
                }
603
                break;
604
            case 'aZ09':
605
                if (!is_array($out)) {
606
                    $out = trim($out);
607
                    if (preg_match('/[^a-z0-9_\-\.]+/i', $out))
608
                        $out = '';
609
                }
610
                break;
611
            case 'aZ09comma':  // great to sanitize sortfield or sortorder params that can be t.abc,t.def_gh
612
                if (!is_array($out)) {
613
                    $out = trim($out);
614
                    if (preg_match('/[^a-z0-9_\-\.,]+/i', $out))
615
                        $out = '';
616
                }
617
                break;
618
            case 'array':
619
                if (!is_array($out) || empty($out))
620
                    $out = array();
621
                break;
622
            case 'nohtml':  // Recommended for most scalar parameters
623
                $out = dol_string_nohtmltag($out, 0);
624
                break;
625
            case 'alphanohtml': // Recommended for search parameters
626
                if (!is_array($out)) {
627
                    $out = trim($out);
628
                    // '"' is dangerous because param in url can close the href= or src= and add javascript functions.
629
                    // '../' is dangerous because it allows dir transversals
630
                    if (preg_match('/"/', $out))
631
                        $out = '';
632
                    else if (preg_match('/\.\.\//', $out))
633
                        $out = '';
634
                    $out = dol_string_nohtmltag($out);
635
                }
636
                break;
637
            case 'custom':
638
                if (empty($filter))
639
                    return 'BadFourthParameterForDolUtils::GETPOST';
640
                $out = filter_var($out, $filter, $options);
641
                break;
642
        }
643
644
        // Code for search criteria persistence.
645
        // Save data into session if key start with 'search_' or is 'smonth', 'syear', 'month', 'year'
646
        if (empty($method) || $method == 3 || $method == 4) {
647
            if (preg_match('/^search_/', $paramname) || in_array($paramname, array('sortorder', 'sortfield'))) {
648
                //var_dump($paramname.' - '.$out.' '.$user->default_values[$relativepathstring]['filters'][$paramname]);
649
                // We save search key only if $out not empty that means:
650
                // - posted value not empty, or
651
                // - if posted value is empty and a default value exists that is not empty (it means we did a filter to an empty value when default was not).
652
653
                if ($out != '') {  // $out = '0' or 'abc', it is a search criteria to keep
654
                    $user->lastsearch_values_tmp[$relativepathstring][$paramname] = $out;
655
                }
656
            }
657
        }
658
659
        return $out;
660
    }
661
662
    /**
663
     *  Return a prefix to use for this Dolibarr instance, for session/cookie names or email id.
664
     *  The prefix for session is unique in a web context only and is unique for instance and avoid conflict
665
     *  between multi-instances, even when having two instances with one root dir or two instances in virtual servers.
666
     *  The prefix for email is unique if MAIL_PREFIX_FOR_EMAIL_ID is set to a value, otherwise value may be same than other instance.
667
     *
668
     *  @param  string  $mode                   '' (prefix for session name) or 'email' (prefix for email id)
669
     *  @return	string                          A calculated prefix
670
     */
671
    static function dol_getprefix($mode = '')
672
    {
673
        // If prefix is for email
674
        if ($mode == 'email') {
675
            if (empty(Globals::$conf->global->MAIL_PREFIX_FOR_EMAIL_ID)) {
676
                return Security::dol_hash(DOL_DOCUMENT_ROOT . DOL_BASE_URI);
677
            }
678
            // If MAIL_PREFIX_FOR_EMAIL_ID is set (a value initialized with a random value is recommended)
679
            if (Globals::$conf->global->MAIL_PREFIX_FOR_EMAIL_ID != 'SERVER_NAME') {
680
                return Globals::$conf->global->MAIL_PREFIX_FOR_EMAIL_ID;
681
            }
682
            if (isset($_SERVER["SERVER_NAME"])) {
683
                return $_SERVER["SERVER_NAME"];
684
            }
685
686
            return Security::dol_hash(DOL_DOCUMENT_ROOT . DOL_BASE_URI);
687
        }
688
689
        if (isset($_SERVER["SERVER_NAME"]) && isset($_SERVER["DOCUMENT_ROOT"])) {
690
            return Security::dol_hash($_SERVER["SERVER_NAME"] . $_SERVER["DOCUMENT_ROOT"] . DOL_DOCUMENT_ROOT . DOL_BASE_URI);
691
692
            // Use this for a "readable" cookie name
693
            //return dol_sanitizeFileName($_SERVER["SERVER_NAME"].$_SERVER["DOCUMENT_ROOT"].DOL_DOCUMENT_ROOT.DOL_BASE_URI);
694
        }
695
        return Security::dol_hash(DOL_DOCUMENT_ROOT . DOL_BASE_URI);
696
    }
697
698
    /**
699
     * 	Make an include_once using default root and alternate root if it fails.
700
     *  To link to a core file, use include(DOL_DOCUMENT_ROOT.'/pathtofile')
701
     *  To link to a module file from a module file, use include './mymodulefile';
702
     *  To link to a module file from a core file, then this function can be used (call by hook / trigger / speciales pages)
703
     *
704
     * 	@param	string	$relpath	Relative path to file (Ie: mydir/myfile, ../myfile, ...)
705
     * 	@param	string	$classname	Class name (deprecated)
706
     *  @return bool                True if load is a success, False if it fails
707
     */
708
    static function dol_include_once($relpath, $classname = '')
709
    {
710
       // global Globals::$conf, $langs, $user, $mysoc;   // Do not remove this. They must be defined for files we include. Other globals var must be retreived with $GLOBALS['var']
711
712
        $fullpath = dol_buildpath($relpath);
713
714
        if (!file_exists($fullpath)) {
715
            dol_syslog('functions::dol_include_once Tried to load unexisting file: ' . $relpath, LOG_ERR);
716
            return false;
717
        }
718
719
        if (!empty($classname) && !class_exists($classname)) {
720
            return include $fullpath;
721
        } else {
722
            return include_once $fullpath;
723
        }
724
    }
725
726
    /**
727
     * 	Return path of url or filesystem. Can check into alternate dir or alternate dir + main dir depending on value of $returnemptyifnotfound.
728
     *
729
     * 	@param	string	$path						Relative path to file (if mode=0) or relative url (if mode=1). Ie: mydir/myfile, ../myfile
730
     *  @param	int		$type						0=Used for a Filesystem path, 1=Used for an URL path (output relative), 2=Used for an URL path (output full path using same host that current url), 3=Used for an URL path (output full path using host defined into $dolibarr_main_url_root of conf file)
731
     *  @param	int		$returnemptyifnotfound		0:If $type==0 and if file was not found into alternate dir, return default path into main dir (no test on it)
732
     *  											1:If $type==0 and if file was not found into alternate dir, return empty string
733
     *  											2:If $type==0 and if file was not found into alternate dir, test into main dir, return default path if found, empty string if not found
734
     *  @return string								Full filesystem path (if path=0), Full url path (if mode=1)
735
     */
736
    static function dol_buildpath($path, $type = 0, $returnemptyifnotfound = 0)
737
    {
738
       // global Globals::$conf;
739
740
        $path = preg_replace('/^\//', '', $path);
741
742
        if ($type == 0 /* empty($type) */) { // For a filesystem path
743
//$res = DOL_BASE_PATH . '' . $path;  // Standard default path
744
            $res = DOL_BASE_PATH . '/' . $path;  // Standard default path
745
            if (isset(Globals::$conf->file->dol_document_root)) {
746
                foreach (Globals::$conf->file->dol_document_root as $key => $dirroot) { // ex: array(["main"]=>"/home/main/htdocs", ["alt0"]=>"/home/dirmod/htdocs", ...)
747
                    if ($key == 'main') {
748
                        continue;
749
                    }
750
                    if (file_exists($dirroot . '/' . $path)) {
751
                        $res = $dirroot . '/' . $path;
752
                        return $res;
753
                    }
754
                }
755
            }
756
            if ($returnemptyifnotfound) {        // Not found into alternate dir
757
                if ($returnemptyifnotfound == 1 || !file_exists($res))
758
                    return '';
759
            }
760
        }
761
        else {    // For an url path
762
// We try to get local path of file on filesystem from url
763
// Note that trying to know if a file on disk exist by forging path on disk from url
764
// works only for some web server and some setup. This is bugged when
765
// using proxy, rewriting, virtual path, etc...
766
            $res = '';
767
            if ($type == 1) {
768
                $res = /* DOL_BASE_URI */ DOL_BASE_URI . '/' . $path;   // Standard value
769
            }
770
            if ($type == 2) {
771
                $res = /* DOL_MAIN_URL_ROOT */ DOL_BASE_PATH . '/' . $path;  // Standard value
772
            }
773
            if ($type == 3) {
774
                $res = DOL_BASE_URI . '/' . $path;
775
            }
776
777
            foreach (Globals::$conf->file->dol_document_root as $key => $dirroot) { // ex: array(["main"]=>"/home/main/htdocs", ["alt0"]=>"/home/dirmod/htdocs", ...)
778
                if ($key == 'main') {
779
                    if ($type == 3) {
780
                       // global $dolibarr_main_url_root;
781
                        // Define $urlwithroot
782
783
                        // $urlwithouturlroot = preg_replace('/' . preg_quote(DOL_BASE_URI, '/') . '$/i', '', trim($dolibarr_main_url_root));
784
                        $urlwithouturlroot = preg_replace('/' . preg_quote(DOL_BASE_URI, '/') . '$/i', '', trim(DOL_BASE_URI));
785
786
                        $urlwithroot = $urlwithouturlroot . DOL_BASE_URI;  // This is to use external domain name found into config file
787
                        //$urlwithroot=DOL_MAIN_URL_ROOT;					// This is to use same domain name than current
788
789
                        $res = (preg_match('/^http/i', Globals::$conf->file->dol_url_root[$key]) ? '' : $urlwithroot) . '/' . $path;     // Test on start with http is for old conf syntax
790
                    }
791
                    continue;
792
                }
793
                preg_match('/^([^\?]+(\.css\.php|\.css|\.js\.php|\.js|\.png|\.jpg|\.php)?)/i', $path, $regs);    // Take part before '?'
794
                if (!empty($regs[1])) {
795
                    //print $key.'-'.$dirroot.'/'.$path.'-'.$conf->file->dol_url_root[$type].'<br>'."\n";
796
                    if (file_exists($dirroot . '/' . $regs[1])) {
797
                        if ($type == 1) {
798
                            $res = (preg_match('/^http/i', Globals::$conf->file->dol_url_root[$key]) ? '' : DOL_BASE_URI) . Globals::$conf->file->dol_url_root[$key] . '/' . $path;
799
                        }
800
                        if ($type == 2) {
801
                            $res = (preg_match('/^http/i', Globals::$conf->file->dol_url_root[$key]) ? '' : DOL_MAIN_URL_ROOT) . Globals::$conf->file->dol_url_root[$key] . '/' . $path;
802
                        }
803
                        if ($type == 3) {
804
                           // global $dolibarr_main_url_root;
805
                            // Define $urlwithroot
806
                            $urlwithouturlroot = preg_replace('/' . preg_quote(DOL_BASE_URI, '/') . '$/i', '', trim($dolibarr_main_url_root));
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_url_root seems to be never defined.
Loading history...
807
                            $urlwithroot = $urlwithouturlroot . DOL_BASE_URI;  // This is to use external domain name found into config file
808
                            //$urlwithroot=DOL_MAIN_URL_ROOT;					// This is to use same domain name than current
809
810
                            $res = (preg_match('/^http/i', Globals::$conf->file->dol_url_root[$key]) ? '' : $urlwithroot) . Globals::$conf->file->dol_url_root[$key] . '/' . $path;     // Test on start with http is for old conf syntax
811
                        }
812
                        break;
813
                    }
814
                }
815
            }
816
        }
817
818
        return $res;
819
    }
820
821
    /**
822
     * 	Create a clone of instance of object (new instance with same value for properties)
823
     *  With native = 0: Property that are reference are also new object (true clone). This means $this->db is not valid.
824
     *  With native = 1: Use PHP clone. Property that are reference are same pointer. This means $this->db is still valid.
825
     *
826
     * 	@param	object	$object		Object to clone
827
     *  @param	int		$native		Native method or true method
828
     * 	@return object				Object clone
829
     *  @see https://php.net/manual/language.oop5.cloning.php
830
     */
831
    static function dol_clone($object, $native = 0)
832
    {
833
//dol_syslog(__FUNCTION__ . " is deprecated", LOG_WARNING);
834
835
        if (empty($native)) {
836
            $myclone = unserialize(serialize($object));
837
        } else {
838
            $myclone = clone $object;     // PHP clone is a shallow copy only, not a real clone, so properties of references will keep references (refer to the same target/variable)
839
        }
840
841
        return $myclone;
842
    }
843
844
    /**
845
     * 	Optimize a size for some browsers (phone, smarphone, ...)
846
     *
847
     * 	@param	int		$size		Size we want
848
     * 	@param	string	$type		Type of optimizing:
849
     * 								'' = function used to define a size for truncation
850
     * 								'width' = function is used to define a width
851
     * 	@return int					New size after optimizing
852
     */
853
    static function dol_size($size, $type = '')
854
    {
855
        //global Globals::$conf;
856
        if (empty(Globals::$conf->dol_optimize_smallscreen))
857
            return $size;
858
        if ($type == 'width' && $size > 250)
859
            return 250;
860
        else
861
            return 10;
862
    }
863
864
    /**
865
     * 	Clean a string to use it as a file name
866
     *
867
     * 	@param	string	$str            String to clean
868
     * 	@param	string	$newstr			String to replace bad chars with
869
     *  @param	int	    $unaccent		1=Remove also accent (default), 0 do not remove them
870
     * 	@return string          		String cleaned (a-zA-Z_)
871
     *
872
     * 	@see        	dol_string_nospecial, dol_string_unaccent, dol_sanitizePathName
873
     */
874
    static function dol_sanitizeFileName($str, $newstr = '_', $unaccent = 1)
875
    {
876
        $filesystem_forbidden_chars = array('<', '>', '/', '\\', '?', '*', '|', '"', '°');
877
        return dol_string_nospecial($unaccent ? dol_string_unaccent($str) : $str, $newstr, $filesystem_forbidden_chars);
878
    }
879
880
    /**
881
     * 	Clean a string to use it as a path name
882
     *
883
     * 	@param	string	$str            String to clean
884
     * 	@param	string	$newstr			String to replace bad chars with
885
     *  @param	int	    $unaccent		1=Remove also accent (default), 0 do not remove them
886
     * 	@return string          		String cleaned (a-zA-Z_)
887
     *
888
     * 	@see        	dol_string_nospecial, dol_string_unaccent, dol_sanitizeFileName
889
     */
890
    static function dol_sanitizePathName($str, $newstr = '_', $unaccent = 1)
891
    {
892
        $filesystem_forbidden_chars = array('<', '>', '?', '*', '|', '"', '°');
893
        return dol_string_nospecial($unaccent ? dol_string_unaccent($str) : $str, $newstr, $filesystem_forbidden_chars);
894
    }
895
896
    /**
897
     * 	Clean a string from all accent characters to be used as ref, login or by dol_sanitizeFileName
898
     *
899
     * 	@param	string	$str			String to clean
900
     * 	@return string   	       		Cleaned string
901
     *
902
     * 	@see    		dol_sanitizeFilename, dol_string_nospecial
903
     */
904
    static function dol_string_unaccent($str)
905
    {
906
        if (utf8_check($str)) {
907
// See http://www.utf8-chartable.de/
908
            $string = rawurlencode($str);
909
            $replacements = array(
910
                '%C3%80' => 'A', '%C3%81' => 'A', '%C3%82' => 'A', '%C3%83' => 'A', '%C3%84' => 'A', '%C3%85' => 'A',
911
                '%C3%88' => 'E', '%C3%89' => 'E', '%C3%8A' => 'E', '%C3%8B' => 'E',
912
                '%C3%8C' => 'I', '%C3%8D' => 'I', '%C3%8E' => 'I', '%C3%8F' => 'I',
913
                '%C3%92' => 'O', '%C3%93' => 'O', '%C3%94' => 'O', '%C3%95' => 'O', '%C3%96' => 'O',
914
                '%C3%99' => 'U', '%C3%9A' => 'U', '%C3%9B' => 'U', '%C3%9C' => 'U',
915
                '%C3%A0' => 'a', '%C3%A1' => 'a', '%C3%A2' => 'a', '%C3%A3' => 'a', '%C3%A4' => 'a', '%C3%A5' => 'a',
916
                '%C3%A7' => 'c',
917
                '%C3%A8' => 'e', '%C3%A9' => 'e', '%C3%AA' => 'e', '%C3%AB' => 'e',
918
                '%C3%AC' => 'i', '%C3%AD' => 'i', '%C3%AE' => 'i', '%C3%AF' => 'i',
919
                '%C3%B1' => 'n',
920
                '%C3%B2' => 'o', '%C3%B3' => 'o', '%C3%B4' => 'o', '%C3%B5' => 'o', '%C3%B6' => 'o',
921
                '%C3%B9' => 'u', '%C3%BA' => 'u', '%C3%BB' => 'u', '%C3%BC' => 'u',
922
                '%C3%BF' => 'y'
923
            );
924
            $string = strtr($string, $replacements);
925
            return rawurldecode($string);
926
        } else {
927
// See http://www.ascii-code.com/
928
            $string = strtr(
929
                $str, "\xC0\xC1\xC2\xC3\xC4\xC5\xC7
930
			\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1
931
			\xD2\xD3\xD4\xD5\xD8\xD9\xDA\xDB\xDD
932
			\xE0\xE1\xE2\xE3\xE4\xE5\xE7\xE8\xE9\xEA\xEB
933
			\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF8
934
			\xF9\xFA\xFB\xFC\xFD\xFF", "AAAAAAC
935
			EEEEIIIIDN
936
			OOOOOUUUY
937
			aaaaaaceeee
938
			iiiidnooooo
939
			uuuuyy"
940
            );
941
            $string = strtr($string, array("\xC4" => "Ae", "\xC6" => "AE", "\xD6" => "Oe", "\xDC" => "Ue", "\xDE" => "TH", "\xDF" => "ss", "\xE4" => "ae", "\xE6" => "ae", "\xF6" => "oe", "\xFC" => "ue", "\xFE" => "th"));
942
            return $string;
943
        }
944
    }
945
946
    /**
947
     * 	Clean a string from all punctuation characters to use it as a ref or login.
948
     *  This is a more complete static function than dol_sanitizeFileName.
949
     *
950
     * 	@param	string	$str            	String to clean
951
     * 	@param	string	$newstr				String to replace forbidden chars with
952
     *  @param  array	$badcharstoreplace  List of forbidden characters
953
     * 	@return string          			Cleaned string
954
     *
955
     * 	@see    		dol_sanitizeFilename, dol_string_unaccent
956
     */
957
    static function dol_string_nospecial($str, $newstr = '_', $badcharstoreplace = '')
958
    {
959
        $forbidden_chars_to_replace = array(" ", "'", "/", "\\", ":", "*", "?", "\"", "<", ">", "|", "[", "]", ",", ";", "=", '°');  // more complete than dol_sanitizeFileName
960
        $forbidden_chars_to_remove = array();
961
        if (is_array($badcharstoreplace))
962
            $forbidden_chars_to_replace = $badcharstoreplace;
963
//$forbidden_chars_to_remove=array("(",")");
964
965
        return str_replace($forbidden_chars_to_replace, $newstr, str_replace($forbidden_chars_to_remove, "", $str));
966
    }
967
968
    /**
969
     * Encode string for xml usage
970
     *
971
     * @param 	string	$string		String to encode
972
     * @return	string				String encoded
973
     */
974
    static function dolEscapeXML($string)
975
    {
976
        return strtr($string, array('\'' => '&apos;', '"' => '&quot;', '&' => '&amp;', '<' => '&lt;', '>' => '&gt;'));
977
    }
978
979
    /**
980
     *  Returns text escaped for inclusion into javascript code
981
     *
982
     *  @param      string		$stringtoescape		String to escape
983
     *  @param		int		$mode				0=Escape also ' and " into ', 1=Escape ' but not " for usage into 'string', 2=Escape " but not ' for usage into "string", 3=Escape ' and " with \
984
     *  @param		int		$noescapebackslashn	0=Escape also \n. 1=Do not escape \n.
985
     *  @return     string     		 				Escaped string. Both ' and " are escaped into ' if they are escaped.
986
     */
987
    static function dol_escape_js($stringtoescape, $mode = 0, $noescapebackslashn = 0)
988
    {
989
// escape quotes and backslashes, newlines, etc.
990
        $substitjs = array("&#039;" => "\\'", "\r" => '\\r');
991
//$substitjs['</']='<\/';	// We removed this. Should be useless.
992
        if (empty($noescapebackslashn)) {
993
            $substitjs["\n"] = '\\n';
994
            $substitjs['\\'] = '\\\\';
995
        }
996
        if (empty($mode)) {
997
            $substitjs["'"] = "\\'";
998
            $substitjs['"'] = "\\'";
999
        } else if ($mode == 1)
1000
            $substitjs["'"] = "\\'";
1001
        else if ($mode == 2) {
1002
            $substitjs['"'] = '\\"';
1003
        } else if ($mode == 3) {
1004
            $substitjs["'"] = "\\'";
1005
            $substitjs['"'] = "\\\"";
1006
        }
1007
        return strtr($stringtoescape, $substitjs);
1008
    }
1009
1010
    /**
1011
     *  Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields.
1012
     *
1013
     *  @param      string		$stringtoescape		String to escape
1014
     *  @param		int			$keepb				1=Preserve b tags (otherwise, remove them)
1015
     *  @param      int         $keepn              1=Preserve \r\n strings (otherwise, replace them with escaped value)
1016
     *  @return     string     				 		Escaped string
1017
     *  @see		dol_string_nohtmltag, dol_string_nospecial, dol_string_unaccent
1018
     */
1019
    static function dol_escape_htmltag($stringtoescape, $keepb = 0, $keepn = 0)
1020
    {
1021
// escape quotes and backslashes, newlines, etc.
1022
        $tmp = html_entity_decode($stringtoescape, ENT_COMPAT, 'UTF-8');  // TODO Use htmlspecialchars_decode instead, that make only required change for html tags
1023
        if (!$keepb)
1024
            $tmp = strtr($tmp, array("<b>" => '', '</b>' => ''));
1025
        if (!$keepn)
1026
            $tmp = strtr($tmp, array("\r" => '\\r', "\n" => '\\n'));
1027
        return htmlentities($tmp, ENT_COMPAT, 'UTF-8');      // TODO Use htmlspecialchars instead, that make only required change for html tags
1028
    }
1029
1030
    /**
1031
     * Convert a string to lower. Never use strtolower because it does not works with UTF8 strings.
1032
     *
1033
     * @param 	string		$utf8_string		String to encode
1034
     * @return 	string							String converted
1035
     */
1036
    static function dol_strtolower($utf8_string)
1037
    {
1038
        return mb_strtolower($utf8_string, "UTF-8");
1039
    }
1040
1041
    /**
1042
     * Convert a string to upper. Never use strtolower because it does not works with UTF8 strings.
1043
     *
1044
     * @param 	string		$utf8_string		String to encode
1045
     * @return 	string							String converted
1046
     */
1047
    static function dol_strtoupper($utf8_string)
1048
    {
1049
        return mb_strtoupper($utf8_string, "UTF-8");
1050
    }
1051
1052
    /**
1053
     * 	Write log message into outputs. Possible outputs can be:
1054
     * 	SYSLOG_HANDLERS = ["mod_syslog_file"]  		file name is then defined by SYSLOG_FILE
1055
     * 	SYSLOG_HANDLERS = ["mod_syslog_syslog"]  	facility is then defined by SYSLOG_FACILITY
1056
     *  Warning, syslog functions are bugged on Windows, generating memory protection faults. To solve
1057
     *  this, use logging to files instead of syslog (see setup of module).
1058
     *  Note: If constant 'SYSLOG_FILE_NO_ERROR' defined, we never output any error message when writing to log fails.
1059
     *  Note: You can get log message into html sources by adding parameter &logtohtml=1 (constant MAIN_LOGTOHTML must be set)
1060
     *  This static function works only if syslog module is enabled.
1061
     * 	This must not use any call to other static function calling dol_syslog (avoid infinite loop).
1062
     *
1063
     * 	@param  string		$message				Line to log. ''=Show nothing
1064
     *  @param  int			$level					Log level
1065
     * 												On Windows LOG_ERR=4, LOG_WARNING=5, LOG_NOTICE=LOG_INFO=6, LOG_DEBUG=6 si define_syslog_variables ou PHP 5.3+, 7 si dolibarr
1066
     * 												On Linux   LOG_ERR=3, LOG_WARNING=4, LOG_INFO=6, LOG_DEBUG=7
1067
     *  @param	int			$ident					1=Increase ident of 1, -1=Decrease ident of 1
1068
     *  @param	string		$suffixinfilename		When output is a file, append this suffix into default log filename.
1069
     *  @param	string		$restricttologhandler	Output log only for this log handler
1070
     *  @return	void
1071
     */
1072
    static function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename = '', $restricttologhandler = '')
1073
    {
1074
       // global Globals::$conf, $user;
1075
// If syslog module enabled
1076
        if (empty(Globals::$conf->syslog->enabled))
1077
            return;
1078
1079
        if ($ident < 0) {
1080
            foreach (Globals::$conf->loghandlers as $loghandlerinstance) {
1081
                $loghandlerinstance->setIdent($ident);
1082
            }
1083
        }
1084
1085
        if (!empty($message)) {
1086
// Test log level
1087
            $logLevels = array(LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG);
1088
            if (!in_array($level, $logLevels, true)) {
1089
                throw new Exception('Incorrect log level');
0 ignored issues
show
Bug introduced by
The type Alixar\Helpers\Exception was not found. Did you mean Exception? If so, make sure to prefix the type with \.
Loading history...
1090
            }
1091
            if ($level > Globals::$conf->global->SYSLOG_LEVEL)
1092
                return;
1093
1094
            $message = preg_replace('/password=\'[^\']*\'/', 'password=\'hidden\'', $message); // protection to avoid to have value of password in log
1095
// If adding log inside HTML page is required
1096
            if (!empty($_REQUEST['logtohtml']) && (!empty(Globals::$conf->global->MAIN_ENABLE_LOG_TO_HTML) || !empty(Globals::$conf->global->MAIN_LOGTOHTML))) {   // MAIN_LOGTOHTML kept for backward compatibility
1097
                Globals::$conf->logbuffer[] = dol_print_date(time(), "%Y-%m-%d %H:%M:%S") . " " . $message;
1098
            }
1099
1100
//TODO: Remove this. MAIN_ENABLE_LOG_INLINE_HTML should be deprecated and use a log handler dedicated to HTML output
1101
// If html log tag enabled and url parameter log defined, we show output log on HTML comments
1102
            if (!empty(Globals::$conf->global->MAIN_ENABLE_LOG_INLINE_HTML) && !empty($_GET["log"])) {
1103
                print "\n\n<!-- Log start\n";
1104
                print $message . "\n";
1105
                print "Log end -->\n";
1106
            }
1107
1108
            $data = array(
1109
                'message' => $message,
1110
                'script' => (isset($_SERVER['PHP_SELF']) ? basename($_SERVER['PHP_SELF'], '.php') : false),
1111
                'level' => $level,
1112
                'user' => ((is_object($user) && $user->id) ? $user->login : false),
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $user seems to be never defined.
Loading history...
1113
                'ip' => false
1114
            );
1115
1116
// This is when server run behind a reverse proxy
1117
            if (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
1118
                $data['ip'] = $_SERVER['HTTP_X_FORWARDED_FOR'] . (empty($_SERVER["REMOTE_ADDR"]) ? '' : '->' . $_SERVER['REMOTE_ADDR']);
1119
// This is when server run normally on a server
1120
            else if (!empty($_SERVER["REMOTE_ADDR"]))
1121
                $data['ip'] = $_SERVER['REMOTE_ADDR'];
1122
// This is when PHP session is ran inside a web server but not inside a client request (example: init code of apache)
1123
            else if (!empty($_SERVER['SERVER_ADDR']))
1124
                $data['ip'] = $_SERVER['SERVER_ADDR'];
1125
// This is when PHP session is ran outside a web server, like from Windows command line (Not always defined, but useful if OS defined it).
1126
            else if (!empty($_SERVER['COMPUTERNAME']))
1127
                $data['ip'] = $_SERVER['COMPUTERNAME'] . (empty($_SERVER['USERNAME']) ? '' : '@' . $_SERVER['USERNAME']);
1128
// This is when PHP session is ran outside a web server, like from Linux command line (Not always defined, but usefull if OS defined it).
1129
            else if (!empty($_SERVER['LOGNAME']))
1130
                $data['ip'] = '???@' . $_SERVER['LOGNAME'];
1131
// Loop on each log handler and send output
1132
            foreach (Globals::$conf->loghandlers as $loghandlerinstance) {
1133
                if ($restricttologhandler && $loghandlerinstance->code != $restricttologhandler)
1134
                    continue;
1135
                $loghandlerinstance->export($data, $suffixinfilename);
1136
            }
1137
            unset($data);
1138
        }
1139
1140
        if ($ident > 0) {
1141
            foreach (Globals::$conf->loghandlers as $loghandlerinstance) {
1142
                $loghandlerinstance->setIdent($ident);
1143
            }
1144
        }
1145
    }
1146
1147
    /**
1148
     * 	Show tab header of a card
1149
     *
1150
     * 	@param	array	$links				Array of tabs. Currently initialized by calling a static function xxx_admin_prepare_head
1151
     * 	@param	string	$active     		Active tab name (document', 'info', 'ldap', ....)
1152
     * 	@param  string	$title      		Title
1153
     * 	@param  int		$notab				-1 or 0=Add tab header, 1=no tab header. If you set this to 1, using dol_fiche_end() to close tab is not required.
1154
     * 	@param	string	$picto				Add a picto on tab title
1155
     * 	@param	int		$pictoisfullpath	If 1, image path is a full path. If you set this to 1, you can use url returned by dol_buildpath('/mymodyle/img/myimg.png',1) for $picto.
1156
     *  @param	string	$morehtmlright		Add more html content on right of tabs title
1157
     *  @param	string	$morecss			More Css
1158
     * 	@return	void
1159
     */
1160
    static function dol_fiche_head($links = array(), $active = '0', $title = '', $notab = 0, $picto = '', $pictoisfullpath = 0, $morehtmlright = '', $morecss = '')
1161
    {
1162
        print dol_get_fiche_head($links, $active, $title, $notab, $picto, $pictoisfullpath, $morehtmlright, $morecss);
1163
    }
1164
1165
    /**
1166
     *  Show tab header of a card
1167
     *
1168
     * 	@param	array	$links				Array of tabs
1169
     * 	@param	string	$active     		Active tab name
1170
     * 	@param  string	$title      		Title
1171
     * 	@param  int		$notab				-1 or 0=Add tab header, 1=no tab header. If you set this to 1, using dol_fiche_end() to close tab is not required.
1172
     * 	@param	string	$picto				Add a picto on tab title
1173
     * 	@param	int		$pictoisfullpath	If 1, image path is a full path. If you set this to 1, you can use url returned by dol_buildpath('/mymodyle/img/myimg.png',1) for $picto.
1174
     *  @param	string	$morehtmlright		Add more html content on right of tabs title
1175
     *  @param	string	$morecss			More Css
1176
     * 	@return	string
1177
     */
1178
    static function dol_get_fiche_head($links = array(), $active = '', $title = '', $notab = 0, $picto = '', $pictoisfullpath = 0, $morehtmlright = '', $morecss = '')
1179
    {
1180
       // global Globals::$conf, $langs, $hookmanager;
1181
1182
        $out = "\n" . '<div class="tabs" data-role="controlgroup" data-type="horizontal">' . "\n";
1183
1184
        if ($morehtmlright) {
1185
            $out .= '<div class="inline-block floatright tabsElem">' . $morehtmlright . '</div>'; // Output right area first so when space is missing, text is in front of tabs and not under.
1186
        }
1187
1188
// Show title
1189
        $showtitle = 1;
1190
        if (!empty(Globals::$conf->dol_optimize_smallscreen))
1191
            $showtitle = 0;
1192
        if (!empty($title) && $showtitle) {
1193
            $limittitle = 30;
1194
            $out .= '<a class="tabTitle">';
1195
            if ($picto)
1196
                $out .= img_picto($title, ($pictoisfullpath ? '' : 'object_') . $picto, '', $pictoisfullpath) . ' ';
1197
            $out .= '<span class="tabTitleText">' . dol_trunc($title, $limittitle) . '</span>';
1198
            $out .= '</a>';
1199
        }
1200
1201
// Define max of key (max may be higher than sizeof because of hole due to module disabling some tabs).
1202
        $maxkey = -1;
1203
        if (is_array($links) && !empty($links)) {
1204
            $keys = array_keys($links);
1205
            if (count($keys))
1206
                $maxkey = max($keys);
1207
        }
1208
1209
        if (!empty(Globals::$conf->dol_optimize_smallscreen))
1210
            Globals::$conf->global->MAIN_MAXTABS_IN_CARD = 2;
1211
1212
// Show tabs
1213
        $bactive = false;
1214
// if =0 we don't use the feature
1215
        $limittoshow = (empty(Globals::$conf->global->MAIN_MAXTABS_IN_CARD) ? 99 : Globals::$conf->global->MAIN_MAXTABS_IN_CARD);
1216
        $displaytab = 0;
1217
        $nbintab = 0;
1218
        $popuptab = 0;
1219
        $outmore = '';
1220
        for ($i = 0; $i <= $maxkey; $i++) {
1221
            if ((is_numeric($active) && $i == $active) || (!empty($links[$i][2]) && !is_numeric($active) && $active == $links[$i][2])) {
1222
// If active tab is already present
1223
                if ($i >= $limittoshow)
1224
                    $limittoshow--;
1225
            }
1226
        }
1227
1228
        for ($i = 0; $i <= $maxkey; $i++) {
1229
            if ((is_numeric($active) && $i == $active) || (!empty($links[$i][2]) && !is_numeric($active) && $active == $links[$i][2])) {
1230
                $isactive = true;
1231
                $bactive = true;
1232
            } else {
1233
                $isactive = false;
1234
            }
1235
1236
            if ($i < $limittoshow || $isactive) {
1237
                $out .= '<div class="inline-block tabsElem' . ($isactive ? ' tabsElemActive' : '') . ((!$isactive && !empty(Globals::$conf->global->MAIN_HIDE_INACTIVETAB_ON_PRINT)) ? ' hideonprint' : '') . '"><!-- id tab = ' . (empty($links[$i][2]) ? '' : $links[$i][2]) . ' -->';
1238
                if (isset($links[$i][2]) && $links[$i][2] == 'image') {
1239
                    if (!empty($links[$i][0])) {
1240
                        $out .= '<a class="tabimage' . ($morecss ? ' ' . $morecss : '') . '" href="' . $links[$i][0] . '">' . $links[$i][1] . '</a>' . "\n";
1241
                    } else {
1242
                        $out .= '<span class="tabspan">' . $links[$i][1] . '</span>' . "\n";
1243
                    }
1244
                } else if (!empty($links[$i][1])) {
1245
                    //print "x $i $active ".$links[$i][2]." z";
1246
                    if ($isactive) {
1247
                        $out .= '<a' . (!empty($links[$i][2]) ? ' id="' . $links[$i][2] . '"' : '') . ' class="tabactive tab inline-block' . ($morecss ? ' ' . $morecss : '') . '" href="' . $links[$i][0] . '">';
1248
                        $out .= $links[$i][1];
1249
                        $out .= '</a>' . "\n";
1250
                    } else {
1251
                        $out .= '<a' . (!empty($links[$i][2]) ? ' id="' . $links[$i][2] . '"' : '') . ' class="tabunactive tab inline-block' . ($morecss ? ' ' . $morecss : '') . '" href="' . $links[$i][0] . '">';
1252
                        $out .= $links[$i][1];
1253
                        $out .= '</a>' . "\n";
1254
                    }
1255
                }
1256
                $out .= '</div>';
1257
            } else {
1258
// The popup with the other tabs
1259
                if (!$popuptab) {
1260
                    $popuptab = 1;
1261
                    $outmore .= '<div class="popuptabset wordwrap">'; // The css used to hide/show popup
1262
                }
1263
                $outmore .= '<div class="popuptab wordwrap" style="display:inherit;">';
1264
                if (isset($links[$i][2]) && $links[$i][2] == 'image') {
1265
                    if (!empty($links[$i][0]))
1266
                        $outmore .= '<a class="tabimage' . ($morecss ? ' ' . $morecss : '') . '" href="' . $links[$i][0] . '">' . $links[$i][1] . '</a>' . "\n";
1267
                    else
1268
                        $outmore .= '<span class="tabspan">' . $links[$i][1] . '</span>' . "\n";
1269
                }
1270
                else if (!empty($links[$i][1])) {
1271
                    $outmore .= '<a' . (!empty($links[$i][2]) ? ' id="' . $links[$i][2] . '"' : '') . ' class="wordwrap inline-block' . ($morecss ? ' ' . $morecss : '') . '" href="' . $links[$i][0] . '">';
1272
                    $outmore .= preg_replace('/([a-z])\/([a-z])/i', '\\1 / \\2', $links[$i][1]); // Replace x/y with x / y to allow wrap on long composed texts.
1273
                    $outmore .= '</a>' . "\n";
1274
                }
1275
                $outmore .= '</div>';
1276
1277
                $nbintab++;
1278
            }
1279
            $displaytab = $i;
1280
        }
1281
        if ($popuptab)
1282
            $outmore .= '</div>';
1283
1284
        if ($displaytab > $limittoshow) {
1285
            $left = ($langs->trans("DIRECTION") == 'rtl' ? 'right' : 'left');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
1286
            $right = ($langs->trans("DIRECTION") == 'rtl' ? 'left' : 'right');
1287
1288
            $tabsname = str_replace("@", "", $picto);
1289
            $out .= '<div id="moretabs' . $tabsname . '" class="inline-block tabsElem">';
1290
            $out .= '<a href="#" class="tab moretab inline-block tabunactive reposition">' . $langs->trans("More") . '... (' . $nbintab . ')</a>';
1291
            $out .= '<div id="moretabsList' . $tabsname . '" style="position: absolute; ' . $left . ': -999em; text-align: ' . $left . '; margin:0px; padding:2px">';
1292
            $out .= $outmore;
1293
            $out .= '</div>';
1294
            $out .= '<div></div>';
1295
            $out .= "</div>\n";
1296
1297
            $out .= "<script>";
1298
            $out .= "$('#moretabs" . $tabsname . "').mouseenter( function() { console.log('mouseenter " . $left . "'); $('#moretabsList" . $tabsname . "').css('" . $left . "','auto');});";
1299
            $out .= "$('#moretabs" . $tabsname . "').mouseleave( function() { console.log('mouseleave " . $left . "'); $('#moretabsList" . $tabsname . "').css('" . $left . "','-999em');});";
1300
            $out .= "</script>";
1301
        }
1302
1303
        $out .= "</div>\n";
1304
1305
        if (!$notab || $notab == -1)
1306
            $out .= "\n" . '<div class="tabBar' . ($notab == -1 ? '' : ' tabBarWithBottom') . '">' . "\n";
1307
1308
        $parameters = array('tabname' => $active, 'out' => $out);
1309
        $reshook = $hookmanager->executeHooks('printTabsHead', $parameters); // This hook usage is called just before output the head of tabs. Take also a look at "completeTabsHead"
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $hookmanager seems to be never defined.
Loading history...
1310
        if ($reshook > 0) {
1311
            $out = $hookmanager->resPrint;
1312
        }
1313
1314
        return $out;
1315
    }
1316
1317
    /**
1318
     *  Show tab footer of a card
1319
     *
1320
     *  @param	int		$notab       -1 or 0=Add tab footer, 1=no tab footer
1321
     *  @return	void
1322
     */
1323
    static function dol_fiche_end($notab = 0)
1324
    {
1325
        print dol_get_fiche_end($notab);
1326
    }
1327
1328
    /**
1329
     * 	Return tab footer of a card
1330
     *
1331
     * 	@param  int		$notab		-1 or 0=Add tab footer, 1=no tab footer
1332
     *  @return	string
1333
     */
1334
    static function dol_get_fiche_end($notab = 0)
1335
    {
1336
        if (!$notab || $notab == -1)
1337
            return "\n</div>\n";
1338
        else
1339
            return '';
1340
    }
1341
1342
    /**
1343
     *  Show tab footer of a card.
1344
     *  Note: $object->next_prev_filter can be set to restrict select to find next or previous record by $form->showrefnav.
1345
     *
1346
     *  @param	Object	$object			Object to show
1347
     *  @param	string	$paramid   		Name of parameter to use to name the id into the URL next/previous link
1348
     *  @param	string	$morehtml  		More html content to output just before the nav bar
1349
     *  @param	int		$shownav	  	Show Condition (navigation is shown if value is 1)
1350
     *  @param	string	$fieldid   		Nom du champ en base a utiliser pour select next et previous (we make the select max and min on this field). Use 'none' for no prev/next search.
1351
     *  @param	string	$fieldref   	Nom du champ objet ref (object->ref) a utiliser pour select next et previous
1352
     *  @param	string	$morehtmlref  	More html to show after ref
1353
     *  @param	string	$moreparam  	More param to add in nav link url.
1354
     * 	@param	int		$nodbprefix		Do not include DB prefix to forge table name
1355
     * 	@param	string	$morehtmlleft	More html code to show before ref
1356
     * 	@param	string	$morehtmlstatus	More html code to show under navigation arrows
1357
     *  @param  int     $onlybanner     Put this to 1, if the card will contains only a banner (this add css 'arearefnobottom' on div)
1358
     * 	@param	string	$morehtmlright	More html code to show before navigation arrows
1359
     *  @return	void
1360
     */
1361
    static function dol_banner_tab($object, $paramid, $morehtml = '', $shownav = 1, $fieldid = 'rowid', $fieldref = 'ref', $morehtmlref = '', $moreparam = '', $nodbprefix = 0, $morehtmlleft = '', $morehtmlstatus = '', $onlybanner = 0, $morehtmlright = '')
1362
    {
1363
       // global Globals::$conf, $form, $user, $langs;
1364
1365
        $error = 0;
1366
1367
        $maxvisiblephotos = 1;
1368
        $showimage = 1;
1369
        $entity = (empty($object->entity) ? Globals::$conf->entity : $object->entity);
1370
        $showbarcode = empty(Globals::$conf->barcode->enabled) ? 0 : ($object->barcode ? 1 : 0);
1371
        if (!empty(Globals::$conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->barcode->lire_advance))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $user seems to be never defined.
Loading history...
1372
            $showbarcode = 0;
1373
        $modulepart = 'unknown';
1374
1375
        if ($object->element == 'societe')
1376
            $modulepart = 'societe';
1377
        if ($object->element == 'contact')
1378
            $modulepart = 'contact';
1379
        if ($object->element == 'member')
1380
            $modulepart = 'memberphoto';
1381
        if ($object->element == 'user')
1382
            $modulepart = 'userphoto';
1383
        if ($object->element == 'product')
1384
            $modulepart = 'product';
1385
1386
        if (class_exists("Imagick")) {
1387
            if ($object->element == 'propal')
1388
                $modulepart = 'propal';
1389
            if ($object->element == 'commande')
1390
                $modulepart = 'commande';
1391
            if ($object->element == 'facture')
1392
                $modulepart = 'facture';
1393
            if ($object->element == 'fichinter')
1394
                $modulepart = 'ficheinter';
1395
            if ($object->element == 'contrat')
1396
                $modulepart = 'contract';
1397
            if ($object->element == 'supplier_proposal')
1398
                $modulepart = 'supplier_proposal';
1399
            if ($object->element == 'order_supplier')
1400
                $modulepart = 'supplier_order';
1401
            if ($object->element == 'invoice_supplier')
1402
                $modulepart = 'supplier_invoice';
1403
            if ($object->element == 'expensereport')
1404
                $modulepart = 'expensereport';
1405
        }
1406
1407
        if ($object->element == 'product') {
1408
            $width = 80;
1409
            $cssclass = 'photoref';
1410
            $showimage = $object->is_photo_available(Globals::$conf->product->multidir_output[$entity]);
1411
            $maxvisiblephotos = (isset(Globals::$conf->global->PRODUCT_MAX_VISIBLE_PHOTO) ? Globals::$conf->global->PRODUCT_MAX_VISIBLE_PHOTO : 5);
1412
            if (Globals::$conf->browser->layout == 'phone')
1413
                $maxvisiblephotos = 1;
1414
            if ($showimage)
1415
                $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref">' . $object->show_photos('product', Globals::$conf->product->multidir_output[$entity], 'small', $maxvisiblephotos, 0, 0, 0, $width, 0) . '</div>';
1416
            else {
1417
                if (!empty(Globals::$conf->global->PRODUCT_NODISPLAYIFNOPHOTO)) {
1418
                    $nophoto = '';
1419
                    $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"></div>';
1420
                }
1421
//elseif (Globals::$conf->browser->layout != 'phone') {    // Show no photo link
1422
                $nophoto = '/public/theme/common/nophoto.png';
1423
// $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="No photo" border="0"' . ($width ? ' width="' . $width . '"' : '') . ' src="' . DOL_BASE_URI . $nophoto . '"></div>';
1424
                $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="No photo" border="0"' . ($width ? ' width="' . $width . '"' : '') . ' src="' . DOL_BASE_URI . $nophoto . '"></div>';
1425
//}
1426
            }
1427
        } elseif ($object->element == 'ticket') {
1428
            $width = 80;
1429
            $cssclass = 'photoref';
1430
            $showimage = $object->is_photo_available(Globals::$conf->ticket->multidir_output[$entity] . '/' . $object->track_id);
1431
            $maxvisiblephotos = (isset(Globals::$conf->global->TICKETSUP_MAX_VISIBLE_PHOTO) ? Globals::$conf->global->TICKETSUP_MAX_VISIBLE_PHOTO : 2);
1432
            if (Globals::$conf->browser->layout == 'phone')
1433
                $maxvisiblephotos = 1;
1434
            if ($showimage)
1435
                $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref">' . $object->show_photos('ticket', Globals::$conf->ticket->multidir_output[$entity], 'small', $maxvisiblephotos, 0, 0, 0, $width, 0) . '</div>';
1436
            else {
1437
                if (!empty(Globals::$conf->global->TICKETSUP_NODISPLAYIFNOPHOTO)) {
1438
                    $nophoto = '';
1439
                    $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"></div>';
1440
                }
1441
//elseif (Globals::$conf->browser->layout != 'phone') {    // Show no photo link
1442
                $nophoto = '/public/theme/common/nophoto.png';
1443
//$morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="No photo" border="0"' . ($width ? ' width="' . $width . '"' : '') . ' src="' . DOL_BASE_URI . $nophoto . '"></div>';
1444
                $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="No photo" border="0"' . ($width ? ' width="' . $width . '"' : '') . ' src="' . DOL_BASE_URI . $nophoto . '"></div>';
1445
//}
1446
            }
1447
        } else {
1448
            if ($showimage) {
1449
                if ($modulepart != 'unknown') {
1450
                    $phototoshow = '';
1451
                    // Check if a preview file is available
1452
                    if (in_array($modulepart, array('propal', 'commande', 'facture', 'ficheinter', 'contract', 'supplier_order', 'supplier_proposal', 'supplier_invoice', 'expensereport')) && class_exists("Imagick")) {
1453
                        $objectref = dol_sanitizeFileName($object->ref);
1454
                        $dir_output = (empty(Globals::$conf->$modulepart->multidir_output[$entity]) ? Globals::$conf->$modulepart->dir_output : Globals::$conf->$modulepart->multidir_output[$entity]) . "/";
1455
                        if (in_array($modulepart, array('invoice_supplier', 'supplier_invoice'))) {
1456
                            $subdir = get_exdir($object->id, 2, 0, 1, $object, $modulepart);
1457
                            $subdir .= ((!empty($subdir) && !preg_match('/\/$/', $subdir)) ? '/' : '') . $objectref;  // the objectref dir is not included into get_exdir when used with level=2, so we add it at end
1458
                        } else {
1459
                            $subdir = get_exdir($object->id, 0, 0, 1, $object, $modulepart);
1460
                        }
1461
                        if (empty($subdir))
1462
                            $subdir = 'errorgettingsubdirofobject'; // Protection to avoid to return empty path
1463
1464
                        $filepath = $dir_output . $subdir . "/";
1465
1466
                        $file = $filepath . $objectref . ".pdf";
1467
                        $relativepath = $subdir . '/' . $objectref . '.pdf';
1468
1469
                        // Define path to preview pdf file (preview precompiled "file.ext" are "file.ext_preview.png")
1470
                        $fileimage = $file . '_preview.png';              // If PDF has 1 page
1471
                        $fileimagebis = $file . '_preview-0.png';         // If PDF has more than one page
1472
                        $relativepathimage = $relativepath . '_preview.png';
1473
1474
                        // Si fichier PDF existe
1475
                        if (file_exists($file)) {
1476
                            $encfile = urlencode($file);
1477
                            // Conversion du PDF en image png si fichier png non existant
1478
                            if ((!file_exists($fileimage) || (filemtime($fileimage) < filemtime($file))) && (!file_exists($fileimagebis) || (filemtime($fileimagebis) < filemtime($file)))
1479
                            ) {
1480
                                if (empty(Globals::$conf->global->MAIN_DISABLE_PDF_THUMBS)) {  // If you experienc trouble with pdf thumb generation and imagick, you can disable here.
1481
                                    include_once DOL_BASE_PATH . '/core/lib/files.lib.php';
1482
                                    $ret = dol_convert_file($file, 'png', $fileimage);
1483
                                    if ($ret < 0)
1484
                                        $error++;
1485
                                }
1486
                            }
1487
1488
                            $heightforphotref = 70;
1489
                            if (!empty(Globals::$conf->dol_optimize_smallscreen))
1490
                                $heightforphotref = 60;
1491
                            // Si fichier png PDF d'1 page trouve
1492
                            if (file_exists($fileimage)) {
1493
                                $phototoshow = '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref">';
1494
                                $phototoshow .= '<img height="' . $heightforphotref . '" class="photo photowithmargin photowithborder" src="' . DOL_BASE_URI . '/viewimage.php?modulepart=apercu' . $modulepart . '&amp;file=' . urlencode($relativepathimage) . '">';
1495
                                $phototoshow .= '</div></div>';
1496
                            }
1497
                            // Si fichier png PDF de plus d'1 page trouve
1498
                            elseif (file_exists($fileimagebis)) {
1499
                                $preview = preg_replace('/\.png/', '', $relativepathimage) . "-0.png";
1500
                                $phototoshow = '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref">';
1501
                                $phototoshow .= '<img height="' . $heightforphotref . '" class="photo photowithmargin photowithborder" src="' . DOL_BASE_URI . '/viewimage.php?modulepart=apercu' . $modulepart . '&amp;file=' . urlencode($preview) . '"><p>';
1502
                                $phototoshow .= '</div></div>';
1503
                            }
1504
                        }
1505
                    } else if (!$phototoshow) {
1506
                        $phototoshow = $form->showphoto($modulepart, $object, 0, 0, 0, 'photoref', 'small', 1, 0, $maxvisiblephotos);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $form seems to be never defined.
Loading history...
1507
                    }
1508
1509
                    if ($phototoshow) {
1510
                        $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref">';
1511
                        $morehtmlleft .= $phototoshow;
1512
                        $morehtmlleft .= '</div>';
1513
                    }
1514
                }
1515
1516
                if (!$phototoshow) {      // Show No photo link (picto of pbject)
1517
                    $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref">';
1518
                    if ($object->element == 'action') {
1519
                        $width = 80;
1520
                        $cssclass = 'photorefcenter';
1521
                        $nophoto = img_picto('', 'title_agenda', '', false, 1);
1522
                    } else {
1523
                        $width = 14;
1524
                        $cssclass = 'photorefcenter';
1525
                        $picto = $object->picto;
1526
                        if ($object->element == 'project' && !$object->public)
1527
                            $picto = 'project'; // instead of projectpub
1528
                        $nophoto = img_picto('', 'object_' . $picto, '', false, 1);
1529
                    }
1530
                    $morehtmlleft .= '<!-- No photo to show -->';
1531
                    $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref"><img class="photo' . $modulepart . ($cssclass ? ' ' . $cssclass : '') . '" alt="No photo" border="0"' . ($width ? ' width="' . $width . '"' : '') . ' src="' . $nophoto . '"></div></div>';
1532
1533
                    $morehtmlleft .= '</div>';
1534
                }
1535
            }
1536
        }
1537
1538
        if ($showbarcode)
1539
            $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref">' . $form->showbarcode($object) . '</div>';
1540
1541
        if ($object->element == 'societe') {
1542
            if (!empty(Globals::$conf->use_javascript_ajax) && $user->rights->societe->creer && !empty(Globals::$conf->global->MAIN_DIRECT_STATUS_UPDATE)) {
1543
                $morehtmlstatus .= ajax_object_onoff($object, 'status', 'status', 'InActivity', 'ActivityCeased');
1544
            } else {
1545
                $morehtmlstatus .= $object->getLibStatut(6);
1546
            }
1547
        } elseif ($object->element == 'product') {
1548
//$morehtmlstatus.=$langs->trans("Status").' ('.$langs->trans("Sell").') ';
1549
            if (!empty(Globals::$conf->use_javascript_ajax) && $user->rights->produit->creer && !empty(Globals::$conf->global->MAIN_DIRECT_STATUS_UPDATE)) {
1550
                $morehtmlstatus .= ajax_object_onoff($object, 'status', 'tosell', 'ProductStatusOnSell', 'ProductStatusNotOnSell');
1551
            } else {
1552
                $morehtmlstatus .= '<span class="statusrefsell">' . $object->getLibStatut(5, 0) . '</span>';
1553
            }
1554
            $morehtmlstatus .= ' &nbsp; ';
1555
//$morehtmlstatus.=$langs->trans("Status").' ('.$langs->trans("Buy").') ';
1556
            if (!empty(Globals::$conf->use_javascript_ajax) && $user->rights->produit->creer && !empty(Globals::$conf->global->MAIN_DIRECT_STATUS_UPDATE)) {
1557
                $morehtmlstatus .= ajax_object_onoff($object, 'status_buy', 'tobuy', 'ProductStatusOnBuy', 'ProductStatusNotOnBuy');
1558
            } else {
1559
                $morehtmlstatus .= '<span class="statusrefbuy">' . $object->getLibStatut(5, 1) . '</span>';
1560
            }
1561
        } elseif (in_array($object->element, array('facture', 'invoice', 'invoice_supplier', 'chargesociales', 'loan'))) {
1562
            $tmptxt = $object->getLibStatut(6, $object->totalpaye);
1563
            if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3) || Globals::$conf->browser->layout == 'phone')
1564
                $tmptxt = $object->getLibStatut(5, $object->totalpaye);
1565
            $morehtmlstatus .= $tmptxt;
1566
        }
1567
        elseif ($object->element == 'contrat' || $object->element == 'contract') {
1568
            if ($object->statut == 0)
1569
                $morehtmlstatus .= $object->getLibStatut(5);
1570
            else
1571
                $morehtmlstatus .= $object->getLibStatut(4);
1572
        }
1573
        elseif ($object->element == 'facturerec') {
1574
            if ($object->frequency == 0)
1575
                $morehtmlstatus .= $object->getLibStatut(2);
1576
            else
1577
                $morehtmlstatus .= $object->getLibStatut(5);
1578
        }
1579
        elseif ($object->element == 'project_task') {
1580
            $object->fk_statut = 1;
1581
            if ($object->progress > 0)
1582
                $object->fk_statut = 2;
1583
            if ($object->progress >= 100)
1584
                $object->fk_statut = 3;
1585
            $tmptxt = $object->getLibStatut(5);
1586
            $morehtmlstatus .= $tmptxt;  // No status on task
1587
        }
1588
        else { // Generic case
1589
            $tmptxt = $object->getLibStatut(6);
1590
            if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3) || Globals::$conf->browser->layout == 'phone')
1591
                $tmptxt = $object->getLibStatut(5);
1592
            $morehtmlstatus .= $tmptxt;
1593
        }
1594
1595
// Add if object was dispatched "into accountancy"
1596
        if (!empty(Globals::$conf->accounting->enabled) && in_array($object->element, array('bank', 'facture', 'invoice', 'invoice_supplier', 'expensereport'))) {
1597
            if (method_exists($object, 'getVentilExportCompta')) {
1598
                $accounted = $object->getVentilExportCompta();
1599
                $langs->load("accountancy");
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
1600
                $morehtmlstatus .= '</div><div class="statusref statusrefbis">' . ($accounted > 0 ? $langs->trans("Accounted") : $langs->trans("NotYetAccounted"));
1601
            }
1602
        }
1603
1604
// Add alias for thirdparty
1605
        if (!empty($object->name_alias))
1606
            $morehtmlref .= '<div class="refidno">' . $object->name_alias . '</div>';
1607
1608
// Add label
1609
        if ($object->element == 'product' || $object->element == 'bank_account' || $object->element == 'project_task') {
1610
            if (!empty($object->label))
1611
                $morehtmlref .= '<div class="refidno">' . $object->label . '</div>';
1612
        }
1613
1614
        if (method_exists($object, 'getBannerAddress') && $object->element != 'product' && $object->element != 'bookmark' && $object->element != 'ecm_directories' && $object->element != 'ecm_files') {
1615
            $morehtmlref .= '<div class="refidno">';
1616
            $morehtmlref .= $object->getBannerAddress('refaddress', $object);
1617
            $morehtmlref .= '</div>';
1618
        }
1619
        if (!empty(Globals::$conf->global->MAIN_SHOW_TECHNICAL_ID) && in_array($object->element, array('societe', 'contact', 'member', 'product'))) {
1620
            $morehtmlref .= '<div style="clear: both;"></div><div class="refidno">';
1621
            $morehtmlref .= $langs->trans("TechnicalID") . ': ' . $object->id;
1622
            $morehtmlref .= '</div>';
1623
        }
1624
1625
        print '<div class="' . ($onlybanner ? 'arearefnobottom ' : 'arearef ') . 'heightref valignmiddle" width="100%">';
1626
        print $form->showrefnav($object, $paramid, $morehtml, $shownav, $fieldid, $fieldref, $morehtmlref, $moreparam, $nodbprefix, $morehtmlleft, $morehtmlstatus, $morehtmlright);
1627
        print '</div>';
1628
        print '<div class="underrefbanner clearboth"></div>';
1629
    }
1630
1631
    /**
1632
     * Show a string with the label tag dedicated to the HTML edit field.
1633
     *
1634
     * @param	string	$langkey		Translation key
1635
     * @param 	string	$fieldkey		Key of the html select field the text refers to
1636
     * @param	int		$fieldrequired	1=Field is mandatory
1637
     * @return string
1638
     * @deprecated Form::editfieldkey
1639
     */
1640
    static function fieldLabel($langkey, $fieldkey, $fieldrequired = 0)
1641
    {
1642
       // global Globals::$conf, $langs;
1643
        $ret = '';
1644
        if ($fieldrequired)
1645
            $ret .= '<span class="fieldrequired">';
1646
        if ((Globals::$conf->dol_use_jmobile != 4))
1647
            $ret .= '<label for="' . $fieldkey . '">';
1648
        $ret .= $langs->trans($langkey);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
1649
        if ((Globals::$conf->dol_use_jmobile != 4))
1650
            $ret .= '</label>';
1651
        if ($fieldrequired)
1652
            $ret .= '</span>';
1653
        return $ret;
1654
    }
1655
1656
    /**
1657
     * Return string to add class property on html element with pair/impair.
1658
     *
1659
     * @param	string	$var			0 or 1
1660
     * @param	string	$moreclass		More class to add
1661
     * @return	string					String to add class onto HTML element
1662
     */
1663
    static function dol_bc($var, $moreclass = '')
1664
    {
1665
       // global $bc;
1666
        $ret = ' ' . $bc[$var];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $bc seems to be never defined.
Loading history...
1667
        if ($moreclass)
1668
            $ret = preg_replace('/class=\"/', 'class="' . $moreclass . ' ', $ret);
1669
        return $ret;
1670
    }
1671
1672
    /**
1673
     *      Return a formated address (part address/zip/town/state) according to country rules
1674
     *
1675
     *      @param  Object		$object			A company or contact object
1676
     * 	    @param	int			$withcountry		1=Add country into address string
1677
     *      @param	string		$sep				Separator to use to build string
1678
     *      @param	Translate	$outputlangs		Object lang that contains language for text translation.
0 ignored issues
show
Bug introduced by
The type Alixar\Helpers\Translate was not found. Did you mean Translate? If so, make sure to prefix the type with \.
Loading history...
1679
     *      @param	int		$mode		0=Standard output, 1=Remove address
1680
     *      @return string						Formated string
1681
     *      @see dol_print_address
1682
     */
1683
    static function dol_format_address($object, $withcountry = 0, $sep = "\n", $outputlangs = '', $mode = 0)
1684
    {
1685
       // global Globals::$conf, $langs;
1686
1687
        $ret = '';
1688
        $countriesusingstate = array('AU', 'CA', 'US', 'IN', 'GB', 'ES', 'UK', 'TR');    // See also MAIN_FORCE_STATE_INTO_ADDRESS
1689
// Address
1690
        if (empty($mode)) {
1691
            $ret .= $object->address;
1692
        }
1693
// Zip/Town/State
1694
        if (in_array($object->country_code, array('AU', 'CA', 'US')) || !empty(Globals::$conf->global->MAIN_FORCE_STATE_INTO_ADDRESS)) {    // US: title firstname name \n address lines \n town, state, zip \n country
1695
            $ret .= ($ret ? $sep : '' ) . $object->town;
1696
            if ($object->state) {
1697
                $ret .= ($ret ? ", " : '') . $object->state;
1698
            }
1699
            if ($object->zip)
1700
                $ret .= ($ret ? ", " : '') . $object->zip;
1701
        }
1702
        else if (in_array($object->country_code, array('GB', 'UK'))) { // UK: title firstname name \n address lines \n town state \n zip \n country
1703
            $ret .= ($ret ? $sep : '' ) . $object->town;
1704
            if ($object->state) {
1705
                $ret .= ($ret ? ", " : '') . $object->state;
1706
            }
1707
            if ($object->zip)
1708
                $ret .= ($ret ? $sep : '' ) . $object->zip;
1709
        }
1710
        else if (in_array($object->country_code, array('ES', 'TR'))) { // ES: title firstname name \n address lines \n zip town \n state \n country
1711
            $ret .= ($ret ? $sep : '' ) . $object->zip;
1712
            $ret .= ($object->town ? (($object->zip ? ' ' : '') . $object->town) : '');
1713
            if ($object->state) {
1714
                $ret .= "\n" . $object->state;
1715
            }
1716
        } else if (in_array($object->country_code, array('IT'))) { // IT: tile firstname name\n address lines \n zip (Code Departement) \n country
1717
            $ret .= ($ret ? $sep : '' ) . $object->zip;
1718
            $ret .= ($object->town ? (($object->zip ? ' ' : '') . $object->town) : '');
1719
            $ret .= ($object->departement_id ? (' (' . ($object->departement_id) . ')') : '');
1720
        } else {                                          // Other: title firstname name \n address lines \n zip town \n country
1721
            $ret .= $object->zip ? (($ret ? $sep : '' ) . $object->zip) : '';
1722
            $ret .= ($object->town ? (($object->zip ? ' ' : ($ret ? $sep : '' )) . $object->town) : '');
1723
            if ($object->state && in_array($object->country_code, $countriesusingstate)) {
1724
                $ret .= ($ret ? ", " : '') . $object->state;
1725
            }
1726
        }
1727
        if (!is_object($outputlangs))
1728
            $outputlangs = $langs;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
1729
        if ($withcountry) {
1730
            $langs->load("dict");
1731
            $ret .= ($object->country_code ? ($ret ? $sep : '') . $outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country" . $object->country_code)) : '');
1732
        }
1733
1734
        return $ret;
1735
    }
1736
1737
    /**
1738
     * 	Format a string.
1739
     *
1740
     * 	@param	string	$fmt		Format of strftime static function (http://php.net/manual/fr/function.strftime.php)
1741
     *  @param	int		$ts			Timesamp (If is_gmt is true, timestamp is already includes timezone and daylight saving offset, if is_gmt is false, timestamp is a GMT timestamp and we must compensate with server PHP TZ)
1742
     *  @param	int		$is_gmt		See comment of timestamp parameter
1743
     * 	@return	string				A formatted string
1744
     */
1745
    static function dol_strftime($fmt, $ts = false, $is_gmt = false)
1746
    {
1747
        if ((abs($ts) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range
1748
            return ($is_gmt) ? @gmstrftime($fmt, $ts) : @strftime($fmt, $ts);
1749
        } else
1750
            return 'Error date into a not supported range';
1751
    }
1752
1753
    /**
1754
     * 	Output date in a string format according to outputlangs (or langs if not defined).
1755
     * 	Return charset is always UTF-8, except if encodetoouput is defined. In this case charset is output charset
1756
     *
1757
     * 	@param	int			$time			GM Timestamps date
1758
     * 	@param	string		$format      	Output date format (tag of strftime function)
1759
     * 										"%d %b %Y",
1760
     * 										"%d/%m/%Y %H:%M",
1761
     * 										"%d/%m/%Y %H:%M:%S",
1762
     *                                      "%B"=Long text of month, "%A"=Long text of day, "%b"=Short text of month, "%a"=Short text of day
1763
     * 										"day", "daytext", "dayhour", "dayhourldap", "dayhourtext", "dayrfc", "dayhourrfc", "...reduceformat"
1764
     * 	@param	string		$tzoutput		true or 'gmt' => string is for Greenwich location
1765
     * 										false or 'tzserver' => output string is for local PHP server TZ usage
1766
     * 										'tzuser' => output string is for user TZ (current browser TZ with current dst) => In a future, we should have same behaviour than 'tzuserrel'
1767
     *                                      'tzuserrel' => output string is for user TZ (current browser TZ with dst or not, depending on date position) (TODO not implemented yet)
1768
     * 	@param	Translate	$outputlangs	Object lang that contains language for text translation.
1769
     *  @param  boolean		$encodetooutput false=no convert into output pagecode
1770
     * 	@return string      				Formated date or '' if time is null
1771
     *
1772
     *  @see        dol_mktime, dol_stringtotime, dol_getdate
1773
     */
1774
    static function dol_print_date($time, $format = '', $tzoutput = 'tzserver', $outputlangs = '', $encodetooutput = false)
1775
    {
1776
       // global Globals::$conf, $langs;
1777
// Clean parameters
1778
        $to_gmt = false;
1779
        $offsettz = $offsetdst = 0;
1780
        if ($tzoutput) {
1781
            $to_gmt = true; // For backward compatibility
1782
            if (is_string($tzoutput)) {
1783
                if ($tzoutput == 'tzserver') {
1784
                    $to_gmt = false;
1785
                    $offsettzstring = @date_default_timezone_get();  // Example 'Europe/Berlin' or 'Indian/Reunion'
1786
                    $offsettz = 0;
1787
                    $offsetdst = 0;
1788
                } elseif ($tzoutput == 'tzuser' || $tzoutput == 'tzuserrel') {
1789
                    $to_gmt = true;
1790
                    $offsettzstring = (empty($_SESSION['dol_tz_string']) ? 'UTC' : $_SESSION['dol_tz_string']); // Example 'Europe/Berlin' or 'Indian/Reunion'
1791
                    $offsettz = (empty($_SESSION['dol_tz']) ? 0 : $_SESSION['dol_tz']) * 60 * 60;  // Will not be used anymore
1792
                    $offsetdst = (empty($_SESSION['dol_dst']) ? 0 : $_SESSION['dol_dst']) * 60 * 60; // Will not be used anymore
1793
                }
1794
            }
1795
        }
1796
        if (!is_object($outputlangs))
1797
            $outputlangs = $langs;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
1798
        if (!$format)
1799
            $format = 'daytextshort';
1800
        $reduceformat = (!empty(Globals::$conf->dol_optimize_smallscreen) && in_array($format, array('day', 'dayhour'))) ? 1 : 0;
1801
        $formatwithoutreduce = preg_replace('/reduceformat/', '', $format);
1802
        if ($formatwithoutreduce != $format) {
1803
            $format = $formatwithoutreduce;
1804
            $reduceformat = 1;
1805
        }  // so format 'dayreduceformat' is processed like day
1806
// Change predefined format into computer format. If found translation in lang file we use it, otherwise we use default.
1807
// TODO Add format daysmallyear and dayhoursmallyear
1808
        if ($format == 'day')
1809
            $format = ($outputlangs->trans("FormatDateShort") != "FormatDateShort" ? $outputlangs->trans("FormatDateShort") : Globals::$conf->format_date_short);
1810
        else if ($format == 'hour')
1811
            $format = ($outputlangs->trans("FormatHourShort") != "FormatHourShort" ? $outputlangs->trans("FormatHourShort") : Globals::$conf->format_hour_short);
1812
        else if ($format == 'hourduration')
1813
            $format = ($outputlangs->trans("FormatHourShortDuration") != "FormatHourShortDuration" ? $outputlangs->trans("FormatHourShortDuration") : Globals::$conf->format_hour_short_duration);
1814
        else if ($format == 'daytext')
1815
            $format = ($outputlangs->trans("FormatDateText") != "FormatDateText" ? $outputlangs->trans("FormatDateText") : Globals::$conf->format_date_text);
1816
        else if ($format == 'daytextshort')
1817
// Notice: Undefined property: stdClass::$format_date_text_short in \alixar\dolibarr\htdocs\core\lib\functions.lib.php on line 1781
1818
            $format = ($outputlangs->trans("FormatDateTextShort") != "FormatDateTextShort" ? $outputlangs->trans("FormatDateTextShort") : Globals::$conf->format_date_text_short);
1819
        else if ($format == 'dayhour')
1820
            $format = ($outputlangs->trans("FormatDateHourShort") != "FormatDateHourShort" ? $outputlangs->trans("FormatDateHourShort") : Globals::$conf->format_date_hour_short);
1821
        else if ($format == 'dayhoursec')
1822
            $format = ($outputlangs->trans("FormatDateHourSecShort") != "FormatDateHourSecShort" ? $outputlangs->trans("FormatDateHourSecShort") : Globals::$conf->format_date_hour_sec_short);
1823
        else if ($format == 'dayhourtext')
1824
            $format = ($outputlangs->trans("FormatDateHourText") != "FormatDateHourText" ? $outputlangs->trans("FormatDateHourText") : Globals::$conf->format_date_hour_text);
1825
        else if ($format == 'dayhourtextshort')
1826
            $format = ($outputlangs->trans("FormatDateHourTextShort") != "FormatDateHourTextShort" ? $outputlangs->trans("FormatDateHourTextShort") : Globals::$conf->format_date_hour_text_short);
1827
// Format not sensitive to language
1828
        else if ($format == 'dayhourlog')
1829
            $format = '%Y%m%d%H%M%S';
1830
        else if ($format == 'dayhourldap')
1831
            $format = '%Y%m%d%H%M%SZ';
1832
        else if ($format == 'dayhourxcard')
1833
            $format = '%Y%m%dT%H%M%SZ';
1834
        else if ($format == 'dayxcard')
1835
            $format = '%Y%m%d';
1836
        else if ($format == 'dayrfc')
1837
            $format = '%Y-%m-%d';             // DATE_RFC3339
1838
        else if ($format == 'dayhourrfc')
1839
            $format = '%Y-%m-%dT%H:%M:%SZ';   // DATETIME RFC3339
1840
        else if ($format == 'standard')
1841
            $format = '%Y-%m-%d %H:%M:%S';
1842
1843
        if ($reduceformat) {
1844
            $format = str_replace('%Y', '%y', $format);
1845
            $format = str_replace('yyyy', 'yy', $format);
1846
        }
1847
1848
// If date undefined or "", we return ""
1849
        if (dol_strlen($time) == 0)
1850
            return '';  // $time=0 allowed (it means 01/01/1970 00:00:00)
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
            
1885
// Clean format
1886
        if (preg_match('/%b/i', $format)) {  // There is some text to translate
1887
// We inhibate translation to text made by strftime functions. We will use trans instead later.
1888
            $format = str_replace('%b', '__b__', $format);
1889
            $format = str_replace('%B', '__B__', $format);
1890
        }
1891
        if (preg_match('/%a/i', $format)) {  // There is some text to translate
1892
// We inhibate translation to text made by strftime functions. We will use trans instead later.
1893
            $format = str_replace('%a', '__a__', $format);
1894
            $format = str_replace('%A', '__A__', $format);
1895
        }
1896
1897
// Analyze date
1898
        if (preg_match('/^([0-9]+)\-([0-9]+)\-([0-9]+) ?([0-9]+)?:?([0-9]+)?:?([0-9]+)?/i', $time, $reg) || preg_match('/^([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])$/i', $time, $reg)) { // Deprecated. Ex: 1970-01-01, 1970-01-01 01:00:00, 19700101010000
1899
// TODO Remove this.
1900
// This part of code should not be used.
1901
            dol_syslog("Functions.lib::dol_print_date static function call with deprecated value of time in page " . $_SERVER["PHP_SELF"], LOG_ERR);
1902
// Date has format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS' or 'YYYYMMDDHHMMSS'
1903
            $syear = (!empty($reg[1]) ? $reg[1] : '');
1904
            $smonth = (!empty($reg[2]) ? $reg[2] : '');
1905
            $sday = (!empty($reg[3]) ? $reg[3] : '');
1906
            $shour = (!empty($reg[4]) ? $reg[4] : '');
1907
            $smin = (!empty($reg[5]) ? $reg[5] : '');
1908
            $ssec = (!empty($reg[6]) ? $reg[6] : '');
1909
1910
            $time = dol_mktime($shour, $smin, $ssec, $smonth, $sday, $syear, true);
1911
            $ret = adodb_strftime($format, $time + $offsettz + $offsetdst, $to_gmt);
1912
        } else {
1913
// Date is a timestamps
1914
            if ($time < 100000000000) { // Protection against bad date values
1915
                $timetouse = $time + $offsettz + $offsetdst; // TODO Replace this with static function Date PHP. We also should not use anymore offsettz and offsetdst but only offsettzstring.
1916
1917
                $ret = adodb_strftime($format, $timetouse, $to_gmt);
1918
            } else
1919
                $ret = 'Bad value ' . $time . ' for date';
1920
        }
1921
1922
        if (preg_match('/__b__/i', $format)) {
1923
            $timetouse = $time + $offsettz + $offsetdst; // TODO Replace this with static function Date PHP. We also should not use anymore offsettz and offsetdst but only offsettzstring.
1924
// Here ret is string in PHP setup language (strftime was used). Now we convert to $outputlangs.
1925
            $month = adodb_strftime('%m', $timetouse);
1926
            $month = sprintf("%02d", $month); // $month may be return with format '06' on some installation and '6' on other, so we force it to '06'.
1927
            if ($encodetooutput) {
1928
                $monthtext = $outputlangs->transnoentities('Month' . $month);
1929
                $monthtextshort = $outputlangs->transnoentities('MonthShort' . $month);
1930
            } else {
1931
                $monthtext = $outputlangs->transnoentitiesnoconv('Month' . $month);
1932
                $monthtextshort = $outputlangs->transnoentitiesnoconv('MonthShort' . $month);
1933
            }
1934
//print 'monthtext='.$monthtext.' monthtextshort='.$monthtextshort;
1935
            $ret = str_replace('__b__', $monthtextshort, $ret);
1936
            $ret = str_replace('__B__', $monthtext, $ret);
1937
//print 'x'.$outputlangs->charset_output.'-'.$ret.'x';
1938
//return $ret;
1939
        }
1940
        if (preg_match('/__a__/i', $format)) {
1941
            $timetouse = $time + $offsettz + $offsetdst; // TODO Replace this with static function Date PHP. We also should not use anymore offsettz and offsetdst but only offsettzstring.
1942
1943
            $w = adodb_strftime('%w', $timetouse);      // TODO Replace this with static function Date PHP. We also should not use anymore offsettz and offsetdst but only offsettzstring.
1944
            $dayweek = $outputlangs->transnoentitiesnoconv('Day' . $w);
1945
            $ret = str_replace('__A__', $dayweek, $ret);
1946
            $ret = str_replace('__a__', dol_substr($dayweek, 0, 3), $ret);
1947
        }
1948
1949
        return $ret;
1950
    }
1951
1952
    /**
1953
     * 	Return an array with locale date info.
1954
     *  PHP getdate is restricted to the years 1901-2038 on Unix and 1970-2038 on Windows
1955
     *  WARNING: This static function always use PHP server timezone to return locale informations !!!
1956
     *  Usage must be avoid.
1957
     *  FIXME: Replace this with PHP date static function and a parameter $gm
1958
     *
1959
     * 	@param	int			$timestamp      Timestamp
1960
     * 	@param	boolean		$fast           Fast mode
1961
     * 	@return	array						Array of informations
1962
     * 										If no fast mode:
1963
     * 										'seconds' => $secs,
1964
     * 										'minutes' => $min,
1965
     * 										'hours' => $hour,
1966
     * 										'mday' => $day,
1967
     * 										'wday' => $dow,		0=sunday, 6=saturday
1968
     * 										'mon' => $month,
1969
     * 										'year' => $year,
1970
     * 										'yday' => floor($secsInYear/$_day_power),
1971
     * 										'weekday' => gmdate('l',$_day_power*(3+$dow)),
1972
     * 										'month' => gmdate('F',mktime(0,0,0,$month,2,1971)),
1973
     * 										If fast mode:
1974
     * 										'seconds' => $secs,
1975
     * 										'minutes' => $min,
1976
     * 										'hours' => $hour,
1977
     * 										'mday' => $day,
1978
     * 										'mon' => $month,
1979
     * 										'year' => $year,
1980
     * 										'yday' => floor($secsInYear/$_day_power),
1981
     * 										'leap' => $leaf,
1982
     * 										'ndays' => $ndays
1983
     * 	@see 								dol_print_date, dol_stringtotime, dol_mktime
1984
     */
1985
    static function dol_getdate($timestamp, $fast = false)
1986
    {
1987
       // global Globals::$conf;
1988
1989
        $usealternatemethod = false;
1990
        if ($timestamp <= 0)
1991
            $usealternatemethod = true;    // <= 1970
1992
        if ($timestamp >= 2145913200)
1993
            $usealternatemethod = true;  // >= 2038
1994
1995
        if ($usealternatemethod) {
1996
            $arrayinfo = adodb_getdate($timestamp, $fast);
1997
        } else {
1998
            $arrayinfo = getdate($timestamp);
1999
        }
2000
2001
        return $arrayinfo;
2002
    }
2003
2004
    /**
2005
     * 	Return a timestamp date built from detailed informations (by default a local PHP server timestamp)
2006
     * 	Replace static function mktime not available under Windows if year < 1970
2007
     * 	PHP mktime is restricted to the years 1901-2038 on Unix and 1970-2038 on Windows
2008
     *
2009
     * 	@param	int			$hour			Hour	(can be -1 for undefined)
2010
     * 	@param	int			$minute			Minute	(can be -1 for undefined)
2011
     * 	@param	int			$second			Second	(can be -1 for undefined)
2012
     * 	@param	int			$month			Month (1 to 12)
2013
     * 	@param	int			$day			Day (1 to 31)
2014
     * 	@param	int			$year			Year
2015
     * 	@param	mixed		$gm				True or 1 or 'gmt'=Input informations are GMT values
2016
     * 										False or 0 or 'server' = local to server TZ
2017
     * 										'user' = local to user TZ
2018
     * 										'tz,TimeZone' = use specified timezone
2019
     * 	@param	int			$check			0=No check on parameters (Can use day 32, etc...)
2020
     * 	@return	int|string					Date as a timestamp, '' or false if error
2021
     * 	@see 								dol_print_date, dol_stringtotime, dol_getdate
2022
     */
2023
    static function dol_mktime($hour, $minute, $second, $month, $day, $year, $gm = false, $check = 1)
2024
    {
2025
       // global Globals::$conf;
2026
//print "- ".$hour.",".$minute.",".$second.",".$month.",".$day.",".$year.",".$_SERVER["WINDIR"]." -";
2027
// Clean parameters
2028
        if ($hour == -1 || empty($hour))
2029
            $hour = 0;
2030
        if ($minute == -1 || empty($minute))
2031
            $minute = 0;
2032
        if ($second == -1 || empty($second))
2033
            $second = 0;
2034
2035
// Check parameters
2036
        if ($check) {
2037
            if (!$month || !$day)
2038
                return '';
2039
            if ($day > 31)
2040
                return '';
2041
            if ($month > 12)
2042
                return '';
2043
            if ($hour < 0 || $hour > 24)
2044
                return '';
2045
            if ($minute < 0 || $minute > 60)
2046
                return '';
2047
            if ($second < 0 || $second > 60)
2048
                return '';
2049
        }
2050
2051
        if (method_exists('DateTime', 'getTimestamp')) {
2052
            if (empty($gm) || $gm === 'server') {
2053
                $default_timezone = @date_default_timezone_get();  // Example 'Europe/Berlin'
2054
                $localtz = new DateTimeZone($default_timezone);
0 ignored issues
show
Bug introduced by
The type Alixar\Helpers\DateTimeZone was not found. Did you mean DateTimeZone? If so, make sure to prefix the type with \.
Loading history...
2055
            } else if ($gm === 'user') {
2056
// We use dol_tz_string first because it is more reliable.
2057
                $default_timezone = (empty($_SESSION["dol_tz_string"]) ? @date_default_timezone_get() : $_SESSION["dol_tz_string"]);  // Example 'Europe/Berlin'
2058
                try {
2059
                    $localtz = new DateTimeZone($default_timezone);
2060
                } catch (Exception $e) {
2061
                    dol_syslog("Warning dol_tz_string contains an invalid value " . $_SESSION["dol_tz_string"], LOG_WARNING);
2062
                    $default_timezone = @date_default_timezone_get();
2063
                }
2064
            } else if (strrpos($gm, "tz,") !== false) {
2065
                $timezone = str_replace("tz,", "", $gm);  // Example 'tz,Europe/Berlin'
2066
                try {
2067
                    $localtz = new DateTimeZone($timezone);
2068
                } catch (Exception $e) {
2069
                    dol_syslog("Warning passed timezone contains an invalid value " . $timezone, LOG_WARNING);
2070
                }
2071
            }
2072
2073
            if (empty($localtz)) {
2074
                $localtz = new DateTimeZone('UTC');
2075
            }
2076
//var_dump($localtz);
2077
//var_dump($year.'-'.$month.'-'.$day.'-'.$hour.'-'.$minute);
2078
            $dt = new DateTime(null, $localtz);
0 ignored issues
show
Bug introduced by
The type Alixar\Helpers\DateTime was not found. Did you mean DateTime? If so, make sure to prefix the type with \.
Loading history...
2079
            $dt->setDate($year, $month, $day);
2080
            $dt->setTime((int) $hour, (int) $minute, (int) $second);
2081
            $date = $dt->getTimestamp(); // should include daylight saving time
2082
//var_dump($date);
2083
            return $date;
2084
        } else {
2085
            dol_print_error('', 'PHP version must be 5.4+');
2086
            return '';
2087
        }
2088
    }
2089
2090
    /**
2091
     * 	Return date for now. In most cases, we use this static function without parameters (that means GMT time).
2092
     *
2093
     * 	@param	string		$mode	'gmt' => we return GMT timestamp,
2094
     * 								'tzserver' => we add the PHP server timezone
2095
     *  							'tzref' => we add the company timezone
2096
     * 								'tzuser' => we add the user timezone
2097
     * 	@return int   $date	Timestamp
2098
     */
2099
    static function dol_now($mode = 'gmt')
2100
    {
2101
        $ret = 0;
2102
2103
// Note that gmmktime and mktime return same value (GMT) when used without parameters
2104
//if ($mode == 'gmt') $ret=gmmktime(); // Strict Standards: gmmktime(): You should be using the time() static function instead
2105
        if ($mode == 'gmt')
2106
            $ret = time(); // Time for now at greenwich.
2107
        else if ($mode == 'tzserver') {  // Time for now with PHP server timezone added
2108
            require_once DOL_BASE_PATH . '/core/lib/date.lib.php';
2109
            $tzsecond = getServerTimeZoneInt('now');    // Contains tz+dayling saving time
2110
            $ret = (int) (dol_now('gmt') + ($tzsecond * 3600));
2111
        }
2112
        /* else if ($mode == 'tzref')				// Time for now with parent company timezone is added
2113
          {
2114
          require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
2115
          $tzsecond=getParentCompanyTimeZoneInt();    // Contains tz+dayling saving time
2116
          $ret=dol_now('gmt')+($tzsecond*3600);
2117
          } */ else if ($mode == 'tzuser') {    // Time for now with user timezone added
2118
//print 'time: '.time().'-'.mktime().'-'.gmmktime();
2119
            $offsettz = (empty($_SESSION['dol_tz']) ? 0 : $_SESSION['dol_tz']) * 60 * 60;
2120
            $offsetdst = (empty($_SESSION['dol_dst']) ? 0 : $_SESSION['dol_dst']) * 60 * 60;
2121
            $ret = (int) (dol_now('gmt') + ($offsettz + $offsetdst));
2122
        }
2123
2124
        return $ret;
2125
    }
2126
2127
    /**
2128
     * Return string with formated size
2129
     *
2130
     * @param	int		$size		Size to print
2131
     * @param	int		$shortvalue	Tell if we want long value to use another unit (Ex: 1.5Kb instead of 1500b)
2132
     * @param	int		$shortunit	Use short label of size unit (for example 'b' instead of 'bytes')
2133
     * @return	string				Link
2134
     */
2135
    static function dol_print_size($size, $shortvalue = 0, $shortunit = 0)
2136
    {
2137
       // global Globals::$conf, $langs;
2138
        $level = 1024;
2139
2140
        if (!empty(Globals::$conf->dol_optimize_smallscreen))
2141
            $shortunit = 1;
2142
2143
// Set value text
2144
        if (empty($shortvalue) || $size < ($level * 10)) {
2145
            $ret = $size;
2146
            $textunitshort = $langs->trans("b");
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
2147
            $textunitlong = $langs->trans("Bytes");
2148
        } else {
2149
            $ret = round($size / $level, 0);
2150
            $textunitshort = $langs->trans("Kb");
2151
            $textunitlong = $langs->trans("KiloBytes");
2152
        }
2153
// Use long or short text unit
2154
        if (empty($shortunit)) {
2155
            $ret .= ' ' . $textunitlong;
2156
        } else {
2157
            $ret .= ' ' . $textunitshort;
2158
        }
2159
2160
        return $ret;
2161
    }
2162
2163
    /**
2164
     * Show Url link
2165
     *
2166
     * @param	string		$url		Url to show
2167
     * @param	string		$target		Target for link
2168
     * @param	int			$max		Max number of characters to show
2169
     * @param	int			$withpicto	With picto
2170
     * @return	string					HTML Link
2171
     */
2172
    static function dol_print_url($url, $target = '_blank', $max = 32, $withpicto = 0)
2173
    {
2174
       // global $langs;
2175
2176
        if (empty($url))
2177
            return '';
2178
2179
        $link = '<a href="';
2180
        if (!preg_match('/^http/i', $url))
2181
            $link .= 'http://';
2182
        $link .= $url;
2183
        $link .= '"';
2184
        if ($target)
2185
            $link .= ' target="' . $target . '"';
2186
        $link .= '>';
2187
        if (!preg_match('/^http/i', $url))
2188
            $link .= 'http://';
2189
        $link .= dol_trunc($url, $max);
2190
        $link .= '</a>';
2191
        return '<div class="nospan float" style="margin-right: 10px">' . ($withpicto ? img_picto($langs->trans("Url"), 'object_globe.png') . ' ' : '') . $link . '</div>';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
2192
    }
2193
2194
    /**
2195
     * Show EMail link
2196
     *
2197
     * @param	string		$email			EMail to show (only email, without 'Name of recipient' before)
2198
     * @param 	int			$cid 			Id of contact if known
2199
     * @param 	int			$socid 			Id of third party if known
2200
     * @param 	int			$addlink		0=no link, 1=email has a html email link (+ link to create action if constant AGENDA_ADDACTIONFOREMAIL is on)
2201
     * @param	int			$max			Max number of characters to show
2202
     * @param	int			$showinvalid	Show warning if syntax email is wrong
2203
     * @param	int			$withpicto		Show picto
2204
     * @return	string						HTML Link
2205
     */
2206
    static function dol_print_email($email, $cid = 0, $socid = 0, $addlink = 0, $max = 64, $showinvalid = 1, $withpicto = 0)
2207
    {
2208
       // global Globals::$conf, $user, $langs, $hookmanager;
2209
2210
        $newemail = $email;
2211
2212
        if (empty($email))
2213
            return '&nbsp;';
2214
2215
        if (!empty($addlink)) {
2216
            $newemail = '<a style="text-overflow: ellipsis;" href="';
2217
            if (!preg_match('/^mailto:/i', $email))
2218
                $newemail .= 'mailto:';
2219
            $newemail .= $email;
2220
            $newemail .= '">';
2221
            $newemail .= dol_trunc($email, $max);
2222
            $newemail .= '</a>';
2223
            if ($showinvalid && !isValidEmail($email)) {
2224
                $langs->load("errors");
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
2225
                $newemail .= img_warning($langs->trans("ErrorBadEMail", $email));
2226
            }
2227
2228
            if (($cid || $socid) && !empty(Globals::$conf->agenda->enabled) && $user->rights->agenda->myactions->create) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $user seems to be never defined.
Loading history...
2229
                $type = 'AC_EMAIL';
2230
                $link = '';
2231
                if (!empty(Globals::$conf->global->AGENDA_ADDACTIONFOREMAIL))
2232
                    $link = '<a href="' . DOL_BASE_URI . '/comm/action/card.php?action=create&amp;backtopage=1&amp;actioncode=' . $type . '&amp;contactid=' . $cid . '&amp;socid=' . $socid . '">' . img_object($langs->trans("AddAction"), "calendar") . '</a>';
2233
                if ($link)
2234
                    $newemail = '<div>' . $newemail . ' ' . $link . '</div>';
2235
            }
2236
        }
2237
        else {
2238
            if ($showinvalid && !isValidEmail($email)) {
2239
                $langs->load("errors");
2240
                $newemail .= img_warning($langs->trans("ErrorBadEMail", $email));
2241
            }
2242
        }
2243
2244
        $rep = '<div class="nospan float" style="margin-right: 10px">' . ($withpicto ? img_picto($langs->trans("EMail"), 'object_email.png') . ' ' : '') . $newemail . '</div>';
2245
        if ($hookmanager) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $hookmanager seems to be never defined.
Loading history...
2246
            $parameters = array('cid' => $cid, 'socid' => $socid, 'addlink' => $addlink, 'picto' => $withpicto);
2247
            $reshook = $hookmanager->executeHooks('printEmail', $parameters, $email);
2248
            $rep .= $hookmanager->resPrint;
2249
        }
2250
2251
        return $rep;
2252
    }
2253
2254
    /**
2255
     * Show social network link
2256
     *
2257
     * @param	string		$value			Skype to show (only skype, without 'Name of recipient' before)
2258
     * @param	int 		$cid 			Id of contact if known
2259
     * @param	int 		$socid 			Id of third party if known
2260
     * @param	string 		$type			'skype','facebook',...
2261
     * @return	string						HTML Link
2262
     */
2263
    static function dol_print_socialnetworks($value, $cid, $socid, $type)
2264
    {
2265
       // global Globals::$conf, $user, $langs;
2266
2267
        $newskype = $value;
2268
2269
        if (empty($value))
2270
            return '&nbsp;';
2271
2272
        if (!empty($type)) {
2273
            $newskype = '<div class="divsocialnetwork inline-block valignmiddle">';
2274
            $newskype .= img_picto($langs->trans(strtoupper($type)), $type . '.png', '', false, 0, 0, '', 'paddingright');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
2275
            $newskype .= $value;
2276
            if ($type == 'skype') {
2277
                $newskype .= '&nbsp;';
2278
                $newskype .= '<a href="skype:';
2279
                $newskype .= $value;
2280
                $newskype .= '?call" alt="' . $langs->trans("Call") . '&nbsp;' . $value . '" title="' . $langs->trans("Call") . '&nbsp;' . $value . '">';
2281
                $newskype .= '<img src="' . DOL_BASE_URI . '/theme/common/skype_callbutton.png" border="0">';
2282
                $newskype .= '</a><a href="skype:';
2283
                $newskype .= $value;
2284
                $newskype .= '?chat" alt="' . $langs->trans("Chat") . '&nbsp;' . $value . '" title="' . $langs->trans("Chat") . '&nbsp;' . $value . '">';
2285
                $newskype .= '<img class="paddingleft" src="' . DOL_BASE_URI . '/theme/common/skype_chatbutton.png" border="0">';
2286
                $newskype .= '</a>';
2287
            }
2288
            if (($cid || $socid) && !empty(Globals::$conf->agenda->enabled) && $user->rights->agenda->myactions->create && $type == 'skype') {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $user seems to be never defined.
Loading history...
2289
                $addlink = 'AC_SKYPE';
2290
                $link = '';
2291
                if (!empty(Globals::$conf->global->AGENDA_ADDACTIONFORSKYPE))
2292
                    $link = '<a href="' . DOL_BASE_URI . '/comm/action/card.php?action=create&amp;backtopage=1&amp;actioncode=' . $addlink . '&amp;contactid=' . $cid . '&amp;socid=' . $socid . '">' . img_object($langs->trans("AddAction"), "calendar") . '</a>';
2293
                $newskype .= ($link ? ' ' . $link : '');
2294
            }
2295
            $newskype .= '</div>';
2296
        }
2297
        else {
2298
            $langs->load("errors");
2299
            $newskype .= img_warning($langs->trans("ErrorBadSocialNetworkValue", $value));
2300
        }
2301
        return $newskype;
2302
    }
2303
2304
    /**
2305
     * 	Format phone numbers according to country
2306
     *
2307
     * 	@param  string  $phone          Phone number to format
2308
     * 	@param  string  $countrycode    Country code to use for formatting
2309
     * 	@param 	int		$cid 		    Id of contact if known
2310
     * 	@param 	int		$socid          Id of third party if known
2311
     * 	@param 	string	$addlink	    ''=no link to create action, 'AC_TEL'=add link to clicktodial (if module enabled) and add link to create event (if conf->global->AGENDA_ADDACTIONFORPHONE set)
2312
     * 	@param 	string	$separ 		    Separation between numbers for a better visibility example : xx.xx.xx.xx.xx
2313
     *  @param	string  $withpicto      Show picto
2314
     *  @param	string	$titlealt	    Text to show on alt
2315
     *  @param  int     $adddivfloat    Add div float around phone.
2316
     * 	@return string 				    Formated phone number
2317
     */
2318
    static function dol_print_phone($phone, $countrycode = '', $cid = 0, $socid = 0, $addlink = '', $separ = "&nbsp;", $withpicto = '', $titlealt = '', $adddivfloat = 0)
2319
    {
2320
       // global Globals::$conf, $user, $langs, $mysoc, $hookmanager;
2321
// Clean phone parameter
2322
        $phone = preg_replace("/[\s.-]/", "", trim($phone));
2323
        if (empty($phone)) {
2324
            return '';
2325
        }
2326
        if (empty($countrycode))
2327
            $countrycode = $mysoc->country_code;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mysoc seems to be never defined.
Loading history...
2328
2329
// Short format for small screens
2330
        if (Globals::$conf->dol_optimize_smallscreen)
2331
            $separ = '';
2332
2333
        $newphone = $phone;
2334
        if (strtoupper($countrycode) == "FR") {
2335
// France
2336
            if (dol_strlen($phone) == 10) {
2337
                $newphone = substr($newphone, 0, 2) . $separ . substr($newphone, 2, 2) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 2);
2338
            } elseif (dol_strlen($phone) == 7) {
2339
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 2) . $separ . substr($newphone, 5, 2);
2340
            } elseif (dol_strlen($phone) == 9) {
2341
                $newphone = substr($newphone, 0, 2) . $separ . substr($newphone, 2, 3) . $separ . substr($newphone, 5, 2) . $separ . substr($newphone, 7, 2);
2342
            } elseif (dol_strlen($phone) == 11) {
2343
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 2) . $separ . substr($newphone, 5, 2) . $separ . substr($newphone, 7, 2) . $separ . substr($newphone, 9, 2);
2344
            } elseif (dol_strlen($phone) == 12) {
2345
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2);
2346
            }
2347
        } elseif (strtoupper($countrycode) == "CA") {
2348
            if (dol_strlen($phone) == 10) {
2349
                $newphone = ($separ != '' ? '(' : '') . substr($newphone, 0, 3) . ($separ != '' ? ')' : '') . $separ . substr($newphone, 3, 3) . ($separ != '' ? '-' : '') . substr($newphone, 6, 4);
2350
            }
2351
        } elseif (strtoupper($countrycode) == "PT") {//Portugal
2352
            if (dol_strlen($phone) == 13) {//ex: +351_ABC_DEF_GHI
2353
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 3) . $separ . substr($newphone, 10, 3);
2354
            }
2355
        } elseif (strtoupper($countrycode) == "SR") {//Suriname
2356
            if (dol_strlen($phone) == 10) {//ex: +597_ABC_DEF
2357
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 3);
2358
            } elseif (dol_strlen($phone) == 11) {//ex: +597_ABC_DEFG
2359
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 4);
2360
            }
2361
        } elseif (strtoupper($countrycode) == "DE") {//Allemagne
2362
            if (dol_strlen($phone) == 14) {//ex:  +49_ABCD_EFGH_IJK
2363
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 4) . $separ . substr($newphone, 7, 4) . $separ . substr($newphone, 11, 3);
2364
            } elseif (dol_strlen($phone) == 13) {//ex: +49_ABC_DEFG_HIJ
2365
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 4) . $separ . substr($newphone, 10, 3);
2366
            }
2367
        } elseif (strtoupper($countrycode) == "ES") {//Espagne
2368
            if (dol_strlen($phone) == 12) {//ex:  +34_ABC_DEF_GHI
2369
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 3) . $separ . substr($newphone, 9, 3);
2370
            }
2371
        } elseif (strtoupper($countrycode) == "BF") {// Burkina Faso
2372
            if (dol_strlen($phone) == 12) {//ex :  +22 A BC_DE_FG_HI
2373
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 1) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2);
2374
            }
2375
        } elseif (strtoupper($countrycode) == "RO") {// Roumanie
2376
            if (dol_strlen($phone) == 12) {//ex :  +40 AB_CDE_FG_HI
2377
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 2) . $separ . substr($newphone, 5, 3) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2);
2378
            }
2379
        } elseif (strtoupper($countrycode) == "TR") {//Turquie
2380
            if (dol_strlen($phone) == 13) {//ex :  +90 ABC_DEF_GHIJ
2381
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 3) . $separ . substr($newphone, 9, 4);
2382
            }
2383
        } elseif (strtoupper($countrycode) == "US") {//Etat-Unis
2384
            if (dol_strlen($phone) == 12) {//ex: +1 ABC_DEF_GHIJ
2385
                $newphone = substr($newphone, 0, 2) . $separ . substr($newphone, 2, 3) . $separ . substr($newphone, 5, 3) . $separ . substr($newphone, 8, 4);
2386
            }
2387
        } elseif (strtoupper($countrycode) == "MX") {//Mexique
2388
            if (dol_strlen($phone) == 12) {//ex: +52 ABCD_EFG_HI
2389
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 4) . $separ . substr($newphone, 7, 3) . $separ . substr($newphone, 10, 2);
2390
            } elseif (dol_strlen($phone) == 11) {//ex: +52 AB_CD_EF_GH
2391
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 2) . $separ . substr($newphone, 5, 2) . $separ . substr($newphone, 7, 2) . $separ . substr($newphone, 9, 2);
2392
            } elseif (dol_strlen($phone) == 13) {//ex: +52 ABC_DEF_GHIJ
2393
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 3) . $separ . substr($newphone, 9, 4);
2394
            }
2395
        } elseif (strtoupper($countrycode) == "ML") {//Mali
2396
            if (dol_strlen($phone) == 12) {//ex: +223 AB_CD_EF_GH
2397
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2);
2398
            }
2399
        } elseif (strtoupper($countrycode) == "TH") {//Thaïlande
2400
            if (dol_strlen($phone) == 11) {//ex: +66_ABC_DE_FGH
2401
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 3);
2402
            } elseif (dol_strlen($phone) == 12) {//ex: +66_A_BCD_EF_GHI
2403
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 1) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 2) . $separ . substr($newphone, 9, 3);
2404
            }
2405
        } elseif (strtoupper($countrycode) == "MU") {//Maurice
2406
            if (dol_strlen($phone) == 11) {//ex: +230_ABC_DE_FG
2407
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 2) . $separ . substr($newphone, 9, 2);
2408
            } elseif (dol_strlen($phone) == 12) {//ex: +230_ABCD_EF_GH
2409
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 4) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2);
2410
            }
2411
        } elseif (strtoupper($countrycode) == "ZA") {//Afrique du sud
2412
            if (dol_strlen($phone) == 12) {//ex: +27_AB_CDE_FG_HI
2413
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 2) . $separ . substr($newphone, 5, 3) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2);
2414
            }
2415
        } elseif (strtoupper($countrycode) == "SY") {//Syrie
2416
            if (dol_strlen($phone) == 12) {//ex: +963_AB_CD_EF_GH
2417
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2);
2418
            } elseif (dol_strlen($phone) == 13) {//ex: +963_AB_CD_EF_GHI
2419
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 3);
2420
            }
2421
        } elseif (strtoupper($countrycode) == "AE") {//Emirats Arabes Unis
2422
            if (dol_strlen($phone) == 12) {//ex: +971_ABC_DEF_GH
2423
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 3) . $separ . substr($newphone, 10, 2);
2424
            } elseif (dol_strlen($phone) == 13) {//ex: +971_ABC_DEF_GHI
2425
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 3) . $separ . substr($newphone, 10, 3);
2426
            } elseif (dol_strlen($phone) == 14) {//ex: +971_ABC_DEF_GHIK
2427
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 3) . $separ . substr($newphone, 10, 4);
2428
            }
2429
        } elseif (strtoupper($countrycode) == "DZ") {//Algérie
2430
            if (dol_strlen($phone) == 13) {//ex: +213_ABC_DEF_GHI
2431
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 3) . $separ . substr($newphone, 10, 3);
2432
            }
2433
        } elseif (strtoupper($countrycode) == "BE") {//Belgique
2434
            if (dol_strlen($phone) == 11) {//ex: +32_ABC_DE_FGH
2435
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 3);
2436
            } elseif (dol_strlen($phone) == 12) {//ex: +32_ABC_DEF_GHI
2437
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 3) . $separ . substr($newphone, 9, 3);
2438
            }
2439
        } elseif (strtoupper($countrycode) == "PF") {//Polynésie française
2440
            if (dol_strlen($phone) == 12) {//ex: +689_AB_CD_EF_GH
2441
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2);
2442
            }
2443
        } elseif (strtoupper($countrycode) == "CO") {//Colombie
2444
            if (dol_strlen($phone) == 13) {//ex: +57_ABC_DEF_GH_IJ
2445
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 3) . $separ . substr($newphone, 9, 2) . $separ . substr($newphone, 11, 2);
2446
            }
2447
        } elseif (strtoupper($countrycode) == "JO") {//Jordanie
2448
            if (dol_strlen($phone) == 12) {//ex: +962_A_BCD_EF_GH
2449
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 1) . $separ . substr($newphone, 5, 3) . $separ . substr($newphone, 7, 2) . $separ . substr($newphone, 9, 2);
2450
            }
2451
        } elseif (strtoupper($countrycode) == "MG") {//Madagascar
2452
            if (dol_strlen($phone) == 13) {//ex: +261_AB_CD_EF_GHI
2453
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 2) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 3);
2454
            }
2455
        } elseif (strtoupper($countrycode) == "GB") {//Royaume uni
2456
            if (dol_strlen($phone) == 13) {//ex: +44_ABCD_EFG_HIJ
2457
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 4) . $separ . substr($newphone, 7, 3) . $separ . substr($newphone, 10, 3);
2458
            }
2459
        } elseif (strtoupper($countrycode) == "CH") {//Suisse
2460
            if (dol_strlen($phone) == 12) {//ex: +41_AB_CDE_FG_HI
2461
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 2) . $separ . substr($newphone, 5, 3) . $separ . substr($newphone, 8, 2) . $separ . substr($newphone, 10, 2);
2462
            } elseif (dol_strlen($phone) == 15) {// +41_AB_CDE_FGH_IJKL
2463
                $newphone = $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 2) . $separ . substr($newphone, 5, 3) . $separ . substr($newphone, 8, 3) . $separ . substr($newphone, 11, 4);
2464
            }
2465
        } elseif (strtoupper($countrycode) == "TN") {//Tunisie
2466
            if (dol_strlen($phone) == 12) {//ex: +216_AB_CDE_FGH
2467
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 2) . $separ . substr($newphone, 6, 3) . $separ . substr($newphone, 9, 3);
2468
            }
2469
        } elseif (strtoupper($countrycode) == "GF") {//Guyane francaise
2470
            if (dol_strlen($phone) == 13) {//ex: +594_ABC_DE_FG_HI  (ABC=594 de nouveau)
2471
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 2) . $separ . substr($newphone, 9, 2) . $separ . substr($newphone, 11, 2);
2472
            }
2473
        } elseif (strtoupper($countrycode) == "GP") {//Guadeloupe
2474
            if (dol_strlen($phone) == 13) {//ex: +590_ABC_DE_FG_HI  (ABC=590 de nouveau)
2475
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 2) . $separ . substr($newphone, 9, 2) . $separ . substr($newphone, 11, 2);
2476
            }
2477
        } elseif (strtoupper($countrycode) == "MQ") {//Martinique
2478
            if (dol_strlen($phone) == 13) {//ex: +596_ABC_DE_FG_HI  (ABC=596 de nouveau)
2479
                $newphone = substr($newphone, 0, 4) . $separ . substr($newphone, 4, 3) . $separ . substr($newphone, 7, 2) . $separ . substr($newphone, 9, 2) . $separ . substr($newphone, 11, 2);
2480
            }
2481
        } elseif (strtoupper($countrycode) == "IT") {//Italie
2482
            if (dol_strlen($phone) == 12) {//ex: +39_ABC_DEF_GHI
2483
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 3) . $separ . substr($newphone, 9, 3);
2484
            } elseif (dol_strlen($phone) == 13) {//ex: +39_ABC_DEF_GH_IJ
2485
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 3) . $separ . substr($newphone, 6, 3) . $separ . substr($newphone, 9, 2) . $separ . substr($newphone, 11, 2);
2486
            }
2487
        } elseif (strtoupper($countrycode) == "AU") {//Australie
2488
            if (dol_strlen($phone) == 12) {//ex: +61_A_BCDE_FGHI
2489
                $newphone = substr($newphone, 0, 3) . $separ . substr($newphone, 3, 1) . $separ . substr($newphone, 4, 4) . $separ . substr($newphone, 8, 4);
2490
            }
2491
        }
2492
        if (!empty($addlink)) { // Link on phone number (+ link to add action if conf->global->AGENDA_ADDACTIONFORPHONE set)
2493
            if (Globals::$conf->browser->layout == 'phone' || (!empty(Globals::$conf->clicktodial->enabled) && !empty(Globals::$conf->global->CLICKTODIAL_USE_TEL_LINK_ON_PHONE_NUMBERS))) { // If phone or option for, we use link of phone
2494
                $newphone = '<a href="tel:' . $phone . '"';
2495
                $newphone .= '>' . $phone . '</a>';
2496
            } else if (!empty(Globals::$conf->clicktodial->enabled) && $addlink == 'AC_TEL') {  // If click to dial, we use click to dial url
2497
                if (empty($user->clicktodial_loaded))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $user seems to be never defined.
Loading history...
2498
                    $user->fetch_clicktodial();
2499
2500
// Define urlmask
2501
                $urlmask = 'ErrorClickToDialModuleNotConfigured';
2502
                if (!empty(Globals::$conf->global->CLICKTODIAL_URL))
2503
                    $urlmask = Globals::$conf->global->CLICKTODIAL_URL;
2504
                if (!empty($user->clicktodial_url))
2505
                    $urlmask = $user->clicktodial_url;
2506
2507
                $clicktodial_poste = (!empty($user->clicktodial_poste) ? urlencode($user->clicktodial_poste) : '');
2508
                $clicktodial_login = (!empty($user->clicktodial_login) ? urlencode($user->clicktodial_login) : '');
2509
                $clicktodial_password = (!empty($user->clicktodial_password) ? urlencode($user->clicktodial_password) : '');
2510
// This line is for backward compatibility
2511
                $url = sprintf($urlmask, urlencode($phone), $clicktodial_poste, $clicktodial_login, $clicktodial_password);
2512
// Thoose lines are for substitution
2513
                $substitarray = array('__PHONEFROM__' => $clicktodial_poste,
2514
                    '__PHONETO__' => urlencode($phone),
2515
                    '__LOGIN__' => $clicktodial_login,
2516
                    '__PASS__' => $clicktodial_password);
2517
                $url = make_substitutions($url, $substitarray);
2518
                $newphonesav = $newphone;
2519
                $newphone = '<a href="' . $url . '"';
2520
                if (!empty(Globals::$conf->global->CLICKTODIAL_FORCENEWTARGET))
2521
                    $newphone .= ' target="_blank"';
2522
                $newphone .= '>' . $newphonesav . '</a>';
2523
            }
2524
2525
//if (($cid || $socid) && ! empty(Globals::$conf->agenda->enabled) && $user->rights->agenda->myactions->create)
2526
            if (!empty(Globals::$conf->agenda->enabled) && $user->rights->agenda->myactions->create) {
2527
                $type = 'AC_TEL';
2528
                $link = '';
2529
                if ($addlink == 'AC_FAX')
2530
                    $type = 'AC_FAX';
2531
                if (!empty(Globals::$conf->global->AGENDA_ADDACTIONFORPHONE))
2532
                    $link = '<a href="' . DOL_BASE_URI . '/comm/action/card.php?action=create&amp;backtopage=1&amp;actioncode=' . $type . ($cid ? '&amp;contactid=' . $cid : '') . ($socid ? '&amp;socid=' . $socid : '') . '">' . img_object($langs->trans("AddAction"), "calendar") . '</a>';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
2533
                if ($link)
2534
                    $newphone = '<div>' . $newphone . ' ' . $link . '</div>';
2535
            }
2536
        }
2537
2538
        if (empty($titlealt)) {
2539
            $titlealt = ($withpicto == 'fax' ? $langs->trans("Fax") : $langs->trans("Phone"));
2540
        }
2541
        $rep = '';
2542
2543
        if ($hookmanager) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $hookmanager seems to be never defined.
Loading history...
2544
            $parameters = array('countrycode' => $countrycode, 'cid' => $cid, 'socid' => $socid, 'titlealt' => $titlealt, 'picto' => $withpicto);
2545
            $reshook = $hookmanager->executeHooks('printPhone', $parameters, $phone);
2546
            $rep .= $hookmanager->resPrint;
2547
        }
2548
        if (empty($reshook)) {
2549
            $picto = '';
2550
            if ($withpicto) {
2551
                if ($withpicto == 'fax') {
2552
                    $picto = 'phoning_fax';
2553
                } elseif ($withpicto == 'phone') {
2554
                    $picto = 'phoning';
2555
                } elseif ($withpicto == 'mobile') {
2556
                    $picto = 'phoning_mobile';
2557
                } else {
2558
                    $picto = '';
2559
                }
2560
            }
2561
            if ($adddivfloat)
2562
                $rep .= '<div class="nospan float" style="margin-right: 10px">';
2563
            else
2564
                $rep .= '<span style="margin-right: 10px;">';
2565
            $rep .= ($withpicto ? img_picto($titlealt, 'object_' . $picto . '.png') . ' ' : '') . $newphone;
2566
            if ($adddivfloat)
2567
                $rep .= '</div>';
2568
            else
2569
                $rep .= '</span>';
2570
        }
2571
2572
        return $rep;
2573
    }
2574
2575
    /**
2576
     * 	Return an IP formated to be shown on screen
2577
     *
2578
     * 	@param	string	$ip			IP
2579
     * 	@param	int		$mode		0=return IP + country/flag, 1=return only country/flag, 2=return only IP
2580
     * 	@return string 				Formated IP, with country if GeoIP module is enabled
2581
     */
2582
    static function dol_print_ip($ip, $mode = 0)
2583
    {
2584
       // global Globals::$conf, $langs;
2585
2586
        $ret = '';
2587
2588
        if (empty($mode)) {
2589
            $ret .= $ip;
2590
        }
2591
2592
        echo ('<p>DOL_BASE_PATH: ' . DOL_BASE_PATH . '/DOL_BASE_URI: ' . DOL_BASE_URI . '</p>');
2593
2594
        if ($mode != 2) {
2595
            $countrycode = dolGetCountryCodeFromIp($ip);
2596
            if ($countrycode) { // If success, countrycode is us, fr, ...
2597
                if (file_exists(DOL_BASE_PATH . '/theme/common/flags/' . $countrycode . '.png')) {
2598
                    $ret .= ' ' . img_picto($countrycode . ' ' . $langs->trans("AccordingToGeoIPDatabase"), DOL_BASE_URI . '/theme/common/flags/' . $countrycode . '.png', '', 1);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
2599
                } else
2600
                    $ret .= ' (' . $countrycode . ')';
2601
            }
2602
        }
2603
2604
        return $ret;
2605
    }
2606
2607
    /**
2608
     * Return the IP of remote user.
2609
     * Take HTTP_X_FORWARDED_FOR (defined when using proxy)
2610
     * Then HTTP_CLIENT_IP if defined (rare)
2611
     * Then REMOTE_ADDR (not way to be modified by user but may be wrong if using proxy)
2612
     *
2613
     * @return	string		Ip of remote user.
2614
     */
2615
    static function getUserRemoteIP()
2616
    {
2617
        $ip = empty($_SERVER['HTTP_X_FORWARDED_FOR']) ? (empty($_SERVER['HTTP_CLIENT_IP']) ? (empty($_SERVER['REMOTE_ADDR']) ? '' : $_SERVER['REMOTE_ADDR']) : $_SERVER['HTTP_CLIENT_IP']) : $_SERVER['HTTP_X_FORWARDED_FOR'];
2618
        return $ip;
2619
    }
2620
2621
    /**
2622
     * 	Return a country code from IP. Empty string if not found.
2623
     *
2624
     * 	@param	string	$ip			IP
2625
     * 	@return string 				Country code ('us', 'fr', ...)
2626
     */
2627
    static function dolGetCountryCodeFromIp($ip)
2628
    {
2629
       // global Globals::$conf;
2630
2631
        $countrycode = '';
2632
2633
        if (!empty(Globals::$conf->geoipmaxmind->enabled)) {
2634
            $datafile = Globals::$conf->global->GEOIPMAXMIND_COUNTRY_DATAFILE;
2635
//$ip='24.24.24.24';
2636
//$datafile='E:\Mes Sites\Web\Admin1\awstats\maxmind\GeoIP.dat';    Note that this must be downloaded datafile (not same than datafile provided with ubuntu packages)
2637
2638
            include_once DOL_BASE_PATH . '/core/class/dolgeoip.class.php';
2639
            $geoip = new DolGeoIP('country', $datafile);
0 ignored issues
show
Bug introduced by
The type Alixar\Helpers\DolGeoIP was not found. Did you mean DolGeoIP? If so, make sure to prefix the type with \.
Loading history...
2640
//print 'ip='.$ip.' databaseType='.$geoip->gi->databaseType." GEOIP_CITY_EDITION_REV1=".GEOIP_CITY_EDITION_REV1."\n";
2641
//print "geoip_country_id_by_addr=".geoip_country_id_by_addr($geoip->gi,$ip)."\n";
2642
            $countrycode = $geoip->getCountryCodeFromIP($ip);
2643
        }
2644
2645
        return $countrycode;
2646
    }
2647
2648
    /**
2649
     *  Return country code for current user.
2650
     *  If software is used inside a local network, detection may fails (we need a public ip)
2651
     *
2652
     *  @return     string      Country code (fr, es, it, us, ...)
2653
     */
2654
    static function dol_user_country()
2655
    {
2656
       // global Globals::$conf, $langs, $user;
2657
//$ret=$user->xxx;
2658
        $ret = '';
2659
        if (!empty(Globals::$conf->geoipmaxmind->enabled)) {
2660
            $ip = getUserRemoteIP();
2661
            $datafile = Globals::$conf->global->GEOIPMAXMIND_COUNTRY_DATAFILE;
2662
//$ip='24.24.24.24';
2663
//$datafile='E:\Mes Sites\Web\Admin1\awstats\maxmind\GeoIP.dat';
2664
            include_once DOL_BASE_PATH . '/core/class/dolgeoip.class.php';
2665
            $geoip = new DolGeoIP('country', $datafile);
2666
            $countrycode = $geoip->getCountryCodeFromIP($ip);
2667
            $ret = $countrycode;
2668
        }
2669
        return $ret;
2670
    }
2671
2672
    /**
2673
     *  Format address string
2674
     *
2675
     *  @param	string	$address    Address
2676
     *  @param  int		$htmlid     Html ID (for example 'gmap')
2677
     *  @param  int		$mode       thirdparty|contact|member|other
2678
     *  @param  int		$id         Id of object
2679
     *  @param	int		$noprint	No output. Result is the static function return
2680
     *  @param  string  $charfornl  Char to use instead of nl2br. '' means we use a standad nl2br.
2681
     *  @return string|void			Nothing if noprint is 0, formatted address if noprint is 1
2682
     *  @see dol_format_address
2683
     */
2684
    static function dol_print_address($address, $htmlid, $mode, $id, $noprint = 0, $charfornl = '')
2685
    {
2686
       // global Globals::$conf, $user, $langs, $hookmanager;
2687
2688
        $out = '';
2689
2690
        if ($address) {
2691
            if ($hookmanager) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $hookmanager seems to be never defined.
Loading history...
2692
                $parameters = array('element' => $mode, 'id' => $id);
2693
                $reshook = $hookmanager->executeHooks('printAddress', $parameters, $address);
2694
                $out .= $hookmanager->resPrint;
2695
            }
2696
            if (empty($reshook)) {
2697
                if (empty($charfornl))
2698
                    $out .= nl2br($address);
2699
                else
2700
                    $out .= preg_replace('/[\r\n]+/', $charfornl, $address);
2701
2702
                $showgmap = $showomap = 0;
2703
2704
// TODO Add a hook here
2705
                if (($mode == 'thirdparty' || $mode == 'societe') && !empty(Globals::$conf->google->enabled) && !empty(Globals::$conf->global->GOOGLE_ENABLE_GMAPS))
2706
                    $showgmap = 1;
2707
                if ($mode == 'contact' && !empty(Globals::$conf->google->enabled) && !empty(Globals::$conf->global->GOOGLE_ENABLE_GMAPS_CONTACTS))
2708
                    $showgmap = 1;
2709
                if ($mode == 'member' && !empty(Globals::$conf->google->enabled) && !empty(Globals::$conf->global->GOOGLE_ENABLE_GMAPS_MEMBERS))
2710
                    $showgmap = 1;
2711
                if (($mode == 'thirdparty' || $mode == 'societe') && !empty(Globals::$conf->openstreetmap->enabled) && !empty(Globals::$conf->global->OPENSTREETMAP_ENABLE_MAPS))
2712
                    $showomap = 1;
2713
                if ($mode == 'contact' && !empty(Globals::$conf->openstreetmap->enabled) && !empty(Globals::$conf->global->OPENSTREETMAP_ENABLE_MAPS_CONTACTS))
2714
                    $showomap = 1;
2715
                if ($mode == 'member' && !empty(Globals::$conf->openstreetmap->enabled) && !empty(Globals::$conf->global->OPENSTREETMAP_ENABLE_MAPS_MEMBERS))
2716
                    $showomap = 1;
2717
2718
                if ($showgmap) {
2719
                    $url = dol_buildpath('/google/gmaps.php?mode=' . $mode . '&id=' . $id, 1);
2720
                    $out .= ' <a href="' . $url . '" target="_gmaps"><img id="' . $htmlid . '" class="valigntextbottom" src="' . DOL_BASE_URI . '/theme/common/gmap.png"></a>';
2721
                }
2722
                if ($showomap) {
2723
                    $url = dol_buildpath('/openstreetmap/maps.php?mode=' . $mode . '&id=' . $id, 1);
2724
                    $out .= ' <a href="' . $url . '" target="_gmaps"><img id="' . $htmlid . '_openstreetmap" class="valigntextbottom" src="' . DOL_BASE_URI . '/theme/common/gmap.png"></a>';
2725
                }
2726
            }
2727
        }
2728
        if ($noprint)
2729
            return $out;
2730
        else
2731
            print $out;
2732
    }
2733
2734
    /**
2735
     * 	Return true if email syntax is ok
2736
     *
2737
     * 	@param	    string		$address    			email (Ex: "[email protected]", "John Do <[email protected]>")
2738
     *  @param		int			$acceptsupervisorkey	If 1, the special string '__SUPERVISOREMAIL__' is also accepted as valid
2739
     * 	@return     boolean     						true if email syntax is OK, false if KO or empty string
2740
     */
2741
    static function isValidEmail($address, $acceptsupervisorkey = 0)
2742
    {
2743
        if ($acceptsupervisorkey && $address == '__SUPERVISOREMAIL__')
2744
            return true;
2745
        if (filter_var($address, FILTER_VALIDATE_EMAIL))
2746
            return true;
2747
2748
        return false;
2749
    }
2750
2751
    /**
2752
     * 	Return if the domain name has a valid MX record.
2753
     *  WARNING: This need static function idn_to_ascii, checkdnsrr and getmxrr
2754
     *
2755
     * 	@param	    string		$domain	    			Domain name (Ex: "yahoo.com", "yhaoo.com", "dolibarr.fr")
2756
     * 	@return     int     							-1 if error (static function not available), 0=Not valid, 1=Valid
2757
     */
2758
    static function isValidMXRecord($domain)
2759
    {
2760
        if (function_exists('idn_to_ascii') && function_exists('checkdnsrr')) {
2761
            if (!checkdnsrr(idn_to_ascii($domain), 'MX')) {
2762
                return 0;
2763
            }
2764
            if (function_exists('getmxrr')) {
2765
                $mxhosts = array();
2766
                $weight = array();
2767
                getmxrr(idn_to_ascii($domain), $mxhosts, $weight);
2768
                if (count($mxhosts) > 1)
2769
                    return 1;
2770
                if (count($mxhosts) == 1 && !empty($mxhosts[0]))
2771
                    return 1;
2772
2773
                return 0;
2774
            }
2775
        }
2776
        return -1;
2777
    }
2778
2779
    /**
2780
     *  Return true if phone number syntax is ok
2781
     *  TODO Decide what to do with this
2782
     *
2783
     *  @param	string		$phone		phone (Ex: "0601010101")
2784
     *  @return boolean     			true if phone syntax is OK, false if KO or empty string
2785
     */
2786
    static function isValidPhone($phone)
2787
    {
2788
        return true;
2789
    }
2790
2791
    /**
2792
     * Make a strlen call. Works even if mbstring module not enabled
2793
     *
2794
     * @param   string		$string				String to calculate length
2795
     * @param   string		$stringencoding		Encoding of string
2796
     * @return  int								Length of string
2797
     */
2798
    static function dol_strlen($string, $stringencoding = 'UTF-8')
2799
    {
2800
        if (function_exists('mb_strlen'))
2801
            return mb_strlen($string, $stringencoding);
2802
        else
2803
            return strlen($string);
2804
    }
2805
2806
    /**
2807
     * Make a substring. Works even if mbstring module is not enabled for better compatibility.
2808
     *
2809
     * @param	string	$string				String to scan
2810
     * @param	string	$start				Start position
2811
     * @param	int		$length				Length (in nb of characters or nb of bytes depending on trunconbytes param)
2812
     * @param   string	$stringencoding		Page code used for input string encoding
2813
     * @param	int		$trunconbytes		1=Length is max of bytes instead of max of characters
2814
     * @return  string						substring
2815
     */
2816
    static function dol_substr($string, $start, $length, $stringencoding = '', $trunconbytes = 0)
2817
    {
2818
       // global $langs;
2819
2820
        if (empty($stringencoding))
2821
            $stringencoding = $langs->charset_output;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
2822
2823
        $ret = '';
2824
        if (empty($trunconbytes)) {
2825
            if (function_exists('mb_substr')) {
2826
                $ret = mb_substr($string, $start, $length, $stringencoding);
2827
            } else {
2828
                $ret = substr($string, $start, $length);
2829
            }
2830
        } else {
2831
            if (function_exists('mb_strcut')) {
2832
                $ret = mb_strcut($string, $start, $length, $stringencoding);
2833
            } else {
2834
                $ret = substr($string, $start, $length);
2835
            }
2836
        }
2837
        return $ret;
2838
    }
2839
2840
    /**
2841
     * 	Truncate a string to a particular length adding '...' if string larger than length.
2842
     * 	If length = max length+1, we do no truncate to avoid having just 1 char replaced with '...'.
2843
     *  MAIN_DISABLE_TRUNC=1 can disable all truncings
2844
     *
2845
     * 	@param	string	$string				String to truncate
2846
     * 	@param  int		$size				Max string size visible (excluding ...). 0 for no limit. WARNING: Final string size can have 3 more chars (if we added ..., or if size was max+1 or max+2 or max+3 so it does not worse to replace with ...)
2847
     * 	@param	string	$trunc				Where to trunc: right, left, middle (size must be a 2 power), wrap
2848
     * 	@param	string	$stringencoding		Tell what is source string encoding
2849
     *  @param	int		$nodot				Truncation do not add ... after truncation. So it's an exact truncation.
2850
     *  @param  int     $display            Trunc is used to display data and can be changed for small screen. TODO Remove this param (must be dealt with CSS)
2851
     * 	@return string						Truncated string. WARNING: length is never higher than $size if $nodot is set, but can be 3 chars higher otherwise.
2852
     */
2853
    static function dol_trunc($string, $size = 40, $trunc = 'right', $stringencoding = 'UTF-8', $nodot = 0, $display = 0)
2854
    {
2855
       // global Globals::$conf;
2856
2857
        if ($size == 0 || !empty(Globals::$conf->global->MAIN_DISABLE_TRUNC))
2858
            return $string;
2859
2860
        if (empty($stringencoding))
2861
            $stringencoding = 'UTF-8';
2862
// reduce for small screen
2863
        if (Globals::$conf->dol_optimize_smallscreen == 1 && $display == 1)
2864
            $size = round($size / 3);
2865
2866
// We go always here
2867
        if ($trunc == 'right') {
2868
            $newstring = dol_textishtml($string) ? dol_string_nohtmltag($string, 1) : $string;
2869
            if (dol_strlen($newstring, $stringencoding) > ($size + ($nodot ? 0 : 3)))    // If nodot is 0 and size is 1,2 or 3 chars more, we don't trunc and don't add ...
2870
                return dol_substr($newstring, 0, $size, $stringencoding) . ($nodot ? '' : '...');
2871
            else
2872
//return 'u'.$size.'-'.$newstring.'-'.dol_strlen($newstring,$stringencoding).'-'.$string;
2873
                return $string;
2874
        }
2875
        elseif ($trunc == 'middle') {
2876
            $newstring = dol_textishtml($string) ? dol_string_nohtmltag($string, 1) : $string;
2877
            if (dol_strlen($newstring, $stringencoding) > 2 && dol_strlen($newstring, $stringencoding) > ($size + 1)) {
2878
                $size1 = round($size / 2);
2879
                $size2 = round($size / 2);
2880
                return dol_substr($newstring, 0, $size1, $stringencoding) . '...' . dol_substr($newstring, dol_strlen($newstring, $stringencoding) - $size2, $size2, $stringencoding);
2881
            } else
2882
                return $string;
2883
        }
2884
        elseif ($trunc == 'left') {
2885
            $newstring = dol_textishtml($string) ? dol_string_nohtmltag($string, 1) : $string;
2886
            if (dol_strlen($newstring, $stringencoding) > ($size + ($nodot ? 0 : 3)))    // If nodot is 0 and size is 1,2 or 3 chars more, we don't trunc and don't add ...
2887
                return '...' . dol_substr($newstring, dol_strlen($newstring, $stringencoding) - $size, $size, $stringencoding);
2888
            else
2889
                return $string;
2890
        }
2891
        elseif ($trunc == 'wrap') {
2892
            $newstring = dol_textishtml($string) ? dol_string_nohtmltag($string, 1) : $string;
2893
            if (dol_strlen($newstring, $stringencoding) > ($size + 1))
2894
                return dol_substr($newstring, 0, $size, $stringencoding) . "\n" . dol_trunc(dol_substr($newstring, $size, dol_strlen($newstring, $stringencoding) - $size, $stringencoding), $size, $trunc);
2895
            else
2896
                return $string;
2897
        } else
2898
            return 'BadParam3CallingDolTrunc';
2899
    }
2900
2901
    /**
2902
     * 	Show picto whatever it's its name (generic function)
2903
     *
2904
     * 	@param      string		$titlealt         	Text on title tag for tooltip. Not used if param notitle is set to 1.
2905
     * 	@param      string		$picto       		Name of image file to show ('filenew', ...)
2906
     * 												If no extension provided, we use '.png'. Image must be stored into theme/xxx/img directory.
2907
     *                                  			Example: picto.png                  if picto.png is stored into htdocs/theme/mytheme/img
2908
     *                                  			Example: picto.png@mymodule         if picto.png is stored into htdocs/mymodule/img
2909
     *                                  			Example: /mydir/mysubdir/picto.png  if picto.png is stored into htdocs/mydir/mysubdir (pictoisfullpath must be set to 1)
2910
     * 	@param		string		$moreatt			Add more attribute on img tag (For example 'style="float: right"')
2911
     * 	@param		boolean|int	$pictoisfullpath	If true or 1, image path is a full path
2912
     * 	@param		int			$srconly			Return only content of the src attribute of img.
2913
     *  @param		int			$notitle			1=Disable tag title. Use it if you add js tooltip, to avoid duplicate tooltip.
2914
     *  @param		string		$alt				Force alt for bind people
2915
     *  @param		string		$morecss			Add more class css on img tag (For example 'myclascss'). Work only if $moreatt is empty.
2916
     *  @return     string       				    Return img tag
2917
     *  @see        #img_object, #img_picto_common
2918
     */
2919
    static function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $srconly = 0, $notitle = 0, $alt = '', $morecss = '')
2920
    {
2921
       // global Globals::$conf, $langs;
2922
// We forge fullpathpicto for image to $path/img/$picto. By default, we take DOL_BASE_URI/theme/$conf->theme/img/$picto
2923
//$url = DOL_BASE_URI;
2924
        $url = DOL_BASE_URI;
2925
2926
        $theme = Globals::$conf->theme;
2927
        $path = 'theme/' . $theme;
2928
2929
// Define fullpathpicto to use into src
2930
        if ($pictoisfullpath) {
2931
// Clean parameters
2932
            if (!preg_match('/(\.png|\.gif|\.svg)$/i', $picto)) {
2933
                $picto .= '.png';
2934
            }
2935
            $fullpathpicto = $picto;
2936
        } else {
2937
            $pictowithoutext = preg_replace('/(\.png|\.gif|\.svg)$/', '', $picto);
2938
2939
//if (in_array($picto, array('switch_off', 'switch_on', 'off', 'on')))
2940
            if (empty($srconly) && in_array($pictowithoutext, array(
2941
                    'bank', 'close_title', 'delete', 'edit', 'ellipsis-h', 'filter', 'grip', 'grip_title', 'list', 'listlight', 'off', 'on', 'play', 'playdisabled', 'printer', 'resize',
2942
                    'note', 'switch_off', 'switch_on', 'unlink', 'uparrow', '1downarrow', '1uparrow',
2943
                    'jabber', 'skype', 'twitter', 'facebook'
2944
                    )
2945
                )) {
2946
                $fakey = $pictowithoutext;
2947
                $facolor = '';
2948
                $fasize = '';
2949
                $marginleftonlyshort = 2;
2950
                if ($pictowithoutext == 'switch_off') {
2951
                    $fakey = 'fa-toggle-off';
2952
                    $facolor = '#999';
2953
                    $fasize = '2em';
2954
                } elseif ($pictowithoutext == 'switch_on') {
2955
                    $fakey = 'fa-toggle-on';
2956
                    $facolor = '#227722';
2957
                    $fasize = '2em';
2958
                } elseif ($pictowithoutext == 'off') {
2959
                    $fakey = 'fa-square-o';
2960
                    $fasize = '1.3em';
2961
                } elseif ($pictowithoutext == 'on') {
2962
                    $fakey = 'fa-check-square-o';
2963
                    $fasize = '1.3em';
2964
                } elseif ($pictowithoutext == 'bank') {
2965
                    $fakey = 'fa-bank';
2966
                    $facolor = '#444';
2967
                } elseif ($pictowithoutext == 'close_title') {
2968
                    $fakey = 'fa-window-close';
2969
                } elseif ($pictowithoutext == 'delete') {
2970
                    $fakey = 'fa-trash';
2971
                    $facolor = '#444';
2972
                } elseif ($pictowithoutext == 'edit') {
2973
                    $fakey = 'fa-pencil';
2974
                    $facolor = '#444';
2975
                } elseif ($pictowithoutext == 'filter') {
2976
                    $fakey = 'fa-' . $pictowithoutext;
2977
                } elseif ($pictowithoutext == 'grip_title' || $pictowithoutext == 'grip') {
2978
                    $fakey = 'fa-arrows';
2979
                } elseif ($pictowithoutext == 'listlight') {
2980
                    $fakey = 'fa-download';
2981
                    $facolor = '#999';
2982
                    $marginleftonlyshort = 1;
2983
                } elseif ($pictowithoutext == 'printer') {
2984
                    $fakey = 'fa-print';
2985
                    $fasize = '1.2em';
2986
                    $facolor = '#444';
2987
                } elseif ($pictowithoutext == 'resize') {
2988
                    $fakey = 'fa-crop';
2989
                    $facolor = '#444';
2990
                } elseif ($pictowithoutext == 'note') {
2991
                    $fakey = 'fa-sticky-note-o';
2992
                    $facolor = '#999';
2993
                    $marginleftonlyshort = 1;
2994
                } elseif ($pictowithoutext == 'uparrow') {
2995
                    $fakey = 'fa-mail-forward';
2996
                    $facolor = '#555';
2997
                } elseif ($pictowithoutext == '1uparrow') {
2998
                    $fakey = 'fa-caret-up';
2999
                    $marginleftonlyshort = 1;
3000
                } elseif ($pictowithoutext == '1downarrow') {
3001
                    $fakey = 'fa-caret-down';
3002
                    $marginleftonlyshort = 1;
3003
                } elseif ($pictowithoutext == 'unlink') {
3004
                    $fakey = 'fa-chain-broken';
3005
                    $facolor = '#555';
3006
                } elseif ($pictowithoutext == 'playdisabled') {
3007
                    $fakey = 'fa-play';
3008
                    $facolor = '#ccc';
3009
                } elseif ($pictowithoutext == 'play') {
3010
                    $fakey = 'fa-play';
3011
                    $facolor = '#444';
3012
                } elseif ($pictowithoutext == 'jabber') {
3013
                    $fakey = 'fa-comment-o';
3014
                } else {
3015
                    $fakey = 'fa-' . $pictowithoutext;
3016
                    $facolor = '#444';
3017
                    $marginleftonlyshort = 0;
3018
                }
3019
3020
                if (preg_match('/class="([^"]+)"/', $moreatt, $reg)) {
3021
                    $morecss .= ($morecss ? ' ' : '') . $reg[1];
3022
                }
3023
                $enabledisablehtml = '<span class="fa ' . $fakey . ' ' . ($marginleftonlyshort ? ($marginleftonlyshort == 1 ? 'marginleftonlyshort' : 'marginleftonly') : '') . ' valignmiddle' . ($morecss ? ' ' . $morecss : '') . '" style="' . ($fasize ? ('font-size: ' . $fasize . ';') : '') . ($facolor ? (' color: ' . $facolor . ';') : '') . '" alt="' . dol_escape_htmltag($titlealt) . '"' . (($notitle || empty($title)) ? '' : ' title="' . dol_escape_htmltag($title) . '"') . ($moreatt ? ' ' . $moreatt : '') . '>';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $title does not exist. Did you maybe mean $titlealt?
Loading history...
3024
                if (!empty(Globals::$conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
3025
                    $enabledisablehtml .= $titlealt;
3026
                }
3027
                $enabledisablehtml .= '</span>';
3028
3029
                return $enabledisablehtml;
3030
            }
3031
3032
            if (!empty(Globals::$conf->global->MAIN_OVERWRITE_THEME_PATH)) {
3033
                $path = Globals::$conf->global->MAIN_OVERWRITE_THEME_PATH . '/theme/' . $theme; // If the theme does not have the same name as the module
3034
            } else if (!empty(Globals::$conf->global->MAIN_OVERWRITE_THEME_RES)) {
3035
                $path = Globals::$conf->global->MAIN_OVERWRITE_THEME_RES . '/theme/' . Globals::$conf->global->MAIN_OVERWRITE_THEME_RES;  // To allow an external module to overwrite image resources whatever is activated theme
3036
            } else if (!empty(Globals::$conf->modules_parts['theme']) && array_key_exists($theme, Globals::$conf->modules_parts['theme'])) {
3037
                $path = $theme . '/theme/' . $theme; // If the theme have the same name as the module
3038
            }
3039
3040
// If we ask an image into $url/$mymodule/img (instead of default path)
3041
            if (preg_match('/^([^@]+)@([^@]+)$/i', $picto, $regs)) {
3042
                $picto = $regs[1];
3043
                $path = $regs[2]; // $path is $mymodule
3044
            }
3045
3046
// Clean parameters
3047
            if (!preg_match('/(\.png|\.gif|\.svg)$/i', $picto)) {
3048
                $picto .= '.png';
3049
            }
3050
// If alt path are defined, define url where img file is, according to physical path
3051
// ex: array(["main"]=>"/home/maindir/htdocs", ["alt0"]=>"/home/moddir0/htdocs", ...)
3052
            foreach (Globals::$conf->file->dol_document_root as $type => $dirroot) {
3053
                if ($type == 'main') {
3054
                    continue;
3055
                }
3056
// This need a lot of time, that's why enabling alternative dir like "custom" dir is not recommanded
3057
                if (file_exists($dirroot . '/' . $path . '/img/' . $picto)) {
3058
                    //$url = DOL_BASE_URI . Globals::$conf->file->dol_url_root[$type];
3059
                    $url = DOL_BASE_URI . Globals::$conf->file->dol_url_root[$type];
3060
                    break;
3061
                }
3062
            }
3063
3064
// $url is '' or '/custom', $path is current theme or
3065
            $fullpathpicto = $url . '/' . $path . '/img/' . $picto;
3066
        }
3067
3068
        if ($srconly) {
3069
            return $fullpathpicto;
3070
        }
3071
3072
// tag title is used for tooltip on <a>, tag alt can be used with very simple text on image for bind people
3073
        return '<img src="' . $fullpathpicto . '" alt="' . dol_escape_htmltag($alt) . '"' . (($notitle || empty($titlealt)) ? '' : ' title="' . dol_escape_htmltag($titlealt) . '"') . ($moreatt ? ' ' . $moreatt : ' class="inline-block' . ($morecss ? ' ' . $morecss : '') . '"') . '>'; // Alt is used for accessibility, title for popup
3074
    }
3075
3076
    /**
3077
     * 	Show a picto called object_picto (generic function)
3078
     *
3079
     * 	@param	string	$titlealt			Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3080
     * 	@param	string	$picto				Name of image to show object_picto (example: user, group, action, bill, contract, propal, product, ...)
3081
     * 										For external modules use imagename@mymodule to search into directory "img" of module.
3082
     * 	@param	string	$moreatt			Add more attribute on img tag (ie: class="datecallink")
3083
     * 	@param	int		$pictoisfullpath	If 1, image path is a full path
3084
     * 	@param	int		$srconly			Return only content of the src attribute of img.
3085
     *  @param	int		$notitle			1=Disable tag title. Use it if you add js tooltip, to avoid duplicate tooltip.
3086
     * 	@return	string						Return img tag
3087
     * 	@see	#img_picto, #img_picto_common
3088
     */
3089
    static function img_object($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $srconly = 0, $notitle = 0)
3090
    {
3091
        return img_picto($titlealt, 'object_' . $picto, $moreatt, $pictoisfullpath, $srconly, $notitle);
3092
    }
3093
3094
    /**
3095
     * 	Show weather picto
3096
     *
3097
     * 	@param      string		$titlealt         	Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3098
     * 	@param      string		$picto       		Name of image file to show (If no extension provided, we use '.png'). Image must be stored into htdocs/theme/common directory.
3099
     * 	@param		string		$moreatt			Add more attribute on img tag
3100
     * 	@param		int			$pictoisfullpath	If 1, image path is a full path
3101
     * 	@return     string      					Return img tag
3102
     *  @see        #img_object, #img_picto
3103
     */
3104
    static function img_weather($titlealt, $picto, $moreatt = '', $pictoisfullpath = 0)
3105
    {
3106
       // global Globals::$conf;
3107
3108
        if (!preg_match('/(\.png|\.gif)$/i', $picto))
3109
            $picto .= '.png';
3110
3111
//$path = DOL_BASE_URI . '/theme/' . Globals::$conf->theme . '/img/weather/' . $picto;
3112
        $path = DOL_BASE_URI . '/theme/' . Globals::$conf->theme . '/img/weather/' . $picto;
3113
3114
        return img_picto($titlealt, $path, $moreatt, 1);
3115
    }
3116
3117
    /**
3118
     * 	Show picto (generic function)
3119
     *
3120
     * 	@param      string		$titlealt         	Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3121
     * 	@param      string		$picto       		Name of image file to show (If no extension provided, we use '.png'). Image must be stored into htdocs/theme/common directory.
3122
     * 	@param		string		$moreatt			Add more attribute on img tag
3123
     * 	@param		int			$pictoisfullpath	If 1, image path is a full path
3124
     * 	@return     string      					Return img tag
3125
     *  @see        #img_object, #img_picto
3126
     */
3127
    static function img_picto_common($titlealt, $picto, $moreatt = '', $pictoisfullpath = 0)
3128
    {
3129
       // global Globals::$conf;
3130
3131
        if (!preg_match('/(\.png|\.gif)$/i', $picto))
3132
            $picto .= '.png';
3133
3134
        if ($pictoisfullpath)
3135
            $path = $picto;
3136
        else {
3137
//$path = DOL_BASE_URI . '/theme/common/' . $picto;
3138
            $path = DOL_BASE_URI . '/theme/common/' . $picto;
3139
3140
            if (!empty(Globals::$conf->global->MAIN_MODULE_CAN_OVERWRITE_COMMONICONS)) {
3141
                $themepath = DOL_BASE_PATH . 'theme/' . Globals::$conf->theme . '/img/' . $picto;
3142
3143
                if (file_exists($themepath))
3144
                    $path = $themepath;
3145
            }
3146
        }
3147
3148
        return img_picto($titlealt, $path, $moreatt, 1);
3149
    }
3150
3151
    /**
3152
     * 	Show logo action
3153
     *
3154
     * 	@param	string		$titlealt       Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3155
     * 	@param  string		$numaction   	Action id or code to show
3156
     * 	@return string      				Return an img tag
3157
     */
3158
    static function img_action($titlealt, $numaction)
3159
    {
3160
       // global Globals::$conf, $langs;
3161
3162
        if (empty($titlealt) || $titlealt == 'default') {
3163
            if ($numaction == '-1' || $numaction == 'ST_NO') {
3164
                $numaction = -1;
3165
                $titlealt = $langs->transnoentitiesnoconv('ChangeDoNotContact');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3166
            } elseif ($numaction == '0' || $numaction == 'ST_NEVER') {
3167
                $numaction = 0;
3168
                $titlealt = $langs->transnoentitiesnoconv('ChangeNeverContacted');
3169
            } elseif ($numaction == '1' || $numaction == 'ST_TODO') {
3170
                $numaction = 1;
3171
                $titlealt = $langs->transnoentitiesnoconv('ChangeToContact');
3172
            } elseif ($numaction == '2' || $numaction == 'ST_PEND') {
3173
                $numaction = 2;
3174
                $titlealt = $langs->transnoentitiesnoconv('ChangeContactInProcess');
3175
            } elseif ($numaction == '3' || $numaction == 'ST_DONE') {
3176
                $numaction = 3;
3177
                $titlealt = $langs->transnoentitiesnoconv('ChangeContactDone');
3178
            } else {
3179
                $titlealt = $langs->transnoentitiesnoconv('ChangeStatus ' . $numaction);
3180
                $numaction = 0;
3181
            }
3182
        }
3183
        if (!is_numeric($numaction))
3184
            $numaction = 0;
3185
3186
        return img_picto($titlealt, 'stcomm' . $numaction . '.png');
3187
    }
3188
3189
    /**
3190
     *  Show pdf logo
3191
     *
3192
     *  @param	string		$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3193
     *  @param  int		    $size       Taille de l'icone : 3 = 16x16px , 2 = 14x14px
3194
     *  @return string      			Retourne tag img
3195
     */
3196
    static function img_pdf($titlealt = 'default', $size = 3)
3197
    {
3198
       // global Globals::$conf, $langs;
3199
3200
        if ($titlealt == 'default')
3201
            $titlealt = $langs->trans('Show');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3202
3203
        return img_picto($titlealt, 'pdf' . $size . '.png');
3204
    }
3205
3206
    /**
3207
     * 	Show logo +
3208
     *
3209
     * 	@param	string	$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3210
     * 	@param  string	$other      Add more attributes on img
3211
     * 	@return string      		Return tag img
3212
     */
3213
    static function img_edit_add($titlealt = 'default', $other = '')
3214
    {
3215
       // global Globals::$conf, $langs;
3216
3217
        if ($titlealt == 'default')
3218
            $titlealt = $langs->trans('Add');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3219
3220
        return img_picto($titlealt, 'edit_add.png', $other);
3221
    }
3222
3223
    /**
3224
     * 	Show logo -
3225
     *
3226
     * 	@param	string	$titlealt	Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3227
     * 	@param  string	$other      Add more attributes on img
3228
     * 	@return string      		Return tag img
3229
     */
3230
    static function img_edit_remove($titlealt = 'default', $other = '')
3231
    {
3232
       // global Globals::$conf, $langs;
3233
3234
        if ($titlealt == 'default')
3235
            $titlealt = $langs->trans('Remove');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3236
3237
        return img_picto($titlealt, 'edit_remove.png', $other);
3238
    }
3239
3240
    /**
3241
     * 	Show logo editer/modifier fiche
3242
     *
3243
     * 	@param  string	$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3244
     * 	@param  integer	$float      Si il faut y mettre le style "float: right"
3245
     * 	@param  string	$other		Add more attributes on img
3246
     * 	@return string      		Return tag img
3247
     */
3248
    static function img_edit($titlealt = 'default', $float = 0, $other = 'class="pictoedit"')
3249
    {
3250
       // global Globals::$conf, $langs;
3251
3252
        if ($titlealt == 'default')
3253
            $titlealt = $langs->trans('Modify');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3254
3255
        return img_picto($titlealt, 'edit.png', ($float ? 'style="float: ' . ($langs->tab_translate["DIRECTION"] == 'rtl' ? 'left' : 'right') . '"' : "") . ($other ? ' ' . $other : ''));
3256
    }
3257
3258
    /**
3259
     * 	Show logo view card
3260
     *
3261
     * 	@param	string	$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3262
     * 	@param  integer	$float      Si il faut y mettre le style "float: right"
3263
     * 	@param  string	$other		Add more attributes on img
3264
     * 	@return string      		Return tag img
3265
     */
3266
    static function img_view($titlealt = 'default', $float = 0, $other = '')
3267
    {
3268
       // global Globals::$conf, $langs;
3269
3270
        if ($titlealt == 'default')
3271
            $titlealt = $langs->trans('View');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3272
3273
        $moreatt = ($float ? 'style="float: right" ' : '') . $other;
3274
3275
        return img_picto($titlealt, 'view.png', $moreatt);
3276
    }
3277
3278
    /**
3279
     *  Show delete logo
3280
     *
3281
     *  @param	string	$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3282
     * 	@param  string	$other      Add more attributes on img
3283
     *  @return string      		Retourne tag img
3284
     */
3285
    static function img_delete($titlealt = 'default', $other = 'class="pictodelete"')
3286
    {
3287
       // global Globals::$conf, $langs;
3288
3289
        if ($titlealt == 'default')
3290
            $titlealt = $langs->trans('Delete');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3291
3292
        return img_picto($titlealt, 'delete.png', $other);
3293
//return '<span class="fa fa-trash fa-2x fa-fw" style="font-size: 1.7em;" title="'.$titlealt.'"></span>';
3294
    }
3295
3296
    /**
3297
     *  Show printer logo
3298
     *
3299
     *  @param  string  $titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3300
     *  @param  string  $other      Add more attributes on img
3301
     *  @return string              Retourne tag img
3302
     */
3303
    static function img_printer($titlealt = "default", $other = '')
3304
    {
3305
       // global Globals::$conf, $langs;
3306
        if ($titlealt == "default")
3307
            $titlealt = $langs->trans("Print");
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3308
        return img_picto($titlealt, 'printer.png', $other);
3309
    }
3310
3311
    /**
3312
     *  Show split logo
3313
     *
3314
     *  @param	string	$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3315
     * 	@param  string	$other      Add more attributes on img
3316
     *  @return string      		Retourne tag img
3317
     */
3318
    static function img_split($titlealt = 'default', $other = 'class="pictosplit"')
3319
    {
3320
       // global Globals::$conf, $langs;
3321
3322
        if ($titlealt == 'default')
3323
            $titlealt = $langs->trans('Split');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3324
3325
        return img_picto($titlealt, 'split.png', $other);
3326
    }
3327
3328
    /**
3329
     * 	Show help logo with cursor "?"
3330
     *
3331
     * 	@param	int              	$usehelpcursor		1=Use help cursor, 2=Use click pointer cursor, 0=No specific cursor
3332
     * 	@param	int|string	        $usealttitle		Text to use as alt title
3333
     * 	@return string            	           			Return tag img
3334
     */
3335
    static function img_help($usehelpcursor = 1, $usealttitle = 1)
3336
    {
3337
       // global Globals::$conf, $langs;
3338
3339
        if ($usealttitle) {
3340
            if (is_string($usealttitle))
3341
                $usealttitle = dol_escape_htmltag($usealttitle);
3342
            else
3343
                $usealttitle = $langs->trans('Info');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3344
        }
3345
3346
        return img_picto($usealttitle, 'info.png', 'style="vertical-align: middle;' . ($usehelpcursor == 1 ? ' cursor: help' : ($usehelpcursor == 2 ? ' cursor: pointer' : '')) . '"');
3347
    }
3348
3349
    /**
3350
     * 	Show info logo
3351
     *
3352
     * 	@param	string	$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3353
     * 	@return string      		Return img tag
3354
     */
3355
    static function img_info($titlealt = 'default')
3356
    {
3357
       // global Globals::$conf, $langs;
3358
3359
        if ($titlealt == 'default')
3360
            $titlealt = $langs->trans('Informations');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3361
3362
        return img_picto($titlealt, 'info.png', 'style="vertical-align: middle;"');
3363
    }
3364
3365
    /**
3366
     * 	Show warning logo
3367
     *
3368
     * 	@param	string	$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3369
     * 	@param	string	$moreatt	Add more attribute on img tag (For example 'style="float: right"'). If 1, add float: right. Can't be "class" attribute.
3370
     * 	@return string      		Return img tag
3371
     */
3372
    static function img_warning($titlealt = 'default', $moreatt = '')
3373
    {
3374
       // global Globals::$conf, $langs;
3375
3376
        if ($titlealt == 'default')
3377
            $titlealt = $langs->trans('Warning');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3378
3379
//return '<div class="imglatecoin">'.img_picto($titlealt, 'warning_white.png', 'class="pictowarning valignmiddle"'.($moreatt ? ($moreatt == '1' ? ' style="float: right"' : ' '.$moreatt): '')).'</div>';
3380
        return img_picto($titlealt, 'warning.png', 'class="pictowarning valignmiddle"' . ($moreatt ? ($moreatt == '1' ? ' style="float: right"' : ' ' . $moreatt) : ''));
3381
    }
3382
3383
    /**
3384
     *  Show error logo
3385
     *
3386
     * 	@param	string	$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3387
     * 	@return string      		Return img tag
3388
     */
3389
    static function img_error($titlealt = 'default')
3390
    {
3391
       // global Globals::$conf, $langs;
3392
3393
        if ($titlealt == 'default')
3394
            $titlealt = $langs->trans('Error');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3395
3396
        return img_picto($titlealt, 'error.png', 'class="valigntextbottom"');
3397
    }
3398
3399
    /**
3400
     * 	Show next logo
3401
     *
3402
     * 	@param	string	$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3403
     * 	@param	string	$moreatt	Add more attribute on img tag (For example 'style="float: right"')
3404
     * 	@return string      		Return img tag
3405
     */
3406
    static function img_next($titlealt = 'default', $moreatt = '')
3407
    {
3408
       // global Globals::$conf, $langs;
3409
3410
        if ($titlealt == 'default')
3411
            $titlealt = $langs->trans('Next');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3412
3413
//return img_picto($titlealt, 'next.png', $moreatt);
3414
        return '<span class="fa fa-chevron-right paddingright paddingleft" title="' . dol_escape_htmltag($titlealt) . '"></span>';
3415
    }
3416
3417
    /**
3418
     * 	Show previous logo
3419
     *
3420
     * 	@param	string	$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3421
     * 	@param	string	$moreatt	Add more attribute on img tag (For example 'style="float: right"')
3422
     * 	@return string      		Return img tag
3423
     */
3424
    static function img_previous($titlealt = 'default', $moreatt = '')
3425
    {
3426
       // global Globals::$conf, $langs;
3427
3428
        if ($titlealt == 'default')
3429
            $titlealt = $langs->trans('Previous');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3430
3431
//return img_picto($titlealt, 'previous.png', $moreatt);
3432
        return '<span class="fa fa-chevron-left paddingright paddingleft" title="' . dol_escape_htmltag($titlealt) . '"></span>';
3433
    }
3434
3435
    /**
3436
     * 	Show down arrow logo
3437
     *
3438
     * 	@param	string	$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3439
     * 	@param  int		$selected   Selected
3440
     *  @param	string	$moreclass	Add more CSS classes
3441
     * 	@return string      		Return img tag
3442
     */
3443
    static function img_down($titlealt = 'default', $selected = 0, $moreclass = '')
3444
    {
3445
       // global Globals::$conf, $langs;
3446
3447
        if ($titlealt == 'default')
3448
            $titlealt = $langs->trans('Down');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3449
3450
        return img_picto($titlealt, ($selected ? '1downarrow_selected.png' : '1downarrow.png'), 'class="imgdown' . ($moreclass ? " " . $moreclass : "") . '"');
3451
    }
3452
3453
    /**
3454
     * 	Show top arrow logo
3455
     *
3456
     * 	@param	string	$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3457
     * 	@param  int		$selected	Selected
3458
     *  @param	string	$moreclass	Add more CSS classes
3459
     * 	@return string      		Return img tag
3460
     */
3461
    static function img_up($titlealt = 'default', $selected = 0, $moreclass = '')
3462
    {
3463
       // global Globals::$conf, $langs;
3464
3465
        if ($titlealt == 'default')
3466
            $titlealt = $langs->trans('Up');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3467
3468
        return img_picto($titlealt, ($selected ? '1uparrow_selected.png' : '1uparrow.png'), 'class="imgup' . ($moreclass ? " " . $moreclass : "") . '"');
3469
    }
3470
3471
    /**
3472
     * 	Show left arrow logo
3473
     *
3474
     * 	@param	string	$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3475
     * 	@param  int		$selected	Selected
3476
     * 	@param	string	$moreatt	Add more attribute on img tag (For example 'style="float: right"')
3477
     * 	@return string      		Return img tag
3478
     */
3479
    static function img_left($titlealt = 'default', $selected = 0, $moreatt = '')
3480
    {
3481
       // global Globals::$conf, $langs;
3482
3483
        if ($titlealt == 'default')
3484
            $titlealt = $langs->trans('Left');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3485
3486
        return img_picto($titlealt, ($selected ? '1leftarrow_selected.png' : '1leftarrow.png'), $moreatt);
3487
    }
3488
3489
    /**
3490
     * 	Show right arrow logo
3491
     *
3492
     * 	@param	string	$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3493
     * 	@param  int		$selected	Selected
3494
     * 	@param	string	$moreatt	Add more attribute on img tag (For example 'style="float: right"')
3495
     * 	@return string      		Return img tag
3496
     */
3497
    static function img_right($titlealt = 'default', $selected = 0, $moreatt = '')
3498
    {
3499
       // global Globals::$conf, $langs;
3500
3501
        if ($titlealt == 'default')
3502
            $titlealt = $langs->trans('Right');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3503
3504
        return img_picto($titlealt, ($selected ? '1rightarrow_selected.png' : '1rightarrow.png'), $moreatt);
3505
    }
3506
3507
    /**
3508
     * 	Show tick logo if allowed
3509
     *
3510
     * 	@param	string	$allow		Allow
3511
     * 	@param	string	$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3512
     * 	@return string      		Return img tag
3513
     */
3514
    static function img_allow($allow, $titlealt = 'default')
3515
    {
3516
       // global Globals::$conf, $langs;
3517
3518
        if ($titlealt == 'default')
3519
            $titlealt = $langs->trans('Active');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3520
3521
        if ($allow == 1)
3522
            return img_picto($titlealt, 'tick.png');
3523
3524
        return '-';
3525
    }
3526
3527
    /**
3528
     * 	Return image of a credit card according to its brand name
3529
     *
3530
     * 	@param	string	$brand		Brand name of credit card
3531
     * 	@return string     			Return img tag
3532
     */
3533
    static function img_credit_card($brand)
3534
    {
3535
        if ($brand == 'Visa') {
3536
            $brand = 'cc-visa';
3537
        } elseif ($brand == 'MasterCard') {
3538
            $brand = 'cc-mastercard';
3539
        } elseif ($brand == 'American Express') {
3540
            $brand = 'cc-amex';
3541
        } elseif ($brand == 'Discover') {
3542
            $brand = 'cc-discover';
3543
        } elseif ($brand == 'JCB') {
3544
            $brand = 'cc-jcb';
3545
        } elseif ($brand == 'Diners Club') {
3546
            $brand = 'cc-diners-club';
3547
        } elseif (!in_array($brand, array('cc-visa', 'cc-mastercard', 'cc-amex', 'cc-discover', 'cc-jcb', 'cc-diners-club'))) {
3548
            $brand = 'credit-card';
3549
        }
3550
3551
        return '<span class="fa fa-' . $brand . ' fa-2x fa-fw"></span>';
3552
    }
3553
3554
    /**
3555
     * 	Show MIME img of a file
3556
     *
3557
     * 	@param	string	$file		Filename
3558
     * 	@param	string	$titlealt	Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3559
     *  @param	string	$morecss	More css
3560
     * 	@return string     			Return img tag
3561
     */
3562
    static function img_mime($file, $titlealt = '', $morecss = '')
3563
    {
3564
        require_once DOL_BASE_PATH . '/core/lib/files.lib.php';
3565
3566
        $mimetype = dol_mimetype($file, '', 1);
3567
        $mimeimg = dol_mimetype($file, '', 2);
3568
        $mimefa = dol_mimetype($file, '', 4);
3569
3570
        if (empty($titlealt))
3571
            $titlealt = 'Mime type: ' . $mimetype;
3572
3573
//return img_picto_common($titlealt, 'mime/'.$mimeimg, 'class="'.$morecss.'"');
3574
        return '<i class="fa fa-' . $mimefa . ' paddingright"></i>';
3575
    }
3576
3577
    /**
3578
     * 	Show phone logo.
3579
     *  Use img_picto instead.
3580
     *
3581
     * 	@param	string	$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3582
     * 	@param  int		$option		Option
3583
     * 	@return string      		Return img tag
3584
     *  @deprecated
3585
     *  @see img_picto
3586
     */
3587
    static function img_phone($titlealt = 'default', $option = 0)
3588
    {
3589
        dol_syslog(__FUNCTION__ . " is deprecated", LOG_WARNING);
3590
3591
       // global Globals::$conf, $langs;
3592
3593
        if ($titlealt == 'default')
3594
            $titlealt = $langs->trans('Call');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3595
3596
        if ($option == 1)
3597
            $img = 'call';
3598
        else
3599
            $img = 'call_out';
3600
3601
        return img_picto($titlealt, $img);
3602
    }
3603
3604
    /**
3605
     *  Show search logo
3606
     *
3607
     *  @param	string	$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3608
     * 	@param  string	$other      Add more attributes on img
3609
     *  @return string      		Retourne tag img
3610
     */
3611
    static function img_search($titlealt = 'default', $other = '')
3612
    {
3613
       // global Globals::$conf, $langs;
3614
3615
        if ($titlealt == 'default')
3616
            $titlealt = $langs->trans('Search');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3617
3618
        $img = img_picto($titlealt, 'search.png', $other, false, 1);
3619
3620
        $input = '<input type="image" class="liste_titre" name="button_search" src="' . $img . '" ';
3621
        $input .= 'value="' . dol_escape_htmltag($titlealt) . '" title="' . dol_escape_htmltag($titlealt) . '" >';
3622
3623
        return $input;
3624
    }
3625
3626
    /**
3627
     *  Show search logo
3628
     *
3629
     *  @param	string	$titlealt   Text on alt and title of image. Alt only if param notitle is set to 1. If text is "TextA:TextB", use Text A on alt and Text B on title.
3630
     * 	@param  string	$other      Add more attributes on img
3631
     *  @return string      		Retourne tag img
3632
     */
3633
    static function img_searchclear($titlealt = 'default', $other = '')
3634
    {
3635
       // global Globals::$conf, $langs;
3636
3637
        if ($titlealt == 'default')
3638
            $titlealt = $langs->trans('Search');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3639
3640
        $img = img_picto($titlealt, 'searchclear.png', $other, false, 1);
3641
3642
        $input = '<input type="image" class="liste_titre" name="button_removefilter" src="' . $img . '" ';
3643
        $input .= 'value="' . dol_escape_htmltag($titlealt) . '" title="' . dol_escape_htmltag($titlealt) . '" >';
3644
3645
        return $input;
3646
    }
3647
3648
    /**
3649
     * 	Show information for admin users or standard users
3650
     *
3651
     * 	@param	string	$text			Text info
3652
     * 	@param  integer	$infoonimgalt	Info is shown only on alt of star picto, otherwise it is show on output after the star picto
3653
     * 	@param	int		$nodiv			No div
3654
     *  @param  string  $admin          '1'=Info for admin users. '0'=Info for standard users (change only the look), 'xxx'=Other
3655
     *  @param	string	$morecss		More CSS
3656
     * 	@return	string					String with info text
3657
     */
3658
    static function info_admin($text, $infoonimgalt = 0, $nodiv = 0, $admin = '1', $morecss = '')
3659
    {
3660
       // global Globals::$conf, $langs;
3661
3662
        if ($infoonimgalt) {
3663
            return img_picto($text, 'info', 'class="hideonsmartphone' . ($morecss ? ' ' . $morecss : '') . '"');
3664
        }
3665
3666
        return ($nodiv ? '' : '<div class="' . (empty($admin) ? '' : ($admin == '1' ? 'info' : $admin)) . ' hideonsmartphone' . ($morecss ? ' ' . $morecss : '') . '">') . '<span class="fa fa-info-circle" title="' . dol_escape_htmltag($admin ? $langs->trans('InfoAdmin') : $langs->trans('Note')) . '"></span> ' . $text . ($nodiv ? '' : '</div>');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3667
    }
3668
3669
    /**
3670
     * 	Affiche message erreur system avec toutes les informations pour faciliter le diagnostic et la remontee des bugs.
3671
     * 	On doit appeler cette fonction quand une erreur technique bloquante est rencontree.
3672
     * 	Toutefois, il faut essayer de ne l'appeler qu'au sein de pages php, les classes devant
3673
     * 	renvoyer leur erreur par l'intermediaire de leur propriete "error".
3674
     *
3675
     * 	@param	 	DoliDB	$db      	Database handler
3676
     * 	@param  	mixed	$error		String or array of errors strings to show
3677
     *  @param		array	$errors		Array of errors
3678
     * 	@return 	void
3679
     *  @see    	dol_htmloutput_errors
3680
     */
3681
    static function dol_print_error($db = '', $error = '', $errors = null)
3682
    {
3683
       // global Globals::$conf, $langs, $argv;
3684
        // global $dolibarr_main_prod;
3685
3686
        $out = '';
3687
        $syslog = '';
3688
3689
// Si erreur intervenue avant chargement langue
3690
        if (!$langs) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3691
            require_once DOL_BASE_PATH . '/core/class/translate.class.php';
3692
            $langs = new Translate('', Globals::$conf);
3693
            $langs->load("main");
3694
        }
3695
// Load translation files required by the page
3696
        $langs->loadLangs(array('main', 'errors'));
3697
3698
        if ($_SERVER['DOCUMENT_ROOT']) {    // Mode web
3699
            $out .= $langs->trans("DolibarrHasDetectedError") . ".<br>\n";
3700
            if (!empty(Globals::$conf->global->MAIN_FEATURES_LEVEL))
3701
                $out .= "You use an experimental or develop level of features, so please do NOT report any bugs, except if problem is confirmed moving option MAIN_FEATURES_LEVEL back to 0.<br>\n";
3702
            $out .= $langs->trans("InformationToHelpDiagnose") . ":<br>\n";
3703
3704
            $out .= "<b>" . $langs->trans("Date") . ":</b> " . dol_print_date(time(), 'dayhourlog') . "<br>\n";
3705
            $out .= "<b>" . $langs->trans("Dolibarr") . ":</b> " . DOL_VERSION . "<br>\n";
3706
            if (isset(Globals::$conf->global->MAIN_FEATURES_LEVEL))
3707
                $out .= "<b>" . $langs->trans("LevelOfFeature") . ":</b> " . Globals::$conf->global->MAIN_FEATURES_LEVEL . "<br>\n";
3708
            if (function_exists("phpversion")) {
3709
                $out .= "<b>" . $langs->trans("PHP") . ":</b> " . phpversion() . "<br>\n";
3710
            }
3711
            $out .= "<b>" . $langs->trans("Server") . ":</b> " . $_SERVER["SERVER_SOFTWARE"] . "<br>\n";
3712
            if (function_exists("php_uname")) {
3713
                $out .= "<b>" . $langs->trans("OS") . ":</b> " . php_uname() . "<br>\n";
3714
            }
3715
            $out .= "<b>" . $langs->trans("UserAgent") . ":</b> " . $_SERVER["HTTP_USER_AGENT"] . "<br>\n";
3716
            $out .= "<br>\n";
3717
            $out .= "<b>" . $langs->trans("RequestedUrl") . ":</b> " . dol_htmlentities($_SERVER["REQUEST_URI"], ENT_COMPAT, 'UTF-8') . "<br>\n";
3718
            $out .= "<b>" . $langs->trans("Referer") . ":</b> " . (isset($_SERVER["HTTP_REFERER"]) ? dol_htmlentities($_SERVER["HTTP_REFERER"], ENT_COMPAT, 'UTF-8') : '') . "<br>\n";
3719
            $out .= "<b>" . $langs->trans("MenuManager") . ":</b> " . (isset(Globals::$conf->standard_menu) ? Globals::$conf->standard_menu : '') . "<br>\n";
3720
            $out .= "<br>\n";
3721
            $syslog .= "url=" . dol_escape_htmltag($_SERVER["REQUEST_URI"]);
3722
            $syslog .= ", query_string=" . dol_escape_htmltag($_SERVER["QUERY_STRING"]);
3723
        } else {                              // Mode CLI
3724
            $out .= '> ' . $langs->transnoentities("ErrorInternalErrorDetected") . ":\n" . $argv[0] . "\n";
3725
            $syslog .= "pid=" . dol_getmypid();
3726
        }
3727
3728
        if (is_object($db)) {
3729
            if ($_SERVER['DOCUMENT_ROOT']) {  // Mode web
3730
                $out .= "<b>" . $langs->trans("DatabaseTypeManager") . ":</b> " . $db->type . "<br>\n";
3731
                $out .= "<b>" . $langs->trans("RequestLastAccessInError") . ":</b> " . ($db->lastqueryerror() ? dol_escape_htmltag($db->lastqueryerror()) : $langs->trans("ErrorNoRequestInError")) . "<br>\n";
3732
                $out .= "<b>" . $langs->trans("ReturnCodeLastAccessInError") . ":</b> " . ($db->lasterrno() ? dol_escape_htmltag($db->lasterrno()) : $langs->trans("ErrorNoRequestInError")) . "<br>\n";
3733
                $out .= "<b>" . $langs->trans("InformationLastAccessInError") . ":</b> " . ($db->lasterror() ? dol_escape_htmltag($db->lasterror()) : $langs->trans("ErrorNoRequestInError")) . "<br>\n";
3734
                $out .= "<br>\n";
3735
            } else {                            // Mode CLI
3736
// No dol_escape_htmltag for output, we are in CLI mode
3737
                $out .= '> ' . $langs->transnoentities("DatabaseTypeManager") . ":\n" . $db->type . "\n";
3738
                $out .= '> ' . $langs->transnoentities("RequestLastAccessInError") . ":\n" . ($db->lastqueryerror() ? $db->lastqueryerror() : $langs->transnoentities("ErrorNoRequestInError")) . "\n";
3739
                $out .= '> ' . $langs->transnoentities("ReturnCodeLastAccessInError") . ":\n" . ($db->lasterrno() ? $db->lasterrno() : $langs->transnoentities("ErrorNoRequestInError")) . "\n";
3740
                $out .= '> ' . $langs->transnoentities("InformationLastAccessInError") . ":\n" . ($db->lasterror() ? $db->lasterror() : $langs->transnoentities("ErrorNoRequestInError")) . "\n";
3741
            }
3742
            $syslog .= ", sql=" . $db->lastquery();
3743
            $syslog .= ", db_error=" . $db->lasterror();
3744
        }
3745
3746
        if ($error || $errors) {
3747
            $langs->load("errors");
3748
3749
// Merge all into $errors array
3750
            if (is_array($error) && is_array($errors))
3751
                $errors = array_merge($error, $errors);
3752
            elseif (is_array($error))
3753
                $errors = $error;
3754
            elseif (is_array($errors))
3755
                $errors = array_merge(array($error), $errors);
3756
            else
3757
                $errors = array_merge(array($error));
3758
3759
            foreach ($errors as $msg) {
3760
                if (empty($msg))
3761
                    continue;
3762
                if ($_SERVER['DOCUMENT_ROOT']) {  // Mode web
3763
                    $out .= "<b>" . $langs->trans("Message") . ":</b> " . dol_escape_htmltag($msg) . "<br>\n";
3764
                } else {                        // Mode CLI
3765
                    $out .= '> ' . $langs->transnoentities("Message") . ":\n" . $msg . "\n";
3766
                }
3767
                $syslog .= ", msg=" . $msg;
3768
            }
3769
        }
3770
        if (empty($dolibarr_main_prod) && $_SERVER['DOCUMENT_ROOT'] && function_exists('xdebug_print_function_stack') && function_exists('xdebug_call_file')) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_prod seems to never exist and therefore empty should always be true.
Loading history...
3771
            xdebug_print_function_stack();
3772
            $out .= '<b>XDebug informations:</b>' . "<br>\n";
3773
            $out .= 'File: ' . xdebug_call_file() . "<br>\n";
3774
            $out .= 'Line: ' . xdebug_call_line() . "<br>\n";
3775
            $out .= 'Function: ' . xdebug_call_function() . "<br>\n";
3776
            $out .= "<br>\n";
3777
        }
3778
3779
        if (empty($dolibarr_main_prod))
3780
            print $out;
3781
        else {
3782
            print $langs->trans("DolibarrHasDetectedError") . '. ';
3783
            print $langs->trans("YouCanSetOptionDolibarrMainProdToZero");
3784
            define("MAIN_CORE_ERROR", 1);
3785
        }
3786
//else print 'Sorry, an error occured but the parameter $dolibarr_main_prod is defined in conf file so no message is reported to your browser. Please read the log file for error message.';
3787
        dol_syslog("Error " . $syslog, LOG_ERR);
3788
    }
3789
3790
    /**
3791
     * Show a public email and error code to contact if technical error
3792
     *
3793
     * @param	string	$prefixcode		Prefix of public error code
3794
     * @param   string  $errormessage   Complete error message
3795
     * @param	array	$errormessages	Array of error messages
3796
     * @param	string	$morecss		More css
3797
     * @param	string	$email			Email
3798
     * @return	void
3799
     */
3800
    static function dol_print_error_email($prefixcode, $errormessage = '', $errormessages = array(), $morecss = 'error', $email = '')
3801
    {
3802
       // global $langs, Globals::$conf;
3803
3804
        if (empty($email))
3805
            $email = Globals::$conf->global->MAIN_INFO_SOCIETE_MAIL;
3806
3807
        $langs->load("errors");
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3808
        $now = dol_now();
3809
3810
        print '<br><div class="center login_main_message"><div class="' . $morecss . '">';
3811
        print $langs->trans("ErrorContactEMail", $email, $prefixcode . dol_print_date($now, '%Y%m%d'));
3812
        if ($errormessage)
3813
            print '<br><br>' . $errormessage;
3814
        if (is_array($errormessages) && count($errormessages)) {
3815
            foreach ($errormessages as $mesgtoshow) {
3816
                print '<br><br>' . $mesgtoshow;
3817
            }
3818
        }
3819
        print '</div></div>';
3820
    }
3821
3822
    /**
3823
     * 	Show title line of an array
3824
     *
3825
     * 	@param	string	$name        Label of field
3826
     * 	@param	string	$file        Url used when we click on sort picto
3827
     * 	@param	string	$field       Field to use for new sorting
3828
     * 	@param	string	$begin       ("" by defaut)
3829
     * 	@param	string	$moreparam   Add more parameters on sort url links ("" by default)
3830
     * 	@param  string	$moreattrib  Options of attribute td ("" by defaut, example: 'align="center"')
3831
     * 	@param  string	$sortfield   Current field used to sort
3832
     * 	@param  string	$sortorder   Current sort order
3833
     *  @param	string	$prefix		 Prefix for css. Use space after prefix to add your own CSS tag.
3834
     *  @param	string	$tooltip	 Tooltip
3835
     * 	@return	void
3836
     */
3837
    static function print_liste_field_titre($name, $file = "", $field = "", $begin = "", $moreparam = "", $moreattrib = "", $sortfield = "", $sortorder = "", $prefix = "", $tooltip = "")
3838
    {
3839
        print getTitleFieldOfList($name, 0, $file, $field, $begin, $moreparam, $moreattrib, $sortfield, $sortorder, $prefix, 0, $tooltip);
3840
    }
3841
3842
    /**
3843
     * 	Get title line of an array
3844
     *
3845
     * 	@param	string	$name        		Translation key of field
3846
     * 	@param	int		$thead		 		0=To use with standard table format, 1=To use inside <thead><tr>, 2=To use with <div>
3847
     * 	@param	string	$file        		Url used when we click on sort picto
3848
     * 	@param	string	$field       		Field to use for new sorting. Empty if this field is not sortable. Example "t.abc" or "t.abc,t.def"
3849
     * 	@param	string	$begin       		("" by defaut)
3850
     * 	@param	string	$moreparam   		Add more parameters on sort url links ("" by default)
3851
     * 	@param  string	$moreattrib  		Add more attributes on th ("" by defaut, example: 'align="center"'). To add more css class, use param $prefix.
3852
     * 	@param  string	$sortfield   		Current field used to sort (Ex: 'd.datep,d.id')
3853
     * 	@param  string	$sortorder   		Current sort order (Ex: 'asc,desc')
3854
     *  @param	string	$prefix		 		Prefix for css. Use space after prefix to add your own CSS tag, for example 'mycss '.
3855
     *  @param	string	$disablesortlink	1=Disable sort link
3856
     *  @param	string	$tooltip	 		Tooltip
3857
     * 	@return	string
3858
     */
3859
    static function getTitleFieldOfList($name, $thead = 0, $file = "", $field = "", $begin = "", $moreparam = "", $moreattrib = "", $sortfield = "", $sortorder = "", $prefix = "", $disablesortlink = 0, $tooltip = '')
3860
    {
3861
       // global Globals::$conf, $langs, $form;
3862
//print "$name, $file, $field, $begin, $options, $moreattrib, $sortfield, $sortorder<br>\n";
3863
3864
        $sortorder = strtoupper($sortorder);
3865
        $out = '';
3866
        $sortimg = '';
3867
3868
        $tag = 'th';
3869
        if ($thead == 2) {
3870
            $tag = 'div';
3871
        }
3872
3873
        $tmpsortfield = explode(',', $sortfield);
3874
        $sortfield1 = trim($tmpsortfield[0]);    // If $sortfield is 'd.datep,d.id', it becomes 'd.datep'
3875
        $tmpfield = explode(',', $field);
3876
        $field1 = trim($tmpfield[0]);            // If $field is 'd.datep,d.id', it becomes 'd.datep'
3877
//var_dump('field='.$field.' field1='.$field1.' sortfield='.$sortfield.' sortfield1='.$sortfield1);
3878
// If field is used as sort criteria we use a specific css class liste_titre_sel
3879
// Example if (sortfield,field)=("nom","xxx.nom") or (sortfield,field)=("nom","nom")
3880
        if ($field1 && ($sortfield1 == $field1 || $sortfield1 == preg_replace("/^[^\.]+\./", "", $field1))) {
3881
            $out .= '<' . $tag . ' class="' . $prefix . 'liste_titre_sel" ' . $moreattrib . '>';
3882
        } else {
3883
            $out .= '<' . $tag . ' class="' . $prefix . 'liste_titre" ' . $moreattrib . '>';
3884
        }
3885
3886
        if (empty($thead) && $field && empty($disablesortlink)) {    // If this is a sort field
3887
            $options = preg_replace('/sortfield=([a-zA-Z0-9,\s\.]+)/i', '', $moreparam);
3888
            $options = preg_replace('/sortorder=([a-zA-Z0-9,\s\.]+)/i', '', $options);
3889
            $options = preg_replace('/&+/i', '&', $options);
3890
            if (!preg_match('/^&/', $options)) {
3891
                $options = '&' . $options;
3892
            }
3893
3894
            $sortordertouseinlink = '';
3895
            if ($field1 != $sortfield1) { // We are on another field than current sorted field
3896
                if (preg_match('/^DESC/i', $sortorder)) {
3897
                    $sortordertouseinlink .= str_repeat('desc,', count(explode(',', $field)));
3898
                } else {  // We reverse the var $sortordertouseinlink
3899
                    $sortordertouseinlink .= str_repeat('asc,', count(explode(',', $field)));
3900
                }
3901
            } else {                        // We are on field that is the first current sorting criteria
3902
                if (preg_match('/^ASC/i', $sortorder)) { // We reverse the var $sortordertouseinlink
3903
                    $sortordertouseinlink .= str_repeat('desc,', count(explode(',', $field)));
3904
                } else {
3905
                    $sortordertouseinlink .= str_repeat('asc,', count(explode(',', $field)));
3906
                }
3907
            }
3908
            $sortordertouseinlink = preg_replace('/,$/', '', $sortordertouseinlink);
3909
            $out .= '<a class="reposition" href="' . $file . '?sortfield=' . $field . '&sortorder=' . $sortordertouseinlink . '&begin=' . $begin . $options . '">';
3910
        }
3911
3912
        if ($tooltip) {
3913
            $out .= $form->textwithpicto($langs->trans($name), $langs->trans($tooltip));
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $form seems to be never defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
3914
        } else {
3915
            $out .= $langs->trans($name);
3916
        }
3917
3918
        if (empty($thead) && $field && empty($disablesortlink)) {    // If this is a sort field
3919
            $out .= '</a>';
3920
        }
3921
3922
        if (empty($thead) && $field) {    // If this is a sort field
3923
            $options = preg_replace('/sortfield=([a-zA-Z0-9,\s\.]+)/i', '', $moreparam);
3924
            $options = preg_replace('/sortorder=([a-zA-Z0-9,\s\.]+)/i', '', $options);
3925
            $options = preg_replace('/&+/i', '&', $options);
3926
            if (!preg_match('/^&/', $options)) {
3927
                $options = '&' . $options;
3928
            }
3929
3930
            if (!$sortorder || $field1 != $sortfield1) {
3931
//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">'.img_down("A-Z",0).'</a>';
3932
//$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">'.img_up("Z-A",0).'</a>';
3933
            } else {
3934
                if (preg_match('/^DESC/', $sortorder)) {
3935
                    //$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">'.img_down("A-Z",0).'</a>';
3936
                    //$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">'.img_up("Z-A",1).'</a>';
3937
                    $sortimg .= '<span class="nowrap">' . img_up("Z-A", 0) . '</span>';
3938
                }
3939
                if (preg_match('/^ASC/', $sortorder)) {
3940
                    //$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">'.img_down("A-Z",1).'</a>';
3941
                    //$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">'.img_up("Z-A",0).'</a>';
3942
                    $sortimg .= '<span class="nowrap">' . img_down("A-Z", 0) . '</span>';
3943
                }
3944
            }
3945
        }
3946
3947
        $out .= $sortimg;
3948
3949
        $out .= '</' . $tag . '>';
3950
3951
        return $out;
3952
    }
3953
3954
    /**
3955
     * 	Show a title.
3956
     *
3957
     * 	@param	string	$title			Title to show
3958
     * 	@return	string					Title to show
3959
     *  @deprecated						Use load_fiche_titre instead
3960
     *  @see load_fiche_titre
3961
     */
3962
    static function print_titre($title)
3963
    {
3964
        dol_syslog(__FUNCTION__ . " is deprecated", LOG_WARNING);
3965
3966
        print '<div class="titre">' . $title . '</div>';
3967
    }
3968
3969
    /**
3970
     * 	Show a title with picto
3971
     *
3972
     * 	@param	string	$title				Title to show
3973
     * 	@param	string	$mesg				Added message to show on right
3974
     * 	@param	string	$picto				Icon to use before title (should be a 32x32 transparent png file)
3975
     * 	@param	int		$pictoisfullpath	1=Icon name is a full absolute url of image
3976
     * 	@param	int		$id					To force an id on html objects
3977
     * 	@return	void
3978
     *  @deprecated Use print load_fiche_titre instead
3979
     */
3980
    static function print_fiche_titre($title, $mesg = '', $picto = 'title_generic.png', $pictoisfullpath = 0, $id = '')
3981
    {
3982
        print load_fiche_titre($title, $mesg, $picto, $pictoisfullpath, $id);
3983
    }
3984
3985
    /**
3986
     * 	Load a title with picto
3987
     *
3988
     * 	@param	string	$titre				Title to show
3989
     * 	@param	string	$morehtmlright		Added message to show on right
3990
     * 	@param	string	$picto				Icon to use before title (should be a 32x32 transparent png file)
3991
     * 	@param	int		$pictoisfullpath	1=Icon name is a full absolute url of image
3992
     * 	@param	string	$id					To force an id on html objects
3993
     *  @param  string  $morecssontable     More css on table
3994
     * 	@param	string	$morehtmlcenter		Added message to show on center
3995
     * 	@return	string
3996
     *  @see print_barre_liste
3997
     */
3998
    static function load_fiche_titre($titre, $morehtmlright = '', $picto = 'title_generic.png', $pictoisfullpath = 0, $id = '', $morecssontable = '', $morehtmlcenter = '')
3999
    {
4000
       // global Globals::$conf;
4001
4002
        $return = '';
4003
4004
        if ($picto == 'setup') {
4005
            $picto = 'title_generic.png';
4006
        }
4007
4008
        $return .= "\n";
4009
        $return .= '<table ' . ($id ? 'id="' . $id . '" ' : '') . 'summary="" class="centpercent notopnoleftnoright' . ($morecssontable ? ' ' . $morecssontable : '') . '" style="margin-bottom: 6px;"><tr>'; // maring bottom must be same than into print_barre_list
4010
        if ($picto) {
4011
            $return .= '<td class="nobordernopadding widthpictotitle opacityhigh" valign="middle">' . img_picto('', $picto, 'class="valignmiddle widthpictotitle pictotitle"', $pictoisfullpath) . '</td>';
4012
        }
4013
        $return .= '<td class="nobordernopadding valignmiddle">';
4014
        $return .= '<div class="titre inline-block">' . $titre . '</div>';
4015
        $return .= '</td>';
4016
        if (dol_strlen($morehtmlcenter)) {
4017
            $return .= '<td class="nobordernopadding" align="center" valign="middle">' . $morehtmlcenter . '</td>';
4018
        }
4019
        if (dol_strlen($morehtmlright)) {
4020
            $return .= '<td class="nobordernopadding titre_right wordbreak" align="right" valign="middle">' . $morehtmlright . '</td>';
4021
        }
4022
        $return .= '</tr></table>' . "\n";
4023
4024
        return $return;
4025
    }
4026
4027
    /**
4028
     * 	Print a title with navigation controls for pagination
4029
     *
4030
     * 	@param	string	    $titre				Title to show (required)
4031
     * 	@param	int   	    $page				Numero of page to show in navigation links (required)
4032
     * 	@param	string	    $file				Url of page (required)
4033
     * 	@param	string	    $options         	More parameters for links ('' by default, does not include sortfield neither sortorder). Value must be 'urlencoded' before calling function.
4034
     * 	@param	string    	$sortfield       	Field to sort on ('' by default)
4035
     * 	@param	string	    $sortorder       	Order to sort ('' by default)
4036
     * 	@param	string	    $morehtmlcenter     String in the middle ('' by default). We often find here string $massaction comming from $form->selectMassAction()
4037
     * 	@param	int		    $num				Number of records found by select with limit+1
4038
     * 	@param	int|string  $totalnboflines		Total number of records/lines for all pages (if known). Use a negative value of number to not show number. Use '' if unknown.
4039
     * 	@param	string	    $picto				Icon to use before title (should be a 32x32 transparent png file)
4040
     * 	@param	int		    $pictoisfullpath	1=Icon name is a full absolute url of image
4041
     *  @param	string	    $morehtmlright			More html to show
4042
     *  @param  string      $morecss            More css to the table
4043
     *  @param  int         $limit              Max number of lines (-1 = use default, 0 = no limit, > 0 = limit).
4044
     *  @param  int         $hideselectlimit    Force to hide select limit
4045
     *  @param  int         $hidenavigation     Force to hide all navigation tools
4046
     * 	@return	void
4047
     */
4048
    static function print_barre_liste($titre, $page, $file, $options = '', $sortfield = '', $sortorder = '', $morehtmlcenter = '', $num = -1, $totalnboflines = '', $picto = 'title_generic.png', $pictoisfullpath = 0, $morehtmlright = '', $morecss = '', $limit = -1, $hideselectlimit = 0, $hidenavigation = 0)
4049
    {
4050
       // global Globals::$conf, $langs;
4051
4052
        $savlimit = $limit;
4053
        $savtotalnboflines = $totalnboflines;
4054
        $totalnboflines = abs($totalnboflines);
4055
4056
        if ($picto == 'setup')
4057
            $picto = 'title_setup.png';
4058
        if ((Globals::$conf->browser->name == 'ie') && $picto == 'title_generic.png')
4059
            $picto = 'title.gif';
4060
        if ($limit < 0)
4061
            $limit = Globals::$conf->liste_limit;
4062
        if ($savlimit != 0 && (($num > $limit) || ($num == -1) || ($limit == 0))) {
4063
            $nextpage = 1;
4064
        } else {
4065
            $nextpage = 0;
4066
        }
4067
//print 'totalnboflines='.$totalnboflines.'-savlimit='.$savlimit.'-limit='.$limit.'-num='.$num.'-nextpage='.$nextpage;
4068
4069
        print "\n";
4070
        print "<!-- Begin title '" . $titre . "' -->\n";
4071
        print '<table border="0" class="centpercent notopnoleftnoright' . ($morecss ? ' ' . $morecss : '') . '" style="margin-bottom: 6px;"><tr>'; // maring bottom must be same than into load_fiche_tire
4072
// Left
4073
//if ($picto && $titre) print '<td class="nobordernopadding hideonsmartphone" width="40" align="left" valign="middle">'.img_picto('', $picto, 'id="pictotitle"', $pictoisfullpath).'</td>';
4074
        print '<td class="nobordernopadding valignmiddle">';
4075
        if ($picto && $titre)
4076
            print img_picto('', $picto, 'class="hideonsmartphone valignmiddle opacityhigh pictotitle widthpictotitle"', $pictoisfullpath);
4077
        print '<div class="titre inline-block">' . $titre;
4078
        if (!empty($titre) && $savtotalnboflines >= 0 && (string) $savtotalnboflines != '')
4079
            print ' (' . $totalnboflines . ')';
4080
        print '</div></td>';
4081
4082
// Center
4083
        if ($morehtmlcenter) {
4084
            print '<td class="nobordernopadding center valignmiddle">' . $morehtmlcenter . '</td>';
4085
        }
4086
4087
// Right
4088
        print '<td class="nobordernopadding valignmiddle" align="right">';
4089
        if ($sortfield)
4090
            $options .= "&sortfield=" . urlencode($sortfield);
4091
        if ($sortorder)
4092
            $options .= "&sortorder=" . urlencode($sortorder);
4093
// Show navigation bar
4094
        $pagelist = '';
4095
        if ($savlimit != 0 && ($page > 0 || $num > $limit)) {
4096
            if ($totalnboflines) { // If we know total nb of lines
4097
// Define nb of extra page links before and after selected page + ... + first or last
4098
                $maxnbofpage = (empty(Globals::$conf->dol_optimize_smallscreen) ? 4 : 1);
4099
4100
                if ($limit > 0)
4101
                    $nbpages = ceil($totalnboflines / $limit);
4102
                else
4103
                    $nbpages = 1;
4104
                $cpt = ($page - $maxnbofpage);
4105
                if ($cpt < 0) {
4106
                    $cpt = 0;
4107
                }
4108
4109
                if ($cpt >= 1) {
4110
                    $pagelist .= '<li' . ((Globals::$conf->dol_use_jmobile != 4) ? ' class="pagination"' : '') . '><a href="' . $file . '?page=0' . $options . '">1</a></li>';
4111
                    if ($cpt > 2)
4112
                        $pagelist .= '<li' . ((Globals::$conf->dol_use_jmobile != 4) ? ' class="pagination"' : '') . '><span ' . ((Globals::$conf->dol_use_jmobile != 4) ? 'class="inactive"' : '') . '>...</span></li>';
4113
                    else if ($cpt == 2)
4114
                        $pagelist .= '<li' . ((Globals::$conf->dol_use_jmobile != 4) ? ' class="pagination"' : '') . '><a href="' . $file . '?page=1' . $options . '">2</a></li>';
4115
                }
4116
4117
                do {
4118
                    if ($cpt == $page) {
4119
                        $pagelist .= '<li' . ((Globals::$conf->dol_use_jmobile != 4) ? ' class="pagination"' : '') . '><span ' . ((Globals::$conf->dol_use_jmobile != 4) ? 'class="active"' : '') . '>' . ($page + 1) . '</span></li>';
4120
                    } else {
4121
                        $pagelist .= '<li' . ((Globals::$conf->dol_use_jmobile != 4) ? ' class="pagination"' : '') . '><a href="' . $file . '?page=' . $cpt . $options . '">' . ($cpt + 1) . '</a></li>';
4122
                    }
4123
                    $cpt++;
4124
                } while ($cpt < $nbpages && $cpt <= $page + $maxnbofpage);
4125
4126
                if ($cpt < $nbpages) {
4127
                    if ($cpt < $nbpages - 2)
4128
                        $pagelist .= '<li' . ((Globals::$conf->dol_use_jmobile != 4) ? ' class="pagination"' : '') . '><span ' . ((Globals::$conf->dol_use_jmobile != 4) ? 'class="inactive"' : '') . '>...</span></li>';
4129
                    else if ($cpt == $nbpages - 2)
4130
                        $pagelist .= '<li' . ((Globals::$conf->dol_use_jmobile != 4) ? ' class="pagination"' : '') . '><a href="' . $file . '?page=' . ($nbpages - 2) . $options . '">' . ($nbpages - 1) . '</a></li>';
4131
                    $pagelist .= '<li' . ((Globals::$conf->dol_use_jmobile != 4) ? ' class="pagination"' : '') . '><a href="' . $file . '?page=' . ($nbpages - 1) . $options . '">' . $nbpages . '</a></li>';
4132
                }
4133
            }
4134
            else {
4135
                $pagelist .= '<li' . ((Globals::$conf->dol_use_jmobile != 4) ? ' class="pagination"' : '') . '><span ' . ((Globals::$conf->dol_use_jmobile != 4) ? 'class="active"' : '') . '>' . ($page + 1) . "</li>";
4136
            }
4137
        }
4138
4139
        print_fleche_navigation($page, $file, $options, $nextpage, $pagelist, $morehtmlright, $savlimit, $totalnboflines, $hideselectlimit);  // output the div and ul for previous/last completed with page numbers into $pagelist
4140
4141
        print '</td>';
4142
4143
        print '</tr></table>' . "\n";
4144
        print "<!-- End title -->\n\n";
4145
    }
4146
4147
    /**
4148
     * 	Function to show navigation arrows into lists
4149
     *
4150
     * 	@param	int				$page				Number of page
4151
     * 	@param	string			$file				Page URL (in most cases provided with $_SERVER["PHP_SELF"])
4152
     * 	@param	string			$options         	Other url paramaters to propagate ("" by default, may include sortfield and sortorder)
4153
     * 	@param	integer			$nextpage	    	Do we show a next page button
4154
     * 	@param	string			$betweenarrows		HTML content to show between arrows. MUST contains '<li> </li>' tags or '<li><span> </span></li>'.
4155
     *  @param	string			$afterarrows		HTML content to show after arrows. Must NOT contains '<li> </li>' tags.
4156
     *  @param  int             $limit              Max nb of record to show  (-1 = no combo with limit, 0 = no limit, > 0 = limit)
4157
     * 	@param	int		        $totalnboflines		Total number of records/lines for all pages (if known)
4158
     *  @param  int             $hideselectlimit    Force to hide select limit
4159
     * 	@return	void
4160
     */
4161
    static function print_fleche_navigation($page, $file, $options = '', $nextpage = 0, $betweenarrows = '', $afterarrows = '', $limit = -1, $totalnboflines = 0, $hideselectlimit = 0)
4162
    {
4163
       // global Globals::$conf, $langs;
4164
4165
        print '<div class="pagination"><ul>';
4166
        if ((int) $limit >= 0 && empty($hideselectlimit)) {
4167
            $pagesizechoices = '10:10,15:15,20:20,30:30,40:40,50:50,100:100,250:250,500:500,1000:1000,5000:5000';
4168
//$pagesizechoices.=',0:'.$langs->trans("All");     // Not yet supported
4169
//$pagesizechoices.=',2:2';
4170
            if (!empty(Globals::$conf->global->MAIN_PAGESIZE_CHOICES))
4171
                $pagesizechoices = Globals::$conf->global->MAIN_PAGESIZE_CHOICES;
4172
4173
            print '<li class="pagination">';
4174
            print '<select class="flat selectlimit" name="limit" title="' . dol_escape_htmltag($langs->trans("MaxNbOfRecordPerPage")) . '">';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
4175
            $tmpchoice = explode(',', $pagesizechoices);
4176
            $tmpkey = $limit . ':' . $limit;
4177
            if (!in_array($tmpkey, $tmpchoice))
4178
                $tmpchoice[] = $tmpkey;
4179
            $tmpkey = Globals::$conf->liste_limit . ':' . Globals::$conf->liste_limit;
4180
            if (!in_array($tmpkey, $tmpchoice))
4181
                $tmpchoice[] = $tmpkey;
4182
            asort($tmpchoice, SORT_NUMERIC);
4183
            $found = false;
4184
            foreach ($tmpchoice as $val) {
4185
                $selected = '';
4186
                $tmp = explode(':', $val);
4187
                $key = $tmp[0];
4188
                $val = $tmp[1];
4189
                if ($key != '' && $val != '') {
4190
                    if ((int) $key == (int) $limit) {
4191
                        $selected = ' selected="selected"';
4192
                        $found = true;
4193
                    }
4194
                    print '<option name="' . $key . '"' . $selected . '>' . dol_escape_htmltag($val) . '</option>' . "\n";
4195
                }
4196
            }
4197
            print '</select>';
4198
            if (Globals::$conf->use_javascript_ajax) {
4199
                print '<!-- JS CODE TO ENABLE select limit to launch submit of page -->
4200
            		<script type="text/javascript">
4201
                	jQuery(document).ready(static function () {
4202
            	  		jQuery(".selectlimit").change(function() {
4203
                            console.log("Change limit. Send submit");
4204
                            $(this).parents(\'form:first\').submit();
4205
            	  		});
4206
                	});
4207
            		</script>
4208
                ';
4209
            }
4210
            print '</li>';
4211
        }
4212
        if ($page > 0) {
4213
            print '<li class="pagination"><a class="paginationprevious" href="' . $file . '?page=' . ($page - 1) . $options . '"><i class="fa fa-chevron-left" title="' . dol_escape_htmltag($langs->trans("Previous")) . '"></i></a></li>';
4214
        }
4215
        if ($betweenarrows) {
4216
            print $betweenarrows;
4217
        }
4218
        if ($nextpage > 0) {
4219
            print '<li class="pagination"><a class="paginationnext" href="' . $file . '?page=' . ($page + 1) . $options . '"><i class="fa fa-chevron-right" title="' . dol_escape_htmltag($langs->trans("Next")) . '"></i></a></li>';
4220
        }
4221
        if ($afterarrows) {
4222
            print '<li class="paginationafterarrows">';
4223
            print $afterarrows;
4224
            print '</li>';
4225
        }
4226
        print '</ul></div>' . "\n";
4227
    }
4228
4229
    /**
4230
     * 	Return a string with VAT rate label formated for view output
4231
     * 	Used into pdf and HTML pages
4232
     *
4233
     * 	@param	string	$rate			Rate value to format ('19.6', '19,6', '19.6%', '19,6%', '19.6 (CODEX)', ...)
4234
     *  @param	boolean	$addpercent		Add a percent % sign in output
4235
     * 	@param	int		$info_bits		Miscellaneous information on vat (0=Default, 1=French NPR vat)
4236
     * 	@param	int		$usestarfornpr	-1=Never show, 0 or 1=Use '*' for NPR vat rates
4237
     *  @return	string					String with formated amounts ('19,6' or '19,6%' or '8.5% (NPR)' or '8.5% *' or '19,6 (CODEX)')
4238
     */
4239
    static function vatrate($rate, $addpercent = false, $info_bits = 0, $usestarfornpr = 0)
4240
    {
4241
        $morelabel = '';
4242
4243
        if (preg_match('/%/', $rate)) {
4244
            $rate = str_replace('%', '', $rate);
4245
            $addpercent = true;
4246
        }
4247
        if (preg_match('/\((.*)\)/', $rate, $reg)) {
4248
            $morelabel = ' (' . $reg[1] . ')';
4249
            $rate = preg_replace('/\s*' . preg_quote($morelabel, '/') . '/', '', $rate);
4250
        }
4251
        if (preg_match('/\*/', $rate)) {
4252
            $rate = str_replace('*', '', $rate);
4253
            $info_bits |= 1;
4254
        }
4255
4256
// If rate is '9/9/9' we don't change it.  If rate is '9.000' we apply price()
4257
        if (!preg_match('/\//', $rate))
4258
            $ret = price($rate, 0, '', 0, 0) . ($addpercent ? '%' : '');
4259
        else {
4260
// TODO Split on / and output with a price2num to have clean numbers without ton of 000.
4261
            $ret = $rate . ($addpercent ? '%' : '');
4262
        }
4263
        if (($info_bits & 1) && $usestarfornpr >= 0)
4264
            $ret .= ' *';
4265
        $ret .= $morelabel;
4266
        return $ret;
4267
    }
4268
4269
    /**
4270
     * 		Function to format a value into an amount for visual output
4271
     * 		Function used into PDF and HTML pages
4272
     *
4273
     * 		@param	float		$amount			Amount to format
4274
     * 		@param	integer		$form			Type of format, HTML or not (not by default)
4275
     * 		@param	Translate	$outlangs		Object langs for output
4276
     * 		@param	int			$trunc			1=Truncate if there is more decimals than MAIN_MAX_DECIMALS_SHOWN (default), 0=Does not truncate. Deprecated because amount are rounded (to unit or total amount accurancy) before beeing inserted into database or after a computation, so this parameter should be useless.
4277
     * 		@param	int			$rounding		Minimum number of decimal to show. If 0, no change, if -1, we use min(Globals::$conf->global->MAIN_MAX_DECIMALS_UNIT,$conf->global->MAIN_MAX_DECIMALS_TOT)
4278
     * 		@param	int			$forcerounding	Force the number of decimal to forcerounding decimal (-1=do not force)
4279
     * 		@param	string		$currency_code	To add currency symbol (''=add nothing, 'auto'=Use default currency, 'XXX'=add currency symbols for XXX currency)
4280
     * 		@return	string						Chaine avec montant formate
4281
     *
4282
     * 		@see	price2num					Revert static function of price
4283
     */
4284
    static function price($amount, $form = 0, $outlangs = '', $trunc = 1, $rounding = -1, $forcerounding = -1, $currency_code = '')
4285
    {
4286
       // global $langs, Globals::$conf;
4287
// Clean parameters
4288
        if (empty($amount))
4289
            $amount = 0; // To have a numeric value if amount not defined or = ''
4290
        $amount = (is_numeric($amount) ? $amount : 0); // Check if amount is numeric, for example, an error occured when amount value = o (letter) instead 0 (number)
4291
        if ($rounding < 0)
4292
            $rounding = min(Globals::$conf->global->MAIN_MAX_DECIMALS_UNIT, Globals::$conf->global->MAIN_MAX_DECIMALS_TOT);
4293
        $nbdecimal = $rounding;
4294
4295
// Output separators by default (french)
4296
        $dec = ',';
4297
        $thousand = ' ';
4298
4299
// If $outlangs not forced, we use use language
4300
        if (!is_object($outlangs))
4301
            $outlangs = $langs;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
4302
4303
        if ($outlangs->transnoentitiesnoconv("SeparatorDecimal") != "SeparatorDecimal")
4304
            $dec = $outlangs->transnoentitiesnoconv("SeparatorDecimal");
4305
        if ($outlangs->transnoentitiesnoconv("SeparatorThousand") != "SeparatorThousand")
4306
            $thousand = $outlangs->transnoentitiesnoconv("SeparatorThousand");
4307
        if ($thousand == 'None')
4308
            $thousand = '';
4309
        else if ($thousand == 'Space')
4310
            $thousand = ' ';
4311
//print "outlangs=".$outlangs->defaultlang." amount=".$amount." html=".$form." trunc=".$trunc." nbdecimal=".$nbdecimal." dec='".$dec."' thousand='".$thousand."'<br>";
4312
//print "amount=".$amount."-";
4313
        $amount = str_replace(',', '.', $amount); // should be useless
4314
//print $amount."-";
4315
        $datas = explode('.', $amount);
4316
        $decpart = isset($datas[1]) ? $datas[1] : '';
4317
        $decpart = preg_replace('/0+$/i', '', $decpart); // Supprime les 0 de fin de partie decimale
4318
//print "decpart=".$decpart."<br>";
4319
        $end = '';
4320
4321
// We increase nbdecimal if there is more decimal than asked (to not loose information)
4322
        if (dol_strlen($decpart) > $nbdecimal)
4323
            $nbdecimal = dol_strlen($decpart);
4324
// Si on depasse max
4325
        if ($trunc && $nbdecimal > Globals::$conf->global->MAIN_MAX_DECIMALS_SHOWN) {
4326
            $nbdecimal = Globals::$conf->global->MAIN_MAX_DECIMALS_SHOWN;
4327
            if (preg_match('/\.\.\./i', Globals::$conf->global->MAIN_MAX_DECIMALS_SHOWN)) {
4328
// Si un affichage est tronque, on montre des ...
4329
                $end = '...';
4330
            }
4331
        }
4332
4333
// If force rounding
4334
        if ($forcerounding >= 0)
4335
            $nbdecimal = $forcerounding;
4336
4337
// Format number
4338
        $output = number_format($amount, $nbdecimal, $dec, $thousand);
4339
        if ($form) {
4340
            $output = preg_replace('/\s/', '&nbsp;', $output);
4341
            $output = preg_replace('/\'/', '&#039;', $output);
4342
        }
4343
// Add symbol of currency if requested
4344
        $cursymbolbefore = $cursymbolafter = '';
4345
        if ($currency_code) {
4346
            if ($currency_code == 'auto')
4347
                $currency_code = Globals::$conf->currency;
4348
4349
            $listofcurrenciesbefore = array('USD', 'GBP', 'AUD', 'MXN', 'PEN', 'CNY');
4350
            if (in_array($currency_code, $listofcurrenciesbefore))
4351
                $cursymbolbefore .= $outlangs->getCurrencySymbol($currency_code);
4352
            else {
4353
                $tmpcur = $outlangs->getCurrencySymbol($currency_code);
4354
                $cursymbolafter .= ($tmpcur == $currency_code ? ' ' . $tmpcur : $tmpcur);
4355
            }
4356
        }
4357
        $output = $cursymbolbefore . $output . $end . ($cursymbolafter ? ' ' : '') . $cursymbolafter;
4358
4359
        return $output;
4360
    }
4361
4362
    /**
4363
     * 	Function that return a number with universal decimal format (decimal separator is '.') from an amount typed by a user.
4364
     * 	Function to use on each input amount before any numeric test or database insert
4365
     *
4366
     * 	@param	float	$amount			Amount to convert/clean
4367
     * 	@param	string	$rounding		''=No rounding
4368
     * 									'MU'=Round to Max unit price (MAIN_MAX_DECIMALS_UNIT)
4369
     * 									'MT'=Round to Max for totals with Tax (MAIN_MAX_DECIMALS_TOT)
4370
     * 									'MS'=Round to Max for stock quantity (MAIN_MAX_DECIMALS_STOCK)
4371
     * 									Numeric = Nb of digits for rounding
4372
     * 	@param	int		$alreadysqlnb	Put 1 if you know that content is already universal format number
4373
     * 	@return	string					Amount with universal numeric format (Example: '99.99999') or unchanged text if conversion fails. If amount is null or '', it returns ''.
4374
     *
4375
     * 	@see    price					Opposite static function of price2num
4376
     */
4377
    static function price2num($amount, $rounding = '', $alreadysqlnb = 0)
4378
    {
4379
       // global $langs, Globals::$conf;
4380
// Round PHP static function does not allow number like '1,234.56' nor '1.234,56' nor '1 234,56'
4381
// Numbers must be '1234.56'
4382
// Decimal delimiter for PHP and database SQL requests must be '.'
4383
        $dec = ',';
4384
        $thousand = ' ';
4385
        if ($langs->transnoentitiesnoconv("SeparatorDecimal") != "SeparatorDecimal")
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
4386
            $dec = $langs->transnoentitiesnoconv("SeparatorDecimal");
4387
        if ($langs->transnoentitiesnoconv("SeparatorThousand") != "SeparatorThousand")
4388
            $thousand = $langs->transnoentitiesnoconv("SeparatorThousand");
4389
        if ($thousand == 'None')
4390
            $thousand = '';
4391
        elseif ($thousand == 'Space')
4392
            $thousand = ' ';
4393
//print "amount=".$amount." html=".$form." trunc=".$trunc." nbdecimal=".$nbdecimal." dec='".$dec."' thousand='".$thousand."'<br>";
4394
// Convert value to universal number format (no thousand separator, '.' as decimal separator)
4395
        if ($alreadysqlnb != 1) { // If not a PHP number or unknown, we change format
4396
//print 'PP'.$amount.' - '.$dec.' - '.$thousand.' - '.intval($amount).'<br>';
4397
// Convert amount to format with dolibarr dec and thousand (this is because PHP convert a number
4398
// to format defined by LC_NUMERIC after a calculation and we want source format to be like defined by Dolibarr setup.
4399
            if (is_numeric($amount)) {
4400
// We put in temps value of decimal ("0.00001"). Works with 0 and 2.0E-5 and 9999.10
4401
                $temps = sprintf("%0.10F", $amount - intval($amount)); // temps=0.0000000000 or 0.0000200000 or 9999.1000000000
4402
                $temps = preg_replace('/([\.1-9])0+$/', '\\1', $temps); // temps=0. or 0.00002 or 9999.1
4403
                $nbofdec = max(0, dol_strlen($temps) - 2); // -2 to remove "0."
4404
                $amount = number_format($amount, $nbofdec, $dec, $thousand);
4405
            }
4406
//print "QQ".$amount.'<br>';
4407
// Now make replace (the main goal of function)
4408
            if ($thousand != ',' && $thousand != '.')
4409
                $amount = str_replace(',', '.', $amount); // To accept 2 notations for french users
4410
            $amount = str_replace(' ', '', $amount);  // To avoid spaces
4411
            $amount = str_replace($thousand, '', $amount); // Replace of thousand before replace of dec to avoid pb if thousand is .
4412
            $amount = str_replace($dec, '.', $amount);
4413
        }
4414
4415
// Now, make a rounding if required
4416
        if ($rounding) {
4417
            $nbofdectoround = '';
4418
            if ($rounding == 'MU')
4419
                $nbofdectoround = Globals::$conf->global->MAIN_MAX_DECIMALS_UNIT;
4420
            elseif ($rounding == 'MT')
4421
                $nbofdectoround = Globals::$conf->global->MAIN_MAX_DECIMALS_TOT;
4422
            elseif ($rounding == 'MS')
4423
                $nbofdectoround = empty(Globals::$conf->global->MAIN_MAX_DECIMALS_STOCK) ? 5 : Globals::$conf->global->MAIN_MAX_DECIMALS_STOCK;
4424
            elseif (is_numeric($rounding))
4425
                $nbofdectoround = $rounding;
4426
//print "RR".$amount.' - '.$nbofdectoround.'<br>';
4427
            if (dol_strlen($nbofdectoround))
4428
                $amount = round($amount, $nbofdectoround); // $nbofdectoround can be 0.
4429
            else
4430
                return 'ErrorBadParameterProvidedToFunction';
4431
//print 'SS'.$amount.' - '.$nbofdec.' - '.$dec.' - '.$thousand.' - '.$nbofdectoround.'<br>';
4432
// Convert amount to format with dolibarr dec and thousand (this is because PHP convert a number
4433
// to format defined by LC_NUMERIC after a calculation and we want source format to be defined by Dolibarr setup.
4434
            if (is_numeric($amount)) {
4435
// We put in temps value of decimal ("0.00001"). Works with 0 and 2.0E-5 and 9999.10
4436
                $temps = sprintf("%0.10F", $amount - intval($amount)); // temps=0.0000000000 or 0.0000200000 or 9999.1000000000
4437
                $temps = preg_replace('/([\.1-9])0+$/', '\\1', $temps); // temps=0. or 0.00002 or 9999.1
4438
                $nbofdec = max(0, dol_strlen($temps) - 2); // -2 to remove "0."
4439
                $amount = number_format($amount, min($nbofdec, $nbofdectoround), $dec, $thousand);  // Convert amount to format with dolibarr dec and thousand
4440
            }
4441
//print "TT".$amount.'<br>';
4442
// Always make replace because each math static function (like round) replace
4443
// with local values and we want a number that has a SQL string format x.y
4444
            if ($thousand != ',' && $thousand != '.')
4445
                $amount = str_replace(',', '.', $amount); // To accept 2 notations for french users
4446
            $amount = str_replace(' ', '', $amount);  // To avoid spaces
4447
            $amount = str_replace($thousand, '', $amount); // Replace of thousand before replace of dec to avoid pb if thousand is .
4448
            $amount = str_replace($dec, '.', $amount);
4449
        }
4450
4451
        return $amount;
4452
    }
4453
4454
    /**
4455
     * Output a dimension with best unit
4456
     *
4457
     * @param   float       $dimension      Dimension
4458
     * @param   int         $unit           Unit of dimension (0, -3, ...)
4459
     * @param   string      $type           'weight', 'volume', ...
4460
     * @param   Translate   $outputlangs    Translate language object
4461
     * @param   int         $round          -1 = non rounding, x = number of decimal
4462
     * @param   string      $forceunitoutput    'no' or numeric (-3, -6, ...) compared to $unit
4463
     * @return  string                      String to show dimensions
4464
     */
4465
    static function showDimensionInBestUnit($dimension, $unit, $type, $outputlangs, $round = -1, $forceunitoutput = 'no')
4466
    {
4467
        require_once DOL_BASE_PATH . '/core/lib/product.lib.php';
4468
4469
        if (($forceunitoutput == 'no' && $dimension < 1 / 10000) || (is_numeric($forceunitoutput) && $forceunitoutput == -6)) {
4470
            $dimension = $dimension * 1000000;
4471
            $unit = $unit - 6;
4472
        } elseif (($forceunitoutput == 'no' && $dimension < 1 / 10) || (is_numeric($forceunitoutput) && $forceunitoutput == -3)) {
4473
            $dimension = $dimension * 1000;
4474
            $unit = $unit - 3;
4475
        } elseif (($forceunitoutput == 'no' && $dimension > 100000000) || (is_numeric($forceunitoutput) && $forceunitoutput == 6)) {
4476
            $dimension = $dimension / 1000000;
4477
            $unit = $unit + 6;
4478
        } elseif (($forceunitoutput == 'no' && $dimension > 100000) || (is_numeric($forceunitoutput) && $forceunitoutput == 3)) {
4479
            $dimension = $dimension / 1000;
4480
            $unit = $unit + 3;
4481
        }
4482
4483
        $ret = price($dimension, 0, $outputlangs, 0, 0, $round) . ' ' . measuring_units_string($unit, $type);
4484
4485
        return $ret;
4486
    }
4487
4488
    /**
4489
     * 	Return localtax rate for a particular vat, when selling a product with vat $vatrate, from a $thirdparty_buyer to a $thirdparty_seller
4490
     *  Note: This static function applies same rules than get_default_tva
4491
     *
4492
     * 	@param	float		$vatrate		        Vat rate. Can be '8.5' or '8.5 (VATCODEX)' for example
4493
     * 	@param  int			$local		         	Local tax to search and return (1 or 2 return only tax rate 1 or tax rate 2)
4494
     *  @param  Societe		$thirdparty_buyer    	Object of buying third party
0 ignored issues
show
Bug introduced by
The type Alixar\Helpers\Societe was not found. Did you mean Societe? If so, make sure to prefix the type with \.
Loading history...
4495
     *  @param	Societe		$thirdparty_seller		Object of selling third party ($mysoc if not defined)
4496
     *  @param	int			$vatnpr					If vat rate is NPR or not
4497
     * 	@return	mixed			   					0 if not found, localtax rate if found
4498
     *  @see get_default_tva
4499
     */
4500
    static function get_localtax($vatrate, $local, $thirdparty_buyer = "", $thirdparty_seller = "", $vatnpr = 0)
4501
    {
4502
       // global $db, Globals::$conf, $mysoc;
4503
4504
        if (empty($thirdparty_seller) || !is_object($thirdparty_seller))
4505
            $thirdparty_seller = $mysoc;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mysoc seems to be never defined.
Loading history...
4506
4507
        dol_syslog("get_localtax tva=" . $vatrate . " local=" . $local . " thirdparty_buyer id=" . (is_object($thirdparty_buyer) ? $thirdparty_buyer->id : '') . "/country_code=" . (is_object($thirdparty_buyer) ? $thirdparty_buyer->country_code : '') . " thirdparty_seller id=" . $thirdparty_seller->id . "/country_code=" . $thirdparty_seller->country_code . " thirdparty_seller localtax1_assuj=" . $thirdparty_seller->localtax1_assuj . "  thirdparty_seller localtax2_assuj=" . $thirdparty_seller->localtax2_assuj);
4508
4509
        $vatratecleaned = $vatrate;
4510
        if (preg_match('/^(.*)\s*\((.*)\)$/', $vatrate, $reg)) {      // If vat is "xx (yy)"
4511
            $vatratecleaned = trim($reg[1]);
4512
            $vatratecode = $reg[2];
4513
        }
4514
4515
        /* if ($thirdparty_buyer->country_code != $thirdparty_seller->country_code)
4516
          {
4517
          return 0;
4518
          } */
4519
4520
// Some test to guess with no need to make database access
4521
        if ($mysoc->country_code == 'ES') { // For spain localtaxes 1 and 2, tax is qualified if buyer use local tax
4522
            if ($local == 1) {
4523
                if (!$mysoc->localtax1_assuj || (string) $vatratecleaned == "0")
4524
                    return 0;
4525
                if ($thirdparty_seller->id == $mysoc->id) {
4526
                    if (!$thirdparty_buyer->localtax1_assuj)
0 ignored issues
show
Bug introduced by
The property localtax1_assuj does not exist on string.
Loading history...
4527
                        return 0;
4528
                }
4529
                else {
4530
                    if (!$thirdparty_seller->localtax1_assuj)
4531
                        return 0;
4532
                }
4533
            }
4534
4535
            if ($local == 2) {
4536
//if (! $mysoc->localtax2_assuj || (string) $vatratecleaned == "0") return 0;
4537
                if (!$mysoc->localtax2_assuj)
4538
                    return 0;  // If main vat is 0, IRPF may be different than 0.
4539
                if ($thirdparty_seller->id == $mysoc->id) {
4540
                    if (!$thirdparty_buyer->localtax2_assuj)
0 ignored issues
show
Bug introduced by
The property localtax2_assuj does not exist on string.
Loading history...
4541
                        return 0;
4542
                }
4543
                else {
4544
                    if (!$thirdparty_seller->localtax2_assuj)
4545
                        return 0;
4546
                }
4547
            }
4548
        }
4549
        else {
4550
            if ($local == 1 && !$thirdparty_seller->localtax1_assuj)
4551
                return 0;
4552
            if ($local == 2 && !$thirdparty_seller->localtax2_assuj)
4553
                return 0;
4554
        }
4555
4556
// For some country MAIN_GET_LOCALTAXES_VALUES_FROM_THIRDPARTY is forced to on.
4557
        if (in_array($mysoc->country_code, array('ES'))) {
4558
            Globals::$conf->global->MAIN_GET_LOCALTAXES_VALUES_FROM_THIRDPARTY = 1;
4559
        }
4560
4561
// Search local taxes
4562
        if (!empty(Globals::$conf->global->MAIN_GET_LOCALTAXES_VALUES_FROM_THIRDPARTY)) {
4563
            if ($local == 1) {
4564
                if ($thirdparty_seller != $mysoc) {
4565
                    if (!isOnlyOneLocalTax($local)) {  // TODO We should provide $vatrate to search on correct line and not always on line with highest vat rate
4566
                        return $thirdparty_seller->localtax1_value;
4567
                    }
4568
                } else {  // i am the seller
4569
                    if (!isOnlyOneLocalTax($local)) {  // TODO If seller is me, why not always returning this, even if there is only one locatax vat.
4570
                        return Globals::$conf->global->MAIN_INFO_VALUE_LOCALTAX1;
4571
                    }
4572
                }
4573
            }
4574
            if ($local == 2) {
4575
                if ($thirdparty_seller != $mysoc) {
4576
                    if (!isOnlyOneLocalTax($local)) {  // TODO We should provide $vatrate to search on correct line and not always on line with highest vat rate
4577
                        // TODO We should also return value defined on thirdparty only if defined
4578
                        return $thirdparty_seller->localtax2_value;
4579
                    }
4580
                } else {  // i am the seller
4581
                    if (in_array($mysoc->country_code, array('ES'))) {
4582
                        return $thirdparty_buyer->localtax2_value;
0 ignored issues
show
Bug introduced by
The property localtax2_value does not exist on string.
Loading history...
4583
                    } else {
4584
                        return Globals::$conf->global->MAIN_INFO_VALUE_LOCALTAX2;
4585
                    }
4586
                }
4587
            }
4588
        }
4589
4590
// By default, search value of local tax on line of common tax
4591
        $sql = "SELECT t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
4592
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_tva as t, " . MAIN_DB_PREFIX . "c_country as c";
4593
        $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '" . $thirdparty_seller->country_code . "'";
4594
        $sql .= " AND t.taux = " . ((float) $vatratecleaned) . " AND t.active = 1";
4595
        if ($vatratecode)
4596
            $sql .= " AND t.code ='" . $vatratecode . "'";  // If we have the code, we use it in priority
4597
        else
4598
            $sql .= " AND t.recuperableonly ='" . $vatnpr . "'";
4599
        dol_syslog("get_localtax", LOG_DEBUG);
4600
        $resql = $db->query($sql);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $db seems to be never defined.
Loading history...
4601
4602
        if ($resql) {
4603
            $obj = $db->fetch_object($resql);
4604
            if ($local == 1)
4605
                return $obj->localtax1;
4606
            elseif ($local == 2)
4607
                return $obj->localtax2;
4608
        }
4609
4610
        return 0;
4611
    }
4612
4613
    /**
4614
     * Return true if LocalTax (1 or 2) is unique.
4615
     * Example: If localtax1 is 5 on line with highest common vat rate, return true
4616
     * Example: If localtax1 is 5:8:15 on line with highest common vat rate, return false
4617
     *
4618
     * @param   int 	$local	Local tax to test (1 or 2)
4619
     * @return  boolean 		True if LocalTax have multiple values, False if not
4620
     */
4621
    static function isOnlyOneLocalTax($local)
4622
    {
4623
        $tax = get_localtax_by_third($local);
4624
4625
        $valors = explode(":", $tax);
4626
4627
        if (count($valors) > 1) {
4628
            return false;
4629
        } else {
4630
            return true;
4631
        }
4632
    }
4633
4634
    /**
4635
     * Get values of localtaxes (1 or 2) for company country for the common vat with the highest value
4636
     *
4637
     * @param	int		$local 	LocalTax to get
4638
     * @return	number			Values of localtax
4639
     */
4640
    static function get_localtax_by_third($local)
4641
    {
4642
       // global $db, $mysoc;
4643
        $sql = "SELECT t.localtax1, t.localtax2 ";
4644
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_tva as t inner join " . MAIN_DB_PREFIX . "c_country as c ON c.rowid=t.fk_pays";
4645
        $sql .= " WHERE c.code = '" . $mysoc->country_code . "' AND t.active = 1 AND t.taux=(";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mysoc seems to be never defined.
Loading history...
4646
        $sql .= "  SELECT max(tt.taux) FROM " . MAIN_DB_PREFIX . "c_tva as tt inner join " . MAIN_DB_PREFIX . "c_country as c ON c.rowid=tt.fk_pays";
4647
        $sql .= "  WHERE c.code = '" . $mysoc->country_code . "' AND tt.active = 1";
4648
        $sql .= "  )";
4649
4650
        $resql = $db->query($sql);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $db seems to be never defined.
Loading history...
4651
        if ($resql) {
4652
            $obj = $db->fetch_object($resql);
4653
            if ($local == 1)
4654
                return $obj->localtax1;
4655
            elseif ($local == 2)
4656
                return $obj->localtax2;
4657
        }
4658
4659
        return 0;
4660
    }
4661
4662
    /**
4663
     *  Get vat main information from Id.
4664
     *  You can call getLocalTaxesFromRate after to get other fields.
4665
     *
4666
     *  @param	int|string  $vatrate		    VAT ID or Rate. Value can be value or the string with code into parenthesis or rowid if $firstparamisid is 1. Example: '8.5' or '8.5 (8.5NPR)' or 123.
4667
     *  @param	Societe	    $buyer         		Company object
4668
     *  @param	Societe	    $seller        		Company object
4669
     *  @param  int         $firstparamisid     1 if first param is id into table (use this if you can)
4670
     *  @return	array       	  				array('rowid'=> , 'code'=> ...)
4671
     *  @see getLocalTaxesFromRate
4672
     */
4673
    static function getTaxesFromId($vatrate, $buyer = null, $seller = null, $firstparamisid = 1)
4674
    {
4675
       // global $db, $mysoc;
4676
4677
        dol_syslog("getTaxesFromId vat id or rate = " . $vatrate);
4678
4679
// Search local taxes
4680
        $sql = "SELECT t.rowid, t.code, t.taux as rate, t.recuperableonly as npr, t.accountancy_code_sell, t.accountancy_code_buy";
4681
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_tva as t";
4682
        if ($firstparamisid)
4683
            $sql .= " WHERE t.rowid = " . (int) $vatrate;
4684
        else {
4685
            $vatratecleaned = $vatrate;
4686
            $vatratecode = '';
4687
            if (preg_match('/^(.*)\s*\((.*)\)$/', $vatrate, $reg)) {      // If vat is "xx (yy)"
4688
                $vatratecleaned = $reg[1];
4689
                $vatratecode = $reg[2];
4690
            }
4691
4692
            $sql .= ", " . MAIN_DB_PREFIX . "c_country as c";
4693
            /* if ($mysoc->country_code == 'ES') $sql.= " WHERE t.fk_pays = c.rowid AND c.code = '".$buyer->country_code."'";    // vat in spain use the buyer country ??
4694
              else $sql.= " WHERE t.fk_pays = c.rowid AND c.code = '".$seller->country_code."'"; */
4695
            $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '" . $seller->country_code . "'";
4696
            $sql .= " AND t.taux = " . ((float) $vatratecleaned) . " AND t.active = 1";
4697
            if ($vatratecode)
4698
                $sql .= " AND t.code = '" . $vatratecode . "'";
4699
        }
4700
4701
        $resql = $db->query($sql);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $db seems to be never defined.
Loading history...
4702
        if ($resql) {
4703
            $obj = $db->fetch_object($resql);
4704
            if ($obj)
4705
                return array('rowid' => $obj->rowid, 'code' => $obj->code, 'rate' => $obj->rate, 'npr' => $obj->npr, 'accountancy_code_sell' => $obj->accountancy_code_sell, 'accountancy_code_buy' => $obj->accountancy_code_buy);
4706
            else
4707
                return array();
4708
        } else
4709
            dol_print_error($db);
4710
4711
        return array();
4712
    }
4713
4714
    /**
4715
     *  Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
4716
     *  This does not take into account the seller setup if subject to vat or not, only country.
4717
     *  TODO
4718
     *  This static function is ALSO called to retrieve type for building PDF. Such call of static function must be removed.
4719
     *  Instead this static function must be called when adding a line to get the array of localtax and type, and then
4720
     *  provide it to the static function calcul_price_total.
4721
     *
4722
     *  @param	int|string  $vatrate			VAT ID or Rate+Code. Value can be value or the string with code into parenthesis or rowid if $firstparamisid is 1. Example: '8.5' or '8.5 (8.5NPR)' or 123.
4723
     *  @param	int		    $local              Number of localtax (1 or 2, or 0 to return 1 & 2)
4724
     *  @param	Societe	    $buyer         		Company object
4725
     *  @param	Societe	    $seller        		Company object
4726
     *  @param  int         $firstparamisid     1 if first param is ID into table instead of Rate+code (use this if you can)
4727
     *  @return	array    	    				array(localtax_type1(1-6/0 if not found), rate localtax1, localtax_type2, rate localtax2, accountancycodecust, accountancycodesupp)
4728
     *  @see getTaxesFromId
4729
     */
4730
    static function getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid = 0)
4731
    {
4732
       // global $db, $mysoc;
4733
4734
        dol_syslog("getLocalTaxesFromRate vatrate=" . $vatrate . " local=" . $local);
4735
4736
// Search local taxes
4737
        $sql = "SELECT t.localtax1, t.localtax1_type, t.localtax2, t.localtax2_type, t.accountancy_code_sell, t.accountancy_code_buy";
4738
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_tva as t";
4739
        if ($firstparamisid)
4740
            $sql .= " WHERE t.rowid = " . (int) $vatrate;
4741
        else {
4742
            $vatratecleaned = $vatrate;
4743
            $vatratecode = '';
4744
            if (preg_match('/^(.*)\s*\((.*)\)$/', $vatrate, $reg)) {      // If vat is "x.x (yy)"
4745
                $vatratecleaned = $reg[1];
4746
                $vatratecode = $reg[2];
4747
            }
4748
4749
            $sql .= ", " . MAIN_DB_PREFIX . "c_country as c";
4750
            if ($mysoc->country_code == 'ES')
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mysoc seems to be never defined.
Loading history...
4751
                $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '" . $buyer->country_code . "'";    // local tax in spain use the buyer country ??
4752
            else
4753
                $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '" . $seller->country_code . "'";
4754
            $sql .= " AND t.taux = " . ((float) $vatratecleaned) . " AND t.active = 1";
4755
            if ($vatratecode)
4756
                $sql .= " AND t.code = '" . $vatratecode . "'";
4757
        }
4758
4759
        $resql = $db->query($sql);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $db seems to be never defined.
Loading history...
4760
        if ($resql) {
4761
            $obj = $db->fetch_object($resql);
4762
            if ($local == 1) {
4763
                return array($obj->localtax1_type, get_localtax($vatrate, $local, $buyer, $seller), $obj->accountancy_code_sell, $obj->accountancy_code_buy);
4764
            } elseif ($local == 2) {
4765
                return array($obj->localtax2_type, get_localtax($vatrate, $local, $buyer, $seller), $obj->accountancy_code_sell, $obj->accountancy_code_buy);
4766
            } else {
4767
                return array($obj->localtax1_type, get_localtax($vatrate, 1, $buyer, $seller), $obj->localtax2_type, get_localtax($vatrate, 2, $buyer, $seller), $obj->accountancy_code_sell, $obj->accountancy_code_buy);
4768
            }
4769
        }
4770
4771
        return 0;
4772
    }
4773
4774
    /**
4775
     * 	Return vat rate of a product in a particular selling country or default country vat if product is unknown
4776
     *  Function called by get_default_tva
4777
     *
4778
     *  @param	int			$idprod          	Id of product or 0 if not a predefined product
4779
     *  @param  Societe		$thirdparty_seller  Thirdparty with a ->country_code defined (FR, US, IT, ...)
4780
     * 	@param	int			$idprodfournprice	Id product_fournisseur_price (for "supplier" proposal/order/invoice)
4781
     *  @return float|string   				    Vat rate to use with format 5.0 or '5.0 (XXX)'
4782
     *  @see get_product_localtax_for_country
4783
     */
4784
    static function get_product_vat_for_country($idprod, $thirdparty_seller, $idprodfournprice = 0)
4785
    {
4786
       // global $db, Globals::$conf, $mysoc;
4787
4788
        require_once DOL_BASE_PATH . '/product/class/product.class.php';
4789
4790
        $ret = 0;
4791
        $found = 0;
4792
4793
        if ($idprod > 0) {
4794
// Load product
4795
            $product = new Product($db);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $db seems to be never defined.
Loading history...
Bug introduced by
The type Alixar\Helpers\Product was not found. Did you mean Product? If so, make sure to prefix the type with \.
Loading history...
4796
            $result = $product->fetch($idprod);
4797
4798
            if ($mysoc->country_code == $thirdparty_seller->country_code) { // If selling country is ours
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mysoc seems to be never defined.
Loading history...
4799
                if ($idprodfournprice > 0) {     // We want vat for product for a "supplier" object
4800
                    $product->get_buyprice($idprodfournprice, 0, 0, 0);
4801
                    $ret = $product->vatrate_supplier;
4802
                    if ($product->default_vat_code)
4803
                        $ret .= ' (' . $product->default_vat_code . ')';
4804
                }
4805
                else {
4806
                    $ret = $product->tva_tx;    // Default vat of product we defined
4807
                    if ($product->default_vat_code)
4808
                        $ret .= ' (' . $product->default_vat_code . ')';
4809
                }
4810
                $found = 1;
4811
            }
4812
            else {
4813
// TODO Read default product vat according to countrycode and product. Vat for couple countrycode/product is a feature not implemeted yet.
4814
// May be usefull/required if hidden option SERVICE_ARE_ECOMMERCE_200238EC is on
4815
            }
4816
        }
4817
4818
        if (!$found) {
4819
            if (empty(Globals::$conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS)) {
4820
// If vat of product for the country not found or not defined, we return the first higher vat of country.
4821
                $sql = "SELECT t.taux as vat_rate, t.code as default_vat_code";
4822
                $sql .= " FROM " . MAIN_DB_PREFIX . "c_tva as t, " . MAIN_DB_PREFIX . "c_country as c";
4823
                $sql .= " WHERE t.active=1 AND t.fk_pays = c.rowid AND c.code='" . $thirdparty_seller->country_code . "'";
4824
                $sql .= " ORDER BY t.taux DESC, t.code ASC, t.recuperableonly ASC";
4825
                $sql .= $db->plimit(1);
4826
4827
                $resql = $db->query($sql);
4828
                if ($resql) {
4829
                    $obj = $db->fetch_object($resql);
4830
                    if ($obj) {
4831
                        $ret = $obj->vat_rate;
4832
                        if ($obj->default_vat_code)
4833
                            $ret .= ' (' . $obj->default_vat_code . ')';
4834
                    }
4835
                    $db->free($sql);
4836
                } else
4837
                    dol_print_error($db);
4838
            } else
4839
                $ret = Globals::$conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS;    // Forced value if autodetect fails
4840
        }
4841
4842
        dol_syslog("get_product_vat_for_country: ret=" . $ret);
4843
        return $ret;
4844
    }
4845
4846
    /**
4847
     * 	Return localtax vat rate of a product in a particular selling country or default country vat if product is unknown
4848
     *
4849
     *  @param	int		$idprod         		Id of product
4850
     *  @param  int		$local          		1 for localtax1, 2 for localtax 2
4851
     *  @param  Societe	$thirdparty_seller    	Thirdparty with a ->country_code defined (FR, US, IT, ...)
4852
     *  @return int             				<0 if KO, Vat rate if OK
4853
     *  @see get_product_vat_for_country
4854
     */
4855
    static function get_product_localtax_for_country($idprod, $local, $thirdparty_seller)
4856
    {
4857
       // global $db, $mysoc;
4858
4859
        if (!class_exists('Product')) {
4860
            require_once DOL_BASE_PATH . 'product/class/product.class.php';
4861
        }
4862
4863
        $ret = 0;
4864
        $found = 0;
4865
4866
        if ($idprod > 0) {
4867
// Load product
4868
            $product = new Product($db);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $db seems to be never defined.
Loading history...
4869
            $result = $product->fetch($idprod);
4870
4871
            if ($mysoc->country_code == $thirdparty_seller->country_code) { // If selling country is ours
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mysoc seems to be never defined.
Loading history...
4872
                /* Not defined yet, so we don't use this
4873
                  if ($local==1) $ret=$product->localtax1_tx;
4874
                  elseif ($local==2) $ret=$product->localtax2_tx;
4875
                  $found=1;
4876
                 */
4877
            } else {
4878
// TODO Read default product vat according to countrycode and product
4879
            }
4880
        }
4881
4882
        if (!$found) {
4883
// If vat of product for the country not found or not defined, we return higher vat of country.
4884
            $sql = "SELECT taux as vat_rate, localtax1, localtax2";
4885
            $sql .= " FROM " . MAIN_DB_PREFIX . "c_tva as t, " . MAIN_DB_PREFIX . "c_country as c";
4886
            $sql .= " WHERE t.active=1 AND t.fk_pays = c.rowid AND c.code='" . $thirdparty_seller->country_code . "'";
4887
            $sql .= " ORDER BY t.taux DESC, t.recuperableonly ASC";
4888
            $sql .= $db->plimit(1);
4889
4890
            $resql = $db->query($sql);
4891
            if ($resql) {
4892
                $obj = $db->fetch_object($resql);
4893
                if ($obj) {
4894
                    if ($local == 1)
4895
                        $ret = $obj->localtax1;
4896
                    elseif ($local == 2)
4897
                        $ret = $obj->localtax2;
4898
                }
4899
            } else
4900
                dol_print_error($db);
4901
        }
4902
4903
        dol_syslog("get_product_localtax_for_country: ret=" . $ret);
4904
        return $ret;
4905
    }
4906
4907
    /**
4908
     * 	Function that return vat rate of a product line (according to seller, buyer and product vat rate)
4909
     *   Si vendeur non assujeti a TVA, TVA par defaut=0. Fin de regle.
4910
     * 	 Si le (pays vendeur = pays acheteur) alors TVA par defaut=TVA du produit vendu. Fin de regle.
4911
     * 	 Si (vendeur et acheteur dans Communaute europeenne) et (bien vendu = moyen de transports neuf comme auto, bateau, avion) alors TVA par defaut=0 (La TVA doit etre paye par acheteur au centre d'impots de son pays et non au vendeur). Fin de regle.
4912
     * 	 Si (vendeur et acheteur dans Communaute europeenne) et (acheteur = particulier ou entreprise sans num TVA intra) alors TVA par defaut=TVA du produit vendu. Fin de regle
4913
     * 	 Si (vendeur et acheteur dans Communaute europeenne) et (acheteur = entreprise avec num TVA) intra alors TVA par defaut=0. Fin de regle
4914
     * 	 Sinon TVA proposee par defaut=0. Fin de regle.
4915
     *
4916
     * 	@param	Societe		$thirdparty_seller    	Objet societe vendeuse
4917
     * 	@param  Societe		$thirdparty_buyer   	Objet societe acheteuse
4918
     * 	@param  int			$idprod					Id product
4919
     * 	@param	int			$idprodfournprice		Id product_fournisseur_price (for supplier order/invoice)
4920
     * 	@return float|string   				      	Vat rate to use with format 5.0 or '5.0 (XXX)', -1 if we can't guess it
4921
     *  @see get_default_npr, get_default_localtax
4922
     */
4923
    static function get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod = 0, $idprodfournprice = 0)
4924
    {
4925
       // global Globals::$conf;
4926
4927
        require_once DOL_BASE_PATH . '/core/lib/company.lib.php';
4928
4929
// Note: possible values for tva_assuj are 0/1 or franchise/reel
4930
        $seller_use_vat = ((is_numeric($thirdparty_seller->tva_assuj) && !$thirdparty_seller->tva_assuj) || (!is_numeric($thirdparty_seller->tva_assuj) && $thirdparty_seller->tva_assuj == 'franchise')) ? 0 : 1;
4931
4932
        $seller_country_code = $thirdparty_seller->country_code;
4933
        $seller_in_cee = isInEEC($thirdparty_seller);
4934
4935
        $buyer_country_code = $thirdparty_buyer->country_code;
4936
        $buyer_in_cee = isInEEC($thirdparty_buyer);
4937
4938
        dol_syslog("get_default_tva: seller use vat=" . $seller_use_vat . ", seller country=" . $seller_country_code . ", seller in cee=" . $seller_in_cee . ", buyer vat number=" . $thirdparty_buyer->tva_intra . " buyer country=" . $buyer_country_code . ", buyer in cee=" . $buyer_in_cee . ", idprod=" . $idprod . ", idprodfournprice=" . $idprodfournprice . ", SERVICE_ARE_ECOMMERCE_200238EC=" . (!empty(Globals::$conf->global->SERVICES_ARE_ECOMMERCE_200238EC) ? Globals::$conf->global->SERVICES_ARE_ECOMMERCE_200238EC : ''));
4939
4940
// If services are eServices according to EU Council Directive 2002/38/EC (http://ec.europa.eu/taxation_customs/taxation/vat/traders/e-commerce/article_1610_en.htm)
4941
// we use the buyer VAT.
4942
        if (!empty(Globals::$conf->global->SERVICE_ARE_ECOMMERCE_200238EC)) {
4943
            if ($seller_in_cee && $buyer_in_cee && !$thirdparty_buyer->isACompany()) {
4944
//print 'VATRULE 0';
4945
                return get_product_vat_for_country($idprod, $thirdparty_buyer, $idprodfournprice);
4946
            }
4947
        }
4948
4949
// If seller does not use VAT
4950
        if (!$seller_use_vat) {
4951
//print 'VATRULE 1';
4952
            return 0;
4953
        }
4954
4955
// Le test ci-dessus ne devrait pas etre necessaire. Me signaler l'exemple du cas juridique concerne si le test suivant n'est pas suffisant.
4956
// Si le (pays vendeur = pays acheteur) alors la TVA par defaut=TVA du produit vendu. Fin de regle.
4957
        if (($seller_country_code == $buyer_country_code) || (in_array($seller_country_code, array('FR,MC')) && in_array($buyer_country_code, array('FR', 'MC')))) { // Warning ->country_code not always defined
4958
//print 'VATRULE 2';
4959
            return get_product_vat_for_country($idprod, $thirdparty_seller, $idprodfournprice);
4960
        }
4961
4962
// Si (vendeur et acheteur dans Communaute europeenne) et (bien vendu = moyen de transports neuf comme auto, bateau, avion) alors TVA par defaut=0 (La TVA doit etre paye par l'acheteur au centre d'impots de son pays et non au vendeur). Fin de regle.
4963
// Not supported
4964
// Si (vendeur et acheteur dans Communaute europeenne) et (acheteur = entreprise) alors TVA par defaut=0. Fin de regle
4965
// Si (vendeur et acheteur dans Communaute europeenne) et (acheteur = particulier) alors TVA par defaut=TVA du produit vendu. Fin de regle
4966
        if (($seller_in_cee && $buyer_in_cee)) {
4967
            $isacompany = $thirdparty_buyer->isACompany();
4968
            if ($isacompany) {
4969
//print 'VATRULE 3';
4970
                return 0;
4971
            } else {
4972
//print 'VATRULE 4';
4973
                return get_product_vat_for_country($idprod, $thirdparty_seller, $idprodfournprice);
4974
            }
4975
        }
4976
4977
// Si (vendeur en France et acheteur hors Communaute europeenne et acheteur particulier) alors TVA par defaut=TVA du produit vendu. Fin de regle
4978
        if (!empty(Globals::$conf->global->MAIN_USE_VAT_OF_PRODUCT_FOR_INDIVIDUAL_CUSTOMER_OUT_OF_EEC) && empty($buyer_in_cee) && !$thirdparty_buyer->isACompany()) {
4979
            return get_product_vat_for_country($idprod, $thirdparty_seller, $idprodfournprice);
4980
        }
4981
4982
// Sinon la TVA proposee par defaut=0. Fin de regle.
4983
// Rem: Cela signifie qu'au moins un des 2 est hors Communaute europeenne et que le pays differe
4984
//print 'VATRULE 5';
4985
        return 0;
4986
    }
4987
4988
    /**
4989
     * 	Fonction qui renvoie si tva doit etre tva percue recuperable
4990
     *
4991
     * 	@param	Societe		$thirdparty_seller    	Thirdparty seller
4992
     * 	@param  Societe		$thirdparty_buyer   	Thirdparty buyer
4993
     *  @param  int			$idprod                 Id product
4994
     *  @param	int			$idprodfournprice		Id supplier price for product
4995
     * 	@return float       			        	0 or 1
4996
     *  @see get_default_tva, get_default_localtax
4997
     */
4998
    static function get_default_npr(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod = 0, $idprodfournprice = 0)
4999
    {
5000
       // global $db;
5001
5002
        if ($idprodfournprice > 0) {
5003
            if (!class_exists('ProductFournisseur'))
5004
                require_once DOL_BASE_PATH . '/fourn/class/fournisseur.product.class.php';
5005
            $prodprice = new ProductFournisseur($db);
0 ignored issues
show
Bug introduced by
The type Alixar\Helpers\ProductFournisseur was not found. Did you mean ProductFournisseur? If so, make sure to prefix the type with \.
Loading history...
Comprehensibility Best Practice introduced by
The variable $db seems to be never defined.
Loading history...
5006
            $prodprice->fetch_product_fournisseur_price($idprodfournprice);
5007
            return $prodprice->fourn_tva_npr;
5008
        }
5009
        elseif ($idprod > 0) {
5010
            if (!class_exists('Product'))
5011
                require_once DOL_BASE_PATH . 'product/class/product.class.php';
5012
            $prod = new Product($db);
5013
            $prod->fetch($idprod);
5014
            return $prod->tva_npr;
5015
        }
5016
5017
        return 0;
5018
    }
5019
5020
    /**
5021
     * 	Function that return localtax of a product line (according to seller, buyer and product vat rate)
5022
     *   Si vendeur non assujeti a TVA, TVA par defaut=0. Fin de regle.
5023
     * 	 Si le (pays vendeur = pays acheteur) alors TVA par defaut=TVA du produit vendu. Fin de regle.
5024
     * 	 Sinon TVA proposee par defaut=0. Fin de regle.
5025
     *
5026
     * 	@param	Societe		$thirdparty_seller    	Thirdparty seller
5027
     * 	@param  Societe		$thirdparty_buyer   	Thirdparty buyer
5028
     *  @param	int			$local					Localtax to process (1 or 2)
5029
     * 	@param  int			$idprod					Id product
5030
     * 	@return integer        				       	localtax, -1 si ne peut etre determine
5031
     *  @see get_default_tva, get_default_npr
5032
     */
5033
    static function get_default_localtax($thirdparty_seller, $thirdparty_buyer, $local, $idprod = 0)
5034
    {
5035
       // global $mysoc;
5036
5037
        if (!is_object($thirdparty_seller))
5038
            return -1;
5039
        if (!is_object($thirdparty_buyer))
5040
            return -1;
5041
5042
        if ($local == 1) { // Localtax 1
5043
            if ($mysoc->country_code == 'ES') {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mysoc seems to be never defined.
Loading history...
5044
                if (is_numeric($thirdparty_buyer->localtax1_assuj) && !$thirdparty_buyer->localtax1_assuj)
5045
                    return 0;
5046
            }
5047
            else {
5048
// Si vendeur non assujeti a Localtax1, localtax1 par default=0
5049
                if (is_numeric($thirdparty_seller->localtax1_assuj) && !$thirdparty_seller->localtax1_assuj)
5050
                    return 0;
5051
                if (!is_numeric($thirdparty_seller->localtax1_assuj) && $thirdparty_seller->localtax1_assuj == 'localtax1off')
5052
                    return 0;
5053
            }
5054
        }
5055
        elseif ($local == 2) { //I Localtax 2
5056
// Si vendeur non assujeti a Localtax2, localtax2 par default=0
5057
            if (is_numeric($thirdparty_seller->localtax2_assuj) && !$thirdparty_seller->localtax2_assuj)
5058
                return 0;
5059
            if (!is_numeric($thirdparty_seller->localtax2_assuj) && $thirdparty_seller->localtax2_assuj == 'localtax2off')
5060
                return 0;
5061
        }
5062
5063
        if ($thirdparty_seller->country_code == $thirdparty_buyer->country_code) {
5064
            return get_product_localtax_for_country($idprod, $local, $thirdparty_seller);
5065
        }
5066
5067
        return 0;
5068
    }
5069
5070
    /**
5071
     * 	Return yes or no in current language
5072
     *
5073
     * 	@param	string	$yesno			Value to test (1, 'yes', 'true' or 0, 'no', 'false')
5074
     * 	@param	integer	$case			1=Yes/No, 0=yes/no, 2=Disabled checkbox, 3=Disabled checkbox + Yes/No
5075
     * 	@param	int		$color			0=texte only, 1=Text is formated with a color font style ('ok' or 'error'), 2=Text is formated with 'ok' color.
5076
     * 	@return	string					HTML string
5077
     */
5078
    static function yn($yesno, $case = 1, $color = 0)
5079
    {
5080
       // global $langs;
5081
        $result = 'unknown';
5082
        $classname = '';
5083
        if ($yesno == 1 || strtolower($yesno) == 'yes' || strtolower($yesno) == 'true') {  // A mettre avant test sur no a cause du == 0
5084
            $result = $langs->trans('yes');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
5085
            if ($case == 1 || $case == 3)
5086
                $result = $langs->trans("Yes");
5087
            if ($case == 2)
5088
                $result = '<input type="checkbox" value="1" checked disabled>';
5089
            if ($case == 3)
5090
                $result = '<input type="checkbox" value="1" checked disabled> ' . $result;
5091
5092
            $classname = 'ok';
5093
        }
5094
        elseif ($yesno == 0 || strtolower($yesno) == 'no' || strtolower($yesno) == 'false') {
5095
            $result = $langs->trans("no");
5096
            if ($case == 1 || $case == 3)
5097
                $result = $langs->trans("No");
5098
            if ($case == 2)
5099
                $result = '<input type="checkbox" value="0" disabled>';
5100
            if ($case == 3)
5101
                $result = '<input type="checkbox" value="0" disabled> ' . $result;
5102
5103
            if ($color == 2)
5104
                $classname = 'ok';
5105
            else
5106
                $classname = 'error';
5107
        }
5108
        if ($color)
5109
            return '<font class="' . $classname . '">' . $result . '</font>';
5110
        return $result;
5111
    }
5112
5113
    /**
5114
     * 	Return a path to have a the directory according to object where files are stored.
5115
     *  New usage:       Globals::$conf->module->multidir_output[$object->entity].'/'.get_exdir(0, 0, 0, 1, $object, $modulepart)
5116
     *         or:       Globals::$conf->module->dir_output.'/'.get_exdir(0, 0, 0, 1, $object, $modulepart)     if multidir_output not defined.
5117
     *  Example our with new usage:       $object is invoice -> 'INYYMM-ABCD'
5118
     *  Example our with old usage:       '015' with level 3->"0/1/5/", '015' with level 1->"5/", 'ABC-1' with level 3 ->"0/0/1/"
5119
     *
5120
     * 	@param	string	$num            Id of object (deprecated, $object will be used in future)
5121
     * 	@param  int		$level		    Level of subdirs to return (1, 2 or 3 levels). (deprecated,// global option will be used in future)
5122
     * 	@param	int		$alpha		    0=Keep number only to forge path, 1=Use alpha part afer the - (By default, use 0). (deprecated,// global option will be used in future)
5123
     *  @param  int		$withoutslash   0=With slash at end (except if '/', we return ''), 1=without slash at end
5124
     *  @param	Object	$object			Object
5125
     *  @param	string	$modulepart		Type of object ('invoice_supplier, 'donation', 'invoice', ...')
5126
     *  @return	string					Dir to use ending. Example '' or '1/' or '1/2/'
5127
     */
5128
    static function get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart)
5129
    {
5130
       // global Globals::$conf;
5131
5132
        $path = '';
5133
5134
        $arrayforoldpath = array('cheque', 'user', 'category', 'holiday', 'supplier_invoice', 'invoice_supplier', 'mailing', 'supplier_payment');
5135
        if (!empty(Globals::$conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO))
5136
            $arrayforoldpath[] = 'product';
5137
        if (!empty($level) && in_array($modulepart, $arrayforoldpath)) {
5138
// This part should be removed once all code is using "get_exdir" to forge path, with all parameters provided.
5139
            if (empty($alpha))
5140
                $num = preg_replace('/([^0-9])/i', '', $num);
5141
            else
5142
                $num = preg_replace('/^.*\-/i', '', $num);
5143
            $num = substr("000" . $num, -$level);
5144
            if ($level == 1)
5145
                $path = substr($num, 0, 1);
5146
            if ($level == 2)
5147
                $path = substr($num, 1, 1) . '/' . substr($num, 0, 1);
5148
            if ($level == 3)
5149
                $path = substr($num, 2, 1) . '/' . substr($num, 1, 1) . '/' . substr($num, 0, 1);
5150
        }
5151
        else {
5152
// TODO
5153
// We will enhance here a common way of forging path for document storage
5154
// Here, object->id, object->ref and modulepart are required.
5155
//var_dump($modulepart);
5156
            if (in_array($modulepart, array('thirdparty', 'contact', 'member', 'propal', 'proposal', 'commande', 'order', 'facture', 'invoice',
5157
                    'supplier_order', 'supplier_proposal', 'shipment', 'contract', 'expensereport'))) {
5158
                $path = ($object->ref ? $object->ref : $object->id);
5159
            }
5160
        }
5161
5162
        if (empty($withoutslash) && !empty($path))
5163
            $path .= '/';
5164
5165
        return $path;
5166
    }
5167
5168
    /**
5169
     * 	Creation of a directory (this can create recursive subdir)
5170
     *
5171
     * 	@param	string	$dir		Directory to create (Separator must be '/'. Example: '/mydir/mysubdir')
5172
     * 	@param	string	$dataroot	Data root directory (To avoid having the data root in the loop. Using this will also lost the warning on first dir PHP has no permission when open_basedir is used)
5173
     *  @param	int		$newmask	Mask for new file (Defaults to Globals::$conf->global->MAIN_UMASK or 0755 if unavailable). Example: '0444'
5174
     * 	@return int         		< 0 if KO, 0 = already exists, > 0 if OK
5175
     */
5176
    static function dol_mkdir($dir, $dataroot = '', $newmask = null)
5177
    {
5178
       // global Globals::$conf;
5179
5180
        dol_syslog("functions.lib::dol_mkdir: dir=" . $dir, LOG_INFO);
5181
5182
        $dir_osencoded = dol_osencode($dir);
5183
        if (@is_dir($dir_osencoded))
5184
            return 0;
5185
5186
        $nberr = 0;
5187
        $nbcreated = 0;
5188
5189
        $ccdir = '';
5190
        if (!empty($dataroot)) {
5191
// Remove data root from loop
5192
            $dir = str_replace($dataroot . '/', '', $dir);
5193
            $ccdir = $dataroot . '/';
5194
        }
5195
5196
        $cdir = explode("/", $dir);
5197
        $num = count($cdir);
5198
        for ($i = 0; $i < $num; $i++) {
5199
            if ($i > 0)
5200
                $ccdir .= '/' . $cdir[$i];
5201
            else
5202
                $ccdir .= $cdir[$i];
5203
            if (preg_match("/^.:$/", $ccdir, $regs))
5204
                continue; // Si chemin Windows incomplet, on poursuit par rep suivant
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
                
5239
// Attention, le is_dir() peut echouer bien que le rep existe.
5240
// (ex selon config de open_basedir)
5241
            if ($ccdir) {
5242
                $ccdir_osencoded = dol_osencode($ccdir);
5243
                if (!@is_dir($ccdir_osencoded)) {
5244
                    dol_syslog("functions.lib::dol_mkdir: Directory '" . $ccdir . "' does not exists or is outside open_basedir PHP setting.", LOG_DEBUG);
5245
5246
                    umask(0);
5247
                    $dirmaskdec = octdec($newmask);
5248
                    if (empty($newmask)) {
5249
                        $dirmaskdec = empty(Globals::$conf->global->MAIN_UMASK) ? octdec('0755') : octdec(Globals::$conf->global->MAIN_UMASK);
5250
                    }
5251
                    $dirmaskdec |= octdec('0111');  // Set x bit required for directories
5252
                    if (!@mkdir($ccdir_osencoded, $dirmaskdec)) {
5253
                        // Si le is_dir a renvoye une fausse info, alors on passe ici.
5254
                        dol_syslog("functions.lib::dol_mkdir: Fails to create directory '" . $ccdir . "' or directory already exists.", LOG_WARNING);
5255
                        $nberr++;
5256
                    } else {
5257
                        dol_syslog("functions.lib::dol_mkdir: Directory '" . $ccdir . "' created", LOG_DEBUG);
5258
                        $nberr = 0; // On remet a zero car si on arrive ici, cela veut dire que les echecs precedents peuvent etre ignore
5259
                        $nbcreated++;
5260
                    }
5261
                } else {
5262
                    $nberr = 0; // On remet a zero car si on arrive ici, cela veut dire que les echecs precedents peuvent etre ignores
5263
                }
5264
            }
5265
        }
5266
        return ($nberr ? -$nberr : $nbcreated);
5267
    }
5268
5269
    /**
5270
     * 	Return picto saying a field is required
5271
     *
5272
     * 	@return  string		Chaine avec picto obligatoire
5273
     */
5274
    static function picto_required()
5275
    {
5276
        return '<span class="fieldrequired">*</span>';
5277
    }
5278
5279
    /**
5280
     * 	Clean a string from all HTML tags and entities.
5281
     *  This static function differs from strip_tags because:
5282
     *  - <br> are replaced with \n if removelinefeed=0 or 1
5283
     *  - if entities are found, they are decoded BEFORE the strip
5284
     *  - you can decide to convert line feed into a space
5285
     *
5286
     * 	@param	string	$stringtoclean		String to clean
5287
     * 	@param	integer	$removelinefeed		1=Replace all new lines by 1 space, 0=Only ending new lines are removed others are replaced with \n, 2=Ending new lines are removed but others are kept with a same number of \n than nb of <br> when there is both "...<br>\n..."
5288
     *  @param  string	$pagecodeto      	Encoding of input/output string
5289
     *  @param	integer	$strip_tags			0=Use internal strip, 1=Use strip_tags() php static function (bugged when text contains a < char that is not for a html tag)
5290
     * 	@return string	    				String cleaned
5291
     *
5292
     * 	@see	dol_escape_htmltag strip_tags dol_string_onlythesehtmltags dol_string_neverthesehtmltags
5293
     */
5294
    static function dol_string_nohtmltag($stringtoclean, $removelinefeed = 1, $pagecodeto = 'UTF-8', $strip_tags = 0)
5295
    {
5296
        if ($removelinefeed == 2)
5297
            $stringtoclean = preg_replace('/<br[^>]*>\n+/ims', '<br>', $stringtoclean);
5298
        $temp = preg_replace('/<br[^>]*>/i', "\n", $stringtoclean);
5299
5300
        if ($strip_tags) {
5301
            $temp = strip_tags($temp);
5302
        } else {
5303
            $pattern = "/<[^<>]+>/";
5304
// Exemple of $temp: <a href="/myurl" title="<u>A title</u>">0000-021</a>
5305
            $temp = preg_replace($pattern, "", $temp);    // pass 1
5306
// $temp after pass 1: <a href="/myurl" title="A title">0000-021
5307
            $temp = preg_replace($pattern, "", $temp);    // pass 2
5308
// $temp after pass 2: 0000-021
5309
        }
5310
5311
        $temp = dol_html_entity_decode($temp, ENT_COMPAT, $pagecodeto);
5312
5313
// Supprime aussi les retours
5314
        if ($removelinefeed == 1)
5315
            $temp = str_replace(array("\r\n", "\r", "\n"), " ", $temp);
5316
5317
// et les espaces doubles
5318
        while (strpos($temp, "  ")) {
5319
            $temp = str_replace("  ", " ", $temp);
5320
        }
5321
5322
        return trim($temp);
5323
    }
5324
5325
    /**
5326
     * 	Clean a string to keep only desirable HTML tags.
5327
     *
5328
     * 	@param	string	$stringtoclean		String to clean
5329
     * 	@return string	    				String cleaned
5330
     *
5331
     * 	@see	dol_escape_htmltag strip_tags dol_string_nohtmltag dol_string_neverthesehtmltags
5332
     */
5333
    static function dol_string_onlythesehtmltags($stringtoclean)
5334
    {
5335
        $allowed_tags = array(
5336
            "html", "head", "meta", "body", "article", "a", "b", "br", "div", "em", "font", "img", "ins", "hr", "i", "li", "link",
5337
            "ol", "p", "s", "section", "span", "strong", "title",
5338
            "table", "tr", "th", "td", "u", "ul"
5339
        );
5340
5341
        $allowed_tags_string = join("><", $allowed_tags);
5342
        $allowed_tags_string = preg_replace('/^>/', '', $allowed_tags_string);
5343
        $allowed_tags_string = preg_replace('/<$/', '', $allowed_tags_string);
5344
5345
        $temp = strip_tags($stringtoclean, $allowed_tags_string);
5346
5347
        return $temp;
5348
    }
5349
5350
    /**
5351
     * 	Clean a string from some undesirable HTML tags.
5352
     *
5353
     * 	@param	string	$stringtoclean		String to clean
5354
     *  @param	array	$disallowed_tags	Array of tags not allowed
5355
     * 	@return string	    				String cleaned
5356
     *
5357
     * 	@see	dol_escape_htmltag strip_tags dol_string_nohtmltag dol_string_onlythesehtmltags
5358
     */
5359
    static function dol_string_neverthesehtmltags($stringtoclean, $disallowed_tags = array('textarea'))
5360
    {
5361
        $temp = $stringtoclean;
5362
        foreach ($disallowed_tags as $tagtoremove) {
5363
            $temp = preg_replace('/<\/?' . $tagtoremove . '>/', '', $temp);
5364
            $temp = preg_replace('/<\/?' . $tagtoremove . '\s+[^>]*>/', '', $temp);
5365
        }
5366
        return $temp;
5367
    }
5368
5369
    /**
5370
     * Return first line of text. Cut will depends if content is HTML or not.
5371
     *
5372
     * @param 	string	$text		Input text
5373
     * @param	int		$nboflines  Nb of lines to get (default is 1 = first line only)
5374
     * @return	string				Output text
5375
     * @see dol_nboflines_bis, dol_string_nohtmltag, dol_escape_htmltag
5376
     */
5377
    static function dolGetFirstLineOfText($text, $nboflines = 1)
5378
    {
5379
        if ($nboflines == 1) {
5380
            if (dol_textishtml($text)) {
5381
                $firstline = preg_replace('/<br[^>]*>.*$/s', '', $text);  // The s pattern modifier means the . can match newline characters
5382
                $firstline = preg_replace('/<div[^>]*>.*$/s', '', $firstline); // The s pattern modifier means the . can match newline characters
5383
            } else {
5384
                $firstline = preg_replace('/[\n\r].*/', '', $text);
5385
            }
5386
            return $firstline . ((strlen($firstline) != strlen($text)) ? '...' : '');
5387
        } else {
5388
            $ishtml = 0;
5389
            if (dol_textishtml($text)) {
5390
                $text = preg_replace('/\n/', '', $text);
5391
                $ishtml = 1;
5392
                $repTable = array("\t" => " ", "\n" => " ", "\r" => " ", "\0" => " ", "\x0B" => " ");
5393
            } else {
5394
                $repTable = array("\t" => " ", "\n" => "<br>", "\r" => " ", "\0" => " ", "\x0B" => " ");
5395
            }
5396
5397
            $text = strtr($text, $repTable);
5398
            if ($charset == 'UTF-8') {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $charset seems to be never defined.
Loading history...
5399
                $pattern = '/(<br[^>]*>)/Uu';
5400
            } // /U is to have UNGREEDY regex to limit to one html tag. /u is for UTF8 support
5401
            else
5402
                $pattern = '/(<br[^>]*>)/U';       // /U is to have UNGREEDY regex to limit to one html tag.
5403
            $a = preg_split($pattern, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
5404
5405
            $firstline = '';
5406
            $i = 0;
5407
            $nba = count($a); // 2x nb of lines in $a because $a contains also a line for each new line separator
5408
            while (($i < $nba) && ($i < ($nboflines * 2))) {
5409
                if ($i % 2 == 0)
5410
                    $firstline .= $a[$i];
5411
                elseif (($i < (($nboflines * 2) - 1)) && ($i < ($nba - 1)))
5412
                    $firstline .= ($ishtml ? "<br>\n" : "\n");
5413
                $i++;
5414
            }
5415
            unset($a);
5416
            return $firstline . (($i < $nba) ? '...' : '');
5417
        }
5418
    }
5419
5420
    /**
5421
     * Replace CRLF in string with a HTML BR tag
5422
     *
5423
     * @param	string	$stringtoencode		String to encode
5424
     * @param	int     $nl2brmode			0=Adding br before \n, 1=Replacing \n by br
5425
     * @param   bool	$forxml             false=Use <br>, true=Use <br />
5426
     * @return	string						String encoded
5427
     * @see dol_nboflines, dolGetFirstLineOfText
5428
     */
5429
    static function dol_nl2br($stringtoencode, $nl2brmode = 0, $forxml = false)
5430
    {
5431
        if (!$nl2brmode) {
5432
            return nl2br($stringtoencode, $forxml);
5433
        } else {
5434
            $ret = preg_replace('/(\r\n|\r|\n)/i', ($forxml ? '<br />' : '<br>'), $stringtoencode);
5435
            return $ret;
5436
        }
5437
    }
5438
5439
    /**
5440
     * 	This static function is called to encode a string into a HTML string but differs from htmlentities because
5441
     * 	a detection is done before to see if text is already HTML or not. Also, all entities but &,<,> are converted.
5442
     *  This permits to encode special chars to entities with no double encoding for already encoded HTML strings.
5443
     * 	This static function also remove last EOL or BR if $removelasteolbr=1 (default).
5444
     *  For PDF usage, you can show text by 2 ways:
5445
     *              - writeHTMLCell -> param must be encoded into HTML.
5446
     *              - MultiCell -> param must not be encoded into HTML.
5447
     *              Because writeHTMLCell convert also \n into <br>, if function
5448
     *              is used to build PDF, nl2brmode must be 1.
5449
     *
5450
     * 	@param	string	$stringtoencode		String to encode
5451
     * 	@param	int		$nl2brmode			0=Adding br before \n, 1=Replacing \n by br (for use with FPDF writeHTMLCell static function for example)
5452
     *  @param  string	$pagecodefrom       Pagecode stringtoencode is encoded
5453
     *  @param	int		$removelasteolbr	1=Remove last br or lasts \n (default), 0=Do nothing
5454
     *  @return	string						String encoded
5455
     */
5456
    static function dol_htmlentitiesbr($stringtoencode, $nl2brmode = 0, $pagecodefrom = 'UTF-8', $removelasteolbr = 1)
5457
    {
5458
        $newstring = $stringtoencode;
5459
        if (dol_textishtml($stringtoencode)) { // Check if text is already HTML or not
5460
            $newstring = preg_replace('/<br(\s[\sa-zA-Z_="]*)?\/?>/i', '<br>', $newstring); // Replace "<br type="_moz" />" by "<br>". It's same and avoid pb with FPDF.
5461
            if ($removelasteolbr)
5462
                $newstring = preg_replace('/<br>$/i', '', $newstring); // Remove last <br> (remove only last one)
5463
            $newstring = strtr($newstring, array('&' => '__and__', '<' => '__lt__', '>' => '__gt__', '"' => '__dquot__'));
5464
            $newstring = dol_htmlentities($newstring, ENT_COMPAT, $pagecodefrom); // Make entity encoding
5465
            $newstring = strtr($newstring, array('__and__' => '&', '__lt__' => '<', '__gt__' => '>', '__dquot__' => '"'));
5466
        }
5467
        else {
5468
            if ($removelasteolbr)
5469
                $newstring = preg_replace('/(\r\n|\r|\n)$/i', '', $newstring); // Remove last \n (may remove several)
5470
            $newstring = dol_nl2br(dol_htmlentities($newstring, ENT_COMPAT, $pagecodefrom), $nl2brmode);
5471
        }
5472
// Other substitutions that htmlentities does not do
5473
//$newstring=str_replace(chr(128),'&euro;',$newstring);	// 128 = 0x80. Not in html entity table.     // Seems useles with TCPDF. Make bug with UTF8 languages
5474
        return $newstring;
5475
    }
5476
5477
    /**
5478
     * 	This static function is called to decode a HTML string (it decodes entities and br tags)
5479
     *
5480
     * 	@param	string	$stringtodecode		String to decode
5481
     * 	@param	string	$pagecodeto			Page code for result
5482
     * 	@return	string						String decoded
5483
     */
5484
    static function dol_htmlentitiesbr_decode($stringtodecode, $pagecodeto = 'UTF-8')
5485
    {
5486
        $ret = dol_html_entity_decode($stringtodecode, ENT_COMPAT, $pagecodeto);
5487
        $ret = preg_replace('/' . "\r\n" . '<br(\s[\sa-zA-Z_="]*)?\/?>/i', "<br>", $ret);
5488
        $ret = preg_replace('/<br(\s[\sa-zA-Z_="]*)?\/?>' . "\r\n" . '/i', "\r\n", $ret);
5489
        $ret = preg_replace('/<br(\s[\sa-zA-Z_="]*)?\/?>' . "\n" . '/i', "\n", $ret);
5490
        $ret = preg_replace('/<br(\s[\sa-zA-Z_="]*)?\/?>/i', "\n", $ret);
5491
        return $ret;
5492
    }
5493
5494
    /**
5495
     * 	This static function remove all ending \n and br at end
5496
     *
5497
     * 	@param	string	$stringtodecode		String to decode
5498
     * 	@return	string						String decoded
5499
     */
5500
    static function dol_htmlcleanlastbr($stringtodecode)
5501
    {
5502
        $ret = preg_replace('/(<br>|<br(\s[\sa-zA-Z_="]*)?\/?>|' . "\n" . '|' . "\r" . ')+$/i', "", $stringtodecode);
5503
        return $ret;
5504
    }
5505
5506
    /**
5507
     * Replace html_entity_decode functions to manage errors
5508
     *
5509
     * @param   string	$a		Operand a
5510
     * @param   string	$b		Operand b (ENT_QUOTES=convert simple and double quotes)
5511
     * @param   string	$c		Operand c
5512
     * @return  string			String decoded
5513
     */
5514
    static function dol_html_entity_decode($a, $b, $c = 'UTF-8')
5515
    {
5516
        return html_entity_decode($a, $b, $c);
5517
    }
5518
5519
    /**
5520
     * Replace htmlentities functions.
5521
     * Goal of this static function is to be sure to have default values of htmlentities that match what we need.
5522
     *
5523
     * @param   string  $string         The input string to encode
5524
     * @param   int     $flags          Flags (see PHP doc above)
5525
     * @param   string  $encoding       Encoding page code
5526
     * @param   bool    $double_encode  When double_encode is turned off, PHP will not encode existing html entities
5527
     * @return  string  $ret            Encoded string
5528
     */
5529
    static function dol_htmlentities($string, $flags = null, $encoding = 'UTF-8', $double_encode = false)
5530
    {
5531
        return htmlentities($string, $flags, $encoding, $double_encode);
5532
    }
5533
5534
    /**
5535
     * 	Check if a string is a correct iso string
5536
     * 	If not, it will we considered not HTML encoded even if it is by FPDF.
5537
     * 	Example, if string contains euro symbol that has ascii code 128
5538
     *
5539
     * 	@param	string	$s      String to check
5540
     * 	@return	int     		0 if bad iso, 1 if good iso
5541
     */
5542
    static function dol_string_is_good_iso($s)
5543
    {
5544
        $len = dol_strlen($s);
5545
        $ok = 1;
5546
        for ($scursor = 0; $scursor < $len; $scursor++) {
5547
            $ordchar = ord($s{$scursor});
5548
//print $scursor.'-'.$ordchar.'<br>';
5549
            if ($ordchar < 32 && $ordchar != 13 && $ordchar != 10) {
5550
                $ok = 0;
5551
                break;
5552
            }
5553
            if ($ordchar > 126 && $ordchar < 160) {
5554
                $ok = 0;
5555
                break;
5556
            }
5557
        }
5558
        return $ok;
5559
    }
5560
5561
    /**
5562
     * 	Return nb of lines of a clear text
5563
     *
5564
     * 	@param	string	$s			String to check
5565
     * 	@param	int     $maxchar	Not yet used
5566
     * 	@return	int					Number of lines
5567
     *  @see	dol_nboflines_bis, dolGetFirstLineOfText
5568
     */
5569
    static function dol_nboflines($s, $maxchar = 0)
5570
    {
5571
        if ($s == '')
5572
            return 0;
5573
        $arraystring = explode("\n", $s);
5574
        $nb = count($arraystring);
5575
5576
        return $nb;
5577
    }
5578
5579
    /**
5580
     * 	Return nb of lines of a formated text with \n and <br> (WARNING: string must not have mixed \n and br separators)
5581
     *
5582
     * 	@param	string	$text      		Text
5583
     * 	@param	int		$maxlinesize  	Largeur de ligne en caracteres (ou 0 si pas de limite - defaut)
5584
     * 	@param	string	$charset		Give the charset used to encode the $text variable in memory.
5585
     * 	@return int						Number of lines
5586
     * 	@see	dol_nboflines, dolGetFirstLineOfText
5587
     */
5588
    static function dol_nboflines_bis($text, $maxlinesize = 0, $charset = 'UTF-8')
5589
    {
5590
        $repTable = array("\t" => " ", "\n" => "<br>", "\r" => " ", "\0" => " ", "\x0B" => " ");
5591
        if (dol_textishtml($text))
5592
            $repTable = array("\t" => " ", "\n" => " ", "\r" => " ", "\0" => " ", "\x0B" => " ");
5593
5594
        $text = strtr($text, $repTable);
5595
        if ($charset == 'UTF-8') {
5596
            $pattern = '/(<br[^>]*>)/Uu';
5597
        } // /U is to have UNGREEDY regex to limit to one html tag. /u is for UTF8 support
5598
        else
5599
            $pattern = '/(<br[^>]*>)/U';       // /U is to have UNGREEDY regex to limit to one html tag.
5600
        $a = preg_split($pattern, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
5601
5602
        $nblines = (int) floor((count($a) + 1) / 2);
5603
// count possible auto line breaks
5604
        if ($maxlinesize) {
5605
            foreach ($a as $line) {
5606
                if (dol_strlen($line) > $maxlinesize) {
5607
                    //$line_dec = html_entity_decode(strip_tags($line));
5608
                    $line_dec = html_entity_decode($line);
5609
                    if (dol_strlen($line_dec) > $maxlinesize) {
5610
                        $line_dec = wordwrap($line_dec, $maxlinesize, '\n', true);
5611
                        $nblines += substr_count($line_dec, '\n');
5612
                    }
5613
                }
5614
            }
5615
        }
5616
5617
        unset($a);
5618
        return $nblines;
5619
    }
5620
5621
    /**
5622
     * 	 Same static function than microtime in PHP 5 but compatible with PHP4
5623
     *
5624
     * @return		float		Time (millisecondes) with microsecondes in decimal part
5625
     * @deprecated Dolibarr does not support PHP4, you should use native function
5626
     * @see microtime()
5627
     */
5628
    static function dol_microtime_float()
5629
    {
5630
        dol_syslog(__FUNCTION__ . " is deprecated", LOG_WARNING);
5631
5632
        return microtime(true);
5633
    }
5634
5635
    /**
5636
     * 	Return if a text is a html content
5637
     *
5638
     * 	@param	string	$msg		Content to check
5639
     * 	@param	int		$option		0=Full detection, 1=Fast check
5640
     * 	@return	boolean				true/false
5641
     * 	@see	dol_concatdesc
5642
     */
5643
    static function dol_textishtml($msg, $option = 0)
5644
    {
5645
        if ($option == 1) {
5646
            if (preg_match('/<html/i', $msg))
5647
                return true;
5648
            elseif (preg_match('/<body/i', $msg))
5649
                return true;
5650
            elseif (preg_match('/<br/i', $msg))
5651
                return true;
5652
            return false;
5653
        }
5654
        else {
5655
            if (preg_match('/<html/i', $msg))
5656
                return true;
5657
            elseif (preg_match('/<body/i', $msg))
5658
                return true;
5659
            elseif (preg_match('/<(b|em|i|u)>/i', $msg))
5660
                return true;
5661
            elseif (preg_match('/<br\/>/i', $msg))
5662
                return true;
5663
            elseif (preg_match('/<(br|div|font|li|p|span|strong|table)>/i', $msg))
5664
                return true;
5665
            elseif (preg_match('/<(br|div|font|li|p|span|strong|table)\s+[^<>\/]*>/i', $msg))
5666
                return true;
5667
            elseif (preg_match('/<(br|div|font|li|p|span|strong|table)\s+[^<>\/]*\/>/i', $msg))
5668
                return true;
5669
            elseif (preg_match('/<img\s+[^<>]*src[^<>]*>/i', $msg))
5670
                return true; // must accept <img src="http://example.com/aaa.png" />
5671
            elseif (preg_match('/<a\s+[^<>]*href[^<>]*>/i', $msg))
5672
                return true; // must accept <a href="http://example.com/aaa.png" />
5673
            elseif (preg_match('/<h[0-9]>/i', $msg))
5674
                return true;
5675
            elseif (preg_match('/&[A-Z0-9]{1,6};/i', $msg))
5676
                return true;    // Html entities names (http://www.w3schools.com/tags/ref_entities.asp)
5677
            elseif (preg_match('/&#[0-9]{2,3};/i', $msg))
5678
                return true;    // Html entities numbers (http://www.w3schools.com/tags/ref_entities.asp)
5679
5680
            return false;
5681
        }
5682
    }
5683
5684
    /**
5685
     *  Concat 2 descriptions with a new line between them (second operand after first one with appropriate new line separator)
5686
     *  text1 html + text2 html => text1 + '<br>' + text2
5687
     *  text1 html + text2 txt  => text1 + '<br>' + dol_nl2br(text2)
5688
     *  text1 txt  + text2 html => dol_nl2br(text1) + '<br>' + text2
5689
     *  text1 txt  + text2 txt  => text1 + '\n' + text2
5690
     *
5691
     *  @param  string  $text1          Text 1
5692
     *  @param  string  $text2          Text 2
5693
     *  @param  bool    $forxml         false=Use <br>instead of \n if html content detected, true=Use <br /> instead of \n if html content detected
5694
     *  @param  bool    $invert         invert order of description lines if CONF CHANGE_ORDER_CONCAT_DESCRIPTION is active
5695
     *  @return string                  Text 1 + new line + Text2
5696
     *  @see    dol_textishtml
5697
     */
5698
    static function dol_concatdesc($text1, $text2, $forxml = false, $invert = false)
5699
    {
5700
        if (!empty($invert)) {
5701
            $tmp = $text1;
5702
            $text1 = $text2;
5703
            $text2 = $tmp;
5704
        }
5705
5706
        $ret = '';
5707
        $ret .= (!dol_textishtml($text1) && dol_textishtml($text2)) ? dol_nl2br($text1, 0, $forxml) : $text1;
5708
        $ret .= (!empty($text1) && !empty($text2)) ? ((dol_textishtml($text1) || dol_textishtml($text2)) ? ($forxml ? "<br \>\n" : "<br>\n") : "\n") : "";
5709
        $ret .= (dol_textishtml($text1) && !dol_textishtml($text2)) ? dol_nl2br($text2, 0, $forxml) : $text2;
5710
        return $ret;
5711
    }
5712
5713
    /**
5714
     * Return array of possible common substitutions. This includes several families like: 'system', 'mycompany', 'object', 'objectamount', 'date', 'user'
5715
     *
5716
     * @param	Translate	$outputlangs	Output language
5717
     * @param   int         $onlykey        1=Do not calculate some heavy values of keys (performance enhancement when we need only the keys), 2=Values are trunc and html sanitized (to use for help tooltip)
5718
     * @param   array       $exclude        Array of family keys we want to exclude. For example array('system', 'mycompany', 'object', 'objectamount', 'date', 'user', ...)
5719
     * @param   Object      $object         Object for keys on object
5720
     * @return	array						Array of substitutions
5721
     * @see setSubstitFromObject
5722
     */
5723
    static function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, $object = null)
5724
    {
5725
       // global $db, Globals::$conf, $mysoc, $user, $extrafields;
5726
5727
        $substitutionarray = array();
5728
5729
        if (empty($exclude) || !in_array('user', $exclude)) {
5730
// Add SIGNATURE into substitutionarray first, so, when we will make the substitution,
5731
// this will include signature content first and then replace var found into content of signature
5732
            $signature = $user->signature;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $user seems to be never defined.
Loading history...
5733
            $substitutionarray = array_merge($substitutionarray, array(
5734
                '__USER_SIGNATURE__' => (string) (($signature && empty(Globals::$conf->global->MAIN_MAIL_DO_NOT_USE_SIGN)) ? ($onlykey == 2 ? dol_trunc(dol_string_nohtmltag($signature), 30) : $signature) : '')
5735
                )
5736
            );
5737
// For backward compatibility
5738
            if ($onlykey != 2) {
5739
                $substitutionarray['__SIGNATURE__'] = (string) (($signature && empty(Globals::$conf->global->MAIN_MAIL_DO_NOT_USE_SIGN)) ? ($onlykey == 2 ? dol_trunc(dol_string_nohtmltag($signature), 30) : $signature) : '');
5740
            }
5741
5742
            $substitutionarray = array_merge($substitutionarray, array(
5743
                '__USER_ID__' => (string) $user->id,
5744
                '__USER_LOGIN__' => (string) $user->login,
5745
                '__USER_LASTNAME__' => (string) $user->lastname,
5746
                '__USER_FIRSTNAME__' => (string) $user->firstname,
5747
                '__USER_FULLNAME__' => (string) $user->getFullName($outputlangs),
5748
                '__USER_SUPERVISOR_ID__' => (string) ($user->fk_user ? $user->fk_user : '0'),
5749
                '__USER_REMOTE_IP__' => (string) getUserRemoteIP()
5750
                )
5751
            );
5752
        }
5753
        if ((empty($exclude) || !in_array('mycompany', $exclude)) && is_object($mysoc)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mysoc seems to be never defined.
Loading history...
5754
            $substitutionarray = array_merge($substitutionarray, array(
5755
                '__MYCOMPANY_NAME__' => $mysoc->name,
5756
                '__MYCOMPANY_EMAIL__' => $mysoc->email,
5757
                '__MYCOMPANY_PROFID1__' => $mysoc->idprof1,
5758
                '__MYCOMPANY_PROFID2__' => $mysoc->idprof2,
5759
                '__MYCOMPANY_PROFID3__' => $mysoc->idprof3,
5760
                '__MYCOMPANY_PROFID4__' => $mysoc->idprof4,
5761
                '__MYCOMPANY_PROFID5__' => $mysoc->idprof5,
5762
                '__MYCOMPANY_PROFID6__' => $mysoc->idprof6,
5763
                '__MYCOMPANY_CAPITAL__' => $mysoc->capital,
5764
                '__MYCOMPANY_FULLADDRESS__' => $mysoc->getFullAddress(1, ', '),
5765
                '__MYCOMPANY_ADDRESS__' => $mysoc->address,
5766
                '__MYCOMPANY_ZIP__' => $mysoc->zip,
5767
                '__MYCOMPANY_TOWN__' => $mysoc->town,
5768
                '__MYCOMPANY_COUNTRY__' => $mysoc->country,
5769
                '__MYCOMPANY_COUNTRY_ID__' => $mysoc->country_id,
5770
                '__MYCOMPANY_CURRENCY_CODE__' => Globals::$conf->currency
5771
            ));
5772
        }
5773
5774
        if (($onlykey || is_object($object)) && (empty($exclude) || !in_array('object', $exclude))) {
5775
            if ($onlykey) {
5776
                $substitutionarray['__ID__'] = '__ID__';
5777
                $substitutionarray['__REF__'] = '__REF__';
5778
                $substitutionarray['__REFCLIENT__'] = '__REFCLIENT__';
5779
                $substitutionarray['__REFSUPPLIER__'] = '__REFSUPPLIER__';
5780
                $substitutionarray['__EXTRAFIELD_XXX__'] = '__EXTRAFIELD_XXX__';
5781
5782
                $substitutionarray['__THIRDPARTY_ID__'] = '__THIRDPARTY_ID__';
5783
                $substitutionarray['__THIRDPARTY_NAME__'] = '__THIRDPARTY_NAME__';
5784
                $substitutionarray['__THIRDPARTY_NAME_ALIAS__'] = '__THIRDPARTY_NAME_ALIAS__';
5785
                $substitutionarray['__THIRDPARTY_EMAIL__'] = '__THIRDPARTY_EMAIL__';
5786
5787
                if (is_object($object) && $object->element == 'member') {
5788
                    $substitutionarray['__MEMBER_ID__'] = '__MEMBER_ID__';
5789
                    $substitutionarray['__MEMBER_CIVILITY__'] = '__MEMBER_CIVILITY__';
5790
                    $substitutionarray['__MEMBER_FIRSTNAME__'] = '__MEMBER_FIRSTNAME__';
5791
                    $substitutionarray['__MEMBER_LASTNAME__'] = '__MEMBER_LASTNAME__';
5792
                }
5793
                $substitutionarray['__PROJECT_ID__'] = '__PROJECT_ID__';
5794
                $substitutionarray['__PROJECT_REF__'] = '__PROJECT_REF__';
5795
                $substitutionarray['__PROJECT_NAME__'] = '__PROJECT_NAME__';
5796
5797
                $substitutionarray['__CONTRACT_HIGHEST_PLANNED_START_DATE__'] = 'Highest date planned for a service start';
5798
                $substitutionarray['__CONTRACT_HIGHEST_PLANNED_START_DATETIME__'] = 'Highest date and hour planned for service start';
5799
                $substitutionarray['__CONTRACT_LOWEST_EXPIRATION_DATE__'] = 'Lowest data for planned expiration of service';
5800
                $substitutionarray['__CONTRACT_LOWEST_EXPIRATION_DATETIME__'] = 'Lowest date and hour for planned expiration of service';
5801
5802
                $substitutionarray['__ONLINE_PAYMENT_URL__'] = 'UrlToPayOnlineIfApplicable';
5803
                $substitutionarray['__ONLINE_PAYMENT_TEXT_AND_URL__'] = 'TextAndUrlToPayOnlineIfApplicable';
5804
                $substitutionarray['__SECUREKEYPAYMENT__'] = 'Security key (if key is not unique per record)';
5805
                $substitutionarray['__SECUREKEYPAYMENT_MEMBER__'] = 'Security key for payment on a member subscription (one key per member)';
5806
                $substitutionarray['__SECUREKEYPAYMENT_ORDER__'] = 'Security key for payment on an order';
5807
                $substitutionarray['__SECUREKEYPAYMENT_INVOICE__'] = 'Security key for payment on an invoice';
5808
                $substitutionarray['__SECUREKEYPAYMENT_CONTRACTLINE__'] = 'Security key for payment on a a service';
5809
5810
                $substitutionarray['__DIRECTDOWNLOAD_URL_PROPOSAL__'] = 'Direct download url of a proposal';
5811
                $substitutionarray['__DIRECTDOWNLOAD_URL_ORDER__'] = 'Direct download url of an order';
5812
                $substitutionarray['__DIRECTDOWNLOAD_URL_INVOICE__'] = 'Direct download url of an invoice';
5813
5814
                if (is_object($object) && $object->element == 'shipping') {
5815
                    $substitutionarray['__SHIPPINGTRACKNUM__'] = 'Shipping tacking number';
5816
                    $substitutionarray['__SHIPPINGTRACKNUMURL__'] = 'Shipping tracking url';
5817
                }
5818
            } else {
5819
                $substitutionarray['__ID__'] = $object->id;
5820
                $substitutionarray['__REF__'] = $object->ref;
5821
                $substitutionarray['__REFCLIENT__'] = (isset($object->ref_client) ? $object->ref_client : (isset($object->ref_customer) ? $object->ref_customer : ''));
5822
                $substitutionarray['__REFSUPPLIER__'] = (isset($object->ref_supplier) ? $object->ref_supplier : '');
5823
5824
// TODO Remove this
5825
                $msgishtml = 0;
5826
5827
                $birthday = dol_print_date($object->birth, 'day');
5828
5829
                $substitutionarray['__MEMBER_ID__'] = $object->id;
5830
                if (method_exists($object, 'getCivilityLabel'))
5831
                    $substitutionarray['__MEMBER_CIVILITY__'] = $object->getCivilityLabel();
5832
                $substitutionarray['__MEMBER_FIRSTNAME__'] = $msgishtml ? dol_htmlentitiesbr($object->firstname) : $object->firstname;
5833
                $substitutionarray['__MEMBER_LASTNAME__'] = $msgishtml ? dol_htmlentitiesbr($object->lastname) : $object->lastname;
5834
                if (method_exists($object, 'getFullName'))
5835
                    $substitutionarray['__MEMBER_FULLNAME__'] = $msgishtml ? dol_htmlentitiesbr($object->getFullName($outputlangs)) : $object->getFullName($outputlangs);
5836
                $substitutionarray['__MEMBER_COMPANY__'] = $msgishtml ? dol_htmlentitiesbr($object->societe) : $object->societe;
5837
                $substitutionarray['__MEMBER_ADDRESS__'] = $msgishtml ? dol_htmlentitiesbr($object->address) : $object->address;
5838
                $substitutionarray['__MEMBER_ZIP__'] = $msgishtml ? dol_htmlentitiesbr($object->zip) : $object->zip;
5839
                $substitutionarray['__MEMBER_TOWN__'] = $msgishtml ? dol_htmlentitiesbr($object->town) : $object->town;
5840
                $substitutionarray['__MEMBER_COUNTRY__'] = $msgishtml ? dol_htmlentitiesbr($object->country) : $object->country;
5841
                $substitutionarray['__MEMBER_EMAIL__'] = $msgishtml ? dol_htmlentitiesbr($object->email) : $object->email;
5842
                $substitutionarray['__MEMBER_BIRTH__'] = $msgishtml ? dol_htmlentitiesbr($birthday) : $birthday;
5843
                $substitutionarray['__MEMBER_PHOTO__'] = $msgishtml ? dol_htmlentitiesbr($object->photo) : $object->photo;
5844
                $substitutionarray['__MEMBER_LOGIN__'] = $msgishtml ? dol_htmlentitiesbr($object->login) : $object->login;
5845
                $substitutionarray['__MEMBER_PASSWORD__'] = $msgishtml ? dol_htmlentitiesbr($object->pass) : $object->pass;
5846
                $substitutionarray['__MEMBER_PHONE__'] = $msgishtml ? dol_htmlentitiesbr($object->phone) : $object->phone;
5847
                $substitutionarray['__MEMBER_PHONEPRO__'] = $msgishtml ? dol_htmlentitiesbr($object->phone_perso) : $object->phone_perso;
5848
                $substitutionarray['__MEMBER_PHONEMOBILE__'] = $msgishtml ? dol_htmlentitiesbr($object->phone_mobile) : $object->phone_mobile;
5849
                $substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE__'] = dol_print_date($object->first_subscription_date, 'dayrfc');
5850
                $substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE_START__'] = dol_print_date($object->first_subscription_date_start, 'dayrfc');
5851
                $substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE_END__'] = dol_print_date($object->first_subscription_date_end, 'dayrfc');
5852
                $substitutionarray['__MEMBER_LAST_SUBSCRIPTION_DATE__'] = dol_print_date($object->last_subscription_date, 'dayrfc');
5853
                $substitutionarray['__MEMBER_LAST_SUBSCRIPTION_DATE_START__'] = dol_print_date($object->last_subscription_date_start, 'dayrfc');
5854
                $substitutionarray['__MEMBER_LAST_SUBSCRIPTION_DATE_END__'] = dol_print_date($object->last_subscription_date_end, 'dayrfc');
5855
5856
                if (is_object($object) && $object->element == 'societe') {
5857
                    $substitutionarray['__THIRDPARTY_ID__'] = (is_object($object) ? $object->id : '');
5858
                    $substitutionarray['__THIRDPARTY_NAME__'] = (is_object($object) ? $object->name : '');
5859
                    $substitutionarray['__THIRDPARTY_NAME_ALIAS__'] = (is_object($object) ? $object->name_alias : '');
5860
                    $substitutionarray['__THIRDPARTY_EMAIL__'] = (is_object($object) ? $object->email : '');
5861
                } elseif (is_object($object->thirdparty) && $object->thirdparty->id > 0) {
5862
                    $substitutionarray['__THIRDPARTY_ID__'] = (is_object($object->thirdparty) ? $object->thirdparty->id : '');
5863
                    $substitutionarray['__THIRDPARTY_NAME__'] = (is_object($object->thirdparty) ? $object->thirdparty->name : '');
5864
                    $substitutionarray['__THIRDPARTY_NAME_ALIAS__'] = (is_object($object->thirdparty) ? $object->thirdparty->name_alias : '');
5865
                    $substitutionarray['__THIRDPARTY_EMAIL__'] = (is_object($object->thirdparty) ? $object->thirdparty->email : '');
5866
                }
5867
5868
                if (is_object($object->projet) && $object->projet->id > 0) {
5869
                    $substitutionarray['__PROJECT_ID__'] = (is_object($object->projet) ? $object->projet->id : '');
5870
                    $substitutionarray['__PROJECT_REF__'] = (is_object($object->projet) ? $object->projet->ref : '');
5871
                    $substitutionarray['__PROJECT_NAME__'] = (is_object($object->projet) ? $object->projet->title : '');
5872
                }
5873
5874
                if (is_object($object) && $object->element == 'shipping') {
5875
                    $substitutionarray['__SHIPPINGTRACKNUM__'] = $object->tracking_number;
5876
                    $substitutionarray['__SHIPPINGTRACKNUMURL__'] = $object->tracking_url;
5877
                }
5878
5879
                if (is_object($object) && $object->element == 'contrat' && is_array($object->lines)) {
5880
                    $dateplannedstart = '';
5881
                    $datenextexpiration = '';
5882
                    foreach ($object->lines as $line) {
5883
                        if ($line->date_ouverture_prevue > $dateplannedstart)
5884
                            $dateplannedstart = $line->date_ouverture_prevue;
5885
                        if ($line->statut == 4 && $line->date_fin_prevue && (!$datenextexpiration || $line->date_fin_prevue < $datenextexpiration))
5886
                            $datenextexpiration = $line->date_fin_prevue;
5887
                    }
5888
                    $substitutionarray['__CONTRACT_HIGHEST_PLANNED_START_DATE__'] = dol_print_date($dateplannedstart, 'dayrfc');
5889
                    $substitutionarray['__CONTRACT_HIGHEST_PLANNED_START_DATETIME__'] = dol_print_date($dateplannedstart, 'standard');
5890
                    $substitutionarray['__CONTRACT_LOWEST_EXPIRATION_DATE__'] = dol_print_date($datenextexpiration, 'dayrfc');
5891
                    $substitutionarray['__CONTRACT_LOWEST_EXPIRATION_DATETIME__'] = dol_print_date($datenextexpiration, 'standard');
5892
                }
5893
5894
// Create dynamic tags for __EXTRAFIELD_FIELD__
5895
                if ($object->table_element && $object->id > 0) {
5896
                    if (!is_object($extrafields))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $extrafields seems to be never defined.
Loading history...
5897
                        $extrafields = new ExtraFields($db);
0 ignored issues
show
Bug introduced by
The type Alixar\Helpers\ExtraFields was not found. Did you mean ExtraFields? If so, make sure to prefix the type with \.
Loading history...
Comprehensibility Best Practice introduced by
The variable $db seems to be never defined.
Loading history...
5898
                    $extrafields->fetch_name_optionals_label($object->table_element, true);
5899
5900
                    if ($object->fetch_optionals() > 0) {
0 ignored issues
show
Bug introduced by
The method fetch_optionals() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

5900
                    if ($object->/** @scrutinizer ignore-call */ fetch_optionals() > 0) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
5901
                        if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label']) > 0) {
5902
                            foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $label) {
5903
                                $substitutionarray['__EXTRAFIELD_' . strtoupper($key) . '__'] = $object->array_options['options_' . $key];
5904
                            }
5905
                        }
5906
                    }
5907
                }
5908
5909
// Complete substitution array with the url to make online payment
5910
                $paymenturl = '';
5911
                if (empty($substitutionarray['__REF__'])) {
5912
                    $paymenturl = '';
5913
                } else {
5914
                    // Set the online payment url link into __ONLINE_PAYMENT_URL__ key
5915
                    require_once DOL_BASE_PATH . '/core/lib/payments.lib.php';
5916
                    $outputlangs->loadLangs(array('paypal', 'other'));
5917
                    $typeforonlinepayment = 'free';
5918
                    if (is_object($object) && $object->element == 'commande')
5919
                        $typeforonlinepayment = 'order';
5920
                    if (is_object($object) && $object->element == 'facture')
5921
                        $typeforonlinepayment = 'invoice';
5922
                    if (is_object($object) && $object->element == 'member')
5923
                        $typeforonlinepayment = 'member';
5924
                    $url = getOnlinePaymentUrl(0, $typeforonlinepayment, $substitutionarray['__REF__']);
5925
                    $paymenturl = $url;
5926
                }
5927
5928
                $substitutionarray['__ONLINE_PAYMENT_TEXT_AND_URL__'] = ($paymenturl ? str_replace('\n', "\n", $outputlangs->trans("PredefinedMailContentLink", $paymenturl)) : '');
5929
                $substitutionarray['__ONLINE_PAYMENT_URL__'] = $paymenturl;
5930
5931
                if (!empty(Globals::$conf->global->PROPOSAL_ALLOW_EXTERNAL_DOWNLOAD) && is_object($object) && $object->element == 'propal') {
5932
                    $substitutionarray['__DIRECTDOWNLOAD_URL_PROPOSAL__'] = $object->getLastMainDocLink($object->element);
5933
                } else
5934
                    $substitutionarray['__DIRECTDOWNLOAD_URL_PROPOSAL__'] = '';
5935
                if (!empty(Globals::$conf->global->ORDER_ALLOW_EXTERNAL_DOWNLOAD) && is_object($object) && $object->element == 'commande') {
5936
                    $substitutionarray['__DIRECTDOWNLOAD_URL_ORDER__'] = $object->getLastMainDocLink($object->element);
5937
                } else
5938
                    $substitutionarray['__DIRECTDOWNLOAD_URL_ORDER__'] = '';
5939
                if (!empty(Globals::$conf->global->INVOICE_ALLOW_EXTERNAL_DOWNLOAD) && is_object($object) && $object->element == 'facture') {
5940
                    $substitutionarray['__DIRECTDOWNLOAD_URL_INVOICE__'] = $object->getLastMainDocLink($object->element);
5941
                } else
5942
                    $substitutionarray['__DIRECTDOWNLOAD_URL_INVOICE__'] = '';
5943
            }
5944
        }
5945
        if (empty($exclude) || !in_array('objectamount', $exclude)) {
5946
            $substitutionarray['__DATE_YMD__'] = is_object($object) ? (isset($object->date) ? dol_print_date($object->date, 'day', 0, $outputlangs) : '') : '';
5947
            $substitutionarray['__DATE_DUE_YMD__'] = is_object($object) ? (isset($object->date_lim_reglement) ? dol_print_date($object->date_lim_reglement, 'day', 0, $outputlangs) : '') : '';
5948
5949
            $substitutionarray['__AMOUNT__'] = is_object($object) ? $object->total_ttc : '';
5950
            $substitutionarray['__AMOUNT_EXCL_TAX__'] = is_object($object) ? $object->total_ht : '';
5951
            $substitutionarray['__AMOUNT_VAT__'] = is_object($object) ? ($object->total_vat ? $object->total_vat : $object->total_tva) : '';
5952
            if ($onlykey != 2 || $mysoc->useLocalTax(1))
5953
                $substitutionarray['__AMOUNT_TAX2__'] = is_object($object) ? $object->total_localtax1 : '';
5954
            if ($onlykey != 2 || $mysoc->useLocalTax(2))
5955
                $substitutionarray['__AMOUNT_TAX3__'] = is_object($object) ? $object->total_localtax2 : '';
5956
5957
            $substitutionarray['__AMOUNT_FORMATED__'] = is_object($object) ? price($object->total_ttc, 0, $outputlangs, 0, 0, -1, Globals::$conf->currency) : '';
5958
            $substitutionarray['__AMOUNT_EXCL_TAX_FORMATED__'] = is_object($object) ? price($object->total_ht, 0, $outputlangs, 0, 0, -1, Globals::$conf->currency) : '';
5959
            $substitutionarray['__AMOUNT_VAT_FORMATED__'] = is_object($object) ? ($object->total_vat ? price($object->total_vat, 0, $outputlangs, 0, 0, -1, Globals::$conf->currency) : price($object->total_tva, 0, $outputlangs, 0, 0, -1, Globals::$conf->currency)) : '';
5960
            if ($onlykey != 2 || $mysoc->useLocalTax(1))
5961
                $substitutionarray['__AMOUNT_TAX2_FORMATED__'] = is_object($object) ? price($object->total_localtax1, 0, $outputlangs, 0, 0, -1, Globals::$conf->currency) : '';
5962
            if ($onlykey != 2 || $mysoc->useLocalTax(2))
5963
                $substitutionarray['__AMOUNT_TAX3_FORMATED__'] = is_object($object) ? price($object->total_localtax2, 0, $outputlangs, 0, 0, -1, Globals::$conf->currency) : '';
5964
5965
// TODO Add keys for foreign multicurrency
5966
// For backward compatibility
5967
            if ($onlykey != 2) {
5968
                $substitutionarray['__TOTAL_TTC__'] = is_object($object) ? $object->total_ttc : '';
5969
                $substitutionarray['__TOTAL_HT__'] = is_object($object) ? $object->total_ht : '';
5970
                $substitutionarray['__TOTAL_VAT__'] = is_object($object) ? ($object->total_vat ? $object->total_vat : $object->total_tva) : '';
5971
            }
5972
        }
5973
5974
//var_dump($substitutionarray['__AMOUNT_FORMATED__']);
5975
        if (empty($exclude) || !in_array('date', $exclude)) {
5976
            include_once DOL_BASE_PATH . '/core/lib/date.lib.php';
5977
5978
            $tmp = dol_getdate(dol_now(), true);
5979
            $tmp2 = dol_get_prev_day($tmp['mday'], $tmp['mon'], $tmp['year']);
5980
            $tmp3 = dol_get_prev_month($tmp['mon'], $tmp['year']);
5981
            $tmp4 = dol_get_next_day($tmp['mday'], $tmp['mon'], $tmp['year']);
5982
            $tmp5 = dol_get_next_month($tmp['mon'], $tmp['year']);
5983
5984
            $substitutionarray = array_merge($substitutionarray, array(
5985
                '__DAY__' => (string) $tmp['mday'],
5986
                '__DAY_TEXT__' => $outputlangs->trans('Day' . $tmp['wday']), // Monday
5987
                '__DAY_TEXT_SHORT__' => $outputlangs->trans($tmp['weekday'] . 'Min'), // Mon
5988
                '__DAY_TEXT_MIN__' => $outputlangs->trans('Short' . $tmp['weekday']), // M
5989
                '__MONTH__' => (string) $tmp['mon'],
5990
                '__MONTH_TEXT__' => $outputlangs->trans('Month' . sprintf("%02d", $tmp['mon'])),
5991
                '__MONTH_TEXT_SHORT__' => $outputlangs->trans('MonthShort' . sprintf("%02d", $tmp['mon'])),
5992
                '__MONTH_TEXT_MIN__' => $outputlangs->trans('MonthVeryShort' . sprintf("%02d", $tmp['mon'])),
5993
                '__YEAR__' => (string) $tmp['year'],
5994
                '__PREVIOUS_DAY__' => (string) $tmp2['day'],
5995
                '__PREVIOUS_MONTH__' => (string) $tmp3['month'],
5996
                '__PREVIOUS_YEAR__' => (string) ($tmp['year'] - 1),
5997
                '__NEXT_DAY__' => (string) $tmp4['day'],
5998
                '__NEXT_MONTH__' => (string) $tmp5['month'],
5999
                '__NEXT_YEAR__' => (string) ($tmp['year'] + 1),
6000
            ));
6001
        }
6002
6003
        if (!empty(Globals::$conf->multicompany->enabled)) {
6004
            $substitutionarray = array_merge($substitutionarray, array('__ENTITY_ID__' => Globals::$conf->entity));
6005
        }
6006
        if (empty($exclude) || !in_array('system', $exclude)) {
6007
            $substitutionarray['__DOL_MAIN_URL_ROOT__'] = DOL_MAIN_URL_ROOT;
6008
            $substitutionarray['__(AnyTranslationKey)__'] = $outputlangs->trans('TranslationOfKey');
6009
            $substitutionarray['__[AnyConstantKey]__'] = $outputlangs->trans('ValueOfConstantKey');
6010
        }
6011
6012
        return $substitutionarray;
6013
    }
6014
6015
    /**
6016
     *  Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newval),
6017
     *  and texts like __(TranslationKey|langfile)__ and __[ConstantKey]__ are also replaced.
6018
     *  Example of usage:
6019
     *  $substitutionarray = getCommonSubstitutionArray($langs, 0, null, $thirdparty);
6020
     *  complete_substitutions_array($substitutionarray, $langs, $thirdparty);
6021
     *  $mesg = make_substitutions($mesg, $substitutionarray, $langs);
6022
     *
6023
     *  @param	string		$text	      			Source string in which we must do substitution
6024
     *  @param  array		$substitutionarray		Array with key->val to substitute. Example: array('__MYKEY__' => 'MyVal', ...)
6025
     *  @param	Translate	$outputlangs			Output language
6026
     * 	@return string  		    				Output string after substitutions
6027
     *  @see	complete_substitutions_array, getCommonSubstitutionArray
6028
     */
6029
    static function make_substitutions($text, $substitutionarray, $outputlangs = null)
6030
    {
6031
       // global Globals::$conf, $langs;
6032
6033
        if (!is_array($substitutionarray))
6034
            return 'ErrorBadParameterSubstitutionArrayWhenCalling_make_substitutions';
6035
6036
        if (empty($outputlangs))
6037
            $outputlangs = Globals::$langs;
6038
6039
// Make substitution for language keys
6040
        if (is_object($outputlangs)) {
6041
            while (preg_match('/__\(([^\)]+)\)__/', $text, $reg)) {
6042
                $msgishtml = 0;
6043
                if (DolUtils::dol_textishtml($text, 1))
6044
                    $msgishtml = 1;
6045
6046
// If key is __(TranslationKey|langfile)__, then force load of langfile.lang
6047
                $tmp = explode('|', $reg[1]);
6048
                if (!empty($tmp[1]))
6049
                    $outputlangs->load($tmp[1]);
6050
6051
                $text = preg_replace('/__\(' . preg_quote($reg[1], '/') . '\)__/', $msgishtml ? dol_htmlentitiesbr($outputlangs->transnoentitiesnoconv($reg[1])) : $outputlangs->transnoentitiesnoconv($reg[1]), $text);
6052
            }
6053
        }
6054
6055
// Make substitution for constant keys. Must be after the substitution of translation, so if text of translation contains a constant,
6056
// it is also converted.
6057
        while (preg_match('/__\[([^\]]+)\]__/', $text, $reg)) {
6058
            $msgishtml = 0;
6059
            if (DolUtils::dol_textishtml($text, 1))
6060
                $msgishtml = 1;
6061
6062
            $keyfound = $reg[1];
6063
            if (preg_match('/(_pass|password|secret|_key|key$)/i', $keyfound))
6064
                $newval = '*****forbidden*****';
6065
            else
6066
                $newval = empty(Globals::$conf->global->$keyfound) ? '' : Globals::$conf->global->$keyfound;
6067
            $text = preg_replace('/__\[' . preg_quote($keyfound, '/') . '\]__/', $msgishtml ? dol_htmlentitiesbr($newval) : $newval, $text);
6068
        }
6069
6070
// Make substitition for array $substitutionarray
6071
        foreach ($substitutionarray as $key => $value) {
6072
            if ($key == '__SIGNATURE__' && (!empty(Globals::$conf->global->MAIN_MAIL_DO_NOT_USE_SIGN)))
6073
                $value = '';  // Protection
6074
            if ($key == '__USER_SIGNATURE__' && (!empty(Globals::$conf->global->MAIN_MAIL_DO_NOT_USE_SIGN)))
6075
                $value = ''; // Protection
6076
6077
            $text = str_replace("$key", "$value", $text); // We must keep the " to work when value is 123.5 for example
6078
        }
6079
6080
        return $text;
6081
    }
6082
6083
    /**
6084
     *  Complete the $substitutionarray with more entries coming from external module that had set the "substitutions=1" into module_part array.
6085
     *  In this case, method completesubstitutionarray provided by module is called.
6086
     *
6087
     *  @param  array		$substitutionarray		Array substitution old value => new value value
6088
     *  @param  Translate	$outputlangs            Output language
6089
     *  @param  Object		$object                 Source object
6090
     *  @param  mixed		$parameters       		Add more parameters (useful to pass product lines)
6091
     *  @param  string      $callfunc               What is the name of the custom static function that will be called? (default: completesubstitutionarray)
6092
     *  @return	void
6093
     *  @see 	make_substitutions
6094
     */
6095
    static function complete_substitutions_array(&$substitutionarray, $outputlangs, $object = null, $parameters = null, $callfunc = "completesubstitutionarray")
6096
    {
6097
       // global Globals::$conf, $user;
6098
6099
        require_once DOL_BASE_PATH . '/core/lib/files.lib.php';
6100
6101
// Add a substitution key for each extrafields, using key __EXTRA_XXX__
6102
// TODO Remove this. Already available into the getCommonSubstitutionArray used to build the substitution array.
6103
        /* if (is_object($object) && is_array($object->array_options))
6104
          {
6105
          foreach($object->array_options as $key => $val)
6106
          {
6107
          $keyshort=preg_replace('/^(options|extra)_/','',$key);
6108
          $substitutionarray['__EXTRAFIELD_'.$keyshort.'__']=$val;
6109
          // For backward compatibiliy
6110
          $substitutionarray['%EXTRA_'.$keyshort.'%']=$val;
6111
          }
6112
          } */
6113
6114
// Check if there is external substitution to do, requested by plugins
6115
        $dirsubstitutions = array_merge(array(), (array) Globals::$conf->modules_parts['substitutions']);
6116
6117
        foreach ($dirsubstitutions as $reldir) {
6118
            $dir = dol_buildpath($reldir, 0);
6119
6120
// Check if directory exists
6121
            if (!dol_is_dir($dir))
6122
                continue;
6123
6124
            $substitfiles = dol_dir_list($dir, 'files', 0, 'functions_');
6125
            foreach ($substitfiles as $substitfile) {
6126
                if (preg_match('/functions_(.*)\.lib\.php/i', $substitfile['name'], $reg)) {
6127
                    $module = $reg[1];
6128
6129
                    dol_syslog("Library " . $substitfile['name'] . " found into " . $dir);
6130
                    // Include the user's functions file
6131
                    require_once $dir . $substitfile['name'];
6132
                    // Call the user's function, and only if it is defined
6133
                    $function_name = $module . "_" . $callfunc;
6134
                    if (function_exists($function_name))
6135
                        $function_name($substitutionarray, $outputlangs, $object, $parameters);
6136
                }
6137
            }
6138
        }
6139
    }
6140
6141
    /**
6142
     *    Format output for start and end date
6143
     *
6144
     *    @param	int	$date_start    Start date
6145
     *    @param    int	$date_end      End date
6146
     *    @param    string		$format        Output format
6147
     *    @param	Translate	$outputlangs   Output language
6148
     *    @return	void
6149
     */
6150
    static function print_date_range($date_start, $date_end, $format = '', $outputlangs = '')
6151
    {
6152
        print get_date_range($date_start, $date_end, $format, $outputlangs);
6153
    }
6154
6155
    /**
6156
     *    Format output for start and end date
6157
     *
6158
     *    @param	int			$date_start    		Start date
6159
     *    @param    int			$date_end      		End date
6160
     *    @param    string		$format        		Output format
6161
     *    @param	Translate	$outputlangs   		Output language
6162
     *    @param	integer		$withparenthesis	1=Add parenthesis, 0=non parenthesis
6163
     *    @return	string							String
6164
     */
6165
    static function get_date_range($date_start, $date_end, $format = '', $outputlangs = '', $withparenthesis = 1)
6166
    {
6167
       // global $langs;
6168
6169
        $out = '';
6170
6171
        if (!is_object($outputlangs))
6172
            $outputlangs = $langs;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
6173
6174
        if ($date_start && $date_end) {
6175
            $out .= ($withparenthesis ? ' (' : '') . $outputlangs->transnoentitiesnoconv('DateFromTo', dol_print_date($date_start, $format, false, $outputlangs), dol_print_date($date_end, $format, false, $outputlangs)) . ($withparenthesis ? ')' : '');
6176
        }
6177
        if ($date_start && !$date_end) {
6178
            $out .= ($withparenthesis ? ' (' : '') . $outputlangs->transnoentitiesnoconv('DateFrom', dol_print_date($date_start, $format, false, $outputlangs)) . ($withparenthesis ? ')' : '');
6179
        }
6180
        if (!$date_start && $date_end) {
6181
            $out .= ($withparenthesis ? ' (' : '') . $outputlangs->transnoentitiesnoconv('DateUntil', dol_print_date($date_end, $format, false, $outputlangs)) . ($withparenthesis ? ')' : '');
6182
        }
6183
6184
        return $out;
6185
    }
6186
6187
    /**
6188
     * Return firstname and lastname in correct order
6189
     *
6190
     * @param	string	$firstname		Firstname
6191
     * @param	string	$lastname		Lastname
6192
     * @param	int		$nameorder		-1=Auto, 0=Lastname+Firstname, 1=Firstname+Lastname, 2=Firstname
6193
     * @return	string					Firstname + lastname or Lastname + firstname
6194
     */
6195
    static function dolGetFirstLastname($firstname, $lastname, $nameorder = -1)
6196
    {
6197
       // global Globals::$conf;
6198
6199
        $ret = '';
6200
// If order not defined, we use the setup
6201
        if ($nameorder < 0)
6202
            $nameorder = (empty(Globals::$conf->global->MAIN_FIRSTNAME_NAME_POSITION) ? 1 : 0);
6203
        if ($nameorder && ((string) $nameorder != '2')) {
6204
            $ret .= $firstname;
6205
            if ($firstname && $lastname)
6206
                $ret .= ' ';
6207
            $ret .= $lastname;
6208
        }
6209
        else if ($nameorder == 2) {
6210
            $ret .= $firstname;
6211
        } else {
6212
            $ret .= $lastname;
6213
            if ($firstname && $lastname)
6214
                $ret .= ' ';
6215
            $ret .= $firstname;
6216
        }
6217
        return $ret;
6218
    }
6219
6220
    /**
6221
     * 	Set event message in dol_events session object. Will be output by calling dol_htmloutput_events.
6222
     *  Note: Calling dol_htmloutput_events is done into pages by standard llxFooter() function.
6223
     *  Note: Prefer to use setEventMessages instead.
6224
     *
6225
     * 	@param	mixed	$mesgs			Message string or array
6226
     *  @param  string	$style      	Which style to use ('mesgs' by default, 'warnings', 'errors')
6227
     *  @return	void
6228
     *  @see	dol_htmloutput_events
6229
     */
6230
    static function setEventMessage($mesgs, $style = 'mesgs')
6231
    {
6232
//dol_syslog(__FUNCTION__ . " is deprecated", LOG_WARNING);		This is not deprecated, it is used by setEventMessages function
6233
        if (!is_array($mesgs)) {  // If mesgs is a string
6234
            if ($mesgs)
6235
                $_SESSION['dol_events'][$style][] = $mesgs;
6236
        }
6237
        else {      // If mesgs is an array
6238
            foreach ($mesgs as $mesg) {
6239
                if ($mesg)
6240
                    $_SESSION['dol_events'][$style][] = $mesg;
6241
            }
6242
        }
6243
    }
6244
6245
    /**
6246
     * 	Set event messages in dol_events session object. Will be output by calling dol_htmloutput_events.
6247
     *  Note: Calling dol_htmloutput_events is done into pages by standard llxFooter() function.
6248
     *
6249
     * 	@param	string	$mesg			Message string
6250
     * 	@param	array	$mesgs			Message array
6251
     *  @param  string	$style      	Which style to use ('mesgs' by default, 'warnings', 'errors')
6252
     *  @return	void
6253
     *  @see	dol_htmloutput_events
6254
     */
6255
    static function setEventMessages($mesg, $mesgs, $style = 'mesgs')
6256
    {
6257
        if (empty($mesg) && empty($mesgs)) {
6258
            dol_syslog("Try to add a message in stack with empty message", LOG_WARNING);
6259
        } else {
6260
            if (!in_array((string) $style, array('mesgs', 'warnings', 'errors')))
6261
                dol_print_error('', 'Bad parameter style=' . $style . ' for setEventMessages');
6262
            if (empty($mesgs))
6263
                setEventMessage($mesg, $style);
6264
            else {
6265
                if (!empty($mesg) && !in_array($mesg, $mesgs))
6266
                    setEventMessage($mesg, $style); // Add message string if not already into array
6267
                setEventMessage($mesgs, $style);
6268
            }
6269
        }
6270
    }
6271
6272
    /**
6273
     * 	Print formated messages to output (Used to show messages on html output).
6274
     *  Note: Calling dol_htmloutput_events is done into pages by standard llxFooter() function, so there is
6275
     *  no need to call it explicitely.
6276
     *
6277
     *  @param	int		$disabledoutputofmessages	Clear all messages stored into session without diplaying them
6278
     *  @return	void
6279
     *  @see    									dol_htmloutput_mesg
6280
     */
6281
    static function dol_htmloutput_events($disabledoutputofmessages = 0)
6282
    {
6283
// Show mesgs
6284
        if (isset($_SESSION['dol_events']['mesgs'])) {
6285
            if (empty($disabledoutputofmessages))
6286
                dol_htmloutput_mesg('', $_SESSION['dol_events']['mesgs']);
6287
            unset($_SESSION['dol_events']['mesgs']);
6288
        }
6289
6290
// Show errors
6291
        if (isset($_SESSION['dol_events']['errors'])) {
6292
            if (empty($disabledoutputofmessages))
6293
                dol_htmloutput_mesg('', $_SESSION['dol_events']['errors'], 'error');
6294
            unset($_SESSION['dol_events']['errors']);
6295
        }
6296
6297
// Show warnings
6298
        if (isset($_SESSION['dol_events']['warnings'])) {
6299
            if (empty($disabledoutputofmessages))
6300
                dol_htmloutput_mesg('', $_SESSION['dol_events']['warnings'], 'warning');
6301
            unset($_SESSION['dol_events']['warnings']);
6302
        }
6303
    }
6304
6305
    /**
6306
     * 	Get formated messages to output (Used to show messages on html output).
6307
     *  This include also the translation of the message key.
6308
     *
6309
     * 	@param	string		$mesgstring		Message string or message key
6310
     * 	@param	string[]	$mesgarray      Array of message strings or message keys
6311
     *  @param  string		$style          Style of message output ('ok' or 'error')
6312
     *  @param  int			$keepembedded   Set to 1 in error message must be kept embedded into its html place (this disable jnotify)
6313
     * 	@return	string						Return html output
6314
     *
6315
     *  @see    dol_print_error
6316
     *  @see    dol_htmloutput_errors
6317
     *  @see    setEventMessages
6318
     */
6319
    static function get_htmloutput_mesg($mesgstring = '', $mesgarray = '', $style = 'ok', $keepembedded = 0)
6320
    {
6321
       // global Globals::$conf, $langs;
6322
6323
        $ret = 0;
6324
        $return = '';
6325
        $out = '';
6326
        $divstart = $divend = '';
6327
6328
// If inline message with no format, we add it.
6329
        if ((empty(Globals::$conf->use_javascript_ajax) || !empty(Globals::$conf->global->MAIN_DISABLE_JQUERY_JNOTIFY) || $keepembedded) && !preg_match('/<div class=".*">/i', $out)) {
6330
            $divstart = '<div class="' . $style . ' clearboth">';
6331
            $divend = '</div>';
6332
        }
6333
6334
        if ((is_array($mesgarray) && count($mesgarray)) || $mesgstring) {
6335
            $langs->load("errors");
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
6336
            $out .= $divstart;
6337
            if (is_array($mesgarray) && count($mesgarray)) {
6338
                foreach ($mesgarray as $message) {
6339
                    $ret++;
6340
                    $out .= $langs->trans($message);
6341
                    if ($ret < count($mesgarray))
6342
                        $out .= "<br>\n";
6343
                }
6344
            }
6345
            if ($mesgstring) {
6346
                $langs->load("errors");
6347
                $ret++;
6348
                $out .= $langs->trans($mesgstring);
6349
            }
6350
            $out .= $divend;
6351
        }
6352
6353
        if ($out) {
6354
            if (!empty(Globals::$conf->use_javascript_ajax) && empty(Globals::$conf->global->MAIN_DISABLE_JQUERY_JNOTIFY) && empty($keepembedded)) {
6355
                $return = '<script type="text/javascript">
6356
					$(document).ready(function() {
6357
						var block = ' . (!empty(Globals::$conf->global->MAIN_USE_JQUERY_BLOCKUI) ? "true" : "false") . '
6358
						if (block) {
6359
							$.dolEventValid("","' . dol_escape_js($out) . '");
6360
						} else {
6361
							/* jnotify(message, preset of message type, keepmessage) */
6362
							$.jnotify("' . dol_escape_js($out) . '",
6363
							"' . ($style == "ok" ? 3000 : $style) . '",
6364
							' . ($style == "ok" ? "false" : "true") . ',
6365
							{ remove: static function (){} } );
6366
						}
6367
					});
6368
				</script>';
6369
            } else {
6370
                $return = $out;
6371
            }
6372
        }
6373
6374
        return $return;
6375
    }
6376
6377
    /**
6378
     *  Get formated error messages to output (Used to show messages on html output).
6379
     *
6380
     *  @param  string	$mesgstring         Error message
6381
     *  @param  array	$mesgarray          Error messages array
6382
     *  @param  int		$keepembedded       Set to 1 in error message must be kept embedded into its html place (this disable jnotify)
6383
     *  @return string                		Return html output
6384
     *
6385
     *  @see    dol_print_error
6386
     *  @see    dol_htmloutput_mesg
6387
     */
6388
    static function get_htmloutput_errors($mesgstring = '', $mesgarray = array(), $keepembedded = 0)
6389
    {
6390
        return get_htmloutput_mesg($mesgstring, $mesgarray, 'error', $keepembedded);
6391
    }
6392
6393
    /**
6394
     * 	Print formated messages to output (Used to show messages on html output).
6395
     *
6396
     * 	@param	string		$mesgstring		Message string or message key
6397
     * 	@param	string[]	$mesgarray      Array of message strings or message keys
6398
     * 	@param  string      $style          Which style to use ('ok', 'warning', 'error')
6399
     * 	@param  int         $keepembedded   Set to 1 if message must be kept embedded into its html place (this disable jnotify)
6400
     * 	@return	void
6401
     *
6402
     * 	@see    dol_print_error
6403
     * 	@see    dol_htmloutput_errors
6404
     * 	@see    setEventMessages
6405
     */
6406
    static function dol_htmloutput_mesg($mesgstring = '', $mesgarray = array(), $style = 'ok', $keepembedded = 0)
6407
    {
6408
        if (empty($mesgstring) && (!is_array($mesgarray) || count($mesgarray) == 0))
6409
            return;
6410
6411
        $iserror = 0;
6412
        $iswarning = 0;
6413
        if (is_array($mesgarray)) {
6414
            foreach ($mesgarray as $val) {
6415
                if ($val && preg_match('/class="error"/i', $val)) {
6416
                    $iserror++;
6417
                    break;
6418
                }
6419
                if ($val && preg_match('/class="warning"/i', $val)) {
6420
                    $iswarning++;
6421
                    break;
6422
                }
6423
            }
6424
        } else if ($mesgstring && preg_match('/class="error"/i', $mesgstring))
6425
            $iserror++;
6426
        else if ($mesgstring && preg_match('/class="warning"/i', $mesgstring))
6427
            $iswarning++;
6428
        if ($style == 'error')
6429
            $iserror++;
6430
        if ($style == 'warning')
6431
            $iswarning++;
6432
6433
        if ($iserror || $iswarning) {
6434
// Remove div from texts
6435
            $mesgstring = preg_replace('/<\/div><div class="(error|warning)">/', '<br>', $mesgstring);
6436
            $mesgstring = preg_replace('/<div class="(error|warning)">/', '', $mesgstring);
6437
            $mesgstring = preg_replace('/<\/div>/', '', $mesgstring);
6438
// Remove div from texts array
6439
            if (is_array($mesgarray)) {
6440
                $newmesgarray = array();
6441
                foreach ($mesgarray as $val) {
6442
                    $tmpmesgstring = preg_replace('/<\/div><div class="(error|warning)">/', '<br>', $val);
6443
                    $tmpmesgstring = preg_replace('/<div class="(error|warning)">/', '', $tmpmesgstring);
6444
                    $tmpmesgstring = preg_replace('/<\/div>/', '', $tmpmesgstring);
6445
                    $newmesgarray[] = $tmpmesgstring;
6446
                }
6447
                $mesgarray = $newmesgarray;
6448
            }
6449
            print get_htmloutput_mesg($mesgstring, $mesgarray, ($iserror ? 'error' : 'warning'), $keepembedded);
6450
        } else
6451
            print get_htmloutput_mesg($mesgstring, $mesgarray, 'ok', $keepembedded);
6452
    }
6453
6454
    /**
6455
     *  Print formated error messages to output (Used to show messages on html output).
6456
     *
6457
     *  @param	string	$mesgstring          Error message
6458
     *  @param  array	$mesgarray           Error messages array
6459
     *  @param  int		$keepembedded        Set to 1 in error message must be kept embedded into its html place (this disable jnotify)
6460
     *  @return	void
6461
     *
6462
     *  @see    dol_print_error
6463
     *  @see    dol_htmloutput_mesg
6464
     */
6465
    static function dol_htmloutput_errors($mesgstring = '', $mesgarray = array(), $keepembedded = 0)
6466
    {
6467
        dol_htmloutput_mesg($mesgstring, $mesgarray, 'error', $keepembedded);
6468
    }
6469
6470
    /**
6471
     * 	Advanced sort array by second index function, which produces ascending (default)
6472
     *  or descending output and uses optionally natural case insensitive sorting (which
6473
     *  can be optionally case sensitive as well).
6474
     *
6475
     *  @param      array		$array      		Array to sort (array of array('key','otherkey1','otherkey2'...))
6476
     *  @param      string		$index				Key in array to use for sorting criteria
6477
     *  @param      int			$order				Sort order ('asc' or 'desc')
6478
     *  @param      int			$natsort			1=use "natural" sort (natsort), 0=use "standard" sort (asort)
6479
     *  @param      int			$case_sensitive		1=sort is case sensitive, 0=not case sensitive
6480
     *  @param		int			$keepindex			If 0 and index key of array to sort is a numeric, than index will be rewrote. If 1 or index key is not numeric, key for index is kept after sorting.
6481
     *  @return     array							Sorted array
6482
     */
6483
    static function dol_sort_array(&$array, $index, $order = 'asc', $natsort = 0, $case_sensitive = 0, $keepindex = 0)
6484
    {
6485
// Clean parameters
6486
        $order = strtolower($order);
6487
6488
        if (is_array($array)) {
6489
            $sizearray = count($array);
6490
            if ($sizearray > 0) {
6491
                $temp = array();
6492
                foreach (array_keys($array) as $key)
6493
                    $temp[$key] = $array[$key][$index];
6494
6495
                if (!$natsort)
6496
                    ($order == 'asc') ? asort($temp) : arsort($temp);
6497
                else {
6498
                    ($case_sensitive) ? natsort($temp) : natcasesort($temp);
6499
                    if ($order != 'asc')
6500
                        $temp = array_reverse($temp, true);
6501
                }
6502
6503
                $sorted = array();
6504
6505
                foreach (array_keys($temp) as $key) {
6506
                    (is_numeric($key) && empty($keepindex)) ? $sorted[] = $array[$key] : $sorted[$key] = $array[$key];
6507
                }
6508
6509
                return $sorted;
6510
            }
6511
        }
6512
        return $array;
6513
    }
6514
6515
    /**
6516
     *      Check if a string is in UTF8
6517
     *
6518
     *      @param	string	$str        String to check
6519
     * 		@return	boolean				True if string is UTF8 or ISO compatible with UTF8, False if not (ISO with special char or Binary)
6520
     */
6521
    static function utf8_check($str)
6522
    {
6523
// We must use here a binary strlen static function (so not dol_strlen)
6524
        $strLength = dol_strlen($str);
6525
        for ($i = 0; $i < $strLength; $i++) {
6526
            if (ord($str[$i]) < 0x80)
6527
                continue; // 0bbbbbbb
6528
            elseif ((ord($str[$i]) & 0xE0) == 0xC0)
6529
                $n = 1; // 110bbbbb
6530
            elseif ((ord($str[$i]) & 0xF0) == 0xE0)
6531
                $n = 2; // 1110bbbb
6532
            elseif ((ord($str[$i]) & 0xF8) == 0xF0)
6533
                $n = 3; // 11110bbb
6534
            elseif ((ord($str[$i]) & 0xFC) == 0xF8)
6535
                $n = 4; // 111110bb
6536
            elseif ((ord($str[$i]) & 0xFE) == 0xFC)
6537
                $n = 5; // 1111110b
6538
            else
6539
                return false; // Does not match any model
6540
            for ($j = 0; $j < $n; $j++) { // n bytes matching 10bbbbbb follow ?
6541
                if (( ++$i == strlen($str)) || ((ord($str[$i]) & 0xC0) != 0x80))
6542
                    return false;
6543
            }
6544
        }
6545
        return true;
6546
    }
6547
6548
    /**
6549
     *      Return a string encoded into OS filesystem encoding. This static function is used to define
6550
     * 	    value to pass to filesystem PHP functions.
6551
     *
6552
     *      @param	string	$str        String to encode (UTF-8)
6553
     * 		@return	string				Encoded string (UTF-8, ISO-8859-1)
6554
     */
6555
    function dol_osencode($str)
6556
    {
6557
       // global Globals::$conf;
6558
6559
        $tmp = ini_get("unicode.filesystem_encoding");      // Disponible avec PHP 6.0
6560
        if (empty($tmp) && !empty($_SERVER["WINDIR"]))
6561
            $tmp = 'iso-8859-1'; // By default for windows
6562
        if (empty($tmp))
6563
            $tmp = 'utf-8';          // By default for other
6564
        if (!empty(Globals::$conf->global->MAIN_FILESYSTEM_ENCODING))
6565
            $tmp = Globals::$conf->global->MAIN_FILESYSTEM_ENCODING;
6566
6567
        if ($tmp == 'iso-8859-1')
6568
            return utf8_decode($str);
6569
        return $str;
6570
    }
6571
6572
    /**
6573
     *      Return an id or code from a code or id.
6574
     *      Store also Code-Id into a cache to speed up next request on same key.
6575
     *
6576
     * 		@param	DoliDB	$db				Database handler
6577
     * 		@param	string	$key			Code or Id to get Id or Code
6578
     * 		@param	string	$tablename		Table name without prefix
6579
     * 		@param	string	$fieldkey		Field to search the key into
6580
     * 		@param	string	$fieldid		Field to get
6581
     *      @param  int		$entityfilter	Filter by entity
6582
     *      @return int						<0 if KO, Id of code if OK
6583
     *      @see $langs->getLabelFromKey
6584
     */
6585
    static function dol_getIdFromCode($db, $key, $tablename, $fieldkey = 'code', $fieldid = 'id', $entityfilter = 0)
6586
    {
6587
       // global $cache_codes;
6588
// If key empty
6589
        if ($key == '')
6590
            return '';
6591
6592
// Check in cache
6593
        if (isset($cache_codes[$tablename][$key][$fieldid])) { // Can be defined to 0 or ''
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $cache_codes seems to never exist and therefore isset should always be false.
Loading history...
6594
            return $cache_codes[$tablename][$key][$fieldid];   // Found in cache
6595
        }
6596
6597
        dol_syslog('dol_getIdFromCode (value not found into cache)', LOG_DEBUG);
6598
6599
        $sql = "SELECT " . $fieldid . " as valuetoget";
6600
        $sql .= " FROM " . MAIN_DB_PREFIX . $tablename;
6601
        $sql .= " WHERE " . $fieldkey . " = '" . $db->escape($key) . "'";
6602
        if (!empty($entityfilter))
6603
            $sql .= " AND entity IN (" . getEntity($tablename) . ")";
6604
6605
        $resql = $db->query($sql);
6606
        if ($resql) {
6607
            $obj = $db->fetch_object($resql);
6608
            if ($obj)
6609
                $cache_codes[$tablename][$key][$fieldid] = $obj->valuetoget;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$cache_codes was never initialized. Although not strictly required by PHP, it is generally a good practice to add $cache_codes = array(); before regardless.
Loading history...
6610
            else
6611
                $cache_codes[$tablename][$key][$fieldid] = '';
6612
            $db->free($resql);
6613
            return $cache_codes[$tablename][$key][$fieldid];
6614
        }
6615
        else {
6616
            return -1;
6617
        }
6618
    }
6619
6620
    /**
6621
     * Verify if condition in string is ok or not
6622
     *
6623
     * @param 	string		$strRights		String with condition to check
6624
     * @return 	boolean						True or False. Return True if strRights is ''
6625
     */
6626
    static function verifCond($strRights)
6627
    {
6628
       // global $user, Globals::$conf, $langs;
6629
        // global $leftmenu;
6630
        // global $rights;    // To export to dol_eval function
6631
//print $strRights."<br>\n";
6632
        $rights = true;
6633
        if ($strRights != '') {
6634
            $str = 'if(!(' . $strRights . ')) { $rights = false; }';
6635
            self::dol_eval($str);  // The dol_eval must contains all the// global $xxx used into a condition
6636
        }
6637
        return $rights;
6638
    }
6639
6640
    /**
6641
     * Replace eval static function to add more security.
6642
     * This static function is called by verifCond() or trans() and transnoentitiesnoconv().
6643
     *
6644
     * @param 	string	$s				String to evaluate
6645
     * @param	int		$returnvalue	0=No return (used to execute eval($a=something)). 1=Value of eval is returned (used to eval($something)).
6646
     * @param   int     $hideerrors     1=Hide errors
6647
     * @return	mixed					Nothing or return of eval
6648
     */
6649
    static function dol_eval($s, $returnvalue = 0, $hideerrors = 1)
6650
    {
6651
// Only// global variables can be changed by eval static function and returned to caller
6652
        // global $db, $langs, $user, Globals::$conf, $website, $websitepage;
6653
        // global $action, $mainmenu, $leftmenu;
6654
        // global $rights;
6655
        // global $object;
6656
        // global $mysoc;
6657
        // global $obj;       // To get $obj used into list when dol_eval is used for computed fields and $obj is not yet $object
6658
        // global $soc;       // For backward compatibility
6659
//print $s."<br>\n";
6660
        if ($returnvalue) {
6661
            if ($hideerrors)
6662
                return @eval('return ' . $s . ';');
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
6663
            else
6664
                return eval('return ' . $s . ';');
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
6665
        }
6666
        else {
6667
            if ($hideerrors)
6668
                @eval($s);
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
6669
            else
6670
                eval($s);
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
6671
        }
6672
    }
6673
6674
    /**
6675
     * Return if var element is ok
6676
     *
6677
     * @param   string      $element    Variable to check
6678
     * @return  boolean                 Return true of variable is not empty
6679
     */
6680
    static function dol_validElement($element)
6681
    {
6682
        return (trim($element) != '');
6683
    }
6684
6685
    /**
6686
     * 	Return img flag of country for a language code or country code
6687
     *
6688
     * 	@param	string	$codelang	Language code (en_IN, fr_CA...) or Country code (IN, FR)
6689
     *  @param	string	$moreatt	Add more attribute on img tag (For example 'style="float: right"')
6690
     * 	@return	string				HTML img string with flag.
6691
     */
6692
    static function picto_from_langcode($codelang, $moreatt = '')
6693
    {
6694
       // global $langs;
6695
6696
        if (empty($codelang))
6697
            return '';
6698
6699
        if ($codelang == 'auto') {
6700
            return '<span class="fa fa-globe"></span>';
6701
        }
6702
6703
        $langtocountryflag = array(
6704
            'ar_AR' => '',
6705
            'ca_ES' => 'catalonia',
6706
            'da_DA' => 'dk',
6707
            'fr_CA' => 'mq',
6708
            'sv_SV' => 'se'
6709
        );
6710
6711
        if (isset($langtocountryflag[$codelang]))
6712
            $flagImage = $langtocountryflag[$codelang];
6713
        else {
6714
            $tmparray = explode('_', $codelang);
6715
            $flagImage = empty($tmparray[1]) ? $tmparray[0] : $tmparray[1];
6716
        }
6717
6718
        return img_picto_common($codelang, 'flags/' . strtolower($flagImage) . '.png', $moreatt);
6719
    }
6720
6721
    /**
6722
     * Return default language from country code
6723
     *
6724
     * @param 	string 	$countrycode	Country code like 'US', 'FR', 'CA', ...
6725
     * @return	string					Value of locale like 'en_US', 'fr_FR', ...
6726
     */
6727
    static function getLanguageCodeFromCountryCode($countrycode)
6728
    {
6729
       // global $mysoc;
6730
6731
        if (strtoupper($countrycode) == 'MQ')
6732
            return 'fr_CA';
6733
        if (strtoupper($countrycode) == 'SE')
6734
            return 'sv_SE'; // se_SE is Sami/Sweden, and we want in priority sv_SE for SE country
6735
        if (strtoupper($countrycode) == 'CH') {
6736
            if ($mysoc->country_code == 'FR')
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mysoc seems to be never defined.
Loading history...
6737
                return 'fr_CH';
6738
            if ($mysoc->country_code == 'DE')
6739
                return 'de_CH';
6740
        }
6741
6742
// Locale list taken from:
6743
// http://stackoverflow.com/questions/3191664/
6744
// list-of-all-locales-and-their-short-codes
6745
        $locales = array(
6746
            'af-ZA',
6747
            'am-ET',
6748
            'ar-AE',
6749
            'ar-BH',
6750
            'ar-DZ',
6751
            'ar-EG',
6752
            'ar-IQ',
6753
            'ar-JO',
6754
            'ar-KW',
6755
            'ar-LB',
6756
            'ar-LY',
6757
            'ar-MA',
6758
            'ar-OM',
6759
            'ar-QA',
6760
            'ar-SA',
6761
            'ar-SY',
6762
            'ar-TN',
6763
            'ar-YE',
6764
            'as-IN',
6765
            'ba-RU',
6766
            'be-BY',
6767
            'bg-BG',
6768
            'bn-BD',
6769
            'bn-IN',
6770
            'bo-CN',
6771
            'br-FR',
6772
            'ca-ES',
6773
            'co-FR',
6774
            'cs-CZ',
6775
            'cy-GB',
6776
            'da-DK',
6777
            'de-AT',
6778
            'de-CH',
6779
            'de-DE',
6780
            'de-LI',
6781
            'de-LU',
6782
            'dv-MV',
6783
            'el-GR',
6784
            'en-AU',
6785
            'en-BZ',
6786
            'en-CA',
6787
            'en-GB',
6788
            'en-IE',
6789
            'en-IN',
6790
            'en-JM',
6791
            'en-MY',
6792
            'en-NZ',
6793
            'en-PH',
6794
            'en-SG',
6795
            'en-TT',
6796
            'en-US',
6797
            'en-ZA',
6798
            'en-ZW',
6799
            'es-AR',
6800
            'es-BO',
6801
            'es-CL',
6802
            'es-CO',
6803
            'es-CR',
6804
            'es-DO',
6805
            'es-EC',
6806
            'es-ES',
6807
            'es-GT',
6808
            'es-HN',
6809
            'es-MX',
6810
            'es-NI',
6811
            'es-PA',
6812
            'es-PE',
6813
            'es-PR',
6814
            'es-PY',
6815
            'es-SV',
6816
            'es-US',
6817
            'es-UY',
6818
            'es-VE',
6819
            'et-EE',
6820
            'eu-ES',
6821
            'fa-IR',
6822
            'fi-FI',
6823
            'fo-FO',
6824
            'fr-BE',
6825
            'fr-CA',
6826
            'fr-CH',
6827
            'fr-FR',
6828
            'fr-LU',
6829
            'fr-MC',
6830
            'fy-NL',
6831
            'ga-IE',
6832
            'gd-GB',
6833
            'gl-ES',
6834
            'gu-IN',
6835
            'he-IL',
6836
            'hi-IN',
6837
            'hr-BA',
6838
            'hr-HR',
6839
            'hu-HU',
6840
            'hy-AM',
6841
            'id-ID',
6842
            'ig-NG',
6843
            'ii-CN',
6844
            'is-IS',
6845
            'it-CH',
6846
            'it-IT',
6847
            'ja-JP',
6848
            'ka-GE',
6849
            'kk-KZ',
6850
            'kl-GL',
6851
            'km-KH',
6852
            'kn-IN',
6853
            'ko-KR',
6854
            'ky-KG',
6855
            'lb-LU',
6856
            'lo-LA',
6857
            'lt-LT',
6858
            'lv-LV',
6859
            'mi-NZ',
6860
            'mk-MK',
6861
            'ml-IN',
6862
            'mn-MN',
6863
            'mr-IN',
6864
            'ms-BN',
6865
            'ms-MY',
6866
            'mt-MT',
6867
            'nb-NO',
6868
            'ne-NP',
6869
            'nl-BE',
6870
            'nl-NL',
6871
            'nn-NO',
6872
            'oc-FR',
6873
            'or-IN',
6874
            'pa-IN',
6875
            'pl-PL',
6876
            'ps-AF',
6877
            'pt-BR',
6878
            'pt-PT',
6879
            'rm-CH',
6880
            'ro-RO',
6881
            'ru-RU',
6882
            'rw-RW',
6883
            'sa-IN',
6884
            'se-FI',
6885
            'se-NO',
6886
            'se-SE',
6887
            'si-LK',
6888
            'sk-SK',
6889
            'sl-SI',
6890
            'sq-AL',
6891
            'sv-FI',
6892
            'sv-SE',
6893
            'sw-KE',
6894
            'ta-IN',
6895
            'te-IN',
6896
            'th-TH',
6897
            'tk-TM',
6898
            'tn-ZA',
6899
            'tr-TR',
6900
            'tt-RU',
6901
            'ug-CN',
6902
            'uk-UA',
6903
            'ur-PK',
6904
            'vi-VN',
6905
            'wo-SN',
6906
            'xh-ZA',
6907
            'yo-NG',
6908
            'zh-CN',
6909
            'zh-HK',
6910
            'zh-MO',
6911
            'zh-SG',
6912
            'zh-TW',
6913
            'zu-ZA',
6914
        );
6915
6916
        $buildprimarykeytotest = strtolower($countrycode) . '-' . strtoupper($countrycode);
6917
        if (in_array($buildprimarykeytotest, $locales))
6918
            return strtolower($countrycode) . '_' . strtoupper($countrycode);
6919
6920
        foreach ($locales as $locale) {
6921
            $locale_language = locale_get_primary_language($locale);
6922
            $locale_region = locale_get_region($locale);
6923
            if (strtoupper($countrycode) == $locale_region) {
6924
//var_dump($locale.'-'.$locale_language.'-'.$locale_region);
6925
                return strtolower($locale_language) . '_' . strtoupper($locale_region);
6926
            }
6927
        }
6928
6929
        return null;
6930
    }
6931
6932
    /**
6933
     *  Complete or removed entries into a head array (used to build tabs).
6934
     *  For example, with value added by external modules. Such values are declared into Globals::$conf->modules_parts['tab'].
6935
     *  Or by change using hook completeTabsHead
6936
     *
6937
     *  @param	Conf			$conf           Object conf
0 ignored issues
show
Bug introduced by
The type Alixar\Helpers\Conf was not found. Did you mean Conf? If so, make sure to prefix the type with \.
Loading history...
6938
     *  @param  Translate		$langs          Object langs
6939
     *  @param  object|null		$object         Object object
6940
     *  @param  array			$head          	Object head
6941
     *  @param  int				$h				New position to fill
6942
     *  @param  string			$type           Value for object where objectvalue can be
6943
     *                              			'thirdparty'       to add a tab in third party view
6944
     * 		                        	      	'intervention'     to add a tab in intervention view
6945
     *     		                    	     	'supplier_order'   to add a tab in supplier order view
6946
     *          		            	        'supplier_invoice' to add a tab in supplier invoice view
6947
     *                  		    	        'invoice'          to add a tab in customer invoice view
6948
     *                          			    'order'            to add a tab in customer order view
6949
     *                          				'contract'		   to add a tabl in contract view
6950
     *                      			        'product'          to add a tab in product view
6951
     *                              			'propal'           to add a tab in propal view
6952
     *                              			'user'             to add a tab in user view
6953
     *                              			'group'            to add a tab in group view
6954
     * 		        	               	     	'member'           to add a tab in fundation member view
6955
     *      		                        	'categories_x'	   to add a tab in category view ('x': type of category (0=product, 1=supplier, 2=customer, 3=member)
6956
     *      									'ecm'			   to add a tab for another ecm view
6957
     *                                          'stock'            to add a tab for warehouse view
6958
     *  @param  string		$mode  	        	'add' to complete head, 'remove' to remove entries
6959
     * 	@return	void
6960
     */
6961
    static function complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, $mode = 'add')
6962
    {
6963
       // global $hookmanager;
6964
6965
        if (isset(Globals::$conf->modules_parts['tabs'][$type]) && is_array(Globals::$conf->modules_parts['tabs'][$type])) {
6966
            foreach (Globals::$conf->modules_parts['tabs'][$type] as $value) {
6967
6968
                $values = explode(':', $value);
6969
6970
                if ($mode == 'add' && !preg_match('/^\-/', $values[1])) {
6971
                    if (count($values) == 6) {       // new declaration with permissions:  $value='objecttype:+tabname1:Title1:langfile@mymodule:$user->rights->mymodule->read:/mymodule/mynewtab1.php?id=__ID__'
6972
                        if ($values[0] != $type)
6973
                            continue;
6974
6975
                        if (verifCond($values[4])) {
6976
                            if ($values[3])
6977
                                $langs->load($values[3]);
6978
                            if (preg_match('/SUBSTITUTION_([^_]+)/i', $values[2], $reg)) {
6979
                                $substitutionarray = array();
6980
                                complete_substitutions_array($substitutionarray, $langs, $object, array('needforkey' => $values[2]));
6981
                                $label = make_substitutions($reg[1], $substitutionarray);
6982
                            } else
6983
                                $label = $langs->trans($values[2]);
6984
6985
                            //$head[$h][0] = dol_buildpath(preg_replace('/__ID__/i', ((is_object($object) && !empty($object->id)) ? $object->id : ''), $values[5]), 1);
6986
                            $head[$h][0] = BASE_URI . preg_replace('/__ID__/i', ((is_object($object) && !empty($object->id)) ? $object->id : ''), $values[5]);
6987
                            $head[$h][1] = $label;
6988
                            $head[$h][2] = str_replace('+', '', $values[1]);
6989
                            $h++;
6990
                        }
6991
                    }
6992
                    else if (count($values) == 5) {       // deprecated
6993
                        dol_syslog('Passing 5 values in tabs module_parts is deprecated. Please update to 6 with permissions.', LOG_WARNING);
6994
6995
                        if ($values[0] != $type)
6996
                            continue;
6997
                        if ($values[3])
6998
                            $langs->load($values[3]);
6999
                        if (preg_match('/SUBSTITUTION_([^_]+)/i', $values[2], $reg)) {
7000
                            $substitutionarray = array();
7001
                            complete_substitutions_array($substitutionarray, $langs, $object, array('needforkey' => $values[2]));
7002
                            $label = make_substitutions($reg[1], $substitutionarray);
7003
                        } else
7004
                            $label = $langs->trans($values[2]);
7005
7006
                        $head[$h][0] = dol_buildpath(preg_replace('/__ID__/i', ((is_object($object) && !empty($object->id)) ? $object->id : ''), $values[4]), 1);
7007
                        $head[$h][1] = $label;
7008
                        $head[$h][2] = str_replace('+', '', $values[1]);
7009
                        $h++;
7010
                    }
7011
                }
7012
                else if ($mode == 'remove' && preg_match('/^\-/', $values[1])) {
7013
                    if ($values[0] != $type)
7014
                        continue;
7015
                    $tabname = str_replace('-', '', $values[1]);
7016
                    foreach ($head as $key => $val) {
7017
                        $condition = (!empty($values[3]) ? verifCond($values[3]) : 1);
7018
                        //var_dump($key.' - '.$tabname.' - '.$head[$key][2].' - '.$values[3].' - '.$condition);
7019
                        if ($head[$key][2] == $tabname && $condition) {
7020
                            unset($head[$key]);
7021
                            break;
7022
                        }
7023
                    }
7024
                }
7025
            }
7026
        }
7027
7028
// No need to make a return $head. Var is modified as a reference
7029
        if (!empty($hookmanager)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $hookmanager seems to never exist and therefore empty should always be true.
Loading history...
7030
            $parameters = array('object' => $object, 'mode' => $mode, 'head' => $head);
7031
            $reshook = $hookmanager->executeHooks('completeTabsHead', $parameters);
7032
            if ($reshook > 0) {
7033
                $head = $hookmanager->resArray;
7034
                $h = count($head);
7035
            }
7036
        }
7037
    }
7038
7039
    /**
7040
     * Print common footer :
7041
     * 		conf->global->MAIN_HTML_FOOTER
7042
     *      js for switch of menu hider
7043
     * 		js for conf->global->MAIN_GOOGLE_AN_ID
7044
     * 		js for conf->global->MAIN_SHOW_TUNING_INFO or $_SERVER["MAIN_SHOW_TUNING_INFO"]
7045
     * 		js for conf->logbuffer
7046
     *
7047
     * @param	string	$zone	'private' (for private pages) or 'public' (for public pages)
7048
     * @return	void
7049
     */
7050
    static function printCommonFooter($zone = 'private')
7051
    {
7052
       // global Globals::$conf, $hookmanager, $user;
7053
        // global $action;
7054
        // global $micro_start_time;
7055
7056
        if ($zone == 'private')
7057
            print "\n" . '<!-- Common footer for private page -->' . "\n";
7058
        else
7059
            print "\n" . '<!-- Common footer for public page -->' . "\n";
7060
7061
// A div to store page_y POST parameter so we can read it using javascript
7062
        print "\n<!-- A div to store page_y POST paramater -->\n";
7063
        print '<div id="page_y" style="display: none;">' . $_POST['page_y'] . '</div>' . "\n";
7064
7065
        $parameters = array();
7066
        $reshook = $hookmanager->executeHooks('printCommonFooter', $parameters);    // Note that $action and $object may have been modified by some hooks
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $hookmanager seems to be never defined.
Loading history...
7067
        if (empty($reshook)) {
7068
            if (!empty(Globals::$conf->global->MAIN_HTML_FOOTER))
7069
                print Globals::$conf->global->MAIN_HTML_FOOTER . "\n";
7070
7071
            print "\n";
7072
            if (!empty(Globals::$conf->use_javascript_ajax)) {
7073
                print '<script type="text/javascript" language="javascript">' . "\n";
7074
                print 'jQuery(document).ready(function() {' . "\n";
7075
7076
                if ($zone == 'private' && empty(Globals::$conf->dol_use_jmobile)) {
7077
                    print "\n";
7078
                    print '/* JS CODE TO ENABLE to manage handler to switch left menu page (menuhider) */' . "\n";
7079
                    print 'jQuery(".menuhider").click(function() {';
7080
                    print '  console.log("We click on .menuhider");' . "\n";
7081
                    //print "  $('.side-nav').animate({width:'toggle'},200);\n";     // OK with eldy theme but not with md
7082
                    print "  $('.side-nav').toggle()\n";
7083
                    print "  $('.login_block').toggle()\n";
7084
                    print '});' . "\n";
7085
                }
7086
7087
// Management of focus and mandatory for fields
7088
                if ($action == 'create' || $action == 'edit' || (empty($action) && (preg_match('/new\.php/', $_SERVER["PHP_SELF"])))) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $action seems to never exist and therefore empty should always be true.
Loading history...
Comprehensibility Best Practice introduced by
The variable $action seems to be never defined.
Loading history...
7089
                    print '/* JS CODE TO ENABLE to manage focus and mandatory form fields */' . "\n";
7090
                    $relativepathstring = $_SERVER["PHP_SELF"];
7091
                    // Clean $relativepathstring
7092
                    if (constant('DOL_BASE_URI'))
7093
                        $relativepathstring = preg_replace('/^' . preg_quote(constant('DOL_BASE_URI'), '/') . '/', '', $relativepathstring);
7094
                    $relativepathstring = preg_replace('/^\//', '', $relativepathstring);
7095
                    $relativepathstring = preg_replace('/^custom\//', '', $relativepathstring);
7096
                    $tmpqueryarraywehave = explode('&', dol_string_nohtmltag($_SERVER['QUERY_STRING']));
7097
                    if (!empty($user->default_values[$relativepathstring]['focus'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $user seems to be never defined.
Loading history...
7098
                        foreach ($user->default_values[$relativepathstring]['focus'] as $defkey => $defval) {
7099
                            $qualified = 0;
7100
                            if ($defkey != '_noquery_') {
7101
                                $tmpqueryarraytohave = explode('&', $defkey);
7102
                                $foundintru = 0;
7103
                                foreach ($tmpqueryarraytohave as $tmpquerytohave) {
7104
                                    if (!in_array($tmpquerytohave, $tmpqueryarraywehave))
7105
                                        $foundintru = 1;
7106
                                }
7107
                                if (!$foundintru)
7108
                                    $qualified = 1;
7109
                                //var_dump($defkey.'-'.$qualified);
7110
                            } else
7111
                                $qualified = 1;
7112
7113
                            if ($qualified) {
7114
                                foreach ($defval as $paramkey => $paramval) {
7115
                                    // Set focus on field
7116
                                    print 'jQuery("input[name=\'' . $paramkey . '\']").focus();' . "\n";
7117
                                    print 'jQuery("textarea[name=\'' . $paramkey . '\']").focus();' . "\n";
7118
                                    print 'jQuery("select[name=\'' . $paramkey . '\']").focus();' . "\n";  // Not really usefull, but we keep it in case of.
7119
                                }
7120
                            }
7121
                        }
7122
                    }
7123
                    if (!empty($user->default_values[$relativepathstring]['mandatory'])) {
7124
                        foreach ($user->default_values[$relativepathstring]['mandatory'] as $defkey => $defval) {
7125
                            $qualified = 0;
7126
                            if ($defkey != '_noquery_') {
7127
                                $tmpqueryarraytohave = explode('&', $defkey);
7128
                                $foundintru = 0;
7129
                                foreach ($tmpqueryarraytohave as $tmpquerytohave) {
7130
                                    if (!in_array($tmpquerytohave, $tmpqueryarraywehave))
7131
                                        $foundintru = 1;
7132
                                }
7133
                                if (!$foundintru)
7134
                                    $qualified = 1;
7135
                                //var_dump($defkey.'-'.$qualified);
7136
                            } else
7137
                                $qualified = 1;
7138
7139
                            if ($qualified) {
7140
                                foreach ($defval as $paramkey => $paramval) {
7141
                                    // Add property 'required' on input
7142
                                    print 'jQuery("input[name=\'' . $paramkey . '\']").prop(\'required\',true);' . "\n";
7143
                                    print 'jQuery("textarea[name=\'' . $paramkey . '\']").prop(\'required\',true);' . "\n";
7144
                                    print 'jQuery("select[name=\'' . $paramkey . '\']").prop(\'required\',true);' . "\n";  // required on a select works only if key is "", this does not happen in Dolibarr
7145
                                }
7146
                            }
7147
                        }
7148
                    }
7149
                }
7150
7151
                print '});' . "\n";
7152
7153
// Google Analytics
7154
// TODO Add a hook here
7155
                if (!empty(Globals::$conf->google->enabled) && !empty(Globals::$conf->global->MAIN_GOOGLE_AN_ID)) {
7156
                    if ((Globals::$conf->dol_use_jmobile != 4)) {
7157
                        print "\n";
7158
                        print "/* JS CODE TO ENABLE for google analtics tag */\n";
7159
                        print '  var _gaq = _gaq || [];' . "\n";
7160
                        print '  _gaq.push([\'_setAccount\', \'' . Globals::$conf->global->MAIN_GOOGLE_AN_ID . '\']);' . "\n";
7161
                        print '  _gaq.push([\'_trackPageview\']);' . "\n";
7162
                        print '' . "\n";
7163
                        print '  (function() {' . "\n";
7164
                        print '    var ga = document.createElement(\'script\'); ga.type = \'text/javascript\'; ga.async = true;' . "\n";
7165
                        print '    ga.src = (\'https:\' == document.location.protocol ? \'https://ssl\' : \'http://www\') + \'.google-analytics.com/ga.js\';' . "\n";
7166
                        print '    var s = document.getElementsByTagName(\'script\')[0]; s.parentNode.insertBefore(ga, s);' . "\n";
7167
                        print '  })();' . "\n";
7168
                    }
7169
                }
7170
7171
// End of tuning
7172
                if (!empty($_SERVER['MAIN_SHOW_TUNING_INFO']) || !empty(Globals::$conf->global->MAIN_SHOW_TUNING_INFO)) {
7173
                    print "\n";
7174
                    print "/* JS CODE TO ENABLE to add memory info */\n";
7175
                    print 'window.console && console.log("';
7176
                    if (!empty(Globals::$conf->global->MEMCACHED_SERVER))
7177
                        print 'MEMCACHED_SERVER=' . Globals::$conf->global->MEMCACHED_SERVER . ' - ';
7178
                    print 'MAIN_OPTIMIZE_SPEED=' . (isset(Globals::$conf->global->MAIN_OPTIMIZE_SPEED) ? Globals::$conf->global->MAIN_OPTIMIZE_SPEED : 'off');
7179
                    if (!empty($micro_start_time)) {   // Works only if MAIN_SHOW_TUNING_INFO is defined at $_SERVER level. Not in// global variable.
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $micro_start_time seems to never exist and therefore empty should always be true.
Loading history...
7180
                        $micro_end_time = microtime(true);
7181
                        print ' - Build time: ' . ceil(1000 * ($micro_end_time - $micro_start_time)) . ' ms';
7182
                    }
7183
                    if (function_exists("memory_get_usage")) {
7184
                        print ' - Mem: ' . memory_get_usage();
7185
                    }
7186
                    if (function_exists("xdebug_memory_usage")) {
7187
                        print ' - XDebug time: ' . ceil(1000 * xdebug_time_index()) . ' ms';
7188
                        print ' - XDebug mem: ' . xdebug_memory_usage();
7189
                        print ' - XDebug mem peak: ' . xdebug_peak_memory_usage();
7190
                    }
7191
                    if (function_exists("zend_loader_file_encoded")) {
7192
                        print ' - Zend encoded file: ' . (zend_loader_file_encoded() ? 'yes' : 'no');
7193
                    }
7194
                    print '");' . "\n";
7195
                }
7196
7197
                print "\n" . '</script>' . "\n";
7198
            }
7199
7200
// Add Xdebug coverage of code
7201
            if (defined('XDEBUGCOVERAGE')) {
7202
                print_r(xdebug_get_code_coverage());
7203
            }
7204
7205
// If there is some logs in buffer to show
7206
            if (count(Globals::$conf->logbuffer)) {
7207
                print "\n";
7208
                print "<!-- Start of log output\n";
7209
//print '<div class="hidden">'."\n";
7210
                foreach (Globals::$conf->logbuffer as $logline) {
7211
                    print $logline . "<br>\n";
7212
                }
7213
//print '</div>'."\n";
7214
                print "End of log output -->\n";
7215
            }
7216
        }
7217
    }
7218
7219
    /**
7220
     * Split a string with 2 keys into key array.
7221
     * For example: "A=1;B=2;C=2" is exploded into array('A'=>1,'B'=>2,'C'=>3)
7222
     *
7223
     * @param 	string	$string		String to explode
7224
     * @param 	string	$delimiter	Delimiter between each couple of data
7225
     * @param 	string	$kv			Delimiter between key and value
7226
     * @return	array				Array of data exploded
7227
     */
7228
    static function dolExplodeIntoArray($string, $delimiter = ';', $kv = '=')
7229
    {
7230
        if ($a = explode($delimiter, $string)) {
7231
            $ka = array();
7232
            foreach ($a as $s) { // each part
7233
                if ($s) {
7234
                    if ($pos = strpos($s, $kv)) { // key/value delimiter
7235
                        $ka[trim(substr($s, 0, $pos))] = trim(substr($s, $pos + strlen($kv)));
7236
                    } else { // key delimiter not found
7237
                        $ka[] = trim($s);
7238
                    }
7239
                }
7240
            }
7241
            return $ka;
7242
        }
7243
        return array();
7244
    }
7245
7246
    /**
7247
     * Set focus onto field with selector (similar behaviour of 'autofocus' HTML5 tag)
7248
     *
7249
     * @param 	string	$selector	Selector ('#id' or 'input[name="ref"]') to use to find the HTML input field that must get the autofocus. You must use a CSS selector, so unique id preceding with the '#' char.
7250
     * @return	string				HTML code to set focus
7251
     */
7252
    static function dol_set_focus($selector)
7253
    {
7254
        print "\n" . '<!-- Set focus onto a specific field -->' . "\n";
7255
        print '<script type="text/javascript" language="javascript">jQuery(document).ready(function() { jQuery("' . dol_escape_js($selector) . '").focus(); });</script>' . "\n";
7256
    }
7257
7258
    /**
7259
     * Return getmypid() or random PID when static function is disabled
7260
     * Some web hosts disable this php static function for security reasons
7261
     * and sometimes we can't redeclare function
7262
     *
7263
     * @return	int
7264
     */
7265
    static function dol_getmypid()
7266
    {
7267
        if (!function_exists('getmypid')) {
7268
            return mt_rand(1, 32768);
7269
        } else {
7270
            return getmypid();
7271
        }
7272
    }
7273
7274
    /**
7275
     * Generate natural SQL search string for a criteria (this criteria can be tested on one or several fields)
7276
     *
7277
     * @param   string|string[]	$fields 	String or array of strings, filled with the name of all fields in the SQL query we must check (combined with a OR). Example: array("p.field1","p.field2")
7278
     * @param   string 			$value 		The value to look for.
7279
     *                          		    If param $mode is 0, can contains several keywords separated with a space or |
7280
     *                                      like "keyword1 keyword2" = We want record field like keyword1 AND field like keyword2
7281
     *                                      or like "keyword1|keyword2" = We want record field like keyword1 OR field like keyword2
7282
     *                             			If param $mode is 1, can contains an operator <, > or = like "<10" or ">=100.5 < 1000"
7283
     *                             			If param $mode is 2, can contains a list of int id separated by comma like "1,3,4"
7284
     *                             			If param $mode is 3, can contains a list of string separated by comma like "a,b,c"
7285
     * @param	integer			$mode		0=value is list of keyword strings, 1=value is a numeric test (Example ">5.5 <10"), 2=value is a list of ID separated with comma (Example '1,3,4')
7286
     * 										3=value is list of string separated with comma (Example 'text 1,text 2'), 4=value is a list of ID separated with comma (Example '1,3,4') for search into a multiselect string ('1,2')
7287
     * @param	integer			$nofirstand	1=Do not output the first 'AND'
7288
     * @return 	string 			$res 		The statement to append to the SQL query
7289
     */
7290
    static function natural_search($fields, $value, $mode = 0, $nofirstand = 0)
7291
    {
7292
       // global $db, $langs;
7293
7294
        $value = trim($value);
7295
7296
        if ($mode == 0) {
7297
            $value = preg_replace('/\*/', '%', $value); // Replace * with %
7298
        }
7299
        if ($mode == 1) {
7300
            $value = preg_replace('/([<>=]+)\s+([0-9' . preg_quote($langs->trans("DecimalSeparator"), '/') . '\-])/', '\1\2', $value); // Clean string '< 10' into '<10' so we can the explode on space to get all tests to do
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
7301
        }
7302
7303
        $value = preg_replace('/\s*\|\s*/', '|', $value);
7304
7305
        $crits = explode(' ', $value);
7306
        $res = '';
7307
        if (!is_array($fields))
7308
            $fields = array($fields);
7309
7310
        $nboffields = count($fields);
7311
        $end2 = count($crits);
7312
        $j = 0;
7313
        foreach ($crits as $crit) {
7314
            $i = 0;
7315
            $i2 = 0;
7316
            $newres = '';
7317
            foreach ($fields as $field) {
7318
                if ($mode == 1) {
7319
                    $operator = '=';
7320
                    $newcrit = preg_replace('/([<>=]+)/', '', trim($crit));
7321
7322
                    preg_match('/([<>=]+)/', trim($crit), $reg);
7323
                    if ($reg[1]) {
7324
                        $operator = $reg[1];
7325
                    }
7326
                    if ($newcrit != '') {
7327
                        $numnewcrit = price2num($newcrit);
7328
                        if (is_numeric($numnewcrit)) {
7329
                            $newres .= ($i2 > 0 ? ' OR ' : '') . $field . ' ' . $operator . ' ' . $numnewcrit;
7330
                        } else {
7331
                            $newres .= ($i2 > 0 ? ' OR ' : '') . '1 = 2'; // force false
7332
                        }
7333
                        $i2++; // a criteria was added to string
7334
                    }
7335
                } else if ($mode == 2) {
7336
                    $newres .= ($i2 > 0 ? ' OR ' : '') . $field . " IN (" . $db->escape(trim($crit)) . ")";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $db seems to be never defined.
Loading history...
7337
                    $i2++; // a criteria was added to string
7338
                } else if ($mode == 3) {
7339
                    $tmparray = explode(',', trim($crit));
7340
                    if (count($tmparray)) {
7341
                        $listofcodes = '';
7342
                        foreach ($tmparray as $val) {
7343
                            if ($val) {
7344
                                $listofcodes .= ($listofcodes ? ',' : '');
7345
                                $listofcodes .= "'" . $db->escape(trim($val)) . "'";
7346
                            }
7347
                        }
7348
                        $newres .= ($i2 > 0 ? ' OR ' : '') . $field . " IN (" . $listofcodes . ")";
7349
                        $i2++; // a criteria was added to string
7350
                    }
7351
                } else if ($mode == 4) {
7352
                    $tmparray = explode(',', trim($crit));
7353
                    if (count($tmparray)) {
7354
                        $listofcodes = '';
7355
                        foreach ($tmparray as $val) {
7356
                            if ($val) {
7357
                                $newres .= ($i2 > 0 ? ' OR (' : '(') . $field . ' LIKE \'' . $db->escape(trim($val)) . ',%\'';
7358
                                $newres .= ' OR ' . $field . ' = \'' . $db->escape(trim($val)) . '\'';
7359
                                $newres .= ' OR ' . $field . ' LIKE \'%,' . $db->escape(trim($val)) . '\'';
7360
                                $newres .= ' OR ' . $field . ' LIKE \'%,' . $db->escape(trim($val)) . ',%\'';
7361
                                $newres .= ')';
7362
                                $i2++;
7363
                            }
7364
                        }
7365
                    }
7366
                } else {    // $mode=0
7367
                    $textcrit = '';
7368
                    $tmpcrits = explode('|', $crit);
7369
                    $i3 = 0;
7370
                    foreach ($tmpcrits as $tmpcrit) {
7371
                        if (empty($tmpcrit))
7372
                            continue;
7373
7374
                        $newres .= (($i2 > 0 || $i3 > 0) ? ' OR ' : '');
7375
7376
                        if (preg_match('/\.(id|rowid)$/', $field)) { // Special case for rowid that is sometimes a ref so used as a search field
7377
                            $newres .= $field . " = " . (is_numeric(trim($tmpcrit)) ? trim($tmpcrit) : '0');
7378
                        } else {
7379
                            $newres .= $field . " LIKE '";
7380
7381
                            $tmpcrit = trim($tmpcrit);
7382
                            $tmpcrit2 = $tmpcrit;
7383
                            $tmpbefore = '%';
7384
                            $tmpafter = '%';
7385
                            if (preg_match('/^[\^\$]/', $tmpcrit)) {
7386
                                $tmpbefore = '';
7387
                                $tmpcrit2 = preg_replace('/^[\^\$]/', '', $tmpcrit2);
7388
                            }
7389
                            if (preg_match('/[\^\$]$/', $tmpcrit)) {
7390
                                $tmpafter = '';
7391
                                $tmpcrit2 = preg_replace('/[\^\$]$/', '', $tmpcrit2);
7392
                            }
7393
                            $newres .= $tmpbefore;
7394
                            $newres .= $db->escape($tmpcrit2);
7395
                            $newres .= $tmpafter;
7396
                            $newres .= "'";
7397
                            if ($tmpcrit2 == '') {
7398
                                $newres .= ' OR ' . $field . " IS NULL";
7399
                            }
7400
                        }
7401
7402
                        $i3++;
7403
                    }
7404
                    $i2++; // a criteria was added to string
7405
                }
7406
                $i++;
7407
            }
7408
            if ($newres)
7409
                $res = $res . ($res ? ' AND ' : '') . ($i2 > 1 ? '(' : '') . $newres . ($i2 > 1 ? ')' : '');
7410
            $j++;
7411
        }
7412
        $res = ($nofirstand ? "" : " AND ") . "(" . $res . ")";
7413
//print 'xx'.$res.'yy';
7414
        return $res;
7415
    }
7416
7417
    /**
7418
     * Return string with full Url. The file qualified is the one defined by relative path in $object->last_main_doc
7419
     *
7420
     * @param   Object	$object				Object
7421
     * @return	string						Url string
7422
     */
7423
    static function showDirectDownloadLink($object)
7424
    {
7425
       // global Globals::$conf, $langs;
7426
7427
        $out = '';
7428
        $url = $object->getLastMainDocLink($object->element);
7429
7430
        if ($url) {
7431
            $out .= img_picto('', 'object_globe.png') . ' ' . $langs->trans("DirectDownloadLink") . '<br>';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
7432
            $out .= '<input type="text" id="directdownloadlink" class="quatrevingtpercent" value="' . $url . '">';
7433
            $out .= ajax_autoselect("directdownloadlink", 0);
7434
        }
7435
        return $out;
7436
    }
7437
7438
    /**
7439
     * Return the filename of file to get the thumbs
7440
     *
7441
     * @param   string  $file           Original filename (full or relative path)
7442
     * @param   string  $extName        Extension to differenciate thumb file name ('', '_small', '_mini')
7443
     * @param   string  $extImgTarget   Force image extension for thumbs. Use '' to keep same extension than original image (default).
7444
     * @return  string                  New file name (full or relative path, including the thumbs/)
7445
     */
7446
    static function getImageFileNameForSize($file, $extName, $extImgTarget = '')
7447
    {
7448
        $dirName = dirname($file);
7449
        if ($dirName == '.')
7450
            $dirName = '';
7451
7452
        $fileName = preg_replace('/(\.gif|\.jpeg|\.jpg|\.png|\.bmp)$/i', '', $file); // We remove extension, whatever is its case
7453
        $fileName = basename($fileName);
7454
7455
        if (empty($extImgTarget))
7456
            $extImgTarget = (preg_match('/\.jpg$/i', $file) ? '.jpg' : '');
7457
        if (empty($extImgTarget))
7458
            $extImgTarget = (preg_match('/\.jpeg$/i', $file) ? '.jpeg' : '');
7459
        if (empty($extImgTarget))
7460
            $extImgTarget = (preg_match('/\.gif$/i', $file) ? '.gif' : '');
7461
        if (empty($extImgTarget))
7462
            $extImgTarget = (preg_match('/\.png$/i', $file) ? '.png' : '');
7463
        if (empty($extImgTarget))
7464
            $extImgTarget = (preg_match('/\.bmp$/i', $file) ? '.bmp' : '');
7465
7466
        if (!$extImgTarget)
7467
            return $file;
7468
7469
        $subdir = '';
7470
        if ($extName)
7471
            $subdir = 'thumbs/';
7472
7473
        return ($dirName ? $dirName . '/' : '') . $subdir . $fileName . $extName . $extImgTarget; // New filename for thumb
7474
    }
7475
7476
    /**
7477
     * Return URL we can use for advanced preview links
7478
     *
7479
     * @param   string    $modulepart     propal, facture, facture_fourn, ...
7480
     * @param   string    $relativepath   Relative path of docs.
7481
     * @param	int		  $alldata		  Return array with all components (1 is recommended, then use a simple a href link with the class, target and mime attribute added. 'documentpreview' css class is handled by jquery code into main.inc.php)
7482
     * @param	string	  $param		  More param on http links
7483
     * @return  string|array              Output string with href link or array with all components of link
7484
     */
7485
    static function getAdvancedPreviewUrl($modulepart, $relativepath, $alldata = 0, $param = '')
7486
    {
7487
       // global Globals::$conf, $langs;
7488
7489
        if (empty(Globals::$conf->use_javascript_ajax))
7490
            return '';
7491
7492
        $mime_preview = array('bmp', 'jpeg', 'png', 'gif', 'tiff', 'pdf', 'plain', 'css', 'svg+xml');
7493
//$mime_preview[]='vnd.oasis.opendocument.presentation';
7494
//$mime_preview[]='archive';
7495
        $num_mime = array_search(dol_mimetype($relativepath, '', 1), $mime_preview);
7496
7497
        if ($alldata == 1) {
7498
            if ($num_mime !== false)
7499
                return array('target' => '_blank', 'css' => 'documentpreview', 'url' => DOL_BASE_URI . '/document.php?modulepart=' . $modulepart . '&attachment=0&file=' . urlencode($relativepath) . ($param ? '&' . $param : ''), 'mime' => dol_mimetype($relativepath),);
7500
            else
7501
                return array();
7502
        }
7503
7504
// old behavior
7505
        if ($num_mime !== false)
7506
            return 'javascript:document_preview(\'' . dol_escape_js(DOL_BASE_URI . '/document.php?modulepart=' . $modulepart . '&attachment=0&file=' . urlencode($relativepath) . ($param ? '&' . $param : '')) . '\', \'' . dol_mimetype($relativepath) . '\', \'' . dol_escape_js($langs->trans('Preview')) . '\')';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
7507
        else
7508
            return '';
7509
    }
7510
7511
    /**
7512
     * Make content of an input box selected when we click into input field.
7513
     *
7514
     * @param string	$htmlname	Id of html object
7515
     * @param string	$addlink	Add a 'link to' after
7516
     * @return string
7517
     */
7518
    static function ajax_autoselect($htmlname, $addlink = '')
7519
    {
7520
       // global $langs;
7521
        $out = '<script type="text/javascript">
7522
               jQuery(document).ready(static function () {
7523
				    jQuery("#' . $htmlname . '").click(function() { jQuery(this).select(); } );
7524
				});
7525
		    </script>';
7526
        if ($addlink)
7527
            $out .= ' <a href="' . $addlink . '" target="_blank">' . $langs->trans("Link") . '</a>';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $langs seems to be never defined.
Loading history...
7528
        return $out;
7529
    }
7530
7531
    /**
7532
     * 	Return mime type of a file
7533
     *
7534
     * 	@param	string	$file		Filename we looking for MIME type
7535
     *  @param  string	$default    Default mime type if extension not found in known list
7536
     * 	@param	int		$mode    	0=Return full mime, 1=otherwise short mime string, 2=image for mime type, 3=source language, 4=css of font fa
7537
     * 	@return string 		    	Return a mime type family (text/xxx, application/xxx, image/xxx, audio, video, archive)
7538
     *  @see    image_format_supported (images.lib.php)
7539
     */
7540
    static function dol_mimetype($file, $default = 'application/octet-stream', $mode = 0)
7541
    {
7542
        $mime = $default;
7543
        $imgmime = 'other.png';
7544
        $famime = 'file-o';
7545
        $srclang = '';
7546
7547
        $tmpfile = preg_replace('/\.noexe$/', '', $file);
7548
7549
// Text files
7550
        if (preg_match('/\.txt$/i', $tmpfile)) {
7551
            $mime = 'text/plain';
7552
            $imgmime = 'text.png';
7553
            $famime = 'file-text-o';
7554
        }
7555
        if (preg_match('/\.rtx$/i', $tmpfile)) {
7556
            $mime = 'text/richtext';
7557
            $imgmime = 'text.png';
7558
            $famime = 'file-text-o';
7559
        }
7560
        if (preg_match('/\.csv$/i', $tmpfile)) {
7561
            $mime = 'text/csv';
7562
            $imgmime = 'text.png';
7563
            $famime = 'file-text-o';
7564
        }
7565
        if (preg_match('/\.tsv$/i', $tmpfile)) {
7566
            $mime = 'text/tab-separated-values';
7567
            $imgmime = 'text.png';
7568
            $famime = 'file-text-o';
7569
        }
7570
        if (preg_match('/\.(cf|conf|log)$/i', $tmpfile)) {
7571
            $mime = 'text/plain';
7572
            $imgmime = 'text.png';
7573
            $famime = 'file-text-o';
7574
        }
7575
        if (preg_match('/\.ini$/i', $tmpfile)) {
7576
            $mime = 'text/plain';
7577
            $imgmime = 'text.png';
7578
            $srclang = 'ini';
7579
            $famime = 'file-text-o';
7580
        }
7581
        if (preg_match('/\.css$/i', $tmpfile)) {
7582
            $mime = 'text/css';
7583
            $imgmime = 'css.png';
7584
            $srclang = 'css';
7585
            $famime = 'file-text-o';
7586
        }
7587
// Certificate files
7588
        if (preg_match('/\.(crt|cer|key|pub)$/i', $tmpfile)) {
7589
            $mime = 'text/plain';
7590
            $imgmime = 'text.png';
7591
            $famime = 'file-text-o';
7592
        }
7593
// HTML/XML
7594
        if (preg_match('/\.(html|htm|shtml)$/i', $tmpfile)) {
7595
            $mime = 'text/html';
7596
            $imgmime = 'html.png';
7597
            $srclang = 'html';
7598
            $famime = 'file-text-o';
7599
        }
7600
        if (preg_match('/\.(xml|xhtml)$/i', $tmpfile)) {
7601
            $mime = 'text/xml';
7602
            $imgmime = 'other.png';
7603
            $srclang = 'xml';
7604
            $famime = 'file-text-o';
7605
        }
7606
// Languages
7607
        if (preg_match('/\.bas$/i', $tmpfile)) {
7608
            $mime = 'text/plain';
7609
            $imgmime = 'text.png';
7610
            $srclang = 'bas';
7611
            $famime = 'file-code-o';
7612
        }
7613
        if (preg_match('/\.(c)$/i', $tmpfile)) {
7614
            $mime = 'text/plain';
7615
            $imgmime = 'text.png';
7616
            $srclang = 'c';
7617
            $famime = 'file-code-o';
7618
        }
7619
        if (preg_match('/\.(cpp)$/i', $tmpfile)) {
7620
            $mime = 'text/plain';
7621
            $imgmime = 'text.png';
7622
            $srclang = 'cpp';
7623
            $famime = 'file-code-o';
7624
        }
7625
        if (preg_match('/\.(h)$/i', $tmpfile)) {
7626
            $mime = 'text/plain';
7627
            $imgmime = 'text.png';
7628
            $srclang = 'h';
7629
            $famime = 'file-code-o';
7630
        }
7631
        if (preg_match('/\.(java|jsp)$/i', $tmpfile)) {
7632
            $mime = 'text/plain';
7633
            $imgmime = 'text.png';
7634
            $srclang = 'java';
7635
            $famime = 'file-code-o';
7636
        }
7637
        if (preg_match('/\.php([0-9]{1})?$/i', $tmpfile)) {
7638
            $mime = 'text/plain';
7639
            $imgmime = 'php.png';
7640
            $srclang = 'php';
7641
            $famime = 'file-code-o';
7642
        }
7643
        if (preg_match('/\.phtml$/i', $tmpfile)) {
7644
            $mime = 'text/plain';
7645
            $imgmime = 'php.png';
7646
            $srclang = 'php';
7647
            $famime = 'file-code-o';
7648
        }
7649
        if (preg_match('/\.(pl|pm)$/i', $tmpfile)) {
7650
            $mime = 'text/plain';
7651
            $imgmime = 'pl.png';
7652
            $srclang = 'perl';
7653
            $famime = 'file-code-o';
7654
        }
7655
        if (preg_match('/\.sql$/i', $tmpfile)) {
7656
            $mime = 'text/plain';
7657
            $imgmime = 'text.png';
7658
            $srclang = 'sql';
7659
            $famime = 'file-code-o';
7660
        }
7661
        if (preg_match('/\.js$/i', $tmpfile)) {
7662
            $mime = 'text/x-javascript';
7663
            $imgmime = 'jscript.png';
7664
            $srclang = 'js';
7665
            $famime = 'file-code-o';
7666
        }
7667
// Open office
7668
        if (preg_match('/\.odp$/i', $tmpfile)) {
7669
            $mime = 'application/vnd.oasis.opendocument.presentation';
7670
            $imgmime = 'ooffice.png';
7671
            $famime = 'file-powerpoint-o';
7672
        }
7673
        if (preg_match('/\.ods$/i', $tmpfile)) {
7674
            $mime = 'application/vnd.oasis.opendocument.spreadsheet';
7675
            $imgmime = 'ooffice.png';
7676
            $famime = 'file-excel-o';
7677
        }
7678
        if (preg_match('/\.odt$/i', $tmpfile)) {
7679
            $mime = 'application/vnd.oasis.opendocument.text';
7680
            $imgmime = 'ooffice.png';
7681
            $famime = 'file-word-o';
7682
        }
7683
// MS Office
7684
        if (preg_match('/\.mdb$/i', $tmpfile)) {
7685
            $mime = 'application/msaccess';
7686
            $imgmime = 'mdb.png';
7687
            $famime = 'file-o';
7688
        }
7689
        if (preg_match('/\.doc(x|m)?$/i', $tmpfile)) {
7690
            $mime = 'application/msword';
7691
            $imgmime = 'doc.png';
7692
            $famime = 'file-word-o';
7693
        }
7694
        if (preg_match('/\.dot(x|m)?$/i', $tmpfile)) {
7695
            $mime = 'application/msword';
7696
            $imgmime = 'doc.png';
7697
            $famime = 'file-word-o';
7698
        }
7699
        if (preg_match('/\.xlt(x)?$/i', $tmpfile)) {
7700
            $mime = 'application/vnd.ms-excel';
7701
            $imgmime = 'xls.png';
7702
            $famime = 'file-excel-o';
7703
        }
7704
        if (preg_match('/\.xla(m)?$/i', $tmpfile)) {
7705
            $mime = 'application/vnd.ms-excel';
7706
            $imgmime = 'xls.png';
7707
            $famime = 'file-excel-o';
7708
        }
7709
        if (preg_match('/\.xls$/i', $tmpfile)) {
7710
            $mime = 'application/vnd.ms-excel';
7711
            $imgmime = 'xls.png';
7712
            $famime = 'file-excel-o';
7713
        }
7714
        if (preg_match('/\.xls(b|m|x)$/i', $tmpfile)) {
7715
            $mime = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
7716
            $imgmime = 'xls.png';
7717
            $famime = 'file-excel-o';
7718
        }
7719
        if (preg_match('/\.pps(m|x)?$/i', $tmpfile)) {
7720
            $mime = 'application/vnd.ms-powerpoint';
7721
            $imgmime = 'ppt.png';
7722
            $famime = 'file-powerpoint-o';
7723
        }
7724
        if (preg_match('/\.ppt(m|x)?$/i', $tmpfile)) {
7725
            $mime = 'application/x-mspowerpoint';
7726
            $imgmime = 'ppt.png';
7727
            $famime = 'file-powerpoint-o';
7728
        }
7729
// Other
7730
        if (preg_match('/\.pdf$/i', $tmpfile)) {
7731
            $mime = 'application/pdf';
7732
            $imgmime = 'pdf.png';
7733
            $famime = 'file-pdf-o';
7734
        }
7735
// Scripts
7736
        if (preg_match('/\.bat$/i', $tmpfile)) {
7737
            $mime = 'text/x-bat';
7738
            $imgmime = 'script.png';
7739
            $srclang = 'dos';
7740
            $famime = 'file-code-o';
7741
        }
7742
        if (preg_match('/\.sh$/i', $tmpfile)) {
7743
            $mime = 'text/x-sh';
7744
            $imgmime = 'script.png';
7745
            $srclang = 'bash';
7746
            $famime = 'file-code-o';
7747
        }
7748
        if (preg_match('/\.ksh$/i', $tmpfile)) {
7749
            $mime = 'text/x-ksh';
7750
            $imgmime = 'script.png';
7751
            $srclang = 'bash';
7752
            $famime = 'file-code-o';
7753
        }
7754
        if (preg_match('/\.bash$/i', $tmpfile)) {
7755
            $mime = 'text/x-bash';
7756
            $imgmime = 'script.png';
7757
            $srclang = 'bash';
7758
            $famime = 'file-code-o';
7759
        }
7760
// Images
7761
        if (preg_match('/\.ico$/i', $tmpfile)) {
7762
            $mime = 'image/x-icon';
7763
            $imgmime = 'image.png';
7764
            $famime = 'file-image-o';
7765
        }
7766
        if (preg_match('/\.(jpg|jpeg)$/i', $tmpfile)) {
7767
            $mime = 'image/jpeg';
7768
            $imgmime = 'image.png';
7769
            $famime = 'file-image-o';
7770
        }
7771
        if (preg_match('/\.png$/i', $tmpfile)) {
7772
            $mime = 'image/png';
7773
            $imgmime = 'image.png';
7774
            $famime = 'file-image-o';
7775
        }
7776
        if (preg_match('/\.gif$/i', $tmpfile)) {
7777
            $mime = 'image/gif';
7778
            $imgmime = 'image.png';
7779
            $famime = 'file-image-o';
7780
        }
7781
        if (preg_match('/\.bmp$/i', $tmpfile)) {
7782
            $mime = 'image/bmp';
7783
            $imgmime = 'image.png';
7784
            $famime = 'file-image-o';
7785
        }
7786
        if (preg_match('/\.(tif|tiff)$/i', $tmpfile)) {
7787
            $mime = 'image/tiff';
7788
            $imgmime = 'image.png';
7789
            $famime = 'file-image-o';
7790
        }
7791
        if (preg_match('/\.svg$/i', $tmpfile)) {
7792
            $mime = 'image/svg+xml';
7793
            $imgmime = 'image.png';
7794
            $famime = 'file-image-o';
7795
        }
7796
// Calendar
7797
        if (preg_match('/\.vcs$/i', $tmpfile)) {
7798
            $mime = 'text/calendar';
7799
            $imgmime = 'other.png';
7800
            $famime = 'file-text-o';
7801
        }
7802
        if (preg_match('/\.ics$/i', $tmpfile)) {
7803
            $mime = 'text/calendar';
7804
            $imgmime = 'other.png';
7805
            $famime = 'file-text-o';
7806
        }
7807
// Other
7808
        if (preg_match('/\.torrent$/i', $tmpfile)) {
7809
            $mime = 'application/x-bittorrent';
7810
            $imgmime = 'other.png';
7811
            $famime = 'file-o';
7812
        }
7813
// Audio
7814
        if (preg_match('/\.(mp3|ogg|au|wav|wma|mid)$/i', $tmpfile)) {
7815
            $mime = 'audio';
7816
            $imgmime = 'audio.png';
7817
            $famime = 'file-audio-o';
7818
        }
7819
// Video
7820
        if (preg_match('/\.ogv$/i', $tmpfile)) {
7821
            $mime = 'video/ogg';
7822
            $imgmime = 'video.png';
7823
            $famime = 'file-video-o';
7824
        }
7825
        if (preg_match('/\.webm$/i', $tmpfile)) {
7826
            $mime = 'video/webm';
7827
            $imgmime = 'video.png';
7828
            $famime = 'file-video-o';
7829
        }
7830
        if (preg_match('/\.avi$/i', $tmpfile)) {
7831
            $mime = 'video/x-msvideo';
7832
            $imgmime = 'video.png';
7833
            $famime = 'file-video-o';
7834
        }
7835
        if (preg_match('/\.divx$/i', $tmpfile)) {
7836
            $mime = 'video/divx';
7837
            $imgmime = 'video.png';
7838
            $famime = 'file-video-o';
7839
        }
7840
        if (preg_match('/\.xvid$/i', $tmpfile)) {
7841
            $mime = 'video/xvid';
7842
            $imgmime = 'video.png';
7843
            $famime = 'file-video-o';
7844
        }
7845
        if (preg_match('/\.(wmv|mpg|mpeg)$/i', $tmpfile)) {
7846
            $mime = 'video';
7847
            $imgmime = 'video.png';
7848
            $famime = 'file-video-o';
7849
        }
7850
// Archive
7851
        if (preg_match('/\.(zip|rar|gz|tgz|z|cab|bz2|7z|tar|lzh)$/i', $tmpfile)) {
7852
            $mime = 'archive';
7853
            $imgmime = 'archive.png';
7854
            $famime = 'file-archive-o';
7855
        }    // application/xxx where zzz is zip, ...
7856
// Exe
7857
        if (preg_match('/\.(exe|com)$/i', $tmpfile)) {
7858
            $mime = 'application/octet-stream';
7859
            $imgmime = 'other.png';
7860
            $famime = 'file-o';
7861
        }
7862
// Lib
7863
        if (preg_match('/\.(dll|lib|o|so|a)$/i', $tmpfile)) {
7864
            $mime = 'library';
7865
            $imgmime = 'library.png';
7866
            $famime = 'file-o';
7867
        }
7868
// Err
7869
        if (preg_match('/\.err$/i', $tmpfile)) {
7870
            $mime = 'error';
7871
            $imgmime = 'error.png';
7872
            $famime = 'file-text-o';
7873
        }
7874
7875
// Return string
7876
        if ($mode == 1) {
7877
            $tmp = explode('/', $mime);
7878
            return (!empty($tmp[1]) ? $tmp[1] : $tmp[0]);
7879
        }
7880
        if ($mode == 2) {
7881
            return $imgmime;
7882
        }
7883
        if ($mode == 3) {
7884
            return $srclang;
7885
        }
7886
        if ($mode == 4) {
7887
            return $famime;
7888
        }
7889
        return $mime;
7890
    }
7891
7892
    /**
7893
     * Return value from dictionary
7894
     *
7895
     * @param string	$tablename		name of dictionary
7896
     * @param string	$field			the value to return
7897
     * @param int		$id				id of line
7898
     * @param bool		$checkentity	add filter on entity
7899
     * @param string	$rowidfield		name of the column rowid
7900
     * @return string
7901
     */
7902
    static function getDictvalue($tablename, $field, $id, $checkentity = false, $rowidfield = 'rowid')
7903
    {
7904
       // global $dictvalues, $db, $langs;
7905
7906
        if (!isset($dictvalues[$tablename])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dictvalues seems to never exist and therefore isset should always be false.
Loading history...
7907
            $dictvalues[$tablename] = array();
0 ignored issues
show
Comprehensibility Best Practice introduced by
$dictvalues was never initialized. Although not strictly required by PHP, it is generally a good practice to add $dictvalues = array(); before regardless.
Loading history...
7908
            $sql = 'SELECT * FROM ' . $tablename . ' WHERE 1';
7909
            if ($checkentity)
7910
                $sql .= ' AND entity IN (0,' . getEntity($tablename) . ')';
7911
7912
            $resql = $db->query($sql);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $db seems to be never defined.
Loading history...
7913
            if ($resql) {
7914
                while ($obj = $db->fetch_object($resql)) {
7915
                    $dictvalues[$tablename][$obj->{$rowidfield}] = $obj;
7916
                }
7917
            } else {
7918
                dol_print_error($db);
7919
            }
7920
        }
7921
7922
        if (!empty($dictvalues[$tablename][$id]))
7923
            return $dictvalues[$tablename][$id]->{$field}; // Found
7924
        else { // Not found
7925
            if ($id > 0)
7926
                return $id;
7927
            return '';
7928
        }
7929
    }
7930
7931
    /**
7932
     * 	Return true if the color is light
7933
     *
7934
     *  @param	string	$stringcolor		String with hex (FFFFFF) or comma RGB ('255,255,255')
7935
     *  @return	int							-1 : Error with argument passed |0 : color is dark | 1 : color is light
7936
     */
7937
    static function colorIsLight($stringcolor)
7938
    {
7939
        $res = -1;
7940
        if (!empty($stringcolor)) {
7941
            $res = 0;
7942
            $tmp = explode(',', $stringcolor);
7943
            if (count($tmp) > 1) {   // This is a comma RGB ('255','255','255')
7944
                $r = $tmp[0];
7945
                $g = $tmp[1];
7946
                $b = $tmp[2];
7947
            } else {
7948
                $hexr = $stringcolor[0] . $stringcolor[1];
7949
                $hexg = $stringcolor[2] . $stringcolor[3];
7950
                $hexb = $stringcolor[4] . $stringcolor[5];
7951
                $r = hexdec($hexr);
7952
                $g = hexdec($hexg);
7953
                $b = hexdec($hexb);
7954
            }
7955
            $bright = (max($r, $g, $b) + min($r, $g, $b)) / 510.0;    // HSL algorithm
7956
            if ($bright > 0.6)
7957
                $res = 1;
7958
        }
7959
        return $res;
7960
    }
7961
7962
    /**
7963
     * Function to test if an entry is enabled or not
7964
     *
7965
     * @param	string		$type_user					0=We test for internal user, 1=We test for external user
7966
     * @param	array		$menuentry					Array for feature entry to test
7967
     * @param	array		$listofmodulesforexternal	Array with list of modules allowed to external users
7968
     * @return	int										0=Hide, 1=Show, 2=Show gray
7969
     */
7970
    static function isVisibleToUserType($type_user, &$menuentry, &$listofmodulesforexternal)
7971
    {
7972
       // global Globals::$conf;
7973
//print 'type_user='.$type_user.' module='.$menuentry['module'].' enabled='.$menuentry['enabled'].' perms='.$menuentry['perms'];
7974
//print 'ok='.in_array($menuentry['module'], $listofmodulesforexternal);
7975
        if (empty($menuentry['enabled']))
7976
            return 0; // Entry disabled by condition
7977
        if ($type_user && $menuentry['module']) {
7978
            $tmploops = explode('|', $menuentry['module']);
7979
            $found = 0;
7980
            foreach ($tmploops as $tmploop) {
7981
                if (in_array($tmploop, $listofmodulesforexternal)) {
7982
                    $found++;
7983
                    break;
7984
                }
7985
            }
7986
            if (!$found)
7987
                return 0; // Entry is for menus all excluded to external users
7988
        }
7989
        if (!$menuentry['perms'] && $type_user)
7990
            return 0;            // No permissions and user is external
7991
        if (!$menuentry['perms'] && !empty(Globals::$conf->global->MAIN_MENU_HIDE_UNAUTHORIZED))
7992
            return 0; // No permissions and option to hide when not allowed, even for internal user, is on
7993
        if (!$menuentry['perms'])
7994
            return 2;               // No permissions and user is external
7995
        return 1;
7996
    }
7997
7998
    /**
7999
     * Round to next multiple.
8000
     *
8001
     * @param 	double		$n		Number to round up
8002
     * @param 	integer		$x		Multiple. For example 60 to round up to nearest exact minute for a date with seconds.
8003
     * @return 	integer				Value rounded.
8004
     */
8005
    static function roundUpToNextMultiple($n, $x = 5)
8006
    {
8007
        return (ceil($n) % $x === 0) ? ceil($n) : round(($n + $x / 2) / $x) * $x;
8008
    }
8009
}
8010