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