dolibarr 20.0.0
extrafields.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2002-2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2002-2003 Jean-Louis Bergamo <jlb@j1b.org>
4 * Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
5 * Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
6 * Copyright (C) 2009-2012 Laurent Destailleur <eldy@users.sourceforge.net>
7 * Copyright (C) 2009-2012 Regis Houssin <regis.houssin@inodbox.com>
8 * Copyright (C) 2013 Florian Henry <forian.henry@open-concept.pro>
9 * Copyright (C) 2015-2023 Charlene BENKE <charlene@patas-monkey.com>
10 * Copyright (C) 2016 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
11 * Copyright (C) 2017 Nicolas ZABOURI <info@inovea-conseil.com>
12 * Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
13 * Copyright (C) 2022 Antonin MARCHAL <antonin@letempledujeu.fr>
14 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 3 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program. If not, see <https://www.gnu.org/licenses/>.
28 */
29
41{
45 public $db;
46
50 public $attributes = array();
51
55 public $expand_display;
56
60 public $error = '';
61
65 public $errors = array();
66
70 public $errno;
71
75 public static $type2label = array(
76 'varchar' => 'String1Line',
77 'text' => 'TextLongNLines',
78 'html' => 'HtmlText',
79 'int' => 'Int',
80 'double' => 'Float',
81 'date' => 'Date',
82 'datetime' => 'DateAndTime',
83 //'datetimegmt'=>'DateAndTimeUTC',
84 'boolean' => 'Boolean',
85 'price' => 'ExtrafieldPrice',
86 'pricecy' => 'ExtrafieldPriceWithCurrency',
87 'phone' => 'ExtrafieldPhone',
88 'mail' => 'ExtrafieldMail',
89 'url' => 'ExtrafieldUrl',
90 'ip' => 'ExtrafieldIP',
91 'icon' => 'Icon',
92 'password' => 'ExtrafieldPassword',
93 'radio' => 'ExtrafieldRadio',
94 'select' => 'ExtrafieldSelect',
95 'sellist' => 'ExtrafieldSelectList',
96 'checkbox' => 'ExtrafieldCheckBox',
97 'chkbxlst' => 'ExtrafieldCheckBoxFromList',
98 'link' => 'ExtrafieldLink',
99 'point' => 'ExtrafieldPointGeo',
100 'multipts' => 'ExtrafieldMultiPointGeo',
101 'linestrg' => 'ExtrafieldLinestringGeo',
102 'polygon' => 'ExtrafieldPolygonGeo',
103 'separate' => 'ExtrafieldSeparator',
104 );
105
111 public function __construct($db)
112 {
113 $this->db = $db;
114 }
115
142 public function addExtraField($attrname, $label, $type, $pos, $size, $elementtype, $unique = 0, $required = 0, $default_value = '', $param = '', $alwayseditable = 0, $perms = '', $list = '-1', $help = '', $computed = '', $entity = '', $langfile = '', $enabled = '1', $totalizable = 0, $printable = 0, $moreparams = array())
143 {
144 if (empty($attrname)) {
145 return -1;
146 }
147 if (empty($label)) {
148 return -1;
149 }
150
151 $result = 0;
152
153 // Clean properties
154 if ($type == 'separator' || $type == 'separate') {
155 $type = 'separate';
156 $unique = 0;
157 $required = 0;
158 } // Force unique and not required if this is a separator field to avoid troubles.
159 if ($elementtype == 'thirdparty') {
160 $elementtype = 'societe';
161 }
162 if ($elementtype == 'contact') {
163 $elementtype = 'socpeople';
164 }
165 // If property has a computed formula, it must not be a required or unique field
166 if (!empty($computed)) {
167 $required = 0;
168 $unique = 0;
169 }
170
171 // Create field into database except for separator type which is not stored in database
172 if ($type != 'separate') {
173 $result = $this->create($attrname, $type, $size, $elementtype, $unique, $required, $default_value, $param, $perms, $list, $computed, $help, $moreparams);
174 }
175 $err1 = $this->errno;
176 if ($result > 0 || $err1 == 'DB_ERROR_COLUMN_ALREADY_EXISTS' || $type == 'separate') {
177 // Add declaration of field into table
178 $result2 = $this->create_label($attrname, $label, $type, $pos, $size, $elementtype, $unique, $required, $param, $alwayseditable, $perms, $list, $help, $default_value, $computed, $entity, $langfile, $enabled, $totalizable, $printable, $moreparams);
179 $err2 = $this->errno;
180 if ($result2 > 0 || ($err1 == 'DB_ERROR_COLUMN_ALREADY_EXISTS' && $err2 == 'DB_ERROR_RECORD_ALREADY_EXISTS')) {
181 $this->error = '';
182 $this->errno = '0';
183 return 1;
184 } else {
185 return -2;
186 }
187 } else {
188 return -1;
189 }
190 }
191
218 public function updateExtraField($attrname, $label, $type, $pos, $size, $elementtype, $unique = 0, $required = 0, $default_value = '', $param = '', $alwayseditable = 0, $perms = '', $list = '-1', $help = '', $computed = '', $entity = '', $langfile = '', $enabled = '1', $totalizable = 0, $printable = 0, $moreparams = array())
219 {
220 if (empty($attrname)) {
221 return -1;
222 }
223 if (empty($label)) {
224 return -1;
225 }
226
227 $result = 0;
228
229 if ($type == 'separator' || $type == 'separate') {
230 $type = 'separate';
231 $unique = 0;
232 $required = 0;
233 } // Force unique and not required if this is a separator field to avoid troubles.
234 if ($elementtype == 'thirdparty') {
235 $elementtype = 'societe';
236 }
237 if ($elementtype == 'contact') {
238 $elementtype = 'socpeople';
239 }
240
241 // Create field into database except for separator type which is not stored in database
242 if ($type != 'separate') {
243 dol_syslog(get_class($this).'::thisupdate', LOG_DEBUG);
244 $result = $this->update($attrname, $label, $type, $size, $elementtype, $unique, $required, $pos, $param, $alwayseditable, $perms, $list, $help, $default_value, $computed, $entity, $langfile, $enabled, $totalizable, $printable, $moreparams);
245 }
246 $err1 = $this->errno;
247 if ($result > 0 || $err1 == 'DB_ERROR_COLUMN_ALREADY_EXISTS' || $type == 'separate') {
248 // Add declaration of field into table
249 dol_syslog(get_class($this).'::thislabel', LOG_DEBUG);
250 $result2 = $this->update_label($attrname, $label, $type, $size, $elementtype, $unique, $required, $pos, $param, $alwayseditable, $perms, $list, $help, $default_value, $computed, $entity, $langfile, $enabled, $totalizable, $printable, $moreparams);
251 $err2 = $this->errno;
252 if ($result2 > 0 || ($err1 == 'DB_ERROR_COLUMN_ALREADY_EXISTS' && $err2 == 'DB_ERROR_RECORD_ALREADY_EXISTS')) {
253 $this->error = '';
254 $this->errno = '0';
255 return 1;
256 } else {
257 return -2;
258 }
259 } else {
260 return -1;
261 }
262 }
263
283 private function create($attrname, $type = 'varchar', $length = '255', $elementtype = '', $unique = 0, $required = 0, $default_value = '', $param = array(), $perms = '', $list = '0', $computed = '', $help = '', $moreparams = array())
284 {
285 if ($elementtype == 'thirdparty') {
286 $elementtype = 'societe';
287 }
288 if ($elementtype == 'contact') {
289 $elementtype = 'socpeople';
290 }
291
292 $table = $elementtype.'_extrafields';
293 if ($elementtype == 'categorie') {
294 $table = 'categories_extrafields';
295 }
296
297 if (!empty($attrname) && preg_match("/^\w[a-zA-Z0-9_]*$/", $attrname) && !is_numeric($attrname)) {
298 if ($type == 'boolean') {
299 $typedb = 'int';
300 $lengthdb = '1';
301 } elseif ($type == 'price') {
302 $typedb = 'double';
303 $lengthdb = '24,8';
304 } elseif ($type == 'pricecy') {
305 $typedb = 'varchar';
306 $lengthdb = '64';
307 } elseif ($type == 'phone') {
308 $typedb = 'varchar';
309 $lengthdb = '20';
310 } elseif ($type == 'mail' || $type == 'ip' || $type == 'icon') {
311 $typedb = 'varchar';
312 $lengthdb = '128';
313 } elseif ($type == 'url') {
314 $typedb = 'varchar';
315 $lengthdb = '255';
316 } elseif (($type == 'select') || ($type == 'sellist') || ($type == 'radio') || ($type == 'checkbox') || ($type == 'chkbxlst')) {
317 $typedb = 'varchar';
318 $lengthdb = '255';
319 } elseif ($type == 'link') {
320 $typedb = 'int';
321 $lengthdb = '11';
322 } elseif ($type == 'point') {
323 $typedb = 'point';
324 $lengthdb = '';
325 } elseif ($type == 'multipts') {
326 $typedb = 'multipoint';
327 $lengthdb = '';
328 } elseif ($type == 'linestrg') {
329 $typedb = 'linestring';
330 $lengthdb = '';
331 } elseif ($type == 'polygon') {
332 $typedb = 'polygon';
333 $lengthdb = '';
334 } elseif ($type == 'html') {
335 $typedb = 'text';
336 $lengthdb = $length;
337 } elseif ($type == 'password') {
338 $typedb = 'varchar';
339 $lengthdb = '128';
340 } else {
341 $typedb = $type;
342 $lengthdb = $length;
343 if ($type == 'varchar' && empty($lengthdb)) {
344 $lengthdb = '255';
345 }
346 }
347 $field_desc = array(
348 'type' => $typedb,
349 'value' => $lengthdb,
350 'null' => ($required ? 'NOT NULL' : 'NULL'),
351 'default' => $default_value
352 );
353
354 $result = $this->db->DDLAddField($this->db->prefix().$table, $attrname, $field_desc);
355 if ($result > 0) {
356 if ($unique) {
357 $sql = "ALTER TABLE ".$this->db->prefix().$table." ADD UNIQUE INDEX uk_".$table."_".$attrname." (".$attrname.")";
358 $resql = $this->db->query($sql, 1, 'dml');
359 }
360 return 1;
361 } else {
362 $this->error = $this->db->lasterror();
363 $this->errno = $this->db->lasterrno();
364 return -1;
365 }
366 } else {
367 return 0;
368 }
369 }
370
371 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
399 private function create_label($attrname, $label = '', $type = '', $pos = 0, $size = '', $elementtype = '', $unique = 0, $required = 0, $param = '', $alwayseditable = 0, $perms = '', $list = '-1', $help = '', $default = '', $computed = '', $entity = '', $langfile = '', $enabled = '1', $totalizable = 0, $printable = 0, $moreparams = array())
400 {
401 // phpcs:enable
402 global $conf, $user;
403
404 if ($elementtype == 'thirdparty') {
405 $elementtype = 'societe';
406 }
407 if ($elementtype == 'contact') {
408 $elementtype = 'socpeople';
409 }
410
411 // Clean parameters
412 if (empty($pos)) {
413 $pos = 0;
414 }
415 if (empty($list)) {
416 $list = '0';
417 }
418 if (empty($required)) {
419 $required = 0;
420 }
421 if (empty($unique)) {
422 $unique = 0;
423 }
424 if (empty($printable)) {
425 $printable = 0;
426 }
427 if (empty($alwayseditable)) {
428 $alwayseditable = 0;
429 }
430 if (empty($totalizable)) {
431 $totalizable = 0;
432 }
433
434 $css = '';
435 if (!empty($moreparams) && !empty($moreparams['css'])) {
436 $css = $moreparams['css'];
437 }
438 $csslist = '';
439 if (!empty($moreparams) && !empty($moreparams['csslist'])) {
440 $csslist = $moreparams['csslist'];
441 }
442 $cssview = '';
443 if (!empty($moreparams) && !empty($moreparams['cssview'])) {
444 $cssview = $moreparams['cssview'];
445 }
446
447 if (!empty($attrname) && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname) && !is_numeric($attrname)) {
448 if (is_array($param) && count($param) > 0) {
449 $params = serialize($param);
450 } elseif (strlen($param) > 0) {
451 $params = trim($param);
452 } else {
453 $params = '';
454 }
455
456 $sql = "INSERT INTO ".$this->db->prefix()."extrafields(";
457 $sql .= " name,";
458 $sql .= " label,";
459 $sql .= " type,";
460 $sql .= " pos,";
461 $sql .= " size,";
462 $sql .= " entity,";
463 $sql .= " elementtype,";
464 $sql .= " fieldunique,";
465 $sql .= " fieldrequired,";
466 $sql .= " param,";
467 $sql .= " alwayseditable,";
468 $sql .= " perms,";
469 $sql .= " langs,";
470 $sql .= " list,";
471 $sql .= " printable,";
472 $sql .= " fielddefault,";
473 $sql .= " fieldcomputed,";
474 $sql .= " fk_user_author,";
475 $sql .= " fk_user_modif,";
476 $sql .= " datec,";
477 $sql .= " enabled,";
478 $sql .= " help,";
479 $sql .= " totalizable,";
480 $sql .= " css,";
481 $sql .= " csslist,";
482 $sql .= " cssview";
483 $sql .= " )";
484 $sql .= " VALUES('".$this->db->escape($attrname)."',";
485 $sql .= " '".$this->db->escape($label)."',";
486 $sql .= " '".$this->db->escape($type)."',";
487 $sql .= " ".((int) $pos).",";
488 $sql .= " '".$this->db->escape($size)."',";
489 $sql .= " ".($entity === '' ? $conf->entity : $entity).",";
490 $sql .= " '".$this->db->escape($elementtype)."',";
491 $sql .= " ".((int) $unique).",";
492 $sql .= " ".((int) $required).",";
493 $sql .= " '".$this->db->escape($params)."',";
494 $sql .= " ".((int) $alwayseditable).",";
495 $sql .= " ".($perms ? "'".$this->db->escape($perms)."'" : "null").",";
496 $sql .= " ".($langfile ? "'".$this->db->escape($langfile)."'" : "null").",";
497 $sql .= " '".$this->db->escape($list)."',";
498 $sql .= " '".$this->db->escape($printable)."',";
499 $sql .= " ".($default ? "'".$this->db->escape($default)."'" : "null").",";
500 $sql .= " ".($computed ? "'".$this->db->escape($computed)."'" : "null").",";
501 $sql .= " ".(is_object($user) ? $user->id : 0).",";
502 $sql .= " ".(is_object($user) ? $user->id : 0).",";
503 $sql .= "'".$this->db->idate(dol_now())."',";
504 $sql .= " ".($enabled ? "'".$this->db->escape($enabled)."'" : "1").",";
505 $sql .= " ".($help ? "'".$this->db->escape($help)."'" : "null").",";
506 $sql .= " ".($totalizable ? 'TRUE' : 'FALSE').",";
507 $sql .= " ".($css ? "'".$this->db->escape($css)."'" : "null").",";
508 $sql .= " ".($csslist ? "'".$this->db->escape($csslist)."'" : "null").",";
509 $sql .= " ".($cssview ? "'".$this->db->escape($cssview)."'" : "null");
510 $sql .= ')';
511
512 if ($this->db->query($sql)) {
513 dol_syslog(get_class($this)."::create_label_success", LOG_DEBUG);
514 return 1;
515 } else {
516 dol_syslog(get_class($this)."::create_label_error", LOG_DEBUG);
517 $this->error = $this->db->lasterror();
518 $this->errno = $this->db->lasterrno();
519 return -1;
520 }
521 }
522 return -1;
523 }
524
532 public function delete($attrname, $elementtype = '')
533 {
534 if ($elementtype == 'thirdparty') {
535 $elementtype = 'societe';
536 }
537 if ($elementtype == 'contact') {
538 $elementtype = 'socpeople';
539 }
540
541 $table = $elementtype.'_extrafields';
542 if ($elementtype == 'categorie') {
543 $table = 'categories_extrafields';
544 }
545
546 $error = 0;
547
548 if (!empty($attrname) && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname)) {
549 $result = $this->delete_label($attrname, $elementtype);
550 if ($result < 0) {
551 $this->error = $this->db->lasterror();
552 $this->errors[] = $this->db->lasterror();
553 $error++;
554 }
555
556 if (!$error) {
557 $sql = "SELECT COUNT(rowid) as nb";
558 $sql .= " FROM ".$this->db->prefix()."extrafields";
559 $sql .= " WHERE elementtype = '".$this->db->escape($elementtype)."'";
560 $sql .= " AND name = '".$this->db->escape($attrname)."'";
561 //$sql.= " AND entity IN (0,".$conf->entity.")"; Do not test on entity here. We want to see if there is still on field remaining in other entities before deleting field in table
562 $resql = $this->db->query($sql);
563 if ($resql) {
564 $obj = $this->db->fetch_object($resql);
565 if ($obj->nb <= 0) {
566 $result = $this->db->DDLDropField($this->db->prefix().$table, $attrname); // This also drop the unique key
567 if ($result < 0) {
568 $this->error = $this->db->lasterror();
569 $this->errors[] = $this->db->lasterror();
570 $error++;
571 }
572 }
573 }
574 }
575
576 return $result;
577 } else {
578 return 0;
579 }
580 }
581
582 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
590 private function delete_label($attrname, $elementtype = '')
591 {
592 // phpcs:enable
593 global $conf;
594
595 if ($elementtype == 'thirdparty') {
596 $elementtype = 'societe';
597 }
598 if ($elementtype == 'contact') {
599 $elementtype = 'socpeople';
600 }
601
602 if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname)) {
603 $sql = "DELETE FROM ".$this->db->prefix()."extrafields";
604 $sql .= " WHERE name = '".$this->db->escape($attrname)."'";
605 $sql .= " AND entity IN (0,".$conf->entity.')';
606 $sql .= " AND elementtype = '".$this->db->escape($elementtype)."'";
607
608 dol_syslog(get_class($this)."::delete_label", LOG_DEBUG);
609 $resql = $this->db->query($sql);
610 if ($resql) {
611 return 1;
612 } else {
613 dol_print_error($this->db);
614 return -1;
615 }
616 } else {
617 return 0;
618 }
619 }
620
648 public function update($attrname, $label, $type, $length, $elementtype, $unique = 0, $required = 0, $pos = 0, $param = array(), $alwayseditable = 0, $perms = '', $list = '', $help = '', $default = '', $computed = '', $entity = '', $langfile = '', $enabled = '1', $totalizable = 0, $printable = 0, $moreparams = array())
649 {
650 global $action, $hookmanager;
651
652 $result = 0;
653
654 if ($elementtype == 'thirdparty') {
655 $elementtype = 'societe';
656 }
657 if ($elementtype == 'contact') {
658 $elementtype = 'socpeople';
659 }
660
661 $table = $elementtype.'_extrafields';
662 if ($elementtype == 'categorie') {
663 $table = 'categories_extrafields';
664 }
665
666 if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname)) {
667 // Clean parameters
668 if ($type == 'boolean') {
669 $typedb = 'int';
670 $lengthdb = '1';
671 } elseif ($type == 'price') {
672 $typedb = 'double';
673 $lengthdb = '24,8';
674 } elseif ($type == 'pricecy') {
675 $typedb = 'varchar';
676 $lengthdb = '64';
677 } elseif ($type == 'phone') {
678 $typedb = 'varchar';
679 $lengthdb = '20';
680 } elseif ($type == 'mail' || $type == 'ip' || $type == 'icon') {
681 $typedb = 'varchar';
682 $lengthdb = '128';
683 } elseif ($type == 'url') {
684 $typedb = 'varchar';
685 $lengthdb = '255';
686 } elseif (($type == 'select') || ($type == 'sellist') || ($type == 'radio') || ($type == 'checkbox') || ($type == 'chkbxlst')) {
687 $typedb = 'varchar';
688 $lengthdb = '255';
689 } elseif ($type == 'html') {
690 $typedb = 'text';
691 $lengthdb = $length;
692 } elseif ($type == 'link') {
693 $typedb = 'int';
694 $lengthdb = '11';
695 } elseif ($type == 'point') {
696 $typedb = 'point';
697 $lengthdb = '';
698 } elseif ($type == 'multipts') {
699 $typedb = 'multipoint';
700 $lengthdb = '';
701 } elseif ($type == 'linestrg') {
702 $typedb = 'linestring';
703 $lengthdb = '';
704 } elseif ($type == 'polygon') {
705 $typedb = 'polygon';
706 $lengthdb = '';
707 } elseif ($type == 'password') {
708 $typedb = 'varchar';
709 $lengthdb = '128';
710 } else {
711 $typedb = $type;
712 $lengthdb = $length;
713 }
714 $field_desc = array('type' => $typedb, 'value' => $lengthdb, 'null' => ($required ? 'NOT NULL' : 'NULL'), 'default' => $default);
715
716 // If property has a computed formula, it must not be a required or unique field
717 if (!empty($computed)) {
718 $required = 0;
719 $unique = 0;
720 }
721
722 if (is_object($hookmanager)) {
723 $hookmanager->initHooks(array('extrafieldsdao'));
724 $parameters = array('field_desc' => &$field_desc, 'table' => $table, 'attr_name' => $attrname, 'label' => $label, 'type' => $type, 'length' => $length, 'unique' => $unique, 'required' => $required, 'pos' => $pos, 'param' => $param, 'alwayseditable' => $alwayseditable, 'perms' => $perms, 'list' => $list, 'help' => $help, 'default' => $default, 'computed' => $computed, 'entity' => $entity, 'langfile' => $langfile, 'enabled' => $enabled, 'totalizable' => $totalizable, 'printable' => $printable);
725 $reshook = $hookmanager->executeHooks('updateExtrafields', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
726
727 if ($reshook < 0) {
728 $this->error = $this->db->lasterror();
729 return -1;
730 }
731 }
732
733 dol_syslog(get_class($this).'::DDLUpdateField', LOG_DEBUG);
734 if ($type != 'separate') { // No table update when separate type
735 $result = $this->db->DDLUpdateField($this->db->prefix().$table, $attrname, $field_desc);
736 }
737 if ($result > 0 || $type == 'separate') {
738 if ($label) {
739 dol_syslog(get_class($this).'::update_label', LOG_DEBUG);
740 $result = $this->update_label($attrname, $label, $type, $length, $elementtype, $unique, $required, $pos, $param, $alwayseditable, $perms, $list, $help, $default, $computed, $entity, $langfile, $enabled, $totalizable, $printable, $moreparams);
741 }
742 if ($result > 0) {
743 $sql = '';
744 if ($unique) {
745 dol_syslog(get_class($this).'::update_unique', LOG_DEBUG);
746 $sql = "ALTER TABLE ".$this->db->prefix().$table." ADD UNIQUE INDEX uk_".$table."_".$this->db->sanitize($attrname)." (".$this->db->sanitize($attrname).")";
747 } else {
748 dol_syslog(get_class($this).'::update_common', LOG_DEBUG);
749 $sql = "ALTER TABLE ".$this->db->prefix().$table." DROP INDEX IF EXISTS uk_".$table."_".$this->db->sanitize($attrname);
750 }
751 dol_syslog(get_class($this).'::update', LOG_DEBUG);
752 $resql = $this->db->query($sql, 1, 'dml');
753 /*if ($resql < 0) {
754 $this->error = $this->db->lasterror();
755 return -1;
756 }*/
757 return 1;
758 } else {
759 $this->error = $this->db->lasterror();
760 return -1;
761 }
762 } else {
763 $this->error = $this->db->lasterror();
764 return -1;
765 }
766 } else {
767 return 0;
768 }
769 }
770
771 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
800 private function update_label($attrname, $label, $type, $size, $elementtype, $unique = 0, $required = 0, $pos = 0, $param = array(), $alwayseditable = 0, $perms = '', $list = '0', $help = '', $default = '', $computed = '', $entity = '', $langfile = '', $enabled = '1', $totalizable = 0, $printable = 0, $moreparams = array())
801 {
802 // phpcs:enable
803 global $conf, $user;
804 dol_syslog(get_class($this)."::update_label ".$attrname.", ".$label.", ".$type.", ".$size.", ".$elementtype.", ".$unique.", ".$required.", ".$pos.", ".$alwayseditable.", ".$perms.", ".$list.", ".$default.", ".$computed.", ".$entity.", ".$langfile.", ".$enabled.", ".$totalizable.", ".$printable);
805
806 // Clean parameters
807 if ($elementtype == 'thirdparty') {
808 $elementtype = 'societe';
809 }
810 if ($elementtype == 'contact') {
811 $elementtype = 'socpeople';
812 }
813
814 if (empty($pos)) {
815 $pos = 0;
816 }
817 if (empty($list)) {
818 $list = '0';
819 }
820 if (empty($totalizable)) {
821 $totalizable = 0;
822 }
823 if (empty($required)) {
824 $required = 0;
825 }
826 if (empty($unique)) {
827 $unique = 0;
828 }
829 if (empty($alwayseditable)) {
830 $alwayseditable = 0;
831 }
832
833 $css = '';
834 if (!empty($moreparams) && !empty($moreparams['css'])) {
835 $css = $moreparams['css'];
836 }
837 $csslist = '';
838 if (!empty($moreparams) && !empty($moreparams['csslist'])) {
839 $csslist = $moreparams['csslist'];
840 }
841 $cssview = '';
842 if (!empty($moreparams) && !empty($moreparams['cssview'])) {
843 $cssview = $moreparams['cssview'];
844 }
845
846 if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname)) {
847 $this->db->begin();
848
849 if (is_array($param) && count($param) > 0) {
850 $params = serialize($param);
851 } elseif (is_array($param)) {
852 $params = '';
853 } elseif (strlen($param) > 0) {
854 $params = trim($param);
855 } else {
856 $params = '';
857 }
858
859 if ($entity === '' || $entity != '0') {
860 // We don't want on all entities, we delete all and current
861 $sql_del = "DELETE FROM ".$this->db->prefix()."extrafields";
862 $sql_del .= " WHERE name = '".$this->db->escape($attrname)."'";
863 $sql_del .= " AND entity IN (0, ".($entity === '' ? $conf->entity : $entity).")";
864 $sql_del .= " AND elementtype = '".$this->db->escape($elementtype)."'";
865 } else {
866 // We want on all entities ($entities = '0'), we delete on all only (we keep setup specific to each entity)
867 $sql_del = "DELETE FROM ".$this->db->prefix()."extrafields";
868 $sql_del .= " WHERE name = '".$this->db->escape($attrname)."'";
869 $sql_del .= " AND entity = 0";
870 $sql_del .= " AND elementtype = '".$this->db->escape($elementtype)."'";
871 }
872 $resql1 = $this->db->query($sql_del);
873
874 $sql = "INSERT INTO ".$this->db->prefix()."extrafields(";
875 $sql .= " name,"; // This is code
876 $sql .= " entity,";
877 $sql .= " label,";
878 $sql .= " type,";
879 $sql .= " size,";
880 $sql .= " elementtype,";
881 $sql .= " fieldunique,";
882 $sql .= " fieldrequired,";
883 $sql .= " perms,";
884 $sql .= " langs,";
885 $sql .= " pos,";
886 $sql .= " alwayseditable,";
887 $sql .= " param,";
888 $sql .= " list,";
889 $sql .= " printable,";
890 $sql .= " totalizable,";
891 $sql .= " fielddefault,";
892 $sql .= " fieldcomputed,";
893 $sql .= " fk_user_author,";
894 $sql .= " fk_user_modif,";
895 $sql .= " datec,";
896 $sql .= " enabled,";
897 $sql .= " help,";
898 $sql .= " css,";
899 $sql .= " csslist,";
900 $sql .= " cssview";
901 $sql .= ") VALUES (";
902 $sql .= "'".$this->db->escape($attrname)."',";
903 $sql .= " ".($entity === '' ? $conf->entity : $entity).",";
904 $sql .= " '".$this->db->escape($label)."',";
905 $sql .= " '".$this->db->escape($type)."',";
906 $sql .= " '".$this->db->escape($size)."',";
907 $sql .= " '".$this->db->escape($elementtype)."',";
908 $sql .= " ".$unique.",";
909 $sql .= " ".$required.",";
910 $sql .= " ".($perms ? "'".$this->db->escape($perms)."'" : "null").",";
911 $sql .= " ".($langfile ? "'".$this->db->escape($langfile)."'" : "null").",";
912 $sql .= " ".$pos.",";
913 $sql .= " '".$this->db->escape($alwayseditable)."',";
914 $sql .= " '".$this->db->escape($params)."',";
915 $sql .= " '".$this->db->escape($list)."',";
916 $sql .= " ".((int) $printable).",";
917 $sql .= " ".($totalizable ? 'TRUE' : 'FALSE').",";
918 $sql .= " ".(($default != '') ? "'".$this->db->escape($default)."'" : "null").",";
919 $sql .= " ".($computed ? "'".$this->db->escape($computed)."'" : "null").",";
920 $sql .= " ".$user->id.",";
921 $sql .= " ".$user->id.",";
922 $sql .= "'".$this->db->idate(dol_now())."',";
923 $sql .= "'".$this->db->escape($enabled)."',";
924 $sql .= " ".($help ? "'".$this->db->escape($help)."'" : "null").",";
925 $sql .= " ".($css ? "'".$this->db->escape($css)."'" : "null").",";
926 $sql .= " ".($csslist ? "'".$this->db->escape($csslist)."'" : "null").",";
927 $sql .= " ".($cssview ? "'".$this->db->escape($cssview)."'" : "null");
928 $sql .= ")";
929
930 $resql2 = $this->db->query($sql);
931
932 if ($resql1 && $resql2) {
933 $this->db->commit();
934 return 1;
935 } else {
936 $this->db->rollback();
937 dol_print_error($this->db);
938 return -1;
939 }
940 } else {
941 return 0;
942 }
943 }
944
945 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
954 public function fetch_name_optionals_label($elementtype, $forceload = false, $attrname = '')
955 {
956 // phpcs:enable
957 global $conf;
958
959 if (empty($elementtype)) {
960 return array();
961 }
962
963 if ($elementtype == 'thirdparty') {
964 $elementtype = 'societe';
965 }
966 if ($elementtype == 'contact') {
967 $elementtype = 'socpeople';
968 }
969 if ($elementtype == 'order_supplier') {
970 $elementtype = 'commande_fournisseur';
971 }
972
973 // Test cache $this->attributes[$elementtype]['loaded'] to see if we must do something
974 // TODO
975
976 $array_name_label = array();
977
978 // We should not have several time this request. If we have, there is some optimization to do by calling a simple $extrafields->fetch_optionals() in top of code and not into subcode
979 $sql = "SELECT rowid, name, label, type, size, elementtype, fieldunique, fieldrequired, param, pos, alwayseditable, perms, langs, list, printable, totalizable, fielddefault, fieldcomputed, entity, enabled, help,";
980 $sql .= " css, cssview, csslist";
981 $sql .= " FROM ".$this->db->prefix()."extrafields";
982 //$sql.= " WHERE entity IN (0,".$conf->entity.")"; // Filter is done later
983 if ($elementtype && $elementtype != 'all') {
984 $sql .= " WHERE elementtype = '".$this->db->escape($elementtype)."'"; // Filed with object->table_element
985 }
986 if ($attrname && $elementtype && $elementtype != 'all') {
987 $sql .= " AND name = '".$this->db->escape($attrname)."'";
988 }
989 $sql .= " ORDER BY pos";
990
991 $resql = $this->db->query($sql);
992 if ($resql) {
993 $count = 0;
994 if ($this->db->num_rows($resql)) {
995 while ($tab = $this->db->fetch_object($resql)) {
996 if ($tab->entity != 0 && $tab->entity != $conf->entity) {
997 // This field is not in current entity. We discard but before we save it into the array of mandatory fields if it is a mandatory field without default value
998 if ($tab->fieldrequired && is_null($tab->fielddefault)) {
999 $this->attributes[$tab->elementtype]['mandatoryfieldsofotherentities'][$tab->name] = $tab->type;
1000 }
1001 continue;
1002 }
1003
1004 // We can add this attribute to object. TODO Remove this and return $this->attributes[$elementtype]['label']
1005 if ($tab->type != 'separate') {
1006 $array_name_label[$tab->name] = $tab->label;
1007 }
1008
1009
1010 $this->attributes[$tab->elementtype]['type'][$tab->name] = $tab->type;
1011 $this->attributes[$tab->elementtype]['label'][$tab->name] = $tab->label;
1012 $this->attributes[$tab->elementtype]['size'][$tab->name] = $tab->size;
1013 $this->attributes[$tab->elementtype]['elementtype'][$tab->name] = $tab->elementtype;
1014 $this->attributes[$tab->elementtype]['default'][$tab->name] = $tab->fielddefault;
1015 $this->attributes[$tab->elementtype]['computed'][$tab->name] = $tab->fieldcomputed;
1016 $this->attributes[$tab->elementtype]['unique'][$tab->name] = $tab->fieldunique;
1017 $this->attributes[$tab->elementtype]['required'][$tab->name] = $tab->fieldrequired;
1018 $this->attributes[$tab->elementtype]['param'][$tab->name] = ($tab->param ? jsonOrUnserialize($tab->param) : '');
1019 $this->attributes[$tab->elementtype]['pos'][$tab->name] = $tab->pos;
1020 $this->attributes[$tab->elementtype]['alwayseditable'][$tab->name] = $tab->alwayseditable;
1021 $this->attributes[$tab->elementtype]['perms'][$tab->name] = ((is_null($tab->perms) || strlen($tab->perms) == 0) ? 1 : $tab->perms);
1022 $this->attributes[$tab->elementtype]['langfile'][$tab->name] = $tab->langs;
1023 $this->attributes[$tab->elementtype]['list'][$tab->name] = $tab->list;
1024 $this->attributes[$tab->elementtype]['printable'][$tab->name] = $tab->printable;
1025 $this->attributes[$tab->elementtype]['totalizable'][$tab->name] = ($tab->totalizable ? 1 : 0);
1026 $this->attributes[$tab->elementtype]['entityid'][$tab->name] = $tab->entity;
1027 $this->attributes[$tab->elementtype]['enabled'][$tab->name] = $tab->enabled;
1028 $this->attributes[$tab->elementtype]['help'][$tab->name] = $tab->help;
1029 $this->attributes[$tab->elementtype]['css'][$tab->name] = $tab->css;
1030 $this->attributes[$tab->elementtype]['cssview'][$tab->name] = $tab->cssview;
1031 $this->attributes[$tab->elementtype]['csslist'][$tab->name] = $tab->csslist;
1032
1033 $this->attributes[$tab->elementtype]['loaded'] = 1;
1034 $count++;
1035 }
1036 }
1037 if ($elementtype) {
1038 $this->attributes[$elementtype]['loaded'] = 1; // Note: If nothing is found, we also set the key 'loaded' to 1.
1039 $this->attributes[$elementtype]['count'] = $count;
1040 }
1041 } else {
1042 $this->error = $this->db->lasterror();
1043 dol_syslog(get_class($this)."::fetch_name_optionals_label ".$this->error, LOG_ERR);
1044 }
1045
1046 return $array_name_label;
1047 }
1048
1049
1065 public function showInputField($key, $value, $moreparam = '', $keysuffix = '', $keyprefix = '', $morecss = '', $objectid = 0, $extrafieldsobjectkey = '', $mode = 0)
1066 {
1067 global $conf, $langs, $form;
1068
1069 if (!is_object($form)) {
1070 require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
1071 $form = new Form($this->db);
1072 }
1073
1074 $out = '';
1075
1076 if (!preg_match('/options_$/', $keyprefix)) { // Because we work on extrafields, we add 'options_' to prefix if not already added
1077 $keyprefix = $keyprefix.'options_';
1078 }
1079
1080 if (empty($extrafieldsobjectkey)) {
1081 dol_syslog(get_class($this).'::showInputField extrafieldsobjectkey required', LOG_ERR);
1082 return 'BadValueForParamExtraFieldsObjectKey';
1083 }
1084
1085 $label = $this->attributes[$extrafieldsobjectkey]['label'][$key];
1086 $type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
1087 $size = $this->attributes[$extrafieldsobjectkey]['size'][$key];
1088 $default = $this->attributes[$extrafieldsobjectkey]['default'][$key];
1089 $computed = $this->attributes[$extrafieldsobjectkey]['computed'][$key];
1090 $unique = $this->attributes[$extrafieldsobjectkey]['unique'][$key];
1091 $required = $this->attributes[$extrafieldsobjectkey]['required'][$key];
1092 $param = $this->attributes[$extrafieldsobjectkey]['param'][$key];
1093 $perms = (int) dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1, 1, '2');
1094 $langfile = $this->attributes[$extrafieldsobjectkey]['langfile'][$key];
1095 $list = (string) dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1, 1, '2');
1096 $totalizable = $this->attributes[$extrafieldsobjectkey]['totalizable'][$key];
1097 $help = $this->attributes[$extrafieldsobjectkey]['help'][$key];
1098 $hidden = (empty($list) ? 1 : 0); // If empty, 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)
1099
1100 //var_dump('key='.$key.' '.$value.' '.$moreparam.' '.$keysuffix.' '.$keyprefix.' '.$objectid.' '.$extrafieldsobjectkey.' '.$mode);
1101 //var_dump('label='.$label.' type='.$type.' param='.var_export($param, 1));
1102
1103 if ($computed) {
1104 if (!preg_match('/^search_/', $keyprefix)) {
1105 return '<span class="opacitymedium">'.$langs->trans("AutomaticallyCalculated").'</span>';
1106 } else {
1107 return '';
1108 }
1109 }
1110
1111 //
1112 // 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'cssview'=>'wordbreak', 'csslist'=>'tdoverflowmax200'
1113 if (empty($morecss)) {
1114 // Add automatic css
1115 if ($type == 'date') {
1116 $morecss = 'minwidth100imp';
1117 } elseif ($type == 'datetime' || $type == 'datetimegmt' || $type == 'link') {
1118 $morecss = 'minwidth200imp';
1119 } elseif (in_array($type, array('int', 'integer', 'double', 'price'))) {
1120 $morecss = 'maxwidth75';
1121 } elseif ($type == 'password') {
1122 $morecss = 'maxwidth100';
1123 } elseif ($type == 'url') {
1124 $morecss = 'minwidth400';
1125 } elseif ($type == 'boolean') {
1126 $morecss = '';
1127 } elseif ($type == 'radio') {
1128 $morecss = 'width25';
1129 } else {
1130 if (empty($size) || round((float) $size) < 12) {
1131 $morecss = 'minwidth100';
1132 } elseif (round((float) $size) <= 48) {
1133 $morecss = 'minwidth200';
1134 } else {
1135 $morecss = 'minwidth400';
1136 }
1137 }
1138 // If css forced in attribute, we use this one
1139 if (!empty($this->attributes[$extrafieldsobjectkey]['css'][$key])) {
1140 $morecss = $this->attributes[$extrafieldsobjectkey]['css'][$key];
1141 }
1142 }
1143
1144 if (in_array($type, array('date'))) {
1145 $tmp = explode(',', $size);
1146 $newsize = $tmp[0];
1147 $showtime = 0;
1148
1149 // Do not show current date when field not required (see selectDate() method)
1150 if (!$required && $value == '') {
1151 $value = '-1';
1152 }
1153
1154 if ($mode == 1) {
1155 // search filter on a date extrafield shows two inputs to select a date range
1156 $prefill = array(
1157 'start' => isset($value['start']) ? $value['start'] : '',
1158 'end' => isset($value['end']) ? $value['end'] : ''
1159 );
1160 $out = '<div ' . ($moreparam ? $moreparam : '') . '><div class="nowrap">';
1161 $out .= $form->selectDate($prefill['start'], $keyprefix.$key.$keysuffix.'_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From"));
1162 $out .= '</div><div class="nowrap">';
1163 $out .= $form->selectDate($prefill['end'], $keyprefix.$key.$keysuffix.'_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"));
1164 $out .= '</div></div>';
1165 } else {
1166 // TODO Must also support $moreparam
1167 $out = $form->selectDate($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 0, 1);
1168 }
1169 } elseif (in_array($type, array('datetime', 'datetimegmt'))) {
1170 $tmp = explode(',', $size);
1171 $newsize = $tmp[0];
1172 $showtime = 1;
1173
1174 // Do not show current date when field not required (see selectDate() method)
1175 if (!$required && $value == '') {
1176 $value = '-1';
1177 }
1178
1179 if ($mode == 1) {
1180 // search filter on a date extrafield shows two inputs to select a date range
1181 $prefill = array(
1182 'start' => isset($value['start']) ? $value['start'] : '',
1183 'end' => isset($value['end']) ? $value['end'] : ''
1184 );
1185 $out = '<div ' . ($moreparam ? $moreparam : '') . '><div class="nowrap">';
1186 $out .= $form->selectDate($prefill['start'], $keyprefix.$key.$keysuffix.'_start', 1, 1, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From"), 'tzuserrel');
1187 $out .= '</div><div class="nowrap">';
1188 $out .= $form->selectDate($prefill['end'], $keyprefix.$key.$keysuffix.'_end', 1, 1, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"), 'tzuserrel');
1189 $out .= '</div></div>';
1190 } else {
1191 // TODO Must also support $moreparam
1192 $out = $form->selectDate($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 0, 1, '', '', '', 1, '', '', 'tzuserrel');
1193 }
1194 } elseif (in_array($type, array('int', 'integer'))) {
1195 $tmp = explode(',', $size);
1196 $newsize = $tmp[0];
1197 $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" maxlength="'.$newsize.'" value="'.dol_escape_htmltag($value).'"'.($moreparam ? $moreparam : '').'>';
1198 } elseif (preg_match('/varchar/', $type)) {
1199 $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" maxlength="'.$size.'" value="'.dol_escape_htmltag($value).'"'.($moreparam ? $moreparam : '').'>';
1200 } elseif (in_array($type, array('mail', 'ip', 'phone', 'url'))) {
1201 $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam ? $moreparam : '').'>';
1202 } elseif ($type == 'icon') {
1203 /* External lib inclusion are not allowed in backoffice. Also lib is included several time if there is several icon file.
1204 Some code must be added into main when MAIN_ADD_ICONPICKER_JS is set to add of lib in html header
1205 $out ='<link rel="stylesheet" href="'.dol_buildpath('/myfield/css/fontawesome-iconpicker.min.css', 1).'">';
1206 $out.='<script src="'.dol_buildpath('/myfield/js/fontawesome-iconpicker.min.js', 1).'"></script>';
1207 */
1208 $out .= '<input type="text" class="form-control icp icp-auto iconpicker-element iconpicker-input flat '.$morecss.' maxwidthonsmartphone"';
1209 $out .= ' name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam ? $moreparam : '').'>';
1210 if (getDolGlobalInt('MAIN_ADD_ICONPICKER_JS')) {
1211 $out .= '<script>';
1212 $options = "{ title: '<b>".$langs->trans("IconFieldSelector")."</b>', placement: 'right', showFooter: false, templates: {";
1213 $options .= "iconpicker: '<div class=\"iconpicker\"><div style=\"background-color:#EFEFEF;\" class=\"iconpicker-items\"></div></div>',";
1214 $options .= "iconpickerItem: '<a role=\"button\" href=\"#\" class=\"iconpicker-item\" style=\"background-color:#DDDDDD;\"><i></i></a>',";
1215 // $options.="buttons: '<button style=\"background-color:#FFFFFF;\" class=\"iconpicker-btn iconpicker-btn-cancel btn btn-default btn-sm\">".$langs->trans("Cancel")."</button>";
1216 // $options.="<button style=\"background-color:#FFFFFF;\" class=\"iconpicker-btn iconpicker-btn-accept btn btn-primary btn-sm\">".$langs->trans("Save")."</button>',";
1217 $options .= "footer: '<div class=\"popover-footer\" style=\"background-color:#EFEFEF;\"></div>',";
1218 $options .= "search: '<input type=\"search\" class\"form-control iconpicker-search\" placeholder=\"".$langs->trans("TypeToFilter")."\" />',";
1219 $options .= "popover: '<div class=\"iconpicker-popover popover\">";
1220 $options .= " <div class=\"arrow\" ></div>";
1221 $options .= " <div class=\"popover-title\" style=\"text-align:center;background-color:#EFEFEF;\"></div>";
1222 $options .= " <div class=\"popover-content \" ></div>";
1223 $options .= "</div>'}}";
1224 $out .= "$('#".$keyprefix.$key.$keysuffix."').iconpicker(".$options.");";
1225 $out .= '</script>';
1226 }
1227 } elseif ($type == 'text') {
1228 if (!preg_match('/search_/', $keyprefix)) { // If keyprefix is search_ or search_options_, we must just use a simple text field
1229 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1230 $doleditor = new DolEditor($keyprefix.$key.$keysuffix, $value, '', 200, 'dolibarr_notes', 'In', false, false, false, ROWS_5, '90%');
1231 $out = (string) $doleditor->Create(1);
1232 } else {
1233 $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam ? $moreparam : '').'>';
1234 }
1235 } elseif ($type == 'html') {
1236 if (!preg_match('/search_/', $keyprefix)) { // If keyprefix is search_ or search_options_, we must just use a simple text field
1237 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1238 $doleditor = new DolEditor($keyprefix.$key.$keysuffix, $value, '', 200, 'dolibarr_notes', 'In', false, false, isModEnabled('fckeditor') && getDolGlobalInt('FCKEDITOR_ENABLE_SOCIETE'), ROWS_5, '90%');
1239 $out = (string) $doleditor->Create(1);
1240 } else {
1241 $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam ? $moreparam : '').'>';
1242 }
1243 } elseif ($type == 'boolean') {
1244 if (empty($mode)) {
1245 $checked = '';
1246 if (!empty($value)) {
1247 $checked = ' checked value="1" ';
1248 } else {
1249 $checked = ' value="1" ';
1250 }
1251 $out = '<input type="checkbox" class="flat valignmiddle'.($morecss ? ' '.$morecss : '').' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.$checked.' '.($moreparam ? $moreparam : '').'>';
1252 } else {
1253 $out = $form->selectyesno($keyprefix.$key.$keysuffix, $value, 1, false, 1);
1254 }
1255 $out .= '<input type="hidden" name="'.$keyprefix.$key.$keysuffix.'_boolean" value="1">'; // A hidden field ending with "_boolean" that is always set to 1.
1256 } elseif ($type == 'price') {
1257 if (!empty($value)) { // $value in memory is a php numeric, we format it into user number format.
1258 $value = price($value);
1259 }
1260 $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone right" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam ? $moreparam : '').' placeholder="'.$langs->getCurrencySymbol($conf->currency).'">';
1261 } elseif ($type == 'pricecy') {
1262 $currency = $conf->currency;
1263 if (!empty($value)) {
1264 // $value in memory is a php string like '10.01:USD'
1265 $pricetmp = explode(':', $value);
1266 $currency = !empty($pricetmp[1]) ? $pricetmp[1] : $conf->currency;
1267 $value = price($pricetmp[0]);
1268 }
1269 $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam ? $moreparam : '').'> ';
1270 $out .= $form->selectCurrency($currency, $keyprefix.$key.$keysuffix.'currency_id');
1271 } elseif ($type == 'double') {
1272 if (!empty($value)) { // $value in memory is a php numeric, we format it into user number format.
1273 $value = price($value);
1274 }
1275 $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam ? $moreparam : '').'> ';
1276 } elseif ($type == 'select') {
1277 $out = '';
1278 if ($mode) {
1279 $options = array();
1280 foreach ($param['options'] as $okey => $val) {
1281 if ((string) $okey == '') {
1282 continue;
1283 }
1284
1285 $valarray = explode('|', $val);
1286 $val = $valarray[0];
1287
1288 if ($langfile && $val) {
1289 $options[$okey] = $langs->trans($val);
1290 } else {
1291 $options[$okey] = $val;
1292 }
1293 }
1294 $selected = array();
1295 if (!is_array($value)) {
1296 $selected = explode(',', $value);
1297 }
1298
1299 $out .= $form->multiselectarray($keyprefix.$key.$keysuffix, $options, $selected, 0, 0, $morecss, 0, 0, '', '', '', !empty($conf->use_javascript_ajax) && !getDolGlobalString('MAIN_EXTRAFIELDS_DISABLE_SELECT2'));
1300 } else {
1301 if (!empty($conf->use_javascript_ajax) && !getDolGlobalString('MAIN_EXTRAFIELDS_DISABLE_SELECT2')) {
1302 include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
1303 $out .= ajax_combobox($keyprefix.$key.$keysuffix, array(), 0);
1304 }
1305
1306 $out .= '<select class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam ? $moreparam : '').'>';
1307 $out .= '<option value="0">&nbsp;</option>';
1308 foreach ($param['options'] as $key2 => $val2) {
1309 if ((string) $key2 == '') {
1310 continue;
1311 }
1312 $valarray = explode('|', $val2);
1313 $val2 = $valarray[0];
1314 $parent = '';
1315 if (!empty($valarray[1])) {
1316 $parent = $valarray[1];
1317 }
1318 $out .= '<option value="'.$key2.'"';
1319 $out .= (((string) $value == (string) $key2) ? ' selected' : '');
1320 $out .= (!empty($parent) ? ' parent="'.$parent.'"' : '');
1321 $out .= '>';
1322 if ($langfile && $val2) {
1323 $out .= $langs->trans($val2);
1324 } else {
1325 $out .= $val2;
1326 }
1327 $out .= '</option>';
1328 }
1329 $out .= '</select>';
1330 }
1331 } elseif ($type == 'sellist') { // List of values selected from a table (1 choice)
1332 $out = '';
1333 if (!empty($conf->use_javascript_ajax) && !getDolGlobalString('MAIN_EXTRAFIELDS_DISABLE_SELECT2')) {
1334 include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
1335 $out .= ajax_combobox($keyprefix.$key.$keysuffix, array(), 0);
1336 }
1337
1338 $out .= '<select class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam ? $moreparam : '').'>';
1339 if (is_array($param['options'])) {
1340 $tmpparamoptions = array_keys($param['options']);
1341 $paramoptions = preg_split('/[\r\n]+/', $tmpparamoptions[0]);
1342
1343 $InfoFieldList = explode(":", $paramoptions[0], 5);
1344 // 0 : tableName
1345 // 1 : label field name
1346 // 2 : key fields name (if different of rowid)
1347 // optional parameters...
1348 // 3 : key field parent (for dependent lists). How this is used ?
1349 // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value. Or use USF on the second line.
1350 // 5 : string category type. This replace the filter.
1351 // 6 : ids categories list separated by comma for category root. This replace the filter.
1352 // 7 : sort field (not used here but used into format for commobject)
1353
1354 // If there is a filter, we extract it by taking all content inside parenthesis.
1355 if (! empty($InfoFieldList[4])) {
1356 $pos = 0; // $pos will be position of ending filter
1357 $parenthesisopen = 0;
1358 while (substr($InfoFieldList[4], $pos, 1) !== '' && ($parenthesisopen || $pos == 0 || substr($InfoFieldList[4], $pos, 1) != ':')) {
1359 if (substr($InfoFieldList[4], $pos, 1) == '(') {
1360 $parenthesisopen++;
1361 }
1362 if (substr($InfoFieldList[4], $pos, 1) == ')') {
1363 $parenthesisopen--;
1364 }
1365 $pos++;
1366 }
1367 $tmpbefore = substr($InfoFieldList[4], 0, $pos);
1368 $tmpafter = substr($InfoFieldList[4], $pos + 1);
1369 //var_dump($InfoFieldList[4].' -> '.$pos); var_dump($tmpafter);
1370 $InfoFieldList[4] = $tmpbefore;
1371 if ($tmpafter !== '') {
1372 $InfoFieldList = array_merge($InfoFieldList, explode(':', $tmpafter));
1373 }
1374
1375 // Fix better compatibility with some old extrafield syntax filter "(field=123)"
1376 $reg = array();
1377 if (preg_match('/^\‍(?([a-z0-9]+)([=<>]+)(\d+)\‍)?$/i', $InfoFieldList[4], $reg)) {
1378 $InfoFieldList[4] = '('.$reg[1].':'.$reg[2].':'.$reg[3].')';
1379 }
1380
1381 //var_dump($InfoFieldList);
1382 }
1383
1384 //$Usf = empty($paramoptions[1]) ? '' :$paramoptions[1];
1385
1386 $parentName = '';
1387 $parentField = '';
1388 $keyList = (empty($InfoFieldList[2]) ? 'rowid' : $InfoFieldList[2].' as rowid');
1389
1390 if (count($InfoFieldList) > 3 && !empty($InfoFieldList[3])) {
1391 list($parentName, $parentField) = explode('|', $InfoFieldList[3]);
1392 $keyList .= ', '.$parentField;
1393 }
1394 if (count($InfoFieldList) > 4 && !empty($InfoFieldList[4])) {
1395 if (strpos($InfoFieldList[4], 'extra.') !== false) {
1396 $keyList = 'main.'.$InfoFieldList[2].' as rowid';
1397 } else {
1398 $keyList = $InfoFieldList[2].' as rowid';
1399 }
1400 }
1401
1402 $filter_categorie = false;
1403 if (count($InfoFieldList) > 5) {
1404 if ($InfoFieldList[0] == 'categorie') {
1405 $filter_categorie = true;
1406 }
1407 }
1408
1409 if ($filter_categorie === false) {
1410 $fields_label = explode('|', $InfoFieldList[1]);
1411 if (is_array($fields_label)) {
1412 $keyList .= ', ';
1413 $keyList .= implode(', ', $fields_label);
1414 }
1415
1416 $sqlwhere = '';
1417 $sql = "SELECT ".$keyList;
1418 $sql .= ' FROM '.$this->db->prefix().$InfoFieldList[0];
1419
1420 // Add filter from 4th field
1421 if (!empty($InfoFieldList[4])) {
1422 // can use current entity filter
1423 if (strpos($InfoFieldList[4], '$ENTITY$') !== false) {
1424 $InfoFieldList[4] = str_replace('$ENTITY$', (string) $conf->entity, $InfoFieldList[4]);
1425 }
1426 // can use SELECT request
1427 if (strpos($InfoFieldList[4], '$SEL$') !== false) {
1428 $InfoFieldList[4] = str_replace('$SEL$', 'SELECT', $InfoFieldList[4]);
1429 }
1430
1431 // current object id can be use into filter
1432 if (strpos($InfoFieldList[4], '$ID$') !== false && !empty($objectid)) {
1433 $InfoFieldList[4] = str_replace('$ID$', (string) $objectid, $InfoFieldList[4]);
1434 } else {
1435 $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
1436 }
1437
1438 // We have to join on extrafield table
1439 $errstr = '';
1440 if (strpos($InfoFieldList[4], 'extra.') !== false) {
1441 $sql .= ' as main, '.$this->db->sanitize($this->db->prefix().$InfoFieldList[0]).'_extrafields as extra';
1442 $sqlwhere .= " WHERE extra.fk_object = main.".$this->db->sanitize($InfoFieldList[2]);
1443 $sqlwhere .= " AND " . forgeSQLFromUniversalSearchCriteria($InfoFieldList[4], $errstr, 1);
1444 } else {
1445 $sqlwhere .= " WHERE " . forgeSQLFromUniversalSearchCriteria($InfoFieldList[4], $errstr, 1);
1446 }
1447 } else {
1448 $sqlwhere .= ' WHERE 1=1';
1449 }
1450
1451 // Add Usf filter on second line
1452 /*
1453 if ($Usf) {
1454 $errorstr = '';
1455 $sqlusf .= forgeSQLFromUniversalSearchCriteria($Usf, $errorstr);
1456 if (!$errorstr) {
1457 $sqlwhere .= $sqlusf;
1458 } else {
1459 $sqlwhere .= " AND invalid_usf_filter_of_extrafield";
1460 }
1461 }
1462 */
1463
1464 // Some tables may have field, some other not. For the moment we disable it.
1465 if (in_array($InfoFieldList[0], array('tablewithentity'))) {
1466 $sqlwhere .= ' AND entity = '.((int) $conf->entity);
1467 }
1468 $sql .= $sqlwhere;
1469 //print $sql;
1470
1471 $sql .= ' ORDER BY '.implode(', ', $fields_label);
1472
1473 dol_syslog(get_class($this).'::showInputField type=sellist', LOG_DEBUG);
1474 $resql = $this->db->query($sql);
1475 if ($resql) {
1476 $out .= '<option value="0">&nbsp;</option>';
1477 $num = $this->db->num_rows($resql);
1478 $i = 0;
1479 while ($i < $num) {
1480 $labeltoshow = '';
1481 $obj = $this->db->fetch_object($resql);
1482
1483 // Several field into label (eq table:code|label:rowid)
1484 $notrans = false;
1485 $fields_label = explode('|', $InfoFieldList[1]);
1486 if (is_array($fields_label) && count($fields_label) > 1) {
1487 $notrans = true;
1488 foreach ($fields_label as $field_toshow) {
1489 $labeltoshow .= $obj->$field_toshow.' ';
1490 }
1491 } else {
1492 $labeltoshow = $obj->{$InfoFieldList[1]};
1493 }
1494
1495 if ($value == $obj->rowid) {
1496 if (!$notrans) {
1497 foreach ($fields_label as $field_toshow) {
1498 $translabel = $langs->trans($obj->$field_toshow);
1499 $labeltoshow = $translabel.' ';
1500 }
1501 }
1502 $out .= '<option value="'.$obj->rowid.'" selected>'.$labeltoshow.'</option>';
1503 } else {
1504 if (!$notrans) {
1505 $translabel = $langs->trans($obj->{$InfoFieldList[1]});
1506 $labeltoshow = $translabel;
1507 }
1508 if (empty($labeltoshow)) {
1509 $labeltoshow = '(not defined)';
1510 }
1511
1512 if (!empty($InfoFieldList[3]) && $parentField) {
1513 $parent = $parentName.':'.$obj->{$parentField};
1514 }
1515
1516 $out .= '<option value="'.$obj->rowid.'"';
1517 $out .= ($value == $obj->rowid ? ' selected' : '');
1518 $out .= (!empty($parent) ? ' parent="'.$parent.'"' : '');
1519 $out .= '>'.$labeltoshow.'</option>';
1520 }
1521
1522 $i++;
1523 }
1524 $this->db->free($resql);
1525 } else {
1526 print 'Error in request '.$sql.' '.$this->db->lasterror().'. Check setup of extra parameters.<br>';
1527 }
1528 } else {
1529 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1530 $data = $form->select_all_categories(Categorie::$MAP_ID_TO_CODE[$InfoFieldList[5]], '', 'parent', 64, $InfoFieldList[6], 1, 1);
1531 $out .= '<option value="0">&nbsp;</option>';
1532 if (is_array($data)) {
1533 foreach ($data as $data_key => $data_value) {
1534 $out .= '<option value="'.$data_key.'"';
1535 $out .= ($value == $data_key ? ' selected' : '');
1536 $out .= '>'.$data_value.'</option>';
1537 }
1538 }
1539 }
1540 }
1541 $out .= '</select>';
1542 } elseif ($type == 'checkbox') {
1543 $value_arr = $value;
1544 if (!is_array($value)) {
1545 $value_arr = explode(',', $value);
1546 }
1547 $out = $form->multiselectarray($keyprefix.$key.$keysuffix, (empty($param['options']) ? null : $param['options']), $value_arr, '', 0, '', 0, '100%');
1548 } elseif ($type == 'radio') {
1549 $out = '';
1550 foreach ($param['options'] as $keyopt => $val) {
1551 $out .= '<input class="flat '.$morecss.'" type="radio" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam ? $moreparam : '');
1552 $out .= ' value="'.$keyopt.'"';
1553 $out .= ' id="'.$keyprefix.$key.$keysuffix.'_'.$keyopt.'"';
1554 $out .= ($value == $keyopt ? 'checked' : '');
1555 $out .= '/><label for="'.$keyprefix.$key.$keysuffix.'_'.$keyopt.'">'.$langs->trans($val).'</label><br>';
1556 }
1557 } elseif ($type == 'chkbxlst') { // List of values selected from a table (n choices)
1558 if (is_array($value)) {
1559 $value_arr = $value;
1560 } else {
1561 $value_arr = explode(',', $value);
1562 }
1563
1564 if (is_array($param['options'])) {
1565 $tmpparamoptions = array_keys($param['options']);
1566 $paramoptions = preg_split('/[\r\n]+/', $tmpparamoptions[0]);
1567
1568 $InfoFieldList = explode(":", $paramoptions[0], 5);
1569 // 0 : tableName
1570 // 1 : label field name
1571 // 2 : key fields name (if different of rowid)
1572 // optional parameters...
1573 // 3 : key field parent (for dependent lists). How this is used ?
1574 // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value. Or use USF on the second line.
1575 // 5 : string category type. This replace the filter.
1576 // 6 : ids categories list separated by comma for category root. This replace the filter.
1577 // 7 : sort field (not used here but used into format for commobject)
1578
1579 // If there is a filter, we extract it by taking all content inside parenthesis.
1580 if (! empty($InfoFieldList[4])) {
1581 $pos = 0;
1582 $parenthesisopen = 0;
1583 while (substr($InfoFieldList[4], $pos, 1) !== '' && ($parenthesisopen || $pos == 0 || substr($InfoFieldList[4], $pos, 1) != ':')) {
1584 if (substr($InfoFieldList[4], $pos, 1) == '(') {
1585 $parenthesisopen++;
1586 }
1587 if (substr($InfoFieldList[4], $pos, 1) == ')') {
1588 $parenthesisopen--;
1589 }
1590 $pos++;
1591 }
1592 $tmpbefore = substr($InfoFieldList[4], 0, $pos);
1593 $tmpafter = substr($InfoFieldList[4], $pos + 1);
1594 //var_dump($InfoFieldList[4].' -> '.$pos); var_dump($tmpafter);
1595 $InfoFieldList[4] = $tmpbefore;
1596 if ($tmpafter !== '') {
1597 $InfoFieldList = array_merge($InfoFieldList, explode(':', $tmpafter));
1598 }
1599
1600 // Fix better compatibility with some old extrafield syntax filter "(field=123)"
1601 $reg = array();
1602 if (preg_match('/^\‍(?([a-z0-9]+)([=<>]+)(\d+)\‍)?$/i', $InfoFieldList[4], $reg)) {
1603 $InfoFieldList[4] = '('.$reg[1].':'.$reg[2].':'.$reg[3].')';
1604 }
1605
1606 //var_dump($InfoFieldList);
1607 }
1608
1609 //$Usf = empty($paramoptions[1]) ? '' :$paramoptions[1];
1610
1611 $parentName = '';
1612 $parentField = '';
1613 $keyList = (empty($InfoFieldList[2]) ? 'rowid' : $InfoFieldList[2].' as rowid');
1614
1615 if (count($InfoFieldList) > 3 && !empty($InfoFieldList[3])) {
1616 list($parentName, $parentField) = explode('|', $InfoFieldList[3]);
1617 $keyList .= ', '.$parentField;
1618 }
1619 if (count($InfoFieldList) > 4 && !empty($InfoFieldList[4])) {
1620 if (strpos($InfoFieldList[4], 'extra.') !== false) {
1621 $keyList = 'main.'.$InfoFieldList[2].' as rowid';
1622 } else {
1623 $keyList = $InfoFieldList[2].' as rowid';
1624 }
1625 }
1626
1627 $filter_categorie = false;
1628 if (count($InfoFieldList) > 5) {
1629 if ($InfoFieldList[0] == 'categorie') {
1630 $filter_categorie = true;
1631 }
1632 }
1633
1634 if ($filter_categorie === false) {
1635 $fields_label = explode('|', $InfoFieldList[1]);
1636 if (is_array($fields_label)) {
1637 $keyList .= ', ';
1638 $keyList .= implode(', ', $fields_label);
1639 }
1640
1641 $sqlwhere = '';
1642 $sql = "SELECT ".$keyList;
1643 $sql .= ' FROM '.$this->db->prefix().$InfoFieldList[0];
1644
1645 // Add filter from 4th field
1646 if (!empty($InfoFieldList[4])) {
1647 // can use current entity filter
1648 if (strpos($InfoFieldList[4], '$ENTITY$') !== false) {
1649 $InfoFieldList[4] = str_replace('$ENTITY$', (string) $conf->entity, $InfoFieldList[4]);
1650 }
1651 // can use SELECT request
1652 if (strpos($InfoFieldList[4], '$SEL$') !== false) {
1653 $InfoFieldList[4] = str_replace('$SEL$', 'SELECT', $InfoFieldList[4]);
1654 }
1655
1656 // current object id can be use into filter
1657 if (strpos($InfoFieldList[4], '$ID$') !== false && !empty($objectid)) {
1658 $InfoFieldList[4] = str_replace('$ID$', (string) $objectid, $InfoFieldList[4]);
1659 } elseif (preg_match("#^.*list.php$#", $_SERVER["PHP_SELF"])) {
1660 // Pattern for word=$ID$
1661 $word = '\b[a-zA-Z0-9-\.-_]+\b=\$ID\$';
1662
1663 // Removing spaces around =, ( and )
1664 $InfoFieldList[4] = preg_replace('# *(=|\‍(|\‍)) *#', '$1', $InfoFieldList[4]);
1665
1666 $nbPreg = 1;
1667 // While we have parenthesis
1668 while ($nbPreg != 0) {
1669 // Initialise counters
1670 $nbPregRepl = $nbPregSel = 0;
1671 // Remove all parenthesis not preceded with '=' sign
1672 $InfoFieldList[4] = preg_replace('#([^=])(\‍([^)^(]*('.$word.')[^)^(]*\‍))#', '$1 $3 ', $InfoFieldList[4], -1, $nbPregRepl);
1673 // Remove all escape characters around '=' and parenthesis
1674 $InfoFieldList[4] = preg_replace('# *(=|\‍(|\‍)) *#', '$1', $InfoFieldList[4]);
1675 // Remove all parentheses preceded with '='
1676 $InfoFieldList[4] = preg_replace('#\b[a-zA-Z0-9-\.-_]+\b=\‍([^)^(]*('.$word.')[^)^(]*\‍)#', '$1 ', $InfoFieldList[4], -1, $nbPregSel);
1677 // On retire les escapes autour des = et parenthèses
1678 $InfoFieldList[4] = preg_replace('# *(=|\‍(|\‍)) *#', '$1', $InfoFieldList[4]);
1679
1680 // UPdate the totals counter for the loop
1681 $nbPreg = $nbPregRepl + $nbPregSel;
1682 }
1683
1684 // In case there is AND ou OR, before or after
1685 $matchCondition = array();
1686 preg_match('#(AND|OR|) *('.$word.') *(AND|OR|)#', $InfoFieldList[4], $matchCondition);
1687 while (!empty($matchCondition[0])) {
1688 // If the two sides differ but are not empty
1689 if (!empty($matchCondition[1]) && !empty($matchCondition[3]) && $matchCondition[1] != $matchCondition[3]) {
1690 // Nobody sain would do that without parentheses
1691 $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
1692 } else {
1693 if (!empty($matchCondition[1])) {
1694 $boolCond = (($matchCondition[1] == "AND") ? ' AND TRUE ' : ' OR FALSE ');
1695 $InfoFieldList[4] = str_replace($matchCondition[0], $boolCond.$matchCondition[3], $InfoFieldList[4]);
1696 } elseif (!empty($matchCondition[3])) {
1697 $boolCond = (($matchCondition[3] == "AND") ? ' TRUE AND ' : ' FALSE OR');
1698 $InfoFieldList[4] = str_replace($matchCondition[0], $boolCond, $InfoFieldList[4]);
1699 } else {
1700 $InfoFieldList[4] = " TRUE ";
1701 }
1702 }
1703
1704 // In case there is AND ou OR, before or after
1705 preg_match('#(AND|OR|) *('.$word.') *(AND|OR|)#', $InfoFieldList[4], $matchCondition);
1706 }
1707 } else {
1708 $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
1709 }
1710
1711 // We have to join on extrafield table
1712 $errstr = '';
1713 if (strpos($InfoFieldList[4], 'extra.') !== false) {
1714 $sql .= ' as main, '.$this->db->sanitize($this->db->prefix().$InfoFieldList[0]).'_extrafields as extra';
1715 $sqlwhere .= " WHERE extra.fk_object = main.".$this->db->sanitize($InfoFieldList[2]);
1716 $sqlwhere .= " AND " . forgeSQLFromUniversalSearchCriteria($InfoFieldList[4], $errstr, 1);
1717 } else {
1718 $sqlwhere .= " WHERE " . forgeSQLFromUniversalSearchCriteria($InfoFieldList[4], $errstr, 1);
1719 }
1720 } else {
1721 $sqlwhere .= ' WHERE 1=1';
1722 }
1723
1724 // Add Usf filter on second line
1725 /*
1726 if ($Usf) {
1727 $errorstr = '';
1728 $sqlusf .= forgeSQLFromUniversalSearchCriteria($Usf, $errorstr);
1729 if (!$errorstr) {
1730 $sqlwhere .= $sqlusf;
1731 } else {
1732 $sqlwhere .= " AND invalid_usf_filter_of_extrafield";
1733 }
1734 }
1735 */
1736
1737 // Some tables may have field, some other not. For the moment we disable it.
1738 if (in_array($InfoFieldList[0], array('tablewithentity'))) {
1739 $sqlwhere .= " AND entity = ".((int) $conf->entity);
1740 }
1741 // $sql.=preg_replace('/^ AND /','',$sqlwhere);
1742 // print $sql;
1743
1744 $sql .= $sqlwhere;
1745 $sql .= ' ORDER BY '.implode(', ', $fields_label);
1746
1747 dol_syslog(get_class($this).'::showInputField type=chkbxlst', LOG_DEBUG);
1748 $resql = $this->db->query($sql);
1749 if ($resql) {
1750 $num = $this->db->num_rows($resql);
1751 $i = 0;
1752
1753 $data = array();
1754
1755 while ($i < $num) {
1756 $labeltoshow = '';
1757 $obj = $this->db->fetch_object($resql);
1758
1759 $notrans = false;
1760 // Several field into label (eq table:code|label:rowid)
1761 $fields_label = explode('|', $InfoFieldList[1]);
1762 if (is_array($fields_label)) {
1763 $notrans = true;
1764 foreach ($fields_label as $field_toshow) {
1765 $labeltoshow .= $obj->$field_toshow.' ';
1766 }
1767 } else {
1768 $labeltoshow = $obj->{$InfoFieldList[1]};
1769 }
1770 $labeltoshow = dol_trunc($labeltoshow, 45);
1771
1772 if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1773 $labeltoshow = '';
1774 foreach ($fields_label as $field_toshow) {
1775 $translabel = $langs->trans($obj->$field_toshow);
1776 if ($translabel != $obj->$field_toshow) {
1777 $labeltoshow .= ' '.dol_trunc($translabel, 18).' ';
1778 } else {
1779 $labeltoshow .= ' '.dol_trunc($obj->$field_toshow, 18).' ';
1780 }
1781 }
1782 $data[$obj->rowid] = $labeltoshow;
1783 } else {
1784 if (!$notrans) {
1785 $translabel = $langs->trans($obj->{$InfoFieldList[1]});
1786 if ($translabel != $obj->{$InfoFieldList[1]}) {
1787 $labeltoshow = dol_trunc($translabel, 18);
1788 } else {
1789 $labeltoshow = dol_trunc($obj->{$InfoFieldList[1]}, 18);
1790 }
1791 }
1792 if (empty($labeltoshow)) {
1793 $labeltoshow = '(not defined)';
1794 }
1795
1796 if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1797 $data[$obj->rowid] = $labeltoshow;
1798 }
1799
1800 if (!empty($InfoFieldList[3]) && $parentField) {
1801 $parent = $parentName.':'.$obj->{$parentField};
1802 }
1803
1804 $data[$obj->rowid] = $labeltoshow;
1805 }
1806
1807 $i++;
1808 }
1809 $this->db->free($resql);
1810
1811 $out = $form->multiselectarray($keyprefix.$key.$keysuffix, $data, $value_arr, '', 0, '', 0, '100%');
1812 } else {
1813 print 'Error in request '.$sql.' '.$this->db->lasterror().'. Check setup of extra parameters.<br>';
1814 }
1815 } else {
1816 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1817 $data = $form->select_all_categories(Categorie::$MAP_ID_TO_CODE[$InfoFieldList[5]], '', 'parent', 64, $InfoFieldList[6], 1, 1);
1818 $out = $form->multiselectarray($keyprefix.$key.$keysuffix, $data, $value_arr, '', 0, '', 0, '100%');
1819 }
1820 }
1821 } elseif ($type == 'link') {
1822 $param_list = array_keys($param['options']); // $param_list[0] = 'ObjectName:classPath' but can also be 'ObjectName:classPath:1:(status:=:1)'
1823 /* Removed.
1824 The selectForForms is called with parameter $objectfield defined, so the app can retrieve the filter inside the ajax component instead of being provided as parameters. The
1825 filter was used to pass SQL requests leading to serious SQL injection problem. This should not be possible. Also the call of the ajax was broken by some WAF.
1826 if (strpos($param_list[0], '$ID$') !== false && !empty($objectid)) {
1827 $param_list[0] = str_replace('$ID$', $objectid, $param_list[0]);
1828 }*/
1829 $showempty = (($required && $default != '') ? 0 : 1);
1830
1831 $tmparray = explode(':', $param_list[0]);
1832
1833 $element = $extrafieldsobjectkey; // $extrafieldsobjectkey comes from $object->table_element but we need $object->element
1834 if ($element == 'socpeople') {
1835 $element = 'contact';
1836 } elseif ($element == 'projet') {
1837 $element = 'project';
1838 }
1839
1840 //$objectdesc = $param_list[0]; // Example: 'ObjectName:classPath:1:(status:=:1)' Replaced by next line: this was propagated also a filter by ajax call that was blocked by some WAF
1841 $objectdesc = $tmparray[0]; // Example: 'ObjectName:classPath' To not propagate any filter (selectForForms do ajax call and propagating SQL filter is blocked by some WAF). Also we should use the one into the definition in the ->fields of $elem if found.
1842 $objectfield = $element.':options_'.$key; // Example: 'actioncomm:options_fff' To be used in priority to know object linked with all its definition (including filters)
1843
1844 $out = $form->selectForForms($objectdesc, $keyprefix.$key.$keysuffix, $value, $showempty, '', '', $morecss, '', 0, 0, '', $objectfield);
1845 } elseif (in_array($type, ['point', 'multipts', 'linestrg', 'polygon'])) {
1846 require_once DOL_DOCUMENT_ROOT.'/core/class/dolgeophp.class.php';
1847 $dolgeophp = new DolGeoPHP($this->db);
1848 $geojson = '{}';
1849 $centroidjson = getDolGlobalString('MAIN_INFO_SOCIETE_GEO_COORDINATES', '{}');
1850 if (!empty($value)) {
1851 $tmparray = $dolgeophp->parseGeoString($value);
1852 $geojson = $tmparray['geojson'];
1853 $centroidjson = $tmparray['centroidjson'];
1854 }
1855 if (!preg_match('/search_/', $keyprefix)) {
1856 require_once DOL_DOCUMENT_ROOT.'/core/class/geomapeditor.class.php';
1857 $geomapeditor = new GeoMapEditor();
1858 $out .= $geomapeditor->getHtml($keyprefix.$key.$keysuffix, $geojson, $centroidjson, $type);
1859 } else {
1860 // If keyprefix is search_ or search_options_, we must just use a simple text field
1861 $out = '';
1862 }
1863 } elseif ($type == 'password') {
1864 // If prefix is 'search_', field is used as a filter, we use a common text field.
1865 $out = '<input style="display:none" type="text" name="fakeusernameremembered">'; // Hidden field to reduce impact of evil Google Chrome autopopulate bug.
1866 $out .= '<input autocomplete="new-password" type="'.($keyprefix == 'search_' ? 'text' : 'password').'" class="flat '.$morecss.'" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam ? $moreparam : '').'>';
1867 }
1868 if (!empty($hidden)) {
1869 $out = '<input type="hidden" value="'.$value.'" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'"/>';
1870 }
1871 /* Add comments
1872 if ($type == 'date') $out.=' (YYYY-MM-DD)';
1873 elseif ($type == 'datetime') $out.=' (YYYY-MM-DD HH:MM:SS)';
1874 */
1875 /*if (!empty($help) && $keyprefix != 'search_options_') {
1876 $out .= $form->textwithpicto('', $help, 1, 'help', '', 0, 3);
1877 }*/
1878 return $out;
1879 }
1880
1881
1892 public function showOutputField($key, $value, $moreparam = '', $extrafieldsobjectkey = '', $outputlangs = null)
1893 {
1894 global $conf, $langs;
1895
1896 if (is_null($outputlangs) || !is_object($outputlangs)) {
1897 $outputlangs = $langs;
1898 }
1899
1900 if (empty($extrafieldsobjectkey)) {
1901 dol_syslog(get_class($this).'::showOutputField extrafieldsobjectkey required', LOG_ERR);
1902 return 'BadValueForParamExtraFieldsObjectKey';
1903 }
1904
1905 $label = $this->attributes[$extrafieldsobjectkey]['label'][$key];
1906 $type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
1907 $size = $this->attributes[$extrafieldsobjectkey]['size'][$key]; // Can be '255', '24,8'...
1908 $default = $this->attributes[$extrafieldsobjectkey]['default'][$key];
1909 $computed = $this->attributes[$extrafieldsobjectkey]['computed'][$key];
1910 $unique = $this->attributes[$extrafieldsobjectkey]['unique'][$key];
1911 $required = $this->attributes[$extrafieldsobjectkey]['required'][$key];
1912 $param = $this->attributes[$extrafieldsobjectkey]['param'][$key];
1913 $perms = (int) dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1, 1, '2');
1914 $langfile = $this->attributes[$extrafieldsobjectkey]['langfile'][$key];
1915 $list = (string) dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1, 1, '2');
1916 $help = $this->attributes[$extrafieldsobjectkey]['help'][$key];
1917 $cssview = $this->attributes[$extrafieldsobjectkey]['cssview'][$key];
1918
1919 $hidden = (empty($list) ? 1 : 0); // If $list empty, 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)
1920
1921 if ($hidden) {
1922 return ''; // This is a protection. If field is hidden, we should just not call this method.
1923 }
1924
1925 //if ($computed) $value = // $value is already calculated into $value before calling this method
1926
1927 $showsize = 0;
1928 if ($type == 'date') {
1929 $showsize = 10;
1930 if ($value !== '') {
1931 $value = dol_print_date($value, 'day'); // For date without hour, date is always GMT for storage and output
1932 }
1933 } elseif ($type == 'datetime') {
1934 $showsize = 19;
1935 if ($value !== '') {
1936 $value = dol_print_date($value, 'dayhour', 'tzuserrel');
1937 }
1938 } elseif ($type == 'datetimegmt') {
1939 $showsize = 19;
1940 if ($value !== '') {
1941 $value = dol_print_date($value, 'dayhour', 'gmt');
1942 }
1943 } elseif ($type == 'int') {
1944 $showsize = 10;
1945 } elseif ($type == 'double') {
1946 if (!empty($value)) {
1947 //$value=price($value);
1948 $sizeparts = explode(",", $size);
1949 $number_decimals = array_key_exists(1, $sizeparts) ? $sizeparts[1] : 0;
1950 $value = price($value, 0, $outputlangs, 0, 0, $number_decimals, '');
1951 }
1952 } elseif ($type == 'boolean') {
1953 $checked = '';
1954 if (!empty($value)) {
1955 $checked = ' checked ';
1956 }
1957 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER') < 2) {
1958 $value = '<input type="checkbox" '.$checked.' '.($moreparam ? $moreparam : '').' readonly disabled>';
1959 } else {
1960 $value = yn($value ? 1 : 0);
1961 }
1962 } elseif ($type == 'mail') {
1963 $value = dol_print_email($value, 0, 0, 0, 64, 1, 1);
1964 } elseif ($type == 'ip') {
1965 $value = dol_print_ip($value, 0);
1966 } elseif ($type == 'icon') {
1967 $value = '<span class="'.$value.'"></span>';
1968 } elseif ($type == 'url') {
1969 $value = dol_print_url($value, '_blank', 32, 1);
1970 } elseif ($type == 'phone') {
1971 $value = dol_print_phone($value, '', 0, 0, '', '&nbsp;', 'phone');
1972 } elseif ($type == 'price') {
1973 //$value = price($value, 0, $langs, 0, 0, -1, $conf->currency);
1974 if ($value || $value == '0') {
1975 $value = price($value, 0, $outputlangs, 0, $conf->global->MAIN_MAX_DECIMALS_TOT, -1).' '.$outputlangs->getCurrencySymbol($conf->currency);
1976 }
1977 } elseif ($type == 'pricecy') {
1978 $currency = $conf->currency;
1979 if (!empty($value)) {
1980 // $value in memory is a php string like '0.01:EUR'
1981 $pricetmp = explode(':', $value);
1982 $currency = !empty($pricetmp[1]) ? $pricetmp[1] : $conf->currency;
1983 $value = $pricetmp[0];
1984 }
1985 if ($value || $value == '0') {
1986 $value = price($value, 0, $outputlangs, 0, $conf->global->MAIN_MAX_DECIMALS_TOT, -1, $currency);
1987 }
1988 } elseif ($type == 'select') {
1989 $valstr = (!empty($param['options'][$value]) ? $param['options'][$value] : '');
1990 if (($pos = strpos($valstr, "|")) !== false) {
1991 $valstr = substr($valstr, 0, $pos);
1992 }
1993 if ($langfile && $valstr) {
1994 $value = $outputlangs->trans($valstr);
1995 } else {
1996 $value = $valstr;
1997 }
1998 } elseif ($type == 'sellist') {
1999 $param_list = array_keys($param['options']);
2000 $InfoFieldList = explode(":", $param_list[0]);
2001
2002 $selectkey = "rowid";
2003 $keyList = 'rowid';
2004
2005 if (count($InfoFieldList) >= 3) {
2006 $selectkey = $InfoFieldList[2];
2007 $keyList = $InfoFieldList[2].' as rowid';
2008 }
2009
2010 $fields_label = explode('|', $InfoFieldList[1]);
2011 if (is_array($fields_label)) {
2012 $keyList .= ', ';
2013 $keyList .= implode(', ', $fields_label);
2014 }
2015
2016 $filter_categorie = false;
2017 if (count($InfoFieldList) > 5) {
2018 if ($InfoFieldList[0] == 'categorie') {
2019 $filter_categorie = true;
2020 }
2021 }
2022
2023 $sql = "SELECT ".$keyList;
2024 $sql .= ' FROM '.$this->db->prefix().$InfoFieldList[0];
2025 if (!empty($InfoFieldList[4]) && strpos($InfoFieldList[4], 'extra.') !== false) {
2026 $sql .= ' as main';
2027 }
2028 if ($selectkey == 'rowid' && empty($value)) {
2029 $sql .= " WHERE ".$selectkey." = 0";
2030 } elseif ($selectkey == 'rowid') {
2031 $sql .= " WHERE ".$selectkey." = ".((int) $value);
2032 } else {
2033 $sql .= " WHERE ".$selectkey." = '".$this->db->escape($value)."'";
2034 }
2035
2036 //$sql.= ' AND entity = '.$conf->entity;
2037
2038 dol_syslog(get_class($this).':showOutputField:$type=sellist', LOG_DEBUG);
2039 $resql = $this->db->query($sql);
2040 if ($resql) {
2041 if ($filter_categorie === false) {
2042 $value = ''; // value was used, so now we reste it to use it to build final output
2043
2044 $obj = $this->db->fetch_object($resql);
2045
2046 // Several field into label (eq table:code|label:rowid)
2047 $fields_label = explode('|', $InfoFieldList[1]);
2048
2049 if (is_array($fields_label) && count($fields_label) > 1) {
2050 foreach ($fields_label as $field_toshow) {
2051 $translabel = '';
2052 if (!empty($obj->$field_toshow)) {
2053 $translabel = $outputlangs->trans($obj->$field_toshow);
2054
2055 if ($translabel != $obj->$field_toshow) {
2056 $value .= dol_trunc($translabel, 24) . ' ';
2057 } else {
2058 $value .= $obj->$field_toshow . ' ';
2059 }
2060 }
2061 }
2062 } else {
2063 $translabel = '';
2064 $tmppropname = $InfoFieldList[1];
2065 //$obj->$tmppropname = '';
2066 if (!empty(isset($obj->$tmppropname) ? $obj->$tmppropname : '')) {
2067 $translabel = $outputlangs->trans($obj->$tmppropname);
2068 }
2069 if ($translabel != (isset($obj->$tmppropname) ? $obj->$tmppropname : '')) {
2070 $value = dol_trunc($translabel, 18);
2071 } else {
2072 $value = isset($obj->$tmppropname) ? $obj->$tmppropname : '';
2073 }
2074 }
2075 } else {
2076 $toprint = array();
2077 $obj = $this->db->fetch_object($resql);
2078 if ($obj->rowid) {
2079 require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
2080 $c = new Categorie($this->db);
2081 $result = $c->fetch($obj->rowid);
2082 if ($result > 0) {
2083 $ways = $c->print_all_ways(); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formatted text
2084 foreach ($ways as $way) {
2085 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories"' . ($c->color ? ' style="background: #' . $c->color . ';"' : ' style="background: #bbb"') . '>' . img_object('', 'category') . ' ' . $way . '</li>';
2086 }
2087 }
2088 }
2089 $value = '<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
2090 }
2091 } else {
2092 dol_syslog(get_class($this).'::showOutputField error '.$this->db->lasterror(), LOG_WARNING);
2093 }
2094 } elseif ($type == 'radio') {
2095 if (!isset($param['options'][$value])) {
2096 $outputlangs->load('errors');
2097 $value = $outputlangs->trans('ErrorNoValueForRadioType');
2098 } else {
2099 $value = $outputlangs->trans($param['options'][$value]);
2100 }
2101 } elseif ($type == 'checkbox') {
2102 $value_arr = explode(',', $value);
2103 $value = '';
2104 $toprint = array();
2105 if (is_array($value_arr)) {
2106 foreach ($value_arr as $keyval => $valueval) {
2107 if (!empty($valueval)) {
2108 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.$param['options'][$valueval].'</li>';
2109 }
2110 }
2111 }
2112 $value = '<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
2113 } elseif ($type == 'chkbxlst') {
2114 $value_arr = explode(',', $value);
2115
2116 $param_list = array_keys($param['options']);
2117 $InfoFieldList = explode(":", $param_list[0]);
2118
2119 $selectkey = "rowid";
2120 $keyList = 'rowid';
2121
2122 if (count($InfoFieldList) >= 3) {
2123 $selectkey = $InfoFieldList[2];
2124 $keyList = $InfoFieldList[2].' as rowid';
2125 }
2126
2127 $fields_label = explode('|', $InfoFieldList[1]);
2128 if (is_array($fields_label)) {
2129 $keyList .= ', ';
2130 $keyList .= implode(', ', $fields_label);
2131 }
2132
2133 $filter_categorie = false;
2134 if (count($InfoFieldList) > 5) {
2135 if ($InfoFieldList[0] == 'categorie') {
2136 $filter_categorie = true;
2137 }
2138 }
2139
2140 $sql = "SELECT ".$keyList;
2141 $sql .= " FROM ".$this->db->prefix().$InfoFieldList[0];
2142 if (strpos($InfoFieldList[4], 'extra.') !== false) {
2143 $sql .= ' as main';
2144 }
2145 // $sql.= " WHERE ".$selectkey."='".$this->db->escape($value)."'";
2146 // $sql.= ' AND entity = '.$conf->entity;
2147
2148 dol_syslog(get_class($this).':showOutputField:$type=chkbxlst', LOG_DEBUG);
2149 $resql = $this->db->query($sql);
2150 if ($resql) {
2151 if ($filter_categorie === false) {
2152 $value = ''; // value was used, so now we reste it to use it to build final output
2153 $toprint = array();
2154 while ($obj = $this->db->fetch_object($resql)) {
2155 // Several field into label (eq table:code|label:rowid)
2156 $fields_label = explode('|', $InfoFieldList[1]);
2157 if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
2158 if (is_array($fields_label) && count($fields_label) > 1) {
2159 $label = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">';
2160 foreach ($fields_label as $field_toshow) {
2161 $translabel = '';
2162 if (!empty($obj->$field_toshow)) {
2163 $translabel = $outputlangs->trans($obj->$field_toshow);
2164 }
2165 if ($translabel != $field_toshow) {
2166 $label .= ' '.dol_trunc($translabel, 18);
2167 } else {
2168 $label .= ' '.$obj->$field_toshow;
2169 }
2170 }
2171 $label .= '</li>';
2172 $toprint[] = $label;
2173 } else {
2174 $translabel = '';
2175 if (!empty($obj->{$InfoFieldList[1]})) {
2176 $translabel = $outputlangs->trans($obj->{$InfoFieldList[1]});
2177 }
2178 if ($translabel != $obj->{$InfoFieldList[1]}) {
2179 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.dol_trunc($translabel, 18).'</li>';
2180 } else {
2181 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.$obj->{$InfoFieldList[1]}.'</li>';
2182 }
2183 }
2184 }
2185 }
2186 } else {
2187 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
2188
2189 $toprint = array();
2190 while ($obj = $this->db->fetch_object($resql)) {
2191 if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
2192 $c = new Categorie($this->db);
2193 $c->fetch($obj->rowid);
2194 $ways = $c->print_all_ways(); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formatted text
2195 foreach ($ways as $way) {
2196 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories"'.($c->color ? ' style="background: #'.$c->color.';"' : ' style="background: #bbb"').'>'.img_object('', 'category').' '.$way.'</li>';
2197 }
2198 }
2199 }
2200 }
2201 if (!empty($toprint)) {
2202 $value = '<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
2203 }
2204 } else {
2205 dol_syslog(get_class($this).'::showOutputField error '.$this->db->lasterror(), LOG_WARNING);
2206 }
2207 } elseif ($type == 'link') {
2208 $out = '';
2209
2210 // Only if something to display (perf)
2211 if ($value) { // If we have -1 here, pb is into insert, not into output (fix insert instead of changing code here to compensate)
2212 $param_list = array_keys($param['options']); // $param_list='ObjectName:classPath'
2213
2214 $InfoFieldList = explode(":", $param_list[0]);
2215 $classname = $InfoFieldList[0];
2216 $classpath = $InfoFieldList[1];
2217 if (!empty($classpath)) {
2218 dol_include_once($InfoFieldList[1]);
2219 if ($classname && class_exists($classname)) {
2220 $object = new $classname($this->db);
2221 $object->fetch($value);
2222 $value = $object->getNomUrl(3);
2223 }
2224 } else {
2225 dol_syslog('Error bad setup of extrafield', LOG_WARNING);
2226 return 'Error bad setup of extrafield';
2227 }
2228 }
2229 } elseif ($type == 'point') {
2230 if (!empty($value)) {
2231 require_once DOL_DOCUMENT_ROOT.'/core/class/dolgeophp.class.php';
2232 $dolgeophp = new DolGeoPHP($this->db);
2233 $value = $dolgeophp->getXYString($value);
2234 } else {
2235 $value = '';
2236 }
2237 } elseif (in_array($type, ['multipts','linestrg', 'polygon'])) {
2238 if (!empty($value)) {
2239 require_once DOL_DOCUMENT_ROOT.'/core/class/dolgeophp.class.php';
2240 $dolgeophp = new DolGeoPHP($this->db);
2241 $value = $dolgeophp->getPointString($value);
2242 } else {
2243 $value = '';
2244 }
2245 } elseif ($type == 'text') {
2246 $value = '<div class="'.($cssview ? $cssview : 'shortmessagecut').'">'.dol_htmlentitiesbr($value).'</div>';
2247 } elseif ($type == 'html') {
2248 $value = dol_htmlentitiesbr($value);
2249 } elseif ($type == 'password') {
2250 $value = dol_trunc(preg_replace('/./i', '*', $value), 8, 'right', 'UTF-8', 1);
2251 } else {
2252 $showsize = round((float) $size);
2253 if ($showsize > 48) {
2254 $showsize = 48;
2255 }
2256 }
2257
2258 //print $type.'-'.$size;
2259 $out = $value;
2260
2261 return $out;
2262 }
2263
2271 public function getAlignFlag($key, $extrafieldsobjectkey = '')
2272 {
2273 $type = 'varchar';
2274 if (!empty($extrafieldsobjectkey)) {
2275 $type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
2276 }
2277
2278 $cssstring = '';
2279
2280 if (in_array($type, array('date', 'datetime', 'datetimegmt',))) {
2281 $cssstring = "center";
2282 } elseif (in_array($type, array('int', 'price', 'double'))) {
2283 $cssstring = "right";
2284 } elseif (in_array($type, array('boolean', 'radio', 'checkbox', 'ip', 'icon'))) {
2285 $cssstring = "center";
2286 }
2287
2288 if (!empty($this->attributes[$extrafieldsobjectkey]['csslist'][$key])) {
2289 $cssstring .= ($cssstring ? ' ' : '').$this->attributes[$extrafieldsobjectkey]['csslist'][$key];
2290 } else {
2291 if (in_array($type, array('ip'))) {
2292 $cssstring .= ($cssstring ? ' ' : '').'tdoverflowmax150';
2293 }
2294 }
2295
2296 return $cssstring;
2297 }
2298
2309 public function showSeparator($key, $object, $colspan = 2, $display_type = 'card', $mode = '')
2310 {
2311 global $conf, $langs;
2312
2313 $tagtype = 'tr';
2314 $tagtype_dyn = 'td';
2315
2316 if ($display_type == 'line') {
2317 $tagtype = 'div';
2318 $tagtype_dyn = 'span';
2319 $colspan = 0;
2320 }
2321
2322 $extrafield_param = $this->attributes[$object->table_element]['param'][$key];
2323 $extrafield_param_list = array();
2324 if (!empty($extrafield_param) && is_array($extrafield_param)) {
2325 $extrafield_param_list = array_keys($extrafield_param['options']);
2326 }
2327
2328 // Set $extrafield_collapse_display_value (do we have to collapse/expand the group after the separator)
2329 $extrafield_collapse_display_value = -1;
2330 $expand_display = false;
2331 if (is_array($extrafield_param_list) && count($extrafield_param_list) > 0) {
2332 $extrafield_collapse_display_value = intval($extrafield_param_list[0]);
2333 $expand_display = ((isset($_COOKIE['DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key]) || GETPOSTINT('ignorecollapsesetup')) ? (empty($_COOKIE['DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key]) ? false : true) : ($extrafield_collapse_display_value == 2 ? false : true));
2334 }
2335 $disabledcookiewrite = 0;
2336 if ($mode == 'create') {
2337 // On create mode, force separator group to not be collapsible
2338 $extrafield_collapse_display_value = 1;
2339 $expand_display = true; // We force group to be shown expanded
2340 $disabledcookiewrite = 1; // We keep status of group unchanged into the cookie
2341 }
2342
2343 $out = '<'.$tagtype.' id="trextrafieldseparator'.$key.(!empty($object->id) ? '_'.$object->id : '').'" class="trextrafieldseparator trextrafieldseparator'.$key.(!empty($object->id) ? '_'.$object->id : '').'">';
2344 $out .= '<'.$tagtype_dyn.' '.(!empty($colspan) ? 'colspan="' . $colspan . '"' : '').'>';
2345 // Some js code will be injected here to manage the collapsing of extrafields
2346 // Output the picto
2347 $out .= '<span class="'.($extrafield_collapse_display_value ? 'cursorpointer ' : '').($extrafield_collapse_display_value == 0 ? 'fas fa-square opacitymedium' : 'far fa-'.(($expand_display ? 'minus' : 'plus').'-square')).'"></span>';
2348 $out .= '&nbsp;';
2349 $out .= '<strong>';
2350 $out .= $langs->trans($this->attributes[$object->table_element]['label'][$key]);
2351 $out .= '</strong>';
2352 $out .= '</'.$tagtype_dyn.'>';
2353 $out .= '</'.$tagtype.'>';
2354
2355 $collapse_group = $key.(!empty($object->id) ? '_'.$object->id : '');
2356 //$extrafields_collapse_num = $this->attributes[$object->table_element]['pos'][$key].(!empty($object->id)?'_'.$object->id:'');
2357
2358 if ($extrafield_collapse_display_value == 1 || $extrafield_collapse_display_value == 2) {
2359 // Set the collapse_display status to cookie in priority or if ignorecollapsesetup is 1, if cookie and ignorecollapsesetup not defined, use the setup.
2360 $this->expand_display[$collapse_group] = $expand_display;
2361
2362 if (!empty($conf->use_javascript_ajax)) {
2363 $out .= '<!-- Add js script to manage the collapse/uncollapse of extrafields separators '.$key.' -->'."\n";
2364 $out .= '<script nonce="'.getNonce().'" type="text/javascript">'."\n";
2365 $out .= 'jQuery(document).ready(function(){'."\n";
2366 if (empty($disabledcookiewrite)) {
2367 if ($expand_display === false) {
2368 $out .= ' console.log("Inject js for the collapsing of extrafield '.$key.' - hide");'."\n";
2369 $out .= ' jQuery(".trextrafields_collapse'.$collapse_group.'").hide();'."\n";
2370 } else {
2371 $out .= ' console.log("Inject js for collapsing of extrafield '.$key.' - keep visible and set cookie");'."\n";
2372 $out .= ' document.cookie = "DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.'=1; path='.$_SERVER["PHP_SELF"].'"'."\n";
2373 }
2374 }
2375 $out .= ' jQuery("#trextrafieldseparator'.$key.(!empty($object->id) ? '_'.$object->id : '').'").click(function(){'."\n";
2376 $out .= ' console.log("We click on collapse/uncollapse to hide/show .trextrafields_collapse'.$collapse_group.'");'."\n";
2377 $out .= ' jQuery(".trextrafields_collapse'.$collapse_group.'").toggle(100, function(){'."\n";
2378 $out .= ' if (jQuery(".trextrafields_collapse'.$collapse_group.'").is(":hidden")) {'."\n";
2379 $out .= ' jQuery("#trextrafieldseparator'.$key.(!empty($object->id) ? '_'.$object->id : '').' '.$tagtype_dyn.' span").addClass("fa-plus-square").removeClass("fa-minus-square");'."\n";
2380 $out .= ' document.cookie = "DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.'=0; path='.$_SERVER["PHP_SELF"].'"'."\n";
2381 $out .= ' } else {'."\n";
2382 $out .= ' jQuery("#trextrafieldseparator'.$key.(!empty($object->id) ? '_'.$object->id : '').' '.$tagtype_dyn.' span").addClass("fa-minus-square").removeClass("fa-plus-square");'."\n";
2383 $out .= ' document.cookie = "DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.'=1; path='.$_SERVER["PHP_SELF"].'"'."\n";
2384 $out .= ' }'."\n";
2385 $out .= ' });'."\n";
2386 $out .= ' });'."\n";
2387 $out .= '});'."\n";
2388 $out .= '</script>'."\n";
2389 }
2390 } else {
2391 $this->expand_display[$collapse_group] = 1;
2392 }
2393
2394 return $out;
2395 }
2396
2408 public function setOptionalsFromPost($extralabels, &$object, $onlykey = '', $todefaultifmissing = 0)
2409 {
2410 global $langs;
2411
2412 $nofillrequired = 0; // For error when required field left blank
2413 $error_field_required = array();
2414
2415 if (isset($this->attributes[$object->table_element]['label']) && is_array($this->attributes[$object->table_element]['label'])) {
2416 $extralabels = $this->attributes[$object->table_element]['label'];
2417 }
2418
2419 if (is_array($extralabels)) {
2420 // Get extra fields
2421 foreach ($extralabels as $key => $value) {
2422 if (!empty($onlykey) && $onlykey != '@GETPOSTISSET' && $key != $onlykey) {
2423 continue;
2424 }
2425
2426 if (!empty($onlykey) && $onlykey == '@GETPOSTISSET' && !GETPOSTISSET('options_'.$key) && (! in_array($this->attributes[$object->table_element]['type'][$key], array('boolean', 'checkbox', 'chkbxlst', 'point', 'multipts', 'linestrg', 'polygon')))) {
2427 //when unticking boolean field, it's not set in POST
2428 continue;
2429 }
2430
2431 $key_type = $this->attributes[$object->table_element]['type'][$key];
2432 if ($key_type == 'separate') {
2433 continue;
2434 }
2435
2436 $enabled = 1;
2437 if (isset($this->attributes[$object->table_element]['enabled'][$key])) { // 'enabled' is often a condition on module enabled or not
2438 $enabled = (int) dol_eval($this->attributes[$object->table_element]['enabled'][$key], 1, 1, '2');
2439 }
2440
2441 $visibility = 1;
2442 if (isset($this->attributes[$object->table_element]['list'][$key])) { // 'list' is option for visibility
2443 $visibility = (int) dol_eval($this->attributes[$object->table_element]['list'][$key], 1, 1, '2');
2444 }
2445
2446 $perms = 1;
2447 if (isset($this->attributes[$object->table_element]['perms'][$key])) {
2448 $perms = (int) dol_eval($this->attributes[$object->table_element]['perms'][$key], 1, 1, '2');
2449 }
2450 if (empty($enabled)
2451 || (
2452 $onlykey === '@GETPOSTISSET'
2453 && in_array($this->attributes[$object->table_element]['type'][$key], array('boolean', 'checkbox', 'chkbxlst'))
2454 && in_array(abs($enabled), array(2, 5))
2455 && ! GETPOSTISSET('options_' . $key) // Update hidden checkboxes and multiselect only if they are provided
2456 )
2457 ) {
2458 continue;
2459 }
2460
2461 $visibility_abs = abs($visibility);
2462 // not modify if extra field is not in update form (0 : never, 2 or -2 : list only, 5 or - 5 : list and view only)
2463 if (empty($visibility_abs) || $visibility_abs == 2 || $visibility_abs == 5) {
2464 continue;
2465 }
2466 if (empty($perms)) {
2467 continue;
2468 }
2469
2470 if ($this->attributes[$object->table_element]['required'][$key]) { // Value is required
2471 // Check if functionally empty without using GETPOST (depending on the type of extrafield, a
2472 // technically non-empty value may be treated as empty functionally).
2473 // value can be alpha, int, array, etc...
2474 $v = $_POST["options_".$key] ?? null;
2475 $type = $this->attributes[$object->table_element]['type'][$key];
2476 if (self::isEmptyValue($v, $type)) {
2477 //print 'ccc'.$value.'-'.$this->attributes[$object->table_element]['required'][$key];
2478
2479 // Field is not defined. We mark this as an error. We may fix it later if there is a default value and $todefaultifmissing is set.
2480
2481 $nofillrequired++;
2482 if (!empty($this->attributes[$object->table_element]['langfile'][$key])) {
2483 $langs->load($this->attributes[$object->table_element]['langfile'][$key]);
2484 }
2485 $error_field_required[$key] = $langs->transnoentitiesnoconv($value);
2486 }
2487 }
2488
2489 if (in_array($key_type, array('date'))) {
2490 // Clean parameters
2491 $value_key = dol_mktime(12, 0, 0, GETPOSTINT("options_".$key."month"), GETPOSTINT("options_".$key."day"), GETPOSTINT("options_".$key."year"));
2492 } elseif (in_array($key_type, array('datetime'))) {
2493 // Clean parameters
2494 $value_key = dol_mktime(GETPOSTINT("options_".$key."hour"), GETPOSTINT("options_".$key."min"), GETPOSTINT("options_".$key."sec"), GETPOSTINT("options_".$key."month"), GETPOSTINT("options_".$key."day"), GETPOSTINT("options_".$key."year"), 'tzuserrel');
2495 } elseif (in_array($key_type, array('datetimegmt'))) {
2496 // Clean parameters
2497 $value_key = dol_mktime(GETPOSTINT("options_".$key."hour"), GETPOSTINT("options_".$key."min"), GETPOSTINT("options_".$key."sec"), GETPOSTINT("options_".$key."month"), GETPOSTINT("options_".$key."day"), GETPOSTINT("options_".$key."year"), 'gmt');
2498 } elseif (in_array($key_type, array('checkbox', 'chkbxlst'))) {
2499 $value_arr = GETPOST("options_".$key, 'array'); // check if an array
2500 if (!empty($value_arr)) {
2501 $value_key = implode(',', $value_arr);
2502 } else {
2503 $value_key = '';
2504 }
2505 } elseif (in_array($key_type, array('price', 'double'))) {
2506 $value_arr = GETPOST("options_".$key, 'alpha');
2507 $value_key = price2num($value_arr);
2508 } elseif (in_array($key_type, array('pricecy', 'double'))) {
2509 $value_key = price2num(GETPOST("options_".$key, 'alpha')).':'.GETPOST("options_".$key."currency_id", 'alpha');
2510 } elseif (in_array($key_type, array('html'))) {
2511 $value_key = GETPOST("options_".$key, 'restricthtml');
2512 } elseif (in_array($key_type, ['point', 'multipts', 'linestrg', 'polygon'])) {
2513 // construct point
2514 require_once DOL_DOCUMENT_ROOT.'/core/class/dolgeophp.class.php';
2515 $geojson = GETPOST("options_".$key, 'restricthtml');
2516 if ($geojson != '{}') {
2517 $dolgeophp = new DolGeoPHP($this->db);
2518 $value_key = $dolgeophp->getWkt($geojson);
2519 } else {
2520 $value_key = '';
2521 }
2522 } elseif (in_array($key_type, array('text'))) {
2523 $label_security_check = 'alphanohtml';
2524 // by default 'alphanohtml' (better security); hidden conf MAIN_SECURITY_ALLOW_UNSECURED_LABELS_WITH_HTML allows basic html
2525 if (getDolGlobalString('MAIN_SECURITY_ALLOW_UNSECURED_REF_LABELS')) {
2526 $label_security_check = 'nohtml';
2527 } else {
2528 $label_security_check = !getDolGlobalString('MAIN_SECURITY_ALLOW_UNSECURED_LABELS_WITH_HTML') ? 'alphanohtml' : 'restricthtml';
2529 }
2530 $value_key = GETPOST("options_".$key, $label_security_check);
2531 } else {
2532 $value_key = GETPOST("options_".$key);
2533 if (in_array($key_type, array('link')) && $value_key == '-1') {
2534 $value_key = '';
2535 }
2536 }
2537
2538 if (!empty($error_field_required[$key]) && $todefaultifmissing) {
2539 // Value is required but we have a default value and we asked to set empty value to the default value
2540 if (!empty($this->attributes[$object->table_element]['default']) && !is_null($this->attributes[$object->table_element]['default'][$key])) {
2541 $value_key = $this->attributes[$object->table_element]['default'][$key];
2542 unset($error_field_required[$key]);
2543 $nofillrequired--;
2544 }
2545 }
2546
2547 $object->array_options["options_".$key] = $value_key;
2548 }
2549
2550 if ($nofillrequired) {
2551 $langs->load('errors');
2552 $this->error = $langs->trans('ErrorFieldsRequired').' : '.implode(', ', $error_field_required);
2553 setEventMessages($this->error, null, 'errors');
2554 return -1;
2555 } else {
2556 return 1;
2557 }
2558 } else {
2559 return 0;
2560 }
2561 }
2562
2571 public function getOptionalsFromPost($extrafieldsobjectkey, $keysuffix = '', $keyprefix = '')
2572 {
2573 global $_POST;
2574
2575 if (is_string($extrafieldsobjectkey) && !empty($this->attributes[$extrafieldsobjectkey]['label']) && is_array($this->attributes[$extrafieldsobjectkey]['label'])) {
2576 $extralabels = $this->attributes[$extrafieldsobjectkey]['label'];
2577 } else {
2578 $extralabels = $extrafieldsobjectkey;
2579 }
2580
2581 if (is_array($extralabels)) {
2582 $array_options = array();
2583
2584 // Get extra fields
2585 foreach ($extralabels as $key => $value) {
2586 $key_type = '';
2587 if (is_string($extrafieldsobjectkey)) {
2588 $key_type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
2589 }
2590
2591 if (in_array($key_type, array('date'))) {
2592 $dateparamname_start = $keyprefix . 'options_' . $key . $keysuffix . '_start';
2593 $dateparamname_end = $keyprefix . 'options_' . $key . $keysuffix . '_end';
2594
2595 if (GETPOST($dateparamname_start . 'year') || GETPOST($dateparamname_end . 'year')) {
2596 $value_key = array();
2597 // values provided as a component year, month, day, etc.
2598 if (GETPOST($dateparamname_start . 'year')) {
2599 $value_key['start'] = dol_mktime(0, 0, 0, GETPOSTINT($dateparamname_start . 'month'), GETPOSTINT($dateparamname_start . 'day'), GETPOSTINT($dateparamname_start . 'year'));
2600 }
2601 if (GETPOST($dateparamname_end . 'year')) {
2602 $value_key['end'] = dol_mktime(23, 59, 59, GETPOSTINT($dateparamname_end . 'month'), GETPOSTINT($dateparamname_end . 'day'), GETPOSTINT($dateparamname_end . 'year'));
2603 }
2604 } elseif (GETPOST($keyprefix."options_".$key.$keysuffix."year")) {
2605 // Clean parameters
2606 $value_key = dol_mktime(12, 0, 0, GETPOSTINT($keyprefix."options_".$key.$keysuffix."month"), GETPOSTINT($keyprefix."options_".$key.$keysuffix."day"), GETPOSTINT($keyprefix."options_".$key.$keysuffix."year"));
2607 } else {
2608 continue; // Value was not provided, we should not set it.
2609 }
2610 } elseif (in_array($key_type, array('datetime', 'datetimegmt'))) {
2611 $dateparamname_start = $keyprefix . 'options_' . $key . $keysuffix . '_start';
2612 $dateparamname_end = $keyprefix . 'options_' . $key . $keysuffix . '_end';
2613
2614 if (GETPOST($dateparamname_start . 'year') || GETPOST($dateparamname_end . 'year')) {
2615 // values provided as a date pair (start date + end date), each date being broken down as year, month, day, etc.
2616 $dateparamname_start_hour = GETPOSTINT($dateparamname_start . 'hour') != '-1' ? GETPOSTINT($dateparamname_start . 'hour') : '00';
2617 $dateparamname_start_min = GETPOSTINT($dateparamname_start . 'min') != '-1' ? GETPOSTINT($dateparamname_start . 'min') : '00';
2618 $dateparamname_start_sec = GETPOSTINT($dateparamname_start . 'sec') != '-1' ? GETPOSTINT($dateparamname_start . 'sec') : '00';
2619 $dateparamname_end_hour = GETPOSTINT($dateparamname_end . 'hour') != '-1' ? GETPOSTINT($dateparamname_end . 'hour') : '23';
2620 $dateparamname_end_min = GETPOSTINT($dateparamname_end . 'min') != '-1' ? GETPOSTINT($dateparamname_end . 'min') : '59';
2621 $dateparamname_end_sec = GETPOSTINT($dateparamname_end . 'sec') != '-1' ? GETPOSTINT($dateparamname_end . 'sec') : '59';
2622 if ($key_type == 'datetimegmt') {
2623 $value_key = array(
2624 'start' => dol_mktime($dateparamname_start_hour, $dateparamname_start_min, $dateparamname_start_sec, GETPOSTINT($dateparamname_start . 'month'), GETPOSTINT($dateparamname_start . 'day'), GETPOSTINT($dateparamname_start . 'year'), 'gmt'),
2625 'end' => dol_mktime($dateparamname_end_hour, $dateparamname_end_min, $dateparamname_end_sec, GETPOSTINT($dateparamname_end . 'month'), GETPOSTINT($dateparamname_end . 'day'), GETPOSTINT($dateparamname_end . 'year'), 'gmt')
2626 );
2627 } else {
2628 $value_key = array(
2629 'start' => dol_mktime($dateparamname_start_hour, $dateparamname_start_min, $dateparamname_start_sec, GETPOSTINT($dateparamname_start . 'month'), GETPOSTINT($dateparamname_start . 'day'), GETPOSTINT($dateparamname_start . 'year'), 'tzuserrel'),
2630 'end' => dol_mktime($dateparamname_end_hour, $dateparamname_end_min, $dateparamname_end_sec, GETPOSTINT($dateparamname_end . 'month'), GETPOSTINT($dateparamname_end . 'day'), GETPOSTINT($dateparamname_end . 'year'), 'tzuserrel')
2631 );
2632 }
2633 } elseif (GETPOST($keyprefix."options_".$key.$keysuffix."year")) {
2634 // Clean parameters
2635 if ($key_type == 'datetimegmt') {
2636 $value_key = dol_mktime(GETPOSTINT($keyprefix."options_".$key.$keysuffix."hour"), GETPOSTINT($keyprefix."options_".$key.$keysuffix."min"), GETPOSTINT($keyprefix."options_".$key.$keysuffix."sec"), GETPOSTINT($keyprefix."options_".$key.$keysuffix."month"), GETPOSTINT($keyprefix."options_".$key.$keysuffix."day"), GETPOSTINT($keyprefix."options_".$key.$keysuffix."year"), 'gmt');
2637 } else {
2638 $value_key = dol_mktime(GETPOSTINT($keyprefix."options_".$key.$keysuffix."hour"), GETPOSTINT($keyprefix."options_".$key.$keysuffix."min"), GETPOSTINT($keyprefix."options_".$key.$keysuffix."sec"), GETPOSTINT($keyprefix."options_".$key.$keysuffix."month"), GETPOSTINT($keyprefix."options_".$key.$keysuffix."day"), GETPOSTINT($keyprefix."options_".$key.$keysuffix."year"), 'tzuserrel');
2639 }
2640 } else {
2641 continue; // Value was not provided, we should not set it.
2642 }
2643 } elseif ($key_type == 'select') {
2644 // to detect if we are in search context
2645 if (GETPOSTISARRAY($keyprefix."options_".$key.$keysuffix)) {
2646 $value_arr = GETPOST($keyprefix."options_".$key.$keysuffix, 'array:aZ09');
2647 // Make sure we get an array even if there's only one selected
2648 $value_arr = (array) $value_arr;
2649 $value_key = implode(',', $value_arr);
2650 } else {
2651 $value_key = GETPOST($keyprefix."options_".$key.$keysuffix);
2652 }
2653 } elseif (in_array($key_type, array('checkbox', 'chkbxlst'))) {
2654 // We test on a hidden field named "..._multiselect" that is always set to 1 if param is in form so
2655 // when nothing is provided we can make a difference between noparam in the form and param was set to nothing.
2656 if (!GETPOSTISSET($keyprefix."options_".$key.$keysuffix.'_multiselect')) {
2657 continue; // Value was not provided, we should not set it.
2658 }
2659 $value_arr = GETPOST($keyprefix."options_".$key.$keysuffix);
2660 // Make sure we get an array even if there's only one checkbox
2661 $value_arr = (array) $value_arr;
2662 $value_key = implode(',', $value_arr);
2663 } elseif (in_array($key_type, array('price', 'double', 'int'))) {
2664 if (!GETPOSTISSET($keyprefix."options_".$key.$keysuffix)) {
2665 continue; // Value was not provided, we should not set it.
2666 }
2667 $value_arr = GETPOST($keyprefix."options_".$key.$keysuffix);
2668 if ($keyprefix != 'search_') { // If value is for a search, we must keep complex string like '>100 <=150'
2669 $value_key = price2num($value_arr);
2670 } else {
2671 $value_key = $value_arr;
2672 }
2673 } elseif (in_array($key_type, array('boolean'))) {
2674 // We test on a hidden field named "..._boolean" that is always set to 1 if param is in form so
2675 // when nothing is provided we can make a difference between noparam in the form and param was set to nothing.
2676 if (!GETPOSTISSET($keyprefix."options_".$key.$keysuffix."_boolean")) {
2677 $value_key = '';
2678 } else {
2679 $value_arr = GETPOST($keyprefix."options_".$key.$keysuffix);
2680 $value_key = $value_arr;
2681 }
2682 } elseif (in_array($key_type, array('html'))) {
2683 if (!GETPOSTISSET($keyprefix."options_".$key.$keysuffix)) {
2684 continue; // Value was not provided, we should not set it.
2685 }
2686 $value_key = dol_htmlcleanlastbr(GETPOST($keyprefix."options_".$key.$keysuffix, 'restricthtml'));
2687 } else {
2688 if (!GETPOSTISSET($keyprefix."options_".$key.$keysuffix)) {
2689 continue; // Value was not provided, we should not set it.
2690 }
2691 $value_key = GETPOST($keyprefix."options_".$key.$keysuffix);
2692 }
2693
2694 $array_options[$keyprefix."options_".$key] = $value_key; // No keyprefix here. keyprefix is used only for read.
2695 }
2696
2697 return $array_options;
2698 }
2699
2700 return 0;
2701 }
2702
2708 public static function getListOfTypesLabels()
2709 {
2710 global $langs;
2711
2712 $arraytype2label = array('');
2713
2714 $tmptype2label = ExtraFields::$type2label;
2715 foreach ($tmptype2label as $key => $val) {
2716 $arraytype2label[$key] = $langs->transnoentitiesnoconv($val);
2717 }
2718
2719 if (!getDolGlobalString('MAIN_USE_EXTRAFIELDS_ICON')) {
2720 unset($arraytype2label['icon']);
2721 }
2722 if (!getDolGlobalString('MAIN_USE_GEOPHP')) {
2723 unset($arraytype2label['point']);
2724 unset($arraytype2label['multipts']);
2725 unset($arraytype2label['linestrg']);
2726 unset($arraytype2label['polygon']);
2727 }
2728
2729 return $arraytype2label;
2730 }
2731
2739 public static function isEmptyValue($v, string $type)
2740 {
2741 if ($v === null || $v === '') {
2742 return true;
2743 }
2744 if (is_array($v) || $type == 'select') {
2745 return empty($v);
2746 }
2747 if ($type == 'link') {
2748 return ($v == '-1');
2749 }
2750 if ($type == 'sellist') {
2751 return ($v == '0');
2752 }
2753 return (empty($v) && $v != '0');
2754 }
2755}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='')
Convert a html select field into an ajax combobox.
Definition ajax.lib.php:456
Class to manage categories.
Class to manage a WYSIWYG editor.
Class to manage Geo processing Usage: $dolgeophp=new DolGeoPHP($db);.
Class to manage standard extra fields.
update_label($attrname, $label, $type, $size, $elementtype, $unique=0, $required=0, $pos=0, $param=array(), $alwayseditable=0, $perms='', $list='0', $help='', $default='', $computed='', $entity='', $langfile='', $enabled='1', $totalizable=0, $printable=0, $moreparams=array())
Modify description of personalized attribute This is a private method.
addExtraField($attrname, $label, $type, $pos, $size, $elementtype, $unique=0, $required=0, $default_value='', $param='', $alwayseditable=0, $perms='', $list='-1', $help='', $computed='', $entity='', $langfile='', $enabled='1', $totalizable=0, $printable=0, $moreparams=array())
Add a new extra field parameter.
getAlignFlag($key, $extrafieldsobjectkey='')
Return the CSS to use for this extrafield into list.
getOptionalsFromPost($extrafieldsobjectkey, $keysuffix='', $keyprefix='')
return array_options array of data of extrafields value of object sent by a search form
create_label($attrname, $label='', $type='', $pos=0, $size='', $elementtype='', $unique=0, $required=0, $param='', $alwayseditable=0, $perms='', $list='-1', $help='', $default='', $computed='', $entity='', $langfile='', $enabled='1', $totalizable=0, $printable=0, $moreparams=array())
Add description of a new optional attribute.
showInputField($key, $value, $moreparam='', $keysuffix='', $keyprefix='', $morecss='', $objectid=0, $extrafieldsobjectkey='', $mode=0)
Return HTML string to put an input field into a page Code very similar with showInputField of common ...
fetch_name_optionals_label($elementtype, $forceload=false, $attrname='')
Load the array of extrafields definition $this->attributes.
create($attrname, $type='varchar', $length='255', $elementtype='', $unique=0, $required=0, $default_value='', $param=array(), $perms='', $list='0', $computed='', $help='', $moreparams=array())
Add a new optional attribute.
showSeparator($key, $object, $colspan=2, $display_type='card', $mode='')
Return HTML string to print separator extrafield.
update($attrname, $label, $type, $length, $elementtype, $unique=0, $required=0, $pos=0, $param=array(), $alwayseditable=0, $perms='', $list='', $help='', $default='', $computed='', $entity='', $langfile='', $enabled='1', $totalizable=0, $printable=0, $moreparams=array())
Modify type of a personalized attribute.
static getListOfTypesLabels()
Return array with all possible types and labels of extrafields.
showOutputField($key, $value, $moreparam='', $extrafieldsobjectkey='', $outputlangs=null)
Return HTML string to put an output field into a page.
updateExtraField($attrname, $label, $type, $pos, $size, $elementtype, $unique=0, $required=0, $default_value='', $param='', $alwayseditable=0, $perms='', $list='-1', $help='', $computed='', $entity='', $langfile='', $enabled='1', $totalizable=0, $printable=0, $moreparams=array())
Update an existing extra field parameter.
__construct($db)
Constructor.
delete_label($attrname, $elementtype='')
Delete description of an optional attribute.
setOptionalsFromPost($extralabels, &$object, $onlykey='', $todefaultifmissing=0)
Fill array_options property of object by extrafields value (using for data sent by forms)
static isEmptyValue($v, string $type)
Return if a value is "empty" for a mandatory vision.
Class to manage generation of HTML components Only common components must be here.
Class to manage a Leaflet map width geometrics objects.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
dol_print_phone($phone, $countrycode='', $cid=0, $socid=0, $addlink='', $separ="&nbsp;", $withpicto='', $titlealt='', $adddivfloat=0, $morecss='')
Format phone numbers according to country.
dol_print_ip($ip, $mode=0)
Return an IP formatted to be shown on screen.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
yn($yesno, $case=1, $color=0)
Return yes or no in current language.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_eval($s, $returnvalue=1, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
dol_print_url($url, $target='_blank', $max=32, $withpicto=0, $morecss='')
Show Url link.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
forgeSQLFromUniversalSearchCriteria
dol_print_email($email, $cid=0, $socid=0, $addlink=0, $max=64, $showinvalid=1, $withpicto=0)
Show EMail link formatted for HTML output.
GETPOSTISARRAY($paramname, $method=0)
Return true if the parameter $paramname is submit from a POST OR GET as an array.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
if(!function_exists( 'dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
dol_htmlcleanlastbr($stringtodecode)
This function remove all ending and br at end.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
jsonOrUnserialize($stringtodecode)
Decode an encode string.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...