Passed
Push — CHECK_API ( 78ffdd...fa4f39 )
by Rafael
41:29
created

FormWebPortal   F

Complexity

Total Complexity 334

Size/Duplication

Total Lines 1320
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 771
dl 0
loc 1320
rs 1.829
c 0
b 0
f 0
wmc 334

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A getSignatureLink() 0 13 3
D getDocumentsLink() 0 87 18
F selectarray() 0 88 34
B selectForForms() 0 49 9
A inputDate() 0 22 6
A inputType() 0 20 6
F selectForFormsList() 0 159 45
F showInputField() 0 337 91
F showOutputFieldForObject() 0 371 121

How to fix   Complexity   

Complex Class

Complex classes like FormWebPortal often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use FormWebPortal, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/* Copyright (C) 2023-2024  Laurent Destailleur         <[email protected]>
4
 * Copyright (C) 2023-2024	Lionel Vessiller		    <[email protected]>
5
 * Copyright (C) 2023-2024	Patrice Andreani		    <[email protected]>
6
 * Copyright (C) 2024		MDW							<[email protected]>
7
 * Copyright (C) 2024       Frédéric France             <[email protected]>
8
 * Copyright (C) 2024       Rafael San José             <[email protected]>
9
 *
10
 * This program is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 3 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22
 */
23
24
namespace Dolibarr\Code\WebPortal\Classes;
25
26
use Dolibarr\Code\Categories\Classes\Categorie;
27
use Dolibarr\Code\Core\Classes\Form;
28
use DoliDB;
29
30
/**
31
 * \file       htdocs/webportal/class/html.formwebportal.class.php
32
 * \ingroup    webportal
33
 * \brief      File of class with all html predefined components for WebPortal
34
 */
35
36
37
/**
38
 * Class to manage generation of HTML components
39
 * Only common components for WebPortal must be here.
40
 */
