Passed
Branch develop (ec45af)
by
unknown
75:52
created

ExtraFields::addExtraField()   C

Complexity

Conditions 13
Paths 50

Size

Total Lines 40
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 26
c 0
b 0
f 0
nc 50
nop 21
dl 0
loc 40
rs 6.6166

How to fix   Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/* Copyright (C) 2002-2003  Rodolphe Quiedeville    <[email protected]>
3
 * Copyright (C) 2002-2003  Jean-Louis Bergamo      <[email protected]>
4
 * Copyright (C) 2004       Sebastien Di Cintio     <[email protected]>
5
 * Copyright (C) 2004       Benoit Mortier          <[email protected]>
6
 * Copyright (C) 2009-2012  Laurent Destailleur     <[email protected]>
7
 * Copyright (C) 2009-2012  Regis Houssin           <[email protected]>
8
 * Copyright (C) 2013       Florian Henry           <[email protected]>
9
 * Copyright (C) 2015       Charles-Fr BENKE        <[email protected]>
10
 * Copyright (C) 2016       Raphaël Doursenaud      <[email protected]>
11
 * Copyright (C) 2017       Nicolas ZABOURI         <[email protected]>
12
 * Copyright (C) 2018-2022  Frédéric France         <[email protected]>
13
 * Copyright (C) 2022 		Antonin MARCHAL         <[email protected]>
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
29
/**
30
 * 	\file 		htdocs/core/class/extrafields.class.php
31
 *	\ingroup    core
32
 *	\brief      File of class to manage extra fields
33
 */
34
35
36
/**
37
 *	Class to manage standard extra fields
38
 */
