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

ExtraFields::getOptionalsFromPost()   F

Complexity

Conditions 30
Paths 136

Size

Total Lines 113
Code Lines 78

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 30
eloc 78
c 1
b 0
f 0
nc 136
nop 3
dl 0
loc 113
rs 3.8666

How to fix   Long Method    Complexity   

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:

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