41
class FormWebPortal extends Form
42
{
43
    /**
44
     * @var DoliDB Database
45
     */
46
    public $db;
47
48
    /**
49
     * @var array $infofiles Array of file info
50
     */
51
    public $infofiles; // Used to return information by function getDocumentsLink
52
53
54
    /**
55
     * Constructor
56
     *
57
     * @param DoliDB $db Database handler
58
     */
59
    public function __construct($db)
60
    {
61
        $this->db = $db;
62
    }
63
64
    /**
65
     * Html for input with label
66
     *
67
     * @param   string  $type           Type of input : button, checkbox, color, email, hidden, month, number, password, radio, range, tel, text, time, url, week
68
     * @param   string  $name           Name
69
     * @param   string  $value          [=''] Value
70
     * @param   string  $id             [=''] Id
71
     * @param   string  $morecss        [=''] Class
72
     * @param   string  $moreparam      [=''] Add attributes (checked, required, etc)
73
     * @param   string  $label          [=''] Label
74
     * @param   string  $addInputLabel  [=''] Add label for input
75
     * @return  string  Html for input with label
76
     */
77
    public function inputType($type, $name, $value = '', $id = '', $morecss = '', $moreparam = '', $label = '', $addInputLabel = '')
78
    {
79
        $out = '';
80
        if ($label != '') {
81
            $out .= '<label for="' . $id . '">';
82
        }
83
        $out .= '<input type="' . $type . '"';
84
        $out .= ($morecss ? ' class="' . $morecss . '"' : '');
85
        if ($id != '') {
86
            $out .= ' id="' . $id . '"';
87
        }
88
        $out .= ' name="' . $name . '"';
89
        $out .= ' value="' . $value . '"';
90
        $out .= ($moreparam ? ' ' . $moreparam : '');
91
        $out .= ' />' . $addInputLabel;
92
        if ($label != '') {
93
            $out .= $label . '</label>';
94
        }
95
96
        return $out;
97
    }
98
99
    /**
100
     * Input for date
101
     *
102
     * @param   string  $name           Name of html input
103
     * @param   string  $value          [=''] Value of input (format : YYYY-MM-DD)
104
     * @param   string  $placeholder    [=''] Placeholder for input (keep empty for no label)
105
     * @param   string  $id             [=''] Id
106
     * @param   string  $morecss        [=''] Class
107
     * @param   string  $moreparam      [=''] Add attributes (checked, required, etc)
108
     * @return  string  Html for input date
109
     */
110
    public function inputDate($name, $value = '', $placeholder = '', $id = '', $morecss = '', $moreparam = '')
111
    {
112
        $out = '';
113
114
        $out .= '<input';
115
        if ($placeholder != '' && $value == '') {
116
            // to show a placeholder on date input
117
            $out .= ' type="text" placeholder="' . $placeholder . '" onfocus="(this.type=\'date\')"';
118
        } else {
119
            $out .= ' type="date"';
120
        }
121
        $out .= ($morecss ? ' class="' . $morecss . '"' : '');
122
        if ($id != '') {
123
            $out .= ' id="' . $id . '"';
124
        }
125
        $out .= ' name="' . $name . '"';
126
        $out .= ' value="' . $value . '"';
127
        $out .= ($moreparam ? ' ' . $moreparam : '');
128
129
        $out .= '>';
130
131
        return $out;
132
    }
133
134
    /**
135
     * Return a HTML select string, built from an array of key+value.
136
     * Note: Do not apply langs->trans function on returned content, content may be entity encoded twice.
137
     *
138
     * @param   string              $htmlname               Name of html select area.
139
     * @param   array               $array                  Array like array(key => value) or array(key=>array('label'=>..., 'data-...'=>..., 'disabled'=>..., 'css'=>...))
140
     * @param   string|string[]     $id                     Preselected key or preselected keys for multiselect. Use 'ifone' to autoselect record if there is only one record.
141
     * @param   int|string          $show_empty             0 no empty value allowed, 1 or string to add an empty value into list (If 1: key is -1 and value is '' or '&nbsp;', If placeholder string: key is -1 and value is the string), <0 to add an empty value with key that is this value.
142
     * @param   int                 $key_in_label           1 to show key into label with format "[key] value"
143
     * @param   int                 $value_as_key           1 to use value as key
144
     * @param   string              $moreparam              Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container
145
     * @param   int                 $translate              1=Translate and encode value
146
     * @param   int                 $maxlen                 Length maximum for labels
147
     * @param   int                 $disabled               Html select box is disabled
148
     * @param   string              $sort                   'ASC' or 'DESC' = Sort on label, '' or 'NONE' or 'POS' = Do not sort, we keep original order
149
     * @param   string              $morecss                Add more class to css styles
150
     * @param   int                 $addjscombo             Add js combo
151
     * @param   string              $moreparamonempty       Add more param on the empty option line. Not used if show_empty not set
152
     * @param   int                 $disablebademail        1=Check if a not valid email, 2=Check string '---', and if found into value, disable and colorize entry
153
     * @param   int                 $nohtmlescape           No html escaping.
154
     * @return  string              HTML select string.
155
     */
156
    public static function selectarray($htmlname, $array, $id = '', $show_empty = 0, $key_in_label = 0, $value_as_key = 0, $moreparam = '', $translate = 0, $maxlen = 0, $disabled = 0, $sort = '', $morecss = 'minwidth75', $addjscombo = 1, $moreparamonempty = '', $disablebademail = 0, $nohtmlescape = 0)
157
    {
158
        global $langs;
159
160
        if ($value_as_key) {
161
            $array = array_combine($array, $array);
162
        }
163
164
        $out = '';
165
166
        $idname = str_replace(array('[', ']'), array('', ''), $htmlname);
167
        $out .= '<select id="' . preg_replace('/^\./', '', $idname) . '"' . ($disabled ? ' disabled="disabled"' : '') . ' class="' . ($morecss ? ' ' . $morecss : '') . '"';
168
        $out .= ' name="' . preg_replace('/^\./', '', $htmlname) . '"' . ($moreparam ? ' ' . $moreparam : '');
169
        $out .= '>' . "\n";
170
171
        if ($show_empty) {
172
            $textforempty = ' ';
173
            if (!is_numeric($show_empty)) {
174
                $textforempty = $show_empty;
175
            }
176
            $out .= '<option value="' . ($show_empty < 0 ? $show_empty : -1) . '"' . ($id == $show_empty ? ' selected' : '') . '>' . $textforempty . '</option>' . "\n";
177
        }
178
179
        if (is_array($array)) {
180
            // Translate
181
            if ($translate) {
182
                foreach ($array as $key => $value) {
183
                    if (!is_array($value)) {
184
                        $array[$key] = $langs->trans($value);
185
                    } else {
186
                        $array[$key]['label'] = $langs->trans($value['label']);
187
                    }
188
                }
189
            }
190
191
            // Sort
192
            if ($sort == 'ASC') {
193
                asort($array);
194
            } elseif ($sort == 'DESC') {
195
                arsort($array);
196
            }
197
198
            foreach ($array as $key => $tmpvalue) {
199
                if (is_array($tmpvalue)) {
200
                    $value = $tmpvalue['label'];
201
                    $disabled = empty($tmpvalue['disabled']) ? '' : ' disabled';
202
                } else {
203
                    $value = $tmpvalue;
204
                    $disabled = '';
205
                }
206
207
                if ($key_in_label) {
208
                    $selectOptionValue = dol_escape_htmltag($key . ' - ' . ($maxlen ? dol_trunc($value, $maxlen) : $value));
209
                } else {
210
                    $selectOptionValue = dol_escape_htmltag($maxlen ? dol_trunc($value, $maxlen) : $value);
211
                    if ($value == '' || $value == '-') {
212
                        $selectOptionValue = '&nbsp;';
213
                    }
214
                }
215
216
                $out .= '<option value="' . $key . '"';
217
                $out .= $disabled;
218
                if (is_array($id)) {
219
                    if (in_array($key, $id) && !$disabled) {
220
                        $out .= ' selected'; // To preselect a value
221
                    }
222
                } else {
223
                    $id = (string) $id; // if $id = 0, then $id = '0'
224
                    if ($id != '' && ($id == $key || ($id == 'ifone' && count($array) == 1)) && !$disabled) {
225
                        $out .= ' selected'; // To preselect a value
226
                    }
227
                }
228
                if (is_array($tmpvalue)) {
229
                    foreach ($tmpvalue as $keyforvalue => $valueforvalue) {
230
                        if (preg_match('/^data-/', $keyforvalue)) {
231
                            $out .= ' ' . $keyforvalue . '="' . dol_escape_htmltag($valueforvalue) . '"';
232
                        }
233
                    }
234
                }
235
                $out .= '>';
236
                $out .= $selectOptionValue;
237
                $out .= "</option>\n";
238
            }
239
        }
240
241
        $out .= "</select>";
242
243
        return $out;
244
    }
245
246
    /**
247
     * Show a Document icon with link(s)
248
     * You may want to call this into a div like this:
249
     * print '<div class="inline-block valignmiddle">'.$formfile->getDocumentsLink($element_doc, $filename, $filedir).'</div>';
250
     *
251
     * @param string $modulepart 'propal', 'facture', 'facture_fourn', ...
252
     * @param string $modulesubdir Sub-directory to scan (Example: '0/1/10', 'FA/DD/MM/YY/9999'). Use '' if file is not into subdir of module.
253
     * @param string $filedir Full path to directory to scan
254
     * @param string $filter Filter filenames on this regex string (Example: '\.pdf$')
255
     * @param string $morecss Add more css to the download picto
256
     * @param int    $allfiles 0=Only generated docs, 1=All files
257
     * @return    string                Output string with HTML link of documents (might be empty string). This also fill the array ->infofiles
258
     */
259
    public function getDocumentsLink($modulepart, $modulesubdir, $filedir, $filter = '', $morecss = '', $allfiles = 0)
260
    {
261
        include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
262
263
        $out = '';
264
265
        $context = Context::getInstance();
266
        if (!$context) {
267
            return '';
268
        }
269
270
        $this->infofiles = array('nboffiles' => 0, 'extensions' => array(), 'files' => array());
271
272
        $entity = 1; // Without multicompany
273
274
        // Get object entity
275
        if (isModEnabled('multicompany')) {
276
            $regs = array();
277
            preg_match('/\/([0-9]+)\/[^\/]+\/' . preg_quote($modulesubdir, '/') . '$/', $filedir, $regs);
278
            $entity = ((!empty($regs[1]) && $regs[1] > 1) ? $regs[1] : 1); // If entity id not found in $filedir this is entity 1 by default
279
        }
280
281
        // Get list of files starting with name of ref (Note: files with '^ref\.extension' are generated files, files with '^ref-...' are uploaded files)
282
        if ($allfiles || getDolGlobalString('MAIN_SHOW_ALL_FILES_ON_DOCUMENT_TOOLTIP')) {
283
            $filterforfilesearch = '^' . preg_quote(basename($modulesubdir), '/');
284
        } else {
285
            $filterforfilesearch = '^' . preg_quote(basename($modulesubdir), '/') . '\.';
286
        }
287
        $file_list = dol_dir_list($filedir, 'files', 0, $filterforfilesearch, '\.meta$|\.png$'); // We also discard .meta and .png preview
288
289
        //var_dump($file_list);
290
        // For ajax treatment
291
        $out .= '<!-- html.formwebportal::getDocumentsLink -->' . "\n";
292
        if (!empty($file_list)) {
293
            $tmpout = '';
294
295
            // Loop on each file found
296
            $found = 0;
297
            $i = 0;
298
            foreach ($file_list as $file) {
299
                $i++;
300
                if ($filter && !preg_match('/' . $filter . '/i', $file["name"])) {
301
                    continue; // Discard this. It does not match provided filter.
302
                }
303
304
                $found++;
305
                // Define relative path for download link (depends on module)
306
                $relativepath = $file["name"]; // Cas general
307
                if ($modulesubdir) {
308
                    $relativepath = $modulesubdir . "/" . $file["name"]; // Cas propal, facture...
309
                }
310
                // Autre cas
311
                if ($modulepart == 'donation') {
312
                    $relativepath = get_exdir($modulesubdir, 2, 0, 0, null, 'donation') . $file["name"];
313
                }
314
                if ($modulepart == 'export') {
315
                    $relativepath = $file["name"];
316
                }
317
318
                $this->infofiles['nboffiles']++;
319
                $this->infofiles['files'][] = $file['fullname'];
320
                $ext = pathinfo($file["name"], PATHINFO_EXTENSION);
321
                if (empty($this->infofiles[$ext])) {
322
                    $this->infofiles['extensions'][$ext] = 1;
323
                } else {
324
                    $this->infofiles['extensions'][$ext]++;
325
                }
326
327
                // Download
328
                $url = $context->getControllerUrl('document') . '&modulepart=' . $modulepart . '&entity=' . $entity . '&file=' . urlencode($relativepath) . '&soc_id=' . $context->logged_thirdparty->id;
329
                $tmpout .= '<a href="' . $url . '"' . ($morecss ? ' class="' . $morecss . '"' : '') . ' role="downloadlink"';
330
                $mime = dol_mimetype($relativepath, '', 0);
331
                if (preg_match('/text/', $mime)) {
332
                    $tmpout .= ' target="_blank" rel="noopener noreferrer"';
333
                }
334
                $tmpout .= '>';
335
                $tmpout .= img_mime($relativepath, $file["name"]);
336
                $tmpout .= strtoupper($ext);
337
                $tmpout .= '</a>';
338
            }
339
340
            if ($found) {
341
                $out .= $tmpout;
342
            }
343
        }
344
345
        return $out;
346
    }
347
348
    /**
349
     * Show a Signature icon with link
350
     * You may want to call this into a div like this:
351
     * print '<div class="inline-block valignmiddle">'.$formfile->getDocumentsLink($element_doc, $filename, $filedir).'</div>';
352
     *
353
     * @param string $modulepart 'proposal', 'facture', 'facture_fourn', ...
354
     * @param Object $object Object linked to the document to be signed
355
     * @param string $morecss Add more css to the download picto
356
     * @return    string                Output string with HTML link of signature (might be empty string).
357
     */
358
    public function getSignatureLink($modulepart, $object, $morecss = '')
359
    {
360
        global $langs;
361
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/signature.lib.php';
362
        $out = '<!-- html.formwebportal::getSignatureLink -->' . "\n";
363
        $url = getOnlineSignatureUrl(0, $modulepart, $object->ref, 1, $object);
364
        if (!empty($url)) {
365
            $out .= '<a target="_blank" rel="noopener noreferrer" href="' . $url . '"' . ($morecss ? ' class="' . $morecss . '"' : '') . ' role="signaturelink">';
366
            $out .= '<i class="fa fa-file-signature"></i>';
367
            $out .= $langs->trans("Sign");
368
            $out .= '</a>';
369
        }
370
        return $out;
371
    }
372
373
    /**
374
     * Generic method to select a component from a combo list.
375
     * Can use autocomplete with ajax after x key pressed or a full combo, depending on setup.
376
     * This is the generic method that will replace all specific existing methods.
377
     *
378
     * @param   string  $objectdesc             'ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]'. For hard coded custom needs. Try to prefer method using $objectfield instead of $objectdesc.
379
     * @param   string  $htmlname               Name of HTML select component
380
     * @param   int     $preselectedvalue       Preselected value (ID of element)
381
     * @param   string  $showempty              ''=empty values not allowed, 'string'=value show if we allow empty values (for example 'All', ...)
382
     * @param   string  $searchkey              Search criteria
383
     * @param   string  $placeholder            Place holder
384
     * @param   string  $morecss                More CSS
385
     * @param   string  $moreparams             More params provided to ajax call
386
     * @param   int     $forcecombo             Force to load all values and output a standard combobox (with no beautification)
387
     * @param   int     $disabled               1=Html component is disabled
388
     * @param   string  $selected_input_value   Value of preselected input text (for use with ajax)
389
     * @param   string  $objectfield            Object:Field that contains the definition (in table $fields or $extrafields). Example: 'Object:xxx' or 'Module_Object:xxx' or 'Object:options_xxx' or 'Module_Object:options_xxx'
390
     * @return  string                          Return HTML string
391
     * @see selectForFormsList(), select_thirdparty_list()
392
     */
393
    public function selectForForms($objectdesc, $htmlname, $preselectedvalue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0, $disabled = 0, $selected_input_value = '', $objectfield = '')
394
    {
395
        global $conf;
396
397
        $objecttmp = null;
398
399
        // Example of value for $objectdec:
400
        // Bom:bom/class/bom.class.php:0:t.status=1
401
        // Bom:bom/class/bom.class.php:0:t.status=1:ref
402
        // Bom:bom/class/bom.class.php:0:(t.status:=:1):ref
403
        $InfoFieldList = explode(":", $objectdesc, 4);
404
        $vartmp = (empty($InfoFieldList[3]) ? '' : $InfoFieldList[3]);
405
        $reg = array();
406
        if (preg_match('/^.*:(\w*)$/', $vartmp, $reg)) {
407
            $InfoFieldList[4] = $reg[1];    // take the sort field
408
        }
409
        $InfoFieldList[3] = preg_replace('/:\w*$/', '', $vartmp);    // take the filter field
410
411
        $classname = $InfoFieldList[0];
412
        $classpath = $InfoFieldList[1];
413
        $filter = empty($InfoFieldList[3]) ? '' : $InfoFieldList[3];
414
        $sortfield = empty($InfoFieldList[4]) ? '' : $InfoFieldList[4];
415
416
        if (!empty($classpath)) {
417
            dol_include_once($classpath);
418
419
            if ($classname && class_exists($classname)) {
420
                $objecttmp = new $classname($this->db);
421
422
                // Make some replacement
423
                $sharedentities = getEntity(strtolower($classname));
424
                $filter = str_replace(
425
                    array('__ENTITY__', '__SHARED_ENTITIES__'),
426
                    array($conf->entity, $sharedentities),
427
                    $filter
428
                );
429
            }
430
        }
431
        if (!is_object($objecttmp)) {
432
            dol_syslog('Error bad setup of type for field ' . implode(',', $InfoFieldList), LOG_WARNING);
433
            return 'Error bad setup of type for field ' . implode(',', $InfoFieldList);
434
        }
435
436
        dol_syslog(__METHOD__ . ' filter=' . $filter, LOG_DEBUG);
437
        $out = '';
438
        // Immediate load of table record.
439
        $out .= $this->selectForFormsList($objecttmp, $htmlname, $preselectedvalue, $showempty, $searchkey, $placeholder, $morecss, $moreparams, $forcecombo, 0, $disabled, $sortfield, $filter);
440
441
        return $out;
442
    }
443
444
    /**
445
     * Output html form to select an object.
446
     * Note, this function is called by selectForForms or by ajax selectobject.php
447
     *
448
     * @param Object        $objecttmp          Object to know the table to scan for combo.
449
     * @param string        $htmlname           Name of HTML select component
450
     * @param int           $preselectedvalue   Preselected value (ID of element)
451
     * @param string        $showempty          ''=empty values not allowed, 'string'=value show if we allow empty values (for example 'All', ...)
452
     * @param string        $searchkey          Search value
453
     * @param string        $placeholder        Place holder
454
     * @param string        $morecss            More CSS
455
     * @param string        $moreparams         More params provided to ajax call
456
     * @param int           $forcecombo         Force to load all values and output a standard combobox (with no beautification)
457
     * @param int           $outputmode         0=HTML select string, 1=Array
458
     * @param int           $disabled           1=Html component is disabled
459
     * @param string        $sortfield          Sort field
460
     * @param string        $filter             Add more filter (Universal Search Filter)
461
     * @return string|array                     Return HTML string
462
     * @see selectForForms()
463
     */
464
    public function selectForFormsList($objecttmp, $htmlname, $preselectedvalue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0, $outputmode = 0, $disabled = 0, $sortfield = '', $filter = '')
465
    {
466
        global $conf, $langs, $hookmanager;
467
468
        $prefixforautocompletemode = $objecttmp->element;
469
        if ($prefixforautocompletemode == 'societe') {
470
            $prefixforautocompletemode = 'company';
471
        }
472
        $confkeyforautocompletemode = strtoupper($prefixforautocompletemode) . '_USE_SEARCH_TO_SELECT'; // For example COMPANY_USE_SEARCH_TO_SELECT
473
474
        if (in_array($objecttmp->element, array('adherent_type'))) {
475
            $fieldstoshow = 't.libelle';
476
        }
477
        if (!empty($objecttmp->fields)) {    // For object that declare it, it is better to use declared fields (like societe, contact, ...)
478
            $tmpfieldstoshow = '';
479
            foreach ($objecttmp->fields as $key => $val) {
480
                if (! (int) dol_eval($val['enabled'], 1, 1, '1')) {
481
                    continue;
482
                }
483
                if (!empty($val['showoncombobox'])) {
484
                    $tmpfieldstoshow .= ($tmpfieldstoshow ? ',' : '') . 't.' . $key;
485
                }
486
            }
487
            if ($tmpfieldstoshow) {
488
                $fieldstoshow = $tmpfieldstoshow;
489
            }
490
        } elseif (!in_array($objecttmp->element, array('adherent_type'))) {
491
            // For backward compatibility
492
            $objecttmp->fields['ref'] = array('type' => 'varchar(30)', 'label' => 'Ref', 'showoncombobox' => 1);
493
        }
494
495
        if (empty($fieldstoshow)) {
496
            if (isset($objecttmp->fields['ref'])) {
497
                $fieldstoshow = 't.ref';
498
            } else {
499
                $langs->load("errors");
500
                $this->error = $langs->trans("ErrorNoFieldWithAttributeShowoncombobox");
501
                return $langs->trans('ErrorNoFieldWithAttributeShowoncombobox');
502
            }
503
        }
504
505
        $out = '';
506
        $outarray = array();
507
        $tmparray = array();
508
509
        $num = 0;
510
511
        // Search data
512
        $sql = "SELECT t.rowid, " . $fieldstoshow . " FROM " . $this->db->prefix() . $objecttmp->table_element . " as t";
513
        if (isset($objecttmp->ismultientitymanaged)) {
514
            if (!is_numeric($objecttmp->ismultientitymanaged)) {
515
                $tmparray = explode('@', $objecttmp->ismultientitymanaged);
516
                $sql .= " INNER JOIN " . $this->db->prefix() . $tmparray[1] . " as parenttable ON parenttable.rowid = t." . $tmparray[0];
517
            }
518
        }
519
520
        // Add where from hooks
521
        $parameters = array(
522
            'object' => $objecttmp,
523
            'htmlname' => $htmlname,
524
            'filter' => $filter,
525
            'searchkey' => $searchkey
526
        );
527
528
        $reshook = $hookmanager->executeHooks('selectForFormsListWhere', $parameters); // Note that $action and $object may have been modified by hook
529
        if (!empty($hookmanager->resPrint)) {
530
            $sql .= $hookmanager->resPrint;
531
        } else {
532
            $sql .= " WHERE 1=1";
533
            if (isset($objecttmp->ismultientitymanaged)) {
534
                if ($objecttmp->ismultientitymanaged == 1) {
535
                    $sql .= " AND t.entity IN (" . getEntity($objecttmp->table_element) . ")";
536
                }
537
                if (!is_numeric($objecttmp->ismultientitymanaged)) {
538
                    $sql .= " AND parenttable.entity = t." . $tmparray[0];
539
                }
540
            }
541
            if ($searchkey != '') {
542
                $sql .= natural_search(explode(',', $fieldstoshow), $searchkey);
543
            }
544
545
            if ($filter) {     // Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
546
                $errormessage = '';
547
                $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
548
                if ($errormessage) {
549
                    return 'Error forging a SQL request from an universal criteria: ' . $errormessage;
550
                }
551
            }
552
        }
553
        $sql .= $this->db->order($sortfield ? $sortfield : $fieldstoshow, "ASC");
554
555
        // Build output string
556
        $resql = $this->db->query($sql);
557
        if ($resql) {
558
            // Construct $out and $outarray
559
            $out .= '<select id="' . $htmlname . '" class="' . ($morecss ? ' ' . $morecss : '') . '"' . ($disabled ? ' disabled="disabled"' : '') . ($moreparams ? ' ' . $moreparams : '') . ' name="' . $htmlname . '">' . "\n";
560
561
            // Warning: Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'. Seems it is no more true with selec2 v4
562
            $textifempty = '&nbsp;';
563
564
            //if (!empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
565
            if (!empty($conf->global->$confkeyforautocompletemode)) {
566
                if ($showempty && !is_numeric($showempty)) {
567
                    $textifempty = $langs->trans($showempty);
568
                } else {
569
                    $textifempty .= $langs->trans("All");
570
                }
571
            }
572
            if ($showempty) {
573
                $out .= '<option value="-1">' . $textifempty . '</option>' . "\n";
574
            }
575
576
            $num = $this->db->num_rows($resql);
577
            $i = 0;
578
            if ($num) {
579
                while ($i < $num) {
580
                    $obj = $this->db->fetch_object($resql);
581
                    $label = '';
582
                    $labelhtml = '';
583
                    $tmparray = explode(',', $fieldstoshow);
584
                    $oldvalueforshowoncombobox = 0;
585
                    foreach ($tmparray as $key => $val) {
586
                        $val = preg_replace('/t\./', '', $val);
587
                        $label .= (($label && $obj->$val) ? ($oldvalueforshowoncombobox != $objecttmp->fields[$val]['showoncombobox'] ? ' - ' : ' ') : '');
588
                        $labelhtml .= (($label && $obj->$val) ? ($oldvalueforshowoncombobox != $objecttmp->fields[$val]['showoncombobox'] ? ' - ' : ' ') : '');
589
                        $label .= $obj->$val;
590
                        $labelhtml .= $obj->$val;
591
592
                        $oldvalueforshowoncombobox = empty($objecttmp->fields[$val]['showoncombobox']) ? 0 : $objecttmp->fields[$val]['showoncombobox'];
593
                    }
594
                    if (empty($outputmode)) {
595
                        if ($preselectedvalue > 0 && $preselectedvalue == $obj->rowid) {
596
                            $out .= '<option value="' . $obj->rowid . '" selected data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
597
                        } else {
598
                            $out .= '<option value="' . $obj->rowid . '" data-html="' . dol_escape_htmltag($labelhtml, 0, 0, '', 0, 1) . '">' . dol_escape_htmltag($label, 0, 0, '', 0, 1) . '</option>';
599
                        }
600
                    } else {
601
                        array_push($outarray, array('key' => $obj->rowid, 'value' => $label, 'label' => $label));
602
                    }
603
604
                    $i++;
605
                    if (($i % 10) == 0) {
606
                        $out .= "\n";
607
                    }
608
                }
609
            }
610
611
            $out .= '</select>' . "\n";
612
        } else {
613
            dol_print_error($this->db);
614
        }
615
616
        $this->result = array('nbofelement' => $num);
617
618
        if ($outputmode) {
619
            return $outarray;
620
        }
621
622
        return $out;
623
    }
624
625
    /**
626
     * Return HTML string to put an input field into a page
627
     * Code very similar with showInputField for common object
628
     *
629
     * @param array|null    $val            Array of properties for field to show
630
     * @param string        $key            Key of attribute
631
     * @param string|array  $value          Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value, for array type must be array)
632
     * @param string        $moreparam      To add more parameters on html input tag
633
     * @param string        $keysuffix      Prefix string to add into name and id of field (can be used to avoid duplicate names)
634
     * @param string        $keyprefix      Suffix string to add into name and id of field (can be used to avoid duplicate names)
635
     * @param string        $morecss        Value for css to define style/length of field. May also be a numeric.
636
     * @return string
637
     */
638
    public function showInputField($val, $key, $value, $moreparam = '', $keysuffix = '', $keyprefix = '', $morecss = '')
639
    {
640
        global $conf, $langs;
641
642
        $out = '';
643
        $param = array();
644
        $reg = array();
645
        $size = !empty($val['size']) ? $val['size'] : 0;
646
        // see common object class
647
        if (preg_match('/^(integer|link):(.*):(.*):(.*):(.*)/i', $val['type'], $reg)) {
648
            $param['options'] = array($reg[2] . ':' . $reg[3] . ':' . $reg[4] . ':' . $reg[5] => 'N');
649
            $type = 'link';
650
        } elseif (preg_match('/^(integer|link):(.*):(.*):(.*)/i', $val['type'], $reg)) {
651
            $param['options'] = array($reg[2] . ':' . $reg[3] . ':' . $reg[4] => 'N');
652
            $type = 'link';
653
        } elseif (preg_match('/^(integer|link):(.*):(.*)/i', $val['type'], $reg)) {
654
            $param['options'] = array($reg[2] . ':' . $reg[3] => 'N');
655
            $type = 'link';
656
        } elseif (preg_match('/^(sellist):(.*):(.*):(.*):(.*)/i', $val['type'], $reg)) {
657
            $param['options'] = array($reg[2] . ':' . $reg[3] . ':' . $reg[4] . ':' . $reg[5] => 'N');
658
            $type = 'sellist';
659
        } elseif (preg_match('/^(sellist):(.*):(.*):(.*)/i', $val['type'], $reg)) {
660
            $param['options'] = array($reg[2] . ':' . $reg[3] . ':' . $reg[4] => 'N');
661
            $type = 'sellist';
662
        } elseif (preg_match('/^(sellist):(.*):(.*)/i', $val['type'], $reg)) {
663
            $param['options'] = array($reg[2] . ':' . $reg[3] => 'N');
664
            $type = 'sellist';
665
        } elseif (preg_match('/^varchar\((\d+)\)/', $val['type'], $reg)) {
666
            $param['options'] = array();
667
            $type = 'text';
668
            $size = $reg[1];
669
        } elseif (preg_match('/^varchar/', $val['type'])) {
670
            $param['options'] = array();
671
            $type = 'text';
672
        } elseif (preg_match('/^double(\([0-9],[0-9]\)){0,1}/', $val['type'])) {
673
            $param['options'] = array();
674
            $type = 'double';
675
        } else {
676
            $param['options'] = array();
677
            $type = $val['type'];
678
        }
679
680
        // Special case that force options and type ($type can be integer, varchar, ...)
681
        if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
682
            $param['options'] = $val['arrayofkeyval'];
683
            $type = $val['type'] == 'checkbox' ? 'checkbox' : 'select';
684
        }
685
686
        //$label = $val['label'];
687
        $default = (!empty($val['default']) ? $val['default'] : '');
688
        $computed = (!empty($val['computed']) ? $val['computed'] : '');
689
        //$unique = (!empty($val['unique']) ? $val['unique'] : 0);
690
        $required = (!empty($val['required']) ? $val['required'] : 0);
691
        $notNull = (!empty($val['notnull']) ? $val['notnull'] : 0);
692
693
        //$langfile = (!empty($val['langfile']) ? $val['langfile'] : '');
694
        //$list = (!empty($val['list']) ? $val[$key]['list'] : 0);
695
        $hidden = (in_array(abs($val['visible']), array(0, 2)) ? 1 : 0);
696
697
        //$objectid = $this->id;
698
699
        if ($computed) {
700
            if (!preg_match('/^search_/', $keyprefix)) {
701
                return '<span>' . $langs->trans("AutomaticallyCalculated") . '</span>';
702
            } else {
703
                return '';
704
            }
705
        }
706
707
        // Set value of $morecss. For this, we use in priority showsize from parameters, then $val['css'] then autodefine
708
        if (empty($morecss) && !empty($val['css'])) {
709
            $morecss = $val['css'];
710
        }
711
712
        $htmlName = $keyprefix . $key . $keysuffix;
713
        $htmlId = $htmlName;
714
        //$moreparam .= (!empty($required)  ? ' required' : '');
715
        switch ($type) {
716
            case 'date':
717
            case 'datetime':
718
                // separate value YYYY-MM-DD HH:ii:ss to date and time
719
                $valueDate = '';
720
                $valueTime = '';
721
                $dateArr = explode(' ', $value);
722
                if (count($dateArr) > 0) {
723
                    $valueDate = $dateArr[0];
724
                    if (isset($dateArr[1])) {
725
                        $valueTime = $dateArr[1];
726
                    }
727
                }
728
                $out = $this->inputDate($htmlName, $valueDate, '', $htmlId, $morecss, $moreparam);
729
730
                if ($type == 'datetime') {
731
                    //$moreparam .= ' step="1"'; to show seconds
732
                    $out .= ' ' . $this->inputType('time', $htmlName . '_time', $valueTime, $htmlId, $morecss, $moreparam);
733
                }
734
                break;
735
736
            case 'integer':
737
                $out = $this->inputType('number', $htmlName, dol_escape_htmltag($value), $htmlId, $morecss, $moreparam);
738
                break;
739
740
            case 'text':
741
            case 'html':
742
                $moreparam .= ($size > 0 ? ' maxlength="' . $size . '"' : '');
743
                $out = $this->inputType('text', $htmlName, dol_escape_htmltag($value), $htmlId, $morecss, $moreparam);
744
                break;
745
746
            case 'email':
747
                $out = $this->inputType('email', $htmlName, dol_escape_htmltag($value), $htmlId, $morecss, $moreparam);
748
                break;
749
750
            case 'tel':
751
                $out = $this->inputType('tel', $htmlName, dol_escape_htmltag($value), $htmlId, $morecss, $moreparam);
752
                break;
753
754
            case 'url':
755
                $out = $this->inputType('url', $htmlName, dol_escape_htmltag($value), $htmlId, $morecss, $moreparam);
756
                break;
757
758
            case 'price':
759
                if (!empty($value)) {
760
                    $value = price($value); // $value in memory is a php numeric, we format it into user number format.
761
                }
762
                $addInputLabel = ' ' . $langs->getCurrencySymbol($conf->currency);
763
                $out = $this->inputType('text', $htmlName, $value, $htmlId, $morecss, $moreparam, '', $addInputLabel);
764
                break;
765
766
            case 'double':
767
                if (!empty($value)) {
768
                    $value = price($value); // $value in memory is a php numeric, we format it into user number format.
769
                }
770
                $out = $this->inputType('text', $htmlName, $value, $htmlId, $morecss, $moreparam);
771
                break;
772
773
            case 'password':
774
                $out = $this->inputType('password', $htmlName, $value, $htmlId, $morecss, $moreparam);
775
                break;
776
777
            case 'radio':
778
                foreach ($param['options'] as $keyopt => $valopt) {
779
                    $htmlId = $htmlName . '_' . $keyopt;
780
                    $htmlMoreParam = $moreparam . ($value == $keyopt ? ' checked' : '');
781
                    $out .= $this->inputType('radio', $htmlName, $keyopt, $htmlId, $morecss, $htmlMoreParam, $valopt) . '<br>';
782
                }
783
                break;
784
785
            case 'select':
786
                $out = '<select class="' . $morecss . '" name="' . $htmlName . '" id="' . $htmlId . '"' . ($moreparam ? ' ' . $moreparam : '') . ' >';
787
                if ($default == '' || $notNull != 1) {
788
                    $out .= '<option value="0">&nbsp;</option>';
789
                }
790
                foreach ($param['options'] as $keyb => $valb) {
791
                    if ($keyb == '') {
792
                        continue;
793
                    }
794
                    if (strpos($valb, "|") !== false) {
795
                        list($valb, $parent) = explode('|', $valb);
796
                    }
797
                    $out .= '<option value="' . $keyb . '"';
798
                    $out .= (((string) $value == $keyb) ? ' selected' : '');
799
                    $out .= (!empty($parent) ? ' parent="' . $parent . '"' : '');
800
                    $out .= '>' . $valb . '</option>';
801
                }
802
                $out .= '</select>';
803
                break;
804
            case 'sellist':
805
                $out = '<select class="' . $morecss . '" name="' . $htmlName . '" id="' . $htmlId . '"' . ($moreparam ? ' ' . $moreparam : '') . '>';
806
807
                $param_list = array_keys($param['options']);
808
                $InfoFieldList = explode(":", $param_list[0]);
809
                $parentName = '';
810
                $parentField = '';
811
                // 0 : tableName
812
                // 1 : label field name
813
                // 2 : key fields name (if differ of rowid)
814
                // 3 : key field parent (for dependent lists)
815
                // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value
816
                // 5 : id category type
817
                // 6 : ids categories list separated by comma for category root
818
                $keyList = (empty($InfoFieldList[2]) ? 'rowid' : $InfoFieldList[2] . ' as rowid');
819
820
                if (count($InfoFieldList) > 4 && !empty($InfoFieldList[4])) {
821
                    if (strpos($InfoFieldList[4], 'extra.') !== false) {
822
                        $keyList = 'main.' . $InfoFieldList[2] . ' as rowid';
823
                    } else {
824
                        $keyList = $InfoFieldList[2] . ' as rowid';
825
                    }
826
                }
827
                if (count($InfoFieldList) > 3 && !empty($InfoFieldList[3])) {
828
                    list($parentName, $parentField) = explode('|', $InfoFieldList[3]);
829
                    $keyList .= ', ' . $parentField;
830
                }
831
832
                $filter_categorie = false;
833
                if (count($InfoFieldList) > 5) {
834
                    if ($InfoFieldList[0] == 'categorie') {
835
                        $filter_categorie = true;
836
                    }
837
                }
838
839
                if ($filter_categorie === false) {
840
                    $fields_label = explode('|', $InfoFieldList[1]);
841
                    if (is_array($fields_label)) {
842
                        $keyList .= ', ';
843
                        $keyList .= implode(', ', $fields_label);
844
                    }
845
846
                    $sqlwhere = '';
847
                    $sql = "SELECT " . $keyList;
848
                    $sql .= " FROM " . $this->db->prefix() . $InfoFieldList[0];
849
                    if (!empty($InfoFieldList[4])) {
850
                        // can use SELECT request
851
                        if (strpos($InfoFieldList[4], '$SEL$') !== false) {
852
                            $InfoFieldList[4] = str_replace('$SEL$', 'SELECT', $InfoFieldList[4]);
853
                        }
854
855
                        // current object id can be use into filter
856
                        $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
857
858
                        //We have to join on extrafield table
859
                        if (strpos($InfoFieldList[4], 'extra') !== false) {
860
                            $sql .= " as main, " . $this->db->prefix() . $InfoFieldList[0] . "_extrafields as extra";
861
                            $sqlwhere .= " WHERE extra.fk_object=main." . $InfoFieldList[2] . " AND " . $InfoFieldList[4];
862
                        } else {
863
                            $sqlwhere .= " WHERE " . $InfoFieldList[4];
864
                        }
865
                    } else {
866
                        $sqlwhere .= ' WHERE 1=1';
867
                    }
868
                    // Some tables may have field, some other not. For the moment we disable it.
869
                    if (in_array($InfoFieldList[0], array('tablewithentity'))) {
870
                        $sqlwhere .= " AND entity = " . ((int) $conf->entity);
871
                    }
872
                    $sql .= $sqlwhere;
873
                    //print $sql;
874
875
                    $sql .= ' ORDER BY ' . implode(', ', $fields_label);
876
877
                    dol_syslog(get_class($this) . '::showInputField type=sellist', LOG_DEBUG);
878
                    $resql = $this->db->query($sql);
879
                    if ($resql) {
880
                        $out .= '<option value="0">&nbsp;</option>';
881
                        $num = $this->db->num_rows($resql);
882
                        $i = 0;
883
                        while ($i < $num) {
884
                            $labeltoshow = '';
885
                            $obj = $this->db->fetch_object($resql);
886
887
                            // Several field into label (eq table:code|libelle:rowid)
888
                            $notrans = false;
889
                            $fields_label = explode('|', $InfoFieldList[1]);
890
                            if (count($fields_label) > 1) {
891
                                $notrans = true;
892
                                foreach ($fields_label as $field_toshow) {
893
                                    $labeltoshow .= $obj->$field_toshow . ' ';
894
                                }
895
                            } else {
896
                                $labeltoshow = $obj->{$InfoFieldList[1]};
897
                            }
898
                            $labeltoshow = dol_trunc($labeltoshow, 45);
899
900
                            if ($value == $obj->rowid) {
901
                                foreach ($fields_label as $field_toshow) {
902
                                    $translabel = $langs->trans($obj->$field_toshow);
903
                                    if ($translabel != $obj->$field_toshow) {
904
                                        $labeltoshow = dol_trunc($translabel) . ' ';
905
                                    } else {
906
                                        $labeltoshow = dol_trunc($obj->$field_toshow) . ' ';
907
                                    }
908
                                }
909
                                $out .= '<option value="' . $obj->rowid . '" selected>' . $labeltoshow . '</option>';
910
                            } else {
911
                                if (!$notrans) {
912
                                    $translabel = $langs->trans($obj->{$InfoFieldList[1]});
913
                                    if ($translabel != $obj->{$InfoFieldList[1]}) {
914
                                        $labeltoshow = dol_trunc($translabel, 18);
915
                                    } else {
916
                                        $labeltoshow = dol_trunc($obj->{$InfoFieldList[1]});
917
                                    }
918
                                }
919
                                if (empty($labeltoshow)) {
920
                                    $labeltoshow = '(not defined)';
921
                                }
922
                                if ($value == $obj->rowid) {
923
                                    $out .= '<option value="' . $obj->rowid . '" selected>' . $labeltoshow . '</option>';
924
                                }
925
926
                                if (!empty($InfoFieldList[3]) && $parentField) {
927
                                    $parent = $parentName . ':' . $obj->{$parentField};
928
                                    $isDependList = 1;
929
                                }
930
931
                                $out .= '<option value="' . $obj->rowid . '"';
932
                                $out .= ($value == $obj->rowid ? ' selected' : '');
933
                                $out .= (!empty($parent) ? ' parent="' . $parent . '"' : '');
934
                                $out .= '>' . $labeltoshow . '</option>';
935
                            }
936
937
                            $i++;
938
                        }
939
                        $this->db->free($resql);
940
                    } else {
941
                        $out .= 'Error in request ' . $sql . ' ' . $this->db->lasterror() . '. Check setup of extra parameters.<br>';
942
                    }
943
                } else {
944
                    $categorytype = $InfoFieldList[5];
945
                    if (is_numeric($categorytype)) {
946
                        $categorytype = Categorie::$MAP_ID_TO_CODE[$categorytype]; // For backward compatibility
947
                    }
948
                    $data = $this->select_all_categories($categorytype, '', 'parent', 64, $InfoFieldList[6], 1, 1);
949
                    $out .= '<option value="0">&nbsp;</option>';
950
                    foreach ($data as $data_key => $data_value) {
951
                        $out .= '<option value="' . $data_key . '"';
952
                        $out .= ($value == $data_key ? ' selected' : '');
953
                        $out .= '>' . $data_value . '</option>';
954
                    }
955
                }
956
                $out .= '</select>';
957
                break;
958
959
            case 'link':
960
                $param_list = array_keys($param['options']); // $param_list='ObjectName:classPath[:AddCreateButtonOrNot[:Filter[:Sortfield]]]'
961
                $showempty = (($required && $default != '') ? 0 : 1);
962
963
                $out = $this->selectForForms($param_list[0], $htmlName, $value, $showempty, '', '', $morecss, $moreparam, 0, empty($val['disabled']) ? 0 : 1);
964
965
                break;
966
967
            default:
968
                if (!empty($hidden)) {
969
                    $out = $this->inputType('hidden', $htmlName, $value, $htmlId);
970
                }
971
                break;
972
        }
973
974
        return $out;
975
    }