39
class ExtraFields
40
{
41
	/**
42
	 * @var DoliDB Database handler.
43
	 */
44
	public $db;
45
46
	/**
47
	 * @var array New array to store extrafields definition
48
	 */
49
	public $attributes;
50
51
	/**
52
	 * @var array	Array with boolean of status of groups
53
	 */
54
	public $expand_display;
55
56
	/**
57
	 * @var string Error code (or message)
58
	 */
59
	public $error = '';
60
61
	/**
62
	 * @var string[] Array of Error code (or message)
63
	 */
64
	public $errors = array();
65
66
	/**
67
	 * @var string DB Error number
68
	 */
69
	public $errno;
70
71
	/**
72
	 * @var array array of type to label
73
	 */
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
101
	/**
102
	 *	Constructor
103
	 *
104
	 *  @param		DoliDB		$db      Database handler
105
	 */
106
	public function __construct($db)
107
	{
108
		$this->db = $db;
109
		$this->error = '';
110
		$this->errors = array();
111
		$this->attributes = array();
112
	}
113
114
	/**
115
	 *  Add a new extra field parameter
116
	 *
117
	 *  @param	string			$attrname           Code of attribute
118
	 *  @param  string			$label              label of attribute
119
	 *  @param  string			$type               Type of attribute ('boolean','int','varchar','text','html','date','datehour','price', 'pricecy', 'phone','mail','password','url','select','checkbox','separate',...)
120
	 *  @param  int				$pos                Position of attribute
121
	 *  @param  string			$size               Size/length definition of attribute ('5', '24,8', ...). For float, it contains 2 numeric separated with a comma.
122
	 *  @param  string			$elementtype        Element type. Same value than object->table_element (Example 'member', 'product', 'thirdparty', ...)
123
	 *  @param	int				$unique				Is field unique or not
124
	 *  @param	int				$required			Is field required or not
125
	 *  @param	string			$default_value		Defaulted value (In database. use the default_value feature for default value on screen. Example: '', '0', 'null', 'avalue')
126
	 *  @param  array|string	$param				Params for field (ex for select list : array('options' => array(value'=>'label of option')) )
127
	 *  @param  int				$alwayseditable		Is attribute always editable regardless of the document status
128
	 *  @param	string			$perms				Permission to check
129
	 *  @param	string			$list				Visibilty ('0'=never visible, '1'=visible on list+forms, '2'=list only, '3'=form only or 'eval string')
130
	 *  @param	string			$help				Text with help tooltip
131
	 *  @param  string  		$computed           Computed value
132
	 *  @param  string  		$entity    		 	Entity of extrafields (for multicompany modules)
133
	 *  @param  string  		$langfile  		 	Language file
134
	 *  @param  string  		$enabled  		 	Condition to have the field enabled or not
135
	 *  @param	int				$totalizable		Is a measure. Must show a total on lists
136
	 *  @param  int             $printable          Is extrafield displayed on PDF
137
	 *  @param	array			$moreparams			More parameters. Example: array('css'=>, 'csslist'=>Css on list, 'cssview'=>...)
138
	 *  @return int      							<=0 if KO, >0 if OK
139
	 */
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
183
	/**
184
	 *	Add a new optional attribute.
185
	 *  This is a private method. For public method, use addExtraField.
186
	 *
187
	 *	@param	string	$attrname			code of attribute
188
	 *  @param	int		$type				Type of attribute ('boolean', 'int', 'varchar', 'text', 'html', 'date', 'datehour','price','pricecy','phone','mail','password','url','select','checkbox', ...)
189
	 *  @param	string	$length				Size/length of attribute ('5', '24,8', ...)
190
	 *  @param  string	$elementtype        Element type ('member', 'product', 'thirdparty', 'contact', ...)
191
	 *  @param	int		$unique				Is field unique or not
192
	 *  @param	int		$required			Is field required or not
193
	 *  @param  string  $default_value		Default value for field (in database)
194
	 *  @param  array	$param				Params for field  (ex for select list : array('options'=>array('value'=>'label of option'))
195
	 *  @param	string	$perms				Permission
196
	 *	@param	string	$list				Into list view by default
197
	 *  @param  string  $computed           Computed value
198
	 *  @param	string	$help				Help on tooltip
199
	 *  @param	array	$moreparams			More parameters. Example: array('css'=>, 'csslist'=>, 'cssview'=>...)
200
	 *  @return int      	           		<=0 if KO, >0 if OK
201
	 */
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
279
	/**
280
	 *	Add description of a new optional attribute
281
	 *
282
	 *	@param	string			$attrname		code of attribute
283
	 *	@param	string			$label			label of attribute
284
	 *  @param	int				$type			Type of attribute ('int', 'varchar', 'text', 'html', 'date', 'datehour', 'float')
285
	 *  @param	int				$pos			Position of attribute
286
	 *  @param	string			$size			Size/length of attribute ('5', '24,8', ...)
287
	 *  @param  string			$elementtype	Element type ('member', 'product', 'thirdparty', ...)
288
	 *  @param	int				$unique			Is field unique or not
289
	 *  @param	int				$required		Is field required or not
290
	 *  @param  array|string	$param			Params for field  (ex for select list : array('options' => array(value'=>'label of option')) )
291
	 *  @param  int				$alwayseditable	Is attribute always editable regardless of the document status
292
	 *  @param	string			$perms			Permission to check
293
	 *  @param	string			$list			Visibily
294
	 *  @param	string			$help			Help on tooltip
295
	 *  @param  string          $default        Default value (in database. use the default_value feature for default value on screen).
296
	 *  @param  string          $computed       Computed value
297
	 *  @param  string          $entity     	Entity of extrafields
298
	 *  @param	string			$langfile		Language file
299
	 *  @param  string  		$enabled  		Condition to have the field enabled or not
300
	 *  @param	int				$totalizable	Is a measure. Must show a total on lists
301
	 *  @param  int             $printable      Is extrafield displayed on PDF
302
	 *  @param	array			$moreparams		More parameters. Example: array('css'=>, 'csslist'=>, 'cssview'=>...)
303
	 *  @return	int								<=0 if KO, >0 if OK
304
	 *  @throws Exception
305
	 */
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
430
	/**
431
	 *	Delete an optional attribute
432
	 *
433
	 *	@param	string	$attrname		Code of attribute to delete
434
	 *  @param  string	$elementtype    Element type ('member', 'product', 'thirdparty', 'contact', ...)
435
	 *  @return int              		< 0 if KO, 0 if nothing is done, 1 if OK
436
	 */
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
488
	/**
489
	 *	Delete description of an optional attribute
490
	 *
491
	 *	@param	string	$attrname			Code of attribute to delete
492
	 *  @param  string	$elementtype        Element type ('member', 'product', 'thirdparty', ...)
493
	 *  @return int              			< 0 if KO, 0 if nothing is done, 1 if OK
494
	 */
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
526
	/**
527
	 * 	Modify type of a personalized attribute
528
	 *
529
	 *  @param	string	$attrname			Name of attribute
530
	 *  @param	string	$label				Label of attribute
531
	 *  @param	string	$type				Type of attribute ('boolean', 'int', 'varchar', 'text', 'html', 'date', 'datehour','price','phone','mail','password','url','select','checkbox', ...)
532
	 *  @param	int		$length				Length of attribute
533
	 *  @param  string	$elementtype        Element type ('member', 'product', 'thirdparty', 'contact', ...)
534
	 *  @param	int		$unique				Is field unique or not
535
	 *  @param	int		$required			Is field required or not
536
	 *  @param	int		$pos				Position of attribute
537
	 *  @param  array	$param				Params for field (ex for select list : array('options' => array(value'=>'label of option')) )
538
	 *  @param  int		$alwayseditable		Is attribute always editable regardless of the document status
539
	 *  @param	string	$perms				Permission to check
540
	 *  @param	string	$list				Visibility
541
	 *  @param	string	$help				Help on tooltip
542
	 *  @param  string  $default            Default value (in database. use the default_value feature for default value on screen).
543
	 *  @param  string  $computed           Computed value
544
	 *  @param  string  $entity	            Entity of extrafields
545
	 *  @param	string	$langfile			Language file
546
	 *  @param  string  $enabled  			Condition to have the field enabled or not
547
	 *  @param  int     $totalizable        Is extrafield totalizable on list
548
	 *  @param  int     $printable        	Is extrafield displayed on PDF
549
	 *  @param	array	$moreparams			More parameters. Example: array('css'=>, 'csslist'=>, 'cssview'=>...)
550
	 * 	@return	int							>0 if OK, <=0 if KO
551
	 *  @throws Exception
552
	 */
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);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $lengthdb does not seem to be defined for all execution paths leading up to this point.
Loading history...
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
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $action seems to be never defined.
Loading history...
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') {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.
Loading history...
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
651
	/**
652
	 *  Modify description of personalized attribute
653
	 *
654
	 *  @param	string	$attrname			Name of attribute
655
	 *  @param	string	$label				Label of attribute
656
	 *  @param  string	$type               Type of attribute
657
	 *  @param  int		$size		        Length of attribute
658
	 *  @param  string	$elementtype		Element type ('member', 'product', 'thirdparty', ...)
659
	 *  @param	int		$unique				Is field unique or not
660
	 *  @param	int		$required			Is field required or not
661
	 *  @param	int		$pos				Position of attribute
662
	 *  @param  array	$param				Params for field  (ex for select list : array('options' => array(value'=>'label of option')) )
663
	 *  @param  int		$alwayseditable		Is attribute always editable regardless of the document status
664
	 *  @param	string	$perms				Permission to check
665
	 *  @param	string	$list				Visiblity
666
	 *  @param	string	$help				Help on tooltip.
667
	 *  @param  string  $default            Default value (in database. use the default_value feature for default value on screen).
668
	 *  @param  string  $computed           Computed value
669
	 *  @param  string  $entity     		Entity of extrafields
670
	 *  @param	string	$langfile			Language file
671
	 *  @param  string  $enabled  			Condition to have the field enabled or not
672
	 *  @param  int     $totalizable        Is extrafield totalizable on list
673
	 *  @param  int     $printable        	Is extrafield displayed on PDF
674
	 *  @param	array	$moreparams			More parameters. Example: array('css'=>, 'csslist'=>, 'cssview'=>...)
675
	 *  @return	int							<=0 if KO, >0 if OK
676
	 *  @throws Exception
677
	 */
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
823
	/**
824
	 * 	Load array this->attributes
825
	 *
826
	 * 	@param	string		$elementtype		Type of element ('' = all or $object->table_element like 'adherent', 'commande', 'thirdparty', 'facture', 'propal', 'product', ...).
827
	 * 	@param	boolean		$forceload			Force load of extra fields whatever is status of cache.
828
	 * 	@return	array							Array of attributes keys+label for all extra fields.
829
	 */
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
919
	/**
920
	 * Return HTML string to put an input field into a page
921
	 * Code very similar with showInputField of common object
922
	 *
923
	 * @param  string        $key            		Key of attribute
924
	 * @param  string|array  $value 			    Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value); for dates in filter mode, a range array('start'=><timestamp>, 'end'=><timestamp>) should be provided
925
	 * @param  string        $moreparam      		To add more parameters on html input tag
926
	 * @param  string        $keysuffix      		Prefix string to add after name and id of field (can be used to avoid duplicate names)
927
	 * @param  string        $keyprefix      		Suffix string to add before name and id of field (can be used to avoid duplicate names)
928
	 * @param  string        $morecss        		More css (to defined size of field. Old behaviour: may also be a numeric)
929
	 * @param  int           $objectid       		Current object id
930
	 * @param  string        $extrafieldsobjectkey	The key to use to store retreived data (for example $object->table_element)
931
	 * @param  string        $mode                  1=Used for search filters
932
	 * @return string
933
	 */
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
1569
	/**
1570
	 * Return HTML string to put an output field into a page
1571
	 *
1572
	 * @param   string	$key            		Key of attribute
1573
	 * @param   string	$value          		Value to show
1574
	 * @param	string	$moreparam				To add more parameters on html input tag (only checkbox use html input for output rendering)
1575
	 * @param	string	$extrafieldsobjectkey	Required (for example $object->table_element).
1576
	 * @return	string							Formated value
1577
	 */
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
1919
	/**
1920
	 * Return the CSS to use for this extrafield into list
1921
	 *
1922
	 * @param   string	$key            		Key of attribute
1923
	 * @param	string	$extrafieldsobjectkey	If defined, use the new method to get extrafields data
1924
	 * @return	string							Formated value
1925
	 */
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
1956
	/**
1957
	 * Return HTML string to print separator extrafield
1958
	 *
1959
	 * @param   string	$key            Key of attribute
1960
	 * @param	object	$object			Object
1961
	 * @param	int		$colspan		Value of colspan to use (it must includes the first column with title)
1962
	 * @param	string	$display_type	"card" for form display, "line" for document line display (extrafields on propal line, order line, etc...)
1963
	 * @param 	string  $mode           Show output ('view') or input ('create' or 'edit') for extrafield
1964
	 * @return 	string					HTML code with line for separator
1965
	 */
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 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
2054
	/**
2055
	 * Fill array_options property of object by extrafields value (using for data sent by forms)
2056
	 *
2057
	 * @param   array|null	$extralabels    	Deprecated (old $array of extrafields, now set this to null)
2058
	 * @param   object		$object         	Object
2059
	 * @param	string		$onlykey			Only some keys are filled:
2060
	 *                      	            	'string' => When we make update of only one extrafield ($action = 'update_extras'), calling page can set this to avoid to have other extrafields being reset.
2061
	 *                          	        	'@GETPOSTISSET' => When we make update of several extrafields ($action = 'update'), calling page can set this to avoid to have fields not into POST being reset.
2062
	 * @param	int			$todefaultifmissing 1=Set value to the default value in database if value is mandatory and missing
2063
	 * @return	int								1 if array_options set, 0 if no value, -1 if error (field required missing for example)
2064
	 */
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)) {
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
2197
	/**
2198
	 * return array_options array of data of extrafields value of object sent by a search form
2199
	 *
2200
	 * @param  array|string		$extrafieldsobjectkey  	array of extrafields (old usage) or value of object->table_element (new usage)
2201
	 * @param  string			$keyprefix      		Prefix string to add into name and id of field (can be used to avoid duplicate names)
2202
	 * @param  string			$keysuffix      		Suffix string to add into name and id of field (can be used to avoid duplicate names)
2203
	 * @return array|int								array_options set or 0 if no value
2204
	 */
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
}
2320