dolibarr 21.0.0-alpha
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 if ($type == 'separator' || $type == 'separate') {
154 $type = 'separate';
155 $unique = 0;
156 $required = 0;
157 } // Force unique and not required if this is a separator field to avoid troubles.
158 if ($elementtype == 'thirdparty') {
159 $elementtype = 'societe';
160 }
161 if ($elementtype == 'contact') {
162 $elementtype = 'socpeople';
163 }
164
165 // Create field into database except for separator type which is not stored in database
166 if ($type != 'separate') {
167 $result = $this->create($attrname, $type, $size, $elementtype, $unique, $required, $default_value, $param, $perms, $list, $computed, $help, $moreparams);
168 }
169 $err1 = $this->errno;
170 if ($result > 0 || $err1 == 'DB_ERROR_COLUMN_ALREADY_EXISTS' || $type == 'separate') {
171 // Add declaration of field into table
172 $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);
173 $err2 = $this->errno;
174 if ($result2 > 0 || ($err1 == 'DB_ERROR_COLUMN_ALREADY_EXISTS' && $err2 == 'DB_ERROR_RECORD_ALREADY_EXISTS')) {
175 $this->error = '';
176 $this->errno = '0';
177 return 1;
178 } else {
179 return -2;
180 }
181 } else {
182 return -1;
183 }
184 }
185
212 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())
213 {
214 if (empty($attrname)) {
215 return -1;
216 }
217 if (empty($label)) {
218 return -1;
219 }
220
221 $result = 0;
222
223 if ($type == 'separator' || $type == 'separate') {
224 $type = 'separate';
225 $unique = 0;
226 $required = 0;
227 } // Force unique and not required if this is a separator field to avoid troubles.
228 if ($elementtype == 'thirdparty') {
229 $elementtype = 'societe';
230 }
231 if ($elementtype == 'contact') {
232 $elementtype = 'socpeople';
233 }
234
235 // Create field into database except for separator type which is not stored in database
236 if ($type != 'separate') {
237 dol_syslog(get_class($this).'::thisupdate', LOG_DEBUG);
238 $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);
239 }
240 $err1 = $this->errno;
241 if ($result > 0 || $err1 == 'DB_ERROR_COLUMN_ALREADY_EXISTS' || $type == 'separate') {
242 // Add declaration of field into table
243 dol_syslog(get_class($this).'::thislabel', LOG_DEBUG);
244 $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);
245 $err2 = $this->errno;
246 if ($result2 > 0 || ($err1 == 'DB_ERROR_COLUMN_ALREADY_EXISTS' && $err2 == 'DB_ERROR_RECORD_ALREADY_EXISTS')) {
247 $this->error = '';
248 $this->errno = '0';
249 return 1;
250 } else {
251 return -2;
252 }
253 } else {
254 return -1;
255 }
256 }
257
277 private function create($attrname, $type = 'varchar', $length = '255', $elementtype = '', $unique = 0, $required = 0, $default_value = '', $param = array(), $perms = '', $list = '0', $computed = '', $help = '', $moreparams = array())
278 {
279 if ($elementtype == 'thirdparty') {
280 $elementtype = 'societe';
281 }
282 if ($elementtype == 'contact') {
283 $elementtype = 'socpeople';
284 }
285
286 $table = $elementtype.'_extrafields';
287 if ($elementtype == 'categorie') {
288 $table = 'categories_extrafields';
289 }
290
291 if (!empty($attrname) && preg_match("/^\w[a-zA-Z0-9_]*$/", $attrname) && !is_numeric($attrname)) {
292 if ($type == 'boolean') {
293 $typedb = 'int';
294 $lengthdb = '1';
295 } elseif ($type == 'price') {
296 $typedb = 'double';
297 $lengthdb = '24,8';
298 } elseif ($type == 'pricecy') {
299 $typedb = 'varchar';
300 $lengthdb = '64';
301 } elseif ($type == 'phone') {
302 $typedb = 'varchar';
303 $lengthdb = '20';
304 } elseif ($type == 'mail' || $type == 'ip' || $type == 'icon') {
305 $typedb = 'varchar';
306 $lengthdb = '128';
307 } elseif ($type == 'url') {
308 $typedb = 'varchar';
309 $lengthdb = '255';
310 } elseif (($type == 'select') || ($type == 'sellist') || ($type == 'radio') || ($type == 'checkbox') || ($type == 'chkbxlst')) {
311 $typedb = 'varchar';
312 $lengthdb = '255';
313 } elseif ($type == 'link') {
314 $typedb = 'int';
315 $lengthdb = '11';
316 } elseif ($type == 'point') {
317 $typedb = 'point';
318 $lengthdb = '';
319 } elseif ($type == 'multipts') {
320 $typedb = 'multipoint';
321 $lengthdb = '';
322 } elseif ($type == 'linestrg') {
323 $typedb = 'linestring';
324 $lengthdb = '';
325 } elseif ($type == 'polygon') {
326 $typedb = 'polygon';
327 $lengthdb = '';
328 } elseif ($type == 'html') {
329 $typedb = 'text';
330 $lengthdb = $length;
331 } elseif ($type == 'password') {
332 $typedb = 'varchar';
333 $lengthdb = '128';
334 } else {
335 $typedb = $type;
336 $lengthdb = $length;
337 if ($type == 'varchar' && empty($lengthdb)) {
338 $lengthdb = '255';
339 }
340 }
341 $field_desc = array(
342 'type' => $typedb,
343 'value' => $lengthdb,
344 'null' => ($required ? 'NOT NULL' : 'NULL'),
345 'default' => $default_value
346 );
347
348 $result = $this->db->DDLAddField($this->db->prefix().$table, $attrname, $field_desc);
349 if ($result > 0) {
350 if ($unique) {
351 $sql = "ALTER TABLE ".$this->db->prefix().$table." ADD UNIQUE INDEX uk_".$table."_".$attrname." (".$attrname.")";
352 $resql = $this->db->query($sql, 1, 'dml');
353 }
354 return 1;
355 } else {
356 $this->error = $this->db->lasterror();
357 $this->errno = $this->db->lasterrno();
358 return -1;
359 }
360 } else {
361 return 0;
362 }
363 }
364
365 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
393 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())
394 {
395 // phpcs:enable
396 global $conf, $user;
397
398 if ($elementtype == 'thirdparty') {
399 $elementtype = 'societe';
400 }
401 if ($elementtype == 'contact') {
402 $elementtype = 'socpeople';
403 }
404
405 // Clean parameters
406 if (empty($pos)) {
407 $pos = 0;
408 }
409 if (empty($list)) {
410 $list = '0';
411 }
412 if (empty($required)) {
413 $required = 0;
414 }
415 if (empty($unique)) {
416 $unique = 0;
417 }
418 if (empty($printable)) {
419 $printable = 0;
420 }
421 if (empty($alwayseditable)) {
422 $alwayseditable = 0;
423 }
424 if (empty($totalizable)) {
425 $totalizable = 0;
426 }
427
428 $css = '';
429 if (!empty($moreparams) && !empty($moreparams['css'])) {
430 $css = $moreparams['css'];
431 }
432 $csslist = '';
433 if (!empty($moreparams) && !empty($moreparams['csslist'])) {
434 $csslist = $moreparams['csslist'];
435 }
436 $cssview = '';
437 if (!empty($moreparams) && !empty($moreparams['cssview'])) {
438 $cssview = $moreparams['cssview'];
439 }
440
441 if (!empty($attrname) && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname) && !is_numeric($attrname)) {
442 if (is_array($param) && count($param) > 0) {
443 $params = serialize($param);
444 } elseif (strlen($param) > 0) {
445 $params = trim($param);
446 } else {
447 $params = '';
448 }
449
450 $sql = "INSERT INTO ".$this->db->prefix()."extrafields(";
451 $sql .= " name,";
452 $sql .= " label,";
453 $sql .= " type,";
454 $sql .= " pos,";
455 $sql .= " size,";
456 $sql .= " entity,";
457 $sql .= " elementtype,";
458 $sql .= " fieldunique,";
459 $sql .= " fieldrequired,";
460 $sql .= " param,";
461 $sql .= " alwayseditable,";
462 $sql .= " perms,";
463 $sql .= " langs,";
464 $sql .= " list,";
465 $sql .= " printable,";
466 $sql .= " fielddefault,";
467 $sql .= " fieldcomputed,";
468 $sql .= " fk_user_author,";
469 $sql .= " fk_user_modif,";
470 $sql .= " datec,";
471 $sql .= " enabled,";
472 $sql .= " help,";
473 $sql .= " totalizable,";
474 $sql .= " css,";
475 $sql .= " csslist,";
476 $sql .= " cssview";
477 $sql .= " )";
478 $sql .= " VALUES('".$this->db->escape($attrname)."',";
479 $sql .= " '".$this->db->escape($label)."',";
480 $sql .= " '".$this->db->escape($type)."',";
481 $sql .= " ".((int) $pos).",";
482 $sql .= " '".$this->db->escape($size)."',";
483 $sql .= " ".($entity === '' ? $conf->entity : $entity).",";
484 $sql .= " '".$this->db->escape($elementtype)."',";
485 $sql .= " ".((int) $unique).",";
486 $sql .= " ".((int) $required).",";
487 $sql .= " '".$this->db->escape($params)."',";
488 $sql .= " ".((int) $alwayseditable).",";
489 $sql .= " ".($perms ? "'".$this->db->escape($perms)."'" : "null").",";
490 $sql .= " ".($langfile ? "'".$this->db->escape($langfile)."'" : "null").",";
491 $sql .= " '".$this->db->escape($list)."',";
492 $sql .= " '".$this->db->escape($printable)."',";
493 $sql .= " ".($default ? "'".$this->db->escape($default)."'" : "null").",";
494 $sql .= " ".($computed ? "'".$this->db->escape($computed)."'" : "null").",";
495 $sql .= " ".(is_object($user) ? $user->id : 0).",";
496 $sql .= " ".(is_object($user) ? $user->id : 0).",";
497 $sql .= "'".$this->db->idate(dol_now())."',";
498 $sql .= " ".($enabled ? "'".$this->db->escape($enabled)."'" : "1").",";
499 $sql .= " ".($help ? "'".$this->db->escape($help)."'" : "null").",";
500 $sql .= " ".($totalizable ? 'TRUE' : 'FALSE').",";
501 $sql .= " ".($css ? "'".$this->db->escape($css)."'" : "null").",";
502 $sql .= " ".($csslist ? "'".$this->db->escape($csslist)."'" : "null").",";
503 $sql .= " ".($cssview ? "'".$this->db->escape($cssview)."'" : "null");
504 $sql .= ')';
505
506 if ($this->db->query($sql)) {
507 dol_syslog(get_class($this)."::create_label_success", LOG_DEBUG);
508 return 1;
509 } else {
510 dol_syslog(get_class($this)."::create_label_error", LOG_DEBUG);
511 $this->error = $this->db->lasterror();
512 $this->errno = $this->db->lasterrno();
513 return -1;
514 }
515 }
516 return -1;
517 }
518
526 public function delete($attrname, $elementtype = '')
527 {
528 if ($elementtype == 'thirdparty') {
529 $elementtype = 'societe';
530 }
531 if ($elementtype == 'contact') {
532 $elementtype = 'socpeople';
533 }
534
535 $table = $elementtype.'_extrafields';
536 if ($elementtype == 'categorie') {
537 $table = 'categories_extrafields';
538 }
539
540 $error = 0;
541
542 if (!empty($attrname) && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname)) {
543 $result = $this->delete_label($attrname, $elementtype);
544 if ($result < 0) {
545 $this->error = $this->db->lasterror();
546 $this->errors[] = $this->db->lasterror();
547 $error++;
548 }
549
550 if (!$error) {
551 $sql = "SELECT COUNT(rowid) as nb";
552 $sql .= " FROM ".$this->db->prefix()."extrafields";
553 $sql .= " WHERE elementtype = '".$this->db->escape($elementtype)."'";
554 $sql .= " AND name = '".$this->db->escape($attrname)."'";
555 //$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
556 $resql = $this->db->query($sql);
557 if ($resql) {
558 $obj = $this->db->fetch_object($resql);
559 if ($obj->nb <= 0) {
560 $result = $this->db->DDLDropField($this->db->prefix().$table, $attrname); // This also drop the unique key
561 if ($result < 0) {
562 $this->error = $this->db->lasterror();
563 $this->errors[] = $this->db->lasterror();
564 $error++;
565 }
566 }
567 } else {
568 $this->error = $this->db->lasterror();
569 $this->errors[] = $this->db->lasterror();
570 $error++;
571 }
572 }
573 if (empty($error)) {
574 return $result;
575 } else {
576 return $error*-1;
577 }
578 } else {
579 return 0;
580 }
581 }
582
583 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
591 private function delete_label($attrname, $elementtype = '')
592 {
593 // phpcs:enable
594 global $conf;
595
596 if ($elementtype == 'thirdparty') {
597 $elementtype = 'societe';
598 }
599 if ($elementtype == 'contact') {
600 $elementtype = 'socpeople';
601 }
602
603 if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname)) {
604 $sql = "DELETE FROM ".$this->db->prefix()."extrafields";
605 $sql .= " WHERE name = '".$this->db->escape($attrname)."'";
606 $sql .= " AND entity IN (0,".$conf->entity.')';
607 $sql .= " AND elementtype = '".$this->db->escape($elementtype)."'";
608
609 dol_syslog(get_class($this)."::delete_label", LOG_DEBUG);
610 $resql = $this->db->query($sql);
611 if ($resql) {
612 return 1;
613 } else {
614 dol_print_error($this->db);
615 return -1;
616 }
617 } else {
618 return 0;
619 }
620 }
621
649 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())
650 {
651 global $action, $hookmanager;
652
653 if ($elementtype == 'thirdparty') {
654 $elementtype = 'societe';
655 }
656 if ($elementtype == 'contact') {
657 $elementtype = 'socpeople';
658 }
659
660 $table = $elementtype.'_extrafields';
661 if ($elementtype == 'categorie') {
662 $table = 'categories_extrafields';
663 }
664
665 if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname)) {
666 if ($type == 'boolean') {
667 $typedb = 'int';
668 $lengthdb = '1';
669 } elseif ($type == 'price') {
670 $typedb = 'double';
671 $lengthdb = '24,8';
672 } elseif ($type == 'pricecy') {
673 $typedb = 'varchar';
674 $lengthdb = '64';
675 } elseif ($type == 'phone') {
676 $typedb = 'varchar';
677 $lengthdb = '20';
678 } elseif ($type == 'mail' || $type == 'ip' || $type == 'icon') {
679 $typedb = 'varchar';
680 $lengthdb = '128';
681 } elseif ($type == 'url') {
682 $typedb = 'varchar';
683 $lengthdb = '255';
684 } elseif (($type == 'select') || ($type == 'sellist') || ($type == 'radio') || ($type == 'checkbox') || ($type == 'chkbxlst')) {
685 $typedb = 'varchar';
686 $lengthdb = '255';
687 } elseif ($type == 'html') {
688 $typedb = 'text';
689 $lengthdb = $length;
690 } elseif ($type == 'link') {
691 $typedb = 'int';
692 $lengthdb = '11';
693 } elseif ($type == 'point') {
694 $typedb = 'point';
695 $lengthdb = '';
696 } elseif ($type == 'multipts') {
697 $typedb = 'multipoint';
698 $lengthdb = '';
699 } elseif ($type == 'linestrg') {
700 $typedb = 'linestring';
701 $lengthdb = '';
702 } elseif ($type == 'polygon') {
703 $typedb = 'polygon';
704 $lengthdb = '';
705 } elseif ($type == 'password') {
706 $typedb = 'varchar';
707 $lengthdb = '128';
708 } else {
709 $typedb = $type;
710 $lengthdb = $length;
711 }
712 $field_desc = array('type' => $typedb, 'value' => $lengthdb, 'null' => ($required ? 'NOT NULL' : 'NULL'), 'default' => $default);
713
714 if (is_object($hookmanager)) {
715 $hookmanager->initHooks(array('extrafieldsdao'));
716 $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);
717 $reshook = $hookmanager->executeHooks('updateExtrafields', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
718
719 if ($reshook < 0) {
720 $this->error = $this->db->lasterror();
721 return -1;
722 }
723 }
724
725 dol_syslog(get_class($this).'::DDLUpdateField', LOG_DEBUG);
726 if ($type != 'separate') { // No table update when separate type
727 $result = $this->db->DDLUpdateField($this->db->prefix().$table, $attrname, $field_desc);
728 }
729 if ($result > 0 || $type == 'separate') {
730 if ($label) {
731 dol_syslog(get_class($this).'::update_label', LOG_DEBUG);
732 $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);
733 }
734 if ($result > 0) {
735 $sql = '';
736 if ($unique) {
737 dol_syslog(get_class($this).'::update_unique', LOG_DEBUG);
738 $sql = "ALTER TABLE ".$this->db->prefix().$table." ADD UNIQUE INDEX uk_".$table."_".$this->db->sanitize($attrname)." (".$this->db->sanitize($attrname).")";
739 } else {
740 dol_syslog(get_class($this).'::update_common', LOG_DEBUG);
741 $sql = "ALTER TABLE ".$this->db->prefix().$table." DROP INDEX IF EXISTS uk_".$table."_".$this->db->sanitize($attrname);
742 }
743 dol_syslog(get_class($this).'::update', LOG_DEBUG);
744 $resql = $this->db->query($sql, 1, 'dml');
745 /*if ($resql < 0) {
746 $this->error = $this->db->lasterror();
747 return -1;
748 }*/
749 return 1;
750 } else {
751 $this->error = $this->db->lasterror();
752 return -1;
753 }
754 } else {
755 $this->error = $this->db->lasterror();
756 return -1;
757 }
758 } else {
759 return 0;
760 }
761 }
762
763 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
792 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())
793 {
794 // phpcs:enable
795 global $conf, $user;
796 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);
797
798 // Clean parameters
799 if ($elementtype == 'thirdparty') {
800 $elementtype = 'societe';
801 }
802 if ($elementtype == 'contact') {
803 $elementtype = 'socpeople';
804 }
805
806 if (empty($pos)) {
807 $pos = 0;
808 }
809 if (empty($list)) {
810 $list = '0';
811 }
812 if (empty($totalizable)) {
813 $totalizable = 0;
814 }
815 if (empty($required)) {
816 $required = 0;
817 }
818 if (empty($unique)) {
819 $unique = 0;
820 }
821 if (empty($alwayseditable)) {
822 $alwayseditable = 0;
823 }
824
825 $css = '';
826 if (!empty($moreparams) && !empty($moreparams['css'])) {
827 $css = $moreparams['css'];
828 }
829 $csslist = '';
830 if (!empty($moreparams) && !empty($moreparams['csslist'])) {
831 $csslist = $moreparams['csslist'];
832 }
833 $cssview = '';
834 if (!empty($moreparams) && !empty($moreparams['cssview'])) {
835 $cssview = $moreparams['cssview'];
836 }
837
838 if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname)) {
839 $this->db->begin();
840
841 if (is_array($param) && count($param) > 0) {
842 $params = serialize($param);
843 } elseif (is_array($param)) {
844 $params = '';
845 } elseif (strlen($param) > 0) {
846 $params = trim($param);
847 } else {
848 $params = '';
849 }
850
851 if ($entity === '' || $entity != '0') {
852 // We don't want on all entities, we delete all and current
853 $sql_del = "DELETE FROM ".$this->db->prefix()."extrafields";
854 $sql_del .= " WHERE name = '".$this->db->escape($attrname)."'";
855 $sql_del .= " AND entity IN (0, ".($entity === '' ? $conf->entity : $entity).")";
856 $sql_del .= " AND elementtype = '".$this->db->escape($elementtype)."'";
857 } else {
858 // We want on all entities ($entities = '0'), we delete on all only (we keep setup specific to each entity)
859 $sql_del = "DELETE FROM ".$this->db->prefix()."extrafields";
860 $sql_del .= " WHERE name = '".$this->db->escape($attrname)."'";
861 $sql_del .= " AND entity = 0";
862 $sql_del .= " AND elementtype = '".$this->db->escape($elementtype)."'";
863 }
864 $resql1 = $this->db->query($sql_del);
865
866 $sql = "INSERT INTO ".$this->db->prefix()."extrafields(";
867 $sql .= " name,"; // This is code
868 $sql .= " entity,";
869 $sql .= " label,";
870 $sql .= " type,";
871 $sql .= " size,";
872 $sql .= " elementtype,";
873 $sql .= " fieldunique,";
874 $sql .= " fieldrequired,";
875 $sql .= " perms,";
876 $sql .= " langs,";
877 $sql .= " pos,";
878 $sql .= " alwayseditable,";
879 $sql .= " param,";
880 $sql .= " list,";
881 $sql .= " printable,";
882 $sql .= " totalizable,";
883 $sql .= " fielddefault,";
884 $sql .= " fieldcomputed,";
885 $sql .= " fk_user_author,";
886 $sql .= " fk_user_modif,";
887 $sql .= " datec,";
888 $sql .= " enabled,";
889 $sql .= " help,";
890 $sql .= " css,";
891 $sql .= " csslist,";
892 $sql .= " cssview";
893 $sql .= ") VALUES (";
894 $sql .= "'".$this->db->escape($attrname)."',";
895 $sql .= " ".($entity === '' ? $conf->entity : $entity).",";
896 $sql .= " '".$this->db->escape($label)."',";
897 $sql .= " '".$this->db->escape($type)."',";
898 $sql .= " '".$this->db->escape($size)."',";
899 $sql .= " '".$this->db->escape($elementtype)."',";
900 $sql .= " ".$unique.",";
901 $sql .= " ".$required.",";
902 $sql .= " ".($perms ? "'".$this->db->escape($perms)."'" : "null").",";
903 $sql .= " ".($langfile ? "'".$this->db->escape($langfile)."'" : "null").",";
904 $sql .= " ".$pos.",";
905 $sql .= " '".$this->db->escape($alwayseditable)."',";
906 $sql .= " '".$this->db->escape($params)."',";
907 $sql .= " '".$this->db->escape($list)."',";
908 $sql .= " ".((int) $printable).",";
909 $sql .= " ".($totalizable ? 'TRUE' : 'FALSE').",";
910 $sql .= " ".(($default != '') ? "'".$this->db->escape($default)."'" : "null").",";
911 $sql .= " ".($computed ? "'".$this->db->escape($computed)."'" : "null").",";
912 $sql .= " ".$user->id.",";
913 $sql .= " ".$user->id.",";
914 $sql .= "'".$this->db->idate(dol_now())."',";
915 $sql .= "'".$this->db->escape($enabled)."',";
916 $sql .= " ".($help ? "'".$this->db->escape($help)."'" : "null").",";
917 $sql .= " ".($css ? "'".$this->db->escape($css)."'" : "null").",";
918 $sql .= " ".($csslist ? "'".$this->db->escape($csslist)."'" : "null").",";
919 $sql .= " ".($cssview ? "'".$this->db->escape($cssview)."'" : "null");
920 $sql .= ")";
921
922 $resql2 = $this->db->query($sql);
923
924 if ($resql1 && $resql2) {
925 $this->db->commit();
926 return 1;
927 } else {
928 $this->db->rollback();
929 dol_print_error($this->db);
930 return -1;
931 }
932 } else {
933 return 0;
934 }
935 }
936
937 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
946 public function fetch_name_optionals_label($elementtype, $forceload = false, $attrname = '')
947 {
948 // phpcs:enable
949 global $conf;
950
951 if (empty($elementtype)) {
952 return array();
953 }
954
955 if ($elementtype == 'thirdparty') {
956 $elementtype = 'societe';
957 }
958 if ($elementtype == 'contact') {
959 $elementtype = 'socpeople';
960 }
961 if ($elementtype == 'order_supplier') {
962 $elementtype = 'commande_fournisseur';
963 }
964
965 // Test cache $this->attributes[$elementtype]['loaded'] to see if we must do something
966 // TODO
967
968 $array_name_label = array();
969
970 // 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
971 $sql = "SELECT rowid, name, label, type, size, elementtype, fieldunique, fieldrequired, param, pos, alwayseditable, perms, langs, list, printable, totalizable, fielddefault, fieldcomputed, entity, enabled, help,";
972 $sql .= " css, cssview, csslist";
973 $sql .= " FROM ".$this->db->prefix()."extrafields";
974 //$sql.= " WHERE entity IN (0,".$conf->entity.")"; // Filter is done later
975 if ($elementtype && $elementtype != 'all') {
976 $sql .= " WHERE elementtype = '".$this->db->escape($elementtype)."'"; // Filed with object->table_element
977 }
978 if ($attrname && $elementtype && $elementtype != 'all') {
979 $sql .= " AND name = '".$this->db->escape($attrname)."'";
980 }
981 $sql .= " ORDER BY pos";
982
983 $resql = $this->db->query($sql);
984 if ($resql) {
985 $count = 0;
986 if ($this->db->num_rows($resql)) {
987 while ($tab = $this->db->fetch_object($resql)) {
988 if ($tab->entity != 0 && $tab->entity != $conf->entity) {
989 // 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
990 if ($tab->fieldrequired && is_null($tab->fielddefault)) {
991 $this->attributes[$tab->elementtype]['mandatoryfieldsofotherentities'][$tab->name] = $tab->type;
992 }
993 continue;
994 }
995
996 // We can add this attribute to object. TODO Remove this and return $this->attributes[$elementtype]['label']
997 if ($tab->type != 'separate') {
998 $array_name_label[$tab->name] = $tab->label;
999 }
1000
1001
1002 $this->attributes[$tab->elementtype]['type'][$tab->name] = $tab->type;
1003 $this->attributes[$tab->elementtype]['label'][$tab->name] = $tab->label;
1004 $this->attributes[$tab->elementtype]['size'][$tab->name] = $tab->size;
1005 $this->attributes[$tab->elementtype]['elementtype'][$tab->name] = $tab->elementtype;
1006 $this->attributes[$tab->elementtype]['default'][$tab->name] = $tab->fielddefault;
1007 $this->attributes[$tab->elementtype]['computed'][$tab->name] = $tab->fieldcomputed;
1008 $this->attributes[$tab->elementtype]['unique'][$tab->name] = $tab->fieldunique;
1009 $this->attributes[$tab->elementtype]['required'][$tab->name] = $tab->fieldrequired;
1010 $this->attributes[$tab->elementtype]['param'][$tab->name] = ($tab->param ? jsonOrUnserialize($tab->param) : '');
1011 $this->attributes[$tab->elementtype]['pos'][$tab->name] = $tab->pos;
1012 $this->attributes[$tab->elementtype]['alwayseditable'][$tab->name] = $tab->alwayseditable;
1013 $this->attributes[$tab->elementtype]['perms'][$tab->name] = ((is_null($tab->perms) || strlen($tab->perms) == 0) ? 1 : $tab->perms);
1014 $this->attributes[$tab->elementtype]['langfile'][$tab->name] = $tab->langs;
1015 $this->attributes[$tab->elementtype]['list'][$tab->name] = $tab->list;
1016 $this->attributes[$tab->elementtype]['printable'][$tab->name] = $tab->printable;
1017 $this->attributes[$tab->elementtype]['totalizable'][$tab->name] = ($tab->totalizable ? 1 : 0);
1018 $this->attributes[$tab->elementtype]['entityid'][$tab->name] = $tab->entity;
1019 $this->attributes[$tab->elementtype]['enabled'][$tab->name] = $tab->enabled;
1020 $this->attributes[$tab->elementtype]['help'][$tab->name] = $tab->help;
1021 $this->attributes[$tab->elementtype]['css'][$tab->name] = $tab->css;
1022 $this->attributes[$tab->elementtype]['cssview'][$tab->name] = $tab->cssview;
1023 $this->attributes[$tab->elementtype]['csslist'][$tab->name] = $tab->csslist;
1024
1025 $this->attributes[$tab->elementtype]['loaded'] = 1;
1026 $count++;
1027 }
1028 }
1029 if ($elementtype) {
1030 $this->attributes[$elementtype]['loaded'] = 1; // Note: If nothing is found, we also set the key 'loaded' to 1.
1031 $this->attributes[$elementtype]['count'] = $count;
1032 }
1033 } else {
1034 $this->error = $this->db->lasterror();
1035 dol_syslog(get_class($this)."::fetch_name_optionals_label ".$this->error, LOG_ERR);
1036 }
1037
1038 return $array_name_label;
1039 }
1040
1041
1057 public function showInputField($key, $value, $moreparam = '', $keysuffix = '', $keyprefix = '', $morecss = '', $objectid = 0, $extrafieldsobjectkey = '', $mode = 0)
1058 {
1059 global $conf, $langs, $form;
1060
1061 if (!is_object($form)) {
1062 require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
1063 $form = new Form($this->db);
1064 }
1065
1066 $out = '';
1067
1068 if (!preg_match('/options_$/', $keyprefix)) { // Because we work on extrafields, we add 'options_' to prefix if not already added
1069 $keyprefix .= 'options_';
1070 }
1071
1072 if (empty($extrafieldsobjectkey)) {
1073 dol_syslog(get_class($this).'::showInputField extrafieldsobjectkey required', LOG_ERR);
1074 return 'BadValueForParamExtraFieldsObjectKey';
1075 }
1076
1077 $label = $this->attributes[$extrafieldsobjectkey]['label'][$key];
1078 $type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
1079 $size = $this->attributes[$extrafieldsobjectkey]['size'][$key];
1080 $default = $this->attributes[$extrafieldsobjectkey]['default'][$key];
1081 $computed = $this->attributes[$extrafieldsobjectkey]['computed'][$key];
1082 $unique = $this->attributes[$extrafieldsobjectkey]['unique'][$key];
1083 $required = $this->attributes[$extrafieldsobjectkey]['required'][$key];
1084 $param = $this->attributes[$extrafieldsobjectkey]['param'][$key];
1085 $perms = (int) dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1, 1, '2');
1086 $langfile = $this->attributes[$extrafieldsobjectkey]['langfile'][$key];
1087 $list = (string) dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1, 1, '2');
1088 $totalizable = $this->attributes[$extrafieldsobjectkey]['totalizable'][$key];
1089 $help = $this->attributes[$extrafieldsobjectkey]['help'][$key];
1090 $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)
1091
1092 //var_dump('key='.$key.' '.$value.' '.$moreparam.' '.$keysuffix.' '.$keyprefix.' '.$objectid.' '.$extrafieldsobjectkey.' '.$mode);
1093 //var_dump('label='.$label.' type='.$type.' param='.var_export($param, 1));
1094
1095 if ($computed) {
1096 if (!preg_match('/^search_/', $keyprefix)) {
1097 return '<span class="opacitymedium">'.$langs->trans("AutomaticallyCalculated").'</span>';
1098 } else {
1099 return '';
1100 }
1101 }
1102
1103 //
1104 // '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'
1105 if (empty($morecss)) {
1106 // Add automatic css
1107 if ($type == 'date') {
1108 $morecss = 'minwidth100imp';
1109 } elseif ($type == 'datetime' || $type == 'datetimegmt' || $type == 'link') {
1110 $morecss = 'minwidth200imp';
1111 } elseif (in_array($type, array('int', 'integer', 'double', 'price'))) {
1112 $morecss = 'maxwidth75';
1113 } elseif ($type == 'password') {
1114 $morecss = 'maxwidth100';
1115 } elseif ($type == 'url') {
1116 $morecss = 'minwidth400';
1117 } elseif ($type == 'boolean') {
1118 $morecss = '';
1119 } elseif ($type == 'radio') {
1120 $morecss = 'width25';
1121 } else {
1122 if (empty($size) || round((float) $size) < 12) {
1123 $morecss = 'minwidth100';
1124 } elseif (round((float) $size) <= 48) {
1125 $morecss = 'minwidth200';
1126 } else {
1127 $morecss = 'minwidth400';
1128 }
1129 }
1130 // If css forced in attribute, we use this one
1131 if (!empty($this->attributes[$extrafieldsobjectkey]['css'][$key])) {
1132 $morecss = $this->attributes[$extrafieldsobjectkey]['css'][$key];
1133 }
1134 }
1135
1136 if (in_array($type, array('date'))) {
1137 $tmp = explode(',', $size);
1138 $newsize = $tmp[0];
1139 $showtime = 0;
1140
1141 // Do not show current date when field not required (see selectDate() method)
1142 if (!$required && $value == '') {
1143 $value = '-1';
1144 }
1145
1146 if ($mode == 1) {
1147 // search filter on a date extrafield shows two inputs to select a date range
1148 $prefill = array(
1149 'start' => isset($value['start']) ? $value['start'] : '',
1150 'end' => isset($value['end']) ? $value['end'] : ''
1151 );
1152 $out = '<div ' . ($moreparam ? $moreparam : '') . '><div class="nowrap">';
1153 $out .= $form->selectDate($prefill['start'], $keyprefix.$key.$keysuffix.'_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From"));
1154 $out .= '</div><div class="nowrap">';
1155 $out .= $form->selectDate($prefill['end'], $keyprefix.$key.$keysuffix.'_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"));
1156 $out .= '</div></div>';
1157 } else {
1158 // TODO Must also support $moreparam
1159 $out = $form->selectDate($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 0, 1);
1160 }
1161 } elseif (in_array($type, array('datetime', 'datetimegmt'))) {
1162 $tmp = explode(',', $size);
1163 $newsize = $tmp[0];
1164 $showtime = 1;
1165
1166 // Do not show current date when field not required (see selectDate() method)
1167 if (!$required && $value == '') {
1168 $value = '-1';
1169 }
1170
1171 if ($mode == 1) {
1172 // search filter on a date extrafield shows two inputs to select a date range
1173 $prefill = array(
1174 'start' => isset($value['start']) ? $value['start'] : '',
1175 'end' => isset($value['end']) ? $value['end'] : ''
1176 );
1177 $out = '<div ' . ($moreparam ? $moreparam : '') . '><div class="nowrap">';
1178 $out .= $form->selectDate($prefill['start'], $keyprefix.$key.$keysuffix.'_start', 1, 1, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From"), 'tzuserrel');
1179 $out .= '</div><div class="nowrap">';
1180 $out .= $form->selectDate($prefill['end'], $keyprefix.$key.$keysuffix.'_end', 1, 1, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"), 'tzuserrel');
1181 $out .= '</div></div>';
1182 } else {
1183 // TODO Must also support $moreparam
1184 $out = $form->selectDate($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 0, 1, '', '', '', 1, '', '', 'tzuserrel');
1185 }
1186 } elseif (in_array($type, array('int', 'integer'))) {
1187 $tmp = explode(',', $size);
1188 $newsize = $tmp[0];
1189 $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 : '').'>';
1190 } elseif (preg_match('/varchar/', $type)) {
1191 $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 : '').'>';
1192 } elseif (in_array($type, array('mail', 'ip', 'phone', 'url'))) {
1193 $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam ? $moreparam : '').'>';
1194 } elseif ($type == 'icon') {
1195 /* External lib inclusion are not allowed in backoffice. Also lib is included several time if there is several icon file.
1196 Some code must be added into main when MAIN_ADD_ICONPICKER_JS is set to add of lib in html header
1197 $out ='<link rel="stylesheet" href="'.dol_buildpath('/myfield/css/fontawesome-iconpicker.min.css', 1).'">';
1198 $out.='<script src="'.dol_buildpath('/myfield/js/fontawesome-iconpicker.min.js', 1).'"></script>';
1199 */
1200 $out .= '<input type="text" class="form-control icp icp-auto iconpicker-element iconpicker-input flat '.$morecss.' maxwidthonsmartphone"';
1201 $out .= ' name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam ? $moreparam : '').'>';
1202 if (getDolGlobalInt('MAIN_ADD_ICONPICKER_JS')) {
1203 $out .= '<script>';
1204 $options = "{ title: '<b>".$langs->trans("IconFieldSelector")."</b>', placement: 'right', showFooter: false, templates: {";
1205 $options .= "iconpicker: '<div class=\"iconpicker\"><div style=\"background-color:#EFEFEF;\" class=\"iconpicker-items\"></div></div>',";
1206 $options .= "iconpickerItem: '<a role=\"button\" href=\"#\" class=\"iconpicker-item\" style=\"background-color:#DDDDDD;\"><i></i></a>',";
1207 // $options.="buttons: '<button style=\"background-color:#FFFFFF;\" class=\"iconpicker-btn iconpicker-btn-cancel btn btn-default btn-sm\">".$langs->trans("Cancel")."</button>";
1208 // $options.="<button style=\"background-color:#FFFFFF;\" class=\"iconpicker-btn iconpicker-btn-accept btn btn-primary btn-sm\">".$langs->trans("Save")."</button>',";
1209 $options .= "footer: '<div class=\"popover-footer\" style=\"background-color:#EFEFEF;\"></div>',";
1210 $options .= "search: '<input type=\"search\" class\"form-control iconpicker-search\" placeholder=\"".$langs->trans("TypeToFilter")."\" />',";
1211 $options .= "popover: '<div class=\"iconpicker-popover popover\">";
1212 $options .= " <div class=\"arrow\" ></div>";
1213 $options .= " <div class=\"popover-title\" style=\"text-align:center;background-color:#EFEFEF;\"></div>";
1214 $options .= " <div class=\"popover-content \" ></div>";
1215 $options .= "</div>'}}";
1216 $out .= "$('#".$keyprefix.$key.$keysuffix."').iconpicker(".$options.");";
1217 $out .= '</script>';
1218 }
1219 } elseif ($type == 'text') {
1220 if (!preg_match('/search_/', $keyprefix)) { // If keyprefix is search_ or search_options_, we must just use a simple text field
1221 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1222 $doleditor = new DolEditor($keyprefix.$key.$keysuffix, $value, '', 200, 'dolibarr_notes', 'In', false, false, false, ROWS_5, '90%');
1223 $out = (string) $doleditor->Create(1);
1224 } else {
1225 $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam ? $moreparam : '').'>';
1226 }
1227 } elseif ($type == 'html') {
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, isModEnabled('fckeditor') && getDolGlobalInt('FCKEDITOR_ENABLE_SOCIETE'), 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 == 'boolean') {
1236 if (empty($mode)) {
1237 $checked = '';
1238 if (!empty($value)) {
1239 $checked = ' checked value="1" ';
1240 } else {
1241 $checked = ' value="1" ';
1242 }
1243 $out = '<input type="checkbox" class="flat valignmiddle'.($morecss ? ' '.$morecss : '').' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.$checked.' '.($moreparam ? $moreparam : '').'>';
1244 } else {
1245 $out = $form->selectyesno($keyprefix.$key.$keysuffix, $value, 1, false, 1, 1, 'width75 yesno');
1246 }
1247 $out .= '<input type="hidden" name="'.$keyprefix.$key.$keysuffix.'_boolean" value="1">'; // A hidden field ending with "_boolean" that is always set to 1.
1248 } elseif ($type == 'price') {
1249 if (!empty($value)) { // $value in memory is a php numeric, we format it into user number format.
1250 $value = price($value);
1251 }
1252 $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).'">';
1253 } elseif ($type == 'pricecy') {
1254 $currency = $conf->currency;
1255 if (!empty($value)) {
1256 // $value in memory is a php string like '10.01:USD'
1257 $pricetmp = explode(':', $value);
1258 $currency = !empty($pricetmp[1]) ? $pricetmp[1] : $conf->currency;
1259 $value = price($pricetmp[0]);
1260 }
1261 $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam ? $moreparam : '').'> ';
1262 $out .= $form->selectCurrency($currency, $keyprefix.$key.$keysuffix.'currency_id');
1263 } elseif ($type == 'double') {
1264 if (!empty($value)) { // $value in memory is a php numeric, we format it into user number format.
1265 $value = price($value);
1266 }
1267 $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam ? $moreparam : '').'> ';
1268 } elseif ($type == 'select') {
1269 $out = '';
1270 if ($mode) {
1271 $options = array();
1272 foreach ($param['options'] as $okey => $val) {
1273 if ((string) $okey == '') {
1274 continue;
1275 }
1276
1277 $valarray = explode('|', $val);
1278 $val = $valarray[0];
1279
1280 if ($langfile && $val) {
1281 $options[$okey] = $langs->trans($val);
1282 } else {
1283 $options[$okey] = $val;
1284 }
1285 }
1286 $selected = array();
1287 if (!is_array($value)) {
1288 $selected = explode(',', $value);
1289 }
1290
1291 $out .= $form->multiselectarray($keyprefix.$key.$keysuffix, $options, $selected, 0, 0, $morecss, 0, 0, '', '', '', !empty($conf->use_javascript_ajax) && !getDolGlobalString('MAIN_EXTRAFIELDS_DISABLE_SELECT2'));
1292 } else {
1293 if (!empty($conf->use_javascript_ajax) && !getDolGlobalString('MAIN_EXTRAFIELDS_DISABLE_SELECT2')) {
1294 include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
1295 $out .= ajax_combobox($keyprefix.$key.$keysuffix, array(), 0);
1296 }
1297
1298 $out .= '<select class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam ? $moreparam : '').'>';
1299 $out .= '<option value="0">&nbsp;</option>';
1300 foreach ($param['options'] as $key2 => $val2) {
1301 if ((string) $key2 == '') {
1302 continue;
1303 }
1304 $valarray = explode('|', $val2);
1305 $val2 = $valarray[0];
1306 $parent = '';
1307 if (!empty($valarray[1])) {
1308 $parent = $valarray[1];
1309 }
1310 $out .= '<option value="'.$key2.'"';
1311 $out .= (((string) $value == (string) $key2) ? ' selected' : '');
1312 $out .= (!empty($parent) ? ' parent="'.$parent.'"' : '');
1313 $out .= '>';
1314 if ($langfile && $val2) {
1315 $out .= $langs->trans($val2);
1316 } else {
1317 $out .= $val2;
1318 }
1319 $out .= '</option>';
1320 }
1321 $out .= '</select>';
1322 }
1323 } elseif ($type == 'sellist') {
1324 $out = '';
1325 if (!empty($conf->use_javascript_ajax) && !getDolGlobalString('MAIN_EXTRAFIELDS_DISABLE_SELECT2')) {
1326 include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
1327 $out .= ajax_combobox($keyprefix.$key.$keysuffix, array(), 0);
1328 }
1329
1330 $out .= '<select class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam ? $moreparam : '').'>';
1331 if (is_array($param['options'])) {
1332 $param_list = array_keys($param['options']);
1333 $InfoFieldList = explode(":", $param_list[0]);
1334 $parentName = '';
1335 $parentField = '';
1336 // 0 : tableName
1337 // 1 : label field name
1338 // 2 : key fields name (if differ of rowid)
1339 // 3 : key field parent (for dependent lists)
1340 // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value
1341 // 5 : id category type
1342 // 6 : ids categories list separated by comma for category root
1343 // 7 : sort by (to be close to common object)
1344 $keyList = (empty($InfoFieldList[2]) ? 'rowid' : $InfoFieldList[2].' as rowid');
1345
1346
1347 if (count($InfoFieldList) > 4 && !empty($InfoFieldList[4])) {
1348 if (strpos($InfoFieldList[4], 'extra.') !== false) {
1349 $keyList = 'main.'.$InfoFieldList[2].' as rowid';
1350 } else {
1351 $keyList = $InfoFieldList[2].' as rowid';
1352 }
1353 }
1354 if (count($InfoFieldList) > 3 && !empty($InfoFieldList[3])) {
1355 list($parentName, $parentField) = explode('|', $InfoFieldList[3]);
1356 $keyList .= ', '.$parentField;
1357 }
1358
1359 $filter_categorie = false;
1360 if (count($InfoFieldList) > 5) {
1361 if ($InfoFieldList[0] == 'categorie') {
1362 $filter_categorie = true;
1363 }
1364 }
1365
1366 if (!$filter_categorie) {
1367 $fields_label = explode('|', $InfoFieldList[1]);
1368 if (is_array($fields_label)) {
1369 $keyList .= ', ';
1370 $keyList .= implode(', ', $fields_label);
1371 }
1372
1373 $sqlwhere = '';
1374 $sql = "SELECT ".$keyList;
1375 $sql .= ' FROM '.$this->db->prefix().$InfoFieldList[0];
1376 if (!empty($InfoFieldList[4])) {
1377 // can use current entity filter
1378 if (strpos($InfoFieldList[4], '$ENTITY$') !== false) {
1379 $InfoFieldList[4] = str_replace('$ENTITY$', (string) $conf->entity, $InfoFieldList[4]);
1380 }
1381 // can use SELECT request
1382 if (strpos($InfoFieldList[4], '$SEL$') !== false) {
1383 $InfoFieldList[4] = str_replace('$SEL$', 'SELECT', $InfoFieldList[4]);
1384 }
1385
1386 // current object id can be use into filter
1387 if (strpos($InfoFieldList[4], '$ID$') !== false && !empty($objectid)) {
1388 $InfoFieldList[4] = str_replace('$ID$', (string) $objectid, $InfoFieldList[4]);
1389 } else {
1390 $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
1391 }
1392 //We have to join on extrafield table
1393 if (strpos($InfoFieldList[4], 'extra.') !== false) {
1394 $sql .= ' as main, '.$this->db->prefix().$InfoFieldList[0].'_extrafields as extra';
1395 $sqlwhere .= " WHERE extra.fk_object=main.".$InfoFieldList[2]." AND ".$InfoFieldList[4];
1396 } else {
1397 $sqlwhere .= " WHERE ".$InfoFieldList[4];
1398 }
1399 } else {
1400 $sqlwhere .= ' WHERE 1=1';
1401 }
1402 // Some tables may have field, some other not. For the moment we disable it.
1403 if (in_array($InfoFieldList[0], array('tablewithentity'))) {
1404 $sqlwhere .= ' AND entity = '.((int) $conf->entity);
1405 }
1406 $sql .= $sqlwhere;
1407 //print $sql;
1408
1409 $sql .= ' ORDER BY '.implode(', ', $fields_label);
1410
1411 dol_syslog(get_class($this).'::showInputField type=sellist', LOG_DEBUG);
1412 $resql = $this->db->query($sql);
1413 if ($resql) {
1414 $out .= '<option value="0">&nbsp;</option>';
1415 $num = $this->db->num_rows($resql);
1416 $i = 0;
1417 while ($i < $num) {
1418 $labeltoshow = '';
1419 $obj = $this->db->fetch_object($resql);
1420
1421 // Several field into label (eq table:code|label:rowid)
1422 $notrans = false;
1423 $fields_label = explode('|', $InfoFieldList[1]);
1424 if (is_array($fields_label) && count($fields_label) > 1) {
1425 $notrans = true;
1426 foreach ($fields_label as $field_toshow) {
1427 $labeltoshow .= $obj->$field_toshow.' ';
1428 }
1429 } else {
1430 $labeltoshow = $obj->{$InfoFieldList[1]};
1431 }
1432
1433 if ($value == $obj->rowid) {
1434 if (!$notrans) {
1435 foreach ($fields_label as $field_toshow) {
1436 $translabel = $langs->trans($obj->$field_toshow);
1437 $labeltoshow = $translabel.' ';
1438 }
1439 }
1440 $out .= '<option value="'.$obj->rowid.'" selected>'.$labeltoshow.'</option>';
1441 } else {
1442 if (!$notrans) {
1443 $translabel = $langs->trans($obj->{$InfoFieldList[1]});
1444 $labeltoshow = $translabel;
1445 }
1446 if (empty($labeltoshow)) {
1447 $labeltoshow = '(not defined)';
1448 }
1449
1450 if (!empty($InfoFieldList[3]) && $parentField) {
1451 $parent = $parentName.':'.$obj->{$parentField};
1452 }
1453
1454 $out .= '<option value="'.$obj->rowid.'"';
1455 $out .= ($value == $obj->rowid ? ' selected' : '');
1456 $out .= (!empty($parent) ? ' parent="'.$parent.'"' : '');
1457 $out .= '>'.$labeltoshow.'</option>';
1458 }
1459
1460 $i++;
1461 }
1462 $this->db->free($resql);
1463 } else {
1464 print 'Error in request '.$sql.' '.$this->db->lasterror().'. Check setup of extra parameters.<br>';
1465 }
1466 } else {
1467 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1468 $data = $form->select_all_categories(Categorie::$MAP_ID_TO_CODE[$InfoFieldList[5]], '', 'parent', 64, $InfoFieldList[6], 1, 1);
1469 $out .= '<option value="0">&nbsp;</option>';
1470 if (is_array($data)) {
1471 foreach ($data as $data_key => $data_value) {
1472 $out .= '<option value="'.$data_key.'"';
1473 $out .= ($value == $data_key ? ' selected' : '');
1474 $out .= '>'.$data_value.'</option>';
1475 }
1476 }
1477 }
1478 }
1479 $out .= '</select>';
1480 } elseif ($type == 'checkbox') {
1481 $value_arr = $value;
1482 if (!is_array($value)) {
1483 $value_arr = explode(',', $value);
1484 }
1485 $out = $form->multiselectarray($keyprefix.$key.$keysuffix, (empty($param['options']) ? null : $param['options']), $value_arr, '', 0, '', 0, '100%');
1486 } elseif ($type == 'radio') {
1487 $out = '';
1488 foreach ($param['options'] as $keyopt => $val) {
1489 $out .= '<input class="flat '.$morecss.'" type="radio" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam ? $moreparam : '');
1490 $out .= ' value="'.$keyopt.'"';
1491 $out .= ' id="'.$keyprefix.$key.$keysuffix.'_'.$keyopt.'"';
1492 $out .= ($value == $keyopt ? 'checked' : '');
1493 $out .= '/><label for="'.$keyprefix.$key.$keysuffix.'_'.$keyopt.'">'.$langs->trans($val).'</label><br>';
1494 }
1495 } elseif ($type == 'chkbxlst') {
1496 if (is_array($value)) {
1497 $value_arr = $value;
1498 } else {
1499 $value_arr = explode(',', $value);
1500 }
1501
1502 if (is_array($param['options'])) {
1503 $param_list = array_keys($param['options']);
1504 $InfoFieldList = explode(":", $param_list[0]);
1505 $parentName = '';
1506 $parentField = '';
1507 // 0 : tableName
1508 // 1 : label field name
1509 // 2 : key fields name (if differ of rowid)
1510 // 3 : key field parent (for dependent lists)
1511 // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value
1512 // 5 : id category type
1513 // 6 : ids categories list separated by comma for category root
1514 // 7 : sort by (to be close to common object)
1515 $keyList = (empty($InfoFieldList[2]) ? 'rowid' : $InfoFieldList[2].' as rowid');
1516
1517 if (count($InfoFieldList) > 3 && !empty($InfoFieldList[3])) {
1518 list($parentName, $parentField) = explode('|', $InfoFieldList[3]);
1519 $keyList .= ', '.$parentField;
1520 }
1521 if (count($InfoFieldList) > 4 && !empty($InfoFieldList[4])) {
1522 if (strpos($InfoFieldList[4], 'extra.') !== false) {
1523 $keyList = 'main.'.$InfoFieldList[2].' as rowid';
1524 } else {
1525 $keyList = $InfoFieldList[2].' as rowid';
1526 }
1527 }
1528
1529 $filter_categorie = false;
1530 if (count($InfoFieldList) > 5) {
1531 if ($InfoFieldList[0] == 'categorie') {
1532 $filter_categorie = true;
1533 }
1534 }
1535
1536 if (!$filter_categorie) {
1537 $fields_label = explode('|', $InfoFieldList[1]);
1538 if (is_array($fields_label)) {
1539 $keyList .= ', ';
1540 $keyList .= implode(', ', $fields_label);
1541 }
1542
1543 $sqlwhere = '';
1544 $sql = "SELECT ".$keyList;
1545 $sql .= ' FROM '.$this->db->prefix().$InfoFieldList[0];
1546 if (!empty($InfoFieldList[4])) {
1547 // can use current entity filter
1548 if (strpos($InfoFieldList[4], '$ENTITY$') !== false) {
1549 $InfoFieldList[4] = str_replace('$ENTITY$', (string) $conf->entity, $InfoFieldList[4]);
1550 }
1551 // can use SELECT request
1552 if (strpos($InfoFieldList[4], '$SEL$') !== false) {
1553 $InfoFieldList[4] = str_replace('$SEL$', 'SELECT', $InfoFieldList[4]);
1554 }
1555
1556 // current object id can be use into filter
1557 if (strpos($InfoFieldList[4], '$ID$') !== false && !empty($objectid)) {
1558 $InfoFieldList[4] = str_replace('$ID$', (string) $objectid, $InfoFieldList[4]);
1559 } elseif (preg_match("#^.*list.php$#", $_SERVER["PHP_SELF"])) {
1560 // Pattern for word=$ID$
1561 $word = '\b[a-zA-Z0-9-\.-_]+\b=\$ID\$';
1562
1563 // Removing spaces around =, ( and )
1564 $InfoFieldList[4] = preg_replace('# *(=|\‍(|\‍)) *#', '$1', $InfoFieldList[4]);
1565
1566 $nbPreg = 1;
1567 // While we have parenthesis
1568 while ($nbPreg != 0) {
1569 // Initialise counters
1570 $nbPregRepl = $nbPregSel = 0;
1571 // Remove all parenthesis not preceded with '=' sign
1572 $InfoFieldList[4] = preg_replace('#([^=])(\‍([^)^(]*('.$word.')[^)^(]*\‍))#', '$1 $3 ', $InfoFieldList[4], -1, $nbPregRepl);
1573 // Remove all escape characters around '=' and parenthesis
1574 $InfoFieldList[4] = preg_replace('# *(=|\‍(|\‍)) *#', '$1', $InfoFieldList[4]);
1575 // Remove all parentheses preceded with '='
1576 $InfoFieldList[4] = preg_replace('#\b[a-zA-Z0-9-\.-_]+\b=\‍([^)^(]*('.$word.')[^)^(]*\‍)#', '$1 ', $InfoFieldList[4], -1, $nbPregSel);
1577 // On retire les escapes autour des = et parenthèses
1578 $InfoFieldList[4] = preg_replace('# *(=|\‍(|\‍)) *#', '$1', $InfoFieldList[4]);
1579
1580 // UPdate the totals counter for the loop
1581 $nbPreg = $nbPregRepl + $nbPregSel;
1582 }
1583
1584 // In case there is AND ou OR, before or after
1585 $matchCondition = array();
1586 preg_match('#(AND|OR|) *('.$word.') *(AND|OR|)#', $InfoFieldList[4], $matchCondition);
1587 while (!empty($matchCondition[0])) {
1588 // If the two sides differ but are not empty
1589 if (!empty($matchCondition[1]) && !empty($matchCondition[3]) && $matchCondition[1] != $matchCondition[3]) {
1590 // Nobody sain would do that without parentheses
1591 $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
1592 } else {
1593 if (!empty($matchCondition[1])) {
1594 $boolCond = (($matchCondition[1] == "AND") ? ' AND TRUE ' : ' OR FALSE ');
1595 $InfoFieldList[4] = str_replace($matchCondition[0], $boolCond.$matchCondition[3], $InfoFieldList[4]);
1596 } elseif (!empty($matchCondition[3])) {
1597 $boolCond = (($matchCondition[3] == "AND") ? ' TRUE AND ' : ' FALSE OR');
1598 $InfoFieldList[4] = str_replace($matchCondition[0], $boolCond, $InfoFieldList[4]);
1599 } else {
1600 $InfoFieldList[4] = " TRUE ";
1601 }
1602 }
1603
1604 // In case there is AND ou OR, before or after
1605 preg_match('#(AND|OR|) *('.$word.') *(AND|OR|)#', $InfoFieldList[4], $matchCondition);
1606 }
1607 } else {
1608 $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
1609 }
1610
1611 // We have to join on extrafield table
1612 if (strpos($InfoFieldList[4], 'extra.') !== false) {
1613 $sql .= ' as main, '.$this->db->prefix().$InfoFieldList[0].'_extrafields as extra';
1614 $sqlwhere .= " WHERE extra.fk_object=main.".$InfoFieldList[2]." AND ".$InfoFieldList[4];
1615 } else {
1616 $sqlwhere .= " WHERE ".$InfoFieldList[4];
1617 }
1618 } else {
1619 $sqlwhere .= ' WHERE 1=1';
1620 }
1621 // Some tables may have field, some other not. For the moment we disable it.
1622 if (in_array($InfoFieldList[0], array('tablewithentity'))) {
1623 $sqlwhere .= " AND entity = ".((int) $conf->entity);
1624 }
1625 // $sql.=preg_replace('/^ AND /','',$sqlwhere);
1626 // print $sql;
1627
1628 $sql .= $sqlwhere;
1629 $sql .= ' ORDER BY '.implode(', ', $fields_label);
1630
1631 dol_syslog(get_class($this).'::showInputField type=chkbxlst', LOG_DEBUG);
1632 $resql = $this->db->query($sql);
1633 if ($resql) {
1634 $num = $this->db->num_rows($resql);
1635 $i = 0;
1636
1637 $data = array();
1638
1639 while ($i < $num) {
1640 $labeltoshow = '';
1641 $obj = $this->db->fetch_object($resql);
1642
1643 $notrans = false;
1644 // Several field into label (eq table:code|label:rowid)
1645 $fields_label = explode('|', $InfoFieldList[1]);
1646 if (is_array($fields_label)) {
1647 $notrans = true;
1648 foreach ($fields_label as $field_toshow) {
1649 $labeltoshow .= $obj->$field_toshow.' ';
1650 }
1651 } else {
1652 $labeltoshow = $obj->{$InfoFieldList[1]};
1653 }
1654 $labeltoshow = dol_trunc($labeltoshow, 45);
1655
1656 if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1657 $labeltoshow = '';
1658 foreach ($fields_label as $field_toshow) {
1659 $translabel = $langs->trans($obj->$field_toshow);
1660 if ($translabel != $obj->$field_toshow) {
1661 $labeltoshow .= ' '.dol_trunc($translabel, 18).' ';
1662 } else {
1663 $labeltoshow .= ' '.dol_trunc($obj->$field_toshow, 18).' ';
1664 }
1665 }
1666 $data[$obj->rowid] = $labeltoshow;
1667 } else {
1668 if (!$notrans) {
1669 $translabel = $langs->trans($obj->{$InfoFieldList[1]});
1670 if ($translabel != $obj->{$InfoFieldList[1]}) {
1671 $labeltoshow = dol_trunc($translabel, 18);
1672 } else {
1673 $labeltoshow = dol_trunc($obj->{$InfoFieldList[1]}, 18);
1674 }
1675 }
1676 if (empty($labeltoshow)) {
1677 $labeltoshow = '(not defined)';
1678 }
1679
1680 if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1681 $data[$obj->rowid] = $labeltoshow;
1682 }
1683
1684 if (!empty($InfoFieldList[3]) && $parentField) {
1685 $parent = $parentName.':'.$obj->{$parentField};
1686 }
1687
1688 $data[$obj->rowid] = $labeltoshow;
1689 }
1690
1691 $i++;
1692 }
1693 $this->db->free($resql);
1694
1695 $out = $form->multiselectarray($keyprefix.$key.$keysuffix, $data, $value_arr, '', 0, '', 0, '100%');
1696 } else {
1697 print 'Error in request '.$sql.' '.$this->db->lasterror().'. Check setup of extra parameters.<br>';
1698 }
1699 } else {
1700 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1701 $data = $form->select_all_categories(Categorie::$MAP_ID_TO_CODE[$InfoFieldList[5]], '', 'parent', 64, $InfoFieldList[6], 1, 1);
1702 $out = $form->multiselectarray($keyprefix.$key.$keysuffix, $data, $value_arr, '', 0, '', 0, '100%');
1703 }
1704 }
1705 } elseif ($type == 'link') {
1706 $param_list = array_keys($param['options']); // $param_list[0] = 'ObjectName:classPath' but can also be 'ObjectName:classPath:1:(status:=:1)'
1707 /* Removed.
1708 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
1709 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.
1710 if (strpos($param_list[0], '$ID$') !== false && !empty($objectid)) {
1711 $param_list[0] = str_replace('$ID$', $objectid, $param_list[0]);
1712 }*/
1713 $showempty = (($required && $default != '') ? 0 : 1);
1714
1715 $tmparray = explode(':', $param_list[0]);
1716
1717 $element = $extrafieldsobjectkey; // $extrafieldsobjectkey comes from $object->table_element but we need $object->element
1718 if ($element == 'socpeople') {
1719 $element = 'contact';
1720 } elseif ($element == 'projet') {
1721 $element = 'project';
1722 }
1723
1724 //$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
1725 $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.
1726 $objectfield = $element.':options_'.$key; // Example: 'actioncomm:options_fff' To be used in priority to know object linked with all its definition (including filters)
1727
1728 $out = $form->selectForForms($objectdesc, $keyprefix.$key.$keysuffix, $value, $showempty, '', '', $morecss, '', 0, 0, '', $objectfield);
1729 } elseif (in_array($type, ['point', 'multipts', 'linestrg', 'polygon'])) {
1730 require_once DOL_DOCUMENT_ROOT.'/core/class/dolgeophp.class.php';
1731 $dolgeophp = new DolGeoPHP($this->db);
1732 $geojson = '{}';
1733 $centroidjson = getDolGlobalString('MAIN_INFO_SOCIETE_GEO_COORDINATES', '{}');
1734 if (!empty($value)) {
1735 $tmparray = $dolgeophp->parseGeoString($value);
1736 $geojson = $tmparray['geojson'];
1737 $centroidjson = $tmparray['centroidjson'];
1738 }
1739 if (!preg_match('/search_/', $keyprefix)) {
1740 require_once DOL_DOCUMENT_ROOT.'/core/class/geomapeditor.class.php';
1741 $geomapeditor = new GeoMapEditor();
1742 $out .= $geomapeditor->getHtml($keyprefix.$key.$keysuffix, $geojson, $centroidjson, $type);
1743 } else {
1744 // If keyprefix is search_ or search_options_, we must just use a simple text field
1745 $out = '';
1746 }
1747 } elseif ($type == 'password') {
1748 // If prefix is 'search_', field is used as a filter, we use a common text field.
1749 $out = '<input style="display:none" type="text" name="fakeusernameremembered">'; // Hidden field to reduce impact of evil Google Chrome autopopulate bug.
1750 $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 : '').'>';
1751 }
1752 if (!empty($hidden)) {
1753 $out = '<input type="hidden" value="'.$value.'" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'"/>';
1754 }
1755 /* Add comments
1756 if ($type == 'date') $out.=' (YYYY-MM-DD)';
1757 elseif ($type == 'datetime') $out.=' (YYYY-MM-DD HH:MM:SS)';
1758 */
1759 /*if (!empty($help) && $keyprefix != 'search_options_') {
1760 $out .= $form->textwithpicto('', $help, 1, 'help', '', 0, 3);
1761 }*/
1762 return $out;
1763 }
1764
1765
1776 public function showOutputField($key, $value, $moreparam = '', $extrafieldsobjectkey = '', $outputlangs = null)
1777 {
1778 global $conf, $langs;
1779
1780 if (is_null($outputlangs) || !is_object($outputlangs)) {
1781 $outputlangs = $langs;
1782 }
1783
1784 if (empty($extrafieldsobjectkey)) {
1785 dol_syslog(get_class($this).'::showOutputField extrafieldsobjectkey required', LOG_ERR);
1786 return 'BadValueForParamExtraFieldsObjectKey';
1787 }
1788
1789 $label = $this->attributes[$extrafieldsobjectkey]['label'][$key];
1790 $type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
1791 $size = $this->attributes[$extrafieldsobjectkey]['size'][$key]; // Can be '255', '24,8'...
1792 $default = $this->attributes[$extrafieldsobjectkey]['default'][$key];
1793 $computed = $this->attributes[$extrafieldsobjectkey]['computed'][$key];
1794 $unique = $this->attributes[$extrafieldsobjectkey]['unique'][$key];
1795 $required = $this->attributes[$extrafieldsobjectkey]['required'][$key];
1796 $param = $this->attributes[$extrafieldsobjectkey]['param'][$key];
1797 $perms = (int) dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1, 1, '2');
1798 $langfile = $this->attributes[$extrafieldsobjectkey]['langfile'][$key];
1799 $list = (string) dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1, 1, '2');
1800 $help = $this->attributes[$extrafieldsobjectkey]['help'][$key];
1801 $cssview = $this->attributes[$extrafieldsobjectkey]['cssview'][$key];
1802
1803 $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)
1804
1805 if ($hidden) {
1806 return ''; // This is a protection. If field is hidden, we should just not call this method.
1807 }
1808
1809 //if ($computed) $value = // $value is already calculated into $value before calling this method
1810
1811 $showsize = 0;
1812 if ($type == 'date') {
1813 $showsize = 10;
1814 if ($value !== '') {
1815 $value = dol_print_date($value, 'day'); // For date without hour, date is always GMT for storage and output
1816 }
1817 } elseif ($type == 'datetime') {
1818 $showsize = 19;
1819 if ($value !== '') {
1820 $value = dol_print_date($value, 'dayhour', 'tzuserrel');
1821 }
1822 } elseif ($type == 'datetimegmt') {
1823 $showsize = 19;
1824 if ($value !== '') {
1825 $value = dol_print_date($value, 'dayhour', 'gmt');
1826 }
1827 } elseif ($type == 'int') {
1828 $showsize = 10;
1829 } elseif ($type == 'double') {
1830 if (!empty($value)) {
1831 //$value=price($value);
1832 $sizeparts = explode(",", $size);
1833 $number_decimals = array_key_exists(1, $sizeparts) ? $sizeparts[1] : 0;
1834 $value = price($value, 0, $outputlangs, 0, 0, $number_decimals, '');
1835 }
1836 } elseif ($type == 'boolean') {
1837 $checked = '';
1838 if (!empty($value)) {
1839 $checked = ' checked ';
1840 }
1841 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER') < 2) {
1842 $value = '<input type="checkbox" '.$checked.' '.($moreparam ? $moreparam : '').' readonly disabled>';
1843 } else {
1844 $value = yn($value ? 1 : 0);
1845 }
1846 } elseif ($type == 'mail') {
1847 $value = dol_print_email($value, 0, 0, 0, 64, 1, 1);
1848 } elseif ($type == 'ip') {
1849 $value = dol_print_ip($value, 0);
1850 } elseif ($type == 'icon') {
1851 $value = '<span class="'.$value.'"></span>';
1852 } elseif ($type == 'url') {
1853 $value = dol_print_url($value, '_blank', 32, 1);
1854 } elseif ($type == 'phone') {
1855 $value = dol_print_phone($value, '', 0, 0, '', '&nbsp;', 'phone');
1856 } elseif ($type == 'price') {
1857 //$value = price($value, 0, $langs, 0, 0, -1, $conf->currency);
1858 if ($value || $value == '0') {
1859 $value = price($value, 0, $outputlangs, 0, $conf->global->MAIN_MAX_DECIMALS_TOT, -1).' '.$outputlangs->getCurrencySymbol($conf->currency);
1860 }
1861 } elseif ($type == 'pricecy') {
1862 $currency = $conf->currency;
1863 if (!empty($value)) {
1864 // $value in memory is a php string like '0.01:EUR'
1865 $pricetmp = explode(':', $value);
1866 $currency = !empty($pricetmp[1]) ? $pricetmp[1] : $conf->currency;
1867 $value = $pricetmp[0];
1868 }
1869 if ($value || $value == '0') {
1870 $value = price($value, 0, $outputlangs, 0, $conf->global->MAIN_MAX_DECIMALS_TOT, -1, $currency);
1871 }
1872 } elseif ($type == 'select') {
1873 $valstr = (!empty($param['options'][$value]) ? $param['options'][$value] : '');
1874 if (($pos = strpos($valstr, "|")) !== false) {
1875 $valstr = substr($valstr, 0, $pos);
1876 }
1877 if ($langfile && $valstr) {
1878 $value = $outputlangs->trans($valstr);
1879 } else {
1880 $value = $valstr;
1881 }
1882 } elseif ($type == 'sellist') {
1883 $param_list = array_keys($param['options']);
1884 $InfoFieldList = explode(":", $param_list[0]);
1885
1886 $selectkey = "rowid";
1887 $keyList = 'rowid';
1888
1889 if (count($InfoFieldList) >= 3) {
1890 $selectkey = $InfoFieldList[2];
1891 $keyList = $InfoFieldList[2].' as rowid';
1892 }
1893
1894 $fields_label = explode('|', $InfoFieldList[1]);
1895 if (is_array($fields_label)) {
1896 $keyList .= ', ';
1897 $keyList .= implode(', ', $fields_label);
1898 }
1899
1900 $filter_categorie = false;
1901 if (count($InfoFieldList) > 5) {
1902 if ($InfoFieldList[0] == 'categorie') {
1903 $filter_categorie = true;
1904 }
1905 }
1906
1907 $sql = "SELECT ".$keyList;
1908 $sql .= ' FROM '.$this->db->prefix().$InfoFieldList[0];
1909 if (!empty($InfoFieldList[4]) && strpos($InfoFieldList[4], 'extra.') !== false) {
1910 $sql .= ' as main';
1911 }
1912 if ($selectkey == 'rowid' && empty($value)) {
1913 $sql .= " WHERE ".$selectkey." = 0";
1914 } elseif ($selectkey == 'rowid') {
1915 $sql .= " WHERE ".$selectkey." = ".((int) $value);
1916 } else {
1917 $sql .= " WHERE ".$selectkey." = '".$this->db->escape($value)."'";
1918 }
1919
1920 //$sql.= ' AND entity = '.$conf->entity;
1921
1922 dol_syslog(get_class($this).':showOutputField:$type=sellist', LOG_DEBUG);
1923 $resql = $this->db->query($sql);
1924 if ($resql) {
1925 if (!$filter_categorie) {
1926 $value = ''; // value was used, so now we reset it to use it to build final output
1927
1928 $obj = $this->db->fetch_object($resql);
1929
1930 // Several field into label (eq table:code|label:rowid)
1931 $fields_label = explode('|', $InfoFieldList[1]);
1932
1933 if (is_array($fields_label) && count($fields_label) > 1) {
1934 foreach ($fields_label as $field_toshow) {
1935 $translabel = '';
1936 if (!empty($obj->$field_toshow)) {
1937 $translabel = $outputlangs->trans($obj->$field_toshow);
1938
1939 if ($translabel != $obj->$field_toshow) {
1940 $value .= dol_trunc($translabel, 24) . ' ';
1941 } else {
1942 $value .= $obj->$field_toshow . ' ';
1943 }
1944 }
1945 }
1946 } else {
1947 $translabel = '';
1948 $tmppropname = $InfoFieldList[1];
1949 //$obj->$tmppropname = '';
1950 if (!empty(isset($obj->$tmppropname) ? $obj->$tmppropname : '')) {
1951 $translabel = $outputlangs->trans($obj->$tmppropname);
1952 }
1953 if ($translabel != (isset($obj->$tmppropname) ? $obj->$tmppropname : '')) {
1954 $value = dol_trunc($translabel, 18);
1955 } else {
1956 $value = isset($obj->$tmppropname) ? $obj->$tmppropname : '';
1957 }
1958 }
1959 } else {
1960 $toprint = array();
1961 $obj = $this->db->fetch_object($resql);
1962 if ($obj->rowid) {
1963 require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
1964 $c = new Categorie($this->db);
1965 $result = $c->fetch($obj->rowid);
1966 if ($result > 0) {
1967 $ways = $c->print_all_ways(); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formatted text
1968 foreach ($ways as $way) {
1969 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories"' . ($c->color ? ' style="background: #' . $c->color . ';"' : ' style="background: #bbb"') . '>' . img_object('', 'category') . ' ' . $way . '</li>';
1970 }
1971 }
1972 }
1973 $value = '<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
1974 }
1975 } else {
1976 dol_syslog(get_class($this).'::showOutputField error '.$this->db->lasterror(), LOG_WARNING);
1977 }
1978 } elseif ($type == 'radio') {
1979 if (!isset($param['options'][$value])) {
1980 $outputlangs->load('errors');
1981 $value = $outputlangs->trans('ErrorNoValueForRadioType');
1982 } else {
1983 $value = $outputlangs->trans($param['options'][$value]);
1984 }
1985 } elseif ($type == 'checkbox') {
1986 $value_arr = explode(',', $value);
1987 $value = '';
1988 $toprint = array();
1989 if (is_array($value_arr)) {
1990 foreach ($value_arr as $keyval => $valueval) {
1991 if (!empty($valueval)) {
1992 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.$param['options'][$valueval].'</li>';
1993 }
1994 }
1995 }
1996 $value = '<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
1997 } elseif ($type == 'chkbxlst') {
1998 $value_arr = explode(',', $value);
1999
2000 $param_list = array_keys($param['options']);
2001 $InfoFieldList = explode(":", $param_list[0]);
2002
2003 $selectkey = "rowid";
2004 $keyList = 'rowid';
2005
2006 if (count($InfoFieldList) >= 3) {
2007 $selectkey = $InfoFieldList[2];
2008 $keyList = $InfoFieldList[2].' as rowid';
2009 }
2010
2011 $fields_label = explode('|', $InfoFieldList[1]);
2012 if (is_array($fields_label)) {
2013 $keyList .= ', ';
2014 $keyList .= implode(', ', $fields_label);
2015 }
2016
2017 $filter_categorie = false;
2018 if (count($InfoFieldList) > 5) {
2019 if ($InfoFieldList[0] == 'categorie') {
2020 $filter_categorie = true;
2021 }
2022 }
2023
2024 $sql = "SELECT ".$keyList;
2025 $sql .= " FROM ".$this->db->prefix().$InfoFieldList[0];
2026 if (strpos($InfoFieldList[4], 'extra.') !== false) {
2027 $sql .= ' as main';
2028 }
2029 // $sql.= " WHERE ".$selectkey."='".$this->db->escape($value)."'";
2030 // $sql.= ' AND entity = '.$conf->entity;
2031
2032 dol_syslog(get_class($this).':showOutputField:$type=chkbxlst', LOG_DEBUG);
2033 $resql = $this->db->query($sql);
2034 if ($resql) {
2035 if (!$filter_categorie) {
2036 $value = ''; // value was used, so now we reset it to use it to build final output
2037 $toprint = array();
2038 while ($obj = $this->db->fetch_object($resql)) {
2039 // Several field into label (eq table:code|label:rowid)
2040 $fields_label = explode('|', $InfoFieldList[1]);
2041 if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
2042 if (is_array($fields_label) && count($fields_label) > 1) {
2043 $label = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">';
2044 foreach ($fields_label as $field_toshow) {
2045 $translabel = '';
2046 if (!empty($obj->$field_toshow)) {
2047 $translabel = $outputlangs->trans($obj->$field_toshow);
2048 }
2049 if ($translabel != $field_toshow) {
2050 $label .= ' '.dol_trunc($translabel, 18);
2051 } else {
2052 $label .= ' '.$obj->$field_toshow;
2053 }
2054 }
2055 $label .= '</li>';
2056 $toprint[] = $label;
2057 } else {
2058 $translabel = '';
2059 if (!empty($obj->{$InfoFieldList[1]})) {
2060 $translabel = $outputlangs->trans($obj->{$InfoFieldList[1]});
2061 }
2062 if ($translabel != $obj->{$InfoFieldList[1]}) {
2063 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.dol_trunc($translabel, 18).'</li>';
2064 } else {
2065 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.$obj->{$InfoFieldList[1]}.'</li>';
2066 }
2067 }
2068 }
2069 }
2070 } else {
2071 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
2072
2073 $toprint = array();
2074 while ($obj = $this->db->fetch_object($resql)) {
2075 if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
2076 $c = new Categorie($this->db);
2077 $c->fetch($obj->rowid);
2078 $ways = $c->print_all_ways(); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formatted text
2079 foreach ($ways as $way) {
2080 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories"'.($c->color ? ' style="background: #'.$c->color.';"' : ' style="background: #bbb"').'>'.img_object('', 'category').' '.$way.'</li>';
2081 }
2082 }
2083 }
2084 }
2085 if (!empty($toprint)) {
2086 $value = '<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
2087 }
2088 } else {
2089 dol_syslog(get_class($this).'::showOutputField error '.$this->db->lasterror(), LOG_WARNING);
2090 }
2091 } elseif ($type == 'link') {
2092 $out = '';
2093
2094 // Only if something to display (perf)
2095 if ($value) { // If we have -1 here, pb is into insert, not into output (fix insert instead of changing code here to compensate)
2096 $param_list = array_keys($param['options']); // $param_list='ObjectName:classPath'
2097
2098 $InfoFieldList = explode(":", $param_list[0]);
2099 $classname = $InfoFieldList[0];
2100 $classpath = $InfoFieldList[1];
2101 if (!empty($classpath)) {
2102 dol_include_once($InfoFieldList[1]);
2103 if ($classname && class_exists($classname)) {
2104 $object = new $classname($this->db);
2105 '@phan-var-force CommonObject $object';
2106 $object->fetch($value);
2107 $value = $object->getNomUrl(3);
2108 }
2109 } else {
2110 dol_syslog('Error bad setup of extrafield', LOG_WARNING);
2111 return 'Error bad setup of extrafield';
2112 }
2113 }
2114 } elseif ($type == 'point') {
2115 if (!empty($value)) {
2116 require_once DOL_DOCUMENT_ROOT.'/core/class/dolgeophp.class.php';
2117 $dolgeophp = new DolGeoPHP($this->db);
2118 $value = $dolgeophp->getXYString($value);
2119 } else {
2120 $value = '';
2121 }
2122 } elseif (in_array($type, ['multipts','linestrg', 'polygon'])) {
2123 if (!empty($value)) {
2124 require_once DOL_DOCUMENT_ROOT.'/core/class/dolgeophp.class.php';
2125 $dolgeophp = new DolGeoPHP($this->db);
2126 $value = $dolgeophp->getPointString($value);
2127 } else {
2128 $value = '';
2129 }
2130 } elseif ($type == 'text') {
2131 $value = '<div class="'.($cssview ? $cssview : 'shortmessagecut').'">'.dol_htmlentitiesbr($value).'</div>';
2132 } elseif ($type == 'html') {
2133 $value = dol_htmlentitiesbr($value);
2134 } elseif ($type == 'password') {
2135 $value = dol_trunc(preg_replace('/./i', '*', $value), 8, 'right', 'UTF-8', 1);
2136 } else {
2137 $showsize = round((float) $size);
2138 if ($showsize > 48) {
2139 $showsize = 48;
2140 }
2141 }
2142
2143 //print $type.'-'.$size;
2144 $out = $value;
2145
2146 return $out;
2147 }
2148
2156 public function getAlignFlag($key, $extrafieldsobjectkey = '')
2157 {
2158 $type = 'varchar';
2159 if (!empty($extrafieldsobjectkey)) {
2160 $type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
2161 }
2162
2163 $cssstring = '';
2164
2165 if (in_array($type, array('date', 'datetime', 'datetimegmt',))) {
2166 $cssstring = "center";
2167 } elseif (in_array($type, array('int', 'price', 'double'))) {
2168 $cssstring = "right";
2169 } elseif (in_array($type, array('boolean', 'radio', 'checkbox', 'ip', 'icon'))) {
2170 $cssstring = "center";
2171 }
2172
2173 if (!empty($this->attributes[$extrafieldsobjectkey]['csslist'][$key])) {
2174 $cssstring .= ($cssstring ? ' ' : '').$this->attributes[$extrafieldsobjectkey]['csslist'][$key];
2175 } else {
2176 if (in_array($type, array('ip'))) {
2177 $cssstring .= ($cssstring ? ' ' : '').'tdoverflowmax150';
2178 }
2179 }
2180
2181 return $cssstring;
2182 }
2183
2194 public function showSeparator($key, $object, $colspan = 2, $display_type = 'card', $mode = '')
2195 {
2196 global $conf, $langs;
2197
2198 $tagtype = 'tr';
2199 $tagtype_dyn = 'td';
2200
2201 if ($display_type == 'line') {
2202 $tagtype = 'div';
2203 $tagtype_dyn = 'span';
2204 $colspan = 0;
2205 }
2206
2207 $extrafield_param = $this->attributes[$object->table_element]['param'][$key];
2208 $extrafield_param_list = array();
2209 if (!empty($extrafield_param) && is_array($extrafield_param)) {
2210 $extrafield_param_list = array_keys($extrafield_param['options']);
2211 }
2212
2213 // Set $extrafield_collapse_display_value (do we have to collapse/expand the group after the separator)
2214 $extrafield_collapse_display_value = -1;
2215 $expand_display = false;
2216 if (is_array($extrafield_param_list) && count($extrafield_param_list) > 0) {
2217 $extrafield_collapse_display_value = intval($extrafield_param_list[0]);
2218 $expand_display = ((isset($_COOKIE['DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key]) || GETPOSTINT('ignorecollapsesetup')) ? (!empty($_COOKIE['DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key])) : !($extrafield_collapse_display_value == 2));
2219 }
2220 $disabledcookiewrite = 0;
2221 if ($mode == 'create') {
2222 // On create mode, force separator group to not be collapsible
2223 $extrafield_collapse_display_value = 1;
2224 $expand_display = true; // We force group to be shown expanded
2225 $disabledcookiewrite = 1; // We keep status of group unchanged into the cookie
2226 }
2227
2228 $out = '<'.$tagtype.' id="trextrafieldseparator'.$key.(!empty($object->id) ? '_'.$object->id : '').'" class="trextrafieldseparator trextrafieldseparator'.$key.(!empty($object->id) ? '_'.$object->id : '').'">';
2229 $out .= '<'.$tagtype_dyn.' '.(!empty($colspan) ? 'colspan="' . $colspan . '"' : '').'>';
2230 // Some js code will be injected here to manage the collapsing of extrafields
2231 // Output the picto
2232 $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>';
2233 $out .= '&nbsp;';
2234 $out .= '<strong>';
2235 $out .= $langs->trans($this->attributes[$object->table_element]['label'][$key]);
2236 $out .= '</strong>';
2237 $out .= '</'.$tagtype_dyn.'>';
2238 $out .= '</'.$tagtype.'>';
2239
2240 $collapse_group = $key.(!empty($object->id) ? '_'.$object->id : '');
2241 //$extrafields_collapse_num = $this->attributes[$object->table_element]['pos'][$key].(!empty($object->id)?'_'.$object->id:'');
2242
2243 if ($extrafield_collapse_display_value == 1 || $extrafield_collapse_display_value == 2) {
2244 // Set the collapse_display status to cookie in priority or if ignorecollapsesetup is 1, if cookie and ignorecollapsesetup not defined, use the setup.
2245 $this->expand_display[$collapse_group] = $expand_display;
2246
2247 if (!empty($conf->use_javascript_ajax)) {
2248 $out .= '<!-- Add js script to manage the collapse/uncollapse of extrafields separators '.$key.' -->'."\n";
2249 $out .= '<script nonce="'.getNonce().'" type="text/javascript">'."\n";
2250 $out .= 'jQuery(document).ready(function(){'."\n";
2251 if (empty($disabledcookiewrite)) {
2252 if (!$expand_display) {
2253 $out .= ' console.log("Inject js for the collapsing of extrafield '.$key.' - hide");'."\n";
2254 $out .= ' jQuery(".trextrafields_collapse'.$collapse_group.'").hide();'."\n";
2255 } else {
2256 $out .= ' console.log("Inject js for collapsing of extrafield '.$key.' - keep visible and set cookie");'."\n";
2257 $out .= ' document.cookie = "DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.'=1; path='.$_SERVER["PHP_SELF"].'"'."\n";
2258 }
2259 }
2260 $out .= ' jQuery("#trextrafieldseparator'.$key.(!empty($object->id) ? '_'.$object->id : '').'").click(function(){'."\n";
2261 $out .= ' console.log("We click on collapse/uncollapse to hide/show .trextrafields_collapse'.$collapse_group.'");'."\n";
2262 $out .= ' jQuery(".trextrafields_collapse'.$collapse_group.'").toggle(100, function(){'."\n";
2263 $out .= ' if (jQuery(".trextrafields_collapse'.$collapse_group.'").is(":hidden")) {'."\n";
2264 $out .= ' jQuery("#trextrafieldseparator'.$key.(!empty($object->id) ? '_'.$object->id : '').' '.$tagtype_dyn.' span").addClass("fa-plus-square").removeClass("fa-minus-square");'."\n";
2265 $out .= ' document.cookie = "DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.'=0; path='.$_SERVER["PHP_SELF"].'"'."\n";
2266 $out .= ' } else {'."\n";
2267 $out .= ' jQuery("#trextrafieldseparator'.$key.(!empty($object->id) ? '_'.$object->id : '').' '.$tagtype_dyn.' span").addClass("fa-minus-square").removeClass("fa-plus-square");'."\n";
2268 $out .= ' document.cookie = "DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.'=1; path='.$_SERVER["PHP_SELF"].'"'."\n";
2269 $out .= ' }'."\n";
2270 $out .= ' });'."\n";
2271 $out .= ' });'."\n";
2272 $out .= '});'."\n";
2273 $out .= '</script>'."\n";
2274 }
2275 } else {
2276 $this->expand_display[$collapse_group] = 1;
2277 }
2278
2279 return $out;
2280 }
2281
2293 public function setOptionalsFromPost($extralabels, &$object, $onlykey = '', $todefaultifmissing = 0)
2294 {
2295 global $langs;
2296
2297 $nofillrequired = 0; // For error when required field left blank
2298 $error_field_required = array();
2299
2300 if (isset($this->attributes[$object->table_element]['label']) && is_array($this->attributes[$object->table_element]['label'])) {
2301 $extralabels = $this->attributes[$object->table_element]['label'];
2302 }
2303
2304 if (is_array($extralabels)) {
2305 // Get extra fields
2306 foreach ($extralabels as $key => $value) {
2307 if (!empty($onlykey) && $onlykey != '@GETPOSTISSET' && $key != $onlykey) {
2308 continue;
2309 }
2310
2311 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')))) {
2312 //when unticking boolean field, it's not set in POST
2313 continue;
2314 }
2315
2316 $key_type = $this->attributes[$object->table_element]['type'][$key];
2317 if ($key_type == 'separate') {
2318 continue;
2319 }
2320
2321 $enabled = 1;
2322 if (isset($this->attributes[$object->table_element]['enabled'][$key])) { // 'enabled' is often a condition on module enabled or not
2323 $enabled = (int) dol_eval($this->attributes[$object->table_element]['enabled'][$key], 1, 1, '2');
2324 }
2325
2326 $visibility = 1;
2327 if (isset($this->attributes[$object->table_element]['list'][$key])) { // 'list' is option for visibility
2328 $visibility = (int) dol_eval($this->attributes[$object->table_element]['list'][$key], 1, 1, '2');
2329 }
2330
2331 $perms = 1;
2332 if (isset($this->attributes[$object->table_element]['perms'][$key])) {
2333 $perms = (int) dol_eval($this->attributes[$object->table_element]['perms'][$key], 1, 1, '2');
2334 }
2335 if (empty($enabled)
2336 || (
2337 $onlykey === '@GETPOSTISSET'
2338 && in_array($this->attributes[$object->table_element]['type'][$key], array('boolean', 'checkbox', 'chkbxlst'))
2339 && in_array(abs($enabled), array(2, 5))
2340 && ! GETPOSTISSET('options_' . $key) // Update hidden checkboxes and multiselect only if they are provided
2341 )
2342 ) {
2343 continue;
2344 }
2345
2346 $visibility_abs = abs($visibility);
2347 // not modify if extra field is not in update form (0 : never, 2 or -2 : list only, 5 or - 5 : list and view only)
2348 if (empty($visibility_abs) || $visibility_abs == 2 || $visibility_abs == 5) {
2349 continue;
2350 }
2351 if (empty($perms)) {
2352 continue;
2353 }
2354
2355 if ($this->attributes[$object->table_element]['required'][$key]) { // Value is required
2356 // Check if functionally empty without using GETPOST (depending on the type of extrafield, a
2357 // technically non-empty value may be treated as empty functionally).
2358 // value can be alpha, int, array, etc...
2359 $v = $_POST["options_".$key] ?? null;
2360 $type = $this->attributes[$object->table_element]['type'][$key];
2361 if (self::isEmptyValue($v, $type)) {
2362 //print 'ccc'.$value.'-'.$this->attributes[$object->table_element]['required'][$key];
2363
2364 // 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.
2365
2366 $nofillrequired++;
2367 if (!empty($this->attributes[$object->table_element]['langfile'][$key])) {
2368 $langs->load($this->attributes[$object->table_element]['langfile'][$key]);
2369 }
2370 $error_field_required[$key] = $langs->transnoentitiesnoconv($value);
2371 }
2372 }
2373
2374 if (in_array($key_type, array('date'))) {
2375 // Clean parameters
2376 $value_key = dol_mktime(12, 0, 0, GETPOSTINT("options_".$key."month"), GETPOSTINT("options_".$key."day"), GETPOSTINT("options_".$key."year"));
2377 } elseif (in_array($key_type, array('datetime'))) {
2378 // Clean parameters
2379 $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');
2380 } elseif (in_array($key_type, array('datetimegmt'))) {
2381 // Clean parameters
2382 $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');
2383 } elseif (in_array($key_type, array('checkbox', 'chkbxlst'))) {
2384 $value_arr = GETPOST("options_".$key, 'array'); // check if an array
2385 if (!empty($value_arr)) {
2386 $value_key = implode(',', $value_arr);
2387 } else {
2388 $value_key = '';
2389 }
2390 } elseif (in_array($key_type, array('price', 'double'))) {
2391 $value_arr = GETPOST("options_".$key, 'alpha');
2392 $value_key = price2num($value_arr);
2393 } elseif (in_array($key_type, array('pricecy', 'double'))) {
2394 $value_key = price2num(GETPOST("options_".$key, 'alpha')).':'.GETPOST("options_".$key."currency_id", 'alpha');
2395 } elseif (in_array($key_type, array('html'))) {
2396 $value_key = GETPOST("options_".$key, 'restricthtml');
2397 } elseif (in_array($key_type, ['point', 'multipts', 'linestrg', 'polygon'])) {
2398 // construct point
2399 require_once DOL_DOCUMENT_ROOT.'/core/class/dolgeophp.class.php';
2400 $geojson = GETPOST("options_".$key, 'restricthtml');
2401 if ($geojson != '{}') {
2402 $dolgeophp = new DolGeoPHP($this->db);
2403 $value_key = $dolgeophp->getWkt($geojson);
2404 } else {
2405 $value_key = '';
2406 }
2407 } elseif (in_array($key_type, array('text'))) {
2408 $label_security_check = 'alphanohtml';
2409 // by default 'alphanohtml' (better security); hidden conf MAIN_SECURITY_ALLOW_UNSECURED_LABELS_WITH_HTML allows basic html
2410 if (getDolGlobalString('MAIN_SECURITY_ALLOW_UNSECURED_REF_LABELS')) {
2411 $label_security_check = 'nohtml';
2412 } else {
2413 $label_security_check = !getDolGlobalString('MAIN_SECURITY_ALLOW_UNSECURED_LABELS_WITH_HTML') ? 'alphanohtml' : 'restricthtml';
2414 }
2415 $value_key = GETPOST("options_".$key, $label_security_check);
2416 } else {
2417 $value_key = GETPOST("options_".$key);
2418 if (in_array($key_type, array('link')) && $value_key == '-1') {
2419 $value_key = '';
2420 }
2421 }
2422
2423 if (!empty($error_field_required[$key]) && $todefaultifmissing) {
2424 // Value is required but we have a default value and we asked to set empty value to the default value
2425 if (!empty($this->attributes[$object->table_element]['default']) && !is_null($this->attributes[$object->table_element]['default'][$key])) {
2426 $value_key = $this->attributes[$object->table_element]['default'][$key];
2427 unset($error_field_required[$key]);
2428 $nofillrequired--;
2429 }
2430 }
2431
2432 $object->array_options["options_".$key] = $value_key;
2433 }
2434
2435 if ($nofillrequired) {
2436 $langs->load('errors');
2437 $this->error = $langs->trans('ErrorFieldsRequired').' : '.implode(', ', $error_field_required);
2438 setEventMessages($this->error, null, 'errors');
2439 return -1;
2440 } else {
2441 return 1;
2442 }
2443 } else {
2444 return 0;
2445 }
2446 }
2447
2456 public function getOptionalsFromPost($extrafieldsobjectkey, $keysuffix = '', $keyprefix = '')
2457 {
2458 global $_POST;
2459
2460 if (is_string($extrafieldsobjectkey) && !empty($this->attributes[$extrafieldsobjectkey]['label']) && is_array($this->attributes[$extrafieldsobjectkey]['label'])) {
2461 $extralabels = $this->attributes[$extrafieldsobjectkey]['label'];
2462 } else {
2463 $extralabels = $extrafieldsobjectkey;
2464 }
2465
2466 if (is_array($extralabels)) {
2467 $array_options = array();
2468
2469 // Get extra fields
2470 foreach ($extralabels as $key => $value) {
2471 $key_type = '';
2472 if (is_string($extrafieldsobjectkey)) {
2473 $key_type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
2474 }
2475
2476 if (in_array($key_type, array('date'))) {
2477 $dateparamname_start = $keyprefix . 'options_' . $key . $keysuffix . '_start';
2478 $dateparamname_end = $keyprefix . 'options_' . $key . $keysuffix . '_end';
2479
2480 if (GETPOST($dateparamname_start . 'year') || GETPOST($dateparamname_end . 'year')) {
2481 $value_key = array();
2482 // values provided as a component year, month, day, etc.
2483 if (GETPOST($dateparamname_start . 'year')) {
2484 $value_key['start'] = dol_mktime(0, 0, 0, GETPOSTINT($dateparamname_start . 'month'), GETPOSTINT($dateparamname_start . 'day'), GETPOSTINT($dateparamname_start . 'year'));
2485 }
2486 if (GETPOST($dateparamname_end . 'year')) {
2487 $value_key['end'] = dol_mktime(23, 59, 59, GETPOSTINT($dateparamname_end . 'month'), GETPOSTINT($dateparamname_end . 'day'), GETPOSTINT($dateparamname_end . 'year'));
2488 }
2489 } elseif (GETPOST($keyprefix."options_".$key.$keysuffix."year")) {
2490 // Clean parameters
2491 $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"));
2492 } else {
2493 continue; // Value was not provided, we should not set it.
2494 }
2495 } elseif (in_array($key_type, array('datetime', 'datetimegmt'))) {
2496 $dateparamname_start = $keyprefix . 'options_' . $key . $keysuffix . '_start';
2497 $dateparamname_end = $keyprefix . 'options_' . $key . $keysuffix . '_end';
2498
2499 if (GETPOST($dateparamname_start . 'year') || GETPOST($dateparamname_end . 'year')) {
2500 // values provided as a date pair (start date + end date), each date being broken down as year, month, day, etc.
2501 $dateparamname_start_hour = GETPOSTINT($dateparamname_start . 'hour') != '-1' ? GETPOSTINT($dateparamname_start . 'hour') : '00';
2502 $dateparamname_start_min = GETPOSTINT($dateparamname_start . 'min') != '-1' ? GETPOSTINT($dateparamname_start . 'min') : '00';
2503 $dateparamname_start_sec = GETPOSTINT($dateparamname_start . 'sec') != '-1' ? GETPOSTINT($dateparamname_start . 'sec') : '00';
2504 $dateparamname_end_hour = GETPOSTINT($dateparamname_end . 'hour') != '-1' ? GETPOSTINT($dateparamname_end . 'hour') : '23';
2505 $dateparamname_end_min = GETPOSTINT($dateparamname_end . 'min') != '-1' ? GETPOSTINT($dateparamname_end . 'min') : '59';
2506 $dateparamname_end_sec = GETPOSTINT($dateparamname_end . 'sec') != '-1' ? GETPOSTINT($dateparamname_end . 'sec') : '59';
2507 if ($key_type == 'datetimegmt') {
2508 $value_key = array(
2509 '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'),
2510 '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')
2511 );
2512 } else {
2513 $value_key = array(
2514 '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'),
2515 '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')
2516 );
2517 }
2518 } elseif (GETPOST($keyprefix."options_".$key.$keysuffix."year")) {
2519 // Clean parameters
2520 if ($key_type == 'datetimegmt') {
2521 $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');
2522 } else {
2523 $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');
2524 }
2525 } else {
2526 continue; // Value was not provided, we should not set it.
2527 }
2528 } elseif ($key_type == 'select') {
2529 // to detect if we are in search context
2530 if (GETPOSTISARRAY($keyprefix."options_".$key.$keysuffix)) {
2531 $value_arr = GETPOST($keyprefix."options_".$key.$keysuffix, 'array:aZ09');
2532 // Make sure we get an array even if there's only one selected
2533 $value_arr = (array) $value_arr;
2534 $value_key = implode(',', $value_arr);
2535 } else {
2536 $value_key = GETPOST($keyprefix."options_".$key.$keysuffix);
2537 }
2538 } elseif (in_array($key_type, array('checkbox', 'chkbxlst'))) {
2539 // We test on a hidden field named "..._multiselect" that is always set to 1 if param is in form so
2540 // when nothing is provided we can make a difference between noparam in the form and param was set to nothing.
2541 if (!GETPOSTISSET($keyprefix."options_".$key.$keysuffix.'_multiselect')) {
2542 continue; // Value was not provided, we should not set it.
2543 }
2544 $value_arr = GETPOST($keyprefix."options_".$key.$keysuffix);
2545 // Make sure we get an array even if there's only one checkbox
2546 $value_arr = (array) $value_arr;
2547 $value_key = implode(',', $value_arr);
2548 } elseif (in_array($key_type, array('price', 'double', 'int'))) {
2549 if (!GETPOSTISSET($keyprefix."options_".$key.$keysuffix)) {
2550 continue; // Value was not provided, we should not set it.
2551 }
2552 $value_arr = GETPOST($keyprefix."options_".$key.$keysuffix);
2553 if ($keyprefix != 'search_') { // If value is for a search, we must keep complex string like '>100 <=150'
2554 $value_key = price2num($value_arr);
2555 } else {
2556 $value_key = $value_arr;
2557 }
2558 } elseif (in_array($key_type, array('boolean'))) {
2559 // We test on a hidden field named "..._boolean" that is always set to 1 if param is in form so
2560 // when nothing is provided we can make a difference between noparam in the form and param was set to nothing.
2561 if (!GETPOSTISSET($keyprefix."options_".$key.$keysuffix."_boolean")) {
2562 $value_key = '';
2563 } else {
2564 $value_arr = GETPOST($keyprefix."options_".$key.$keysuffix);
2565 $value_key = $value_arr;
2566 }
2567 } elseif (in_array($key_type, array('html'))) {
2568 if (!GETPOSTISSET($keyprefix."options_".$key.$keysuffix)) {
2569 continue; // Value was not provided, we should not set it.
2570 }
2571 $value_key = dol_htmlcleanlastbr(GETPOST($keyprefix."options_".$key.$keysuffix, 'restricthtml'));
2572 } else {
2573 if (!GETPOSTISSET($keyprefix."options_".$key.$keysuffix)) {
2574 continue; // Value was not provided, we should not set it.
2575 }
2576 $value_key = GETPOST($keyprefix."options_".$key.$keysuffix);
2577 }
2578
2579 $array_options[$keyprefix."options_".$key] = $value_key; // No keyprefix here. keyprefix is used only for read.
2580 }
2581
2582 return $array_options;
2583 }
2584
2585 return 0;
2586 }
2587
2593 public static function getListOfTypesLabels()
2594 {
2595 global $langs;
2596
2597 $arraytype2label = array('');
2598
2599 $tmptype2label = ExtraFields::$type2label;
2600 foreach ($tmptype2label as $key => $val) {
2601 $arraytype2label[$key] = $langs->transnoentitiesnoconv($val);
2602 }
2603
2604 if (!getDolGlobalString('MAIN_USE_EXTRAFIELDS_ICON')) {
2605 unset($arraytype2label['icon']);
2606 }
2607 if (!getDolGlobalString('MAIN_USE_GEOPHP')) {
2608 unset($arraytype2label['point']);
2609 unset($arraytype2label['multipts']);
2610 unset($arraytype2label['linestrg']);
2611 unset($arraytype2label['polygon']);
2612 }
2613
2614 return $arraytype2label;
2615 }
2616
2624 public static function isEmptyValue($v, string $type)
2625 {
2626 if ($v === null || $v === '') {
2627 return true;
2628 }
2629 if (is_array($v) || $type == 'select') {
2630 return empty($v);
2631 }
2632 if ($type == 'link') {
2633 return ($v == '-1');
2634 }
2635 if ($type == 'sellist') {
2636 return ($v == '0');
2637 }
2638 return (empty($v) && $v != '0');
2639 }
2640}
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_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.
dol_print_phone($phone, $countrycode='', $cid=0, $socid=0, $addlink='', $separ="&nbsp;", $withpicto='', $titlealt='', $adddivfloat=0, $morecss='paddingright')
Format phone numbers according to country.
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.
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.
dol_print_email($email, $cid=0, $socid=0, $addlink=0, $max=64, $showinvalid=1, $withpicto=0, $morecss='paddingrightonly')
Show EMail link formatted for HTML output.
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 a 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...