976
977
    /**
978
     * Return HTML string to show a field into a page
979
     *
980
     * @param CommonObject $object Common object
981
     * @param array $val Array of properties of field to show
982
     * @param string $key Key of attribute
983
     * @param string|string[] $value Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value)
984
     * @param string $moreparam To add more parameters on html input tag
985
     * @param string $keysuffix Prefix string to add into name and id of field (can be used to avoid duplicate names)
986
     * @param string $keyprefix Suffix string to add into name and id of field (can be used to avoid duplicate names)
987
     * @param mixed $morecss Value for css to define size. May also be a numeric.
988
     * @return string
989
     */
990
    public function showOutputFieldForObject($object, $val, $key, $value, $moreparam = '', $keysuffix = '', $keyprefix = '', $morecss = '')
991
    {
992
        global $conf, $langs;
993
994
        $label = empty($val['label']) ? '' : $val['label'];
995
        $type = empty($val['type']) ? '' : $val['type'];
996
        $css = empty($val['css']) ? '' : $val['css'];
997
        $picto = empty($val['picto']) ? '' : $val['picto'];
998
        $reg = array();
999
1000
        // Convert var to be able to share same code than showOutputField of extrafields
1001
        if (preg_match('/varchar\((\d+)\)/', $type, $reg)) {
1002
            $type = 'varchar'; // convert varchar(xx) int varchar
1003
            $css = $reg[1];
1004
        } elseif (preg_match('/varchar/', $type)) {
1005
            $type = 'varchar'; // convert varchar(xx) int varchar
1006
        }
1007
        if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
1008
            $type = $val['type'] == 'checkbox' ? 'checkbox' : 'select';
1009
        }
1010
        if (preg_match('/^integer:(.*):(.*)/i', $val['type'], $reg)) {
1011
            $type = 'link';
1012
        }
1013
1014
        $default = empty($val['default']) ? '' : $val['default'];
1015
        $computed = empty($val['computed']) ? '' : $val['computed'];
1016
        $unique = empty($val['unique']) ? '' : $val['unique'];
1017
        $required = empty($val['required']) ? '' : $val['required'];
1018
        $param = array();
1019
        $param['options'] = array();
1020
1021
        if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
1022
            $param['options'] = $val['arrayofkeyval'];
1023
        }
1024
        if (preg_match('/^integer:(.*):(.*)/i', $val['type'], $reg)) {
1025
            $type = 'link';
1026
            $stringforoptions = $reg[1] . ':' . $reg[2];
1027
            if ($reg[1] == 'User') {
1028
                $stringforoptions .= ':-1';
1029
            }
1030
            $param['options'] = array($stringforoptions => $stringforoptions);
1031
        } elseif (preg_match('/^sellist:(.*):(.*):(.*):(.*)/i', $val['type'], $reg)) {
1032
            $param['options'] = array($reg[1] . ':' . $reg[2] . ':' . $reg[3] . ':' . $reg[4] => 'N');
1033
            $type = 'sellist';
1034
        } elseif (preg_match('/^sellist:(.*):(.*):(.*)/i', $val['type'], $reg)) {
1035
            $param['options'] = array($reg[1] . ':' . $reg[2] . ':' . $reg[3] => 'N');
1036
            $type = 'sellist';
1037
        } elseif (preg_match('/^sellist:(.*):(.*)/i', $val['type'], $reg)) {
1038
            $param['options'] = array($reg[1] . ':' . $reg[2] => 'N');
1039
            $type = 'sellist';
1040
        } elseif (preg_match('/^chkbxlst:(.*)/i', $val['type'], $reg)) {
1041
            $param['options'] = array($reg[1] => 'N');
1042
            $type = 'chkbxlst';
1043
        }
