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