Completed
Branch develop (bb7c03)
by
unknown
34:20
created

ExtraFields   D

Complexity

Total Complexity 343

Size/Duplication

Total Lines 1764
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
dl 0
loc 1764
rs 4.4102
c 0
b 0
f 0
wmc 343
lcom 1
cbo 3

15 Methods

Rating   Name   Duplication   Size   Complexity  
C delete() 0 50 11
C delete_label() 0 32 7
F update() 0 83 26
A __construct() 0 17 1
C addExtraField() 0 32 12
F create() 0 68 24
F create_label() 0 81 17
F update_label() 0 89 17
D fetch_name_optionals_label() 0 99 20
F showInputField() 0 513 122
F showOutputField() 0 288 59
C getAlignFlag() 0 39 8
A showSeparator() 0 5 1
C setOptionalsFromPost() 0 59 12
B getOptionalsFromPost() 0 43 6

How to fix   Complexity   

Complex Class

Complex classes like ExtraFields often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ExtraFields, and based on these observations, apply Extract Interface, too.

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
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 3 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25
 */
26
27
/**
28
 * 	\file 		htdocs/core/class/extrafields.class.php
29
 *	\ingroup    core
30
 *	\brief      File of class to manage extra fields
31
 */
32
33
34
/**
35
 *	Class to manage standard extra fields
36
 */
37
class ExtraFields
38
{
39
	var $db;
40
41
	// type of element (for what object is the extrafield)
42
	var $attribute_elementtype;
43
44
	// Array with type of the extra field
45
	var $attribute_type;
46
	// Array with label of extra field
47
	var $attribute_label;
48
	// Array with size of extra field
49
	var $attribute_size;
50
	// array with list of possible values for some types of extra fields
51
	var $attribute_choice;
52
	// Array to store compute formula for computed fields
53
	var $attribute_computed;
54
	// Array to store default value
55
	var $attribute_default;
56
	// Array to store if attribute is unique or not
57
	var $attribute_unique;
58
	// Array to store if attribute is required or not
59
	var $attribute_required;
60
	// Array to store parameters of attribute (used in select type)
61
	var $attribute_param;
62
	// Array to store position of attribute
63
	var $attribute_pos;
64
	// Array to store if attribute is editable regardless of the document status
65
	var $attribute_alwayseditable;
66
	// Array to store permission to check
67
	var $attribute_perms;
68
	// Array to store language file to translate label of values
69
	var $attribute_langfile;
70
	// Array to store if field is visible by default on list
71
	var $attribute_list;
72
	// Array to store if extra field is hidden
73
	var $attribute_hidden;		// warning, do not rely on this. If your module need a hidden data, it must use its own table.
74
75
	// New array to store extrafields definition
76
	var $attributes;
77
78
	var $error;
79
	var $errno;
80
81
82
	public static $type2label=array(
83
	'varchar'=>'String',
84
	'text'=>'TextLong',
85
	'int'=>'Int',
86
	'double'=>'Float',
87
	'date'=>'Date',
88
	'datetime'=>'DateAndTime',
89
	'boolean'=>'Boolean',
90
	'price'=>'ExtrafieldPrice',
91
	'phone'=>'ExtrafieldPhone',
92
	'mail'=>'ExtrafieldMail',
93
	'url'=>'ExtrafieldUrl',
94
	'password' => 'ExtrafieldPassword',
95
	'select' => 'ExtrafieldSelect',
96
	'sellist' => 'ExtrafieldSelectList',
97
	'radio' => 'ExtrafieldRadio',
98
	'checkbox' => 'ExtrafieldCheckBox',
99
	'chkbxlst' => 'ExtrafieldCheckBoxFromList',
100
	'link' => 'ExtrafieldLink',
101
	'separate' => 'ExtrafieldSeparator',
102
	);
103
104
105
	/**
106
	 *	Constructor
107
	 *
108
	 *  @param		DoliDB		$db      Database handler
109
	*/
110
	function __construct($db)
111
	{
112
		$this->db = $db;
113
		$this->error = array();
114
		$this->attribute_elementtype = array();
115
		$this->attribute_type = array();
116
		$this->attribute_label = array();
117
		$this->attribute_size = array();
118
		$this->attribute_computed = array();
119
		$this->attribute_default = array();
120
		$this->attribute_unique = array();
121
		$this->attribute_required = array();
122
		$this->attribute_perms = array();
123
		$this->attribute_langfile = array();
124
		$this->attribute_list = array();
125
		$this->attribute_hidden = array();
126
	}
127
128
	/**
129
	 *  Add a new extra field parameter
130
	 *
131
	 *  @param	string			$attrname           Code of attribute
132
	 *  @param  string			$label              label of attribute
133
	 *  @param  int				$type               Type of attribute ('boolean', 'int', 'text', 'varchar', 'date', 'datehour','price','phone','mail','password','url','select','checkbox', ...)
134
	 *  @param  int				$pos                Position of attribute
135
	 *  @param  string			$size               Size/length of attribute
136
	 *  @param  string			$elementtype        Element type ('member', 'product', 'thirdparty', ...)
137
	 *  @param	int				$unique				Is field unique or not
138
	 *  @param	int				$required			Is field required or not
139
	 *  @param	string			$default_value		Defaulted value (In database. use the default_value feature for default value on screen. Example: '', '0', 'null', 'avalue')
140
	 *  @param  array|string	$param				Params for field (ex for select list : array('options' => array(value'=>'label of option')) )
141
	 *  @param  int				$alwayseditable		Is attribute always editable regardless of the document status
142
	 *  @param	string			$perms				Permission to check
143
	 *  @param	int				$list				Visibilty
144
	 *  @param	int				$ishidden			Deprecated. Use visibility instead.
145
	 *  @param  string  		$computed           Computed value
146
	 *  @param  string  		$entity    		 	Entity of extrafields
147
	 *  @param  string  		$langfile  		 	Language file
148
	 *  @return int      							<=0 if KO, >0 if OK
149
	 */
150
	function addExtraField($attrname, $label, $type, $pos, $size, $elementtype, $unique=0, $required=0, $default_value='', $param='', $alwayseditable=0, $perms='', $list=-1, $ishidden=0, $computed='', $entity='', $langfile='')
151
	{
152
		if (empty($attrname)) return -1;
153
		if (empty($label)) return -1;
154
155
		if ($elementtype == 'thirdparty') $elementtype='societe';
156
		if ($elementtype == 'contact') $elementtype='socpeople';
157
158
		// Create field into database except for separator type which is not stored in database
159
		if ($type != 'separate')
160
		{
161
			$result=$this->create($attrname, $type, $size, $elementtype, $unique, $required, $default_value, $param, $perms, $list, $computed);
162
		}
163
		$err1=$this->errno;
164
		if ($result > 0 || $err1 == 'DB_ERROR_COLUMN_ALREADY_EXISTS' || $type == 'separate')
0 ignored issues
show
Bug introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
165
		{
166
			// Add declaration of field into table
167
			$result2=$this->create_label($attrname, $label, $type, $pos, $size, $elementtype, $unique, $required, $param, $alwayseditable, $perms, $list, $ishidden, $default, $computed, $entity, $langfile);
0 ignored issues
show
Bug introduced by
The variable $default does not exist. Did you mean $default_value?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
168
			$err2=$this->errno;
169
			if ($result2 > 0 || ($err1 == 'DB_ERROR_COLUMN_ALREADY_EXISTS' && $err2 == 'DB_ERROR_RECORD_ALREADY_EXISTS'))
170
			{
171
				$this->error='';
172
				$this->errno=0;
173
				return 1;
174
			}
175
			else return -2;
176
		}
177
		else
178
		{
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', 'text', 'varchar', 'date', 'datehour','price','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	int		$list				Into list view by default
197
	 *  @param  string  $computed           Computed value
198
	 *  @return int      	           		<=0 if KO, >0 if OK
199
	 */
200
	private function create($attrname, $type='varchar', $length=255, $elementtype='member', $unique=0, $required=0, $default_value='',$param='', $perms='', $list=0, $computed='')
201
	{
202
		if ($elementtype == 'thirdparty') $elementtype='societe';
203
		if ($elementtype == 'contact') $elementtype='socpeople';
204
205
		$table=$elementtype.'_extrafields';
206
		if ($elementtype == 'categorie') $table='categories_extrafields';
207
208
		if (! empty($attrname) && preg_match("/^\w[a-zA-Z0-9_]*$/",$attrname) && ! is_numeric($attrname))
209
		{
210
			if ($type=='boolean') {
211
				$typedb='int';
212
				$lengthdb='1';
213
			} elseif($type=='price') {
214
				$typedb='double';
215
				$lengthdb='24,8';
216
			} elseif($type=='phone') {
217
				$typedb='varchar';
218
				$lengthdb='20';
219
			} elseif($type=='mail') {
220
				$typedb='varchar';
221
				$lengthdb='128';
222
			} elseif($type=='url') {
223
				$typedb='varchar';
224
				$lengthdb='255';
225
			} elseif (($type=='select') || ($type=='sellist') || ($type=='radio') ||($type=='checkbox') ||($type=='chkbxlst')){
226
				$typedb='text';
227
				$lengthdb='';
228
			} elseif ($type=='link') {
229
				$typedb='int';
230
				$lengthdb='11';
231
			} elseif($type=='password') {
232
				$typedb='varchar';
233
				$lengthdb='50';
234
			} else {
235
				$typedb=$type;
236
				$lengthdb=$length;
237
				if ($type == 'varchar' && empty($lengthdb)) $lengthdb='255';
238
			}
239
			$field_desc = array(
240
			'type'=>$typedb,
241
			'value'=>$lengthdb,
242
			'null'=>($required?'NOT NULL':'NULL'),
243
			'default' => $default_value
244
			);
245
246
			$result=$this->db->DDLAddField(MAIN_DB_PREFIX.$table, $attrname, $field_desc);
247
			if ($result > 0)
248
			{
249
				if ($unique)
250
				{
251
					$sql="ALTER TABLE ".MAIN_DB_PREFIX.$table." ADD UNIQUE INDEX uk_".$table."_".$attrname." (".$attrname.")";
252
					$resql=$this->db->query($sql,1,'dml');
253
				}
254
				return 1;
255
			}
256
			else
257
			{
258
				$this->error=$this->db->lasterror();
259
				$this->errno=$this->db->lasterrno();
260
				return -1;
261
			}
262
		}
263
		else
264
		{
265
			return 0;
266
		}
267
	}
268
269
	/**
270
	 *	Add description of a new optional attribute
271
	 *
272
	 *	@param	string			$attrname		code of attribute
273
	 *	@param	string			$label			label of attribute
274
	 *  @param	int				$type			Type of attribute ('int', 'text', 'varchar', 'date', 'datehour', 'float')
275
	 *  @param	int				$pos			Position of attribute
276
	 *  @param	string			$size			Size/length of attribute ('5', '24,8', ...)
277
	 *  @param  string			$elementtype	Element type ('member', 'product', 'thirdparty', ...)
278
	 *  @param	int				$unique			Is field unique or not
279
	 *  @param	int				$required		Is field required or not
280
	 *  @param  array|string	$param			Params for field  (ex for select list : array('options' => array(value'=>'label of option')) )
281
	 *  @param  int				$alwayseditable	Is attribute always editable regardless of the document status
282
	 *  @param	string			$perms			Permission to check
283
	 *  @param	int				$list			Visibily
284
	 *  @param	int				$ishidden		Deprecated. Use visibility instead.
285
	 *  @param  string          $default        Default value (in database. use the default_value feature for default value on screen).
286
	 *  @param  string          $computed       Computed value
287
	 *  @param  string          $entity     	Entity of extrafields
288
	 *  @param	string			$langfile		Language file
289
	 *  @return	int								<=0 if KO, >0 if OK
290
	 */
291
	private function create_label($attrname, $label='', $type='', $pos=0, $size=0, $elementtype='member', $unique=0, $required=0, $param='', $alwayseditable=0, $perms='', $list=-1, $ishidden=0, $default='', $computed='',$entity='', $langfile='')
292
	{
293
		global $conf,$user;
294
295
		if ($elementtype == 'thirdparty') $elementtype='societe';
296
		if ($elementtype == 'contact') $elementtype='socpeople';
297
298
		// Clean parameters
299
		if (empty($pos)) $pos=0;
300
		if (empty($list)) $list=0;
301
302
		if (! empty($attrname) && preg_match("/^\w[a-zA-Z0-9-_]*$/",$attrname) && ! is_numeric($attrname))
303
		{
304
			if(is_array($param) && count($param) > 0)
305
			{
306
				$params = $this->db->escape(serialize($param));
307
			}
308
			elseif (strlen($param) > 0)
309
			{
310
				$params = trim($param);
311
			}
312
			else
313
			{
314
				$params='';
315
			}
316
317
			$sql = "INSERT INTO ".MAIN_DB_PREFIX."extrafields(";
318
			$sql.= " name,";
319
			$sql.= " label,";
320
			$sql.= " type,";
321
			$sql.= " pos,";
322
			$sql.= " size,";
323
			$sql.= " entity,";
324
			$sql.= " elementtype,";
325
			$sql.= " fieldunique,";
326
			$sql.= " fieldrequired,";
327
			$sql.= " param,";
328
			$sql.= " alwayseditable,";
329
			$sql.= " perms,";
330
			$sql.= " langs,";
331
			$sql.= " list,";
332
			$sql.= " fielddefault,";
333
			$sql.= " fieldcomputed,";
334
			$sql.= " fk_user_author,";
335
			$sql.= " fk_user_modif,";
336
			$sql.= " datec";
337
			$sql.= " )";
338
			$sql.= " VALUES('".$attrname."',";
339
			$sql.= " '".$this->db->escape($label)."',";
340
			$sql.= " '".$type."',";
341
			$sql.= " '".$pos."',";
342
			$sql.= " '".$size."',";
343
			$sql.= " ".($entity===''?$conf->entity:$entity).",";
344
			$sql.= " '".$elementtype."',";
345
			$sql.= " '".$unique."',";
346
			$sql.= " '".$required."',";
347
			$sql.= " '".$params."',";
348
			$sql.= " '".$alwayseditable."',";
349
			$sql.= " ".($perms?"'".$this->db->escape($perms)."'":"null").",";
350
			$sql.= " ".($langfile?"'".$this->db->escape($langfile)."'":"null").",";
351
			$sql.= " ".$list.",";
352
			$sql.= " ".($default?"'".$this->db->escape($default)."'":"null").",";
353
			$sql.= " ".($computed?"'".$this->db->escape($computed)."'":"null").",";
354
			$sql .= " " . $user->id . ",";
355
			$sql .= " " . $user->id . ",";
356
			$sql .= "'" . $this->db->idate(dol_now()) . "'";
357
			$sql.=')';
358
359
			dol_syslog(get_class($this)."::create_label", LOG_DEBUG);
360
			if ($this->db->query($sql))
361
			{
362
				return 1;
363
			}
364
			else
365
			{
366
				$this->error=$this->db->lasterror();
367
				$this->errno=$this->db->lasterrno();
368
				return -1;
369
			}
370
		}
371
	}
372
373
	/**
374
	 *	Delete an optional attribute
375
	 *
376
	 *	@param	string	$attrname		Code of attribute to delete
377
	 *  @param  string	$elementtype    Element type ('member', 'product', 'thirdparty', 'contact', ...)
378
	 *  @return int              		< 0 if KO, 0 if nothing is done, 1 if OK
379
	 */
380
	function delete($attrname, $elementtype='member')
381
	{
382
		if ($elementtype == 'thirdparty') $elementtype='societe';
383
		if ($elementtype == 'contact') $elementtype='socpeople';
384
385
		$table=$elementtype.'_extrafields';
386
		if ($elementtype == 'categorie') $table='categories_extrafields';
387
388
		$error=0;
389
390
		if (! empty($attrname) && preg_match("/^\w[a-zA-Z0-9-_]*$/",$attrname))
391
		{
392
			$result=$this->delete_label($attrname,$elementtype);
393
			if ($result < 0)
394
			{
395
			    $this->error=$this->db->lasterror();
396
			    $error++;
397
			}
398
399
			if (! $error)
400
			{
401
        		$sql = "SELECT COUNT(rowid) as nb";
402
        		$sql.= " FROM ".MAIN_DB_PREFIX."extrafields";
403
        		$sql.= " WHERE elementtype = '".$elementtype."'";
404
        		$sql.= " AND name = '".$attrname."'";
405
        		//$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
406
                $resql = $this->db->query($sql);
407
                if ($resql)
408
                {
409
                    $obj = $this->db->fetch_object($resql);
410
                    if ($obj->nb <= 0)
411
                    {
412
            			$result=$this->db->DDLDropField(MAIN_DB_PREFIX.$table,$attrname);	// This also drop the unique key
413
            			if ($result < 0)
414
            			{
415
            				$this->error=$this->db->lasterror();
416
            				$error++;
417
            			}
418
                    }
419
                }
420
			}
421
422
			return $result;
423
		}
424
		else
425
		{
426
			return 0;
427
		}
428
429
	}
430
431
	/**
432
	 *	Delete description of an optional attribute
433
	 *
434
	 *	@param	string	$attrname			Code of attribute to delete
435
	 *  @param  string	$elementtype        Element type ('member', 'product', 'thirdparty', ...)
436
	 *  @return int              			< 0 if KO, 0 if nothing is done, 1 if OK
437
	 */
438
	private function delete_label($attrname, $elementtype='member')
439
	{
440
		global $conf;
441
442
		if ($elementtype == 'thirdparty') $elementtype='societe';
443
		if ($elementtype == 'contact') $elementtype='socpeople';
444
445
		if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/",$attrname))
446
		{
447
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."extrafields";
448
			$sql.= " WHERE name = '".$attrname."'";
449
			$sql.= " AND entity IN  (0,".$conf->entity.')';
450
			$sql.= " AND elementtype = '".$elementtype."'";
451
452
			dol_syslog(get_class($this)."::delete_label", LOG_DEBUG);
453
			$resql=$this->db->query($sql);
454
			if ($resql)
455
			{
456
				return 1;
457
			}
458
			else
459
			{
460
				print dol_print_error($this->db);
461
				return -1;
462
			}
463
		}
464
		else
465
		{
466
			return 0;
467
		}
468
469
	}
470
471
	/**
472
	 * 	Modify type of a personalized attribute
473
	 *
474
	 *  @param	string	$attrname			Name of attribute
475
	 *  @param	string	$label				Label of attribute
476
	 *  @param	string	$type				Type of attribute ('boolean', 'int', 'text', 'varchar', 'date', 'datehour','price','phone','mail','password','url','select','checkbox', ...)
477
	 *  @param	int		$length				Length of attribute
478
	 *  @param  string	$elementtype        Element type ('member', 'product', 'thirdparty', 'contact', ...)
479
	 *  @param	int		$unique				Is field unique or not
480
	 *  @param	int		$required			Is field required or not
481
	 *  @param	int		$pos				Position of attribute
482
	 *  @param  array	$param				Params for field (ex for select list : array('options' => array(value'=>'label of option')) )
483
	 *  @param  int		$alwayseditable		Is attribute always editable regardless of the document status
484
	 *  @param	string	$perms				Permission to check
485
	 *  @param	int		$list				Visibility
486
	 *  @param	int		$ishidden			Deprecated. Use  visiblity instead.
487
	 *  @param  string  $default            Default value (in database. use the default_value feature for default value on screen).
488
	 *  @param  string  $computed           Computed value
489
	 *  @param  string  $entity	            Entity of extrafields
490
	 *  @param	string	$langfile			Language file
491
	 * 	@return	int							>0 if OK, <=0 if KO
492
	 */
493
	function update($attrname, $label, $type, $length, $elementtype, $unique=0, $required=0, $pos=0, $param='', $alwayseditable=0, $perms='', $list='', $ishidden=0, $default='', $computed='', $entity='', $langfile='')
494
	{
495
		if ($elementtype == 'thirdparty') $elementtype='societe';
496
		if ($elementtype == 'contact') $elementtype='socpeople';
497
498
		$table=$elementtype.'_extrafields';
499
		if ($elementtype == 'categorie') $table='categories_extrafields';
500
501
		if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/",$attrname))
502
		{
503
			if ($type=='boolean') {
504
				$typedb='int';
505
				$lengthdb='1';
506
			} elseif($type=='price') {
507
				$typedb='double';
508
				$lengthdb='24,8';
509
			} elseif($type=='phone') {
510
				$typedb='varchar';
511
				$lengthdb='20';
512
			} elseif($type=='mail') {
513
				$typedb='varchar';
514
				$lengthdb='128';
515
			} elseif($type=='url') {
516
				$typedb='varchar';
517
				$lengthdb='255';
518
			} elseif (($type=='select') || ($type=='sellist') || ($type=='radio') || ($type=='checkbox') || ($type=='chkbxlst')) {
519
				$typedb='text';
520
				$lengthdb='';
521
			} elseif ($type=='link') {
522
				$typedb='int';
523
				$lengthdb='11';
524
			} elseif($type=='password') {
525
				$typedb='varchar';
526
				$lengthdb='50';
527
			} else {
528
				$typedb=$type;
529
				$lengthdb=$length;
530
			}
531
			$field_desc = array('type'=>$typedb, 'value'=>$lengthdb, 'null'=>($required?'NOT NULL':'NULL'), 'default'=>$default);
532
533
			if ($type != 'separate') // No table update when separate type
534
			{
535
				$result=$this->db->DDLUpdateField(MAIN_DB_PREFIX.$table, $attrname, $field_desc);
536
			}
537
			if ($result > 0 || $type == 'separate')
538
			{
539
				if ($label)
540
				{
541
					$result=$this->update_label($attrname,$label,$type,$length,$elementtype,$unique,$required,$pos,$param,$alwayseditable,$perms,$list,$ishidden,$default,$computed,$entity,$langfile);
542
				}
543
				if ($result > 0)
0 ignored issues
show
Bug introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
544
				{
545
					$sql='';
546
					if ($unique)
547
					{
548
						$sql="ALTER TABLE ".MAIN_DB_PREFIX.$table." ADD UNIQUE INDEX uk_".$table."_".$attrname." (".$attrname.")";
549
					}
550
					else
551
					{
552
						$sql="ALTER TABLE ".MAIN_DB_PREFIX.$table." DROP INDEX uk_".$table."_".$attrname;
553
					}
554
					dol_syslog(get_class($this).'::update', LOG_DEBUG);
555
					$resql=$this->db->query($sql,1,'dml');
556
					return 1;
557
				}
558
				else
559
				{
560
					$this->error=$this->db->lasterror();
561
					return -1;
562
				}
563
			}
564
			else
565
			{
566
				$this->error=$this->db->lasterror();
567
				return -1;
568
			}
569
		}
570
		else
571
		{
572
			return 0;
573
		}
574
575
	}
576
577
	/**
578
	 *  Modify description of personalized attribute
579
	 *
580
	 *  @param	string	$attrname			Name of attribute
581
	 *  @param	string	$label				Label of attribute
582
	 *  @param  string	$type               Type of attribute
583
	 *  @param  int		$size		        Length of attribute
584
	 *  @param  string	$elementtype		Element type ('member', 'product', 'thirdparty', ...)
585
	 *  @param	int		$unique				Is field unique or not
586
	 *  @param	int		$required			Is field required or not
587
	 *  @param	int		$pos				Position of attribute
588
	 *  @param  array	$param				Params for field  (ex for select list : array('options' => array(value'=>'label of option')) )
589
	 *  @param  int		$alwayseditable		Is attribute always editable regardless of the document status
590
	 *  @param	string	$perms				Permission to check
591
	 *  @param	int		$list				Visiblity
592
	 *  @param	int		$ishidden			Deprecated. Use visility instead.
593
	 *  @param  string  $default            Default value (in database. use the default_value feature for default value on screen).
594
	 *  @param  string  $computed           Computed value
595
	 *  @param  string  $entity     		Entity of extrafields
596
	 *  @param	string	$langfile			Language file
597
	 *  @return	int							<=0 if KO, >0 if OK
598
	 */
599
	private function update_label($attrname,$label,$type,$size,$elementtype,$unique=0,$required=0,$pos=0,$param='',$alwayseditable=0,$perms='',$list=0,$ishidden=0,$default='',$computed='',$entity='',$langfile='')
600
	{
601
		global $conf, $user;
602
		dol_syslog(get_class($this)."::update_label ".$attrname.", ".$label.", ".$type.", ".$size.", ".$elementtype.", ".$unique.", ".$required.", ".$pos.", ".$alwayseditable.", ".$perms.", ".$list.", ".$ishidden.", ".$default.", ".$computed.", ".$entity.", ".$langfile);
603
604
		// Clean parameters
605
		if ($elementtype == 'thirdparty') $elementtype='societe';
606
		if ($elementtype == 'contact') $elementtype='socpeople';
607
608
		if (empty($list)) $list=0;
609
610
		if (isset($attrname) && $attrname != '' && preg_match("/^\w[a-zA-Z0-9-_]*$/",$attrname))
611
		{
612
			$this->db->begin();
613
614
			if(is_array($param) && count($param) > 0)
615
			{
616
				$param = $this->db->escape(serialize($param));
617
			}
618
619
			$sql_del = "DELETE FROM ".MAIN_DB_PREFIX."extrafields";
620
			$sql_del.= " WHERE name = '".$attrname."'";
621
			$sql_del.= " AND entity = ".($entity===''?$conf->entity:$entity);
622
			$sql_del.= " AND elementtype = '".$elementtype."'";
623
624
			$resql1=$this->db->query($sql_del);
625
626
			$sql = "INSERT INTO ".MAIN_DB_PREFIX."extrafields(";
627
			$sql.= " name,";		// This is code
628
			$sql.= " entity,";
629
			$sql.= " label,";
630
			$sql.= " type,";
631
			$sql.= " size,";
632
			$sql.= " elementtype,";
633
			$sql.= " fieldunique,";
634
			$sql.= " fieldrequired,";
635
			$sql.= " perms,";
636
			$sql.= " langs,";
637
			$sql.= " pos,";
638
			$sql.= " alwayseditable,";
639
			$sql.= " param,";
640
			$sql.= " list,";
641
			$sql.= " fielddefault,";
642
			$sql.= " fieldcomputed,";
643
			$sql.= " fk_user_author,";
644
			$sql.= " fk_user_modif,";
645
			$sql.= " datec";
646
			$sql.= ") VALUES (";
647
			$sql.= "'".$attrname."',";
648
			$sql.= " ".($entity===''?$conf->entity:$entity).",";
649
			$sql.= " '".$this->db->escape($label)."',";
650
			$sql.= " '".$type."',";
651
			$sql.= " '".$size."',";
652
			$sql.= " '".$elementtype."',";
653
			$sql.= " '".$unique."',";
654
			$sql.= " '".$required."',";
655
			$sql.= " ".($perms?"'".$this->db->escape($perms)."'":"null").",";
656
			$sql.= " ".($langfile?"'".$this->db->escape($langfile)."'":"null").",";
657
			$sql.= " '".$pos."',";
658
			$sql.= " '".$alwayseditable."',";
659
			$sql.= " '".$param."',";
660
			$sql.= " ".$list.", ";
661
			$sql.= " ".(($default!='')?"'".$this->db->escape($default)."'":"null").",";
662
			$sql.= " ".($computed?"'".$this->db->escape($computed)."'":"null").",";
663
			$sql .= " " . $user->id . ",";
664
			$sql .= " " . $user->id . ",";
665
			$sql .= "'" . $this->db->idate(dol_now()) . "'";
666
			$sql.= ")";
667
668
			$resql2=$this->db->query($sql);
669
670
			if ($resql1 && $resql2)
671
			{
672
				$this->db->commit();
673
				return 1;
674
			}
675
			else
676
			{
677
				$this->db->rollback();
678
				print dol_print_error($this->db);
679
				return -1;
680
			}
681
		}
682
		else
683
		{
684
			return 0;
685
		}
686
687
	}
688
689
690
	/**
691
	 * 	Load array this->attributes, or old this->attribute_xxx like attribute_label, attribute_type, ...
692
	 *
693
	 * 	@param	string		$elementtype		Type of element ('adherent', 'commande', 'thirdparty', 'facture', 'propal', 'product', ...).
694
	 * 	@param	boolean		$forceload			Force load of extra fields whatever is option MAIN_EXTRAFIELDS_DISABLED. Deprecated. Should not be required.
695
	 * 	@return	array							Array of attributes keys+label for all extra fields.
696
	 */
697
	function fetch_name_optionals_label($elementtype,$forceload=false)
698
	{
699
		global $conf;
700
701
		if (empty($elementtype) ) return array();
702
703
		if ($elementtype == 'thirdparty') $elementtype='societe';
704
		if ($elementtype == 'contact') $elementtype='socpeople';
705
706
		$array_name_label=array();
707
708
		// To avoid conflicts with external modules. TODO Remove this.
709
		if (!$forceload && !empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) return $array_name_label;
710
711
		// We should not have several time this log. If we have, there is some optimization to do by calling a simple $object->fetch_optionals() that include cache management.
712
		dol_syslog("fetch_name_optionals_label elementtype=".$elementtype);
713
714
		$sql = "SELECT rowid,name,label,type,size,elementtype,fieldunique,fieldrequired,param,pos,alwayseditable,perms,langs,list,fielddefault,fieldcomputed";
715
		$sql .= ",entity";
716
		$sql.= " FROM ".MAIN_DB_PREFIX."extrafields";
717
		$sql.= " WHERE entity IN (0,".$conf->entity.")";
718
		if ($elementtype) $sql.= " AND elementtype = '".$elementtype."'";
719
		$sql.= " ORDER BY pos";
720
721
		$resql=$this->db->query($sql);
722
		if ($resql)
723
		{
724
			if ($this->db->num_rows($resql))
725
			{
726
				while ($tab = $this->db->fetch_object($resql))
727
				{
728
					// We can add this attribute to object. TODO Remove this and return $this->attributes[$elementtype]['label']
729
					if ($tab->type != 'separate')
730
					{
731
						$array_name_label[$tab->name]=$tab->label;
732
					}
733
734
					// Old usage
735
					$this->attribute_type[$tab->name]=$tab->type;
736
					$this->attribute_label[$tab->name]=$tab->label;
737
					$this->attribute_size[$tab->name]=$tab->size;
738
					$this->attribute_elementtype[$tab->name]=$tab->elementtype;
739
					$this->attribute_default[$tab->name]=$tab->fielddefault;
740
					$this->attribute_computed[$tab->name]=$tab->fieldcomputed;
741
					$this->attribute_unique[$tab->name]=$tab->fieldunique;
742
					$this->attribute_required[$tab->name]=$tab->fieldrequired;
743
					$this->attribute_param[$tab->name]=($tab->param ? unserialize($tab->param) : '');
744
					$this->attribute_pos[$tab->name]=$tab->pos;
745
					$this->attribute_alwayseditable[$tab->name]=$tab->alwayseditable;
746
					$this->attribute_perms[$tab->name]=(strlen($tab->perms) == 0 ? 1 : $tab->perms);
747
					$this->attribute_langfile[$tab->name]=$tab->langs;
748
					$this->attribute_list[$tab->name]=$tab->list;
749
					$this->attribute_entityid[$tab->name]=$tab->entity;
750
751
					// New usage
752
					$this->attributes[$tab->elementtype]['type'][$tab->name]=$tab->type;
753
					$this->attributes[$tab->elementtype]['label'][$tab->name]=$tab->label;
754
					$this->attributes[$tab->elementtype]['size'][$tab->name]=$tab->size;
755
					$this->attributes[$tab->elementtype]['elementtype'][$tab->name]=$tab->elementtype;
756
					$this->attributes[$tab->elementtype]['default'][$tab->name]=$tab->fielddefault;
757
					$this->attributes[$tab->elementtype]['computed'][$tab->name]=$tab->fieldcomputed;
758
					$this->attributes[$tab->elementtype]['unique'][$tab->name]=$tab->fieldunique;
759
					$this->attributes[$tab->elementtype]['required'][$tab->name]=$tab->fieldrequired;
760
					$this->attributes[$tab->elementtype]['param'][$tab->name]=($tab->param ? unserialize($tab->param) : '');
761
					$this->attributes[$tab->elementtype]['pos'][$tab->name]=$tab->pos;
762
					$this->attributes[$tab->elementtype]['alwayseditable'][$tab->name]=$tab->alwayseditable;
763
					$this->attributes[$tab->elementtype]['perms'][$tab->name]=(strlen($tab->perms) == 0 ? 1 : $tab->perms);
764
					$this->attributes[$tab->elementtype]['langfile'][$tab->name]=$tab->langs;
765
					$this->attributes[$tab->elementtype]['list'][$tab->name]=$tab->list;
766
					$this->attributes[$tab->elementtype]['entityid'][$tab->name]=$tab->entity;
767
768
					if (!empty($conf->multicompany->enabled))
769
					{
770
						$sql_entity_name='SELECT label FROM '.MAIN_DB_PREFIX.'entity WHERE rowid='.$tab->entity;
771
						$resql_entity_name=$this->db->query($sql_entity_name);
772
						if ($resql_entity_name)
773
						{
774
							if ($this->db->num_rows($resql_entity_name))
775
							{
776
								if ($obj = $this->db->fetch_object($resql_entity_name))
777
								{
778
									$this->attribute_entitylabel[$tab->name]=$obj->label;
779
									$this->attributes[$tab->elementtype]['entitylabel'][$tab->name]=$obj->label;
780
								}
781
							}
782
						}
783
					}
784
				}
785
			}
786
			if ($elementtype) $this->attributes[$elementtype]['loaded']=1;
787
		}
788
		else
789
		{
790
			$this->error=$this->db->lasterror();
791
			dol_syslog(get_class($this)."::fetch_name_optionals_label ".$this->error, LOG_ERR);
792
		}
793
794
		return $array_name_label;
795
	}
796
797
798
	/**
799
	 * Return HTML string to put an input field into a page
800
	 * Code very similar with showInputField of common object
801
	 *
802
	 * @param  string  $key            Key of attribute
803
	 * @param  string  $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)
804
	 * @param  string  $moreparam      To add more parametes on html input tag
805
	 * @param  string  $keysuffix      Prefix string to add after name and id of field (can be used to avoid duplicate names)
806
	 * @param  string  $keyprefix      Suffix string to add before name and id of field (can be used to avoid duplicate names)
807
	 * @param  mixed   $showsize       Value for css to define size. May also be a numeric.
808
	 * @param  int     $objectid       Current object id
809
	 * @return string
810
	 */
811
	function showInputField($key, $value, $moreparam='', $keysuffix='', $keyprefix='', $showsize=0, $objectid=0)
812
	{
813
		global $conf,$langs,$form;
814
815
		if (! is_object($form))
816
		{
817
			require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
818
			$form=new Form($this->db);
819
		}
820
821
		$out='';
822
823
		$keyprefix = $keyprefix.'options_';		// Because we work on extrafields
824
825
		$label=$this->attribute_label[$key];
826
		$type =$this->attribute_type[$key];
827
		$size =$this->attribute_size[$key];
828
		$elementtype=$this->attribute_elementtype[$key];	// Seems not used
829
		$default=$this->attribute_default[$key];
830
		$computed=$this->attribute_computed[$key];
831
		$unique=$this->attribute_unique[$key];
832
		$required=$this->attribute_required[$key];
833
		$param=$this->attribute_param[$key];
834
		$langfile=$this->attribute_langfile[$key];
835
		$list=$this->attribute_list[$key];
836
		$hidden=$this->attribute_hidden[$key];
837
838
		if ($computed)
839
		{
840
			if (! preg_match('/^search_/', $keyprefix)) return '<span class="opacitymedium">'.$langs->trans("AutomaticallyCalculated").'</span>';
841
			else return '';
842
		}
843
844
		if (empty($showsize))
845
		{
846
			if ($type == 'date')
847
			{
848
				//$showsize=10;
849
				$showsize = 'minwidth100imp';
850
			}
851
			elseif ($type == 'datetime')
852
			{
853
				//$showsize=19;
854
				$showsize = 'minwidth200imp';
855
			}
856
			elseif (in_array($type,array('int','integer','double','price')))
857
			{
858
				//$showsize=10;
859
				$showsize = 'maxwidth75';
860
			}
861
			elseif ($type == 'url')
862
			{
863
				$showsize='minwidth400';
864
			}
865
			elseif ($type == 'boolean')
866
			{
867
				$showsize='';
868
			}
869
			else
870
			{
871
				if (round($size) < 12)
872
				{
873
					$showsize = 'minwidth100';
874
				}
875
				else if (round($size) <= 48)
876
				{
877
					$showsize = 'minwidth200';
878
				}
879
				else
880
				{
881
					//$showsize=48;
882
					$showsize = 'minwidth400';
883
				}
884
			}
885
		}
886
887
		if (in_array($type,array('date','datetime')))
888
		{
889
			$tmp=explode(',',$size);
890
			$newsize=$tmp[0];
891
892
			$showtime = in_array($type,array('datetime')) ? 1 : 0;
893
894
			// Do not show current date when field not required (see select_date() method)
895
			if (!$required && $value == '') $value = '-1';
896
897
			// TODO Must also support $moreparam
898
			$out = $form->select_date($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 1, 0, 1);
899
		}
900
		elseif (in_array($type,array('int','integer')))
901
		{
902
			$tmp=explode(',',$size);
903
			$newsize=$tmp[0];
904
			$out='<input type="text" class="flat '.$showsize.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" maxlength="'.$newsize.'" value="'.dol_escape_htmltag($value).'"'.($moreparam?$moreparam:'').'>';
905
		}
906
		elseif (preg_match('/varchar/', $type))
907
		{
908
			$out='<input type="text" class="flat '.$showsize.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" maxlength="'.$size.'" value="'.dol_escape_htmltag($value).'"'.($moreparam?$moreparam:'').'>';
909
		}
910
		elseif (in_array($type, array('mail', 'phone', 'url')))
911
		{
912
			$out='<input type="text" class="flat '.$showsize.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam?$moreparam:'').'>';
913
		}
914
		elseif ($type == 'text')
915
		{
916
			if (! preg_match('/search_/', $keyprefix))		// If keyprefix is search_ or search_options_, we must just use a simple text field
917
			{
918
				require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
919
				$doleditor=new DolEditor($keyprefix.$key.$keysuffix,$value,'',200,'dolibarr_notes','In',false,false,! empty($conf->fckeditor->enabled) && $conf->global->FCKEDITOR_ENABLE_SOCIETE,ROWS_5,'90%');
920
				$out=$doleditor->Create(1);
921
			}
922
			else
923
			{
924
				$out='<input type="text" class="flat '.$showsize.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam?$moreparam:'').'>';
925
			}
926
		}
927
		elseif ($type == 'boolean')
928
		{
929
			$checked='';
930
			if (!empty($value)) {
931
				$checked=' checked value="1" ';
932
			} else {
933
				$checked=' value="1" ';
934
			}
935
			$out='<input type="checkbox" class="flat '.$showsize.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.$checked.' '.($moreparam?$moreparam:'').'>';
936
		}
937
		elseif ($type == 'price')
938
		{
939
			if (!empty($value)) {		// $value in memory is a php numeric, we format it into user number format.
940
				$value=price($value);
941
			}
942
			$out='<input type="text" class="flat '.$showsize.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam?$moreparam:'').'> '.$langs->getCurrencySymbol($conf->currency);
943
		}
944
		elseif ($type == 'double')
945
		{
946
			if (!empty($value)) {		// $value in memory is a php numeric, we format it into user number format.
947
				$value=price($value);
948
			}
949
			$out='<input type="text" class="flat '.$showsize.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam?$moreparam:'').'> ';
950
		}
951
		elseif ($type == 'select')
952
		{
953
			$out = '';
954
			if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->MAIN_EXTRAFIELDS_USE_SELECT2))
955
			{
956
				include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
957
				$out.= ajax_combobox($keyprefix.$key.$keysuffix, array(), 0);
958
			}
959
960
			$out.='<select class="flat '.$showsize.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam?$moreparam:'').'>';
961
			$out.='<option value="0">&nbsp;</option>';
962
			foreach ($param['options'] as $key => $val)
963
			{
964
				if ((string) $key == '') continue;
965
				list($val, $parent) = explode('|', $val);
966
				$out.='<option value="'.$key.'"';
967
				$out.= (((string) $value == (string) $key)?' selected':'');
968
				$out.= (!empty($parent)?' parent="'.$parent.'"':'');
969
				$out.='>'.$val.'</option>';
970
			}
971
			$out.='</select>';
972
		}
973
		elseif ($type == 'sellist')
974
		{
975
			$out = '';
976
			if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->MAIN_EXTRAFIELDS_USE_SELECT2))
977
			{
978
				include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
979
				$out.= ajax_combobox($keyprefix.$key.$keysuffix, array(), 0);
980
			}
981
982
			$out.='<select class="flat '.$showsize.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam?$moreparam:'').'>';
983
			if (is_array($param['options']))
984
			{
985
				$param_list=array_keys($param['options']);
986
				$InfoFieldList = explode(":", $param_list[0]);
987
				$parentName='';
988
				$parentField='';
989
				// 0 : tableName
990
				// 1 : label field name
991
				// 2 : key fields name (if differ of rowid)
992
				// 3 : key field parent (for dependent lists)
993
				// 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value
994
				$keyList=(empty($InfoFieldList[2])?'rowid':$InfoFieldList[2].' as rowid');
995
996
997
				if (count($InfoFieldList) > 4 && ! empty($InfoFieldList[4]))
998
				{
999
					if (strpos($InfoFieldList[4], 'extra.') !== false)
1000
					{
1001
						$keyList='main.'.$InfoFieldList[2].' as rowid';
1002
					} else {
1003
						$keyList=$InfoFieldList[2].' as rowid';
1004
					}
1005
				}
1006
				if (count($InfoFieldList) > 3 && ! empty($InfoFieldList[3]))
1007
				{
1008
					list($parentName, $parentField) = explode('|', $InfoFieldList[3]);
1009
					$keyList.= ', '.$parentField;
1010
				}
1011
1012
				$fields_label = explode('|',$InfoFieldList[1]);
1013
				if (is_array($fields_label))
1014
				{
1015
					$keyList .=', ';
1016
					$keyList .= implode(', ', $fields_label);
1017
				}
1018
1019
				$sqlwhere='';
1020
				$sql = 'SELECT '.$keyList;
1021
				$sql.= ' FROM '.MAIN_DB_PREFIX .$InfoFieldList[0];
1022
				if (!empty($InfoFieldList[4]))
1023
				{
1024
					// can use SELECT request
1025
					if (strpos($InfoFieldList[4], '$SEL$')!==false) {
1026
						$InfoFieldList[4]=str_replace('$SEL$','SELECT',$InfoFieldList[4]);
1027
					}
1028
1029
					// current object id can be use into filter
1030
					if (strpos($InfoFieldList[4], '$ID$')!==false && !empty($objectid)) {
1031
						$InfoFieldList[4]=str_replace('$ID$',$objectid,$InfoFieldList[4]);
1032
					} else {
1033
						$InfoFieldList[4]=str_replace('$ID$','0',$InfoFieldList[4]);
1034
					}
1035
					//We have to join on extrafield table
1036
					if (strpos($InfoFieldList[4], 'extra')!==false)
1037
					{
1038
						$sql.= ' as main, '.MAIN_DB_PREFIX .$InfoFieldList[0].'_extrafields as extra';
1039
						$sqlwhere.= ' WHERE extra.fk_object=main.'.$InfoFieldList[2]. ' AND '.$InfoFieldList[4];
1040
					}
1041
					else
1042
					{
1043
						$sqlwhere.= ' WHERE '.$InfoFieldList[4];
1044
					}
1045
				}
1046
				else
1047
				{
1048
					$sqlwhere.= ' WHERE 1=1';
1049
				}
1050
				// Some tables may have field, some other not. For the moment we disable it.
1051
				if (in_array($InfoFieldList[0],array('tablewithentity')))
1052
				{
1053
					$sqlwhere.= ' AND entity = '.$conf->entity;
1054
				}
1055
				$sql.=$sqlwhere;
1056
				//print $sql;
1057
1058
				$sql .= ' ORDER BY ' . implode(', ', $fields_label);
1059
1060
				dol_syslog(get_class($this).'::showInputField type=sellist', LOG_DEBUG);
1061
				$resql = $this->db->query($sql);
1062
				if ($resql)
1063
				{
1064
					$out.='<option value="0">&nbsp;</option>';
1065
					$num = $this->db->num_rows($resql);
1066
					$i = 0;
1067
					while ($i < $num)
1068
					{
1069
						$labeltoshow='';
1070
						$obj = $this->db->fetch_object($resql);
1071
1072
						// Several field into label (eq table:code|libelle:rowid)
1073
						$notrans = false;
1074
						$fields_label = explode('|',$InfoFieldList[1]);
1075
						if (is_array($fields_label))
1076
						{
1077
							$notrans = true;
1078
							foreach ($fields_label as $field_toshow)
1079
							{
1080
								$labeltoshow.= $obj->$field_toshow.' ';
1081
							}
1082
						}
1083
						else
1084
						{
1085
							$labeltoshow=$obj->{$InfoFieldList[1]};
1086
						}
1087
						$labeltoshow=dol_trunc($labeltoshow,45);
1088
1089
						if ($value == $obj->rowid)
1090
						{
1091
							foreach ($fields_label as $field_toshow)
1092
							{
1093
								$translabel=$langs->trans($obj->$field_toshow);
1094
								if ($translabel!=$obj->$field_toshow) {
1095
									$labeltoshow=dol_trunc($translabel,18).' ';
1096
								}else {
1097
									$labeltoshow=dol_trunc($obj->$field_toshow,18).' ';
1098
								}
1099
							}
1100
							$out.='<option value="'.$obj->rowid.'" selected>'.$labeltoshow.'</option>';
1101
						}
1102
						else
1103
						{
1104
							if (! $notrans)
1105
							{
1106
								$translabel=$langs->trans($obj->{$InfoFieldList[1]});
1107
								if ($translabel!=$obj->{$InfoFieldList[1]}) {
1108
									$labeltoshow=dol_trunc($translabel,18);
1109
								}
1110
								else {
1111
									$labeltoshow=dol_trunc($obj->{$InfoFieldList[1]},18);
1112
								}
1113
							}
1114
							if (empty($labeltoshow)) $labeltoshow='(not defined)';
1115
							if ($value==$obj->rowid)
1116
							{
1117
								$out.='<option value="'.$obj->rowid.'" selected>'.$labeltoshow.'</option>';
1118
							}
1119
1120
							if (!empty($InfoFieldList[3]) && $parentField)
1121
							{
1122
								$parent = $parentName.':'.$obj->{$parentField};
1123
							}
1124
1125
							$out.='<option value="'.$obj->rowid.'"';
1126
							$out.= ($value==$obj->rowid?' selected':'');
1127
							$out.= (!empty($parent)?' parent="'.$parent.'"':'');
1128
							$out.='>'.$labeltoshow.'</option>';
1129
						}
1130
1131
						$i++;
1132
					}
1133
					$this->db->free($resql);
1134
				}
1135
				else {
1136
					print 'Error in request '.$sql.' '.$this->db->lasterror().'. Check setup of extra parameters.<br>';
1137
				}
1138
			}
1139
			$out.='</select>';
1140
		}
1141
		elseif ($type == 'checkbox')
1142
		{
1143
			$value_arr=explode(',',$value);
1144
			$out=$form->multiselectarray($keyprefix.$key.$keysuffix, (empty($param['options'])?null:$param['options']), $value_arr, '', 0, '', 0, '100%');
1145
		}
1146
		elseif ($type == 'radio')
1147
		{
1148
			$out='';
1149
			foreach ($param['options'] as $keyopt => $val)
1150
			{
1151
				$out.='<input class="flat '.$showsize.'" type="radio" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam?$moreparam:'');
1152
				$out.=' value="'.$keyopt.'"';
1153
				$out.=' id="'.$keyprefix.$key.$keysuffix.'_'.$keyopt.'"';
1154
				$out.= ($value==$keyopt?'checked':'');
1155
				$out.='/><label for="'.$keyprefix.$key.$keysuffix.'_'.$keyopt.'">'.$val.'</label><br>';
1156
			}
1157
		}
1158
		elseif ($type == 'chkbxlst')
1159
		{
1160
			if (is_array($value)) {
1161
				$value_arr = $value;
1162
			}
1163
			else {
1164
				$value_arr = explode(',', $value);
1165
			}
1166
1167
			if (is_array($param['options'])) {
1168
				$param_list = array_keys($param['options']);
1169
				$InfoFieldList = explode(":", $param_list[0]);
1170
				$parentName='';
1171
				$parentField='';
1172
				// 0 : tableName
1173
				// 1 : label field name
1174
				// 2 : key fields name (if differ of rowid)
1175
				// 3 : key field parent (for dependent lists)
1176
				// 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value
1177
				$keyList = (empty($InfoFieldList[2]) ? 'rowid' : $InfoFieldList[2] . ' as rowid');
1178
1179
				if (count($InfoFieldList) > 3 && ! empty($InfoFieldList[3])) {
1180
					list ( $parentName, $parentField ) = explode('|', $InfoFieldList[3]);
1181
					$keyList .= ', ' . $parentField;
1182
				}
1183
				if (count($InfoFieldList) > 4 && ! empty($InfoFieldList[4])) {
1184
					if (strpos($InfoFieldList[4], 'extra.') !== false) {
1185
						$keyList = 'main.' . $InfoFieldList[2] . ' as rowid';
1186
					} else {
1187
						$keyList = $InfoFieldList[2] . ' as rowid';
1188
					}
1189
				}
1190
1191
				$fields_label = explode('|', $InfoFieldList[1]);
1192
				if (is_array($fields_label)) {
1193
					$keyList .= ', ';
1194
					$keyList .= implode(', ', $fields_label);
1195
				}
1196
1197
				$sqlwhere = '';
1198
				$sql = 'SELECT ' . $keyList;
1199
				$sql .= ' FROM ' . MAIN_DB_PREFIX . $InfoFieldList[0];
1200
				if (! empty($InfoFieldList[4])) {
1201
1202
					// can use SELECT request
1203
					if (strpos($InfoFieldList[4], '$SEL$')!==false) {
1204
						$InfoFieldList[4]=str_replace('$SEL$','SELECT',$InfoFieldList[4]);
1205
					}
1206
1207
					// current object id can be use into filter
1208
					if (strpos($InfoFieldList[4], '$ID$')!==false && !empty($objectid)) {
1209
						$InfoFieldList[4]=str_replace('$ID$',$objectid,$InfoFieldList[4]);
1210
					} else {
1211
						$InfoFieldList[4]=str_replace('$ID$','0',$InfoFieldList[4]);
1212
					}
1213
1214
					// We have to join on extrafield table
1215
					if (strpos($InfoFieldList[4], 'extra') !== false) {
1216
						$sql .= ' as main, ' . MAIN_DB_PREFIX . $InfoFieldList[0] . '_extrafields as extra';
1217
						$sqlwhere .= ' WHERE extra.fk_object=main.' . $InfoFieldList[2] . ' AND ' . $InfoFieldList[4];
1218
					} else {
1219
						$sqlwhere .= ' WHERE ' . $InfoFieldList[4];
1220
					}
1221
				} else {
1222
					$sqlwhere .= ' WHERE 1=1';
1223
				}
1224
				// Some tables may have field, some other not. For the moment we disable it.
1225
				if (in_array($InfoFieldList[0], array ('tablewithentity')))
1226
				{
1227
					$sqlwhere .= ' AND entity = ' . $conf->entity;
1228
				}
1229
				// $sql.=preg_replace('/^ AND /','',$sqlwhere);
1230
				// print $sql;
1231
1232
				$sql .= $sqlwhere;
1233
				dol_syslog(get_class($this) . '::showInputField type=chkbxlst',LOG_DEBUG);
1234
				$resql = $this->db->query($sql);
1235
				if ($resql) {
1236
					$num = $this->db->num_rows($resql);
1237
					$i = 0;
1238
1239
					$data=array();
1240
1241
					while ( $i < $num ) {
1242
						$labeltoshow = '';
1243
						$obj = $this->db->fetch_object($resql);
1244
1245
						$notrans = false;
1246
						// Several field into label (eq table:code|libelle:rowid)
1247
						$fields_label = explode('|', $InfoFieldList[1]);
1248
						if (is_array($fields_label)) {
1249
							$notrans = true;
1250
							foreach ( $fields_label as $field_toshow ) {
1251
								$labeltoshow .= $obj->$field_toshow . ' ';
1252
							}
1253
						} else {
1254
							$labeltoshow = $obj->{$InfoFieldList[1]};
1255
						}
1256
						$labeltoshow = dol_trunc($labeltoshow, 45);
1257
1258
						if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1259
							foreach ( $fields_label as $field_toshow ) {
1260
								$translabel = $langs->trans($obj->$field_toshow);
1261
								if ($translabel != $obj->$field_toshow) {
1262
									$labeltoshow = dol_trunc($translabel, 18) . ' ';
1263
								} else {
1264
									$labeltoshow = dol_trunc($obj->$field_toshow, 18) . ' ';
1265
								}
1266
							}
1267
1268
							$data[$obj->rowid]=$labeltoshow;
1269
1270
						} else {
1271
							if (! $notrans) {
1272
								$translabel = $langs->trans($obj->{$InfoFieldList[1]});
1273
								if ($translabel != $obj->{$InfoFieldList[1]}) {
1274
									$labeltoshow = dol_trunc($translabel, 18);
1275
								} else {
1276
									$labeltoshow = dol_trunc($obj->{$InfoFieldList[1]}, 18);
1277
								}
1278
							}
1279
							if (empty($labeltoshow))
1280
								$labeltoshow = '(not defined)';
1281
1282
								if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1283
									$data[$obj->rowid]=$labeltoshow;
1284
								}
1285
1286
								if (! empty($InfoFieldList[3]) && $parentField) {
1287
									$parent = $parentName . ':' . $obj->{$parentField};
1288
								}
1289
1290
								$data[$obj->rowid]=$labeltoshow;
1291
						}
1292
1293
						$i ++;
1294
					}
1295
					$this->db->free($resql);
1296
1297
					$out=$form->multiselectarray($keyprefix.$key.$keysuffix, $data, $value_arr, '', 0, '', 0, '100%');
1298
1299
				} else {
1300
					print 'Error in request ' . $sql . ' ' . $this->db->lasterror() . '. Check setup of extra parameters.<br>';
1301
				}
1302
			}
1303
		}
1304
		elseif ($type == 'link')
1305
		{
1306
			$param_list=array_keys($param['options']);				// $param_list='ObjectName:classPath'
1307
			$showempty=(($required && $default != '')?0:1);
1308
			$out=$form->selectForForms($param_list[0], $keyprefix.$key.$keysuffix, $value, $showempty);
1309
		}
1310
		elseif ($type == 'password')
1311
		{
1312
			// If prefix is 'search_', field is used as a filter, we use a common text field.
1313
			$out='<input type="'.($keyprefix=='search_'?'text':'password').'" class="flat '.$showsize.'" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam?$moreparam:'').'>';
1314
		}
1315
		if (!empty($hidden)) {
1316
			$out='<input type="hidden" value="'.$value.'" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'"/>';
1317
		}
1318
		/* Add comments
1319
		 if ($type == 'date') $out.=' (YYYY-MM-DD)';
1320
		 elseif ($type == 'datetime') $out.=' (YYYY-MM-DD HH:MM:SS)';
1321
		 */
1322
		return $out;
1323
	}
1324
1325
1326
	/**
1327
	 * Return HTML string to put an output field into a page
1328
	 *
1329
	 * @param   string	$key            Key of attribute
1330
	 * @param   string	$value          Value to show
1331
	 * @param	string	$moreparam		To add more parameters on html input tag (only checkbox use html input for output rendering)
1332
	 * @return	string					Formated value
1333
	 */
1334
	function showOutputField($key,$value,$moreparam='')
1335
	{
1336
		global $conf,$langs;
1337
1338
		$elementtype=$this->attribute_elementtype[$key];	// seems not used
1339
		$label=$this->attribute_label[$key];
1340
		$type=$this->attribute_type[$key];
1341
		$size=$this->attribute_size[$key];
1342
		$default=$this->attribute_default[$key];
1343
		$computed=$this->attribute_computed[$key];
1344
		$unique=$this->attribute_unique[$key];
1345
		$required=$this->attribute_required[$key];
1346
		$param=$this->attribute_param[$key];
1347
		$perms=$this->attribute_perms[$key];
1348
		$langfile=$this->attribute_langfile[$key];
1349
		$list=$this->attribute_list[$key];
1350
		$hidden=(($list == 0) ? 1 : 0);		// If zero, 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)
1351
1352
		if ($hidden) return '';		// This is a protection. If field is hidden, we should just not call this method.
1353
1354
		// If field is a computed field, value must become result of compute
1355
		if ($computed)
1356
		{
1357
		    // Make the eval of compute string
1358
		    //var_dump($computed);
1359
		    $value = dol_eval($computed, 1, 0);
1360
		}
1361
1362
		$showsize=0;
1363
		if ($type == 'date')
1364
		{
1365
			$showsize=10;
1366
			$value=dol_print_date($value, 'day', 'tzuser');
1367
		}
1368
		elseif ($type == 'datetime')
1369
		{
1370
			$showsize=19;
1371
			$value=dol_print_date($value, 'dayhour', 'tzuser');
1372
		}
1373
		elseif ($type == 'int')
1374
		{
1375
			$showsize=10;
1376
		}
1377
		elseif ($type == 'double')
1378
		{
1379
			if (!empty($value)) {
1380
				$value=price($value);
1381
			}
1382
		}
1383
		elseif ($type == 'boolean')
1384
		{
1385
			$checked='';
1386
			if (!empty($value)) {
1387
				$checked=' checked ';
1388
			}
1389
			$value='<input type="checkbox" '.$checked.' '.($moreparam?$moreparam:'').' readonly disabled>';
1390
		}
1391
		elseif ($type == 'mail')
1392
		{
1393
			$value=dol_print_email($value, 0, 0, 0, 64, 1, 1);
1394
		}
1395
		elseif ($type == 'url')
1396
		{
1397
			$value=dol_print_url($value,'_blank',32,1);
1398
		}
1399
		elseif ($type == 'phone')
1400
		{
1401
			$value=dol_print_phone($value, '', 0, 0, '', '&nbsp;', 1);
1402
		}
1403
		elseif ($type == 'price')
1404
		{
1405
			$value=price($value, 0, $langs, 0, 0, -1, $conf->currency);
1406
		}
1407
		elseif ($type == 'select')
1408
		{
1409
			$value=$param['options'][$value];
1410
		}
1411
		elseif ($type == 'sellist')
1412
		{
1413
			$param_list=array_keys($param['options']);
1414
			$InfoFieldList = explode(":", $param_list[0]);
1415
1416
			$selectkey="rowid";
1417
			$keyList='rowid';
1418
1419
			if (count($InfoFieldList)>=3)
1420
			{
1421
				$selectkey = $InfoFieldList[2];
1422
				$keyList=$InfoFieldList[2].' as rowid';
1423
			}
1424
1425
			$fields_label = explode('|',$InfoFieldList[1]);
1426
			if(is_array($fields_label)) {
1427
				$keyList .=', ';
1428
				$keyList .= implode(', ', $fields_label);
1429
			}
1430
1431
			$sql = 'SELECT '.$keyList;
1432
			$sql.= ' FROM '.MAIN_DB_PREFIX .$InfoFieldList[0];
1433
			if (strpos($InfoFieldList[4], 'extra')!==false)
1434
			{
1435
				$sql.= ' as main';
1436
			}
1437
			if ($selectkey=='rowid' && empty($value)) {
1438
				$sql.= " WHERE ".$selectkey."=0";
1439
			} elseif ($selectkey=='rowid') {
1440
				$sql.= " WHERE ".$selectkey."=".$this->db->escape($value);
1441
			}else {
1442
				$sql.= " WHERE ".$selectkey."='".$this->db->escape($value)."'";
1443
			}
1444
1445
			//$sql.= ' AND entity = '.$conf->entity;
1446
1447
			dol_syslog(get_class($this).':showOutputField:$type=sellist', LOG_DEBUG);
1448
			$resql = $this->db->query($sql);
1449
			if ($resql)
1450
			{
1451
				$value='';	// value was used, so now we reste it to use it to build final output
1452
1453
				$obj = $this->db->fetch_object($resql);
1454
1455
				// Several field into label (eq table:code|libelle:rowid)
1456
				$fields_label = explode('|',$InfoFieldList[1]);
1457
1458
				if(is_array($fields_label) && count($fields_label)>1)
1459
				{
1460
					foreach ($fields_label as $field_toshow)
1461
					{
1462
						$translabel='';
1463
						if (!empty($obj->$field_toshow)) {
1464
							$translabel=$langs->trans($obj->$field_toshow);
1465
						}
1466
						if ($translabel!=$field_toshow) {
1467
							$value.=dol_trunc($translabel,18).' ';
1468
						}else {
1469
							$value.=$obj->$field_toshow.' ';
1470
						}
1471
					}
1472
				}
1473
				else
1474
				{
1475
					$translabel='';
1476
					if (!empty($obj->{$InfoFieldList[1]})) {
1477
						$translabel=$langs->trans($obj->{$InfoFieldList[1]});
1478
					}
1479
					if ($translabel!=$obj->{$InfoFieldList[1]}) {
1480
						$value=dol_trunc($translabel,18);
1481
					}else {
1482
						$value=$obj->{$InfoFieldList[1]};
1483
					}
1484
				}
1485
			}
1486
			else dol_syslog(get_class($this).'::showOutputField error '.$this->db->lasterror(), LOG_WARNING);
1487
		}
1488
		elseif ($type == 'radio')
1489
		{
1490
			$value=$param['options'][$value];
1491
		}
1492
		elseif ($type == 'checkbox')
1493
		{
1494
			$value_arr=explode(',',$value);
1495
			$value='';
1496
			$toprint=array();
1497
			if (is_array($value_arr))
1498
			{
1499
				foreach ($value_arr as $keyval=>$valueval) {
1500
					$toprint[]='<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #aaa">'.$param['options'][$valueval].'</li>';
1501
				}
1502
			}
1503
			$value='<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
1504
		}
1505
		elseif ($type == 'chkbxlst')
1506
		{
1507
			$value_arr = explode(',', $value);
1508
1509
			$param_list = array_keys($param['options']);
1510
			$InfoFieldList = explode(":", $param_list[0]);
1511
1512
			$selectkey = "rowid";
1513
			$keyList = 'rowid';
1514
1515
			if (count($InfoFieldList) >= 3) {
1516
				$selectkey = $InfoFieldList[2];
1517
				$keyList = $InfoFieldList[2] . ' as rowid';
1518
			}
1519
1520
			$fields_label = explode('|', $InfoFieldList[1]);
1521
			if (is_array($fields_label)) {
1522
				$keyList .= ', ';
1523
				$keyList .= implode(', ', $fields_label);
1524
			}
1525
1526
			$sql = 'SELECT ' . $keyList;
1527
			$sql .= ' FROM ' . MAIN_DB_PREFIX . $InfoFieldList[0];
1528
			if (strpos($InfoFieldList[4], 'extra') !== false) {
1529
				$sql .= ' as main';
1530
			}
1531
			// $sql.= " WHERE ".$selectkey."='".$this->db->escape($value)."'";
1532
			// $sql.= ' AND entity = '.$conf->entity;
1533
1534
			dol_syslog(get_class($this) . ':showOutputField:$type=chkbxlst',LOG_DEBUG);
1535
			$resql = $this->db->query($sql);
1536
			if ($resql) {
1537
				$value = ''; // value was used, so now we reste it to use it to build final output
1538
				$toprint=array();
1539
				while ( $obj = $this->db->fetch_object($resql) ) {
1540
1541
					// Several field into label (eq table:code|libelle:rowid)
1542
					$fields_label = explode('|', $InfoFieldList[1]);
1543
					if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) {
1544
						if (is_array($fields_label) && count($fields_label) > 1) {
1545
							foreach ( $fields_label as $field_toshow ) {
1546
								$translabel = '';
1547
								if (! empty($obj->$field_toshow)) {
1548
									$translabel = $langs->trans($obj->$field_toshow);
1549
								}
1550
								if ($translabel != $field_toshow) {
1551
									$toprint[]='<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #aaa">'.dol_trunc($translabel, 18).'</li>';
1552
								} else {
1553
									$toprint[]='<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #aaa">'.$obj->$field_toshow.'</li>';
1554
								}
1555
							}
1556
						} else {
1557
							$translabel = '';
1558
							if (! empty($obj->{$InfoFieldList[1]})) {
1559
								$translabel = $langs->trans($obj->{$InfoFieldList[1]});
1560
							}
1561
							if ($translabel != $obj->{$InfoFieldList[1]}) {
1562
								$toprint[]='<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #aaa">'.dol_trunc($translabel, 18).'</li>';
1563
							} else {
1564
								$toprint[]='<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #aaa">'.$obj->{$InfoFieldList[1]}.'</li>';
1565
							}
1566
						}
1567
					}
1568
				}
1569
				$value='<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>';
1570
1571
			} else {
1572
				dol_syslog(get_class($this) . '::showOutputField error ' . $this->db->lasterror(), LOG_WARNING);
1573
			}
1574
		}
