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

FormWebPortal::showOutputFieldForObject()   F

Complexity

Conditions 121
Paths > 20000

Size

Total Lines 371
Code Lines 262

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 121
eloc 262
nc 1421328384
nop 8
dl 0
loc 371
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
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