Passed
Push — developer ( 0af0f2...6f5392 )
by Radosław
34:51 queued 16:19
created

Vtiger_Field_Model::getIcon()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
eloc 8
c 0
b 0
f 0
dl 0
loc 12
ccs 0
cts 7
cp 0
rs 8.8333
cc 7
nc 6
nop 1
crap 56
1
<?php
2
/* +***********************************************************************************
3
 * The contents of this file are subject to the vtiger CRM Public License Version 1.0
4
 * ("License"); You may not use this file except in compliance with the License
5
 * The Original Code is:  vtiger CRM Open Source
6
 * The Initial Developer of the Original Code is vtiger.
7
 * Portions created by vtiger are Copyright (C) vtiger.
8
 * All Rights Reserved.
9
 * Contributor(s): YetiForce S.A.
10
 * *********************************************************************************** */
11
12
/**
13
 * Vtiger Field Model Class.
14
 */
15
class Vtiger_Field_Model extends vtlib\Field
16
{
17
	const REFERENCE_TYPE = 'reference';
18
	const OWNER_TYPE = 'owner';
19
	const CURRENCY_LIST = 'currencyList';
20
	const QUICKCREATE_MANDATORY = 0;
21
	const QUICKCREATE_NOT_ENABLED = 1;
22
	const QUICKCREATE_ENABLED = 2;
23
	const QUICKCREATE_NOT_PERMITTED = 3;
24
25
	public static $referenceTypes = ['reference', 'referenceLink', 'referenceProcess', 'referenceSubProcess', 'referenceExtend', 'referenceSubProcessSL'];
26
27
	/** @var array Field maximum length by UiType. */
28
	public static $uiTypeMaxLength = [
29
		120 => 65535,
30
		106 => '3,64',
31
		156 => '3',
32
		360 => '0,99999999',
33
	];
34
35
	/** @var int[] Field maximum length by db type. */
36
	public static $typesMaxLength = [
37
		'tinytext' => 255,
38
		'text' => 65535,
39
		'mediumtext' => 16777215,
40
		'longtext' => 4294967295,
41
		'blob' => 65535,
42
		'mediumblob' => 16777215,
43
		'longblob' => 4294967295,
44
	];
45
46
	/** @var Vtiger_Field_Model[] Cache by field id */
47
	protected static $instanceCacheById = [];
48
49
	/** @var Vtiger_Field_Model[][] Cache by module id and field id */
50
	protected static $instanceCacheByName = [];
51
52
	/**
53
	 * @var array
54
	 */
55
	protected $fieldInfo;
56
	protected $fieldType;
57
	protected $fieldDataTypeShort;
58
	protected $uitype_instance;
59
60
	/** @var string[] List of modules the field referenced to. */
61 118
	public $referenceList;
62
63 118
	/** @var string[] Picklist values only for custom fields;. */
64 118
	public $picklistValues;
65
66 4
	/** @var bool Is calculate field */
67
	protected $isCalculateField = true;
68
69
	/** @var bool|null Field visibility permissions */
70
	protected $permissions;
71
72
	/** @var Vtiger_Base_UIType Vtiger_Base_UIType or UI Type specific model instance */
73
	protected $uitypeModel;
74
75
	/**
76
	 * Initialize.
77 30
	 *
78
	 * @param string     $module
79 30
	 * @param array      $data
80
	 * @param mixed|null $name
81 30
	 *
82
	 * @return \Vtiger_Field_Model
83
	 */
84
	public static function init($module = 'Vtiger', $data = [], $name = '')
85
	{
86
		if (\App\Module::getModuleId($module)) {
87
			$moduleModel = Vtiger_Module_Model::getInstance($module);
88
		} else {
89 64
			$modelClassName = \Vtiger_Loader::getComponentClassName('Model', 'Module', $module);
90
			$moduleModel = new $modelClassName();
91 64
		}
92
		$modelClassName = \Vtiger_Loader::getComponentClassName('Model', 'Field', $module);
93
		$instance = new $modelClassName();
94
		$instance->setModule($moduleModel);
95
		$instance->setData(array_merge([
96
			'uitype' => 1,
97
			'column' => $name,
98
			'name' => $name,
99 67
			'label' => $name,
100
			'displaytype' => 1,
101 67
			'typeofdata' => 'V~O',
102
			'presence' => 0,
103
			'isReadOnly' => false,
104
			'isEditableReadOnly' => false,
105
		], $data));
106
		return $instance;
107
	}
108
109 53
	/**
110
	 * Function to get the value of a given property.
111 53
	 *
112
	 * @param string $propertyName
113
	 *
114
	 * @return mixed|null
115
	 */
116
	public function get(string $propertyName)
117
	{
118
		if (property_exists($this, $propertyName)) {
119 6
			return $this->{$propertyName};
120
		}
121 6
		return null;
122
	}
123
124
	/**
125
	 * Function which sets value for given name.
126
	 *
127
	 * @param string $name  - name for which value need to be assinged
128
	 * @param mixed  $value - values that need to be assigned
129 5813
	 *
130
	 * @return Vtiger_Field_Model
131 5813
	 */
132
	public function set(string $name, $value)
133
	{
134
		$this->{$name} = $value;
135
		return $this;
136
	}
137
138
	/**
139 5836
	 * Function to get the Field Id.
140
	 *
141 5836
	 * @return int
142
	 */
143
	public function getId()
144
	{
145
		return $this->id;
146
	}
147
148
	/**
149 37
	 * Get name.
150
	 *
151 37
	 * @return string
152
	 */
153
	public function getName()
154
	{
155
		return $this->name;
156
	}
157
158
	/**
159
	 * Get full name.
160
	 *
161
	 * @return string
162
	 */
163
	public function getFullName()
164
	{
165
		return $this->get('source_field_name') ? "{$this->getName()}:{$this->getModuleName()}:{$this->get('source_field_name')}" : $this->getName();
166
	}
167
168
	/**
169 16
	 * Get full label translation.
170
	 *
171 16
	 * @param Vtiger_Module_Model|null $module
172 3
	 *
173 3
	 * @return string
174
	 */
175
	public function getFullLabelTranslation(?Vtiger_Module_Model $module = null): string
176 3
	{
177
		$translation = '';
178
		if ($this->get('source_field_name')) {
179 3
			if (!$module) {
180
				throw new \App\Exceptions\AppException('ERR_ARGUMENT_DOES_NOT_EXIST');
181 16
			}
182
			$translation = \App\Language::translate($module->getFieldByName($this->get('source_field_name'))->getFieldLabel(), $module->getName()) . ' - ';
0 ignored issues
show
Bug introduced by
$module->getName() of type boolean is incompatible with the type string expected by parameter $moduleName of App\Language::translate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

182
			$translation = \App\Language::translate($module->getFieldByName($this->get('source_field_name'))->getFieldLabel(), /** @scrutinizer ignore-type */ $module->getName()) . ' - ';
Loading history...
183
		}
184
		return $translation .= \App\Language::translate($this->getFieldLabel(), $this->getModuleName());
185
	}
186
187
	/**
188
	 * Get field name.
189
	 *
190
	 * @deprecated Use $this->getName()
191
	 *
192
	 * @return string
193
	 */
194
	public function getFieldName()
195
	{
196
		return $this->name;
197
	}
198
199
	/**
200
	 * Get field label.
201 5785
	 *
202
	 * @return string
203 5785
	 */
204
	public function getFieldLabel()
205
	{
206
		return $this->label;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->label returns the type boolean which is incompatible with the documented return type string.
Loading history...
207
	}
208
209
	/**
210
	 * Get table name.
211 11
	 *
212
	 * @return string
213 11
	 */
214
	public function getTableName()
215
	{
216
		return $this->table;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->table returns the type boolean which is incompatible with the documented return type string.
Loading history...
217
	}
218
219
	/**
220
	 * Get column label.
221 89
	 *
222
	 * @return string
223 89
	 */
224 69
	public function getColumnName()
225 69
	{
226
		return $this->column;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->column returns the type boolean which is incompatible with the documented return type string.
Loading history...
227
	}
228 69
229
	/**
230 69
	 * Get ui type.
231 23
	 *
232
	 * @return int
233 68
	 */
234 68
	public function getUIType()
235 10
	{
236 10
		return $this->uitype;
237 68
	}
238
239
	/**
240 68
	 * Function to retrieve full data.
241 7
	 *
242 7
	 * @return <array>
0 ignored issues
show
Documentation Bug introduced by
The doc comment <array> at position 0 could not be parsed: Unknown type name '<' at position 0 in <array>.
Loading history...
243 66
	 */
244 3
	public function getData()
245 3
	{
246 66
		return get_object_vars($this);
247 3
	}
248 3
249 66
	/**
250 7
	 * Get module model.
251 7
	 *
252 66
	 * @return Vtiger_Module_Model
253 10
	 */
254 10
	public function getModule()
255 66
	{
256 11
		if (!isset($this->module)) {
257 11
			if (isset($this->block->module)) {
258 66
				$moduleObj = $this->block->module;
259
			}
260
			//fix for opensource emailTemplate listview break
261 66
			if (empty($moduleObj)) {
262 3
				return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type Vtiger_Module_Model.
Loading history...
263 3
			}
264 66
			$this->module = Vtiger_Module_Model::getInstanceFromModuleObject($moduleObj);
0 ignored issues
show
Bug Best Practice introduced by
The property module does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
265 3
		}
266 3
		return $this->module;
267 66
	}
268 3
269 3
	public function setModule($moduleInstance)
270 66
	{
271 3
		$this->module = $moduleInstance;
0 ignored issues
show
Bug Best Practice introduced by
The property module does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
272 3
		return $this;
273 66
	}
274 3
275 3
	/**
276 66
	 * Function to retieve display value for a value.
277 10
	 *
278 10
	 * @param mixed                    $value          value which need to be converted to display value
279 65
	 * @param bool|int                 $record
280 65
	 * @param bool|Vtiger_Record_Model $recordInstance
281 8
	 * @param bool                     $rawText
282 8
	 * @param bool|int                 $length         Length of the text
283 65
	 * @param mixed                    $recordModel
284 8
	 *
285 8
	 * @return mixed converted display value
286 65
	 */
287 7
	public function getDisplayValue($value, $record = false, $recordModel = false, $rawText = false, $length = false)
288 7
	{
289 65
		return $this->getUITypeModel()->getDisplayValue($value, $record, $recordModel, $rawText, $length);
290 7
	}
291 7
292 65
	/**
293 7
	 * Function to retrieve display type of a field.
294 7
	 *
295 65
	 * @return int display type of the field
296 8
	 */
297 8
	public function getDisplayType()
298 65
	{
299 9
		return (int) $this->get('displaytype');
300 9
	}
301 65
302 8
	/**
303 8
	 * Function to get the Webservice Field data type.
304 65
	 *
305 8
	 * @return string Data type of the field
306 8
	 */
307 63
	public function getFieldDataType()
308 5
	{
309 5
		if (!isset($this->fieldDataType)) {
310 63
			$uiType = $this->getUIType();
311 4
			if (55 === $uiType) {
312 4
				$cacheName = $uiType . '-' . $this->getName();
313 63
			} else {
314 6
				$cacheName = $uiType . '-' . $this->get('typeofdata');
315 6
			}
316 61
			if (App\Cache::has('FieldDataType', $cacheName)) {
317 3
				$fieldDataType = App\Cache::get('FieldDataType', $cacheName);
318 3
			} else {
319 61
				switch ($uiType) {
320 6
					case 4:
321 6
						$fieldDataType = 'recordNumber';
322 59
						break;
323 4
					case 8:
324 4
						$fieldDataType = 'totalTime';
325 59
						break;
326 6
					case 9:
327 6
						$fieldDataType = 'percentage';
328 59
						break;
329 1
					case 12:
330 1
						$fieldDataType = 'accountName';
331 59
						break;
332
					case 27:
333
						$fieldDataType = 'fileLocationType';
334 59
						break;
335 7
					case 28:
336 7
						$fieldDataType = 'documentsFileUpload';
337 59
						break;
338 3
					case 31:
339 3
						$fieldDataType = 'theme';
340 59
						break;
341 4
					case 32:
342 4
						$fieldDataType = 'languages';
343 59
						break;
344 4
					case 35:
345 4
						$fieldDataType = 'country';
346 58
						break;
347
					case 54:
348
						$fieldDataType = 'multiowner';
349
						break;
350 58
					case 64:
351 58
						$fieldDataType = 'referenceSubProcessSL';
352 45
						break;
353
					case 65:
354 33
						$fieldDataType = 'referenceExtend';
355 33
						break;
356 33
					case 66:
357 5
						$fieldDataType = 'referenceProcess';
358 5
						break;
359 31
					case 67:
360 14
						$fieldDataType = 'referenceLink';
361 14
						break;
362 28
					case 68:
363 9
						$fieldDataType = 'referenceSubProcess';
364 9
						break;
365 27
					case 69:
366 8
						$fieldDataType = 'image';
367 8
						break;
368 27
					case 79:
369 26
					case 80:
370 17
						$fieldDataType = 'datetime';
371 17
						break;
372 23
					case 98:
373
						$fieldDataType = 'userRole';
374
						break;
375 23
					case 99:
376 18
						$fieldDataType = 'password';
377 18
						break;
378 19
					case 101:
379
						$fieldDataType = 'userReference';
380 19
						break;
381 19
					case 115:
382
						$fieldDataType = 'picklist';
383
						break;
384 58
					case 117:
385
						$fieldDataType = 'currencyList';
386 68
						break;
387
					case 120:
388 69
						$fieldDataType = 'sharedOwner';
389
						break;
390 89
					case 301:
391
						$fieldDataType = 'modules';
392
						break;
393
					case 302:
394
						$fieldDataType = 'tree';
395
						break;
396
					case 303:
397
						$fieldDataType = 'taxes';
398 6
						break;
399
					case 304:
400 6
						$fieldDataType = 'inventoryLimit';
401 3
						break;
402
					case 305:
403 6
						$fieldDataType = 'multiReferenceValue';
404 1
						break;
405
					case 308:
406 6
						$fieldDataType = 'rangeTime';
407 5
						break;
408 5
					case 309:
409 5
						$fieldDataType = 'categoryMultipicklist';
410 5
						break;
411 5
					case 311:
412 5
						$fieldDataType = 'multiImage';
413
						break;
414 5
					case 312:
415 5
						$fieldDataType = 'authySecretTotp';
416 5
						break;
417 5
					case 313:
418 5
						$fieldDataType = 'twitter';
419 5
						break;
420
					case 314:
421 6
						$fieldDataType = 'multiEmail';
422 6
						break;
423 6
					case 315:
424 6
						$fieldDataType = 'multiDependField';
425
						break;
426
					case 316:
427
						$fieldDataType = 'smtp';
428 6
						break;
429
					case 317:
430 6
						$fieldDataType = 'currencyInventory';
431
						break;
432
					case 318:
433
						$fieldDataType = 'serverAccess';
434
						break;
435
					case 319:
436
						$fieldDataType = 'multiDomain';
437
						break;
438
					case 320:
439
						$fieldDataType = 'multiListFields';
440
						break;
441
					case 321:
442
						$fieldDataType = 'multiReference';
443
						break;
444
					case 322:
445
						$fieldDataType = 'mailScannerActions';
446
						break;
447
					case 323:
448
						$fieldDataType = 'mailScannerFields';
449
						break;
450
					case 324:
451
						$fieldDataType = 'token';
452
						break;
453
					case 325:
454
						$fieldDataType = 'magentoServer';
455
						break;
456
					case 326:
457
						$fieldDataType = 'meetingUrl';
458
						break;
459
					case 327:
460
						$fieldDataType = 'barcode';
461
						break;
462 5851
					case 328:
463
						$fieldDataType = 'changesJson';
464 5851
						break;
465 5827
					case 329:
466
						$fieldDataType = 'iban';
467 44
						break;
468
					case 330:
469
						$fieldDataType = 'multiAttachment';
470
						break;
471
					default:
472
						$fieldsDataType = App\Field::getFieldsTypeFromUIType();
473
						if (isset($fieldsDataType[$uiType])) {
474
							$fieldDataType = $fieldsDataType[$uiType]['fieldtype'];
475
						} else {
476
							$fieldTypeArray = explode('~', $this->get('typeofdata'));
0 ignored issues
show
Bug introduced by
It seems like $this->get('typeofdata') can also be of type null; however, parameter $string of explode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

476
							$fieldTypeArray = explode('~', /** @scrutinizer ignore-type */ $this->get('typeofdata'));
Loading history...
477
							switch ($fieldTypeArray[0]) {
478
								case 'T':
479
									$fieldDataType = 'time';
480
									break;
481
								case 'D':
482 4
									$fieldDataType = 'date';
483
									break;
484 4
								case 'DT':
485
									$fieldDataType = 'datetime';
486
									break;
487
								case 'E':
488
									$fieldDataType = 'email';
489
									break;
490
								case 'N':
491
								case 'NN':
492
									$fieldDataType = 'double';
493
									break;
494 4
								case 'P':
495
									$fieldDataType = 'password';
496 4
									break;
497
								case 'I':
498
									$fieldDataType = 'integer';
499 4
									break;
500 4
								case 'V':
501 4
								default:
502 4
									$fieldDataType = 'string';
503 3
									break;
504 3
							}
505
						}
506 2
						break;
507
				}
508 4
				App\Cache::save('FieldDataType', $cacheName, $fieldDataType);
509 1
			}
510
			$this->fieldDataType = $fieldDataType;
0 ignored issues
show
Bug Best Practice introduced by
The property fieldDataType does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
511
		}
512 4
		return $this->fieldDataType;
513 3
	}
514 3
515
	/**
516
	 * Function to get list of modules the field refernced to.
517
	 *
518
	 * @return string[] list of modules for which field is refered to
519
	 */
520
	public function getReferenceList()
521
	{
522 4
		if (isset($this->referenceList)) {
523
			return $this->referenceList;
524
		}
525
		if (\App\Cache::has('getReferenceList', $this->getId())) {
526
			return \App\Cache::get('getReferenceList', $this->getId());
527
		}
528
		if (method_exists($this->getUITypeModel(), 'getReferenceList')) {
529
			$list = $this->getUITypeModel()->getReferenceList();
530
		} else {
531
			if (10 === $this->getUIType()) {
532
				$query = (new \App\Db\Query())->select(['module' => 'relmodule'])
533
					->from('vtiger_fieldmodulerel')
534
					->innerJoin('vtiger_tab', 'vtiger_tab.name = vtiger_fieldmodulerel.relmodule')
535
					->where(['fieldid' => $this->getId()])
536
					->andWhere(['<>', 'vtiger_tab.presence', 1])
537
					->orderBy(['sequence' => SORT_ASC]);
538
			} else {
539
				$query = (new \App\Db\Query())->select(['module' => 'vtiger_ws_referencetype.type'])
540
					->from('vtiger_ws_referencetype')
541
					->innerJoin('vtiger_ws_fieldtype', 'vtiger_ws_referencetype.fieldtypeid = vtiger_ws_fieldtype.fieldtypeid')
542
					->innerJoin('vtiger_tab', 'vtiger_tab.name = vtiger_ws_referencetype.type')
543
					->where(['vtiger_ws_fieldtype.uitype' => $this->getUIType()])
544
					->andWhere(['<>', 'vtiger_tab.presence', 1]);
545
			}
546
			$list = [];
547
			foreach ($query->column() as $moduleName) {
548
				if (\App\Privilege::isPermitted($moduleName)) {
549
					$list[] = $moduleName;
550
				}
551
			}
552
		}
553
		\App\Cache::save('getReferenceList', $this->getId(), $list);
554
		return $list;
555
	}
556
557
	/**
558
	 * Function to check if the field is named field of the module.
559
	 *
560 16
	 * @return bool
561
	 */
562 16
	public function isNameField(): bool
563 16
	{
564
		$moduleModel = $this->getModule();
565
		return $moduleModel && !$this->isReferenceField() && !\in_array($this->getFieldDataType(), ['email', 'url', 'phone']) && \in_array($this->getFieldName(), $moduleModel->getNameFields());
0 ignored issues
show
Deprecated Code introduced by
The function Vtiger_Field_Model::getFieldName() has been deprecated: Use $this->getName() ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

565
		return $moduleModel && !$this->isReferenceField() && !\in_array($this->getFieldDataType(), ['email', 'url', 'phone']) && \in_array(/** @scrutinizer ignore-deprecated */ $this->getFieldName(), $moduleModel->getNameFields());

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
566
	}
567
568
	/**
569
	 * Function to get the UI Type model for the uitype of the current field.
570
	 *
571 17
	 * @return Vtiger_Base_UIType Vtiger_Base_UIType or UI Type specific model instance
572
	 */
573 17
	public function getUITypeModel()
574 6
	{
575
		if (isset($this->uitypeModel)) {
576 14
			return $this->uitypeModel;
577 14
		}
578 14
		return $this->uitypeModel = Vtiger_Base_UIType::getInstanceFromField($this);
579
	}
580
581 14
	public function isRoleBased()
582
	{
583 14
		return 15 === $this->get('uitype') || 33 === $this->get('uitype');
584
	}
585
586
	/**
587
	 * Function to get all the available picklist values for the current field.
588
	 *
589
	 * @param bool $skipCheckingRole
590
	 *
591 11
	 * @return <Array> List of picklist values if the field is of type picklist or multipicklist, null otherwise
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Array> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Array>.
Loading history...
592
	 */
593 11
	public function getPicklistValues($skipCheckingRole = false)
594 3
	{
595
		if (isset($this->picklistValues)) {
596 11
			return $this->picklistValues;
597
		}
598
		$fieldDataType = $this->getFieldDataType();
599
		$fieldPickListValues = [];
600
		if ('picklist' === $fieldDataType || 'multipicklist' === $fieldDataType) {
601
			if ($this->isRoleBased() && !$skipCheckingRole) {
602
				$picklistValues = \App\Fields\Picklist::getRoleBasedValues($this->getName(), \App\User::getCurrentUserModel()->getRole());
603
			} else {
604 6
				$picklistValues = App\Fields\Picklist::getValuesName($this->getName());
605
			}
606
			foreach ($picklistValues as $value) {
607 6
				$fieldPickListValues[$value] = \App\Language::translate($value, $this->getModuleName(), false, false);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type null|string expected by parameter $language of App\Language::translate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

607
				$fieldPickListValues[$value] = \App\Language::translate($value, $this->getModuleName(), /** @scrutinizer ignore-type */ false, false);
Loading history...
Bug introduced by
It seems like $this->getModuleName() can also be of type boolean; however, parameter $moduleName of App\Language::translate() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

607
				$fieldPickListValues[$value] = \App\Language::translate($value, /** @scrutinizer ignore-type */ $this->getModuleName(), false, false);
Loading history...
608 6
			}
609
			// Protection against deleting a value that does not exist on the list
610 4
			if ('picklist' === $fieldDataType) {
611
				$fieldValue = $this->get('fieldvalue');
612 6
				if (!empty($fieldValue) && !isset($fieldPickListValues[$fieldValue])) {
613
					$fieldPickListValues[$fieldValue] = \App\Language::translate($fieldValue, $this->getModuleName(), false, false);
614
					$this->set('isEditableReadOnly', true);
615
				}
616
			}
617
		} elseif (method_exists($this->getUITypeModel(), 'getPicklistValues')) {
618
			$fieldPickListValues = $this->getUITypeModel()->getPicklistValues();
619
		}
620
		return $fieldPickListValues;
621
	}
622
623
	/**
624
	 * Function to get all the available picklist values for the current field.
625
	 *
626
	 * @return <Array> List of picklist values if the field is of type picklist or multipicklist, null otherwise
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Array> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Array>.
Loading history...
627
	 */
628
	public function getModulesListValues()
629
	{
630
		$allModules = \vtlib\Functions::getAllModules(true, false, 0);
631
		$modules = [];
632
		foreach ($allModules as $module) {
633
			$modules[$module['tabid']] = [
634
				'name' => $module['name'],
635
				'label' => App\Language::translate($module['name'], $module['name']),
636
			];
637
		}
638
		return $modules;
639
	}
640
641
	public static function showDisplayTypeList()
642
	{
643
		return [
644
			1 => 'LBL_DISPLAY_TYPE_1',
645
			2 => 'LBL_DISPLAY_TYPE_2',
646
			3 => 'LBL_DISPLAY_TYPE_3',
647
			4 => 'LBL_DISPLAY_TYPE_4',
648
			//5 => 'LBL_DISPLAY_TYPE_5',
649
			9 => 'LBL_DISPLAY_TYPE_9',
650
			10 => 'LBL_DISPLAY_TYPE_10',
651
			6 => 'LBL_DISPLAY_TYPE_6',
652
		];
653
	}
654
655
	/**
656
	 * Function to check if the current field is mandatory or not.
657
	 *
658
	 * @return bool
659
	 */
660
	public function isMandatory()
661
	{
662
		if ($this->get('isMandatory')) {
663
			return $this->get('isMandatory');
664
		}
665
		$typeOfData = explode('~', $this->get('typeofdata'));
0 ignored issues
show
Bug introduced by
It seems like $this->get('typeofdata') can also be of type null; however, parameter $string of explode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

665
		$typeOfData = explode('~', /** @scrutinizer ignore-type */ $this->get('typeofdata'));
Loading history...
666
		return isset($typeOfData[1]) && 'M' === $typeOfData[1];
667
	}
668
669
	/**
670
	 * Function to get the field type.
671
	 *
672
	 * @return string type of the field
673
	 */
674
	public function getFieldType()
675
	{
676
		if (isset($this->fieldType)) {
677
			return $this->fieldType;
678
		}
679
		$fieldTypeArray = explode('~', $this->get('typeofdata'));
0 ignored issues
show
Bug introduced by
It seems like $this->get('typeofdata') can also be of type null; however, parameter $string of explode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

679
		$fieldTypeArray = explode('~', /** @scrutinizer ignore-type */ $this->get('typeofdata'));
Loading history...
680
		$fieldTypeArray = array_shift($fieldTypeArray);
681
		if ('reference' === $this->getFieldDataType()) {
682
			$fieldTypeArray = 'V';
683
		} else {
684
			$fieldTypeArray = \vtlib\Functions::transformFieldTypeOfData($this->get('table'), $this->get('column'), $fieldTypeArray);
685
		}
686
		return $this->fieldType = $fieldTypeArray;
687
	}
688
689
	/**
690
	 * Function to check if the field is shown in detail view.
691
	 *
692
	 * @return bool
693
	 */
694 16
	public function isViewEnabled()
695
	{
696 16
		if (4 === $this->getDisplayType() || 6 === $this->getDisplayType() || 1 === $this->get('presence') || 3 === $this->get('presence')) {
697 16
			return false;
698 16
		}
699
		return $this->getPermissions();
700
	}
701 16
702
	/**
703
	 * Function to check if the field is shown in detail view.
704
	 *
705
	 * @return bool
706
	 */
707
	public function isViewable()
708
	{
709
		if (
710
			!$this->isViewEnabled() || !$this->isActiveReference()
711
			|| ((306 === $this->get('uitype') || 307 === $this->get('uitype') || 311 === $this->get('uitype') || 312 === $this->get('uitype')) && 2 === $this->getDisplayType())
712
		) {
713
			return false;
714
		}
715
		return true;
716
	}
717
718
	/**
719 6
	 * Function to check if the field is export table.
720
	 *
721 6
	 * @return bool
722
	 */
723
	public function isExportTable()
724 6
	{
725
		return $this->isViewable();
726
	}
727
728
	/**
729
	 * Function to check if the field is shown in detail view.
730
	 *
731
	 * @return bool
732
	 */
733
	public function isViewableInDetailView()
734
	{
735
		if (!$this->isViewable() || 3 === $this->getDisplayType() || 5 === $this->getDisplayType()) {
736
			return false;
737
		}
738
		return true;
739
	}
740
741
	/**
742 48
	 * Function to check whether the current field is writable.
743
	 *
744 48
	 * @return bool
745 48
	 */
746 48
	public function isWritable()
747 48
	{
748 48
		$displayType = $this->get('displaytype');
749
		if (!$this->isViewEnabled() || 4 === $displayType || 5 === $displayType
750 48
			|| 0 === strcasecmp($this->getFieldDataType(), 'autogenerated')
751
			|| 0 === strcasecmp($this->getFieldDataType(), 'id')
752
			|| true === $this->isReadOnly()
753
			|| !$this->getUITypeModel()->isWritable()) {
754
			return false;
755
		}
756
		return true;
757
	}
758
759
	/**
760
	 * Function to check whether the current field is editable.
761
	 *
762
	 * @return bool
763
	 */
764
	public function isEditable(): bool
765
	{
766
		$displayType = $this->get('displaytype');
767
		if (!$this->isWritable() || (1 !== $displayType && 10 !== $displayType) || true === $this->isReadOnly()) {
768
			return false;
769
		}
770
		return true;
771
	}
772
773
	/**
774
	 * Function to check whether field is ajax editable.
775
	 *
776
	 * @return bool
777
	 */
778
	public function isAjaxEditable()
779
	{
780
		$ajaxRestrictedFields = [72, 12, 101];
781
		return !(10 === (int) $this->get('displaytype') || $this->isReferenceField() || !$this->getUITypeModel()->isAjaxEditable() || !$this->isEditable() || \in_array($this->get('uitype'), $ajaxRestrictedFields));
782
	}
783
784
	public function isEditableReadOnly()
785
	{
786
		if (null !== $this->get('isEditableReadOnly')) {
787
			return $this->get('isEditableReadOnly');
788
		}
789
		if (10 === (int) $this->get('displaytype')) {
790
			return true;
791
		}
792
		return false;
793
	}
794
795
	/**
796
	 * Function to check whether the current field is read-only.
797
	 *
798
	 * @return bool
799
	 */
800
	public function isReadOnly(): bool
801
	{
802
		if (isset($this->isReadOnly)) {
803
			return $this->isReadOnly;
804
		}
805
		return $this->isReadOnly = !$this->getProfileReadWritePermission();
0 ignored issues
show
Bug Best Practice introduced by
The property isReadOnly does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
806
	}
807
808
	public function isQuickCreateEnabled()
809
	{
810
		$moduleModel = $this->getModule();
811
		$quickCreate = $this->get('quickcreate');
812
		if ((self::QUICKCREATE_MANDATORY == $quickCreate || self::QUICKCREATE_ENABLED == $quickCreate || $this->isMandatory()) && method_exists($moduleModel, 'isQuickCreateSupported') && $moduleModel->isQuickCreateSupported()) {
813
			return true;
814
		}
815
		return false;
816
	}
817
818
	/**
819
	 * Function to check whether summary field or not.
820
	 *
821
	 * @return bool true/false
822
	 */
823
	public function isSummaryField()
824
	{
825
		return ($this->get('summaryfield')) ? true : false;
826
	}
827
828
	/**
829
	 * Function to check whether the current reference field is active.
830 16
	 *
831
	 * @return bool
832 16
	 */
833 16
	public function isActiveReference()
834 16
	{
835 16
		if ('reference' === $this->getFieldDataType() && empty($this->getReferenceList())) {
836 16
			return false;
837 16
		}
838 16
		return true;
839 16
	}
840 16
841 16
	/**
842 16
	 * If the field is sortable in ListView.
843 16
	 */
844 16
	public function isListviewSortable()
845 16
	{
846
		return !$this->get('fromOutsideList') && $this->getUITypeModel()->isListviewSortable();
847 16
	}
848 16
849 16
	/**
850 16
	 * Static Function to get the instance fo Vtiger Field Model from a given vtlib\Field object.
851 16
	 *
852 16
	 * @param vtlib\Field $fieldObj - vtlib field object
853 16
	 *
854 16
	 * @return Vtiger_Field_Model instance
855 16
	 */
856 16
	public static function getInstanceFromFieldObject(vtlib\Field $fieldObj)
857 16
	{
858
		$objectProperties = get_object_vars($fieldObj);
859
		$className = Vtiger_Loader::getComponentClassName('Model', 'Field', $fieldObj->getModuleName());
860
		$fieldModel = new $className();
861
		foreach ($objectProperties as $properName => $propertyValue) {
862
			$fieldModel->{$properName} = $propertyValue;
863
		}
864
		return $fieldModel;
865 16
	}
866 16
867
	/**
868
	 * Function to get the custom view column name transformation of the field for a date field used in date filters.
869 16
	 *
870
	 * @return string - tablename:columnname:fieldname:module_fieldlabel
871
	 */
872 16
	public function getCVDateFilterColumnName()
873
	{
874
		$moduleName = $this->getModuleName();
875
		$tableName = $this->get('table');
876
		$columnName = $this->get('column');
877 16
		$fieldName = $this->get('name');
878 16
		$fieldLabel = $this->get('label');
879 16
880
		$escapedFieldLabel = str_replace(' ', '_', $fieldLabel);
881
		$moduleFieldLabel = $moduleName . '_' . $escapedFieldLabel;
882
883
		return $tableName . ':' . $columnName . ':' . $fieldName . ':' . $moduleFieldLabel;
884
	}
885
886
	/**
887
	 * Function to get value for customview.
888
	 *
889
	 * @param string $sourceFieldName
890
	 *
891
	 * @throws \Exception
892
	 *
893
	 * @return string
894
	 */
895
	public function getCustomViewSelectColumnName(string $sourceFieldName = '')
896 16
	{
897
		return "{$this->get('name')}:{$this->getModuleName()}" . ($sourceFieldName ? ":{$sourceFieldName}" : '');
898
	}
899
900
	/**
901
	 * Function to get the custom view column name transformation of the field.
902 16
	 *
903 16
	 * @return string - tablename:columnname:fieldname:module_fieldlabel:fieldtype
904
	 */
905
	public function getCustomViewColumnName()
906 16
	{
907
		$moduleName = $this->getModuleName();
908
		$tableName = $this->get('table');
909
		$columnName = $this->get('column');
910
		$fieldName = $this->get('name');
911
		$fieldLabel = $this->get('label');
912
		$typeOfData = $this->get('typeofdata');
913
		$fieldTypeOfData = explode('~', $typeOfData);
0 ignored issues
show
Bug introduced by
It seems like $typeOfData can also be of type null; however, parameter $string of explode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

913
		$fieldTypeOfData = explode('~', /** @scrutinizer ignore-type */ $typeOfData);
Loading history...
914
		$fieldTypeOfData = $fieldTypeOfData[0];
915
		//Special condition need for reference field as they should be treated as string field
916
		if ('reference' === $this->getFieldDataType()) {
917
			$fieldTypeOfData = 'V';
918
		} else {
919
			$fieldTypeOfData = \vtlib\Functions::transformFieldTypeOfData($tableName, $columnName, $fieldTypeOfData);
920 16
		}
921 6
		$escapedFieldLabel = str_replace(' ', '_', $fieldLabel);
922 6
		$moduleFieldLabel = "{$moduleName}_{$escapedFieldLabel}";
923 6
924 6
		return "$tableName:$columnName:$fieldName:$moduleFieldLabel:$fieldTypeOfData";
925 10
	}
926 10
927 10
	/**
928 10
	 * This is set from Workflow Record Structure, since workflow expects the field name
929 10
	 * in a different format in its filter. Eg: for module field its fieldname and for reference
930
	 * fields its reference_field_name : (reference_module_name) field - salesorder_id: (SalesOrder) subject.
931
	 *
932
	 * @return string
933 16
	 */
934
	public function getWorkFlowFilterColumnName()
935
	{
936
		return $this->get('workflow_columnname');
937
	}
938
939
	/**
940
	 * Function to get the field details.
941
	 *
942
	 * @return array - array of field values
943
	 */
944
	public function getFieldInfo(): array
945
	{
946
		return $this->getUITypeModel()->getFieldInfo();
947
	}
948
949
	/**
950
	 * Load field info.
951
	 *
952
	 * @return array
953
	 */
954
	public function loadFieldInfo(): array
955
	{
956
		if (null !== $this->fieldInfo) {
957
			return $this->fieldInfo;
958
		}
959
		$this->fieldInfo['name'] = $this->get('name');
960
		$this->fieldInfo['label'] = App\Language::translate($this->get('label'), $this->getModuleName(), false, false);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type null|string expected by parameter $language of App\Language::translate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

960
		$this->fieldInfo['label'] = App\Language::translate($this->get('label'), $this->getModuleName(), /** @scrutinizer ignore-type */ false, false);
Loading history...
Bug introduced by
It seems like $this->get('label') can also be of type null; however, parameter $key of App\Language::translate() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

960
		$this->fieldInfo['label'] = App\Language::translate(/** @scrutinizer ignore-type */ $this->get('label'), $this->getModuleName(), false, false);
Loading history...
Bug introduced by
It seems like $this->getModuleName() can also be of type boolean; however, parameter $moduleName of App\Language::translate() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

960
		$this->fieldInfo['label'] = App\Language::translate($this->get('label'), /** @scrutinizer ignore-type */ $this->getModuleName(), false, false);
Loading history...
961
		$fieldDataType = $this->getFieldDataType();
962
		$this->fieldInfo['type'] = $fieldDataType;
963
		$this->fieldInfo['mandatory'] = $this->isMandatory();
964
		$this->fieldInfo['defaultvalue'] = $this->getDefaultFieldValue();
965
		$this->fieldInfo['presence'] = $this->isActiveField();
966
		$this->fieldInfo['quickcreate'] = $this->isQuickCreateEnabled();
967
		$this->fieldInfo['masseditable'] = $this->isMassEditable();
968 25
		$this->fieldInfo['header_field'] = $this->getHeaderField();
969
		$this->fieldInfo['maxlengthtext'] = $this->get('maxlengthtext');
970 25
		$this->fieldInfo['maximumlength'] = $this->get('maximumlength');
971 5
		$this->fieldInfo['maxwidthcolumn'] = $this->get('maxwidthcolumn');
972
		$this->fieldInfo['tabindex'] = $this->get('tabindex');
973 23
		$this->fieldInfo['fieldtype'] = explode('~', $this->get('typeofdata'))[0] ?? '';
0 ignored issues
show
Bug introduced by
It seems like $this->get('typeofdata') can also be of type null; however, parameter $string of explode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

973
		$this->fieldInfo['fieldtype'] = explode('~', /** @scrutinizer ignore-type */ $this->get('typeofdata'))[0] ?? '';
Loading history...
974 23
		$currentUser = \App\User::getCurrentUserModel();
975 23
		switch ($fieldDataType) {
976 23
			case 'picklist':
977
			case 'multipicklist':
978
			case 'multiowner':
979 23
			case 'multiReferenceValue':
980 23
			case 'inventoryLimit':
981 23
			case 'languages':
982 23
			case 'currencyList':
983 23
			case 'fileLocationType':
984 23
			case 'taxes':
985
			case 'multiListFields':
986 23
			case 'mailScannerFields':
987 23
			case 'country':
988
				$this->fieldInfo['picklistvalues'] = $this->getPicklistValues() ?: [];
989
				break;
990
			case 'date':
991
			case 'datetime':
992
				$this->fieldInfo['date-format'] = $currentUser->getDetail('date_format');
993
				break;
994
			case 'time':
995
				$this->fieldInfo['time-format'] = $currentUser->getDetail('hour_format');
996
				break;
997
			case 'currency':
998 28
				$this->fieldInfo['currency_symbol'] = $currentUser->getDetail('currency_symbol');
999
				$this->fieldInfo['decimal_separator'] = $currentUser->getDetail('currency_decimal_separator');
1000 28
				$this->fieldInfo['group_separator'] = $currentUser->getDetail('currency_grouping_separator');
1001 28
				break;
1002 7
			case 'owner':
1003
			case 'userCreator':
1004 28
			case 'sharedOwner':
1005 21
				if (!App\Config::performance('SEARCH_OWNERS_BY_AJAX') || \in_array(\App\Request::_get('module'), ['CustomView', 'Workflows', 'PDF', 'MappedFields']) || 'showAdvancedSearch' === \App\Request::_get('mode')) {
0 ignored issues
show
Bug introduced by
The method _get() does not exist on App\Request. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1005
				if (!App\Config::performance('SEARCH_OWNERS_BY_AJAX') || \in_array(\App\Request::/** @scrutinizer ignore-call */ _get('module'), ['CustomView', 'Workflows', 'PDF', 'MappedFields']) || 'showAdvancedSearch' === \App\Request::_get('mode')) {
Loading history...
1006 21
					$userList = \App\Fields\Owner::getInstance($this->getModuleName(), $currentUser)->getAccessibleUsers('', $fieldDataType);
1007
					$groupList = \App\Fields\Owner::getInstance($this->getModuleName(), $currentUser)->getAccessibleGroups('', $fieldDataType);
1008
					$pickListValues = [];
1009
					$pickListValues[\App\Language::translate('LBL_USERS', $this->getModuleName())] = $userList;
1010
					$pickListValues[\App\Language::translate('LBL_GROUPS', $this->getModuleName())] = $groupList;
1011 28
					$this->fieldInfo['picklistvalues'] = $pickListValues;
1012 28
					if (App\Config::performance('SEARCH_OWNERS_BY_AJAX')) {
1013
						$this->fieldInfo['searchOperator'] = 'e';
1014
					}
1015
				} else {
1016
					if ('owner' === $fieldDataType) {
1017
						$this->fieldInfo['searchOperator'] = 'e';
1018
					}
1019
				}
1020
				break;
1021
			case 'modules':
1022
				foreach ($this->getModulesListValues() as $module) {
1023
					$modulesList[$module['name']] = $module['label'];
1024
				}
1025
				$this->fieldInfo['picklistvalues'] = $modulesList;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $modulesList seems to be defined by a foreach iteration on line 1022. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
1026
				break;
1027
			case 'categoryMultipicklist':
1028
			case 'tree':
1029
				$this->fieldInfo['picklistvalues'] = \App\Fields\Tree::getPicklistValue($this->getFieldParams(), $this->getModuleName());
0 ignored issues
show
Bug introduced by
$this->getFieldParams() of type array is incompatible with the type integer expected by parameter $templateId of App\Fields\Tree::getPicklistValue(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1029
				$this->fieldInfo['picklistvalues'] = \App\Fields\Tree::getPicklistValue(/** @scrutinizer ignore-type */ $this->getFieldParams(), $this->getModuleName());
Loading history...
1030
				$this->fieldInfo['treetemplate'] = $this->getFieldParams();
1031
				$this->fieldInfo['modulename'] = $this->getModuleName();
1032
				break;
1033
			case 'email':
1034
				if (\App\Config::security('EMAIL_FIELD_RESTRICTED_DOMAINS_ACTIVE') && !empty(\App\Config::security('EMAIL_FIELD_RESTRICTED_DOMAINS_VALUES'))) {
1035
					$validate = false;
1036
					if (empty(\App\Config::security('EMAIL_FIELD_RESTRICTED_DOMAINS_ALLOWED')) || \in_array($this->getModuleName(), \App\Config::security('EMAIL_FIELD_RESTRICTED_DOMAINS_ALLOWED'))) {
1037
						$validate = true;
1038
					}
1039
					if (\in_array($this->getModuleName(), \App\Config::security('EMAIL_FIELD_RESTRICTED_DOMAINS_EXCLUDED'))) {
1040
						$validate = false;
1041
					}
1042
					if ($validate) {
1043
						$this->fieldInfo['restrictedDomains'] = \App\Config::security('EMAIL_FIELD_RESTRICTED_DOMAINS_VALUES');
1044
					}
1045
				}
1046
				break;
1047
			default:
1048
				break;
1049
		}
1050
1051
		return $this->fieldInfo;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->fieldInfo returns the type void which is incompatible with the type-hinted return array.
Loading history...
1052
	}
1053
1054
	public function setFieldInfo($fieldInfo)
1055
	{
1056
		$this->fieldInfo = $fieldInfo;
1057
	}
1058
1059
	/**
1060
	 * Function to get the advanced filter option names by Field type.
1061
	 *
1062
	 * @return <Array>
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Array> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Array>.
Loading history...
1063
	 */
1064
	public static function getAdvancedFilterOpsByFieldType()
1065
	{
1066
		return [
1067
			'V' => ['e', 'n', 's', 'ew', 'c', 'k', 'y', 'ny', 'om', 'wr', 'nwr'],
1068
			'N' => ['e', 'n', 'l', 'g', 'm', 'h', 'y', 'ny'],
1069
			'T' => ['e', 'n', 'l', 'g', 'm', 'h', 'bw', 'b', 'a', 'y', 'ny'],
1070
			'I' => ['e', 'n', 'l', 'g', 'm', 'h', 'y', 'ny'],
1071
			'C' => ['e', 'n', 'y', 'ny'],
1072
			'D' => ['e', 'n', 'bw', 'b', 'a', 'y', 'ny'],
1073
			'DT' => ['e', 'n', 'bw', 'b', 'a', 'y', 'ny'],
1074
			'NN' => ['e', 'n', 'l', 'g', 'm', 'h', 'y', 'ny'],
1075
			'E' => ['e', 'n', 's', 'ew', 'c', 'k', 'y', 'ny'],
1076
		];
1077
	}
1078
1079
	/**
1080
	 * Function to retrieve field model for specific block and module.
1081
	 *
1082
	 * @param vtlib\ModuleBasic $moduleModel
1083
	 *
1084
	 * @return Vtiger_Field_Model[][]
1085
	 */
1086
	public static function getAllForModule(vtlib\ModuleBasic $moduleModel)
1087
	{
1088
		if (\App\Cache::staticHas('ModuleFields', $moduleModel->id)) {
1089
			return \App\Cache::staticGet('ModuleFields', $moduleModel->id);
1090
		}
1091
		$fieldModelList = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $fieldModelList is dead and can be removed.
Loading history...
1092
		$fieldObjects = parent::getAllForModule($moduleModel);
1093
		$fieldModelList = [];
1094
		if (!\is_array($fieldObjects)) {
0 ignored issues
show
introduced by
The condition is_array($fieldObjects) is always false.
Loading history...
1095
			$fieldObjects = [];
1096
		}
1097
		foreach ($fieldObjects as &$fieldObject) {
1098
			$fieldModel = self::getInstanceFromFieldObject($fieldObject);
1099
			$block = $fieldModel->get('block') ? $fieldModel->get('block')->id : 0;
1100
			$fieldModelList[$block][] = $fieldModel;
1101
			self::$instanceCacheById[$fieldModel->getId()] = $fieldModel;
1102
			self::$instanceCacheByName[$moduleModel->getId()][$fieldModel->getName()] = $fieldModel;
1103
		}
1104
		\App\Cache::staticSave('ModuleFields', $moduleModel->id, $fieldModelList);
1105
		return $fieldModelList;
1106
	}
1107
1108
	/**
1109
	 * Function to get new field model instance, the function creates a new object and does not pass a reference.
1110
	 *
1111
	 * @param string|int                $value  fieldname or field id
1112
	 * @param Vtiger_Module_Model|false $module optional - module instance
1113
	 *
1114
	 * @return Vtiger_Field_Model|false
1115
	 */
1116
	public static function getInstance($value, $module = false)
1117
	{
1118
		if (\is_numeric($value)) {
1119
			if (isset(self::$instanceCacheById[$value])) {
1120
				return clone self::$instanceCacheById[$value];
1121
			}
1122
		} elseif ($module) {
1123
			if (isset(self::$instanceCacheByName[$module->getId()][$value])) {
1124
				return clone self::$instanceCacheByName[$module->getId()][$value];
1125
			}
1126
		} else {
1127
			throw new \App\Exceptions\AppException("ERR_NOT_MODULE||$value||$module");
1128
		}
1129
		if ($fieldInstance = parent::getInstance($value, $module)) {
0 ignored issues
show
Bug introduced by
It seems like $module can also be of type false; however, parameter $moduleInstance of vtlib\Field::getInstance() does only seem to accept vtlib\Module, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1129
		if ($fieldInstance = parent::getInstance($value, /** @scrutinizer ignore-type */ $module)) {
Loading history...
1130
			$fieldModel = self::getInstanceFromFieldObject($fieldInstance);
1131
			self::$instanceCacheById[$fieldModel->getId()] = $fieldModel;
1132
			self::$instanceCacheByName[$fieldModel->get('tabid')][$value] = $fieldModel;
1133
			return $fieldModel;
1134
		}
1135
		return false;
1136
	}
1137
1138
	/**
1139
	 * Returns instance of field.
1140
	 *
1141
	 * @param array|string $fieldInfo
1142
	 *
1143
	 * @return bool|\Vtiger_Field_Model|\vtlib\Field|null
1144
	 */
1145
	public static function getInstanceFromFilter($fieldInfo)
1146
	{
1147
		if (\is_string($fieldInfo)) {
1148
			$fieldInfo = array_combine(['field_name', 'module_name', 'source_field_name'], array_pad(explode(':', $fieldInfo), 3, false));
1149
		}
1150
		return static::getInstance($fieldInfo['field_name'], Vtiger_Module_Model::getInstance($fieldInfo['module_name']));
1151
	}
1152
1153
	/**
1154
	 * Function checks if the current Field is Read/Write.
1155
	 *
1156
	 * @return bool
1157
	 */
1158
	public function getProfileReadWritePermission()
1159
	{
1160
		return $this->getPermissions(false);
1161
	}
1162
1163
	/**
1164
	 * Gets default validator.
1165
	 *
1166
	 * @return array
1167
	 */
1168
	public function getDefaultValidator(): array
1169
	{
1170
		$validator = [];
1171
		$fieldName = $this->getName();
1172
		switch ($fieldName) {
1173
			case 'birthday':
1174
				$funcName = ['name' => 'lessThanToday'];
1175
				$validator[] = $funcName;
1176
				break;
1177
			case 'targetenddate':
1178
			case 'actualenddate':
1179
			case 'enddate':
1180
				$funcName = ['name' => 'greaterThanDependentField',
1181
					'params' => ['startdate'], ];
1182
				$validator[] = $funcName;
1183
				break;
1184
			case 'startdate':
1185
				if ('Project' === $this->getModule()->get('name')) {
1186
					$params = ['targetenddate'];
1187
				} else {
1188
					//for project task
1189
					$params = ['enddate'];
1190
				}
1191
				$funcName = ['name' => 'lessThanDependentField',
1192
					'params' => $params, ];
1193
				$validator[] = $funcName;
1194
				break;
1195
			case 'expiry_date':
1196
			case 'due_date':
1197
				$funcName = ['name' => 'greaterThanDependentField',
1198
					'params' => ['start_date'], ];
1199
				$validator[] = $funcName;
1200
				break;
1201 29
			case 'sales_end_date':
1202
				$funcName = ['name' => 'greaterThanDependentField',
1203 29
					'params' => ['sales_start_date'], ];
1204
				$validator[] = $funcName;
1205
				break;
1206
			case 'sales_start_date':
1207
				$funcName = ['name' => 'lessThanDependentField',
1208
					'params' => ['sales_end_date'], ];
1209
				$validator[] = $funcName;
1210
				break;
1211
			case 'qty_per_unit':
1212
			case 'qtyindemand':
1213
			case 'hours':
1214
			case 'days':
1215
				$funcName = ['name' => 'PositiveNumber'];
1216
				$validator[] = $funcName;
1217
				break;
1218
			case 'employees':
1219
				$funcName = ['name' => 'WholeNumber'];
1220
				$validator[] = $funcName;
1221
				break;
1222
			case 'related_to':
1223
				$funcName = ['name' => 'ReferenceField'];
1224
				$validator[] = $funcName;
1225
				break;
1226 11
			//SRecurringOrders field sepecial validators
1227
			case 'end_period':
1228 11
				$funcName1 = ['name' => 'greaterThanDependentField',
1229
					'params' => ['start_period'], ];
1230
				$validator[] = $funcName1;
1231
				$funcName2 = ['name' => 'lessThanDependentField',
1232
					'params' => ['duedate'], ];
1233
				$validator[] = $funcName2;
1234
1235
			// no break
1236
			case 'start_period':
1237
				$funcName = ['name' => 'lessThanDependentField',
1238
					'params' => ['end_period'], ];
1239
				$validator[] = $funcName;
1240
				break;
1241
			default:
1242
				break;
1243
		}
1244
		return $validator;
1245
	}
1246
1247
	/**
1248
	 * Function returns Client Side Validators name.
1249
	 *
1250
	 * @return array [name=>Name of the Validator, params=>Extra Parameters]
1251
	 */
1252
	public function getValidator()
1253
	{
1254
		return method_exists($this->getUITypeModel(), 'getValidator') ? $this->getUITypeModel()->getValidator() : $this->getDefaultValidator();
1255
	}
1256
1257
	/**
1258
	 * Function to retrieve display value in edit view.
1259
	 *
1260
	 * @param mixed               $value
1261
	 * @param Vtiger_Record_Model $recordModel
1262 21
	 *
1263
	 * @return mixed
1264 21
	 */
1265
	public function getEditViewDisplayValue($value, $recordModel = false)
1266
	{
1267
		return $this->getUITypeModel()->getEditViewDisplayValue($value, $recordModel);
0 ignored issues
show
Bug introduced by
It seems like $recordModel can also be of type false; however, parameter $recordModel of Vtiger_Base_UIType::getEditViewDisplayValue() does only seem to accept Vtiger_Record_Model, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1267
		return $this->getUITypeModel()->getEditViewDisplayValue($value, /** @scrutinizer ignore-type */ $recordModel);
Loading history...
1268
	}
1269
1270
	/**
1271
	 * Function to retrieve user value in edit view.
1272 18
	 *
1273
	 * @param mixed               $value
1274 18
	 * @param Vtiger_Record_Model $recordModel
1275
	 *
1276 18
	 * @return mixed
1277
	 */
1278
	public function getEditViewValue($value, $recordModel = false)
1279 16
	{
1280
		return $this->getUITypeModel()->getEditViewValue($value, $recordModel);
0 ignored issues
show
Bug introduced by
It seems like $recordModel can also be of type false; however, parameter $recordModel of Vtiger_Base_UIType::getEditViewValue() does only seem to accept Vtiger_Record_Model, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1280
		return $this->getUITypeModel()->getEditViewValue($value, /** @scrutinizer ignore-type */ $recordModel);
Loading history...
1281 16
	}
1282
1283
	/**
1284
	 * Function to get Display value for RelatedList.
1285
	 *
1286
	 * @param string $value
1287
	 *
1288
	 * @return string
1289
	 */
1290
	public function getRelatedListDisplayValue($value)
1291
	{
1292
		return $this->getUITypeModel()->getRelatedListDisplayValue($value);
1293
	}
1294
1295
	/**
1296 16
	 * Function to get Default Field Value.
1297
	 *
1298 16
	 * @throws \Exception
1299
	 *
1300
	 * @return mixed
1301
	 */
1302
	public function getDefaultFieldValue()
1303
	{
1304
		return $this->getUITypeModel()->getDefaultValue();
1305
	}
1306
1307
	/**
1308
	 * Function whcih will get the databse insert value format from user format.
1309
	 *
1310
	 * @param type  $value       in user format
1311
	 * @param mixed $recordModel
1312
	 *
1313
	 * @return type
1314
	 */
1315
	public function getDBValue($value, $recordModel = false)
1316
	{
1317
		return $this->getUITypeModel()->getDBValue($value, $recordModel);
0 ignored issues
show
Bug introduced by
It seems like $recordModel can also be of type false; however, parameter $recordModel of Vtiger_Base_UIType::getDBValue() does only seem to accept Vtiger_Record_Model, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1317
		return $this->getUITypeModel()->getDBValue($value, /** @scrutinizer ignore-type */ $recordModel);
Loading history...
Bug Best Practice introduced by
The expression return $this->getUITypeM...e($value, $recordModel) returns the type string which is incompatible with the documented return type type.
Loading history...
1318
	}
1319
1320
	/**
1321
	 * Function to get visibilty permissions of a Field.
1322
	 *
1323
	 * @param bool $readOnly
1324
	 *
1325
	 * @return bool
1326
	 */
1327
	public function getPermissions($readOnly = true)
1328
	{
1329
		if (isset($this->permissions)) {
1330
			return $this->permissions;
1331
		}
1332
		return \App\Field::getFieldPermission($this->getModuleId(), $this->getName(), $readOnly);
1333
	}
1334
1335
	public function __update()
1336
	{
1337
		$dbCommand = \App\Db::getInstance()->createCommand();
1338 10
		1 === $this->get('generatedtype') ? $generatedType = 1 : $generatedType = 2;
1339
		$dbCommand->update('vtiger_field', ['typeofdata' => $this->get('typeofdata'), 'presence' => $this->get('presence'), 'quickcreate' => $this->get('quickcreate'),
1340 10
			'masseditable' => $this->get('masseditable'), 'header_field' => $this->get('header_field'), 'maxlengthtext' => $this->get('maxlengthtext'),
1341
			'maxwidthcolumn' => $this->get('maxwidthcolumn'), 'tabindex' => $this->get('tabindex'), 'defaultvalue' => $this->get('defaultvalue'), 'summaryfield' => $this->get('summaryfield'),
1342
			'displaytype' => $this->get('displaytype'), 'helpinfo' => $this->get('helpinfo'), 'generatedtype' => $generatedType,
1343
			'fieldparams' => $this->get('fieldparams'), 'quickcreatesequence' => $this->get('quicksequence'), 'icon' => $this->get('icon'), 'fieldlabel' => $this->get('label'),
1344
		], ['fieldid' => $this->get('id')])->execute();
1345
		if ($anonymizationTarget = $this->get('anonymizationTarget')) {
1346
			$anonymizationTarget = \App\Json::encode($anonymizationTarget);
1347
			$execute = $dbCommand->update('s_#__fields_anonymization', ['anonymization_target' => $anonymizationTarget], ['field_id' => $this->getId()])->execute();
1348
			if (!$execute) {
1349
				$dbCommand->insert('s_#__fields_anonymization', ['field_id' => $this->getId(), 'anonymization_target' => $anonymizationTarget])->execute();
1350
			}
1351
		} else {
1352
			$dbCommand->delete('s_#__fields_anonymization', ['field_id' => $this->getId()])->execute();
1353
		}
1354
		App\Cache::clear();
1355
	}
1356
1357
	public function updateTypeofDataFromMandatory($mandatoryValue = 'O')
1358
	{
1359
		$mandatoryValue = strtoupper($mandatoryValue);
1360
		$supportedMandatoryLiterals = ['O', 'M'];
1361
		if (!\in_array($mandatoryValue, $supportedMandatoryLiterals)) {
1362
			return;
1363
		}
1364
		$typeOfData = $this->get('typeofdata');
1365
		$components = explode('~', $typeOfData);
0 ignored issues
show
Bug introduced by
It seems like $typeOfData can also be of type null; however, parameter $string of explode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1365
		$components = explode('~', /** @scrutinizer ignore-type */ $typeOfData);
Loading history...
1366
		$components[1] = $mandatoryValue;
1367
		$this->set('typeofdata', implode('~', $components));
1368
1369
		return $this;
1370
	}
1371
1372
	public function isCustomField()
1373
	{
1374
		return 2 == $this->generatedtype;
1375
	}
1376
1377
	public function hasDefaultValue()
1378
	{
1379
		return !empty($this->defaultvalue);
1380
	}
1381
1382
	public function isActiveField()
1383
	{
1384
		return \in_array($this->get('presence'), [0, 2]);
1385
	}
1386
1387
	public function isMassEditable()
1388
	{
1389
		return 1 == $this->masseditable;
1390
	}
1391
1392
	public function isHeaderField()
1393
	{
1394
		return !empty($this->header_field);
1395
	}
1396 17
1397
	/**
1398 17
	 * Gets header field data.
1399 17
	 *
1400 17
	 * @throws \App\Exceptions\AppException
1401 17
	 *
1402 16
	 * @return mixed
1403
	 */
1404
	public function getHeaderField()
1405 1
	{
1406
		return !empty($this->header_field) ? \App\Json::decode($this->header_field) : [];
1407
	}
1408
1409
	/**
1410
	 * Gets header field value.
1411
	 *
1412
	 * @param string $type
1413
	 * @param mixed  $default
1414
	 *
1415
	 * @throws \App\Exceptions\AppException
1416
	 *
1417
	 * @return mixed
1418
	 */
1419
	public function getHeaderValue(string $type, $default = '')
1420
	{
1421
		return $this->getHeaderField()[$type] ?? $default;
1422
	}
1423 19
1424
	/**
1425 19
	 * Function which will check if empty piclist option should be given.
1426 19
	 *
1427 19
	 * @return bool
1428
	 */
1429
	public function isEmptyPicklistOptionAllowed()
1430 19
	{
1431 19
		if (method_exists($this->getUITypeModel(), 'isEmptyPicklistOptionAllowed')) {
1432 19
			return $this->getUITypeModel()->isEmptyPicklistOptionAllowed();
1433
		}
1434
		return true;
1435
	}
1436
1437
	/**
1438
	 * Check if it is a tree field.
1439
	 *
1440
	 * @return bool
1441
	 */
1442
	public function isTreeField(): bool
1443 19
	{
1444
		return \in_array($this->getFieldDataType(), ['tree', 'categoryMultipicklist']);
1445
	}
1446
1447
	public function isReferenceField()
1448
	{
1449
		return \in_array($this->getFieldDataType(), self::$referenceTypes);
1450
	}
1451
1452
	public function isOwnerField()
1453 21
	{
1454
		return (self::OWNER_TYPE == $this->getFieldDataType()) ? true : false;
1455 21
	}
1456 21
1457
	/**
1458
	 * Is summation field.
1459 21
	 *
1460 21
	 * @return bool
1461 2
	 */
1462
	public function isCalculateField()
1463 19
	{
1464 19
		return $this->isCalculateField && !$this->get('fromOutsideList') && (\in_array($this->getUIType(), [71, 7, 317, 8]) || \in_array($this->getFieldDataType(), ['integer', 'double']));
1465
	}
1466
1467 19
	/**
1468 19
	 * Function returns field instance for field ID.
1469 19
	 *
1470 8
	 * @param int $fieldId
1471 11
	 * @param int $moduleTabId
1472 2
	 *
1473 1
	 * @return \Vtiger_Field_Model
1474
	 */
1475 1
	public static function getInstanceFromFieldId($fieldId, $moduleTabId = false)
1476 9
	{
1477
		if (isset(self::$instanceCacheById[$fieldId])) {
1478
			return self::$instanceCacheById[$fieldId];
1479
		}
1480
		$field = \App\Field::getFieldInfo($fieldId);
1481 9
		$className = Vtiger_Loader::getComponentClassName('Model', 'Field', \App\Module::getModuleName($field['tabid']));
1482 2
		$fieldModel = new $className();
1483
		$fieldModel->initialize($field, $field['tabid']);
1484
		self::$instanceCacheById[$fieldModel->getId()] = $fieldModel;
1485 2
		self::$instanceCacheByName[$fieldModel->get('tabid')][$fieldModel->getName()] = $fieldModel;
1486 7
		return $fieldModel;
1487 3
	}
1488 4
1489 4
	public function getWithDefaultValue()
1490
	{
1491
		$defaultValue = $this->getDefaultFieldValue();
1492
		$recordValue = $this->get('fieldvalue');
1493
		if (empty($recordValue) && !$defaultValue) {
1494
			$this->set('fieldvalue', $defaultValue);
1495
		}
1496
		return $this;
1497
	}
1498
1499
	/**
1500
	 * Get field params.
1501
	 *
1502
	 * @return array
1503
	 */
1504
	public function getFieldParams()
1505
	{
1506
		if (!\is_array($this->get('fieldparams')) && \App\Json::isJson($this->get('fieldparams'))) {
1507
			return \App\Json::decode($this->get('fieldparams'));
1508
		}
1509
		return $this->get('fieldparams') ?: [];
1510
	}
1511
1512
	/**
1513
	 * Get field icon.
1514
	 *
1515
	 * @param string $place
1516
	 *
1517
	 * @return array
1518
	 */
1519
	public function getIcon(string $place = ''): array
1520
	{
1521
		$icon = [];
1522
		if (\is_array($this->get('icon'))) {
1523
			$icon = $this->get('icon');
1524
		} elseif ($this->get('icon') && \App\Json::isJson($this->get('icon'))) {
1525
			$icon = \App\Json::decode($this->get('icon'));
1526
		}
1527
		if ($place && isset($icon['place']) && !\in_array($place, $icon['place'])) {
1528
			$icon = [];
1529
		}
1530
		return $icon;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $icon could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
1531
	}
1532
1533
	/**
1534
	 * Get anonymization target.
1535
	 *
1536
	 * @see \App\Anonymization::getTypes()
1537
	 *
1538
	 * @return int[]
1539
	 */
1540
	public function getAnonymizationTarget(): array
1541
	{
1542
		if (\is_string($this->get('anonymizationTarget'))) {
1543
			$this->set('anonymizationTarget', \App\Json::decode($this->get('anonymizationTarget')));
1544
		}
1545
		return $this->get('anonymizationTarget');
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get('anonymizationTarget') could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
1546
	}
1547
1548
	/**
1549
	 * Get maximum value.
1550
	 *
1551
	 * @return string|null
1552
	 */
1553
	public function getMaxValue(): ?string
1554
	{
1555
		if (($maximumLength = $this->get('maximumlength')) && false !== strpos($maximumLength, ',')) {
1556
			$maximumLength = explode(',', $maximumLength)[1];
1557
		}
1558
		return $maximumLength;
1559
	}
1560
1561
	public function isActiveSearchView()
1562
	{
1563
		if ($this->get('fromOutsideList') || $this->get('searchLockedFields')) {
1564
			return false;
1565
		}
1566
		return $this->getUITypeModel()->isActiveSearchView();
1567
	}
1568
1569
	/**
1570
	 * Empty value search in view.
1571
	 *
1572
	 * @return bool
1573
	 */
1574
	public function searchLockedEmptyFields(): bool
1575
	{
1576
		return empty($this->get('searchLockedEmptyFields'));
1577
	}
1578
1579
	/**
1580
	 * Function returns info about field structure in database.
1581
	 *
1582
	 * @param bool $returnString
1583
	 *
1584
	 * @return array|string
1585
	 */
1586
	public function getDBColumnType($returnString = true)
1587
	{
1588
		$db = \App\Db::getInstance();
1589
		$tableSchema = $db->getSchema()->getTableSchema($this->getTableName(), true);
1590
		if (empty($tableSchema)) {
1591
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type array|string.
Loading history...
1592
		}
1593
		$columnSchema = $tableSchema->getColumn($this->getColumnName());
1594
		$data = get_object_vars($columnSchema);
1595
		if ($returnString) {
1596
			$string = $data['type'];
1597
			if ($data['size']) {
1598
				if ('decimal' === $data['type']) {
1599
					$string .= '(' . $data['size'] . ',' . $data['scale'] . ')';
1600
				} else {
1601
					$string .= '(' . $data['size'] . ')';
1602
				}
1603
			}
1604
			return $string;
1605
		}
1606
		return $data;
1607
	}
1608
1609
	/**
1610
	 * Function to get range of values.
1611
	 *
1612
	 * @throws \App\Exceptions\AppException
1613
	 *
1614
	 * @return string|null
1615
	 */
1616
	public function getRangeValues()
1617
	{
1618
		$uiTypeModel = $this->getUITypeModel();
1619
		if (method_exists($uiTypeModel, 'getRangeValues')) {
1620
			return $uiTypeModel->getRangeValues();
1621
		}
1622
		$allowedTypes = $uiTypeModel->getAllowedColumnTypes();
1623
		if (null === $allowedTypes) {
0 ignored issues
show
introduced by
The condition null === $allowedTypes is always false.
Loading history...
1624
			return;
1625
		}
1626
		$data = $this->getDBColumnType(false);
1627
		if (!\in_array($data['type'], $allowedTypes)) {
1628
			throw new \App\Exceptions\AppException('ERR_NOT_ALLOWED_TYPE||' . $data['type'] . '||' . print_r($allowedTypes, true));
0 ignored issues
show
Bug introduced by
Are you sure print_r($allowedTypes, true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1628
			throw new \App\Exceptions\AppException('ERR_NOT_ALLOWED_TYPE||' . $data['type'] . '||' . /** @scrutinizer ignore-type */ print_r($allowedTypes, true));
Loading history...
1629
		}
1630
		preg_match('/^([\w\-]+)/i', $data['dbType'], $matches);
1631
		$type = $matches[1] ?? $data['type'];
1632
		$uitype = $this->getUIType();
1633
		if (isset(self::$uiTypeMaxLength[$uitype])) {
1634
			$range = self::$uiTypeMaxLength[$uitype];
1635
		} elseif (isset(self::$typesMaxLength[$type])) {
1636
			$range = self::$typesMaxLength[$type];
1637
		} else {
1638
			switch ($type) {
1639
				case 'binary':
1640
				case 'string':
1641
				case 'varchar':
1642
				case 'varbinary':
1643
					$range = (int) $data['size'];
1644
					break;
1645
				case 'bigint':
1646
				case 'mediumint':
1647
					throw new \App\Exceptions\AppException("ERR_NOT_ALLOWED_TYPE||$type||integer,smallint,tinyint");
1648
				case 'integer':
1649
				case 'int':
1650
					if ($data['unsigned']) {
1651
						$range = '4294967295';
1652
					} else {
1653
						$range = '-2147483648,2147483647';
1654
					}
1655
					break;
1656
				case 'smallint':
1657
					if ($data['unsigned']) {
1658
						$range = '65535';
1659
					} else {
1660
						$range = '-32768,32767';
1661
					}
1662
					break;
1663
				case 'tinyint':
1664
					if ($data['unsigned']) {
1665
						$range = '255';
1666
					} else {
1667
						$range = '-128,127';
1668
					}
1669
					break;
1670
				case 'decimal':
1671
					$range = 10 ** (((int) $data['size']) - ((int) $data['scale'])) - 1;
1672
					break;
1673
				default:
1674
					$range = null;
1675
					break;
1676
			}
1677
		}
1678
		return $range;
1679
	}
1680
1681
	/**
1682
	 * Return allowed query operators for field.
1683
	 *
1684
	 * @return string[]
1685
	 */
1686
	public function getQueryOperators(): array
1687
	{
1688
		$operators = $this->getUITypeModel()->getQueryOperators();
1689
		$oper = [];
1690
		foreach ($operators as $op) {
1691
			$label = '';
1692
			if (isset(\App\Condition::STANDARD_OPERATORS[$op])) {
1693
				$label = \App\Condition::STANDARD_OPERATORS[$op];
1694
			} elseif (isset(\App\Condition::DATE_OPERATORS[$op])) {
1695
				$label = \App\Condition::DATE_OPERATORS[$op]['label'];
1696
			}
1697
			$oper[$op] = $label;
1698
		}
1699
		return $oper;
1700
	}
1701
1702
	/**
1703
	 * Return allowed record operators for field.
1704
	 *
1705
	 * @return string[]
1706
	 */
1707
	public function getRecordOperators(): array
1708
	{
1709
		$operators = $this->getUITypeModel()->getRecordOperators();
1710
		$oper = [];
1711
		foreach ($operators as $op) {
1712
			$label = '';
1713
			if (isset(\App\Condition::STANDARD_OPERATORS[$op])) {
1714
				$label = \App\Condition::STANDARD_OPERATORS[$op];
1715
			} elseif (isset(\App\Condition::DATE_OPERATORS[$op])) {
1716
				$label = \App\Condition::DATE_OPERATORS[$op]['label'];
1717
			}
1718
			$oper[$op] = $label;
1719
		}
1720
		return $oper;
1721
	}
1722
1723
	/**
1724
	 * Returns template for operator.
1725
	 *
1726
	 * @param string $operator
1727
	 *
1728
	 * @return string
1729
	 */
1730
	public function getOperatorTemplateName(string $operator)
1731
	{
1732
		if (\in_array($operator, array_merge(\App\Condition::OPERATORS_WITHOUT_VALUES, array_keys(App\Condition::DATE_OPERATORS)))) {
1733
			return;
1734
		}
1735
		if (\in_array($operator, \App\Condition::FIELD_COMPARISON_OPERATORS)) {
1736
			return 'ConditionBuilder/FieldsListUitype.tpl';
1737
		}
1738
		return $this->getUITypeModel()->getOperatorTemplateName($operator);
1739
	}
1740
1741
	/**
1742
	 * Function to get the field model for condition builder.
1743
	 *
1744
	 * @param string $operator
1745
	 *
1746
	 * @return self
1747
	 */
1748
	public function getConditionBuilderField(string $operator): self
1749
	{
1750
		return $this->getUITypeModel()->getConditionBuilderField($operator);
1751
	}
1752
1753
	/**
1754
	 * Sets data.
1755
	 *
1756
	 * @param array $data
1757
	 *
1758
	 * @return self
1759
	 */
1760
	public function setData(array $data = [])
1761
	{
1762
		foreach ($data as $key => $value) {
1763
			$this->set($key, $value);
1764
		}
1765
		return $this;
1766
	}
1767
1768
	/**
1769
	 * TabIndex last sequence number.
1770
	 *
1771
	 * @var int
1772
	 */
1773
	public static $tabIndexLastSeq = 0;
1774
	/**
1775
	 * TabIndex default sequence number.
1776
	 *
1777
	 * @var int
1778
	 */
1779
	public static $tabIndexDefaultSeq = 0;
1780
1781
	/**
1782
	 * Get TabIndex.
1783
	 *
1784
	 * @return int
1785
	 */
1786
	public function getTabIndex(): int
1787
	{
1788
		$tabindex = 0;
1789
		if (0 !== $this->get('tabindex')) {
1790
			$tabindex = $this->get('tabindex');
1791
		} elseif (self::$tabIndexLastSeq) {
1792
			$tabindex = self::$tabIndexLastSeq;
1793
		}
1794
		return $tabindex + self::$tabIndexDefaultSeq;
1795
	}
1796
1797
	/** {@inheritdoc} */
1798
	public function delete()
1799
	{
1800
		$this->getUITypeModel()->delete();
1801
		Settings_FieldsDependency_Module_Model::removeField($this->getModuleName(), $this->getName());
0 ignored issues
show
Bug introduced by
It seems like $this->getModuleName() can also be of type boolean; however, parameter $moduleName of Settings_FieldsDependenc...le_Model::removeField() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1801
		Settings_FieldsDependency_Module_Model::removeField(/** @scrutinizer ignore-type */ $this->getModuleName(), $this->getName());
Loading history...
1802
		\App\Utils\Kanban::deleteField($this->getModuleName(), $this->getName());
0 ignored issues
show
Bug introduced by
It seems like $this->getModuleName() can also be of type boolean; however, parameter $moduleName of App\Utils\Kanban::deleteField() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1802
		\App\Utils\Kanban::deleteField(/** @scrutinizer ignore-type */ $this->getModuleName(), $this->getName());
Loading history...
1803
		$this->getModule()->clearCache();
1804
		parent::delete();
1805
	}
1806
}
1807