dolibarr  13.0.2
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-2019 Frédéric France <frederic.france@netlogic.fr>
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program. If not, see <https://www.gnu.org/licenses/>.
26  */
27 
39 {
43  public $db;
44 
49  public $attribute_elementtype;
50 
55  public $attribute_type;
56 
61  public $attribute_label;
62 
67  public $attribute_size;
68 
73  public $attribute_choice;
74 
79  public $attribute_computed;
80 
85  public $attribute_default;
86 
91  public $attribute_unique;
92 
97  public $attribute_required;
98 
103  public $attribute_param;
104 
109  public $attribute_pos;
110 
115  public $attribute_alwayseditable;
116 
121  public $attribute_perms;
122 
127  public $attribute_langfile;
128 
133  public $attribute_list;
134 
139  public $attribute_totalizable;
140 
145  public $attribute_entityid;
146 
147 
151  public $attributes;
152 
156  public $error = '';
157 
161  public $errors = array();
162 
166  public $errno;
167 
168 
169  public static $type2label = array(
170  'varchar'=>'String1Line',
171  'text'=>'TextLongNLines',
172  'html'=>'HtmlText',
173  'int'=>'Int',
174  'double'=>'Float',
175  'date'=>'Date',
176  'datetime'=>'DateAndTime',
177  'boolean'=>'Boolean',
178  'price'=>'ExtrafieldPrice',
179  'phone'=>'ExtrafieldPhone',
180  'mail'=>'ExtrafieldMail',
181  'url'=>'ExtrafieldUrl',
182  'password' => 'ExtrafieldPassword',
183  'select' => 'ExtrafieldSelect',
184  'sellist' => 'ExtrafieldSelectList',
185  'radio' => 'ExtrafieldRadio',
186  'checkbox' => 'ExtrafieldCheckBox',
187  'chkbxlst' => 'ExtrafieldCheckBoxFromList',
188  'link' => 'ExtrafieldLink',
189  'separate' => 'ExtrafieldSeparator',
190  );
191 
192 
198  public function __construct($db)
199  {
200  $this->db = $db;
201  $this->error = '';
202  $this->errors = array();
203  $this->attributes = array();
204 
205  // For old usage
206  $this->attribute_elementtype = array();
207  $this->attribute_type = array();
208  $this->attribute_label = array();
209  $this->attribute_size = array();
210  $this->attribute_computed = array();
211  $this->attribute_default = array();
212  $this->attribute_unique = array();
213  $this->attribute_required = array();
214  $this->attribute_perms = array();
215  $this->attribute_langfile = array();
216  $this->attribute_list = array();
217  }
218 
244  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)
245  {
246  if (empty($attrname)) return -1;
247  if (empty($label)) return -1;
248 
249  if ($type == 'separate') { $unique = 0; $required = 0; } // Force unique and not required if this is a separator field to avoid troubles.
250  if ($elementtype == 'thirdparty') $elementtype = 'societe';
251  if ($elementtype == 'contact') $elementtype = 'socpeople';
252 
253  // Create field into database except for separator type which is not stored in database
254  if ($type != 'separate')
255  {
256  $result = $this->create($attrname, $type, $size, $elementtype, $unique, $required, $default_value, $param, $perms, $list, $computed, $help);
257  }
258  $err1 = $this->errno;
259  if ($result > 0 || $err1 == 'DB_ERROR_COLUMN_ALREADY_EXISTS' || $type == 'separate')
260  {
261  // Add declaration of field into table
262  $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);
263  $err2 = $this->errno;
264  if ($result2 > 0 || ($err1 == 'DB_ERROR_COLUMN_ALREADY_EXISTS' && $err2 == 'DB_ERROR_RECORD_ALREADY_EXISTS'))
265  {
266  $this->error = '';
267  $this->errno = 0;
268  return 1;
269  } else return -2;
270  } else {
271  return -1;
272  }
273  }
274 
293  private function create($attrname, $type = 'varchar', $length = 255, $elementtype = 'member', $unique = 0, $required = 0, $default_value = '', $param = '', $perms = '', $list = '0', $computed = '', $help = '')
294  {
295  if ($elementtype == 'thirdparty') $elementtype = 'societe';
296  if ($elementtype == 'contact') $elementtype = 'socpeople';
297 
298  $table = $elementtype.'_extrafields';
299  if ($elementtype == 'categorie') $table = 'categories_extrafields';
300 
301  if (!empty($attrname) && preg_match("/^\w[a-zA-Z0-9_]*$/", $attrname) && !is_numeric($attrname))
302  {
303  if ($type == 'boolean') {
304  $typedb = 'int';
305  $lengthdb = '1';
306  } elseif ($type == 'price') {
307  $typedb = 'double';
308  $lengthdb = '24,8';
309  } elseif ($type == 'phone') {
310  $typedb = 'varchar';
311  $lengthdb = '20';
312  } elseif ($type == 'mail') {
313  $typedb = 'varchar';
314  $lengthdb = '128';
315  } elseif ($type == 'url') {
316  $typedb = 'varchar';
317  $lengthdb = '255';
318  } elseif (($type == 'select') || ($type == 'sellist') || ($type == 'radio') || ($type == 'checkbox') || ($type == 'chkbxlst')) {
319  $typedb = 'varchar';
320  $lengthdb = '255';
321  } elseif ($type == 'link') {
322  $typedb = 'int';
323  $lengthdb = '11';
324  } elseif ($type == 'html') {
325  $typedb = 'text';
326  $lengthdb = $length;
327  } elseif ($type == 'password') {
328  $typedb = 'varchar';
329  $lengthdb = '128';
330  } else {
331  $typedb = $type;
332  $lengthdb = $length;
333  if ($type == 'varchar' && empty($lengthdb)) $lengthdb = '255';
334  }
335  $field_desc = array(
336  'type'=>$typedb,
337  'value'=>$lengthdb,
338  'null'=>($required ? 'NOT NULL' : 'NULL'),
339  'default' => $default_value
340  );
341 
342  $result = $this->db->DDLAddField(MAIN_DB_PREFIX.$table, $attrname, $field_desc);
343  if ($result > 0)
344  {
345  if ($unique)
346  {
347  $sql = "ALTER TABLE ".MAIN_DB_PREFIX.$table." ADD UNIQUE INDEX uk_".$table."_".$attrname." (".$attrname.")";
348  $resql = $this->db->query($sql, 1, 'dml');
349  }
350  return 1;
351  } else {
352  $this->error = $this->db->lasterror();
353  $this->errno = $this->db->lasterrno();
354  return -1;
355  }
356  } else {
357  return 0;
358  }
359  }
360 
361  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
388  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)
389  {
390  // phpcs:enable
391  global $conf, $user;
392 
393  if ($elementtype == 'thirdparty') $elementtype = 'societe';
394  if ($elementtype == 'contact') $elementtype = 'socpeople';
395 
396  // Clean parameters
397  if (empty($pos)) $pos = 0;
398  if (empty($list)) $list = '0';
399  if (empty($required)) $required = 0;
400  if (empty($unique)) $unique = 0;
401  if (empty($printable)) $printable = 0;
402  if (empty($alwayseditable)) $alwayseditable = 0;
403  if (empty($totalizable)) $totalizable = 0;
404 
405  if (!empty($attrname) && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname) && !is_numeric($attrname))
406  {
407  if (is_array($param) && count($param) > 0)
408  {
409  $params = serialize($param);
410  } elseif (strlen($param) > 0)
411  {
412  $params = trim($param);
413  } else {
414  $params = '';
415  }
416 
417  $sql = "INSERT INTO ".MAIN_DB_PREFIX."extrafields(";
418  $sql .= " name,";
419  $sql .= " label,";
420  $sql .= " type,";
421  $sql .= " pos,";
422  $sql .= " size,";
423  $sql .= " entity,";
424  $sql .= " elementtype,";
425  $sql .= " fieldunique,";
426  $sql .= " fieldrequired,";
427  $sql .= " param,";
428  $sql .= " alwayseditable,";
429  $sql .= " perms,";
430  $sql .= " langs,";
431  $sql .= " list,";
432  $sql .= " printable,";
433  $sql .= " fielddefault,";
434  $sql .= " fieldcomputed,";
435  $sql .= " fk_user_author,";
436  $sql .= " fk_user_modif,";
437  $sql .= " datec,";
438  $sql .= " enabled,";
439  $sql .= " help,";
440  $sql .= " totalizable";
441  $sql .= " )";
442  $sql .= " VALUES('".$this->db->escape($attrname)."',";
443  $sql .= " '".$this->db->escape($label)."',";
444  $sql .= " '".$this->db->escape($type)."',";
445  $sql .= " ".$pos.",";
446  $sql .= " '".$this->db->escape($size)."',";
447  $sql .= " ".($entity === '' ? $conf->entity : $entity).",";
448  $sql .= " '".$this->db->escape($elementtype)."',";
449  $sql .= " ".$unique.",";
450  $sql .= " ".$required.",";
451  $sql .= " '".$this->db->escape($params)."',";
452  $sql .= " ".$alwayseditable.",";
453  $sql .= " ".($perms ? "'".$this->db->escape($perms)."'" : "null").",";
454  $sql .= " ".($langfile ? "'".$this->db->escape($langfile)."'" : "null").",";
455  $sql .= " '".$this->db->escape($list)."',";
456  $sql .= " '".$this->db->escape($printable)."',";
457  $sql .= " ".($default ? "'".$this->db->escape($default)."'" : "null").",";
458  $sql .= " ".($computed ? "'".$this->db->escape($computed)."'" : "null").",";
459  $sql .= " ".(is_object($user) ? $user->id : 0).",";
460  $sql .= " ".(is_object($user) ? $user->id : 0).",";
461  $sql .= "'".$this->db->idate(dol_now())."',";
462  $sql .= " ".($enabled ? "'".$this->db->escape($enabled)."'" : "1").",";
463  $sql .= " ".($help ? "'".$this->db->escape($help)."'" : "null").",";
464  $sql .= " ".($totalizable ? 'TRUE' : 'FALSE');
465  $sql .= ')';
466 
467  dol_syslog(get_class($this)."::create_label", LOG_DEBUG);
468  if ($this->db->query($sql))
469  {
470  return 1;
471  } else {
472  $this->error = $this->db->lasterror();
473  $this->errno = $this->db->lasterrno();
474  return -1;
475  }
476  }
477  }
478 
486  public function delete($attrname, $elementtype = 'member')
487  {
488  if ($elementtype == 'thirdparty') $elementtype = 'societe';
489  if ($elementtype == 'contact') $elementtype = 'socpeople';
490 
491  $table = $elementtype.'_extrafields';
492  if ($elementtype == 'categorie') $table = 'categories_extrafields';
493 
494  $error = 0;
495 
496  if (!empty($attrname) && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname))
497  {
498  $result = $this->delete_label($attrname, $elementtype);
499  if ($result < 0)
500  {
501  $this->error = $this->db->lasterror();
502  $this->errors[] = $this->db->lasterror();
503  $error++;
504  }
505 
506  if (!$error)
507  {
508  $sql = "SELECT COUNT(rowid) as nb";
509  $sql .= " FROM ".MAIN_DB_PREFIX."extrafields";
510  $sql .= " WHERE elementtype = '".$this->db->escape($elementtype)."'";
511  $sql .= " AND name = '".$this->db->escape($attrname)."'";
512  //$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
513  $resql = $this->db->query($sql);
514  if ($resql)
515  {
516  $obj = $this->db->fetch_object($resql);
517  if ($obj->nb <= 0)
518  {
519  $result = $this->db->DDLDropField(MAIN_DB_PREFIX.$table, $attrname); // This also drop the unique key
520  if ($result < 0)
521  {
522  $this->error = $this->db->lasterror();
523  $this->errors[] = $this->db->lasterror();
524  $error++;
525  }
526  }
527  }
528  }
529 
530  return $result;
531  } else {
532  return 0;
533  }
534  }
535 
536  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
544  private function delete_label($attrname, $elementtype = 'member')
545  {
546  // phpcs:enable
547  global $conf;
548 
549  if ($elementtype == 'thirdparty') $elementtype = 'societe';
550  if ($elementtype == 'contact') $elementtype = 'socpeople';
551 
552  if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname))
553  {
554  $sql = "DELETE FROM ".MAIN_DB_PREFIX."extrafields";
555  $sql .= " WHERE name = '".$this->db->escape($attrname)."'";
556  $sql .= " AND entity IN (0,".$conf->entity.')';
557  $sql .= " AND elementtype = '".$this->db->escape($elementtype)."'";
558 
559  dol_syslog(get_class($this)."::delete_label", LOG_DEBUG);
560  $resql = $this->db->query($sql);
561  if ($resql)
562  {
563  return 1;
564  } else {
565  dol_print_error($this->db);
566  return -1;
567  }
568  } else {
569  return 0;
570  }
571  }
572 
599  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)
600  {
601  if ($elementtype == 'thirdparty') $elementtype = 'societe';
602  if ($elementtype == 'contact') $elementtype = 'socpeople';
603 
604  $table = $elementtype.'_extrafields';
605  if ($elementtype == 'categorie') $table = 'categories_extrafields';
606 
607  if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname))
608  {
609  if ($type == 'boolean') {
610  $typedb = 'int';
611  $lengthdb = '1';
612  } elseif ($type == 'price') {
613  $typedb = 'double';
614  $lengthdb = '24,8';
615  } elseif ($type == 'phone') {
616  $typedb = 'varchar';
617  $lengthdb = '20';
618  } elseif ($type == 'mail') {
619  $typedb = 'varchar';
620  $lengthdb = '128';
621  } elseif ($type == 'url') {
622  $typedb = 'varchar';
623  $lengthdb = '255';
624  } elseif (($type == 'select') || ($type == 'sellist') || ($type == 'radio') || ($type == 'checkbox') || ($type == 'chkbxlst')) {
625  $typedb = 'varchar';
626  $lengthdb = '255';
627  } elseif ($type == 'html') {
628  $typedb = 'text';
629  } elseif ($type == 'link') {
630  $typedb = 'int';
631  $lengthdb = '11';
632  } elseif ($type == 'password') {
633  $typedb = 'varchar';
634  $lengthdb = '50';
635  } else {
636  $typedb = $type;
637  $lengthdb = $length;
638  }
639  $field_desc = array('type'=>$typedb, 'value'=>$lengthdb, 'null'=>($required ? 'NOT NULL' : 'NULL'), 'default'=>$default);
640 
641  if ($type != 'separate') // No table update when separate type
642  {
643  $result = $this->db->DDLUpdateField(MAIN_DB_PREFIX.$table, $attrname, $field_desc);
644  }
645  if ($result > 0 || $type == 'separate')
646  {
647  if ($label)
648  {
649  $result = $this->update_label($attrname, $label, $type, $length, $elementtype, $unique, $required, $pos, $param, $alwayseditable, $perms, $list, $help, $default, $computed, $entity, $langfile, $enabled, $totalizable, $printable);
650  }
651  if ($result > 0)
652  {
653  $sql = '';
654  if ($unique)
655  {
656  $sql = "ALTER TABLE ".MAIN_DB_PREFIX.$table." ADD UNIQUE INDEX uk_".$table."_".$attrname." (".$attrname.")";
657  } else {
658  $sql = "ALTER TABLE ".MAIN_DB_PREFIX.$table." DROP INDEX uk_".$table."_".$attrname;
659  }
660  dol_syslog(get_class($this).'::update', LOG_DEBUG);
661  $resql = $this->db->query($sql, 1, 'dml');
662  return 1;
663  } else {
664  $this->error = $this->db->lasterror();
665  return -1;
666  }
667  } else {
668  $this->error = $this->db->lasterror();
669  return -1;
670  }
671  } else {
672  return 0;
673  }
674  }
675 
676  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
703  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)
704  {
705  // phpcs:enable
706  global $conf, $user;
707  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);
708 
709  // Clean parameters
710  if ($elementtype == 'thirdparty') $elementtype = 'societe';
711  if ($elementtype == 'contact') $elementtype = 'socpeople';
712 
713  if (empty($pos)) $pos = 0;
714  if (empty($list)) $list = '0';
715  if (empty($totalizable)) {
716  $totalizable = 0;
717  }
718  if (empty($required)) $required = 0;
719  if (empty($unique)) $unique = 0;
720  if (empty($alwayseditable)) $alwayseditable = 0;
721 
722  if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/", $attrname))
723  {
724  $this->db->begin();
725 
726  if (is_array($param) && count($param) > 0)
727  {
728  $params = serialize($param);
729  } elseif (strlen($param) > 0)
730  {
731  $params = trim($param);
732  } else {
733  $params = '';
734  }
735 
736  if ($entity === '' || $entity != '0')
737  {
738  // We dont want on all entities, we delete all and current
739  $sql_del = "DELETE FROM ".MAIN_DB_PREFIX."extrafields";
740  $sql_del .= " WHERE name = '".$this->db->escape($attrname)."'";
741  $sql_del .= " AND entity IN (0, ".($entity === '' ? $conf->entity : $entity).")";
742  $sql_del .= " AND elementtype = '".$this->db->escape($elementtype)."'";
743  } else {
744  // We want on all entities ($entities = '0'), we delete on all only (we keep setup specific to each entity)
745  $sql_del = "DELETE FROM ".MAIN_DB_PREFIX."extrafields";
746  $sql_del .= " WHERE name = '".$this->db->escape($attrname)."'";
747  $sql_del .= " AND entity = 0";
748  $sql_del .= " AND elementtype = '".$this->db->escape($elementtype)."'";
749  }
750  $resql1 = $this->db->query($sql_del);
751 
752  $sql = "INSERT INTO ".MAIN_DB_PREFIX."extrafields(";
753  $sql .= " name,"; // This is code
754  $sql .= " entity,";
755  $sql .= " label,";
756  $sql .= " type,";
757  $sql .= " size,";
758  $sql .= " elementtype,";
759  $sql .= " fieldunique,";
760  $sql .= " fieldrequired,";
761  $sql .= " perms,";
762  $sql .= " langs,";
763  $sql .= " pos,";
764  $sql .= " alwayseditable,";
765  $sql .= " param,";
766  $sql .= " list,";
767  $sql .= " printable,";
768  $sql .= " totalizable,";
769  $sql .= " fielddefault,";
770  $sql .= " fieldcomputed,";
771  $sql .= " fk_user_author,";
772  $sql .= " fk_user_modif,";
773  $sql .= " datec,";
774  $sql .= " enabled,";
775  $sql .= " help";
776  $sql .= ") VALUES (";
777  $sql .= "'".$this->db->escape($attrname)."',";
778  $sql .= " ".($entity === '' ? $conf->entity : $entity).",";
779  $sql .= " '".$this->db->escape($label)."',";
780  $sql .= " '".$this->db->escape($type)."',";
781  $sql .= " '".$this->db->escape($size)."',";
782  $sql .= " '".$this->db->escape($elementtype)."',";
783  $sql .= " ".$unique.",";
784  $sql .= " ".$required.",";
785  $sql .= " ".($perms ? "'".$this->db->escape($perms)."'" : "null").",";
786  $sql .= " ".($langfile ? "'".$this->db->escape($langfile)."'" : "null").",";
787  $sql .= " ".$pos.",";
788  $sql .= " '".$this->db->escape($alwayseditable)."',";
789  $sql .= " '".$this->db->escape($params)."',";
790  $sql .= " '".$this->db->escape($list)."', ";
791  $sql .= " '".$this->db->escape($printable)."', ";
792  $sql .= " ".($totalizable ? 'TRUE' : 'FALSE').",";
793  $sql .= " ".(($default != '') ? "'".$this->db->escape($default)."'" : "null").",";
794  $sql .= " ".($computed ? "'".$this->db->escape($computed)."'" : "null").",";
795  $sql .= " ".$user->id.",";
796  $sql .= " ".$user->id.",";
797  $sql .= "'".$this->db->idate(dol_now())."',";
798  $sql .= "'".$this->db->escape($enabled)."',";
799  $sql .= " ".($help ? "'".$this->db->escape($help)."'" : "null");
800  $sql .= ")";
801 
802  $resql2 = $this->db->query($sql);
803 
804  if ($resql1 && $resql2)
805  {
806  $this->db->commit();
807  return 1;
808  } else {
809  $this->db->rollback();
810  dol_print_error($this->db);
811  return -1;
812  }
813  } else {
814  return 0;
815  }
816  }
817 
818 
819  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
827  public function fetch_name_optionals_label($elementtype, $forceload = false)
828  {
829  // phpcs:enable
830  global $conf;
831 
832  if (empty($elementtype)) return array();
833 
834  if ($elementtype == 'thirdparty') $elementtype = 'societe';
835  if ($elementtype == 'contact') $elementtype = 'socpeople';
836  if ($elementtype == 'order_supplier') $elementtype = 'commande_fournisseur';
837  if ($elementtype == 'stock_mouvement') $elementtype = 'movement';
838 
839  $array_name_label = array();
840 
841  // 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
842  $sql = "SELECT rowid, name, label, type, size, elementtype, fieldunique, fieldrequired, param, pos, alwayseditable, perms, langs, list, printable, totalizable, fielddefault, fieldcomputed, entity, enabled, help";
843  $sql .= " FROM ".MAIN_DB_PREFIX."extrafields";
844  //$sql.= " WHERE entity IN (0,".$conf->entity.")"; // Filter is done later
845  if ($elementtype) $sql .= " WHERE elementtype = '".$this->db->escape($elementtype)."'"; // Filed with object->table_element
846  $sql .= " ORDER BY pos";
847 
848  $resql = $this->db->query($sql);
849  if ($resql)
850  {
851  if ($this->db->num_rows($resql))
852  {
853  while ($tab = $this->db->fetch_object($resql))
854  {
855  if ($tab->entity != 0 && $tab->entity != $conf->entity)
856  {
857  // 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
858  if ($tab->fieldrequired && is_null($tab->fielddefault))
859  {
860  $this->attributes[$tab->elementtype]['mandatoryfieldsofotherentities'][$tab->name] = $tab->type;
861  }
862  continue;
863  }
864 
865  // We can add this attribute to object. TODO Remove this and return $this->attributes[$elementtype]['label']
866  if ($tab->type != 'separate')
867  {
868  $array_name_label[$tab->name] = $tab->label;
869  }
870 
871  // Old usage
872  $this->attribute_type[$tab->name] = $tab->type;
873  $this->attribute_label[$tab->name] = $tab->label;
874  $this->attribute_size[$tab->name] = $tab->size;
875  $this->attribute_elementtype[$tab->name] = $tab->elementtype;
876  $this->attribute_default[$tab->name] = $tab->fielddefault;
877  $this->attribute_computed[$tab->name] = $tab->fieldcomputed;
878  $this->attribute_unique[$tab->name] = $tab->fieldunique;
879  $this->attribute_required[$tab->name] = $tab->fieldrequired;
880  $this->attribute_param[$tab->name] = ($tab->param ? unserialize($tab->param) : '');
881  $this->attribute_pos[$tab->name] = $tab->pos;
882  $this->attribute_alwayseditable[$tab->name] = $tab->alwayseditable;
883  $this->attribute_perms[$tab->name] = (strlen($tab->perms) == 0 ? 1 : $tab->perms);
884  $this->attribute_langfile[$tab->name] = $tab->langs;
885  $this->attribute_list[$tab->name] = $tab->list;
886  $this->attribute_totalizable[$tab->name] = $tab->totalizable;
887  $this->attribute_entityid[$tab->name] = $tab->entity;
888 
889  // New usage
890  $this->attributes[$tab->elementtype]['type'][$tab->name] = $tab->type;
891  $this->attributes[$tab->elementtype]['label'][$tab->name] = $tab->label;
892  $this->attributes[$tab->elementtype]['size'][$tab->name] = $tab->size;
893  $this->attributes[$tab->elementtype]['elementtype'][$tab->name] = $tab->elementtype;
894  $this->attributes[$tab->elementtype]['default'][$tab->name] = $tab->fielddefault;
895  $this->attributes[$tab->elementtype]['computed'][$tab->name] = $tab->fieldcomputed;
896  $this->attributes[$tab->elementtype]['unique'][$tab->name] = $tab->fieldunique;
897  $this->attributes[$tab->elementtype]['required'][$tab->name] = $tab->fieldrequired;
898  $this->attributes[$tab->elementtype]['param'][$tab->name] = ($tab->param ? unserialize($tab->param) : '');
899  $this->attributes[$tab->elementtype]['pos'][$tab->name] = $tab->pos;
900  $this->attributes[$tab->elementtype]['alwayseditable'][$tab->name] = $tab->alwayseditable;
901  $this->attributes[$tab->elementtype]['perms'][$tab->name] = (strlen($tab->perms) == 0 ? 1 : $tab->perms);
902  $this->attributes[$tab->elementtype]['langfile'][$tab->name] = $tab->langs;
903  $this->attributes[$tab->elementtype]['list'][$tab->name] = $tab->list;
904  $this->attributes[$tab->elementtype]['printable'][$tab->name] = $tab->printable;
905  $this->attributes[$tab->elementtype]['totalizable'][$tab->name] = ($tab->totalizable ? 1 : 0);
906  $this->attributes[$tab->elementtype]['entityid'][$tab->name] = $tab->entity;
907  $this->attributes[$tab->elementtype]['enabled'][$tab->name] = $tab->enabled;
908  $this->attributes[$tab->elementtype]['help'][$tab->name] = $tab->help;
909 
910  $this->attributes[$tab->elementtype]['loaded'] = 1;
911  }
912  }
913  if ($elementtype) $this->attributes[$elementtype]['loaded'] = 1; // If nothing found, we also save tag 'loaded'
914  } else {
915  $this->error = $this->db->lasterror();
916  dol_syslog(get_class($this)."::fetch_name_optionals_label ".$this->error, LOG_ERR);
917  }
918 
919  return $array_name_label;
920  }
921 
922 
938  public function showInputField($key, $value, $moreparam = '', $keysuffix = '', $keyprefix = '', $morecss = '', $objectid = 0, $extrafieldsobjectkey = '', $mode = 0)
939  {
940  global $conf, $langs, $form;
941 
942  if (!is_object($form))
943  {
944  require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
945  $form = new Form($this->db);
946  }
947 
948  $out = '';
949 
950  if (!preg_match('/options_$/', $keyprefix)) // Because we work on extrafields, we add 'options_' to prefix if not already added
951  {
952  $keyprefix = $keyprefix.'options_';
953  }
954 
955  if (!empty($extrafieldsobjectkey))
956  {
957  $label = $this->attributes[$extrafieldsobjectkey]['label'][$key];
958  $type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
959  $size = $this->attributes[$extrafieldsobjectkey]['size'][$key];
960  $default = $this->attributes[$extrafieldsobjectkey]['default'][$key];
961  $computed = $this->attributes[$extrafieldsobjectkey]['computed'][$key];
962  $unique = $this->attributes[$extrafieldsobjectkey]['unique'][$key];
963  $required = $this->attributes[$extrafieldsobjectkey]['required'][$key];
964  $param = $this->attributes[$extrafieldsobjectkey]['param'][$key];
965  $perms = dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1);
966  $langfile = $this->attributes[$extrafieldsobjectkey]['langfile'][$key];
967  $list = dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1);
968  $totalizable = $this->attributes[$extrafieldsobjectkey]['totalizable'][$key];
969  $help = $this->attributes[$extrafieldsobjectkey]['help'][$key];
970  $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)
971  } else // Old usage
972  {
973  $label = $this->attribute_label[$key];
974  $type = $this->attribute_type[$key];
975  $size = $this->attribute_size[$key];
976  $elementtype = $this->attribute_elementtype[$key]; // Seems not used
977  $default = $this->attribute_default[$key];
978  $computed = $this->attribute_computed[$key];
979  $unique = $this->attribute_unique[$key];
980  $required = $this->attribute_required[$key];
981  $param = $this->attribute_param[$key];
982  $langfile = $this->attribute_langfile[$key];
983  $list = $this->attribute_list[$key];
984  $totalizable = $this->attribute_totalizable[$key];
985  $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)
986  }
987 
988  if ($computed)
989  {
990  if (!preg_match('/^search_/', $keyprefix)) return '<span class="opacitymedium">'.$langs->trans("AutomaticallyCalculated").'</span>';
991  else return '';
992  }
993 
994  if (empty($morecss)) {
995  if ($type == 'date') {
996  $morecss = 'minwidth100imp';
997  } elseif ($type == 'datetime' || $type == 'link') {
998  $morecss = 'minwidth200imp';
999  } elseif (in_array($type, array('int', 'integer', 'double', 'price'))) {
1000  $morecss = 'maxwidth75';
1001  } elseif ($type == 'password') {
1002  $morecss = 'maxwidth100';
1003  } elseif ($type == 'url') {
1004  $morecss = 'minwidth400';
1005  } elseif ($type == 'boolean') {
1006  $morecss = '';
1007  } else {
1008  if (empty($size) || round($size) < 12) {
1009  $morecss = 'minwidth100';
1010  } elseif (round($size) <= 48) {
1011  $morecss = 'minwidth200';
1012  } else {
1013  $morecss = 'minwidth400';
1014  }
1015  }
1016  }
1017 
1018  if (in_array($type, array('date'))) {
1019  $tmp = explode(',', $size);
1020  $newsize = $tmp[0];
1021  $showtime = 0;
1022 
1023  // Do not show current date when field not required (see selectDate() method)
1024  if (!$required && $value == '') $value = '-1';
1025 
1026  // TODO Must also support $moreparam
1027  $out = $form->selectDate($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 0, 1);
1028  } elseif (in_array($type, array('datetime'))) {
1029  $tmp = explode(',', $size);
1030  $newsize = $tmp[0];
1031  $showtime = 1;
1032 
1033  // Do not show current date when field not required (see selectDate() method)
1034  if (!$required && $value == '') $value = '-1';
1035 
1036  // TODO Must also support $moreparam
1037  $out = $form->selectDate($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 0, 1, '', '', '', 1, '', '', 'tzuserrel');
1038  } elseif (in_array($type, array('int', 'integer')))
1039  {
1040  $tmp = explode(',', $size);
1041  $newsize = $tmp[0];
1042  $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 : '').'>';
1043  } elseif (preg_match('/varchar/', $type))
1044  {
1045  $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 : '').'>';
1046  } elseif (in_array($type, array('mail', 'phone', 'url')))
1047  {
1048  $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam ? $moreparam : '').'>';
1049  } elseif ($type == 'text')
1050  {
1051  if (!preg_match('/search_/', $keyprefix)) // If keyprefix is search_ or search_options_, we must just use a simple text field
1052  {
1053  require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1054  $doleditor = new DolEditor($keyprefix.$key.$keysuffix, $value, '', 200, 'dolibarr_notes', 'In', false, false, false, ROWS_5, '90%');
1055  $out = $doleditor->Create(1);
1056  } else {
1057  $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam ? $moreparam : '').'>';
1058  }
1059  } elseif ($type == 'html')
1060  {
1061  if (!preg_match('/search_/', $keyprefix)) // If keyprefix is search_ or search_options_, we must just use a simple text field
1062  {
1063  require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1064  $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%');
1065  $out = $doleditor->Create(1);
1066  } else {
1067  $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam ? $moreparam : '').'>';
1068  }
1069  } elseif ($type == 'boolean')
1070  {
1071  if (empty($mode))
1072  {
1073  $checked = '';
1074  if (!empty($value)) {
1075  $checked = ' checked value="1" ';
1076  } else {
1077  $checked = ' value="1" ';
1078  }
1079  $out = '<input type="checkbox" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.$checked.' '.($moreparam ? $moreparam : '').'>';
1080  } else {
1081  $out .= $form->selectyesno($keyprefix.$key.$keysuffix, $value, 1, false, 1);
1082  }
1083  } elseif ($type == 'price')
1084  {
1085  if (!empty($value)) { // $value in memory is a php numeric, we format it into user number format.
1086  $value = price($value);
1087  }
1088  $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam ? $moreparam : '').'> '.$langs->getCurrencySymbol($conf->currency);
1089  } elseif ($type == 'double')
1090  {
1091  if (!empty($value)) { // $value in memory is a php numeric, we format it into user number format.
1092  $value = price($value);
1093  }
1094  $out = '<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam ? $moreparam : '').'> ';
1095  } elseif ($type == 'select')
1096  {
1097  $out = '';
1098  if (!empty($conf->use_javascript_ajax) && !empty($conf->global->MAIN_EXTRAFIELDS_USE_SELECT2))
1099  {
1100  include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
1101  $out .= ajax_combobox($keyprefix.$key.$keysuffix, array(), 0);
1102  }
1103 
1104  $out .= '<select class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam ? $moreparam : '').'>';
1105  $out .= '<option value="0">&nbsp;</option>';
1106  foreach ($param['options'] as $key => $val)
1107  {
1108  if ((string) $key == '') continue;
1109  list($val, $parent) = explode('|', $val);
1110  $out .= '<option value="'.$key.'"';
1111  $out .= (((string) $value == (string) $key) ? ' selected' : '');
1112  $out .= (!empty($parent) ? ' parent="'.$parent.'"' : '');
1113  $out .= '>';
1114  if ($langfile && $val) $out .= $langs->trans($val);
1115  else $out .= $val;
1116  $out .= '</option>';
1117  }
1118  $out .= '</select>';
1119  } elseif ($type == 'sellist')
1120  {
1121  $out = '';
1122  if (!empty($conf->use_javascript_ajax) && !empty($conf->global->MAIN_EXTRAFIELDS_USE_SELECT2))
1123  {
1124  include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
1125  $out .= ajax_combobox($keyprefix.$key.$keysuffix, array(), 0);
1126  }
1127 
1128  $out .= '<select class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam ? $moreparam : '').'>';
1129  if (is_array($param['options']))
1130  {
1131  $param_list = array_keys($param['options']);
1132  $InfoFieldList = explode(":", $param_list[0]);
1133  $parentName = '';
1134  $parentField = '';
1135  // 0 : tableName
1136  // 1 : label field name
1137  // 2 : key fields name (if differ of rowid)
1138  // 3 : key field parent (for dependent lists)
1139  // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value
1140  // 5 : id category type
1141  // 6 : ids categories list separated by comma for category root
1142  $keyList = (empty($InfoFieldList[2]) ? 'rowid' : $InfoFieldList[2].' as rowid');
1143 
1144 
1145  if (count($InfoFieldList) > 4 && !empty($InfoFieldList[4]))
1146  {
1147  if (strpos($InfoFieldList[4], 'extra.') !== false)
1148  {
1149  $keyList = 'main.'.$InfoFieldList[2].' as rowid';
1150  } else {
1151  $keyList = $InfoFieldList[2].' as rowid';
1152  }
1153  }
1154  if (count($InfoFieldList) > 3 && !empty($InfoFieldList[3]))
1155  {
1156  list($parentName, $parentField) = explode('|', $InfoFieldList[3]);
1157  $keyList .= ', '.$parentField;
1158  }
1159 
1160  $filter_categorie = false;
1161  if (count($InfoFieldList) > 5) {
1162  if ($InfoFieldList[0] == 'categorie') {
1163  $filter_categorie = true;
1164  }
1165  }
1166 
1167  if ($filter_categorie === false) {
1168  $fields_label = explode('|', $InfoFieldList[1]);
1169  if (is_array($fields_label)) {
1170  $keyList .= ', ';
1171  $keyList .= implode(', ', $fields_label);
1172  }
1173 
1174  $sqlwhere = '';
1175  $sql = 'SELECT '.$keyList;
1176  $sql .= ' FROM '.MAIN_DB_PREFIX.$InfoFieldList[0];
1177  if (!empty($InfoFieldList[4])) {
1178  // can use curent entity filter
1179  if (strpos($InfoFieldList[4], '$ENTITY$') !== false) {
1180  $InfoFieldList[4] = str_replace('$ENTITY$', $conf->entity, $InfoFieldList[4]);
1181  }
1182  // can use SELECT request
1183  if (strpos($InfoFieldList[4], '$SEL$') !== false) {
1184  $InfoFieldList[4] = str_replace('$SEL$', 'SELECT', $InfoFieldList[4]);
1185  }
1186 
1187  // current object id can be use into filter
1188  if (strpos($InfoFieldList[4], '$ID$') !== false && !empty($objectid)) {
1189  $InfoFieldList[4] = str_replace('$ID$', $objectid, $InfoFieldList[4]);
1190  } else {
1191  $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
1192  }
1193  //We have to join on extrafield table
1194  if (strpos($InfoFieldList[4], 'extra') !== false) {
1195  $sql .= ' as main, '.MAIN_DB_PREFIX.$InfoFieldList[0].'_extrafields as extra';
1196  $sqlwhere .= ' WHERE extra.fk_object=main.'.$InfoFieldList[2].' AND '.$InfoFieldList[4];
1197  } else {
1198  $sqlwhere .= ' WHERE '.$InfoFieldList[4];
1199  }
1200  } else {
1201  $sqlwhere .= ' WHERE 1=1';
1202  }
1203  // Some tables may have field, some other not. For the moment we disable it.
1204  if (in_array($InfoFieldList[0], array('tablewithentity'))) {
1205  $sqlwhere .= ' AND entity = '.$conf->entity;
1206  }
1207  $sql .= $sqlwhere;
1208  //print $sql;
1209 
1210  $sql .= ' ORDER BY '.implode(', ', $fields_label);
1211 
1212  dol_syslog(get_class($this).'::showInputField type=sellist', LOG_DEBUG);
1213  $resql = $this->db->query($sql);
1214  if ($resql) {
1215  $out .= '<option value="0">&nbsp;</option>';
1216  $num = $this->db->num_rows($resql);
1217  $i = 0;
1218  while ($i < $num) {
1219  $labeltoshow = '';
1220  $obj = $this->db->fetch_object($resql);
1221 
1222  // Several field into label (eq table:code|libelle:rowid)
1223  $notrans = false;
1224  $fields_label = explode('|', $InfoFieldList[1]);
1225  if (is_array($fields_label) && count($fields_label) > 1) {
1226  $notrans = true;
1227  foreach ($fields_label as $field_toshow) {
1228  $labeltoshow .= $obj->$field_toshow.' ';
1229  }
1230  } else {
1231  $labeltoshow = $obj->{$InfoFieldList[1]};
1232  }
1233  $labeltoshow = $labeltoshow;
1234 
1235  if ($value == $obj->rowid) {
1236  if (!$notrans) {
1237  foreach ($fields_label as $field_toshow) {
1238  $translabel = $langs->trans($obj->$field_toshow);
1239  $labeltoshow = $translabel.' ';
1240  }
1241  }
1242  $out .= '<option value="'.$obj->rowid.'" selected>'.$labeltoshow.'</option>';
1243  } else {
1244  if (!$notrans) {
1245  $translabel = $langs->trans($obj->{$InfoFieldList[1]});
1246  $labeltoshow = $translabel;
1247  }
1248  if (empty($labeltoshow)) $labeltoshow = '(not defined)';
1249 
1250  if (!empty($InfoFieldList[3]) && $parentField) {
1251  $parent = $parentName.':'.$obj->{$parentField};
1252  }
1253 
1254  $out .= '<option value="'.$obj->rowid.'"';
1255  $out .= ($value == $obj->rowid ? ' selected' : '');
1256  $out .= (!empty($parent) ? ' parent="'.$parent.'"' : '');
1257  $out .= '>'.$labeltoshow.'</option>';
1258  }
1259 
1260  $i++;
1261  }
1262  $this->db->free($resql);
1263  } else {
1264  print 'Error in request '.$sql.' '.$this->db->lasterror().'. Check setup of extra parameters.<br>';
1265  }
1266  } else {
1267  require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1268  $data = $form->select_all_categories(Categorie::$MAP_ID_TO_CODE[$InfoFieldList[5]], '', 'parent', 64, $InfoFieldList[6], 1, 1);
1269  $out .= '<option value="0">&nbsp;</option>';
1270  foreach ($data as $data_key => $data_value) {
1271  $out .= '<option value="'.$data_key.'"';
1272  $out .= ($value == $data_key ? ' selected' : '');
1273  $out .= '>'.$data_value.'</option>';
1274  }
1275  }
1276  }
1277  $out .= '</select>';
1278  } elseif ($type == 'checkbox')
1279  {
1280  $value_arr = explode(',', $value);
1281  $out = $form->multiselectarray($keyprefix.$key.$keysuffix, (empty($param['options']) ?null:$param['options']), $value_arr, '', 0, '', 0, '100%');
1282  } elseif ($type == 'radio')
1283  {
1284  $out = '';
1285  foreach ($param['options'] as $keyopt => $val)
1286  {
1287  $out .= '<input class="flat '.$morecss.'" type="radio" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam ? $moreparam : '');
1288  $out .= ' value="'.$keyopt.'"';
1289  $out .= ' id="'.$keyprefix.$key.$keysuffix.'_'.$keyopt.'"';
1290  $out .= ($value == $keyopt ? 'checked' : '');
1291  $out .= '/><label for="'.$keyprefix.$key.$keysuffix.'_'.$keyopt.'">'.$val.'</label><br>';
1292  }
1293  } elseif ($type == 'chkbxlst')
1294  {
1295  if (is_array($value)) {
1296  $value_arr = $value;
1297  } else {
1298  $value_arr = explode(',', $value);
1299  }
1300 
1301  if (is_array($param['options'])) {
1302  $param_list = array_keys($param['options']);
1303  $InfoFieldList = explode(":", $param_list[0]);
1304  $parentName = '';
1305  $parentField = '';
1306  // 0 : tableName
1307  // 1 : label field name
1308  // 2 : key fields name (if differ of rowid)
1309  // 3 : key field parent (for dependent lists)
1310  // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value
1311  // 5 : id category type
1312  // 6 : ids categories list separated by comma for category root
1313  $keyList = (empty($InfoFieldList[2]) ? 'rowid' : $InfoFieldList[2].' as rowid');
1314 
1315  if (count($InfoFieldList) > 3 && !empty($InfoFieldList[3])) {
1316  list ($parentName, $parentField) = explode('|', $InfoFieldList[3]);
1317  $keyList .= ', '.$parentField;
1318  }
1319  if (count($InfoFieldList) > 4 && !empty($InfoFieldList[4])) {
1320  if (strpos($InfoFieldList[4], 'extra.') !== false) {
1321  $keyList = 'main.'.$InfoFieldList[2].' as rowid';
1322  } else {
1323  $keyList = $InfoFieldList[2].' as rowid';
1324  }
1325  }
1326 
1327  $filter_categorie = false;
1328  if (count($InfoFieldList) > 5) {
1329  if ($InfoFieldList[0] == 'categorie') {
1330  $filter_categorie = true;
1331  }
1332  }
1333 
1334  if ($filter_categorie === false) {
1335  $fields_label = explode('|', $InfoFieldList[1]);
1336  if (is_array($fields_label)) {
1337  $keyList .= ', ';
1338  $keyList .= implode(', ', $fields_label);
1339  }
1340 
1341  $sqlwhere = '';
1342  $sql = 'SELECT '.$keyList;
1343  $sql .= ' FROM '.MAIN_DB_PREFIX.$InfoFieldList[0];
1344  if (!empty($InfoFieldList[4])) {
1345  // can use SELECT request
1346  if (strpos($InfoFieldList[4], '$SEL$') !== false) {
1347  $InfoFieldList[4] = str_replace('$SEL$', 'SELECT', $InfoFieldList[4]);
1348  }
1349 
1350  // current object id can be use into filter
1351  if (strpos($InfoFieldList[4], '$ID$') !== false && !empty($objectid)) {
1352  $InfoFieldList[4] = str_replace('$ID$', $objectid, $InfoFieldList[4]);
1353  } elseif (preg_match("#^.*list.php$#", $_SERVER["PHP_SELF"])) {
1354  // Pattern for word=$ID$
1355  $word = '\b[a-zA-Z0-9-\.-_]+\b=\$ID\$';
1356 
1357  // Removing space arount =, ( and )
1358  $InfoFieldList[4] = preg_replace('# *(=|\(|\)) *#', '$1', $InfoFieldList[4]);
1359 
1360  $nbPreg = 1;
1361  // While we have parenthesis
1362  while ($nbPreg != 0) {
1363  // Init des compteurs
1364  $nbPregRepl = $nbPregSel = 0;
1365  // On retire toutes les parenthèses sans = avant
1366  $InfoFieldList[4] = preg_replace('#([^=])(\([^)^(]*('.$word.')[^)^(]*\))#', '$1 $3 ', $InfoFieldList[4], -1, $nbPregRepl);
1367  // On retire les espaces autour des = et parenthèses
1368  $InfoFieldList[4] = preg_replace('# *(=|\(|\)) *#', '$1', $InfoFieldList[4]);
1369  // On retire toutes les parenthèses avec = avant
1370  $InfoFieldList[4] = preg_replace('#\b[a-zA-Z0-9-\.-_]+\b=\([^)^(]*('.$word.')[^)^(]*\)#', '$1 ', $InfoFieldList[4], -1, $nbPregSel);
1371  // On retire les espaces autour des = et parenthèses
1372  $InfoFieldList[4] = preg_replace('# *(=|\(|\)) *#', '$1', $InfoFieldList[4]);
1373 
1374  // Calcul du compteur général pour la boucle
1375  $nbPreg = $nbPregRepl + $nbPregSel;
1376  }
1377 
1378  // Si l'on a un AND ou un OR, avant ou après
1379  preg_match('#(AND|OR|) *('.$word.') *(AND|OR|)#', $InfoFieldList[4], $matchCondition);
1380  while (!empty($matchCondition[0])) {
1381  // If the two sides differ but are not empty
1382  if (!empty($matchCondition[1]) && !empty($matchCondition[3]) && $matchCondition[1] != $matchCondition[3]) {
1383  // Nobody sain would do that without parentheses
1384  $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
1385  } else {
1386  if (!empty($matchCondition[1])) {
1387  $boolCond = (($matchCondition[1] == "AND") ? ' AND TRUE ' : ' OR FALSE ');
1388  $InfoFieldList[4] = str_replace($matchCondition[0], $boolCond.$matchCondition[3], $InfoFieldList[4]);
1389  } elseif (!empty($matchCondition[3])) {
1390  $boolCond = (($matchCondition[3] == "AND") ? ' TRUE AND ' : ' FALSE OR');
1391  $InfoFieldList[4] = str_replace($matchCondition[0], $boolCond, $InfoFieldList[4]);
1392  } else {
1393  $InfoFieldList[4] = " TRUE ";
1394  }
1395  }
1396 
1397  // Si l'on a un AND ou un OR, avant ou après
1398  preg_match('#(AND|OR|) *('.$word.') *(AND|OR|)#', $InfoFieldList[4], $matchCondition);
1399  }
1400  } else {
1401  $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
1402  }
1403 
1404  // We have to join on extrafield table
1405  if (strpos($InfoFieldList[4], 'extra.') !== false) {
1406  $sql .= ' as main, '.MAIN_DB_PREFIX.$InfoFieldList[0].'_extrafields as extra';
1407  $sqlwhere .= ' WHERE extra.fk_object=main.'.$InfoFieldList[2].' AND '.$InfoFieldList[4];
1408  } else {
1409  $sqlwhere .= ' WHERE '.$InfoFieldList[4];
1410  }
1411  } else {
1412  $sqlwhere .= ' WHERE 1=1';
1413  }
1414  // Some tables may have field, some other not. For the moment we disable it.
1415  if (in_array($InfoFieldList[0], array('tablewithentity'))) {
1416  $sqlwhere .= ' AND entity = '.$conf->entity;
1417  }
1418  // $sql.=preg_replace('/^ AND /','',$sqlwhere);
1419  // print $sql;
1420 
1421  $sql .= $sqlwhere;
1422  dol_syslog(get_class($this).'::showInputField type=chkbxlst', LOG_DEBUG);
1423  $resql = $this->db->query($sql);
1424  if ($resql) {
1425  $num = $this->db->num_rows($resql);
1426  $i = 0;
1427 
1428  $data = array();
1429 
1430  while ($i < $num) {
1431  $labeltoshow = '';
1432  $obj = $this->db->fetch_object($resql);
1433 
1434  $notrans = false;
1435  // Several field into label (eq table:code|libelle:rowid)
1436  $fields_label = explode('|', $InfoFieldList[1]);
1437  if (is_array($fields_label)) {
1438  $notrans = true;
1439  foreach ($fields_label as $field_toshow) {
1440  $labeltoshow .= $obj->$field_toshow.' ';
1441  }
1442  } else {
1443  $labeltoshow = $obj->{$InfoFieldList[1]};
1444  }
1445  $labeltoshow = dol_trunc($labeltoshow, 45);
1446 
1447  if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1448  foreach ($fields_label as $field_toshow) {
1449  $translabel = $langs->trans($obj->$field_toshow);
1450  if ($translabel != $obj->$field_toshow) {
1451  $labeltoshow = dol_trunc($translabel, 18).' ';
1452  } else {
1453  $labeltoshow = dol_trunc($obj->$field_toshow, 18).' ';
1454  }
1455  }
1456 
1457  $data[$obj->rowid] = $labeltoshow;
1458  } else {
1459  if (!$notrans) {
1460  $translabel = $langs->trans($obj->{$InfoFieldList[1]});
1461  if ($translabel != $obj->{$InfoFieldList[1]}) {
1462  $labeltoshow = dol_trunc($translabel, 18);
1463  } else {
1464  $labeltoshow = dol_trunc($obj->{$InfoFieldList[1]}, 18);
1465  }
1466  }
1467  if (empty($labeltoshow))
1468  $labeltoshow = '(not defined)';
1469 
1470  if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1471  $data[$obj->rowid] = $labeltoshow;
1472  }
1473 
1474  if (!empty($InfoFieldList[3]) && $parentField) {
1475  $parent = $parentName.':'.$obj->{$parentField};
1476  }
1477 
1478  $data[$obj->rowid] = $labeltoshow;
1479  }
1480 
1481  $i++;
1482  }
1483  $this->db->free($resql);
1484 
1485  $out = $form->multiselectarray($keyprefix.$key.$keysuffix, $data, $value_arr, '', 0, '', 0, '100%');
1486  } else {
1487  print 'Error in request '.$sql.' '.$this->db->lasterror().'. Check setup of extra parameters.<br>';
1488  }
1489  } else {
1490  require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1491  $data = $form->select_all_categories(Categorie::$MAP_ID_TO_CODE[$InfoFieldList[5]], '', 'parent', 64, $InfoFieldList[6], 1, 1);
1492  $out = $form->multiselectarray($keyprefix.$key.$keysuffix, $data, $value_arr, '', 0, '', 0, '100%');
1493  }
1494  }
1495  } elseif ($type == 'link')
1496  {
1497  $param_list = array_keys($param['options']); // $param_list='ObjectName:classPath'
1498  $showempty = (($required && $default != '') ? 0 : 1);
1499  $out = $form->selectForForms($param_list[0], $keyprefix.$key.$keysuffix, $value, $showempty, '', '', $morecss);
1500  } elseif ($type == 'password')
1501  {
1502  // If prefix is 'search_', field is used as a filter, we use a common text field.
1503  $out = '<input style="display:none" type="text" name="fakeusernameremembered">'; // Hidden field to reduce impact of evil Google Chrome autopopulate bug.
1504  $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 : '').'>';
1505  }
1506  if (!empty($hidden)) {
1507  $out = '<input type="hidden" value="'.$value.'" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'"/>';
1508  }
1509  /* Add comments
1510  if ($type == 'date') $out.=' (YYYY-MM-DD)';
1511  elseif ($type == 'datetime') $out.=' (YYYY-MM-DD HH:MM:SS)';
1512  */
1513  /*if (! empty($help) && $keyprefix != 'search_options_') {
1514  $out .= $form->textwithpicto('', $help, 1, 'help', '', 0, 3);
1515  }*/
1516  return $out;
1517  }
1518 
1519 
1529  public function showOutputField($key, $value, $moreparam = '', $extrafieldsobjectkey = '')
1530  {
1531  global $conf, $langs;
1532 
1533  if (!empty($extrafieldsobjectkey))
1534  {
1535  $label = $this->attributes[$extrafieldsobjectkey]['label'][$key];
1536  $type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
1537  $size = $this->attributes[$extrafieldsobjectkey]['size'][$key];
1538  $default = $this->attributes[$extrafieldsobjectkey]['default'][$key];
1539  $computed = $this->attributes[$extrafieldsobjectkey]['computed'][$key];
1540  $unique = $this->attributes[$extrafieldsobjectkey]['unique'][$key];
1541  $required = $this->attributes[$extrafieldsobjectkey]['required'][$key];
1542  $param = $this->attributes[$extrafieldsobjectkey]['param'][$key];
1543  $perms = dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1);
1544  $langfile = $this->attributes[$extrafieldsobjectkey]['langfile'][$key];
1545  $list = dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1);
1546  $help = $this->attributes[$extrafieldsobjectkey]['help'][$key];
1547  $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)
1548  } else // Old usage
1549  {
1550  //dol_syslog("Warning: parameter 'extrafieldsobjectkey' is missing", LOG_WARNING);
1551  $label = $this->attribute_label[$key];
1552  $type = $this->attribute_type[$key];
1553  $size = $this->attribute_size[$key];
1554  $default = $this->attribute_default[$key];
1555  $computed = $this->attribute_computed[$key];
1556  $unique = $this->attribute_unique[$key];
1557  $required = $this->attribute_required[$key];
1558  $param = $this->attribute_param[$key];
1559  $perms = dol_eval($this->attribute_perms[$key], 1);
1560  $langfile = $this->attribute_langfile[$key];
1561  $list = dol_eval($this->attribute_list[$key], 1);
1562  $help = ''; // Not supported with old syntax
1563  $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)
1564  }
1565 
1566  if ($hidden) return ''; // This is a protection. If field is hidden, we should just not call this method.
1567 
1568  //if ($computed) $value = // $value is already calculated into $value before calling this method
1569 
1570  $showsize = 0;
1571  if ($type == 'date')
1572  {
1573  $showsize = 10;
1574  $value = dol_print_date($value, 'day'); // For date without hour, date is always GMT for storage and output
1575  } elseif ($type == 'datetime')
1576  {
1577  $showsize = 19;
1578  $value = dol_print_date($value, 'dayhour', 'tzuserrel');
1579  } elseif ($type == 'int')
1580  {
1581  $showsize = 10;
1582  } elseif ($type == 'double')
1583  {
1584  if (!empty($value)) {
1585  //$value=price($value);
1586  $sizeparts = explode(",", $size);
1587  $number_decimals = $sizeparts[1];
1588  $value = price($value, 0, $langs, 0, 0, $number_decimals, '');
1589  }
1590  } elseif ($type == 'boolean')
1591  {
1592  $checked = '';
1593  if (!empty($value)) {
1594  $checked = ' checked ';
1595  }
1596  $value = '<input type="checkbox" '.$checked.' '.($moreparam ? $moreparam : '').' readonly disabled>';
1597  } elseif ($type == 'mail')
1598  {
1599  $value = dol_print_email($value, 0, 0, 0, 64, 1, 1);
1600  } elseif ($type == 'url')
1601  {
1602  $value = dol_print_url($value, '_blank', 32, 1);
1603  } elseif ($type == 'phone')
1604  {
1605  $value = dol_print_phone($value, '', 0, 0, '', '&nbsp;', 'phone');
1606  } elseif ($type == 'price')
1607  {
1608  //$value = price($value, 0, $langs, 0, 0, -1, $conf->currency);
1609  if ($value || $value == '0') $value = price($value, 0, $langs, 0, 0, -1);
1610  } elseif ($type == 'select') {
1611  $valstr = $param['options'][$value];
1612  if (($pos = strpos($valstr, "|")) !== false)
1613  {
1614  $valstr = substr($valstr, 0, $pos);
1615  }
1616  if ($langfile && $valstr) $value = $langs->trans($valstr);
1617  else $value = $valstr;
1618  } elseif ($type == 'sellist') {
1619  $param_list = array_keys($param['options']);
1620  $InfoFieldList = explode(":", $param_list[0]);
1621 
1622  $selectkey = "rowid";
1623  $keyList = 'rowid';
1624 
1625  if (count($InfoFieldList) >= 3)
1626  {
1627  $selectkey = $InfoFieldList[2];
1628  $keyList = $InfoFieldList[2].' as rowid';
1629  }
1630 
1631  $fields_label = explode('|', $InfoFieldList[1]);
1632  if (is_array($fields_label)) {
1633  $keyList .= ', ';
1634  $keyList .= implode(', ', $fields_label);
1635  }
1636 
1637  $filter_categorie = false;
1638  if (count($InfoFieldList) > 5) {
1639  if ($InfoFieldList[0] == 'categorie') {
1640  $filter_categorie = true;
1641  }
1642  }
1643 
1644  $sql = 'SELECT '.$keyList;
1645  $sql .= ' FROM '.MAIN_DB_PREFIX.$InfoFieldList[0];
1646  if (strpos($InfoFieldList[4], 'extra') !== false)
1647  {
1648  $sql .= ' as main';
1649  }
1650  if ($selectkey == 'rowid' && empty($value)) {
1651  $sql .= " WHERE ".$selectkey."=0";
1652  } elseif ($selectkey == 'rowid') {
1653  $sql .= " WHERE ".$selectkey."=".$this->db->escape($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  {
1664  if ($filter_categorie === false) {
1665  $value = ''; // value was used, so now we reste it to use it to build final output
1666 
1667  $obj = $this->db->fetch_object($resql);
1668 
1669  // Several field into label (eq table:code|libelle:rowid)
1670  $fields_label = explode('|', $InfoFieldList[1]);
1671 
1672  if (is_array($fields_label) && count($fields_label) > 1) {
1673  foreach ($fields_label as $field_toshow) {
1674  $translabel = '';
1675  if (!empty($obj->$field_toshow)) {
1676  $translabel = $langs->trans($obj->$field_toshow);
1677  }
1678  if ($translabel != $field_toshow) {
1679  $value .= dol_trunc($translabel, 18).' ';
1680  } else {
1681  $value .= $obj->$field_toshow.' ';
1682  }
1683  }
1684  } else {
1685  $translabel = '';
1686  if (!empty($obj->{$InfoFieldList[1]})) {
1687  $translabel = $langs->trans($obj->{$InfoFieldList[1]});
1688  }
1689  if ($translabel != $obj->{$InfoFieldList[1]}) {
1690  $value = dol_trunc($translabel, 18);
1691  } else {
1692  $value = $obj->{$InfoFieldList[1]};
1693  }
1694  }
1695  } else {
1696  require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1697 
1698  $toprint = array();
1699  $obj = $this->db->fetch_object($resql);
1700  $c = new Categorie($this->db);
1701  $c->fetch($obj->rowid);
1702  $ways = $c->print_all_ways(); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formatted text
1703  foreach ($ways as $way) {
1704  $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories"'.($c->color ? ' style="background: #'.$c->color.';"' : ' style="background: #bbb"').'>'.img_object('', 'category').' '.$way.'</li>';
1705  }
1706  $value = '<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
1707  }
1708  } else dol_syslog(get_class($this).'::showOutputField error '.$this->db->lasterror(), LOG_WARNING);
1709  } elseif ($type == 'radio')
1710  {
1711  $value = $param['options'][$value];
1712  } elseif ($type == 'checkbox')
1713  {
1714  $value_arr = explode(',', $value);
1715  $value = '';
1716  $toprint = array();
1717  if (is_array($value_arr))
1718  {
1719  foreach ($value_arr as $keyval=>$valueval) {
1720  $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.$param['options'][$valueval].'</li>';
1721  }
1722  }
1723  $value = '<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
1724  } elseif ($type == 'chkbxlst')
1725  {
1726  $value_arr = explode(',', $value);
1727 
1728  $param_list = array_keys($param['options']);
1729  $InfoFieldList = explode(":", $param_list[0]);
1730 
1731  $selectkey = "rowid";
1732  $keyList = 'rowid';
1733 
1734  if (count($InfoFieldList) >= 3) {
1735  $selectkey = $InfoFieldList[2];
1736  $keyList = $InfoFieldList[2].' as rowid';
1737  }
1738 
1739  $fields_label = explode('|', $InfoFieldList[1]);
1740  if (is_array($fields_label)) {
1741  $keyList .= ', ';
1742  $keyList .= implode(', ', $fields_label);
1743  }
1744 
1745  $filter_categorie = false;
1746  if (count($InfoFieldList) > 5) {
1747  if ($InfoFieldList[0] == 'categorie') {
1748  $filter_categorie = true;
1749  }
1750  }
1751 
1752  $sql = 'SELECT '.$keyList;
1753  $sql .= ' FROM '.MAIN_DB_PREFIX.$InfoFieldList[0];
1754  if (strpos($InfoFieldList[4], 'extra') !== false) {
1755  $sql .= ' as main';
1756  }
1757  // $sql.= " WHERE ".$selectkey."='".$this->db->escape($value)."'";
1758  // $sql.= ' AND entity = '.$conf->entity;
1759 
1760  dol_syslog(get_class($this).':showOutputField:$type=chkbxlst', LOG_DEBUG);
1761  $resql = $this->db->query($sql);
1762  if ($resql) {
1763  if ($filter_categorie === false) {
1764  $value = ''; // value was used, so now we reste it to use it to build final output
1765  $toprint = array();
1766  while ($obj = $this->db->fetch_object($resql)) {
1767  // Several field into label (eq table:code|libelle:rowid)
1768  $fields_label = explode('|', $InfoFieldList[1]);
1769  if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1770  if (is_array($fields_label) && count($fields_label) > 1) {
1771  foreach ($fields_label as $field_toshow) {
1772  $translabel = '';
1773  if (!empty($obj->$field_toshow)) {
1774  $translabel = $langs->trans($obj->$field_toshow);
1775  }
1776  if ($translabel != $field_toshow) {
1777  $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.dol_trunc($translabel, 18).'</li>';
1778  } else {
1779  $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.$obj->$field_toshow.'</li>';
1780  }
1781  }
1782  } else {
1783  $translabel = '';
1784  if (!empty($obj->{$InfoFieldList[1]})) {
1785  $translabel = $langs->trans($obj->{$InfoFieldList[1]});
1786  }
1787  if ($translabel != $obj->{$InfoFieldList[1]}) {
1788  $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.dol_trunc($translabel, 18).'</li>';
1789  } else {
1790  $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb">'.$obj->{$InfoFieldList[1]}.'</li>';
1791  }
1792  }
1793  }
1794  }
1795  } else {
1796  require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1797 
1798  $toprint = array();
1799  while ($obj = $this->db->fetch_object($resql)) {
1800  if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1801  $c = new Categorie($this->db);
1802  $c->fetch($obj->rowid);
1803  $ways = $c->print_all_ways(); // $ways[0] = "ccc2 >> ccc2a >> ccc2a1" with html formatted text
1804  foreach ($ways as $way) {
1805  $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories"'.($c->color ? ' style="background: #'.$c->color.';"' : ' style="background: #bbb"').'>'.img_object('', 'category').' '.$way.'</li>';
1806  }
1807  }
1808  }
1809  }
1810  $value = '<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
1811  } else {
1812  dol_syslog(get_class($this).'::showOutputField error '.$this->db->lasterror(), LOG_WARNING);
1813  }
1814  } elseif ($type == 'link')
1815  {
1816  $out = '';
1817 
1818  // Only if something to display (perf)
1819  if ($value) // If we have -1 here, pb is into insert, not into ouptut (fix insert instead of changing code here to compensate)
1820  {
1821  $param_list = array_keys($param['options']); // $param_list='ObjectName:classPath'
1822 
1823  $InfoFieldList = explode(":", $param_list[0]);
1824  $classname = $InfoFieldList[0];
1825  $classpath = $InfoFieldList[1];
1826  if (!empty($classpath))
1827  {
1828  dol_include_once($InfoFieldList[1]);
1829  if ($classname && class_exists($classname))
1830  {
1831  $object = new $classname($this->db);
1832  $object->fetch($value);
1833  $value = $object->getNomUrl(3);
1834  }
1835  } else {
1836  dol_syslog('Error bad setup of extrafield', LOG_WARNING);
1837  return 'Error bad setup of extrafield';
1838  }
1839  }
1840  } elseif ($type == 'text')
1841  {
1842  $value = dol_htmlentitiesbr($value);
1843  } elseif ($type == 'html')
1844  {
1845  $value = dol_htmlentitiesbr($value);
1846  } elseif ($type == 'password')
1847  {
1848  $value = dol_trunc(preg_replace('/./i', '*', $value), 8, 'right', 'UTF-8', 1);
1849  } else {
1850  $showsize = round($size);
1851  if ($showsize > 48) $showsize = 48;
1852  }
1853 
1854  //print $type.'-'.$size;
1855  $out = $value;
1856 
1857  return $out;
1858  }
1859 
1867  public function getAlignFlag($key, $extrafieldsobjectkey = '')
1868  {
1869  global $conf, $langs;
1870 
1871  if (!empty($extrafieldsobjectkey)) $type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
1872  else $type = $this->attribute_type[$key];
1873 
1874  $align = '';
1875 
1876  if ($type == 'date')
1877  {
1878  $align = "center";
1879  } elseif ($type == 'datetime')
1880  {
1881  $align = "center";
1882  } elseif ($type == 'int')
1883  {
1884  $align = "right";
1885  } elseif ($type == 'price')
1886  {
1887  $align = "right";
1888  } elseif ($type == 'double')
1889  {
1890  $align = "right";
1891  } elseif ($type == 'boolean')
1892  {
1893  $align = "center";
1894  } elseif ($type == 'radio')
1895  {
1896  $align = "center";
1897  } elseif ($type == 'checkbox')
1898  {
1899  $align = "center";
1900  } elseif ($type == 'price')
1901  {
1902  $align = "right";
1903  }
1904 
1905  return $align;
1906  }
1907 
1916  public function showSeparator($key, $object, $colspan = 2)
1917  {
1918  global $langs;
1919 
1920  $out = '<tr id="trextrafieldseparator'.$key.'" class="trextrafieldseparator trextrafieldseparator'.$key.'"><td colspan="'.$colspan.'"><strong>';
1921  $out .= $langs->trans($this->attributes[$object->table_element]['label'][$key]);
1922  $out .= '</strong></td></tr>';
1923 
1924  $extrafield_param = $this->attributes[$object->table_element]['param'][$key];
1925  if (!empty($extrafield_param) && is_array($extrafield_param)) {
1926  $extrafield_param_list = array_keys($extrafield_param['options']);
1927 
1928  if (count($extrafield_param_list) > 0) {
1929  $extrafield_collapse_display_value = intval($extrafield_param_list[0]);
1930  if ($extrafield_collapse_display_value == 1 || $extrafield_collapse_display_value == 2) {
1931  // Set the collapse_display status to cookie in priority or if ignorecollapsesetup is 1, if cookie and ignorecollapsesetup not defined, use the setup.
1932  $collapse_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));
1933  $extrafields_collapse_num = $this->attributes[$object->table_element]['pos'][$key];
1934 
1935  $out .= '<!-- Add js script to manage the collpase/uncollapse of extrafields separators '.$key.' -->';
1936  $out .= '<script type="text/javascript">';
1937  $out .= 'jQuery(document).ready(function(){';
1938  if ($collapse_display === false) {
1939  $out .= ' jQuery("#trextrafieldseparator'.$key.' td").prepend("<span class=\"cursorpointer far fa-plus-square\"></span>&nbsp;");'."\n";
1940  $out .= ' jQuery(".trextrafields_collapse'.$extrafields_collapse_num.'").hide();'."\n";
1941  } else {
1942  $out .= ' jQuery("#trextrafieldseparator'.$key.' td").prepend("<span class=\"cursorpointer far fa-minus-square\"></span>&nbsp;");'."\n";
1943  $out .= ' document.cookie = "DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.'=1; path='.$_SERVER["PHP_SELF"].'"'."\n";
1944  }
1945  $out .= ' jQuery("#trextrafieldseparator'.$key.'").click(function(){'."\n";
1946  $out .= ' jQuery(".trextrafields_collapse'.$extrafields_collapse_num.'").toggle(300, function(){'."\n";
1947  $out .= ' if (jQuery(".trextrafields_collapse'.$extrafields_collapse_num.'").is(":hidden")) {'."\n";
1948  $out .= ' jQuery("#trextrafieldseparator'.$key.' td span").addClass("fa-plus-square").removeClass("fa-minus-square");'."\n";
1949  $out .= ' document.cookie = "DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.'=0; path='.$_SERVER["PHP_SELF"].'"'."\n";
1950  $out .= ' } else {'."\n";
1951  $out .= ' jQuery("#trextrafieldseparator'.$key.' td span").addClass("fa-minus-square").removeClass("fa-plus-square");'."\n";
1952  $out .= ' document.cookie = "DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.'=1; path='.$_SERVER["PHP_SELF"].'"'."\n";
1953  $out .= ' }'."\n";
1954  $out .= ' });';
1955  $out .= ' });';
1956  $out .= '});';
1957  $out .= '</script>';
1958  }
1959  }
1960  }
1961 
1962  return $out;
1963  }
1964 
1975  public function setOptionalsFromPost($extralabels, &$object, $onlykey = '')
1976  {
1977  global $_POST, $langs;
1978 
1979  $nofillrequired = 0; // For error when required field left blank
1980  $error_field_required = array();
1981 
1982  if (is_array($this->attributes[$object->table_element]['label'])) $extralabels = $this->attributes[$object->table_element]['label'];
1983 
1984  if (is_array($extralabels))
1985  {
1986  // Get extra fields
1987  foreach ($extralabels as $key => $value)
1988  {
1989  if (!empty($onlykey) && $onlykey != '@GETPOSTISSET' && $key != $onlykey) continue;
1990  if (!empty($onlykey) && $onlykey == '@GETPOSTISSET' && !GETPOSTISSET('options_'.$key)) continue;
1991 
1992  $key_type = $this->attributes[$object->table_element]['type'][$key];
1993  if ($key_type == 'separate') continue;
1994 
1995  $enabled = 1;
1996  if (isset($this->attributes[$object->table_element]['list'][$key]))
1997  {
1998  $enabled = dol_eval($this->attributes[$object->table_element]['list'][$key], 1);
1999  }
2000  $perms = 1;
2001  if (isset($this->attributes[$object->table_element]['perms'][$key]))
2002  {
2003  $perms = dol_eval($this->attributes[$object->table_element]['perms'][$key], 1);
2004  }
2005  if (empty($enabled)) continue;
2006  if (empty($perms)) continue;
2007 
2008  if ($this->attributes[$object->table_element]['required'][$key]) // Value is required
2009  {
2010  // Check if functionally empty without using GETPOST (depending on the type of extrafield, a
2011  // technically non-empty value may be treated as empty functionally).
2012  // value can be alpha, int, array, etc...
2013  if ((!is_array($_POST["options_".$key]) && empty($_POST["options_".$key]) && $this->attributes[$object->table_element]['type'][$key] != 'select' && $_POST["options_".$key] != '0')
2014  || (!is_array($_POST["options_".$key]) && empty($_POST["options_".$key]) && $this->attributes[$object->table_element]['type'][$key] == 'select')
2015  || (!is_array($_POST["options_".$key]) && isset($_POST["options_".$key]) && $this->attributes[$object->table_element]['type'][$key] == 'sellist' && $_POST['options_'.$key] == '0')
2016  || (is_array($_POST["options_".$key]) && empty($_POST["options_".$key])))
2017  {
2018  //print 'ccc'.$value.'-'.$this->attributes[$object->table_element]['required'][$key];
2019  $nofillrequired++;
2020  $error_field_required[] = $langs->transnoentitiesnoconv($value);
2021  }
2022  }
2023 
2024  if (in_array($key_type, array('date'))) {
2025  // Clean parameters
2026  $value_key = dol_mktime(12, 0, 0, GETPOST("options_".$key."month", 'int'), GETPOST("options_".$key."day", 'int'), GETPOST("options_".$key."year", 'int'));
2027  } elseif (in_array($key_type, array('datetime'))) {
2028  // Clean parameters
2029  $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');
2030  } elseif (in_array($key_type, array('checkbox', 'chkbxlst'))) {
2031  $value_arr = GETPOST("options_".$key, 'array'); // check if an array
2032  if (!empty($value_arr)) {
2033  $value_key = implode($value_arr, ',');
2034  } else {
2035  $value_key = '';
2036  }
2037  } elseif (in_array($key_type, array('price', 'double'))) {
2038  $value_arr = GETPOST("options_".$key, 'alpha');
2039  $value_key = price2num($value_arr);
2040  } elseif (in_array($key_type, array('html'))) {
2041  $value_key = GETPOST("options_".$key, 'restricthtml');
2042  } elseif (in_array($key_type, array('text'))) {
2043  $value_key = GETPOST("options_".$key, 'alphanohtml');
2044  } else {
2045  $value_key = GETPOST("options_".$key);
2046  if (in_array($key_type, array('link')) && $value_key == '-1') $value_key = '';
2047  }
2048 
2049  $object->array_options["options_".$key] = $value_key;
2050  }
2051 
2052  if ($nofillrequired) {
2053  $langs->load('errors');
2054  setEventMessages($langs->trans('ErrorFieldsRequired').' : '.implode(', ', $error_field_required), null, 'errors');
2055  return -1;
2056  } else {
2057  return 1;
2058  }
2059  } else {
2060  return 0;
2061  }
2062  }
2063 
2072  public function getOptionalsFromPost($extrafieldsobjectkey, $keyprefix = '', $keysuffix = '')
2073  {
2074  global $_POST;
2075 
2076  if (is_string($extrafieldsobjectkey) && is_array($this->attributes[$extrafieldsobjectkey]['label']))
2077  {
2078  $extralabels = $this->attributes[$extrafieldsobjectkey]['label'];
2079  } else {
2080  $extralabels = $extrafieldsobjectkey;
2081  }
2082 
2083  if (is_array($extralabels))
2084  {
2085  $array_options = array();
2086 
2087  // Get extra fields
2088  foreach ($extralabels as $key => $value)
2089  {
2090  $key_type = '';
2091  if (is_string($extrafieldsobjectkey))
2092  {
2093  $key_type = $this->attributes[$extrafieldsobjectkey]['type'][$key];
2094  }
2095 
2096  if (in_array($key_type, array('date'))) {
2097  if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix."year")) continue; // Value was not provided, we should not set it.
2098  // Clean parameters
2099  $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'));
2100  } elseif (in_array($key_type, array('datetime'))) {
2101  if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix."year")) continue; // Value was not provided, we should not set it.
2102  // Clean parameters
2103  $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');
2104  } elseif (in_array($key_type, array('checkbox', 'chkbxlst'))) {
2105  if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix)) continue; // Value was not provided, we should not set it.
2106  $value_arr = GETPOST($keysuffix."options_".$key.$keyprefix);
2107  // Make sure we get an array even if there's only one checkbox
2108  $value_arr = (array) $value_arr;
2109  $value_key = implode(',', $value_arr);
2110  } elseif (in_array($key_type, array('price', 'double', 'int')))
2111  {
2112  if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix)) continue; // Value was not provided, we should not set it.
2113  $value_arr = GETPOST($keysuffix."options_".$key.$keyprefix);
2114  $value_key = price2num($value_arr);
2115  } else {
2116  if (!GETPOSTISSET($keysuffix."options_".$key.$keyprefix)) continue; // Value was not provided, we should not set it.
2117  $value_key = GETPOST($keysuffix."options_".$key.$keyprefix);
2118  }
2119 
2120  $array_options[$keysuffix."options_".$key] = $value_key; // No keyprefix here. keyprefix is used only for read.
2121  }
2122 
2123  return $array_options;
2124  }
2125 
2126  return 0;
2127  }
2128 }
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname= '')
Make an include_once using default root and alternate root if it fails.
GETPOST($paramname, $check= 'alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_eval($s, $returnvalue=0, $hideerrors=1)
Replace eval function to add more security.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm= 'auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
dol_print_url($url, $target= '_blank', $max=32, $withpicto=0)
Show Url link.
create_label($attrname, $label= '', $type= '', $pos=0, $size=0, $elementtype= 'member', $unique=0, $required=0, $param= '', $alwayseditable=0, $perms= '', $list= '-1', $help= '', $default= '', $computed= '', $entity= '', $langfile= '', $enabled= '1', $totalizable=0, $printable=0)
Add description of a new optional attribute.
create($attrname, $type= 'varchar', $length=255, $elementtype= 'member', $unique=0, $required=0, $default_value= '', $param= '', $perms= '', $list= '0', $computed= '', $help= '')
Add a new optional attribute.
__construct($db)
Constructor.
dol_now($mode= 'auto')
Return date for now.
dol_print_phone($phone, $countrycode= '', $cid=0, $socid=0, $addlink= '', $separ="&nbsp;", $withpicto= '', $titlealt= '', $adddivfloat=0)
Format phone numbers according to country.
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete= 'resolve')
Convert a html select field into an ajax combobox.
Definition: ajax.lib.php:391
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom= 'UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
showInputField($key, $value, $moreparam= '', $keysuffix= '', $keyprefix= '', $morecss= '', $objectid=0, $extrafieldsobjectkey= '', $mode=0)
Return HTML string to put an input field into a page Code very similar with showInputField of common ...
$conf db
API class for accounts.
Definition: inc.php:54
getAlignFlag($key, $extrafieldsobjectkey= '')
Return tag to describe alignement to use for this extrafield.
showSeparator($key, $object, $colspan=2)
Return HTML string to print separator extrafield.
price($amount, $form=0, $outlangs= '', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code= '')
Function to format a value into an amount for visual output Function used into PDF and HTML pages...
Class to manage standard extra fields.
setEventMessages($mesg, $mesgs, $style= 'mesgs', $messagekey= '')
Set event messages in dol_events session object.
Class to manage generation of HTML components Only common components must be here.
getOptionalsFromPost($extrafieldsobjectkey, $keyprefix= '', $keysuffix= '')
return array_options array of data of extrafields value of object sent by a search form ...
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname.
delete_label($attrname, $elementtype= 'member')
Delete description of an optional attribute.
Class to manage categories.
price2num($amount, $rounding= '', $option=0)
Function that return a number with universal decimal format (decimal separator is &#39;...
update($attrname, $label, $type, $length, $elementtype, $unique=0, $required=0, $pos=0, $param= '', $alwayseditable=0, $perms= '', $list= '', $help= '', $default= '', $computed= '', $entity= '', $langfile= '', $enabled= '1', $totalizable=0, $printable=0)
Modify type of a personalized attribute.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
img_object($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
setOptionalsFromPost($extralabels, &$object, $onlykey= '')
Fill array_options property of object by extrafields value (using for data sent by forms) ...
showOutputField($key, $value, $moreparam= '', $extrafieldsobjectkey= '')
Return HTML string to put an output field into a page.
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.
print $_SERVER["PHP_SELF"]
Edit parameters.
addExtraField($attrname, $label, $type, $pos, $size, $elementtype, $unique=0, $required=0, $default_value= '', $param= '', $alwayseditable=0, $perms= '', $list= '-1', $help= '', $computed= '', $entity= '', $langfile= '', $enabled= '1', $totalizable=0, $printable=0)
Add a new extra field parameter.
fetch_name_optionals_label($elementtype, $forceload=false)
Load array this-&gt;attributes, or old this-&gt;attribute_xxx like attribute_label, attribute_type, ...
print
Draft customers invoices.
Definition: index.php:89
dol_print_date($time, $format= '', $tzoutput= 'auto', $outputlangs= '', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->don->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1232
dol_print_error($db= '', $error= '', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_print_email($email, $cid=0, $socid=0, $addlink=0, $max=64, $showinvalid=1, $withpicto=0)
Show EMail link formatted for HTML output.
Class to manage a WYSIWYG editor.
dol_trunc($string, $size=40, $trunc= 'right', $stringencoding= 'UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding &#39;...&#39; if string larger than length.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $keepmoretags= '', $escapeonlyhtmltags=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields...