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