1044
1045
        $langfile = empty($val['langfile']) ? '' : $val['langfile'];
1046
        $list = (empty($val['list']) ? '' : $val['list']);
1047
        $help = (empty($val['help']) ? '' : $val['help']);
1048
        $hidden = (($val['visible'] == 0) ? 1 : 0); // If zero, we are sure it is hidden, otherwise we show. If it depends on mode (view/create/edit form or list, this must be filtered by caller)
1049
1050
        if ($hidden) {
1051
            return '';
1052
        }
1053
1054
        // If field is a computed field, value must become result of compute
1055
        if ($computed) {
1056
            // Make the eval of compute string
1057
            //var_dump($computed);
1058
            $value = (string) dol_eval($computed, 1, 0, '2');
1059
        }
1060
1061
        // Format output value differently according to properties of field
1062
        //
1063
        // First the cases that do not use $value from the arguments:
1064
        //
1065
        if (in_array($key, array('rowid', 'ref'))) {
1066
            if (property_exists($object, 'ref')) {
1067
                $value = $object->ref;
1068
            } elseif (property_exists($object, 'id')) {
1069
                $value = $object->id;
1070
            } else {
1071
                $value = '';
1072
            }
1073
        } elseif ($key == 'status' && method_exists($object, 'getLibStatut')) {
1074
            $value = $object->getLibStatut(3);
1075
            //
1076
            // Then the cases where $value is an array
1077
            //
1078
        } elseif (is_array($value)) {
1079
            // Handle array early to get type identification solve for static
1080
            // analysis
1081
            if ($type == 'array') {
1082
                $value = implode('<br>', $value);
1083
            } else {
1084
                dol_syslog(__METHOD__ . "Unexpected type=" . $type . " for array value=" . ((string) json_encode($value)), LOG_ERR);
1085
            }
1086
            //
1087
            // Then the cases where $value is not an array (hence string)
1088
            //
1089
        } elseif ($type == 'date') {
1090
            if (!empty($value)) {
1091
                $value = dol_print_date($value, 'day');    // We suppose dates without time are always gmt (storage of course + output)
1092
            } else {
1093
                $value = '';
1094
            }
1095
        } elseif ($type == 'datetime' || $type == 'timestamp') {
1096
            if (!empty($value)) {
1097
                $value = dol_print_date($value, 'dayhour', 'tzuserrel');
1098
            } else {
1099
                $value = '';
1100
            }
1101
        } elseif ($type == 'duration') {
1102
            include_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
1103
            if (!is_null($value) && $value !== '') {
1104
                $value = convertSecondToTime($value, 'allhourmin');
1105
            }
1106
        } elseif ($type == 'double' || $type == 'real') {
1107
            if (!is_null($value) && $value !== '') {
1108
                $value = price($value);
1109
            }
1110
        } elseif ($type == 'boolean') {
1111
            $checked = '';
1112
            if (!empty($value)) {
1113
                $checked = ' checked ';
1114
            }
1115
            $value = '<input type="checkbox" ' . $checked . ' ' . ($moreparam ? $moreparam : '') . ' readonly disabled>';
1116
        } elseif ($type == 'mail' || $type == 'email') {
1117
            $value = dol_print_email($value, 0, 0, 0, 64, 1, 1);
1118
        } elseif ($type == 'url') {
1119
            $value = dol_print_url($value, '_blank', 32, 1);
1120
        } elseif ($type == 'phone') {
1121
            $value = dol_print_phone($value, '', 0, 0, '', '&nbsp;', 'phone');
1122
        } elseif ($type == 'ip') {
1123
            $value = dol_print_ip($value, 0);
1124
        } elseif ($type == 'price') {
1125
            if (!is_null($value) && $value !== '') {
1126
                $value = price($value, 0, $langs, 0, 0, -1, $conf->currency);
1127
            }
1128
        } elseif ($type == 'select') {
1129
            $value = isset($param['options'][$value]) ? $param['options'][$value] : '';
1130
        } elseif ($type == 'sellist') {
1131
            $param_list = array_keys($param['options']);
1132
            $InfoFieldList = explode(":", $param_list[0]);
1133
1134
            $selectkey = "rowid";
1135
            $keyList = 'rowid';
1136
1137
            if (count($InfoFieldList) > 4 && !empty($InfoFieldList[4])) {
1138
                $selectkey = $InfoFieldList[2];
1139
                $keyList = $InfoFieldList[2] . ' as rowid';
1140
            }
1141
1142
            $fields_label = explode('|', $InfoFieldList[1]);
1143
            if (is_array($fields_label)) {
1144
                $keyList .= ', ';
1145
                $keyList .= implode(', ', $fields_label);
1146
            }
1147
1148
            $filter_categorie = false;
1149
            if (count($InfoFieldList) > 5) {
1150
                if ($InfoFieldList[0] == 'categorie') {
1151
                    $filter_categorie = true;
1152
                }
1153
            }
1154
1155
            $sql = "SELECT " . $keyList;
1156
            $sql .= ' FROM ' . $this->db->prefix() . $InfoFieldList[0];
1157
            if (strpos($InfoFieldList[4], 'extra') !== false) {
1158
                $sql .= ' as main';
1159
            }
1160
            if ($selectkey == 'rowid' && empty($value)) {
1161
                $sql .= " WHERE " . $selectkey . " = 0";
1162
            } elseif ($selectkey == 'rowid') {
1163
                $sql .= " WHERE " . $selectkey . " = " . ((int) $value);
1164
            } else {
1165
                $sql .= " WHERE " . $selectkey . " = '" . $this->db->escape($value) . "'";
1166
            }
1167
1168
            dol_syslog(__METHOD__ . ' type=sellist', LOG_DEBUG);
1169
            $resql = $this->db->query($sql);
1170
            if ($resql) {
1171
                if ($filter_categorie === false) {
1172
                    $value = ''; // value was used, so now we reste it to use it to build final output
1173
                    $numrows = $this->db->num_rows($resql);
1174
                    if ($numrows) {
1175
                        $obj = $this->db->fetch_object($resql);
1176
1177
                        // Several field into label (eq table:code|libelle:rowid)
1178
                        $fields_label = explode('|', $InfoFieldList[1]);
1179
1180
                        if (is_array($fields_label) && count($fields_label) > 1) {
1181
                            foreach ($fields_label as $field_toshow) {
1182
                                $translabel = '';
1183
                                if (!empty($obj->$field_toshow)) {
1184
                                    $translabel = $langs->trans($obj->$field_toshow);
1185
                                }
1186
                                if ($translabel != $field_toshow) {
1187
                                    $value .= dol_trunc($translabel, 18) . ' ';
1188
                                } else {
1189
                                    $value .= $obj->$field_toshow . ' ';
1190
                                }
1191
                            }
1192
                        } else {
1193
                            $translabel = '';
1194
                            if (!empty($obj->{$InfoFieldList[1]})) {
1195
                                $translabel = $langs->trans($obj->{$InfoFieldList[1]});
1196
                            }
1197
                            if ($translabel != $obj->{$InfoFieldList[1]}) {
1198
                                $value = dol_trunc($translabel, 18);
1199
                            } else {
1200
                                $value = $obj->{$InfoFieldList[1]};
1201
                            }
1202
                        }
1203
                    }
1204
                } else {
1205
                    $toprint = array();
1206
                    $obj = $this->db->fetch_object($resql);
1207
                    $c = new Categorie($this->db);
1208
                    $c->fetch($obj->rowid);
1209
                    $ways = $c->print_all_ways(); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formatted text
1210
                    foreach ($ways as $way) {
1211
                        $toprint[] = '<li>' . img_object('', 'category') . ' ' . $way . '</li>';
1212
                    }
1213
                    $value = '<div><ul>' . implode(' ', $toprint) . '</ul></div>';
1214
                }
1215
            } else {
1216
                dol_syslog(__METHOD__ . ' error ' . $this->db->lasterror(), LOG_WARNING);
1217
            }
1218
        } elseif ($type == 'radio') {
1219
            $value = $param['options'][$value];
1220
        } elseif ($type == 'checkbox') {
1221
            $value_arr = explode(',', $value);
1222
            $value = '';
1223
            if (is_array($value_arr) && count($value_arr) > 0) {
1224
                $toprint = array();
1225
                foreach ($value_arr as $valueval) {
1226
                    if (!empty($valueval)) {
1227
                        $toprint[] = '<li>' . $param['options'][$valueval] . '</li>';
1228
                    }
1229
                }
1230
                if (!empty($toprint)) {
1231
                    $value = '<div><ul>' . implode(' ', $toprint) . '</ul></div>';
1232
                }
1233
            }
1234
        } elseif ($type == 'chkbxlst') {
1235
            $value_arr = explode(',', $value);
1236
1237
            $param_list = array_keys($param['options']);
1238
            $InfoFieldList = explode(":", $param_list[0]);
1239
1240
            $selectkey = "rowid";
1241
            $keyList = 'rowid';
1242
1243
            if (count($InfoFieldList) >= 3) {
1244
                $selectkey = $InfoFieldList[2];
1245
                $keyList = $InfoFieldList[2] . ' as rowid';
1246
            }
1247
1248
            $fields_label = explode('|', $InfoFieldList[1]);
1249
            if (is_array($fields_label)) {
1250
                $keyList .= ', ';
1251
                $keyList .= implode(', ', $fields_label);
1252
            }
1253
1254
            $filter_categorie = false;
1255
            if (count($InfoFieldList) > 5) {
1256
                if ($InfoFieldList[0] == 'categorie') {
1257
                    $filter_categorie = true;
1258
                }
1259
            }
1260
1261
            $sql = "SELECT " . $keyList;
1262
            $sql .= ' FROM ' . $this->db->prefix() . $InfoFieldList[0];
1263
            if (strpos($InfoFieldList[4], 'extra') !== false) {
1264
                $sql .= ' as main';
1265
            }
1266
            // $sql.= " WHERE ".$selectkey."='".$this->db->escape($value)."'";
1267
            // $sql.= ' AND entity = '.$conf->entity;
1268
1269
            dol_syslog(__METHOD__ . ' type=chkbxlst', LOG_DEBUG);
1270
            $resql = $this->db->query($sql);
1271
            if ($resql) {
1272
                if ($filter_categorie === false) {
1273
                    $value = ''; // value was used, so now we reste it to use it to build final output
1274
                    $toprint = array();
1275
                    while ($obj = $this->db->fetch_object($resql)) {
1276
                        // Several field into label (eq table:code|libelle:rowid)
1277
                        $fields_label = explode('|', $InfoFieldList[1]);
1278
                        if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1279
                            if (is_array($fields_label) && count($fields_label) > 1) {
1280
                                foreach ($fields_label as $field_toshow) {
1281
                                    $translabel = '';
1282
                                    if (!empty($obj->$field_toshow)) {
1283
                                        $translabel = $langs->trans($obj->$field_toshow);
1284
                                    }
1285
                                    if ($translabel != $field_toshow) {
1286
                                        $toprint[] = '<li>' . dol_trunc($translabel, 18) . '</li>';
1287
                                    } else {
1288
                                        $toprint[] = '<li>' . $obj->$field_toshow . '</li>';
1289
                                    }
1290
                                }
1291
                            } else {
1292
                                $translabel = '';
1293
                                if (!empty($obj->{$InfoFieldList[1]})) {
1294
                                    $translabel = $langs->trans($obj->{$InfoFieldList[1]});
1295
                                }
1296
                                if ($translabel != $obj->{$InfoFieldList[1]}) {
1297
                                    $toprint[] = '<li>' . dol_trunc($translabel, 18) . '</li>';
1298
                                } else {
1299
                                    $toprint[] = '<li>' . $obj->{$InfoFieldList[1]} . '</li>';
1300
                                }
1301
                            }
1302
                        }
1303
                    }
1304
                } else {
1305
                    $toprint = array();
1306
                    while ($obj = $this->db->fetch_object($resql)) {
1307
                        if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1308
                            $c = new Categorie($this->db);
1309
                            $c->fetch($obj->rowid);
1310
                            $ways = $c->print_all_ways(); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formatted text
1311
                            foreach ($ways as $way) {
1312
                                $toprint[] = '<li>' . img_object('', 'category') . ' ' . $way . '</li>';
1313
                            }
1314
                        }
1315
                    }
1316
                }
