dolibarr 18.0.6
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 Charles-Fr BENKE <charles.fr@benke.fr>
10 * Copyright (C) 2016 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
11 * Copyright (C) 2017 Nicolas ZABOURI <info@inovea-conseil.com>
12 * Copyright (C) 2018-2022 Frédéric France <frederic.france@netlogic.fr>
13 * Copyright (C) 2022 Antonin MARCHAL <antonin@letempledujeu.fr>
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 3 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program. If not, see <https://www.gnu.org/licenses/>.
27 */
28
40{
44 public $db;
45
49 public $attributes;
50
54 public $expand_display;
55
59 public $error = '';
60
64 public $errors = array();
65
69 public $errno;
70
74 public static $type2label = array(
75 'varchar'=>'String1Line',
76 'text'=>'TextLongNLines',
77 'html'=>'HtmlText',
78 'int'=>'Int',
79 'double'=>'Float',
80 'date'=>'Date',
81 'datetime'=>'DateAndTime',
82 //'datetimegmt'=>'DateAndTimeUTC',
83 'boolean'=>'Boolean',
84 'price'=>'ExtrafieldPrice',
85 'pricecy'=>'ExtrafieldPriceWithCurrency',
86 'phone'=>'ExtrafieldPhone',
87 'mail'=>'ExtrafieldMail',
88 'url'=>'ExtrafieldUrl',
89 'ip'=>'ExtrafieldIP',
90 'password' => 'ExtrafieldPassword',
91 'select' => 'ExtrafieldSelect',
92 'sellist' => 'ExtrafieldSelectList',
93 'radio' => 'ExtrafieldRadio',
94 'checkbox' => 'ExtrafieldCheckBox',
95 'chkbxlst' => 'ExtrafieldCheckBoxFromList',
96 'link' => 'ExtrafieldLink',
97 'separate' => 'ExtrafieldSeparator',
98 );
99
100
106 public function __construct($db)
107 {
108 $this->db = $db;
109 $this->error = '';
110 $this->errors = array();
111 $this->attributes = array();
112 }
113
140 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())
141 {
142 if (empty($attrname)) {
143 return -1;
144 }
145 if (empty($label)) {
146 return -1;
147 }
148
149 $result = 0;
150
151 if ($type == 'separate') {
152 $unique = 0;
153 $required = 0;
154 } // Force unique and not required if this is a separator field to avoid troubles.
155 if ($elementtype == 'thirdparty') {
156 $elementtype = 'societe';
157 }
158 if ($elementtype == 'contact') {
159 $elementtype = 'socpeople';
160 }
161
162 // Create field into database except for separator type which is not stored in database
163 if ($type != 'separate') {
164 $result = $this->create($attrname, $type, $size, $elementtype, $unique, $required, $default_value, $param, $perms, $list, $computed, $help, $moreparams);
165 }
166 $err1 = $this->errno;
167 if ($result > 0 || $err1 == 'DB_ERROR_COLUMN_ALREADY_EXISTS' || $type == 'separate') {
168 // Add declaration of field into table
169 $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);
170 $err2 = $this->errno;
171 if ($result2 > 0 || ($err1 == 'DB_ERROR_COLUMN_ALREADY_EXISTS' && $err2 == 'DB_ERROR_RECORD_ALREADY_EXISTS')) {
172 $this->error = '';
173 $this->errno = 0;
174 return 1;
175 } else {
176 return -2;
177 }
178 } else {
179 return -1;
180 }
181 }
182
202 private function create($attrname, $type = 'varchar', $length = 255, $elementtype = 'member', $unique = 0, $required = 0, $default_value = '', $param = '', $perms = '', $list = '0', $computed = '', $help = '', $moreparams = array())
203 {
204 if ($elementtype == 'thirdparty') {
205 $elementtype = 'societe';
206 }
207 if ($elementtype == 'contact') {
208 $elementtype = 'socpeople';
209 }
210
211 $table = $elementtype.'_extrafields';
212 if ($elementtype == 'categorie') {
213 $table = 'categories_extrafields';
214 }
215
216 if (!empty($attrname) && preg_match("/^\w[a-zA-Z0-9_]*$/", $attrname) && !is_numeric($attrname)) {
217 if ($type == 'boolean') {
218 $typedb = 'int';
219 $lengthdb = '1';
220 } elseif ($type == 'price') {
221 $typedb = 'double';
222 $lengthdb = '24,8';
223 } elseif ($type == 'pricecy') {
224 $typedb = 'varchar';
225 $lengthdb = '64';
226 } elseif ($type == 'phone') {
227 $typedb = 'varchar';
228 $lengthdb = '20';
229 } elseif ($type == 'mail' || $type == 'ip') {
230 $typedb = 'varchar';
231 $lengthdb = '128';
232 } elseif ($type == 'url') {
233 $typedb = 'varchar';
234 $lengthdb = '255';
235 } elseif (($type == 'select') || ($type == 'sellist') || ($type == 'radio') || ($type == 'checkbox') || ($type == 'chkbxlst')) {
236 $typedb = 'varchar';
237 $lengthdb = '255';
238 } elseif ($type == 'link') {
239 $typedb = 'int';
240 $lengthdb = '11';
241 } elseif ($type == 'html') {
242 $typedb = 'text';
243 $lengthdb = $length;
244 } elseif ($type == 'password') {
245 $typedb = 'varchar';
246 $lengthdb = '128';
247 } else {
248 $typedb = $type;
249 $lengthdb = $length;
250 if ($type == 'varchar' && empty($lengthdb)) {
251 $lengthdb = '255';
252 }
253 }
254 $field_desc = array(
255 'type'=>$typedb,
256 'value'=>$lengthdb,
257 'null'=>($required ? 'NOT NULL' : 'NULL'),
258 'default' => $default_value
259 );
260
261 $result = $this->db->DDLAddField($this->db->prefix().$table, $attrname, $field_desc);
262 if ($result > 0) {
263 if ($unique) {
264 $sql = "ALTER TABLE ".$this->db->prefix().$table." ADD UNIQUE INDEX uk_".$table."_".$attrname." (".$attrname.")";
265 $resql = $this->db->query($sql, 1, 'dml');
266 }
267 return 1;
268 } else {
269 $this->error = $this->db->lasterror();
270 $this->errno = $this->db->lasterrno();
271 return -1;
272 }
273 } else {
274 return 0;
275 }
276 }
277
278 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
306 private function create_label($attrname, $label = '', $type = '', $pos = 0, $size = 0, $elementtype = 'member', $unique = 0, $required = 0, $param = '', $alwayseditable = 0, $perms = '', $list = '-1', $help = '', $default = '', $computed = '', $entity = '', $langfile = '', $enabled = '1', $totalizable = 0, $printable = 0, $moreparams = array())
307 {
308 // phpcs:enable
309 global $conf, $user;
310
311 if ($elementtype == 'thirdparty') {
312 $elementtype = 'societe';
313 }
314 if ($elementtype == 'contact') {
315 $elementtype = 'socpeople';
316 }
317
318 // Clean parameters
319 if (empty($pos)) {
320 $pos = 0;
321 }
322 if (empty($list)) {
323 $list = '0';
324 }
325 if (empty($required)) {
326 $required = 0;
327 }
328 if (empty($unique)) {
329 $unique = 0;
330 }
331 if (empty($printable)) {
332 $printable = 0;
333 }
334 if (empty($alwayseditable)) {
335 $alwayseditable = 0;
336 }
337 if (empty($totalizable)) {
338 $totalizable = 0;
339 }
340
341 $css = '';
342 if (!empty($moreparams) && !empty($moreparams['css'])) {
343 $css = $moreparams['css'];
344 }
345 $csslist = '';
346 if (!empty($moreparams) && !empty($moreparams['csslist'])) {
347 $csslist = $moreparams['csslist'];
348 }
349 $cssview = '';
350 if (!empty($moreparams) && !empty($moreparams['cssview'])) {
351 $cssview = $moreparams['cssview'];
352 }
353
354 if (!empty($attrname) && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname) && !is_numeric($attrname)) {
355 if (is_array($param) && count($param) > 0) {
356 $params = serialize($param);
357 } elseif (strlen($param) > 0) {
358 $params = trim($param);
359 } else {
360 $params = '';
361 }
362
363 $sql = "INSERT INTO ".$this->db->prefix()."extrafields(";
364 $sql .= " name,";
365 $sql .= " label,";
366 $sql .= " type,";
367 $sql .= " pos,";
368 $sql .= " size,";
369 $sql .= " entity,";
370 $sql .= " elementtype,";
371 $sql .= " fieldunique,";
372 $sql .= " fieldrequired,";
373 $sql .= " param,";
374 $sql .= " alwayseditable,";
375 $sql .= " perms,";
376 $sql .= " langs,";
377 $sql .= " list,";
378 $sql .= " printable,";
379 $sql .= " fielddefault,";
380 $sql .= " fieldcomputed,";
381 $sql .= " fk_user_author,";
382 $sql .= " fk_user_modif,";
383 $sql .= " datec,";
384 $sql .= " enabled,";
385 $sql .= " help,";
386 $sql .= " totalizable,";
387 $sql .= " css,";
388 $sql .= " csslist,";
389 $sql .= " cssview";
390 $sql .= " )";
391 $sql .= " VALUES('".$this->db->escape($attrname)."',";
392 $sql .= " '".$this->db->escape($label)."',";
393 $sql .= " '".$this->db->escape($type)."',";
394 $sql .= " ".((int) $pos).",";
395 $sql .= " '".$this->db->escape($size)."',";
396 $sql .= " ".($entity === '' ? $conf->entity : $entity).",";
397 $sql .= " '".$this->db->escape($elementtype)."',";
398 $sql .= " ".((int) $unique).",";
399 $sql .= " ".((int) $required).",";
400 $sql .= " '".$this->db->escape($params)."',";
401 $sql .= " ".((int) $alwayseditable).",";
402 $sql .= " ".($perms ? "'".$this->db->escape($perms)."'" : "null").",";
403 $sql .= " ".($langfile ? "'".$this->db->escape($langfile)."'" : "null").",";
404 $sql .= " '".$this->db->escape($list)."',";
405 $sql .= " '".$this->db->escape($printable)."',";
406 $sql .= " ".($default ? "'".$this->db->escape($default)."'" : "null").",";
407 $sql .= " ".($computed ? "'".$this->db->escape($computed)."'" : "null").",";
408 $sql .= " ".(is_object($user) ? $user->id : 0).",";
409 $sql .= " ".(is_object($user) ? $user->id : 0).",";
410 $sql .= "'".$this->db->idate(dol_now())."',";
411 $sql .= " ".($enabled ? "'".$this->db->escape($enabled)."'" : "1").",";
412 $sql .= " ".($help ? "'".$this->db->escape($help)."'" : "null").",";
413 $sql .= " ".($totalizable ? 'TRUE' : 'FALSE').",";
414 $sql .= " ".($css ? "'".$this->db->escape($css)."'" : "null").",";
415 $sql .= " ".($csslist ? "'".$this->db->escape($csslist)."'" : "null").",";
416 $sql .= " ".($cssview ? "'".$this->db->escape($cssview)."'" : "null");
417 $sql .= ')';
418
419 dol_syslog(get_class($this)."::create_label", LOG_DEBUG);
420 if ($this->db->query($sql)) {
421 return 1;
422 } else {
423 $this->error = $this->db->lasterror();
424 $this->errno = $this->db->lasterrno();
425 return -1;
426 }
427 }
428 return -1;
429 }
430
438 public function delete($attrname, $elementtype = 'member')
439 {
440 if ($elementtype == 'thirdparty') {
441 $elementtype = 'societe';
442 }
443 if ($elementtype == 'contact') {
444 $elementtype = 'socpeople';
445 }
446
447 $table = $elementtype.'_extrafields';
448 if ($elementtype == 'categorie') {
449 $table = 'categories_extrafields';
450 }
451
452 $error = 0;
453
454 if (!empty($attrname) && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname)) {
455 $result = $this->delete_label($attrname, $elementtype);
456 if ($result < 0) {
457 $this->error = $this->db->lasterror();
458 $this->errors[] = $this->db->lasterror();
459 $error++;
460 }
461
462 if (!$error) {
463 $sql = "SELECT COUNT(rowid) as nb";
464 $sql .= " FROM ".$this->db->prefix()."extrafields";
465 $sql .= " WHERE elementtype = '".$this->db->escape($elementtype)."'";
466 $sql .= " AND name = '".$this->db->escape($attrname)."'";
467 //$sql.= " AND entity IN (0,".$conf->entity.")"; Do not test on entity here. We want to see if there is still on field remaning in other entities before deleting field in table
468 $resql = $this->db->query($sql);
469 if ($resql) {
470 $obj = $this->db->fetch_object($resql);
471 if ($obj->nb <= 0) {
472 $result = $this->db->DDLDropField($this->db->prefix().$table, $attrname); // This also drop the unique key
473 if ($result < 0) {
474 $this->error = $this->db->lasterror();
475 $this->errors[] = $this->db->lasterror();
476 $error++;
477 }
478 }
479 }
480 }
481
482 return $result;
483 } else {
484 return 0;
485 }
486 }
487
488 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
496 private function delete_label($attrname, $elementtype = 'member')
497 {
498 // phpcs:enable
499 global $conf;
500
501 if ($elementtype == 'thirdparty') {
502 $elementtype = 'societe';
503 }
504 if ($elementtype == 'contact') {
505 $elementtype = 'socpeople';
506 }
507
508 if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname)) {
509 $sql = "DELETE FROM ".$this->db->prefix()."extrafields";
510 $sql .= " WHERE name = '".$this->db->escape($attrname)."'";
511 $sql .= " AND entity IN (0,".$conf->entity.')';
512 $sql .= " AND elementtype = '".$this->db->escape($elementtype)."'";
513
514 dol_syslog(get_class($this)."::delete_label", LOG_DEBUG);
515 $resql = $this->db->query($sql);
516 if ($resql) {
517 return 1;
518 } else {
519 dol_print_error($this->db);
520 return -1;
521 }
522 } else {
523 return 0;
524 }
525 }
526
554 public function update($attrname, $label, $type, $length, $elementtype, $unique = 0, $required = 0, $pos = 0, $param = '', $alwayseditable = 0, $perms = '', $list = '', $help = '', $default = '', $computed = '', $entity = '', $langfile = '', $enabled = '1', $totalizable = 0, $printable = 0, $moreparams = array())
555 {
556 global $hookmanager;
557
558 if ($elementtype == 'thirdparty') {
559 $elementtype = 'societe';
560 }
561 if ($elementtype == 'contact') {
562 $elementtype = 'socpeople';
563 }
564
565 $table = $elementtype.'_extrafields';
566 if ($elementtype == 'categorie') {
567 $table = 'categories_extrafields';
568 }
569
570 if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname)) {
571 if ($type == 'boolean') {
572 $typedb = 'int';
573 $lengthdb = '1';
574 } elseif ($type == 'price') {
575 $typedb = 'double';
576 $lengthdb = '24,8';
577 } elseif ($type == 'pricecy') {
578 $typedb = 'varchar';
579 $lengthdb = '64';
580 } elseif ($type == 'phone') {
581 $typedb = 'varchar';
582 $lengthdb = '20';
583 } elseif ($type == 'mail' || $type == 'ip') {
584 $typedb = 'varchar';
585 $lengthdb = '128';
586 } elseif ($type == 'url') {
587 $typedb = 'varchar';
588 $lengthdb = '255';
589 } elseif (($type == 'select') || ($type == 'sellist') || ($type == 'radio') || ($type == 'checkbox') || ($type == 'chkbxlst')) {
590 $typedb = 'varchar';
591 $lengthdb = '255';
592 } elseif ($type == 'html') {
593 $typedb = 'text';
594 } elseif ($type == 'link') {
595 $typedb = 'int';
596 $lengthdb = '11';
597 } elseif ($type == 'password') {
598 $typedb = 'varchar';
599 $lengthdb = '128';
600 } else {
601 $typedb = $type;
602 $lengthdb = $length;
603 }
604 $field_desc = array('type'=>$typedb, 'value'=>$lengthdb, 'null'=>($required ? 'NOT NULL' : 'NULL'), 'default'=>$default);
605
606 if (is_object($hookmanager)) {
607 $hookmanager->initHooks(array('extrafieldsdao'));
608 $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);
609 $reshook = $hookmanager->executeHooks('updateExtrafields', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
610
611 if ($reshook < 0) {
612 $this->error = $this->db->lasterror();
613 return -1;
614 }
615 }
616
617 if ($type != 'separate') { // No table update when separate type
618 $result = $this->db->DDLUpdateField($this->db->prefix().$table, $attrname, $field_desc);
619 }
620 if ($result > 0 || $type == 'separate') {
621 if ($label) {
622 $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);
623 }
624 if ($result > 0) {
625 $sql = '';
626 if ($unique) {
627 $sql = "ALTER TABLE ".$this->db->prefix().$table." ADD UNIQUE INDEX uk_".$table."_".$attrname." (".$attrname.")";
628 } else {
629 $sql = "ALTER TABLE ".$this->db->prefix().$table." DROP INDEX IF EXISTS uk_".$table."_".$attrname;
630 }
631 dol_syslog(get_class($this).'::update', LOG_DEBUG);
632 $resql = $this->db->query($sql, 1, 'dml');
633 /*if ($resql < 0) {
634 $this->error = $this->db->lasterror();
635 return -1;
636 }*/
637 return 1;
638 } else {
639 $this->error = $this->db->lasterror();
640 return -1;
641 }
642 } else {
643 $this->error = $this->db->lasterror();
644 return -1;
645 }
646 } else {
647 return 0;
648 }
649 }
650
651 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
679 private function update_label($attrname, $label, $type, $size, $elementtype, $unique = 0, $required = 0, $pos = 0, $param = '', $alwayseditable = 0, $perms = '', $list = '0', $help = '', $default = '', $computed = '', $entity = '', $langfile = '', $enabled = '1', $totalizable = 0, $printable = 0, $moreparams = array())
680 {
681 // phpcs:enable
682 global $conf, $user;
683 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);
684
685 // Clean parameters
686 if ($elementtype == 'thirdparty') {
687 $elementtype = 'societe';
688 }
689 if ($elementtype == 'contact') {
690 $elementtype = 'socpeople';
691 }
692
693 if (empty($pos)) {
694 $pos = 0;
695 }
696 if (empty($list)) {
697 $list = '0';
698 }
699 if (empty($totalizable)) {
700 $totalizable = 0;
701 }
702 if (empty($required)) {
703 $required = 0;
704 }
705 if (empty($unique)) {
706 $unique = 0;
707 }
708 if (empty($alwayseditable)) {
709 $alwayseditable = 0;
710 }
711
712 $css = '';
713 if (!empty($moreparams) && !empty($moreparams['css'])) {
714 $css = $moreparams['css'];
715 }
716 $csslist = '';
717 if (!empty($moreparams) && !empty($moreparams['csslist'])) {
718 $csslist = $moreparams['csslist'];
719 }
720 $cssview = '';
721 if (!empty($moreparams) && !empty($moreparams['cssview'])) {
722 $cssview = $moreparams['cssview'];
723 }
724
725 if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname)) {
726 $this->db->begin();
727
728 if (is_array($param) && count($param) > 0) {
729 $params = serialize($param);
730 } elseif (is_array($param)) {
731 $params = '';
732 } elseif (strlen($param) > 0) {
733 $params = trim($param);
734 } else {
735 $params = '';
736 }
737
738 if ($entity === '' || $entity != '0') {
739 // We dont want on all entities, we delete all and current
740 $sql_del = "DELETE FROM ".$this->db->prefix()."extrafields";
741 $sql_del .= " WHERE name = '".$this->db->escape($attrname)."'";
742 $sql_del .= " AND entity IN (0, ".($entity === '' ? $conf->entity : $entity).")";
743 $sql_del .= " AND elementtype = '".$this->db->escape($elementtype)."'";
744 } else {
745 // We want on all entities ($entities = '0'), we delete on all only (we keep setup specific to each entity)
746 $sql_del = "DELETE FROM ".$this->db->prefix()."extrafields";
747 $sql_del .= " WHERE name = '".$this->db->escape($attrname)."'";
748 $sql_del .= " AND entity = 0";
749 $sql_del .= " AND elementtype = '".$this->db->escape($elementtype)."'";
750 }
751 $resql1 = $this->db->query($sql_del);
752
753 $sql = "INSERT INTO ".$this->db->prefix()."extrafields(";
754 $sql .= " name,"; // This is code
755 $sql .= " entity,";
756 $sql .= " label,";
757 $sql .= " type,";
758 $sql .= " size,";
759 $sql .= " elementtype,";
760 $sql .= " fieldunique,";
761 $sql .= " fieldrequired,";
762 $sql .= " perms,";
763 $sql .= " langs,";
764 $sql .= " pos,";
765 $sql .= " alwayseditable,";
766 $sql .= " param,";
767 $sql .= " list,";
768 $sql .= " printable,";
769 $sql .= " totalizable,";
770 $sql .= " fielddefault,";
771 $sql .= " fieldcomputed,";
772 $sql .= " fk_user_author,";
773 $sql .= " fk_user_modif,";
774 $sql .= " datec,";
775 $sql .= " enabled,";
776 $sql .= " help,";
777 $sql .= " css,";
778 $sql .= " csslist,";
779 $sql .= " cssview";
780 $sql .= ") VALUES (";
781 $sql .= "'".$this->db->escape($attrname)."',";
782 $sql .= " ".($entity === '' ? $conf->entity : $entity).",";
783 $sql .= " '".$this->db->escape($label)."',";
784 $sql .= " '".$this->db->escape($type)."',";
785 $sql .= " '".$this->db->escape($size)."',";
786 $sql .= " '".$this->db->escape($elementtype)."',";
787 $sql .= " ".$unique.",";
788 $sql .= " ".$required.",";
789 $sql .= " ".($perms ? "'".$this->db->escape($perms)."'" : "null").",";
790 $sql .= " ".($langfile ? "'".$this->db->escape($langfile)."'" : "null").",";
791 $sql .= " ".$pos.",";
792 $sql .= " '".$this->db->escape($alwayseditable)."',";
793 $sql .= " '".$this->db->escape($params)."',";
794 $sql .= " '".$this->db->escape($list)."', ";
795 $sql .= " '".$this->db->escape($printable)."', ";
796 $sql .= " ".($totalizable ? 'TRUE' : 'FALSE').",";
797 $sql .= " ".(($default != '') ? "'".$this->db->escape($default)."'" : "null").",";
798 $sql .= " ".($computed ? "'".$this->db->escape($computed)."'" : "null").",";
799 $sql .= " ".$user->id.",";
800 $sql .= " ".$user->id.",";
801 $sql .= "'".$this->db->idate(dol_now())."',";
802 $sql .= "'".$this->db->escape($enabled)."',";
803 $sql .= " ".($help ? "'".$this->db->escape($help)."'" : "null").",";
804 $sql .= " ".($css ? "'".$this->db->escape($css)."'" : "null").",";
805 $sql .= " ".($csslist ? "'".$this->db->escape($csslist)."'" : "null").",";
806 $sql .= " ".($cssview ? "'".$this->db->escape($cssview)."'" : "null");
807 $sql .= ")";
808
809 $resql2 = $this->db->query($sql);
810
811 if ($resql1 && $resql2) {
812 $this->db->commit();
813 return 1;
814 } else {
815 $this->db->rollback();
816 dol_print_error($this->db);
817 return -1;
818 }
819 } else {
820 return 0;
821 }
822 }
823
824
825 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
833 public function fetch_name_optionals_label($elementtype, $forceload = false)
834 {
835 // phpcs:enable
836 global $conf;
837
838 if (empty($elementtype)) {
839 return array();
840 }
841
842 if ($elementtype == 'thirdparty') {
843 $elementtype = 'societe';
844 }
845 if ($elementtype == 'contact') {
846 $elementtype = 'socpeople';
847 }
848 if ($elementtype == 'order_supplier') {
849 $elementtype = 'commande_fournisseur';
850 }
851
852 // Test cache $this->attributes[$elementtype]['loaded'] to see if we must do something
853 // TODO
854
855 $array_name_label = array();
856
857 // 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
858 $sql = "SELECT rowid, name, label, type, size, elementtype, fieldunique, fieldrequired, param, pos, alwayseditable, perms, langs, list, printable, totalizable, fielddefault, fieldcomputed, entity, enabled, help,";
859 $sql .= " css, cssview, csslist";
860 $sql .= " FROM ".$this->db->prefix()."extrafields";
861 //$sql.= " WHERE entity IN (0,".$conf->entity.")"; // Filter is done later
862 if ($elementtype && $elementtype != 'all') {
863 $sql .= " WHERE elementtype = '".$this->db->escape($elementtype)."'"; // Filed with object->table_element
864 }
865 $sql .= " ORDER BY pos";
866
867 $resql = $this->db->query($sql);
868 if ($resql) {
869 $count = 0;
870 if ($this->db->num_rows($resql)) {
871 while ($tab = $this->db->fetch_object($resql)) {
872 if ($tab->entity != 0 && $tab->entity != $conf->entity) {
873 // 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
874 if ($tab->fieldrequired && is_null($tab->fielddefault)) {
875 $this->attributes[$tab->elementtype]['mandatoryfieldsofotherentities'][$tab->name] = $tab->type;
876 }
877 continue;
878 }
879
880 // We can add this attribute to object. TODO Remove this and return $this->attributes[$elementtype]['label']
881 if ($tab->type != 'separate') {
882 $array_name_label[$tab->name] = $tab->label;
883 }
884
885 $this->attributes[$tab->elementtype]['type'][$tab->name] = $tab->type;
886 $this->attributes[$tab->elementtype]['label'][$tab->name] = $tab->label;
887 $this->attributes[$tab->elementtype]['size'][$tab->name] = $tab->size;
888 $this->attributes[$tab->elementtype]['elementtype'][$tab->name] = $tab->elementtype;
889 $this->attributes[$tab->elementtype]['default'][$tab->name] = $tab->fielddefault;
890 $this->attributes[$tab->elementtype]['computed'][$tab->name] = $tab->fieldcomputed;
891 $this->attributes[$tab->elementtype]['unique'][$tab->name] = $tab->fieldunique;
892 $this->attributes[$tab->elementtype]['required'][$tab->name] = $tab->fieldrequired;
893 $this->attributes[$tab->elementtype]['param'][$tab->name] = ($tab->param ? jsonOrUnserialize($tab->param) : '');
894 $this->attributes[$tab->elementtype]['pos'][$tab->name] = $tab->pos;
895 $this->attributes[$tab->elementtype]['alwayseditable'][$tab->name] = $tab->alwayseditable;
896 $this->attributes[$tab->elementtype]['perms'][$tab->name] = ((is_null($tab->perms) || strlen($tab->perms) == 0) ? 1 : $tab->perms);
897 $this->attributes[$tab->elementtype]['langfile'][$tab->name] = $tab->langs;
898 $this->attributes[$tab->elementtype]['list'][$tab->name] = $tab->list;
899 $this->attributes[$tab->elementtype]['printable'][$tab->name] = $tab->printable;
900 $this->attributes[$tab->elementtype]['totalizable'][$tab->name] = ($tab->totalizable ? 1 : 0);
901 $this->attributes[$tab->elementtype]['entityid'][$tab->name] = $tab->entity;
902 $this->attributes[$tab->elementtype]['enabled'][$tab->name] = $tab->enabled;
903 $this->attributes[$tab->elementtype]['help'][$tab->name] = $tab->help;
904 $this->attributes[$tab->elementtype]['css'][$tab->name] = $tab->css;
905 $this->attributes[$tab->elementtype]['cssview'][$tab->name] = $tab->cssview;
906 $this->attributes[$tab->elementtype]['csslist'][$tab->name] = $tab->csslist;
907
908 $this->attributes[$tab->elementtype]['loaded'] = 1;
909 $count++;
910 }
911 }
912 if ($elementtype) {
913 $this->attributes[$elementtype]['loaded'] = 1; // Note: If nothing is found, we also set the key 'loaded' to 1.
914 $this->attributes[$elementtype]['count'] = $count;
915 }
916 } else {
917 $this->error = $this->db->lasterror();
918 dol_syslog(get_class($this)."::fetch_name_optionals_label ".$this->error, LOG_ERR);
919 }
920
921 return $array_name_label;
922 }
923
924
940 public function showInputField($key, $value, $moreparam = '', $keysuffix = '', $keyprefix = '', $morecss = '', $objectid = 0, $extrafieldsobjectkey = '', $mode = 0)
941 {
942 global $conf, $langs, $form;
943
944 if (!is_object($form)) {
945 require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
946 $form = new Form($this->db);
947 }
948
949 $out = '';
950
951 if (!preg_match('/options_$/', $keyprefix)) { // Because we work on extrafields, we add 'options_' to prefix if not already added
952 $keyprefix = $keyprefix.'options_';
953 }
954
955 if (empty($extrafieldsobjectkey)) {
956 dol_syslog(get_class($this).'::showInputField extrafieldsobjectkey required', LOG_ERR);
957 return 'BadValueForParamExtraFieldsObjectKey';
958 }
959
960 $label = $this->attributes[$extrafieldsobjectkey]['label'][$key];
961 $type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
962 $size = $this->attributes[$extrafieldsobjectkey]['size'][$key];
963 $default = $this->attributes[$extrafieldsobjectkey]['default'][$key];
964 $computed = $this->attributes[$extrafieldsobjectkey]['computed'][$key];
965 $unique = $this->attributes[$extrafieldsobjectkey]['unique'][$key];
966 $required = $this->attributes[$extrafieldsobjectkey]['required'][$key];
967 $param = $this->attributes[$extrafieldsobjectkey]['param'][$key];
968 $perms = dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1, 1, '2');
969 $langfile = $this->attributes[$extrafieldsobjectkey]['langfile'][$key];
970 $list = dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1, 1, '2');
971 $totalizable = $this->attributes[$extrafieldsobjectkey]['totalizable'][$key];
972 $help = $this->attributes[$extrafieldsobjectkey]['help'][$key];
973 $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)
974
975 if ($computed) {
976 if (!preg_match('/^search_/', $keyprefix)) {
977 return '<span class="opacitymedium">'.$langs->trans("AutomaticallyCalculated").'</span>';
978 } else {
979 return '';
980 }
981 }
982
983 //
984 // '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'
985 if (empty($morecss)) {
986 // Add automatic css
987 if ($type == 'date') {
988 $morecss = 'minwidth100imp';
989 } elseif ($type == 'datetime' || $type == 'datetimegmt' || $type == 'link') {
990 $morecss = 'minwidth200imp';
991 } elseif (in_array($type, array('int', 'integer', 'double', 'price'))) {
992 $morecss = 'maxwidth75';
993 } elseif ($type == 'password') {
994 $morecss = 'maxwidth100';
995 } elseif ($type == 'url') {
996 $morecss = 'minwidth400';
997 } elseif ($type == 'boolean') {
998 $morecss = '';
999 } elseif ($type == 'radio') {
1000 $morecss = 'width25';
1001 } else {
1002 if (empty($size) || round($size) < 12) {
1003 $morecss = 'minwidth100';
1004 } elseif (round($size) <= 48) {
1005 $morecss = 'minwidth200';
1006 } else {
1007 $morecss = 'minwidth400';
1008 }
1009 }
1010 // If css forced in attribute, we use this one
1011 if (!empty($this->attributes[$extrafieldsobjectkey]['css'][$key])) {
1012 $morecss = $this->attributes[$extrafieldsobjectkey]['css'][$key];
1013 }
1014 }
1015
1016 if (in_array($type, array('date'))) {
1017 $tmp = explode(',', $size);
1018 $newsize = $tmp[0];
1019 $showtime = 0;
1020
1021 // Do not show current date when field not required (see selectDate() method)
1022 if (!$required && $value == '') {
1023 $value = '-1';
1024 }
1025
1026 if ($mode == 1) {
1027 // search filter on a date extrafield shows two inputs to select a date range
1028 $prefill = array(
1029 'start' => isset($value['start']) ? $value['start'] : '',
1030 'end' => isset($value['end']) ? $value['end'] : ''
1031 );
1032 $out = '<div ' . ($moreparam ? $moreparam : '') . '><div class="nowrap">';
1033 $out .= $form->selectDate($prefill['start'], $keyprefix.$key.$keysuffix.'_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From"));
1034 $out .= '</div><div class="nowrap">';
1035 $out .= $form->selectDate($prefill['end'], $keyprefix.$key.$keysuffix.'_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"));
1036 $out .= '</div></div>';
1037 } else {
1038 // TODO Must also support $moreparam
1039 $out = $form->selectDate($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 0, 1);
1040 }
1041 } elseif (in_array($type, array('datetime', 'datetimegmt'))) {
1042 $tmp = explode(',', $size);
1043 $newsize = $tmp[0];
1044 $showtime = 1;
1045
1046 // Do not show current date when field not required (see selectDate() method)
1047 if (!$required && $value == '') {
1048 $value = '-1';
1049 }
1050
1051 if ($mode == 1) {
1052 // search filter on a date extrafield shows two inputs to select a date range
1053 $prefill = array(
1054 'start' => isset($value['start']) ? $value['start'] : '',
1055 'end' => isset($value['end']) ? $value['end'] : ''
1056 );
1057 $out = '<div ' . ($moreparam ? $moreparam : '') . '><div class="nowrap">';
1058 $out .= $form->selectDate($prefill['start'], $keyprefix.$key.$keysuffix.'_start', 1, 1, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From"), 'tzuserrel');
1059 $out .= '</div><div class="nowrap">';
1060 $out .= $form->selectDate($prefill['end'], $keyprefix.$key.$keysuffix.'_end', 1, 1, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"), 'tzuserrel');
1061 $out .= '</div></div>';
1062 } else {
1063 // TODO Must also support $moreparam
1064 $out = $form->selectDate($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 0, 1, '', '', '', 1, '', '', 'tzuserrel');
1065 }
1066 } elseif (in_array($type, array('int', 'integer'))) {
1067 $tmp = explode(',', $size);
1068 $newsize = $tmp[0];
1069 $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 : '').'>';
1070 } elseif (preg_match('/varchar/', $type)) {
1071 $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 : '').'>';
1072 } elseif (in_array($type, array('mail', 'ip', 'phone', 'url'))) {
1073 $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam ? $moreparam : '').'>';
1074 } elseif ($type == 'text') {
1075 if (!preg_match('/search_/', $keyprefix)) { // If keyprefix is search_ or search_options_, we must just use a simple text field
1076 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1077 $doleditor = new DolEditor($keyprefix.$key.$keysuffix, $value, '', 200, 'dolibarr_notes', 'In', false, false, false, ROWS_5, '90%');
1078 $out = $doleditor->Create(1);
1079 } else {
1080 $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam ? $moreparam : '').'>';
1081 }
1082 } elseif ($type == 'html') {
1083 if (!preg_match('/search_/', $keyprefix)) { // If keyprefix is search_ or search_options_, we must just use a simple text field
1084 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1085 $doleditor = new DolEditor($keyprefix.$key.$keysuffix, $value, '', 200, 'dolibarr_notes', 'In', false, false, isModEnabled('fckeditor') && $conf->global->FCKEDITOR_ENABLE_SOCIETE, ROWS_5, '90%');
1086 $out = $doleditor->Create(1);
1087 } else {
1088 $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam ? $moreparam : '').'>';
1089 }
1090 } elseif ($type == 'boolean') {
1091 if (empty($mode)) {
1092 $checked = '';
1093 if (!empty($value)) {
1094 $checked = ' checked value="1" ';
1095 } else {
1096 $checked = ' value="1" ';
1097 }
1098 $out = '<input type="checkbox" class="flat valignmiddle'.($morecss ? ' '.$morecss : '').' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.$checked.' '.($moreparam ? $moreparam : '').'>';
1099 } else {
1100 $out .= $form->selectyesno($keyprefix.$key.$keysuffix, $value, 1, false, 1);
1101 }
1102 } elseif ($type == 'price') {
1103 if (!empty($value)) { // $value in memory is a php numeric, we format it into user number format.
1104 $value = price($value);
1105 }
1106 $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam ? $moreparam : '').'> '.$langs->getCurrencySymbol($conf->currency);
1107 } elseif ($type == 'pricecy') {
1108 $currency = $conf->currency;
1109 if (!empty($value)) {
1110 // $value in memory is a php string like '10.01:USD'
1111 $pricetmp = explode(':', $value);
1112 $currency = !empty($pricetmp[1]) ? $pricetmp[1] : $conf->currency;
1113 $value = price($pricetmp[0]);
1114 }
1115 $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam ? $moreparam : '').'> ';
1116 $out .= $form->selectCurrency($currency, $keyprefix.$key.$keysuffix.'currency_id');
1117 } elseif ($type == 'double') {
1118 if (!empty($value)) { // $value in memory is a php numeric, we format it into user number format.
1119 $value = price($value);
1120 }
1121 $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam ? $moreparam : '').'> ';
1122 } elseif ($type == 'select') {
1123 $out = '';
1124 if ($mode) {
1125 $options = array();
1126 foreach ($param['options'] as $okey => $val) {
1127 if ((string) $okey == '') {
1128 continue;
1129 }
1130
1131 $valarray = explode('|', $val);
1132 $val = $valarray[0];
1133
1134 if ($langfile && $val) {
1135 $options[$okey] = $langs->trans($val);
1136 } else {
1137 $options[$okey] = $val;
1138 }
1139 }
1140 $selected = array();
1141 if (!is_array($value)) {
1142 $selected = explode(',', $value);
1143 }
1144
1145 $out .= $form->multiselectarray($keyprefix.$key.$keysuffix, $options, $selected, 0, 0, $morecss, 0, 0, '', '', '', !empty($conf->use_javascript_ajax) && empty($conf->global->MAIN_EXTRAFIELDS_DISABLE_SELECT2));
1146 } else {
1147 if (!empty($conf->use_javascript_ajax) && empty($conf->global->MAIN_EXTRAFIELDS_DISABLE_SELECT2)) {
1148 include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
1149 $out .= ajax_combobox($keyprefix.$key.$keysuffix, array(), 0);
1150 }
1151
1152 $out .= '<select class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam ? $moreparam : '').'>';
1153 $out .= '<option value="0">&nbsp;</option>';
1154 foreach ($param['options'] as $key2 => $val2) {
1155 if ((string) $key2 == '') {
1156 continue;
1157 }
1158 $valarray = explode('|', $val2);
1159 $val2 = $valarray[0];
1160 $parent = '';
1161 if (!empty($valarray[1])) {
1162 $parent = $valarray[1];
1163 }
1164 $out .= '<option value="'.$key2.'"';
1165 $out .= (((string) $value == (string) $key2) ? ' selected' : '');
1166 $out .= (!empty($parent) ? ' parent="'.$parent.'"' : '');
1167 $out .= '>';
1168 if ($langfile && $val2) {
1169 $out .= $langs->trans($val2);
1170 } else {
1171 $out .= $val2;
1172 }
1173 $out .= '</option>';
1174 }
1175 $out .= '</select>';
1176 }
1177 } elseif ($type == 'sellist') {
1178 $out = '';
1179 if (!empty($conf->use_javascript_ajax) && empty($conf->global->MAIN_EXTRAFIELDS_DISABLE_SELECT2)) {
1180 include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
1181 $out .= ajax_combobox($keyprefix.$key.$keysuffix, array(), 0);
1182 }
1183
1184 $out .= '<select class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam ? $moreparam : '').'>';
1185 if (is_array($param['options'])) {
1186 $param_list = array_keys($param['options']);
1187 $InfoFieldList = explode(":", $param_list[0]);
1188 $parentName = '';
1189 $parentField = '';
1190 // 0 : tableName
1191 // 1 : label field name
1192 // 2 : key fields name (if differ of rowid)
1193 // 3 : key field parent (for dependent lists)
1194 // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value
1195 // 5 : id category type
1196 // 6 : ids categories list separated by comma for category root
1197 $keyList = (empty($InfoFieldList[2]) ? 'rowid' : $InfoFieldList[2].' as rowid');
1198
1199
1200 if (count($InfoFieldList) > 4 && !empty($InfoFieldList[4])) {
1201 if (strpos($InfoFieldList[4], 'extra.') !== false) {
1202 $keyList = 'main.'.$InfoFieldList[2].' as rowid';
1203 } else {
1204 $keyList = $InfoFieldList[2].' as rowid';
1205 }
1206 }
1207 if (count($InfoFieldList) > 3 && !empty($InfoFieldList[3])) {
1208 list($parentName, $parentField) = explode('|', $InfoFieldList[3]);
1209 $keyList .= ', '.$parentField;
1210 }
1211
1212 $filter_categorie = false;
1213 if (count($InfoFieldList) > 5) {
1214 if ($InfoFieldList[0] == 'categorie') {
1215 $filter_categorie = true;
1216 }
1217 }
1218
1219 if ($filter_categorie === false) {
1220 $fields_label = explode('|', $InfoFieldList[1]);
1221 if (is_array($fields_label)) {
1222 $keyList .= ', ';
1223 $keyList .= implode(', ', $fields_label);
1224 }
1225
1226 $sqlwhere = '';
1227 $sql = "SELECT ".$keyList;
1228 $sql .= ' FROM '.$this->db->prefix().$InfoFieldList[0];
1229 if (!empty($InfoFieldList[4])) {
1230 // can use current entity filter
1231 if (strpos($InfoFieldList[4], '$ENTITY$') !== false) {
1232 $InfoFieldList[4] = str_replace('$ENTITY$', $conf->entity, $InfoFieldList[4]);
1233 }
1234 // can use SELECT request
1235 if (strpos($InfoFieldList[4], '$SEL$') !== false) {
1236 $InfoFieldList[4] = str_replace('$SEL$', 'SELECT', $InfoFieldList[4]);
1237 }
1238
1239 // current object id can be use into filter
1240 if (strpos($InfoFieldList[4], '$ID$') !== false && !empty($objectid)) {
1241 $InfoFieldList[4] = str_replace('$ID$', $objectid, $InfoFieldList[4]);
1242 } else {
1243 $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
1244 }
1245 //We have to join on extrafield table
1246 if (strpos($InfoFieldList[4], 'extra.') !== false) {
1247 $sql .= ' as main, '.$this->db->prefix().$InfoFieldList[0].'_extrafields as extra';
1248 $sqlwhere .= " WHERE extra.fk_object=main.".$InfoFieldList[2]." AND ".$InfoFieldList[4];
1249 } else {
1250 $sqlwhere .= " WHERE ".$InfoFieldList[4];
1251 }
1252 } else {
1253 $sqlwhere .= ' WHERE 1=1';
1254 }
1255 // Some tables may have field, some other not. For the moment we disable it.
1256 if (in_array($InfoFieldList[0], array('tablewithentity'))) {
1257 $sqlwhere .= ' AND entity = '.((int) $conf->entity);
1258 }
1259 $sql .= $sqlwhere;
1260 //print $sql;
1261
1262 $sql .= ' ORDER BY '.implode(', ', $fields_label);
1263
1264 dol_syslog(get_class($this).'::showInputField type=sellist', LOG_DEBUG);
1265 $resql = $this->db->query($sql);
1266 if ($resql) {
1267 $out .= '<option value="0">&nbsp;</option>';
1268 $num = $this->db->num_rows($resql);
1269 $i = 0;
1270 while ($i < $num) {
1271 $labeltoshow = '';
1272 $obj = $this->db->fetch_object($resql);
1273
1274 // Several field into label (eq table:code|label:rowid)
1275 $notrans = false;
1276 $fields_label = explode('|', $InfoFieldList[1]);
1277 if (is_array($fields_label) && count($fields_label) > 1) {
1278 $notrans = true;
1279 foreach ($fields_label as $field_toshow) {
1280 $labeltoshow .= $obj->$field_toshow.' ';
1281 }
1282 } else {
1283 $labeltoshow = $obj->{$InfoFieldList[1]};
1284 }
1285 $labeltoshow = $labeltoshow;
1286
1287 if ($value == $obj->rowid) {
1288 if (!$notrans) {
1289 foreach ($fields_label as $field_toshow) {
1290 $translabel = $langs->trans($obj->$field_toshow);
1291 $labeltoshow = $translabel.' ';
1292 }
1293 }
1294 $out .= '<option value="'.$obj->rowid.'" selected>'.$labeltoshow.'</option>';
1295 } else {
1296 if (!$notrans) {
1297 $translabel = $langs->trans($obj->{$InfoFieldList[1]});
1298 $labeltoshow = $translabel;
1299 }
1300 if (empty($labeltoshow)) {
1301 $labeltoshow = '(not defined)';
1302 }
1303
1304 if (!empty($InfoFieldList[3]) && $parentField) {
1305 $parent = $parentName.':'.$obj->{$parentField};
1306 }
1307
1308 $out .= '<option value="'.$obj->rowid.'"';
1309 $out .= ($value == $obj->rowid ? ' selected' : '');
1310 $out .= (!empty($parent) ? ' parent="'.$parent.'"' : '');
1311 $out .= '>'.$labeltoshow.'</option>';
1312 }
1313
1314 $i++;
1315 }
1316 $this->db->free($resql);
1317 } else {
1318 print 'Error in request '.$sql.' '.$this->db->lasterror().'. Check setup of extra parameters.<br>';
1319 }
1320 } else {
1321 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1322 $data = $form->select_all_categories(Categorie::$MAP_ID_TO_CODE[$InfoFieldList[5]], '', 'parent', 64, $InfoFieldList[6], 1, 1);
1323 $out .= '<option value="0">&nbsp;</option>';
1324 if (is_array($data)) {
1325 foreach ($data as $data_key => $data_value) {
1326 $out .= '<option value="'.$data_key.'"';
1327 $out .= ($value == $data_key ? ' selected' : '');
1328 $out .= '>'.$data_value.'</option>';
1329 }
1330 }
1331 }
1332 }
1333 $out .= '</select>';
1334 } elseif ($type == 'checkbox') {
1335 $value_arr = $value;
1336 if (!is_array($value)) {
1337 $value_arr = explode(',', $value);
1338 }
1339 $out = $form->multiselectarray($keyprefix.$key.$keysuffix, (empty($param['options']) ?null:$param['options']), $value_arr, '', 0, '', 0, '100%');
1340 } elseif ($type == 'radio') {
1341 $out = '';
1342 foreach ($param['options'] as $keyopt => $val) {
1343 $out .= '<input class="flat '.$morecss.'" type="radio" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam ? $moreparam : '');
1344 $out .= ' value="'.$keyopt.'"';
1345 $out .= ' id="'.$keyprefix.$key.$keysuffix.'_'.$keyopt.'"';
1346 $out .= ($value == $keyopt ? 'checked' : '');
1347 $out .= '/><label for="'.$keyprefix.$key.$keysuffix.'_'.$keyopt.'">'.$langs->trans($val).'</label><br>';
1348 }
1349 } elseif ($type == 'chkbxlst') {
1350 if (is_array($value)) {
1351 $value_arr = $value;
1352 } else {
1353 $value_arr = explode(',', $value);
1354 }
1355
1356 if (is_array($param['options'])) {
1357 $param_list = array_keys($param['options']);
1358 $InfoFieldList = explode(":", $param_list[0]);
1359 $parentName = '';
1360 $parentField = '';
1361 // 0 : tableName
1362 // 1 : label field name
1363 // 2 : key fields name (if differ of rowid)
1364 // 3 : key field parent (for dependent lists)
1365 // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value
1366 // 5 : id category type
1367 // 6 : ids categories list separated by comma for category root
1368 $keyList = (empty($InfoFieldList[2]) ? 'rowid' : $InfoFieldList[2].' as rowid');
1369
1370 if (count($InfoFieldList) > 3 && !empty($InfoFieldList[3])) {
1371 list ($parentName, $parentField) = explode('|', $InfoFieldList[3]);
1372 $keyList .= ', '.$parentField;
1373 }
1374 if (count($InfoFieldList) > 4 && !empty($InfoFieldList[4])) {
1375 if (strpos($InfoFieldList[4], 'extra.') !== false) {
1376 $keyList = 'main.'.$InfoFieldList[2].' as rowid';
1377 } else {
1378 $keyList = $InfoFieldList[2].' as rowid';
1379 }
1380 }
1381
1382 $filter_categorie = false;
1383 if (count($InfoFieldList) > 5) {
1384 if ($InfoFieldList[0] == 'categorie') {
1385 $filter_categorie = true;
1386 }
1387 }
1388
1389 if ($filter_categorie === false) {
1390 $fields_label = explode('|', $InfoFieldList[1]);
1391 if (is_array($fields_label)) {
1392 $keyList .= ', ';
1393 $keyList .= implode(', ', $fields_label);
1394 }
1395
1396 $sqlwhere = '';
1397 $sql = "SELECT ".$keyList;
1398 $sql .= ' FROM '.$this->db->prefix().$InfoFieldList[0];
1399 if (!empty($InfoFieldList[4])) {
1400 // can use current entity filter
1401 if (strpos($InfoFieldList[4], '$ENTITY$') !== false) {
1402 $InfoFieldList[4] = str_replace('$ENTITY$', $conf->entity, $InfoFieldList[4]);
1403 }
1404 // can use SELECT request
1405 if (strpos($InfoFieldList[4], '$SEL$') !== false) {
1406 $InfoFieldList[4] = str_replace('$SEL$', 'SELECT', $InfoFieldList[4]);
1407 }
1408
1409 // current object id can be use into filter
1410 if (strpos($InfoFieldList[4], '$ID$') !== false && !empty($objectid)) {
1411 $InfoFieldList[4] = str_replace('$ID$', $objectid, $InfoFieldList[4]);
1412 } elseif (preg_match("#^.*list.php$#", $_SERVER["PHP_SELF"])) {
1413 // Pattern for word=$ID$
1414 $word = '\b[a-zA-Z0-9-\.-_]+\b=\$ID\$';
1415
1416 // Removing space arount =, ( and )
1417 $InfoFieldList[4] = preg_replace('# *(=|\‍(|\‍)) *#', '$1', $InfoFieldList[4]);
1418
1419 $nbPreg = 1;
1420 // While we have parenthesis
1421 while ($nbPreg != 0) {
1422 // Init des compteurs
1423 $nbPregRepl = $nbPregSel = 0;
1424 // On retire toutes les parenthèses sans = avant
1425 $InfoFieldList[4] = preg_replace('#([^=])(\‍([^)^(]*('.$word.')[^)^(]*\‍))#', '$1 $3 ', $InfoFieldList[4], -1, $nbPregRepl);
1426 // On retire les espaces autour des = et parenthèses
1427 $InfoFieldList[4] = preg_replace('# *(=|\‍(|\‍)) *#', '$1', $InfoFieldList[4]);
1428 // On retire toutes les parenthèses avec = avant
1429 $InfoFieldList[4] = preg_replace('#\b[a-zA-Z0-9-\.-_]+\b=\‍([^)^(]*('.$word.')[^)^(]*\‍)#', '$1 ', $InfoFieldList[4], -1, $nbPregSel);
1430 // On retire les espaces autour des = et parenthèses
1431 $InfoFieldList[4] = preg_replace('# *(=|\‍(|\‍)) *#', '$1', $InfoFieldList[4]);
1432
1433 // Calcul du compteur général pour la boucle
1434 $nbPreg = $nbPregRepl + $nbPregSel;
1435 }
1436
1437 // Si l'on a un AND ou un OR, avant ou après
1438 preg_match('#(AND|OR|) *('.$word.') *(AND|OR|)#', $InfoFieldList[4], $matchCondition);
1439 while (!empty($matchCondition[0])) {
1440 // If the two sides differ but are not empty
1441 if (!empty($matchCondition[1]) && !empty($matchCondition[3]) && $matchCondition[1] != $matchCondition[3]) {
1442 // Nobody sain would do that without parentheses
1443 $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
1444 } else {
1445 if (!empty($matchCondition[1])) {
1446 $boolCond = (($matchCondition[1] == "AND") ? ' AND TRUE ' : ' OR FALSE ');
1447 $InfoFieldList[4] = str_replace($matchCondition[0], $boolCond.$matchCondition[3], $InfoFieldList[4]);
1448 } elseif (!empty($matchCondition[3])) {
1449 $boolCond = (($matchCondition[3] == "AND") ? ' TRUE AND ' : ' FALSE OR');
1450 $InfoFieldList[4] = str_replace($matchCondition[0], $boolCond, $InfoFieldList[4]);
1451 } else {
1452 $InfoFieldList[4] = " TRUE ";
1453 }
1454 }
1455
1456 // Si l'on a un AND ou un OR, avant ou après
1457 preg_match('#(AND|OR|) *('.$word.') *(AND|OR|)#', $InfoFieldList[4], $matchCondition);
1458 }
1459 } else {
1460 $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
1461 }
1462
1463 // We have to join on extrafield table
1464 if (strpos($InfoFieldList[4], 'extra.') !== false) {
1465 $sql .= ' as main, '.$this->db->prefix().$InfoFieldList[0].'_extrafields as extra';
1466 $sqlwhere .= " WHERE extra.fk_object=main.".$InfoFieldList[2]." AND ".$InfoFieldList[4];
1467 } else {
1468 $sqlwhere .= " WHERE ".$InfoFieldList[4];
1469 }
1470 } else {
1471 $sqlwhere .= ' WHERE 1=1';
1472 }
1473 // Some tables may have field, some other not. For the moment we disable it.
1474 if (in_array($InfoFieldList[0], array('tablewithentity'))) {
1475 $sqlwhere .= " AND entity = ".((int) $conf->entity);
1476 }
1477 // $sql.=preg_replace('/^ AND /','',$sqlwhere);
1478 // print $sql;
1479
1480 $sql .= $sqlwhere;
1481 dol_syslog(get_class($this).'::showInputField type=chkbxlst', LOG_DEBUG);
1482 $resql = $this->db->query($sql);
1483 if ($resql) {
1484 $num = $this->db->num_rows($resql);
1485 $i = 0;
1486
1487 $data = array();
1488
1489 while ($i < $num) {
1490 $labeltoshow = '';
1491 $obj = $this->db->fetch_object($resql);
1492
1493 $notrans = false;
1494 // Several field into label (eq table:code|label:rowid)
1495 $fields_label = explode('|', $InfoFieldList[1]);
1496 if (is_array($fields_label)) {
1497 $notrans = true;
1498 foreach ($fields_label as $field_toshow) {
1499 $labeltoshow .= $obj->$field_toshow.' ';
1500 }
1501 } else {
1502 $labeltoshow = $obj->{$InfoFieldList[1]};
1503 }
1504 $labeltoshow = dol_trunc($labeltoshow, 45);
1505
1506 if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1507 $labeltoshow = '';
1508 foreach ($fields_label as $field_toshow) {
1509 $translabel = $langs->trans($obj->$field_toshow);
1510 if ($translabel != $obj->$field_toshow) {
1511 $labeltoshow .= ' '.dol_trunc($translabel, 18).' ';
1512 } else {
1513 $labeltoshow .= ' '.dol_trunc($obj->$field_toshow, 18).' ';
1514 }
1515 }
1516 $data[$obj->rowid] = $labeltoshow;
1517 } else {
1518 if (!$notrans) {
1519 $translabel = $langs->trans($obj->{$InfoFieldList[1]});
1520 if ($translabel != $obj->{$InfoFieldList[1]}) {
1521 $labeltoshow = dol_trunc($translabel, 18);
1522 } else {
1523 $labeltoshow = dol_trunc($obj->{$InfoFieldList[1]}, 18);
1524 }
1525 }
1526 if (empty($labeltoshow)) {
1527 $labeltoshow = '(not defined)';
1528 }
1529
1530 if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1531 $data[$obj->rowid] = $labeltoshow;
1532 }
1533
1534 if (!empty($InfoFieldList[3]) && $parentField) {
1535 $parent = $parentName.':'.$obj->{$parentField};
1536 }
1537
1538 $data[$obj->rowid] = $labeltoshow;
1539 }
1540
1541 $i++;
1542 }
1543 $this->db->free($resql);
1544
1545 $out = $form->multiselectarray($keyprefix.$key.$keysuffix, $data, $value_arr, '', 0, '', 0, '100%');
1546 } else {
1547 print 'Error in request '.$sql.' '.$this->db->lasterror().'. Check setup of extra parameters.<br>';
1548 }
1549 } else {
1550 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1551 $data = $form->select_all_categories(Categorie::$MAP_ID_TO_CODE[$InfoFieldList[5]], '', 'parent', 64, $InfoFieldList[6], 1, 1);
1552 $out = $form->multiselectarray($keyprefix.$key.$keysuffix, $data, $value_arr, '', 0, '', 0, '100%');
1553 }
1554 }
1555 } elseif ($type == 'link') {
1556 $param_list = array_keys($param['options']); // $param_list='ObjectName:classPath'
1557 $showempty = (($required && $default != '') ? 0 : 1);
1558 $out = $form->selectForForms($param_list[0], $keyprefix.$key.$keysuffix, $value, $showempty, '', '', $morecss);
1559 } elseif ($type == 'password') {
1560 // If prefix is 'search_', field is used as a filter, we use a common text field.
1561 $out = '<input style="display:none" type="text" name="fakeusernameremembered">'; // Hidden field to reduce impact of evil Google Chrome autopopulate bug.
1562 $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 : '').'>';
1563 }
1564 if (!empty($hidden)) {
1565 $out = '<input type="hidden" value="'.$value.'" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'"/>';
1566 }
1567 /* Add comments
1568 if ($type == 'date') $out.=' (YYYY-MM-DD)';
1569 elseif ($type == 'datetime') $out.=' (YYYY-MM-DD HH:MM:SS)';
1570 */
1571 /*if (!empty($help) && $keyprefix != 'search_options_') {
1572 $out .= $form->textwithpicto('', $help, 1, 'help', '', 0, 3);
1573 }*/
1574 return $out;
1575 }
1576
1577
1588 public function showOutputField($key, $value, $moreparam = '', $extrafieldsobjectkey = '', $outputlangs = null)
1589 {
1590 global $conf, $langs;
1591
1592 if (is_null($outputlangs) || !is_object($outputlangs)) {
1593 $outputlangs = $langs;
1594 }
1595
1596 if (empty($extrafieldsobjectkey)) {
1597 dol_syslog(get_class($this).'::showOutputField extrafieldsobjectkey required', LOG_ERR);
1598 return 'BadValueForParamExtraFieldsObjectKey';
1599 }
1600
1601 $label = $this->attributes[$extrafieldsobjectkey]['label'][$key];
1602 $type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
1603 $size = $this->attributes[$extrafieldsobjectkey]['size'][$key]; // Can be '255', '24,8'...
1604 $default = $this->attributes[$extrafieldsobjectkey]['default'][$key];
1605 $computed = $this->attributes[$extrafieldsobjectkey]['computed'][$key];
1606 $unique = $this->attributes[$extrafieldsobjectkey]['unique'][$key];
1607 $required = $this->attributes[$extrafieldsobjectkey]['required'][$key];
1608 $param = $this->attributes[$extrafieldsobjectkey]['param'][$key];
1609 $perms = dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1, 1, '2');
1610 $langfile = $this->attributes[$extrafieldsobjectkey]['langfile'][$key];
1611 $list = dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1, 1, '2');
1612 $help = $this->attributes[$extrafieldsobjectkey]['help'][$key];
1613 $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)
1614
1615 if ($hidden) {
1616 return ''; // This is a protection. If field is hidden, we should just not call this method.
1617 }
1618
1619 //if ($computed) $value = // $value is already calculated into $value before calling this method
1620
1621 $showsize = 0;
1622 if ($type == 'date') {
1623 $showsize = 10;
1624 if ($value !== '') {
1625 $value = dol_print_date($value, 'day'); // For date without hour, date is always GMT for storage and output
1626 }
1627 } elseif ($type == 'datetime') {
1628 $showsize = 19;
1629 if ($value !== '') {
1630 $value = dol_print_date($value, 'dayhour', 'tzuserrel');
1631 }
1632 } elseif ($type == 'datetimegmt') {
1633 $showsize = 19;
1634 if ($value !== '') {
1635 $value = dol_print_date($value, 'dayhour', 'gmt');
1636 }
1637 } elseif ($type == 'int') {
1638 $showsize = 10;
1639 } elseif ($type == 'double') {
1640 if (!empty($value)) {
1641 //$value=price($value);
1642 $sizeparts = explode(",", $size);
1643 $number_decimals = array_key_exists(1, $sizeparts) ? $sizeparts[1] : 0;
1644 $value = price($value, 0, $outputlangs, 0, 0, $number_decimals, '');
1645 }
1646 } elseif ($type == 'boolean') {
1647 $checked = '';
1648 if (!empty($value)) {
1649 $checked = ' checked ';
1650 }
1651 $value = '<input type="checkbox" '.$checked.' '.($moreparam ? $moreparam : '').' readonly disabled>';
1652 } elseif ($type == 'mail') {
1653 $value = dol_print_email($value, 0, 0, 0, 64, 1, 1);
1654 } elseif ($type == 'ip') {
1655 $value = dol_print_ip($value, 0);
1656 } elseif ($type == 'url') {
1657 $value = dol_print_url($value, '_blank', 32, 1);
1658 } elseif ($type == 'phone') {
1659 $value = dol_print_phone($value, '', 0, 0, '', '&nbsp;', 'phone');
1660 } elseif ($type == 'price') {
1661 //$value = price($value, 0, $langs, 0, 0, -1, $conf->currency);
1662 if ($value || $value == '0') {
1663 $value = price($value, 0, $outputlangs, 0, $conf->global->MAIN_MAX_DECIMALS_TOT, -1).' '.$outputlangs->getCurrencySymbol($conf->currency);
1664 }
1665 } elseif ($type == 'pricecy') {
1666 $currency = $conf->currency;
1667 if (!empty($value)) {
1668 // $value in memory is a php string like '0.01:EUR'
1669 $pricetmp = explode(':', $value);
1670 $currency = !empty($pricetmp[1]) ? $pricetmp[1] : $conf->currency;
1671 $value = $pricetmp[0];
1672 }
1673 if ($value || $value == '0') {
1674 $value = price($value, 0, $outputlangs, 0, $conf->global->MAIN_MAX_DECIMALS_TOT, -1, $currency);
1675 }
1676 } elseif ($type == 'select') {
1677 $valstr = (!empty($param['options'][$value]) ? $param['options'][$value] : '');
1678 if (($pos = strpos($valstr, "|")) !== false) {
1679 $valstr = substr($valstr, 0, $pos);
1680 }
1681 if ($langfile && $valstr) {
1682 $value = $outputlangs->trans($valstr);
1683 } else {
1684 $value = $valstr;
1685 }
1686 } elseif ($type == 'sellist') {
1687 $param_list = array_keys($param['options']);
1688 $InfoFieldList = explode(":", $param_list[0]);
1689
1690 $selectkey = "rowid";
1691 $keyList = 'rowid';
1692
1693 if (count($InfoFieldList) >= 3) {
1694 $selectkey = $InfoFieldList[2];
1695 $keyList = $InfoFieldList[2].' as rowid';
1696 }
1697
1698 $fields_label = explode('|', $InfoFieldList[1]);
1699 if (is_array($fields_label)) {
1700 $keyList .= ', ';
1701 $keyList .= implode(', ', $fields_label);
1702 }
1703
1704 $filter_categorie = false;
1705 if (count($InfoFieldList) > 5) {
1706 if ($InfoFieldList[0] == 'categorie') {
1707 $filter_categorie = true;
1708 }
1709 }
1710
1711 $sql = "SELECT ".$keyList;
1712 $sql .= ' FROM '.$this->db->prefix().$InfoFieldList[0];
1713 if (!empty($InfoFieldList[4]) && strpos($InfoFieldList[4], 'extra.') !== false) {
1714 $sql .= ' as main';
1715 }
1716 if ($selectkey == 'rowid' && empty($value)) {
1717 $sql .= " WHERE ".$selectkey." = 0";
1718 } elseif ($selectkey == 'rowid') {
1719 $sql .= " WHERE ".$selectkey." = ".((int) $value);
1720 } else {
1721 $sql .= " WHERE ".$selectkey." = '".$this->db->escape($value)."'";
1722 }
1723
1724 //$sql.= ' AND entity = '.$conf->entity;
1725
1726 dol_syslog(get_class($this).':showOutputField:$type=sellist', LOG_DEBUG);
1727 $resql = $this->db->query($sql);
1728 if ($resql) {
1729 if ($filter_categorie === false) {
1730 $value = ''; // value was used, so now we reste it to use it to build final output
1731
1732 $obj = $this->db->fetch_object($resql);
1733
1734 // Several field into label (eq table:code|label:rowid)
1735 $fields_label = explode('|', $InfoFieldList[1]);
1736
1737 if (is_array($fields_label) && count($fields_label) > 1) {
1738 foreach ($fields_label as $field_toshow) {
1739 $translabel = '';
1740 if (!empty($obj->$field_toshow)) {
1741 $translabel = $outputlangs->trans($obj->$field_toshow);
1742
1743 if ($translabel != $obj->$field_toshow) {
1744 $value .= dol_trunc($translabel, 24) . ' ';
1745 } else {
1746 $value .= $obj->$field_toshow . ' ';
1747 }
1748 }
1749 }
1750 } else {
1751 $translabel = '';
1752 $tmppropname = $InfoFieldList[1];
1753 //$obj->$tmppropname = '';
1754 if (!empty(isset($obj->$tmppropname) ? $obj->$tmppropname : '')) {
1755 $translabel = $outputlangs->trans($obj->$tmppropname);
1756 }
1757 if ($translabel != (isset($obj->$tmppropname) ? $obj->$tmppropname : '')) {
1758 $value = dol_trunc($translabel, 18);
1759 } else {
1760 $value = isset($obj->$tmppropname) ? $obj->$tmppropname : '';
1761 }
1762 }
1763 } else {
1764 $toprint = array();
1765 $obj = $this->db->fetch_object($resql);
1766 if ($obj->rowid) {
1767 require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
1768 $c = new Categorie($this->db);
1769 $result = $c->fetch($obj->rowid);
1770 if ($result > 0) {
1771 $ways = $c->print_all_ways(); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formatted text
1772 foreach ($ways as $way) {
1773 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories"' . ($c->color ? ' style="background: #' . $c->color . ';"' : ' style="background: #bbb"') . '>' . img_object('', 'category') . ' ' . $way . '</li>';
1774 }
1775 }
1776 }
1777 $value = '<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
1778 }
1779 } else {
1780 dol_syslog(get_class($this).'::showOutputField error '.$this->db->lasterror(), LOG_WARNING);
1781 }
1782 } elseif ($type == 'radio') {
1783 if (!isset($param['options'][$value])) {
1784 $outputlangs->load('errors');
1785 $value = $outputlangs->trans('ErrorNoValueForRadioType');
1786 } else {
1787 $value = $outputlangs->trans($param['options'][$value]);
1788 }
1789 } elseif ($type == 'checkbox') {
1790 $value_arr = explode(',', $value);
1791 $value = '';
1792 $toprint = array();
1793 if (is_array($value_arr)) {
1794 foreach ($value_arr as $keyval => $valueval) {
1795 if (!empty($valueval)) {
1796 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.$param['options'][$valueval].'</li>';
1797 }
1798 }
1799 }
1800 $value = '<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
1801 } elseif ($type == 'chkbxlst') {
1802 $value_arr = explode(',', $value);
1803
1804 $param_list = array_keys($param['options']);
1805 $InfoFieldList = explode(":", $param_list[0]);
1806
1807 $selectkey = "rowid";
1808 $keyList = 'rowid';
1809
1810 if (count($InfoFieldList) >= 3) {
1811 $selectkey = $InfoFieldList[2];
1812 $keyList = $InfoFieldList[2].' as rowid';
1813 }
1814
1815 $fields_label = explode('|', $InfoFieldList[1]);
1816 if (is_array($fields_label)) {
1817 $keyList .= ', ';
1818 $keyList .= implode(', ', $fields_label);
1819 }
1820
1821 $filter_categorie = false;
1822 if (count($InfoFieldList) > 5) {
1823 if ($InfoFieldList[0] == 'categorie') {
1824 $filter_categorie = true;
1825 }
1826 }
1827
1828 $sql = "SELECT ".$keyList;
1829 $sql .= " FROM ".$this->db->prefix().$InfoFieldList[0];
1830 if (strpos($InfoFieldList[4], 'extra.') !== false) {
1831 $sql .= ' as main';
1832 }
1833 // $sql.= " WHERE ".$selectkey."='".$this->db->escape($value)."'";
1834 // $sql.= ' AND entity = '.$conf->entity;
1835
1836 dol_syslog(get_class($this).':showOutputField:$type=chkbxlst', LOG_DEBUG);
1837 $resql = $this->db->query($sql);
1838 if ($resql) {
1839 if ($filter_categorie === false) {
1840 $value = ''; // value was used, so now we reste it to use it to build final output
1841 $toprint = array();
1842 while ($obj = $this->db->fetch_object($resql)) {
1843 // Several field into label (eq table:code|label:rowid)
1844 $fields_label = explode('|', $InfoFieldList[1]);
1845 if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1846 if (is_array($fields_label) && count($fields_label) > 1) {
1847 $label = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">';
1848 foreach ($fields_label as $field_toshow) {
1849 $translabel = '';
1850 if (!empty($obj->$field_toshow)) {
1851 $translabel = $outputlangs->trans($obj->$field_toshow);
1852 }
1853 if ($translabel != $field_toshow) {
1854 $label .= ' '.dol_trunc($translabel, 18);
1855 } else {
1856 $label .= ' '.$obj->$field_toshow;
1857 }
1858 }
1859 $label .= '</li>';
1860 $toprint[] = $label;
1861 } else {
1862 $translabel = '';
1863 if (!empty($obj->{$InfoFieldList[1]})) {
1864 $translabel = $outputlangs->trans($obj->{$InfoFieldList[1]});
1865 }
1866 if ($translabel != $obj->{$InfoFieldList[1]}) {
1867 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.dol_trunc($translabel, 18).'</li>';
1868 } else {
1869 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.$obj->{$InfoFieldList[1]}.'</li>';
1870 }
1871 }
1872 }
1873 }
1874 } else {
1875 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1876
1877 $toprint = array();
1878 while ($obj = $this->db->fetch_object($resql)) {
1879 if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1880 $c = new Categorie($this->db);
1881 $c->fetch($obj->rowid);
1882 $ways = $c->print_all_ways(); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formatted text
1883 foreach ($ways as $way) {
1884 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories"'.($c->color ? ' style="background: #'.$c->color.';"' : ' style="background: #bbb"').'>'.img_object('', 'category').' '.$way.'</li>';
1885 }
1886 }
1887 }
1888 }
1889 if (!empty($toprint)) $value = '<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
1890 } else {
1891 dol_syslog(get_class($this).'::showOutputField error '.$this->db->lasterror(), LOG_WARNING);
1892 }
1893 } elseif ($type == 'link') {
1894 $out = '';
1895
1896 // Only if something to display (perf)
1897 if ($value) { // If we have -1 here, pb is into insert, not into ouptut (fix insert instead of changing code here to compensate)
1898 $param_list = array_keys($param['options']); // $param_list='ObjectName:classPath'
1899
1900 $InfoFieldList = explode(":", $param_list[0]);
1901 $classname = $InfoFieldList[0];
1902 $classpath = $InfoFieldList[1];
1903 if (!empty($classpath)) {
1904 dol_include_once($InfoFieldList[1]);
1905 if ($classname && class_exists($classname)) {
1906 $object = new $classname($this->db);
1907 $object->fetch($value);
1908 $value = $object->getNomUrl(3);
1909 }
1910 } else {
1911 dol_syslog('Error bad setup of extrafield', LOG_WARNING);
1912 return 'Error bad setup of extrafield';
1913 }
1914 }
1915 } elseif ($type == 'text') {
1916 $value = dol_htmlentitiesbr($value);
1917 } elseif ($type == 'html') {
1918 $value = dol_htmlentitiesbr($value);
1919 } elseif ($type == 'password') {
1920 $value = dol_trunc(preg_replace('/./i', '*', $value), 8, 'right', 'UTF-8', 1);
1921 } else {
1922 $showsize = round((float) $size);
1923 if ($showsize > 48) {
1924 $showsize = 48;
1925 }
1926 }
1927
1928 //print $type.'-'.$size;
1929 $out = $value;
1930
1931 return $out;
1932 }
1933
1941 public function getAlignFlag($key, $extrafieldsobjectkey = '')
1942 {
1943 global $conf, $langs;
1944
1945 $type = 'varchar';
1946 if (!empty($extrafieldsobjectkey)) {
1947 $type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
1948 }
1949
1950 $cssstring = '';
1951
1952 if (in_array($type, array('date', 'datetime', 'datetimegmt'))) {
1953 $cssstring = "center";
1954 } elseif (in_array($type, array('int', 'price', 'double'))) {
1955 $cssstring = "right";
1956 } elseif (in_array($type, array('boolean', 'radio', 'checkbox', 'ip'))) {
1957 $cssstring = "center";
1958 }
1959
1960 if (!empty($this->attributes[$extrafieldsobjectkey]['csslist'][$key])) {
1961 $cssstring .= ($cssstring ? ' ' : '').$this->attributes[$extrafieldsobjectkey]['csslist'][$key];
1962 } else {
1963 if (in_array($type, array('ip'))) {
1964 $cssstring .= ($cssstring ? ' ' : '').'tdoverflowmax150';
1965 }
1966 }
1967
1968 return $cssstring;
1969 }
1970
1981 public function showSeparator($key, $object, $colspan = 2, $display_type = 'card', $mode = '')
1982 {
1983 global $conf, $langs;
1984
1985 $tagtype='tr';
1986 $tagtype_dyn='td';
1987
1988 if ($display_type=='line') {
1989 $tagtype='div';
1990 $tagtype_dyn='span';
1991 $colspan=0;
1992 }
1993
1994 $extrafield_param = $this->attributes[$object->table_element]['param'][$key];
1995 $extrafield_param_list = array();
1996 if (!empty($extrafield_param) && is_array($extrafield_param)) {
1997 $extrafield_param_list = array_keys($extrafield_param['options']);
1998 }
1999
2000 // Set $extrafield_collapse_display_value (do we have to collapse/expand the group after the separator)
2001 $extrafield_collapse_display_value = -1;
2002 $expand_display = false;
2003 if (is_array($extrafield_param_list) && count($extrafield_param_list) > 0) {
2004 $extrafield_collapse_display_value = intval($extrafield_param_list[0]);
2005 $expand_display = ((isset($_COOKIE['DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key]) || GETPOST('ignorecollapsesetup', 'int')) ? (empty($_COOKIE['DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key]) ? false : true) : ($extrafield_collapse_display_value == 2 ? false : true));
2006 }
2007 $disabledcookiewrite = 0;
2008 if ($mode == 'create') {
2009 // On create mode, force separator group to not be collapsable
2010 $extrafield_collapse_display_value = 1;
2011 $expand_display = true; // We force group to be shown expanded
2012 $disabledcookiewrite = 1; // We keep status of group unchanged into the cookie
2013 }
2014
2015 $out = '<'.$tagtype.' id="trextrafieldseparator'.$key.(!empty($object->id)?'_'.$object->id:'').'" class="trextrafieldseparator trextrafieldseparator'.$key.(!empty($object->id)?'_'.$object->id:'').'">';
2016 $out .= '<'.$tagtype_dyn.' '.(!empty($colspan)?'colspan="' . $colspan . '"':'').'>';
2017 // Some js code will be injected here to manage the collapsing of extrafields
2018 // Output the picto
2019 $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>';
2020 $out .= '&nbsp;';
2021 $out .= '<strong>';
2022 $out .= $langs->trans($this->attributes[$object->table_element]['label'][$key]);
2023 $out .= '</strong>';
2024 $out .= '</'.$tagtype_dyn.'>';
2025 $out .= '</'.$tagtype.'>';
2026
2027 $collapse_group = $key.(!empty($object->id) ? '_'.$object->id : '');
2028 //$extrafields_collapse_num = $this->attributes[$object->table_element]['pos'][$key].(!empty($object->id)?'_'.$object->id:'');
2029
2030 if ($extrafield_collapse_display_value == 1 || $extrafield_collapse_display_value == 2) {
2031 // Set the collapse_display status to cookie in priority or if ignorecollapsesetup is 1, if cookie and ignorecollapsesetup not defined, use the setup.
2032 $this->expand_display[$collapse_group] = $expand_display;
2033
2034 if (!empty($conf->use_javascript_ajax)) {
2035 $out .= '<!-- Add js script to manage the collapse/uncollapse of extrafields separators '.$key.' -->'."\n";
2036 $out .= '<script nonce="'.getNonce().'" type="text/javascript">'."\n";
2037 $out .= 'jQuery(document).ready(function(){'."\n";
2038 if (empty($disabledcookiewrite)) {
2039 if ($expand_display === false) {
2040 $out .= ' console.log("Inject js for the collapsing of extrafield '.$key.' - hide");'."\n";
2041 $out .= ' jQuery(".trextrafields_collapse'.$collapse_group.'").hide();'."\n";
2042 } else {
2043 $out .= ' console.log("Inject js for collapsing of extrafield '.$key.' - keep visible and set cookie");'."\n";
2044 $out .= ' document.cookie = "DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.'=1; path='.$_SERVER["PHP_SELF"].'"'."\n";
2045 }
2046 }
2047 $out .= ' jQuery("#trextrafieldseparator'.$key.(!empty($object->id)?'_'.$object->id:'').'").click(function(){'."\n";
2048 $out .= ' console.log("We click on collapse/uncollapse to hide/show .trextrafields_collapse'.$collapse_group.'");'."\n";
2049 $out .= ' jQuery(".trextrafields_collapse'.$collapse_group.'").toggle(100, function(){'."\n";
2050 $out .= ' if (jQuery(".trextrafields_collapse'.$collapse_group.'").is(":hidden")) {'."\n";
2051 $out .= ' jQuery("#trextrafieldseparator'.$key.(!empty($object->id)?'_'.$object->id:'').' '.$tagtype_dyn.' span").addClass("fa-plus-square").removeClass("fa-minus-square");'."\n";
2052 $out .= ' document.cookie = "DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.'=0; path='.$_SERVER["PHP_SELF"].'"'."\n";
2053 $out .= ' } else {'."\n";
2054 $out .= ' jQuery("#trextrafieldseparator'.$key.(!empty($object->id)?'_'.$object->id:'').' '.$tagtype_dyn.' span").addClass("fa-minus-square").removeClass("fa-plus-square");'."\n";
2055 $out .= ' document.cookie = "DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.'=1; path='.$_SERVER["PHP_SELF"].'"'."\n";
2056 $out .= ' }'."\n";
2057 $out .= ' });'."\n";
2058 $out .= ' });'."\n";
2059 $out .= '});'."\n";
2060 $out .= '</script>'."\n";
2061 }
2062 } else {
2063 $this->expand_display[$collapse_group] = 1;
2064 }
2065
2066 return $out;
2067 }
2068
2080 public function setOptionalsFromPost($extralabels, &$object, $onlykey = '', $todefaultifmissing = 0)
2081 {
2082 global $_POST, $langs;
2083
2084 $nofillrequired = 0; // For error when required field left blank
2085 $error_field_required = array();
2086
2087 if (isset($this->attributes[$object->table_element]['label']) && is_array($this->attributes[$object->table_element]['label'])) {
2088 $extralabels = $this->attributes[$object->table_element]['label'];
2089 }
2090
2091 if (is_array($extralabels)) {
2092 // Get extra fields
2093 foreach ($extralabels as $key => $value) {
2094 if (!empty($onlykey) && $onlykey != '@GETPOSTISSET' && $key != $onlykey) {
2095 continue;
2096 }
2097
2098 if (!empty($onlykey) && $onlykey == '@GETPOSTISSET' && !GETPOSTISSET('options_'.$key) && (! in_array($this->attributes[$object->table_element]['type'][$key], array('boolean', 'checkbox', 'chkbxlst')))) {
2099 //when unticking boolean field, it's not set in POST
2100 continue;
2101 }
2102
2103 $key_type = $this->attributes[$object->table_element]['type'][$key];
2104 if ($key_type == 'separate') {
2105 continue;
2106 }
2107
2108 $enabled = 1;
2109 if (isset($this->attributes[$object->table_element]['enabled'][$key])) { // 'enabled' is often a condition on module enabled or not
2110 $enabled = dol_eval($this->attributes[$object->table_element]['enabled'][$key], 1, 1, '2');
2111 }
2112
2113 $visibility = 1;
2114 if (isset($this->attributes[$object->table_element]['list'][$key])) { // 'list' is option for visibility
2115 $visibility = intval(dol_eval($this->attributes[$object->table_element]['list'][$key], 1, 1, '2'));
2116 }
2117
2118 $perms = 1;
2119 if (isset($this->attributes[$object->table_element]['perms'][$key])) {
2120 $perms = dol_eval($this->attributes[$object->table_element]['perms'][$key], 1, 1, '2');
2121 }
2122 if (empty($enabled)
2123 || (
2124 $onlykey === '@GETPOSTISSET'
2125 && in_array($this->attributes[$object->table_element]['type'][$key], array('boolean', 'checkbox', 'chkbxlst'))
2126 && in_array(abs($enabled), array(2, 5))
2127 && ! GETPOSTISSET('options_' . $key) // Update hidden checkboxes and multiselect only if they are provided
2128 )
2129 ) {
2130 continue;
2131 }
2132
2133 $visibility_abs = abs($visibility);
2134 // not modify if extra field is not in update form (0 : never, 2 or -2 : list only, 5 or - 5 : list and view only)
2135 if (empty($visibility_abs) || $visibility_abs == 2 || $visibility_abs == 5) {
2136 continue;
2137 }
2138 if (empty($perms)) {
2139 continue;
2140 }
2141
2142 if ($this->attributes[$object->table_element]['required'][$key]) { // Value is required
2143 // Check if functionally empty without using GETPOST (depending on the type of extrafield, a
2144 // technically non-empty value may be treated as empty functionally).
2145 // value can be alpha, int, array, etc...
2146 if ((!is_array($_POST["options_".$key]) && empty($_POST["options_".$key]) && $this->attributes[$object->table_element]['type'][$key] != 'select' && $_POST["options_".$key] != '0')
2147 || (!is_array($_POST["options_".$key]) && empty($_POST["options_".$key]) && $this->attributes[$object->table_element]['type'][$key] == 'select')
2148 || (!is_array($_POST["options_".$key]) && isset($_POST["options_".$key]) && $this->attributes[$object->table_element]['type'][$key] == 'sellist' && $_POST['options_'.$key] == '0')
2149 || (is_array($_POST["options_".$key]) && empty($_POST["options_".$key]))) {
2150 //print 'ccc'.$value.'-'.$this->attributes[$object->table_element]['required'][$key];
2151
2152 // 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.
2153
2154 $nofillrequired++;
2155 if (!empty($this->attributes[$object->table_element]['langfile'][$key])) {
2156 $langs->load($this->attributes[$object->table_element]['langfile'][$key]);
2157 }
2158 $error_field_required[$key] = $langs->transnoentitiesnoconv($value);
2159 }
2160 }
2161
2162 if (in_array($key_type, array('date'))) {
2163 // Clean parameters
2164 $value_key = dol_mktime(12, 0, 0, GETPOST("options_".$key."month", 'int'), GETPOST("options_".$key."day", 'int'), GETPOST("options_".$key."year", 'int'));
2165 } elseif (in_array($key_type, array('datetime'))) {
2166 // Clean parameters
2167 $value_key = dol_mktime(GETPOST("options_".$key."hour", 'int'), GETPOST("options_".$key."min", 'int'), GETPOST("options_".$key."sec", 'int'), GETPOST("options_".$key."month", 'int'), GETPOST("options_".$key."day", 'int'), GETPOST("options_".$key."year", 'int'), 'tzuserrel');
2168 } elseif (in_array($key_type, array('datetimegmt'))) {
2169 // Clean parameters
2170 $value_key = dol_mktime(GETPOST("options_".$key."hour", 'int'), GETPOST("options_".$key."min", 'int'), GETPOST("options_".$key."sec", 'int'), GETPOST("options_".$key."month", 'int'), GETPOST("options_".$key."day", 'int'), GETPOST("options_".$key."year", 'int'), 'gmt');
2171 } elseif (in_array($key_type, array('checkbox', 'chkbxlst'))) {
2172 $value_arr = GETPOST("options_".$key, 'array'); // check if an array
2173 if (!empty($value_arr)) {
2174 $value_key = implode(',', $value_arr);
2175 } else {
2176 $value_key = '';
2177 }
2178 } elseif (in_array($key_type, array('price', 'double'))) {
2179 $value_arr = GETPOST("options_".$key, 'alpha');
2180 $value_key = price2num($value_arr);
2181 } elseif (in_array($key_type, array('pricecy', 'double'))) {
2182 $value_key = price2num(GETPOST("options_".$key, 'alpha')).':'.GETPOST("options_".$key."currency_id", 'alpha');
2183 } elseif (in_array($key_type, array('html'))) {
2184 $value_key = GETPOST("options_".$key, 'restricthtml');
2185 } elseif (in_array($key_type, array('text'))) {
2186 $label_security_check = 'alphanohtml';
2187 // by default 'alphanohtml' (better security); hidden conf MAIN_SECURITY_ALLOW_UNSECURED_LABELS_WITH_HTML allows basic html
2188 if (!empty($conf->global->MAIN_SECURITY_ALLOW_UNSECURED_REF_LABELS)) {
2189 $label_security_check = 'nohtml';
2190 } else {
2191 $label_security_check = empty($conf->global->MAIN_SECURITY_ALLOW_UNSECURED_LABELS_WITH_HTML) ? 'alphanohtml' : 'restricthtml';
2192 }
2193 $value_key = GETPOST("options_".$key, $label_security_check);
2194 } else {
2195 $value_key = GETPOST("options_".$key);
2196 if (in_array($key_type, array('link')) && $value_key == '-1') {
2197 $value_key = '';
2198 }
2199 }
2200
2201 if (!empty($error_field_required[$key]) && $todefaultifmissing) {
2202 // Value is required but we have a default value and we asked to set empty value to the default value
2203 if (!empty($this->attributes[$object->table_element]['default']) && !is_null($this->attributes[$object->table_element]['default'][$key])) {
2204 $value_key = $this->attributes[$object->table_element]['default'][$key];
2205 unset($error_field_required[$key]);
2206 $nofillrequired--;
2207 }
2208 }
2209
2210 $object->array_options["options_".$key] = $value_key;
2211 }
2212
2213 if ($nofillrequired) {
2214 $langs->load('errors');
2215 $this->error = $langs->trans('ErrorFieldsRequired').' : '.implode(', ', $error_field_required);
2216 setEventMessages($this->error, null, 'errors');
2217 return -1;
2218 } else {
2219 return 1;
2220 }
2221 } else {
2222 return 0;
2223 }
2224 }
2225
2234 public function getOptionalsFromPost($extrafieldsobjectkey, $keyprefix = '', $keysuffix = '')
2235 {
2236 global $_POST;
2237
2238 if (is_string($extrafieldsobjectkey) && !empty($this->attributes[$extrafieldsobjectkey]['label']) && is_array($this->attributes[$extrafieldsobjectkey]['label'])) {
2239 $extralabels = $this->attributes[$extrafieldsobjectkey]['label'];
2240 } else {
2241 $extralabels = $extrafieldsobjectkey;
2242 }
2243
2244 if (is_array($extralabels)) {
2245 $array_options = array();
2246
2247 // Get extra fields
2248 foreach ($extralabels as $key => $value) {
2249 $key_type = '';
2250 if (is_string($extrafieldsobjectkey)) {
2251 $key_type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
2252 }
2253
2254 if (in_array($key_type, array('date'))) {
2255 $dateparamname_start = $keysuffix . 'options_' . $key . $keyprefix . '_start';
2256 $dateparamname_end = $keysuffix . 'options_' . $key . $keyprefix . '_end';
2257 if (GETPOSTISSET($dateparamname_start . 'year') || GETPOSTISSET($dateparamname_end . 'year')) {
2258 $value_key = array();
2259 // values provided as a component year, month, day, etc.
2260 if (GETPOSTISSET($dateparamname_start . 'year')) {
2261 $value_key['start'] = dol_mktime(0, 0, 0, GETPOST($dateparamname_start . 'month', 'int'), GETPOST($dateparamname_start . 'day', 'int'), GETPOST($dateparamname_start . 'year', 'int'));
2262 }
2263 if (GETPOSTISSET($dateparamname_start . 'year')) {
2264 $value_key['end'] = dol_mktime(23, 59, 59, GETPOST($dateparamname_end . 'month', 'int'), GETPOST($dateparamname_end . 'day', 'int'), GETPOST($dateparamname_end . 'year', 'int'));
2265 }
2266 } elseif (GETPOSTISSET($keysuffix."options_".$key.$keyprefix."year")) {
2267 // Clean parameters
2268 $value_key = dol_mktime(12, 0, 0, GETPOST($keysuffix."options_".$key.$keyprefix."month", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."day", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."year", 'int'));
2269 } else {
2270 continue; // Value was not provided, we should not set it.
2271 }
2272 } elseif (in_array($key_type, array('datetime', 'datetimegmt'))) {
2273 $dateparamname_start = $keysuffix . 'options_' . $key . $keyprefix . '_start';
2274 $dateparamname_end = $keysuffix . 'options_' . $key . $keyprefix . '_end';
2275 if (GETPOSTISSET($dateparamname_start . 'year') && GETPOSTISSET($dateparamname_end . 'year')) {
2276 // values provided as a date pair (start date + end date), each date being broken down as year, month, day, etc.
2277 $dateparamname_end_hour = GETPOST($dateparamname_end . 'hour', 'int') !='-1' ? GETPOST($dateparamname_end . 'hour', 'int') : '23';
2278 $dateparamname_end_min = GETPOST($dateparamname_end . 'min', 'int') !='-1' ? GETPOST($dateparamname_end . 'min', 'int') : '59';
2279 $dateparamname_end_sec = GETPOST($dateparamname_end . 'sec', 'int') !='-1' ? GETPOST($dateparamname_end . 'sec', 'int') : '59';
2280 if ($key_type == 'datetimegmt') {
2281 $value_key = array(
2282 'start' => dol_mktime(GETPOST($dateparamname_start . 'hour', 'int'), GETPOST($dateparamname_start . 'min', 'int'), GETPOST($dateparamname_start . 'sec', 'int'), GETPOST($dateparamname_start . 'month', 'int'), GETPOST($dateparamname_start . 'day', 'int'), GETPOST($dateparamname_start . 'year', 'int'), 'gmt'),
2283 'end' => dol_mktime($dateparamname_end_hour, $dateparamname_end_min, $dateparamname_end_sec, GETPOST($dateparamname_end . 'month', 'int'), GETPOST($dateparamname_end . 'day', 'int'), GETPOST($dateparamname_end . 'year', 'int'), 'gmt')
2284 );
2285 } else {
2286 $value_key = array(
2287 'start' => dol_mktime(GETPOST($dateparamname_start . 'hour', 'int'), GETPOST($dateparamname_start . 'min', 'int'), GETPOST($dateparamname_start . 'sec', 'int'), GETPOST($dateparamname_start . 'month', 'int'), GETPOST($dateparamname_start . 'day', 'int'), GETPOST($dateparamname_start . 'year', 'int'), 'tzuserrel'),
2288 'end' => dol_mktime($dateparamname_end_hour, $dateparamname_end_min, $dateparamname_end_sec, GETPOST($dateparamname_end . 'month', 'int'), GETPOST($dateparamname_end . 'day', 'int'), GETPOST($dateparamname_end . 'year', 'int'), 'tzuserrel')
2289 );
2290 }
2291 } elseif (GETPOSTISSET($keysuffix."options_".$key.$keyprefix."year")) {
2292 // Clean parameters
2293 if ($key_type == 'datetimegmt') {
2294 $value_key = dol_mktime(GETPOST($keysuffix."options_".$key.$keyprefix."hour", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."min", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."sec", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."month", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."day", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."year", 'int'), 'gmt');
2295 } else {
2296 $value_key = dol_mktime(GETPOST($keysuffix."options_".$key.$keyprefix."hour", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."min", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."sec", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."month", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."day", 'int'), GETPOST($keysuffix."options_".$key.$keyprefix."year", 'int'), 'tzuserrel');
2297 }
2298 } else {
2299 continue; // Value was not provided, we should not set it.
2300 }
2301 } elseif ($key_type == 'select') {
2302 // to detect if we are in search context
2303 if (GETPOSTISARRAY($keysuffix."options_".$key.$keyprefix)) {
2304 $value_arr = GETPOST($keysuffix."options_".$key.$keyprefix, 'array:aZ09');
2305 // Make sure we get an array even if there's only one selected
2306 $value_arr = (array) $value_arr;
2307 $value_key = implode(',', $value_arr);
2308 } else {
2309 $value_key = GETPOST($keysuffix."options_".$key.$keyprefix);
2310 }
2311 } elseif (in_array($key_type, array('checkbox', 'chkbxlst'))) {
2312 if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix)) {
2313 continue; // Value was not provided, we should not set it.
2314 }
2315 $value_arr = GETPOST($keysuffix."options_".$key.$keyprefix);
2316 // Make sure we get an array even if there's only one checkbox
2317 $value_arr = (array) $value_arr;
2318 $value_key = implode(',', $value_arr);
2319 } elseif (in_array($key_type, array('price', 'double', 'int'))) {
2320 if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix)) {
2321 continue; // Value was not provided, we should not set it.
2322 }
2323 $value_arr = GETPOST($keysuffix."options_".$key.$keyprefix);
2324 if ($keysuffix != 'search_') { // If value is for a search, we must keep complex string like '>100 <=150'
2325 $value_key = price2num($value_arr);
2326 } else {
2327 $value_key = $value_arr;
2328 }
2329 } elseif (in_array($key_type, array('boolean'))) {
2330 if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix)) {
2331 $value_key = '';
2332 } else {
2333 $value_arr = GETPOST($keysuffix."options_".$key.$keyprefix);
2334 $value_key = $value_arr;
2335 }
2336 } elseif (in_array($key_type, array('html'))) {
2337 if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix)) {
2338 continue; // Value was not provided, we should not set it.
2339 }
2340 $value_key = dol_htmlcleanlastbr(GETPOST($keysuffix."options_".$key.$keyprefix, 'restricthtml'));
2341 } else {
2342 if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix)) {
2343 continue; // Value was not provided, we should not set it.
2344 }
2345 $value_key = GETPOST($keysuffix."options_".$key.$keyprefix);
2346 }
2347
2348 $array_options[$keysuffix."options_".$key] = $value_key; // No keyprefix here. keyprefix is used only for read.
2349 }
2350
2351 return $array_options;
2352 }
2353
2354 return 0;
2355 }
2356}
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:464
Class to manage categories.
Class to manage a WYSIWYG editor.
Class to manage standard extra fields.
update($attrname, $label, $type, $length, $elementtype, $unique=0, $required=0, $pos=0, $param='', $alwayseditable=0, $perms='', $list='', $help='', $default='', $computed='', $entity='', $langfile='', $enabled='1', $totalizable=0, $printable=0, $moreparams=array())
Modify type of a personalized attribute.
getOptionalsFromPost($extrafieldsobjectkey, $keyprefix='', $keysuffix='')
return array_options array of data of extrafields value of object sent by a search form
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.
update_label($attrname, $label, $type, $size, $elementtype, $unique=0, $required=0, $pos=0, $param='', $alwayseditable=0, $perms='', $list='0', $help='', $default='', $computed='', $entity='', $langfile='', $enabled='1', $totalizable=0, $printable=0, $moreparams=array())
Modify description of personalized 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 ...
create_label($attrname, $label='', $type='', $pos=0, $size=0, $elementtype='member', $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.
showSeparator($key, $object, $colspan=2, $display_type='card', $mode='')
Return HTML string to print separator extrafield.
showOutputField($key, $value, $moreparam='', $extrafieldsobjectkey='', $outputlangs=null)
Return HTML string to put an output field into a page.
create($attrname, $type='varchar', $length=255, $elementtype='member', $unique=0, $required=0, $default_value='', $param='', $perms='', $list='0', $computed='', $help='', $moreparams=array())
Add a new optional attribute.
delete_label($attrname, $elementtype='member')
Delete description of an optional attribute.
fetch_name_optionals_label($elementtype, $forceload=false)
Load the array of extrafields defintion $this->attributes.
__construct($db)
Constructor.
setOptionalsFromPost($extralabels, &$object, $onlykey='', $todefaultifmissing=0)
Fill array_options property of object by extrafields value (using for data sent by forms)
Class to manage generation of HTML components Only common components must be here.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
dol_print_ip($ip, $mode=0)
Return an IP formated to be shown on screen.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
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.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_print_email($email, $cid=0, $socid=0, $addlink=0, $max=64, $showinvalid=1, $withpicto=0)
Show EMail link formatted for HTML output.
GETPOSTISARRAY($paramname, $method=0)
Return true if the parameter $paramname is submit from a POST OR GET as an array.
dol_print_phone($phone, $countrycode='', $cid=0, $socid=0, $addlink='', $separ="&nbsp;", $withpicto='', $titlealt='', $adddivfloat=0)
Format phone numbers according to country.
dol_now($mode='auto')
Return date for now.
if(!function_exists( 'dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
dol_eval($s, $returnvalue=0, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
dol_htmlcleanlastbr($stringtodecode)
This function remove all ending and br at end.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_print_url($url, $target='_blank', $max=32, $withpicto=0, $morecss='float')
Show Url link.
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.
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...