dolibarr  x.y.z
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, '1');
962  $langfile = $this->attributes[$extrafieldsobjectkey]['langfile'][$key];
963  $list = dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1, 1, '1');
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  if ($langfile && $val) {
1125  $options[$okey] = $langs->trans($val);
1126  } else {
1127  $options[$okey] = $val;
1128  }
1129  }
1130  $selected = array();
1131  if (!is_array($value)) {
1132  $selected = explode(',', $value);
1133  }
1134 
1135  $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));
1136  } else {
1137  if (!empty($conf->use_javascript_ajax) && empty($conf->global->MAIN_EXTRAFIELDS_DISABLE_SELECT2)) {
1138  include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
1139  $out .= ajax_combobox($keyprefix.$key.$keysuffix, array(), 0);
1140  }
1141 
1142  $out .= '<select class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam ? $moreparam : '').'>';
1143  $out .= '<option value="0">&nbsp;</option>';
1144  foreach ($param['options'] as $key2 => $val2) {
1145  if ((string) $key2 == '') {
1146  continue;
1147  }
1148  $valarray = explode('|', $val2);
1149  $val2 = $valarray[0];
1150  $parent = '';
1151  if (!empty($valarray[1])) {
1152  $parent = $valarray[1];
1153  }
1154  $out .= '<option value="'.$key2.'"';
1155  $out .= (((string) $value == (string) $key2) ? ' selected' : '');
1156  $out .= (!empty($parent) ? ' parent="'.$parent.'"' : '');
1157  $out .= '>';
1158  if ($langfile && $val2) {
1159  $out .= $langs->trans($val2);
1160  } else {
1161  $out .= $val2;
1162  }
1163  $out .= '</option>';
1164  }
1165  $out .= '</select>';
1166  }
1167  } elseif ($type == 'sellist') {
1168  $out = '';
1169  if (!empty($conf->use_javascript_ajax) && empty($conf->global->MAIN_EXTRAFIELDS_DISABLE_SELECT2)) {
1170  include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
1171  $out .= ajax_combobox($keyprefix.$key.$keysuffix, array(), 0);
1172  }
1173 
1174  $out .= '<select class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam ? $moreparam : '').'>';
1175  if (is_array($param['options'])) {
1176  $param_list = array_keys($param['options']);
1177  $InfoFieldList = explode(":", $param_list[0]);
1178  $parentName = '';
1179  $parentField = '';
1180  // 0 : tableName
1181  // 1 : label field name
1182  // 2 : key fields name (if differ of rowid)
1183  // 3 : key field parent (for dependent lists)
1184  // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value
1185  // 5 : id category type
1186  // 6 : ids categories list separated by comma for category root
1187  $keyList = (empty($InfoFieldList[2]) ? 'rowid' : $InfoFieldList[2].' as rowid');
1188 
1189 
1190  if (count($InfoFieldList) > 4 && !empty($InfoFieldList[4])) {
1191  if (strpos($InfoFieldList[4], 'extra.') !== false) {
1192  $keyList = 'main.'.$InfoFieldList[2].' as rowid';
1193  } else {
1194  $keyList = $InfoFieldList[2].' as rowid';
1195  }
1196  }
1197  if (count($InfoFieldList) > 3 && !empty($InfoFieldList[3])) {
1198  list($parentName, $parentField) = explode('|', $InfoFieldList[3]);
1199  $keyList .= ', '.$parentField;
1200  }
1201 
1202  $filter_categorie = false;
1203  if (count($InfoFieldList) > 5) {
1204  if ($InfoFieldList[0] == 'categorie') {
1205  $filter_categorie = true;
1206  }
1207  }
1208 
1209  if ($filter_categorie === false) {
1210  $fields_label = explode('|', $InfoFieldList[1]);
1211  if (is_array($fields_label)) {
1212  $keyList .= ', ';
1213  $keyList .= implode(', ', $fields_label);
1214  }
1215 
1216  $sqlwhere = '';
1217  $sql = "SELECT ".$keyList;
1218  $sql .= ' FROM '.$this->db->prefix().$InfoFieldList[0];
1219  if (!empty($InfoFieldList[4])) {
1220  // can use current entity filter
1221  if (strpos($InfoFieldList[4], '$ENTITY$') !== false) {
1222  $InfoFieldList[4] = str_replace('$ENTITY$', $conf->entity, $InfoFieldList[4]);
1223  }
1224  // can use SELECT request
1225  if (strpos($InfoFieldList[4], '$SEL$') !== false) {
1226  $InfoFieldList[4] = str_replace('$SEL$', 'SELECT', $InfoFieldList[4]);
1227  }
1228 
1229  // current object id can be use into filter
1230  if (strpos($InfoFieldList[4], '$ID$') !== false && !empty($objectid)) {
1231  $InfoFieldList[4] = str_replace('$ID$', $objectid, $InfoFieldList[4]);
1232  } else {
1233  $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
1234  }
1235  //We have to join on extrafield table
1236  if (strpos($InfoFieldList[4], 'extra') !== false) {
1237  $sql .= ' as main, '.$this->db->prefix().$InfoFieldList[0].'_extrafields as extra';
1238  $sqlwhere .= " WHERE extra.fk_object=main.".$InfoFieldList[2]." AND ".$InfoFieldList[4];
1239  } else {
1240  $sqlwhere .= " WHERE ".$InfoFieldList[4];
1241  }
1242  } else {
1243  $sqlwhere .= ' WHERE 1=1';
1244  }
1245  // Some tables may have field, some other not. For the moment we disable it.
1246  if (in_array($InfoFieldList[0], array('tablewithentity'))) {
1247  $sqlwhere .= ' AND entity = '.((int) $conf->entity);
1248  }
1249  $sql .= $sqlwhere;
1250  //print $sql;
1251 
1252  $sql .= ' ORDER BY '.implode(', ', $fields_label);
1253 
1254  dol_syslog(get_class($this).'::showInputField type=sellist', LOG_DEBUG);
1255  $resql = $this->db->query($sql);
1256  if ($resql) {
1257  $out .= '<option value="0">&nbsp;</option>';
1258  $num = $this->db->num_rows($resql);
1259  $i = 0;
1260  while ($i < $num) {
1261  $labeltoshow = '';
1262  $obj = $this->db->fetch_object($resql);
1263 
1264  // Several field into label (eq table:code|libelle:rowid)
1265  $notrans = false;
1266  $fields_label = explode('|', $InfoFieldList[1]);
1267  if (is_array($fields_label) && count($fields_label) > 1) {
1268  $notrans = true;
1269  foreach ($fields_label as $field_toshow) {
1270  $labeltoshow .= $obj->$field_toshow.' ';
1271  }
1272  } else {
1273  $labeltoshow = $obj->{$InfoFieldList[1]};
1274  }
1275  $labeltoshow = $labeltoshow;
1276 
1277  if ($value == $obj->rowid) {
1278  if (!$notrans) {
1279  foreach ($fields_label as $field_toshow) {
1280  $translabel = $langs->trans($obj->$field_toshow);
1281  $labeltoshow = $translabel.' ';
1282  }
1283  }
1284  $out .= '<option value="'.$obj->rowid.'" selected>'.$labeltoshow.'</option>';
1285  } else {
1286  if (!$notrans) {
1287  $translabel = $langs->trans($obj->{$InfoFieldList[1]});
1288  $labeltoshow = $translabel;
1289  }
1290  if (empty($labeltoshow)) {
1291  $labeltoshow = '(not defined)';
1292  }
1293 
1294  if (!empty($InfoFieldList[3]) && $parentField) {
1295  $parent = $parentName.':'.$obj->{$parentField};
1296  }
1297 
1298  $out .= '<option value="'.$obj->rowid.'"';
1299  $out .= ($value == $obj->rowid ? ' selected' : '');
1300  $out .= (!empty($parent) ? ' parent="'.$parent.'"' : '');
1301  $out .= '>'.$labeltoshow.'</option>';
1302  }
1303 
1304  $i++;
1305  }
1306  $this->db->free($resql);
1307  } else {
1308  print 'Error in request '.$sql.' '.$this->db->lasterror().'. Check setup of extra parameters.<br>';
1309  }
1310  } else {
1311  require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1312  $data = $form->select_all_categories(Categorie::$MAP_ID_TO_CODE[$InfoFieldList[5]], '', 'parent', 64, $InfoFieldList[6], 1, 1);
1313  $out .= '<option value="0">&nbsp;</option>';
1314  if (is_array($data)) {
1315  foreach ($data as $data_key => $data_value) {
1316  $out .= '<option value="'.$data_key.'"';
1317  $out .= ($value == $data_key ? ' selected' : '');
1318  $out .= '>'.$data_value.'</option>';
1319  }
1320  }
1321  }
1322  }
1323  $out .= '</select>';
1324  } elseif ($type == 'checkbox') {
1325  $value_arr = $value;
1326  if (!is_array($value)) {
1327  $value_arr = explode(',', $value);
1328  }
1329  $out = $form->multiselectarray($keyprefix.$key.$keysuffix, (empty($param['options']) ?null:$param['options']), $value_arr, '', 0, '', 0, '100%');
1330  } elseif ($type == 'radio') {
1331  $out = '';
1332  foreach ($param['options'] as $keyopt => $val) {
1333  $out .= '<input class="flat '.$morecss.'" type="radio" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam ? $moreparam : '');
1334  $out .= ' value="'.$keyopt.'"';
1335  $out .= ' id="'.$keyprefix.$key.$keysuffix.'_'.$keyopt.'"';
1336  $out .= ($value == $keyopt ? 'checked' : '');
1337  $out .= '/><label for="'.$keyprefix.$key.$keysuffix.'_'.$keyopt.'">'.$langs->trans($val).'</label><br>';
1338  }
1339  } elseif ($type == 'chkbxlst') {
1340  if (is_array($value)) {
1341  $value_arr = $value;
1342  } else {
1343  $value_arr = explode(',', $value);
1344  }
1345 
1346  if (is_array($param['options'])) {
1347  $param_list = array_keys($param['options']);
1348  $InfoFieldList = explode(":", $param_list[0]);
1349  $parentName = '';
1350  $parentField = '';
1351  // 0 : tableName
1352  // 1 : label field name
1353  // 2 : key fields name (if differ of rowid)
1354  // 3 : key field parent (for dependent lists)
1355  // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value
1356  // 5 : id category type
1357  // 6 : ids categories list separated by comma for category root
1358  $keyList = (empty($InfoFieldList[2]) ? 'rowid' : $InfoFieldList[2].' as rowid');
1359 
1360  if (count($InfoFieldList) > 3 && !empty($InfoFieldList[3])) {
1361  list ($parentName, $parentField) = explode('|', $InfoFieldList[3]);
1362  $keyList .= ', '.$parentField;
1363  }
1364  if (count($InfoFieldList) > 4 && !empty($InfoFieldList[4])) {
1365  if (strpos($InfoFieldList[4], 'extra.') !== false) {
1366  $keyList = 'main.'.$InfoFieldList[2].' as rowid';
1367  } else {
1368  $keyList = $InfoFieldList[2].' as rowid';
1369  }
1370  }
1371 
1372  $filter_categorie = false;
1373  if (count($InfoFieldList) > 5) {
1374  if ($InfoFieldList[0] == 'categorie') {
1375  $filter_categorie = true;
1376  }
1377  }
1378 
1379  if ($filter_categorie === false) {
1380  $fields_label = explode('|', $InfoFieldList[1]);
1381  if (is_array($fields_label)) {
1382  $keyList .= ', ';
1383  $keyList .= implode(', ', $fields_label);
1384  }
1385 
1386  $sqlwhere = '';
1387  $sql = "SELECT ".$keyList;
1388  $sql .= ' FROM '.$this->db->prefix().$InfoFieldList[0];
1389  if (!empty($InfoFieldList[4])) {
1390  // can use current entity filter
1391  if (strpos($InfoFieldList[4], '$ENTITY$') !== false) {
1392  $InfoFieldList[4] = str_replace('$ENTITY$', $conf->entity, $InfoFieldList[4]);
1393  }
1394  // can use SELECT request
1395  if (strpos($InfoFieldList[4], '$SEL$') !== false) {
1396  $InfoFieldList[4] = str_replace('$SEL$', 'SELECT', $InfoFieldList[4]);
1397  }
1398 
1399  // current object id can be use into filter
1400  if (strpos($InfoFieldList[4], '$ID$') !== false && !empty($objectid)) {
1401  $InfoFieldList[4] = str_replace('$ID$', $objectid, $InfoFieldList[4]);
1402  } elseif (preg_match("#^.*list.php$#", $_SERVER["PHP_SELF"])) {
1403  // Pattern for word=$ID$
1404  $word = '\b[a-zA-Z0-9-\.-_]+\b=\$ID\$';
1405 
1406  // Removing space arount =, ( and )
1407  $InfoFieldList[4] = preg_replace('# *(=|\‍(|\‍)) *#', '$1', $InfoFieldList[4]);
1408 
1409  $nbPreg = 1;
1410  // While we have parenthesis
1411  while ($nbPreg != 0) {
1412  // Init des compteurs
1413  $nbPregRepl = $nbPregSel = 0;
1414  // On retire toutes les parenthèses sans = avant
1415  $InfoFieldList[4] = preg_replace('#([^=])(\‍([^)^(]*('.$word.')[^)^(]*\‍))#', '$1 $3 ', $InfoFieldList[4], -1, $nbPregRepl);
1416  // On retire les espaces autour des = et parenthèses
1417  $InfoFieldList[4] = preg_replace('# *(=|\‍(|\‍)) *#', '$1', $InfoFieldList[4]);
1418  // On retire toutes les parenthèses avec = avant
1419  $InfoFieldList[4] = preg_replace('#\b[a-zA-Z0-9-\.-_]+\b=\‍([^)^(]*('.$word.')[^)^(]*\‍)#', '$1 ', $InfoFieldList[4], -1, $nbPregSel);
1420  // On retire les espaces autour des = et parenthèses
1421  $InfoFieldList[4] = preg_replace('# *(=|\‍(|\‍)) *#', '$1', $InfoFieldList[4]);
1422 
1423  // Calcul du compteur général pour la boucle
1424  $nbPreg = $nbPregRepl + $nbPregSel;
1425  }
1426 
1427  // Si l'on a un AND ou un OR, avant ou après
1428  preg_match('#(AND|OR|) *('.$word.') *(AND|OR|)#', $InfoFieldList[4], $matchCondition);
1429  while (!empty($matchCondition[0])) {
1430  // If the two sides differ but are not empty
1431  if (!empty($matchCondition[1]) && !empty($matchCondition[3]) && $matchCondition[1] != $matchCondition[3]) {
1432  // Nobody sain would do that without parentheses
1433  $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
1434  } else {
1435  if (!empty($matchCondition[1])) {
1436  $boolCond = (($matchCondition[1] == "AND") ? ' AND TRUE ' : ' OR FALSE ');
1437  $InfoFieldList[4] = str_replace($matchCondition[0], $boolCond.$matchCondition[3], $InfoFieldList[4]);
1438  } elseif (!empty($matchCondition[3])) {
1439  $boolCond = (($matchCondition[3] == "AND") ? ' TRUE AND ' : ' FALSE OR');
1440  $InfoFieldList[4] = str_replace($matchCondition[0], $boolCond, $InfoFieldList[4]);
1441  } else {
1442  $InfoFieldList[4] = " TRUE ";
1443  }
1444  }
1445 
1446  // Si l'on a un AND ou un OR, avant ou après
1447  preg_match('#(AND|OR|) *('.$word.') *(AND|OR|)#', $InfoFieldList[4], $matchCondition);
1448  }
1449  } else {
1450  $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
1451  }
1452 
1453  // We have to join on extrafield table
1454  if (strpos($InfoFieldList[4], 'extra.') !== false) {
1455  $sql .= ' as main, '.$this->db->prefix().$InfoFieldList[0].'_extrafields as extra';
1456  $sqlwhere .= " WHERE extra.fk_object=main.".$InfoFieldList[2]." AND ".$InfoFieldList[4];
1457  } else {
1458  $sqlwhere .= " WHERE ".$InfoFieldList[4];
1459  }
1460  } else {
1461  $sqlwhere .= ' WHERE 1=1';
1462  }
1463  // Some tables may have field, some other not. For the moment we disable it.
1464  if (in_array($InfoFieldList[0], array('tablewithentity'))) {
1465  $sqlwhere .= " AND entity = ".((int) $conf->entity);
1466  }
1467  // $sql.=preg_replace('/^ AND /','',$sqlwhere);
1468  // print $sql;
1469 
1470  $sql .= $sqlwhere;
1471  dol_syslog(get_class($this).'::showInputField type=chkbxlst', LOG_DEBUG);
1472  $resql = $this->db->query($sql);
1473  if ($resql) {
1474  $num = $this->db->num_rows($resql);
1475  $i = 0;
1476 
1477  $data = array();
1478 
1479  while ($i < $num) {
1480  $labeltoshow = '';
1481  $obj = $this->db->fetch_object($resql);
1482 
1483  $notrans = false;
1484  // Several field into label (eq table:code|libelle:rowid)
1485  $fields_label = explode('|', $InfoFieldList[1]);
1486  if (is_array($fields_label)) {
1487  $notrans = true;
1488  foreach ($fields_label as $field_toshow) {
1489  $labeltoshow .= $obj->$field_toshow.' ';
1490  }
1491  } else {
1492  $labeltoshow = $obj->{$InfoFieldList[1]};
1493  }
1494  $labeltoshow = dol_trunc($labeltoshow, 45);
1495 
1496  if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1497  foreach ($fields_label as $field_toshow) {
1498  $translabel = $langs->trans($obj->$field_toshow);
1499  if ($translabel != $obj->$field_toshow) {
1500  $labeltoshow = dol_trunc($translabel, 18).' ';
1501  } else {
1502  $labeltoshow = dol_trunc($obj->$field_toshow, 18).' ';
1503  }
1504  }
1505 
1506  $data[$obj->rowid] = $labeltoshow;
1507  } else {
1508  if (!$notrans) {
1509  $translabel = $langs->trans($obj->{$InfoFieldList[1]});
1510  if ($translabel != $obj->{$InfoFieldList[1]}) {
1511  $labeltoshow = dol_trunc($translabel, 18);
1512  } else {
1513  $labeltoshow = dol_trunc($obj->{$InfoFieldList[1]}, 18);
1514  }
1515  }
1516  if (empty($labeltoshow)) {
1517  $labeltoshow = '(not defined)';
1518  }
1519 
1520  if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1521  $data[$obj->rowid] = $labeltoshow;
1522  }
1523 
1524  if (!empty($InfoFieldList[3]) && $parentField) {
1525  $parent = $parentName.':'.$obj->{$parentField};
1526  }
1527 
1528  $data[$obj->rowid] = $labeltoshow;
1529  }
1530 
1531  $i++;
1532  }
1533  $this->db->free($resql);
1534 
1535  $out = $form->multiselectarray($keyprefix.$key.$keysuffix, $data, $value_arr, '', 0, '', 0, '100%');
1536  } else {
1537  print 'Error in request '.$sql.' '.$this->db->lasterror().'. Check setup of extra parameters.<br>';
1538  }
1539  } else {
1540  require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1541  $data = $form->select_all_categories(Categorie::$MAP_ID_TO_CODE[$InfoFieldList[5]], '', 'parent', 64, $InfoFieldList[6], 1, 1);
1542  $out = $form->multiselectarray($keyprefix.$key.$keysuffix, $data, $value_arr, '', 0, '', 0, '100%');
1543  }
1544  }
1545  } elseif ($type == 'link') {
1546  $param_list = array_keys($param['options']); // $param_list='ObjectName:classPath'
1547  $showempty = (($required && $default != '') ? 0 : 1);
1548  $out = $form->selectForForms($param_list[0], $keyprefix.$key.$keysuffix, $value, $showempty, '', '', $morecss);
1549  } elseif ($type == 'password') {
1550  // If prefix is 'search_', field is used as a filter, we use a common text field.
1551  $out = '<input style="display:none" type="text" name="fakeusernameremembered">'; // Hidden field to reduce impact of evil Google Chrome autopopulate bug.
1552  $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 : '').'>';
1553  }
1554  if (!empty($hidden)) {
1555  $out = '<input type="hidden" value="'.$value.'" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'"/>';
1556  }
1557  /* Add comments
1558  if ($type == 'date') $out.=' (YYYY-MM-DD)';
1559  elseif ($type == 'datetime') $out.=' (YYYY-MM-DD HH:MM:SS)';
1560  */
1561  /*if (!empty($help) && $keyprefix != 'search_options_') {
1562  $out .= $form->textwithpicto('', $help, 1, 'help', '', 0, 3);
1563  }*/
1564  return $out;
1565  }
1566 
1567 
1577  public function showOutputField($key, $value, $moreparam = '', $extrafieldsobjectkey = '')
1578  {
1579  global $conf, $langs;
1580 
1581  if (empty($extrafieldsobjectkey)) {
1582  dol_syslog(get_class($this).'::showOutputField extrafieldsobjectkey required', LOG_ERR);
1583  return 'BadValueForParamExtraFieldsObjectKey';
1584  }
1585 
1586  $label = $this->attributes[$extrafieldsobjectkey]['label'][$key];
1587  $type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
1588  $size = $this->attributes[$extrafieldsobjectkey]['size'][$key]; // Can be '255', '24,8'...
1589  $default = $this->attributes[$extrafieldsobjectkey]['default'][$key];
1590  $computed = $this->attributes[$extrafieldsobjectkey]['computed'][$key];
1591  $unique = $this->attributes[$extrafieldsobjectkey]['unique'][$key];
1592  $required = $this->attributes[$extrafieldsobjectkey]['required'][$key];
1593  $param = $this->attributes[$extrafieldsobjectkey]['param'][$key];
1594  $perms = dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1, 1, '1');
1595  $langfile = $this->attributes[$extrafieldsobjectkey]['langfile'][$key];
1596  $list = dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1, 1, '1');
1597  $help = $this->attributes[$extrafieldsobjectkey]['help'][$key];
1598  $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)
1599 
1600  if ($hidden) {
1601  return ''; // This is a protection. If field is hidden, we should just not call this method.
1602  }
1603 
1604  //if ($computed) $value = // $value is already calculated into $value before calling this method
1605 
1606  $showsize = 0;
1607  if ($type == 'date') {
1608  $showsize = 10;
1609  if ($value !== '') {
1610  $value = dol_print_date($value, 'day'); // For date without hour, date is always GMT for storage and output
1611  }
1612  } elseif ($type == 'datetime') {
1613  $showsize = 19;
1614  if ($value !== '') {
1615  $value = dol_print_date($value, 'dayhour', 'tzuserrel');
1616  }
1617  } elseif ($type == 'int') {
1618  $showsize = 10;
1619  } elseif ($type == 'double') {
1620  if (!empty($value)) {
1621  //$value=price($value);
1622  $sizeparts = explode(",", $size);
1623  $number_decimals = array_key_exists(1, $sizeparts) ? $sizeparts[1] : 0;
1624  $value = price($value, 0, $langs, 0, 0, $number_decimals, '');
1625  }
1626  } elseif ($type == 'boolean') {
1627  $checked = '';
1628  if (!empty($value)) {
1629  $checked = ' checked ';
1630  }
1631  $value = '<input type="checkbox" '.$checked.' '.($moreparam ? $moreparam : '').' readonly disabled>';
1632  } elseif ($type == 'mail') {
1633  $value = dol_print_email($value, 0, 0, 0, 64, 1, 1);
1634  } elseif ($type == 'ip') {
1635  $value = dol_print_ip($value, 0);
1636  } elseif ($type == 'url') {
1637  $value = dol_print_url($value, '_blank', 32, 1);
1638  } elseif ($type == 'phone') {
1639  $value = dol_print_phone($value, '', 0, 0, '', '&nbsp;', 'phone');
1640  } elseif ($type == 'price') {
1641  //$value = price($value, 0, $langs, 0, 0, -1, $conf->currency);
1642  if ($value || $value == '0') {
1643  $value = price($value, 0, $langs, 0, $conf->global->MAIN_MAX_DECIMALS_TOT, -1).' '.$langs->getCurrencySymbol($conf->currency);
1644  }
1645  } elseif ($type == 'pricecy') {
1646  $currency = $conf->currency;
1647  if (!empty($value)) {
1648  // $value in memory is a php string like '0.01:EUR'
1649  $pricetmp = explode(':', $value);
1650  $currency = !empty($pricetmp[1]) ? $pricetmp[1] : $conf->currency;
1651  $value = $pricetmp[0];
1652  }
1653  if ($value || $value == '0') {
1654  $value = price($value, 0, $langs, 0, $conf->global->MAIN_MAX_DECIMALS_TOT, -1, $currency);
1655  }
1656  } elseif ($type == 'select') {
1657  $valstr = (!empty($param['options'][$value]) ? $param['options'][$value] : '');
1658  if (($pos = strpos($valstr, "|")) !== false) {
1659  $valstr = substr($valstr, 0, $pos);
1660  }
1661  if ($langfile && $valstr) {
1662  $value = $langs->trans($valstr);
1663  } else {
1664  $value = $valstr;
1665  }
1666  } elseif ($type == 'sellist') {
1667  $param_list = array_keys($param['options']);
1668  $InfoFieldList = explode(":", $param_list[0]);
1669 
1670  $selectkey = "rowid";
1671  $keyList = 'rowid';
1672 
1673  if (count($InfoFieldList) >= 3) {
1674  $selectkey = $InfoFieldList[2];
1675  $keyList = $InfoFieldList[2].' as rowid';
1676  }
1677 
1678  $fields_label = explode('|', $InfoFieldList[1]);
1679  if (is_array($fields_label)) {
1680  $keyList .= ', ';
1681  $keyList .= implode(', ', $fields_label);
1682  }
1683 
1684  $filter_categorie = false;
1685  if (count($InfoFieldList) > 5) {
1686  if ($InfoFieldList[0] == 'categorie') {
1687  $filter_categorie = true;
1688  }
1689  }
1690 
1691  $sql = "SELECT ".$keyList;
1692  $sql .= ' FROM '.$this->db->prefix().$InfoFieldList[0];
1693  if (!empty($InfoFieldList[4]) && strpos($InfoFieldList[4], 'extra') !== false) {
1694  $sql .= ' as main';
1695  }
1696  if ($selectkey == 'rowid' && empty($value)) {
1697  $sql .= " WHERE ".$selectkey." = 0";
1698  } elseif ($selectkey == 'rowid') {
1699  $sql .= " WHERE ".$selectkey." = ".((int) $value);
1700  } else {
1701  $sql .= " WHERE ".$selectkey." = '".$this->db->escape($value)."'";
1702  }
1703 
1704  //$sql.= ' AND entity = '.$conf->entity;
1705 
1706  dol_syslog(get_class($this).':showOutputField:$type=sellist', LOG_DEBUG);
1707  $resql = $this->db->query($sql);
1708  if ($resql) {
1709  if ($filter_categorie === false) {
1710  $value = ''; // value was used, so now we reste it to use it to build final output
1711 
1712  $obj = $this->db->fetch_object($resql);
1713 
1714  // Several field into label (eq table:code|libelle:rowid)
1715  $fields_label = explode('|', $InfoFieldList[1]);
1716 
1717  if (is_array($fields_label) && count($fields_label) > 1) {
1718  foreach ($fields_label as $field_toshow) {
1719  $translabel = '';
1720  if (!empty($obj->$field_toshow)) {
1721  $translabel = $langs->trans($obj->$field_toshow);
1722  }
1723  if ($translabel != $obj->$field_toshow) {
1724  $value .= dol_trunc($translabel, 24).' ';
1725  } else {
1726  $value .= $obj->$field_toshow.' ';
1727  }
1728  }
1729  } else {
1730  $translabel = '';
1731  $tmppropname = $InfoFieldList[1];
1732  //$obj->$tmppropname = '';
1733  if (!empty(isset($obj->$tmppropname) ? $obj->$tmppropname : '')) {
1734  $translabel = $langs->trans($obj->$tmppropname);
1735  }
1736  if ($translabel != (isset($obj->$tmppropname) ? $obj->$tmppropname : '')) {
1737  $value = dol_trunc($translabel, 18);
1738  } else {
1739  $value = isset($obj->$tmppropname) ? $obj->$tmppropname : '';
1740  }
1741  }
1742  } else {
1743  $toprint = array();
1744  $obj = $this->db->fetch_object($resql);
1745  if ($obj->rowid) {
1746  require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
1747  $c = new Categorie($this->db);
1748  $result = $c->fetch($obj->rowid);
1749  if ($result > 0) {
1750  $ways = $c->print_all_ways(); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formatted text
1751  foreach ($ways as $way) {
1752  $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories"' . ($c->color ? ' style="background: #' . $c->color . ';"' : ' style="background: #bbb"') . '>' . img_object('', 'category') . ' ' . $way . '</li>';
1753  }
1754  }
1755  }
1756  $value = '<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
1757  }
1758  } else {
1759  dol_syslog(get_class($this).'::showOutputField error '.$this->db->lasterror(), LOG_WARNING);
1760  }
1761  } elseif ($type == 'radio') {
1762  if (!isset($param['options'][$value])) {
1763  $langs->load('errors');
1764  $value = $langs->trans('ErrorNoValueForRadioType');
1765  } else {
1766  $value = $langs->trans($param['options'][$value]);
1767  }
1768  } elseif ($type == 'checkbox') {
1769  $value_arr = explode(',', $value);
1770  $value = '';
1771  $toprint = array();
1772  if (is_array($value_arr)) {
1773  foreach ($value_arr as $keyval => $valueval) {
1774  if (!empty($valueval)) {
1775  $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.$param['options'][$valueval].'</li>';
1776  }
1777  }
1778  }
1779  $value = '<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
1780  } elseif ($type == 'chkbxlst') {
1781  $value_arr = explode(',', $value);
1782 
1783  $param_list = array_keys($param['options']);
1784  $InfoFieldList = explode(":", $param_list[0]);
1785 
1786  $selectkey = "rowid";
1787  $keyList = 'rowid';
1788 
1789  if (count($InfoFieldList) >= 3) {
1790  $selectkey = $InfoFieldList[2];
1791  $keyList = $InfoFieldList[2].' as rowid';
1792  }
1793 
1794  $fields_label = explode('|', $InfoFieldList[1]);
1795  if (is_array($fields_label)) {
1796  $keyList .= ', ';
1797  $keyList .= implode(', ', $fields_label);
1798  }
1799 
1800  $filter_categorie = false;
1801  if (count($InfoFieldList) > 5) {
1802  if ($InfoFieldList[0] == 'categorie') {
1803  $filter_categorie = true;
1804  }
1805  }
1806 
1807  $sql = "SELECT ".$keyList;
1808  $sql .= " FROM ".$this->db->prefix().$InfoFieldList[0];
1809  if (strpos($InfoFieldList[4], 'extra') !== false) {
1810  $sql .= ' as main';
1811  }
1812  // $sql.= " WHERE ".$selectkey."='".$this->db->escape($value)."'";
1813  // $sql.= ' AND entity = '.$conf->entity;
1814 
1815  dol_syslog(get_class($this).':showOutputField:$type=chkbxlst', LOG_DEBUG);
1816  $resql = $this->db->query($sql);
1817  if ($resql) {
1818  if ($filter_categorie === false) {
1819  $value = ''; // value was used, so now we reste it to use it to build final output
1820  $toprint = array();
1821  while ($obj = $this->db->fetch_object($resql)) {
1822  // Several field into label (eq table:code|libelle:rowid)
1823  $fields_label = explode('|', $InfoFieldList[1]);
1824  if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1825  if (is_array($fields_label) && count($fields_label) > 1) {
1826  foreach ($fields_label as $field_toshow) {
1827  $translabel = '';
1828  if (!empty($obj->$field_toshow)) {
1829  $translabel = $langs->trans($obj->$field_toshow);
1830  }
1831  if ($translabel != $field_toshow) {
1832  $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.dol_trunc($translabel, 18).'</li>';
1833  } else {
1834  $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.$obj->$field_toshow.'</li>';
1835  }
1836  }
1837  } else {
1838  $translabel = '';
1839  if (!empty($obj->{$InfoFieldList[1]})) {
1840  $translabel = $langs->trans($obj->{$InfoFieldList[1]});
1841  }
1842  if ($translabel != $obj->{$InfoFieldList[1]}) {
1843  $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.dol_trunc($translabel, 18).'</li>';
1844  } else {
1845  $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.$obj->{$InfoFieldList[1]}.'</li>';
1846  }
1847  }
1848  }
1849  }
1850  } else {
1851  require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1852 
1853  $toprint = array();
1854  while ($obj = $this->db->fetch_object($resql)) {
1855  if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1856  $c = new Categorie($this->db);
1857  $c->fetch($obj->rowid);
1858  $ways = $c->print_all_ways(); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formatted text
1859  foreach ($ways as $way) {
1860  $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories"'.($c->color ? ' style="background: #'.$c->color.';"' : ' style="background: #bbb"').'>'.img_object('', 'category').' '.$way.'</li>';
1861  }
1862  }
1863  }
1864  }
1865  if (!empty($toprint)) $value = '<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
1866  } else {
1867  dol_syslog(get_class($this).'::showOutputField error '.$this->db->lasterror(), LOG_WARNING);
1868  }
1869  } elseif ($type == 'link') {
1870  $out = '';
1871 
1872  // Only if something to display (perf)
1873  if ($value) { // If we have -1 here, pb is into insert, not into ouptut (fix insert instead of changing code here to compensate)
1874  $param_list = array_keys($param['options']); // $param_list='ObjectName:classPath'
1875 
1876  $InfoFieldList = explode(":", $param_list[0]);
1877  $classname = $InfoFieldList[0];
1878  $classpath = $InfoFieldList[1];
1879  if (!empty($classpath)) {
1880  dol_include_once($InfoFieldList[1]);
1881  if ($classname && class_exists($classname)) {
1882  $object = new $classname($this->db);
1883  $object->fetch($value);
1884  $value = $object->getNomUrl(3);
1885  }
1886  } else {
1887  dol_syslog('Error bad setup of extrafield', LOG_WARNING);
1888  return 'Error bad setup of extrafield';
1889  }
1890  }
1891  } elseif ($type == 'text') {
1892  $value = dol_htmlentitiesbr($value);
1893  } elseif ($type == 'html') {
1894  $value = dol_htmlentitiesbr($value);
1895  } elseif ($type == 'password') {
1896  $value = dol_trunc(preg_replace('/./i', '*', $value), 8, 'right', 'UTF-8', 1);
1897  } else {
1898  $showsize = round((float) $size);
1899  if ($showsize > 48) {
1900  $showsize = 48;
1901  }
1902  }
1903 
1904  //print $type.'-'.$size;
1905  $out = $value;
1906 
1907  return $out;
1908  }
1909 
1917  public function getAlignFlag($key, $extrafieldsobjectkey = '')
1918  {
1919  global $conf, $langs;
1920 
1921  $type = 'varchar';
1922  if (!empty($extrafieldsobjectkey)) {
1923  $type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
1924  }
1925 
1926  $cssstring = '';
1927 
1928  if (in_array($type, array('date', 'datetime'))) {
1929  $cssstring = "center";
1930  } elseif (in_array($type, array('int', 'price', 'double'))) {
1931  $cssstring = "right";
1932  } elseif (in_array($type, array('boolean', 'radio', 'checkbox', 'ip'))) {
1933  $cssstring = "center";
1934  }
1935 
1936  if (!empty($this->attributes[$extrafieldsobjectkey]['csslist'][$key])) {
1937  $cssstring .= ($cssstring ? ' ' : '').$this->attributes[$extrafieldsobjectkey]['csslist'][$key];
1938  } else {
1939  if (in_array($type, array('ip'))) {
1940  $cssstring .= ($cssstring ? ' ' : '').'tdoverflowmax150';
1941  }
1942  }
1943 
1944  return $cssstring;
1945  }
1946 
1957  public function showSeparator($key, $object, $colspan = 2, $display_type = 'card', $mode = '')
1958  {
1959  global $conf, $langs;
1960 
1961  $tagtype='tr';
1962  $tagtype_dyn='td';
1963 
1964  if ($display_type=='line') {
1965  $tagtype='div';
1966  $tagtype_dyn='span';
1967  $colspan=0;
1968  }
1969 
1970  $extrafield_param = $this->attributes[$object->table_element]['param'][$key];
1971  $extrafield_param_list = array();
1972  if (!empty($extrafield_param) && is_array($extrafield_param)) {
1973  $extrafield_param_list = array_keys($extrafield_param['options']);
1974  }
1975  $extrafield_collapse_display_value = -1;
1976  $expand_display = false;
1977  if (is_array($extrafield_param_list) && count($extrafield_param_list) > 0) {
1978  $extrafield_collapse_display_value = intval($extrafield_param_list[0]);
1979  $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));
1980  }
1981  if ($mode == 'create') {
1982  $extrafield_collapse_display_value = 0;
1983  }
1984 
1985  $out = '<'.$tagtype.' id="trextrafieldseparator'.$key.(!empty($object->id)?'_'.$object->id:'').'" class="trextrafieldseparator trextrafieldseparator'.$key.(!empty($object->id)?'_'.$object->id:'').'">';
1986  $out .= '<'.$tagtype_dyn.' '.(!empty($colspan)?'colspan="' . $colspan . '"':'').'>';
1987  // Some js code will be injected here to manage the collapsing of extrafields
1988  // Output the picto
1989  $out .= '<span class="cursorpointer '.($extrafield_collapse_display_value == 0 ? 'fas fa-square opacitymedium' : 'far fa-'.(($expand_display ? 'minus' : 'plus').'-square')).'"></span>';
1990  $out .= '&nbsp;';
1991  $out .= '<strong>';
1992  $out .= $langs->trans($this->attributes[$object->table_element]['label'][$key]);
1993  $out .= '</strong>';
1994  $out .= '</'.$tagtype_dyn.'>';
1995  $out .= '</'.$tagtype.'>';
1996 
1997  $collapse_group = $key.(!empty($object->id) ? '_'.$object->id : '');
1998  //$extrafields_collapse_num = $this->attributes[$object->table_element]['pos'][$key].(!empty($object->id)?'_'.$object->id:'');
1999 
2000  if ($extrafield_collapse_display_value == 1 || $extrafield_collapse_display_value == 2) {
2001  // Set the collapse_display status to cookie in priority or if ignorecollapsesetup is 1, if cookie and ignorecollapsesetup not defined, use the setup.
2002  $this->expand_display[$collapse_group] = $expand_display;
2003 
2004  if (!empty($conf->use_javascript_ajax) && $mode != 'create') {
2005  $out .= '<!-- Add js script to manage the collapse/uncollapse of extrafields separators '.$key.' -->'."\n";
2006  $out .= '<script type="text/javascript">'."\n";
2007  $out .= 'jQuery(document).ready(function(){'."\n";
2008  if ($expand_display === false) {
2009  $out .= ' console.log("Inject js for the collapsing of extrafield '.$key.' - hide");'."\n";
2010  $out .= ' jQuery(".trextrafields_collapse'.$collapse_group.'").hide();'."\n";
2011  } else {
2012  $out .= ' console.log("Inject js for collapsing of extrafield '.$key.' - keep visible and set cookie");'."\n";
2013  $out .= ' document.cookie = "DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.'=1; path='.$_SERVER["PHP_SELF"].'"'."\n";
2014  }
2015  $out .= ' jQuery("#trextrafieldseparator'.$key.(!empty($object->id)?'_'.$object->id:'').'").click(function(){'."\n";
2016  $out .= ' console.log("We click on collapse/uncollapse .trextrafields_collapse'.$collapse_group.'");'."\n";
2017  $out .= ' jQuery(".trextrafields_collapse'.$collapse_group.'").toggle(100, function(){'."\n";
2018  $out .= ' if (jQuery(".trextrafields_collapse'.$collapse_group.'").is(":hidden")) {'."\n";
2019  $out .= ' jQuery("#trextrafieldseparator'.$key.(!empty($object->id)?'_'.$object->id:'').' '.$tagtype_dyn.' span").addClass("fa-plus-square").removeClass("fa-minus-square");'."\n";
2020  $out .= ' document.cookie = "DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.'=0; path='.$_SERVER["PHP_SELF"].'"'."\n";
2021  $out .= ' } else {'."\n";
2022  $out .= ' jQuery("#trextrafieldseparator'.$key.(!empty($object->id)?'_'.$object->id:'').' '.$tagtype_dyn.' span").addClass("fa-minus-square").removeClass("fa-plus-square");'."\n";
2023  $out .= ' document.cookie = "DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.'=1; path='.$_SERVER["PHP_SELF"].'"'."\n";
2024  $out .= ' }'."\n";
2025  $out .= ' });'."\n";
2026  $out .= ' });'."\n";
2027  $out .= '});'."\n";
2028  $out .= '</script>'."\n";
2029  }
2030  } else {
2031  $this->expand_display[$collapse_group] = 1;
2032  }
2033 
2034  return $out;
2035  }
2036 
2048  public function setOptionalsFromPost($extralabels, &$object, $onlykey = '', $todefaultifmissing = 0)
2049  {
2050  global $_POST, $langs;
2051 
2052  $nofillrequired = 0; // For error when required field left blank
2053  $error_field_required = array();
2054 
2055  if (isset($this->attributes[$object->table_element]['label']) && is_array($this->attributes[$object->table_element]['label'])) {
2056  $extralabels = $this->attributes[$object->table_element]['label'];
2057  }
2058 
2059  if (is_array($extralabels)) {
2060  // Get extra fields
2061  foreach ($extralabels as $key => $value) {
2062  if (!empty($onlykey) && $onlykey != '@GETPOSTISSET' && $key != $onlykey) {
2063  continue;
2064  }
2065 
2066  if (!empty($onlykey) && $onlykey == '@GETPOSTISSET' && !GETPOSTISSET('options_'.$key) && (! in_array($this->attributes[$object->table_element]['type'][$key], array('boolean', 'chkbxlst')))) {
2067  //when unticking boolean field, it's not set in POST
2068  continue;
2069  }
2070 
2071  $key_type = $this->attributes[$object->table_element]['type'][$key];
2072  if ($key_type == 'separate') {
2073  continue;
2074  }
2075 
2076  $enabled = 1;
2077  if (isset($this->attributes[$object->table_element]['enabled'][$key])) { // 'enabled' is often a condition on module enabled or not
2078  $enabled = dol_eval($this->attributes[$object->table_element]['enabled'][$key], 1, 1, '1');
2079  }
2080 
2081  $visibility = 1;
2082  if (isset($this->attributes[$object->table_element]['list'][$key])) { // 'list' is option for visibility
2083  $visibility = intval(dol_eval($this->attributes[$object->table_element]['list'][$key], 1, 1, '1'));
2084  }
2085 
2086  $perms = 1;
2087  if (isset($this->attributes[$object->table_element]['perms'][$key])) {
2088  $perms = dol_eval($this->attributes[$object->table_element]['perms'][$key], 1, 1, '1');
2089  }
2090  if (empty($enabled)
2091  || (
2092  $onlykey === '@GETPOSTISSET'
2093  && in_array($this->attributes[$object->table_element]['type'][$key], array('boolean', 'chkbxlst'))
2094  && in_array(abs($enabled), array(2, 5))
2095  && ! GETPOSTISSET('options_' . $key) // Update hidden checkboxes and multiselect only if they are provided
2096  )
2097  ) {
2098  continue;
2099  }
2100  if (empty($visibility)) {
2101  continue;
2102  }
2103  if (empty($perms)) {
2104  continue;
2105  }
2106 
2107  if ($this->attributes[$object->table_element]['required'][$key]) { // Value is required
2108  // Check if functionally empty without using GETPOST (depending on the type of extrafield, a
2109  // technically non-empty value may be treated as empty functionally).
2110  // value can be alpha, int, array, etc...
2111  if ((!is_array($_POST["options_".$key]) && empty($_POST["options_".$key]) && $this->attributes[$object->table_element]['type'][$key] != 'select' && $_POST["options_".$key] != '0')
2112  || (!is_array($_POST["options_".$key]) && empty($_POST["options_".$key]) && $this->attributes[$object->table_element]['type'][$key] == 'select')
2113  || (!is_array($_POST["options_".$key]) && isset($_POST["options_".$key]) && $this->attributes[$object->table_element]['type'][$key] == 'sellist' && $_POST['options_'.$key] == '0')
2114  || (is_array($_POST["options_".$key]) && empty($_POST["options_".$key]))) {
2115  //print 'ccc'.$value.'-'.$this->attributes[$object->table_element]['required'][$key];
2116 
2117  // Field is not defined. We mark this as a problem. We may fix it later if there is a default value and $todefaultifmissing is set.
2118  $nofillrequired++;
2119  $error_field_required[$key] = $langs->transnoentitiesnoconv($value);
2120  }
2121  }
2122 
2123  if (in_array($key_type, array('date'))) {
2124  // Clean parameters
2125  $value_key = dol_mktime(12, 0, 0, GETPOST("options_".$key."month", 'int'), GETPOST("options_".$key."day", 'int'), GETPOST("options_".$key."year", 'int'));
2126  } elseif (in_array($key_type, array('datetime'))) {
2127  // Clean parameters
2128  $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');
2129  } elseif (in_array($key_type, array('checkbox', 'chkbxlst'))) {
2130  $value_arr = GETPOST("options_".$key, 'array'); // check if an array
2131  if (!empty($value_arr)) {
2132  $value_key = implode(',', $value_arr);
2133  } else {
2134  $value_key = '';
2135  }
2136  } elseif (in_array($key_type, array('price', 'double'))) {
2137  $value_arr = GETPOST("options_".$key, 'alpha');
2138  $value_key = price2num($value_arr);
2139  } elseif (in_array($key_type, array('pricecy', 'double'))) {
2140  $value_key = price2num(GETPOST("options_".$key, 'alpha')).':'.GETPOST("options_".$key."currency_id", 'alpha');
2141  } elseif (in_array($key_type, array('html'))) {
2142  $value_key = GETPOST("options_".$key, 'restricthtml');
2143  } elseif (in_array($key_type, array('text'))) {
2144  $value_key = GETPOST("options_".$key, 'alphanohtml');
2145  } else {
2146  $value_key = GETPOST("options_".$key);
2147  if (in_array($key_type, array('link')) && $value_key == '-1') {
2148  $value_key = '';
2149  }
2150  }
2151 
2152  if (!empty($error_field_required[$key]) && $todefaultifmissing) {
2153  // Value is required but we have a default value and we asked to set empty value to the default value
2154  if (!empty($this->attributes[$object->table_element]['default']) && !is_null($this->attributes[$object->table_element]['default'][$key])) {
2155  $value_key = $this->attributes[$object->table_element]['default'][$key];
2156  unset($error_field_required[$key]);
2157  $nofillrequired--;
2158  }
2159  }
2160 
2161  $object->array_options["options_".$key] = $value_key;
2162  }
2163 
2164  if ($nofillrequired) {
2165  $langs->load('errors');
2166  $this->error = $langs->trans('ErrorFieldsRequired').' : '.implode(', ', $error_field_required);
2167  setEventMessages($this->error, null, 'errors');
2168  return -1;
2169  } else {
2170  return 1;
2171  }
2172  } else {
2173  return 0;
2174  }
2175  }
2176 
2185  public function getOptionalsFromPost($extrafieldsobjectkey, $keyprefix = '', $keysuffix = '')
2186  {
2187  global $_POST;
2188 
2189  if (is_string($extrafieldsobjectkey) && !empty($this->attributes[$extrafieldsobjectkey]['label']) && is_array($this->attributes[$extrafieldsobjectkey]['label'])) {
2190  $extralabels = $this->attributes[$extrafieldsobjectkey]['label'];
2191  } else {
2192  $extralabels = $extrafieldsobjectkey;
2193  }
2194 
2195  if (is_array($extralabels)) {
2196  $array_options = array();
2197 
2198  // Get extra fields
2199  foreach ($extralabels as $key => $value) {
2200  $key_type = '';
2201  if (is_string($extrafieldsobjectkey)) {
2202  $key_type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
2203  }
2204 
2205  if (in_array($key_type, array('date'))) {
2206  $dateparamname_start = $keysuffix . 'options_' . $key . $keyprefix . '_start';
2207  $dateparamname_end = $keysuffix . 'options_' . $key . $keyprefix . '_end';
2208  if (GETPOSTISSET($dateparamname_start . 'year') && GETPOSTISSET($dateparamname_end . 'year')) {
2209  // values provided as a date pair (start date + end date), each date being broken down as year, month, day, etc.
2210  $value_key = array(
2211  'start' => dol_mktime(0, 0, 0, GETPOST($dateparamname_start . 'month', 'int'), GETPOST($dateparamname_start . 'day', 'int'), GETPOST($dateparamname_start . 'year', 'int')),
2212  'end' => dol_mktime(23, 59, 59, GETPOST($dateparamname_end . 'month', 'int'), GETPOST($dateparamname_end . 'day', 'int'), GETPOST($dateparamname_end . 'year', 'int'))
2213  );
2214  } elseif (GETPOSTISSET($keysuffix."options_".$key.$keyprefix."year")) {
2215  // Clean parameters
2216  $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'));
2217  } else {
2218  continue; // Value was not provided, we should not set it.
2219  }
2220  } elseif (in_array($key_type, array('datetime'))) {
2221  $dateparamname_start = $keysuffix . 'options_' . $key . $keyprefix . '_start';
2222  $dateparamname_end = $keysuffix . 'options_' . $key . $keyprefix . '_end';
2223  if (GETPOSTISSET($dateparamname_start . 'year') && GETPOSTISSET($dateparamname_end . 'year')) {
2224  // values provided as a date pair (start date + end date), each date being broken down as year, month, day, etc.
2225  $dateparamname_end_hour = GETPOST($dateparamname_end . 'hour', 'int') !='-1' ? GETPOST($dateparamname_end . 'hour', 'int') : '23';
2226  $dateparamname_end_min = GETPOST($dateparamname_end . 'min', 'int') !='-1' ? GETPOST($dateparamname_end . 'min', 'int') : '59';
2227  $dateparamname_end_sec = GETPOST($dateparamname_end . 'sec', 'int') !='-1' ? GETPOST($dateparamname_end . 'sec', 'int') : '59';
2228  $value_key = array(
2229  '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'),
2230  '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')
2231  );
2232  } elseif (GETPOSTISSET($keysuffix."options_".$key.$keyprefix."year")) {
2233  // Clean parameters
2234  $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');
2235  } else {
2236  continue; // Value was not provided, we should not set it.
2237  }
2238  } elseif ($key_type == 'select') {
2239  // to detect if we are in search context
2240  if (GETPOSTISARRAY($keysuffix."options_".$key.$keyprefix)) {
2241  $value_arr = GETPOST($keysuffix."options_".$key.$keyprefix, 'array:aZ09');
2242  // Make sure we get an array even if there's only one selected
2243  $value_arr = (array) $value_arr;
2244  $value_key = implode(',', $value_arr);
2245  } else {
2246  $value_key = GETPOST($keysuffix."options_".$key.$keyprefix);
2247  }
2248  } elseif (in_array($key_type, array('checkbox', 'chkbxlst'))) {
2249  if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix)) {
2250  continue; // Value was not provided, we should not set it.
2251  }
2252  $value_arr = GETPOST($keysuffix."options_".$key.$keyprefix);
2253  // Make sure we get an array even if there's only one checkbox
2254  $value_arr = (array) $value_arr;
2255  $value_key = implode(',', $value_arr);
2256  } elseif (in_array($key_type, array('price', 'double', 'int'))) {
2257  if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix)) {
2258  continue; // Value was not provided, we should not set it.
2259  }
2260  $value_arr = GETPOST($keysuffix."options_".$key.$keyprefix);
2261  if ($keysuffix != 'search_') { // If value is for a search, we must keep complex string like '>100 <=150'
2262  $value_key = price2num($value_arr);
2263  } else {
2264  $value_key = $value_arr;
2265  }
2266  } elseif (in_array($key_type, array('boolean'))) {
2267  if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix)) {
2268  $value_key = '';
2269  } else {
2270  $value_arr = GETPOST($keysuffix."options_".$key.$keyprefix);
2271  $value_key = $value_arr;
2272  }
2273  } else {
2274  if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix)) {
2275  continue; // Value was not provided, we should not set it.
2276  }
2277  $value_key = GETPOST($keysuffix."options_".$key.$keyprefix);
2278  }
2279 
2280  $array_options[$keysuffix."options_".$key] = $value_key; // No keyprefix here. keyprefix is used only for read.
2281  }
2282 
2283  return $array_options;
2284  }
2285 
2286  return 0;
2287  }
2288 }
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