1317
                $value = '<div><ul>' . implode(' ', $toprint) . '</ul></div>';
1318
            } else {
1319
                dol_syslog(__METHOD__ . ' error ' . $this->db->lasterror(), LOG_WARNING);
1320
            }
1321
        } elseif ($type == 'link') {
1322
            // only if something to display (perf)
1323
            if ($value) {
1324
                $param_list = array_keys($param['options']); // Example: $param_list='ObjectName:classPath:-1::customer'
1325
1326
                $InfoFieldList = explode(":", $param_list[0]);
1327
                $classname = $InfoFieldList[0];
1328
                $classpath = $InfoFieldList[1];
1329
                if (!empty($classpath)) {
1330
                    dol_include_once($InfoFieldList[1]);
1331
                    if ($classname && class_exists($classname)) {
1332
                        $object = new $classname($this->db);
1333
                        $result = $object->fetch($value);
1334
                        $value = '';
1335
                        if ($result > 0) {
1336
                            if (property_exists($object, 'label')) {
1337
                                $value = $object->label;
1338
                            } elseif (property_exists($object, 'libelle')) {
1339
                                $value = $object->libelle;
1340
                            } elseif (property_exists($object, 'nom')) {
1341
                                $value = $object->nom;
1342
                            }
1343
                        }
1344
                    }
1345
                } else {
1346
                    dol_syslog(__METHOD__ . ' Error bad setup of field', LOG_WARNING);
1347
                    return 'Error bad setup of field';
1348
                }
1349
            } else {
1350
                $value = '';
1351
            }
1352
        } elseif ($type == 'password') {
1353
            $value = preg_replace('/./i', '*', $value);
1354
        } else {    // text|html|varchar
1355
            $value = dol_htmlentitiesbr($value);
1356
        }
1357
1358
        $out = $value;
1359
1360
        return $out;
1361
    }
1362
}
1363