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