1575
		elseif ($type == 'link')
1576
		{
1577
			$out='';
1578
			// only if something to display (perf)
1579
			if ($value)
1580
			{
1581
				$param_list=array_keys($param['options']);				// $param_list='ObjectName:classPath'
1582
1583
				$InfoFieldList = explode(":", $param_list[0]);
1584
				$classname=$InfoFieldList[0];
1585
				$classpath=$InfoFieldList[1];
1586
				if (! empty($classpath))
1587
				{
1588
					dol_include_once($InfoFieldList[1]);
1589
					if ($classname && class_exists($classname))
1590
					{
1591
						$object = new $classname($this->db);
1592
						$object->fetch($value);
1593
						$value=$object->getNomUrl(3);
1594
					}
1595
				}
1596
				else
1597
				{
1598
					dol_syslog('Error bad setup of extrafield', LOG_WARNING);
1599
					return 'Error bad setup of extrafield';
1600
				}
1601
			}
1602
		}
1603
		elseif ($type == 'text')
1604
		{
1605
			$value=dol_htmlentitiesbr($value);
1606
		}
1607
		elseif ($type == 'password')
1608
		{
1609
			$value=preg_replace('/./i','*',$value);
1610
		}
1611
		else
1612
		{
1613
			$showsize=round($size);
1614
			if ($showsize > 48) $showsize=48;
1615
		}
1616
1617
		//print $type.'-'.$size;
1618
		$out=$value;
1619
1620
		return $out;
1621
	}
1622
1623
	/**
1624
	 * Return tag to describe alignement to use for this extrafield
1625
	 *
1626
	 * @param   string	$key            Key of attribute
1627
	 * @return	string					Formated value
1628
	 */
1629
	function getAlignFlag($key)
1630
	{
1631
		global $conf,$langs;
1632
1633
		$type=$this->attribute_type[$key];
1634
1635
		$align='';
1636
1637
		if ($type == 'date')
1638
		{
1639
			$align="center";
1640
		}
1641
		elseif ($type == 'datetime')
1642
		{
1643
			$align="center";
1644
		}
1645
		elseif ($type == 'int')
1646
		{
1647
			$align="right";
1648
		}
1649
		elseif ($type == 'double')
1650
		{
1651
			$align="right";
1652
		}
1653
		elseif ($type == 'boolean')
1654
		{
1655
			$align="center";
1656
		}
1657
		elseif ($type == 'radio')
1658
		{
1659
			$align="center";
1660
		}
1661
		elseif ($type == 'checkbox')
1662
		{
1663
			$align="center";
1664
		}
1665
1666
		return $align;
1667
	}
1668
1669
	/**
1670
	 * Return HTML string to print separator extrafield
1671
	 *
1672
	 * @param   string	$key            Key of attribute
1673
	 * @return string
1674
	 */
1675
	function showSeparator($key)
1676
	{
1677
		$out = '<tr class="trextrafieldseparator"><td colspan="4"><strong>'.$this->attribute_label[$key].'</strong></td></tr>';
1678
		return $out;
1679
	}
1680
1681
	/**
1682
	 * Fill array_options property of object by extrafields value (using for data sent by forms)
1683
	 *
1684
	 * @param   array	$extralabels    $array of extrafields
1685
	 * @param   object	$object         Object
1686
	 * @param	string	$onlykey		Only following key is filled. When we make update of only one extrafield ($action = 'update_extras'), calling page must must set this to avoid to have other extrafields being reset.
1687
	 * @return	int						1 if array_options set, 0 if no value, -1 if error (field required missing for example)
1688
	 */
1689
	function setOptionalsFromPost($extralabels,&$object,$onlykey='')
1690
	{
1691
		global $_POST, $langs;
1692
		$nofillrequired='';// For error when required field left blank
1693
		$error_field_required = array();
1694
1695
		if (is_array($extralabels))
1696
		{
1697
			// Get extra fields
1698
			foreach ($extralabels as $key => $value)
1699
			{
1700
				if (! empty($onlykey) && $key != $onlykey) continue;
1701
1702
				$key_type = $this->attribute_type[$key];
1703
				if ($this->attribute_required[$key] && empty($_POST["options_".$key])) // Check if empty without GETPOST, value can be alpha, int, array, etc...
1704
				{
1705
					$nofillrequired++;
1706
					$error_field_required[] = $value;
1707
				}
1708
1709
				if (in_array($key_type,array('date','datetime')))
1710
				{
1711
					// Clean parameters
1712
					$value_key=dol_mktime($_POST["options_".$key."hour"], $_POST["options_".$key."min"], 0, $_POST["options_".$key."month"], $_POST["options_".$key."day"], $_POST["options_".$key."year"]);
1713
				}
1714
				else if (in_array($key_type,array('checkbox','chkbxlst')))
1715
				{
1716
					$value_arr=GETPOST("options_".$key, 'array'); // check if an array
1717
					if (!empty($value_arr)) {
1718
						$value_key=implode($value_arr,',');
1719
					}else {
1720
						$value_key='';
1721
					}
1722
				}
1723
				else if (in_array($key_type,array('price','double')))
1724
				{
1725
					$value_arr=GETPOST("options_".$key);
1726
					$value_key=price2num($value_arr);
1727
				}
1728
				else
1729
				{
1730
					$value_key=GETPOST("options_".$key);
1731
				}
1732
				$object->array_options["options_".$key]=$value_key;
1733
			}
1734
1735
			if ($nofillrequired) {
1736
				$langs->load('errors');
1737
				setEventMessages($langs->trans('ErrorFieldsRequired').' : '.implode(', ',$error_field_required), null, 'errors');
1738
				return -1;
1739
			}
1740
			else {
1741
				return 1;
1742
			}
1743
		}
1744
		else {
1745
			return 0;
1746
		}
1747
	}
1748
1749
	/**
1750
	 * return array_options array for object by extrafields value (using for data send by forms)
1751
	 *
1752
	 * @param  array   $extralabels    $array of extrafields
1753
	 * @param  string  $keyprefix      Prefix string to add into name and id of field (can be used to avoid duplicate names)
1754
	 * @param  string  $keysuffix      Suffix string to add into name and id of field (can be used to avoid duplicate names)
1755
	 * @return int                     1 if array_options set / 0 if no value
1756
	 */
1757
	function getOptionalsFromPost($extralabels,$keyprefix='',$keysuffix='')
1758
	{
1759
		global $_POST;
1760
1761
		$array_options = array();
1762
		if (is_array($extralabels))
1763
		{
1764
			// Get extra fields
1765
			foreach ($extralabels as $key => $value)
1766
			{
1767
				$key_type = $this->attribute_type[$key];
1768
1769
				if (in_array($key_type,array('date','datetime')))
1770
				{
1771
					// Clean parameters
1772
					$value_key=dol_mktime($_POST[$keysuffix."options_".$key.$keyprefix."hour"], $_POST[$keysuffix."options_".$key.$keyprefix."min"], 0, $_POST[$keysuffix."options_".$key.$keyprefix."month"], $_POST[$keysuffix."options_".$key.$keyprefix."day"], $_POST[$keysuffix."options_".$key.$keyprefix."year"]);
1773
				}
1774
				else if (in_array($key_type,array('checkbox', 'chkbxlst')))
1775
				{
1776
					$value_arr=GETPOST($keysuffix."options_".$key.$keyprefix);
1777
					// Make sure we get an array even if there's only one checkbox
1778
					$value_arr=(array) $value_arr;
1779
					$value_key=implode(',', $value_arr);
1780
				}
1781
				else if (in_array($key_type,array('price','double')))
1782
				{
1783
					$value_arr=GETPOST($keysuffix."options_".$key.$keyprefix);
1784
					$value_key=price2num($value_arr);
1785
				}
1786
				else
1787
				{
1788
					$value_key=GETPOST($keysuffix."options_".$key.$keyprefix);
1789
				}
1790
1791
				$array_options[$keysuffix."options_".$key]=$value_key;	// No keyprefix here. keyprefix is used only for read.
1792
			}
1793
1794
			return $array_options;
1795
		}
1796
		else {
1797
			return 0;
1798
		}
1799
	}
1800
}
1801