Passed
Push — developer ( 762b64...a1cff0 )
by Radosław
20:19
created

Vtiger_Field_Model::getQueryOperators()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
eloc 10
dl 0
loc 14
ccs 0
cts 0
cp 0
rs 9.9332
c 0
b 0
f 0
cc 4
nc 4
nop 0
crap 20

1 Method

Rating   Name   Duplication   Size   Complexity  
A Vtiger_Field_Model::getQueryOperatorLabels() 0 3 1
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
		99 => 100,
30
		120 => 65535,
31
		106 => '3,64',
32
		156 => '3',
33
		360 => '0,99999999',
34
	];
35
36
	/** @var int[] Field maximum length by db type. */
37
	public static $typesMaxLength = [
38
		'tinytext' => 255,
39
		'text' => 65535,
40
		'mediumtext' => 16777215,
41
		'longtext' => 4294967295,
42
		'blob' => 65535,
43
		'mediumblob' => 16777215,
44
		'longblob' => 4294967295,
45
	];
46
47
	/** @var Vtiger_Field_Model[] Cache by field id */
48
	protected static $instanceCacheById = [];
49
50
	/** @var Vtiger_Field_Model[][] Cache by module id and field id */
51
	protected static $instanceCacheByName = [];
52
53
	/**
54
	 * @var array
55
	 */
56
	protected $fieldInfo;
57
	protected $fieldType;
58
	protected $fieldDataTypeShort;
59
	protected $uitype_instance;
60
61 118
	/** @var string[] List of modules the field referenced to. */
62
	public $referenceList;
63 118
64 118
	/** @var string[] Picklist values only for custom fields;. */
65
	public $picklistValues;
66 4
67
	/** @var bool Is calculate field */
68
	protected $isCalculateField = true;
69
70
	/** @var bool|null Field visibility permissions */
71
	protected $permissions;
72
73
	/** @var Vtiger_Base_UIType Vtiger_Base_UIType or UI Type specific model instance */
74
	protected $uitypeModel;
75
76
	/** @var bool[] Permissions cache */
77 30
	protected $permissionsCache = [];
78
79 30
	/**
80
	 * Initialize.
81 30
	 *
82
	 * @param string     $module
83
	 * @param array      $data
84
	 * @param mixed|null $name
85
	 *
86
	 * @return \Vtiger_Field_Model
87
	 */
88
	public static function init($module = 'Vtiger', $data = [], $name = '')
89 64
	{
90
		if (\App\Module::getModuleId($module)) {
91 64
			$moduleModel = Vtiger_Module_Model::getInstance($module);
92
		} else {
93
			$modelClassName = \Vtiger_Loader::getComponentClassName('Model', 'Module', $module);
94
			$moduleModel = new $modelClassName();
95
		}
96
		$modelClassName = \Vtiger_Loader::getComponentClassName('Model', 'Field', $module);
97
		$instance = new $modelClassName();
98
		$instance->setModule($moduleModel);
99 67
		$instance->setData(array_merge([
100
			'uitype' => 1,
101 67
			'column' => $name,
102
			'name' => $name,
103
			'label' => $name,
104
			'displaytype' => 1,
105
			'typeofdata' => 'V~O',
106
			'presence' => 0,
107
			'isReadOnly' => false,
108
			'isEditableReadOnly' => false,
109 53
		], $data));
110
		return $instance;
111 53
	}
112
113
	/**
114
	 * Function to get the value of a given property.
115
	 *
116
	 * @param string $propertyName
117
	 *
118
	 * @return mixed|null
119 6
	 */
120
	public function get(string $propertyName)
121 6
	{
122
		if (property_exists($this, $propertyName)) {
123
			return $this->{$propertyName};
124
		}
125
		return null;
126
	}
127
128
	/**
129 5813
	 * Function which sets value for given name.
130
	 *
131 5813
	 * @param string $name  - name for which value need to be assinged
132
	 * @param mixed  $value - values that need to be assigned
133
	 *
134
	 * @return Vtiger_Field_Model
135
	 */
136
	public function set(string $name, $value)
137
	{
138
		$this->{$name} = $value;
139 5836
		return $this;
140
	}
141 5836
142
	/**
143
	 * Function to get the Field Id.
144
	 *
145
	 * @return int
146
	 */
147
	public function getId()
148
	{
149 37
		return $this->id;
150
	}
151 37
152
	/**
153
	 * Get name.
154
	 *
155
	 * @return string
156
	 */
157
	public function getName()
158
	{
159
		return $this->name;
160
	}
161
162
	/**
163
	 * Get full name.
164
	 *
165
	 * @return string
166
	 */
167
	public function getFullName()
168
	{
169 16
		return $this->get('source_field_name') ? "{$this->getName()}:{$this->getModuleName()}:{$this->get('source_field_name')}" : $this->getName();
170
	}
171 16
172 3
	/**
173 3
	 * Get full label translation.
174
	 *
175
	 * @param Vtiger_Module_Model|null $module
176 3
	 *
177
	 * @return string
178
	 */
179 3
	public function getFullLabelTranslation(?Vtiger_Module_Model $module = null): string
180
	{
181 16
		$translation = '';
182
		if ($this->get('source_field_name') && !$this->get('isLabelCustomized')) {
183
			if (!$module) {
184
				throw new \App\Exceptions\AppException('ERR_ARGUMENT_DOES_NOT_EXIST');
185
			}
186
			$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

186
			$translation = \App\Language::translate($module->getFieldByName($this->get('source_field_name'))->getFieldLabel(), /** @scrutinizer ignore-type */ $module->getName()) . ' - ';
Loading history...
Deprecated Code introduced by
The function Vtiger_Field_Model::getFieldLabel() has been deprecated: 7.0 Use $this->getLabel() ( Ignorable by Annotation )

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

186
			$translation = \App\Language::translate(/** @scrutinizer ignore-deprecated */ $module->getFieldByName($this->get('source_field_name'))->getFieldLabel(), $module->getName()) . ' - ';

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...
187
		}
188
		return $translation .= \App\Language::translate($this->getFieldLabel(), $this->getModuleName());
0 ignored issues
show
Deprecated Code introduced by
The function Vtiger_Field_Model::getFieldLabel() has been deprecated: 7.0 Use $this->getLabel() ( Ignorable by Annotation )

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

188
		return $translation .= \App\Language::translate(/** @scrutinizer ignore-deprecated */ $this->getFieldLabel(), $this->getModuleName());

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...
189
	}
190
191
	/**
192
	 * Get field name.
193
	 *
194
	 * @deprecated Use $this->getName()
195
	 *
196
	 * @return string
197
	 */
198
	public function getFieldName()
199
	{
200
		return $this->name;
201 5785
	}
202
203 5785
	/**
204
	 * Get field label.
205
	 *
206
	 * @deprecated 7.0 Use $this->getLabel()
207
	 *
208
	 * @return string
209
	 */
210
	public function getFieldLabel()
211 11
	{
212
		return $this->getLabel();
213 11
	}
214
215
	/**
216
	 * Get field label.
217
	 *
218
	 * @return string
219
	 */
220
	public function getLabel(): string
221 89
	{
222
		return $this->label;
223 89
	}
224 69
225 69
	/**
226
	 * Get table name.
227
	 *
228 69
	 * @return string
229
	 */
230 69
	public function getTableName()
231 23
	{
232
		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...
233 68
	}
234 68
235 10
	/**
236 10
	 * Get column label.
237 68
	 *
238
	 * @return string
239
	 */
240 68
	public function getColumnName()
241 7
	{
242 7
		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...
243 66
	}
244 3
245 3
	/**
246 66
	 * Get ui type.
247 3
	 *
248 3
	 * @return int
249 66
	 */
250 7
	public function getUIType()
251 7
	{
252 66
		return $this->uitype;
253 10
	}
254 10
255 66
	/**
256 11
	 * Function to retrieve full data.
257 11
	 *
258 66
	 * @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...
259
	 */
260
	public function getData()
261 66
	{
262 3
		return get_object_vars($this);
263 3
	}
264 66
265 3
	/**
266 3
	 * Get module model.
267 66
	 *
268 3
	 * @return Vtiger_Module_Model
269 3
	 */
270 66
	public function getModule()
271 3
	{
272 3
		if (!isset($this->module)) {
273 66
			if (isset($this->block->module)) {
274 3
				$moduleObj = $this->block->module;
275 3
			}
276 66
			//fix for opensource emailTemplate listview break
277 10
			if (empty($moduleObj)) {
278 10
				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...
279 65
			}
280 65
			$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...
281 8
		}
282 8
		return $this->module;
283 65
	}
284 8
285 8
	public function setModule($moduleInstance)
286 65
	{
287 7
		$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...
288 7
		return $this;
289 65
	}
290 7
291 7
	/**
292 65
	 * Function to retieve display value for a value.
293 7
	 *
294 7
	 * @param mixed                    $value          value which need to be converted to display value
295 65
	 * @param bool|int                 $record
296 8
	 * @param bool|Vtiger_Record_Model $recordInstance
297 8
	 * @param bool                     $rawText
298 65
	 * @param bool|int                 $length         Length of the text
299 9
	 * @param mixed                    $recordModel
300 9
	 *
301 65
	 * @return mixed converted display value
302 8
	 */
303 8
	public function getDisplayValue($value, $record = false, $recordModel = false, $rawText = false, $length = false)
304 65
	{
305 8
		return $this->getUITypeModel()->getDisplayValue($value, $record, $recordModel, $rawText, $length);
306 8
	}
307 63
308 5
	/**
309 5
	 * Function to retrieve display type of a field.
310 63
	 *
311 4
	 * @return int display type of the field
312 4
	 */
313 63
	public function getDisplayType()
314 6
	{
315 6
		return (int) $this->get('displaytype');
316 61
	}
317 3
318 3
	/**
319 61
	 * Function to get the Webservice Field data type.
320 6
	 *
321 6
	 * @return string Data type of the field
322 59
	 */
323 4
	public function getFieldDataType()
324 4
	{
325 59
		if (!isset($this->fieldDataType)) {
326 6
			$uiType = $this->getUIType();
327 6
			if (55 === $uiType) {
328 59
				$cacheName = $uiType . '-' . $this->getName();
329 1
			} else {
330 1
				$cacheName = $uiType . '-' . $this->get('typeofdata');
331 59
			}
332
			if (App\Cache::has('FieldDataType', $cacheName)) {
333
				$fieldDataType = App\Cache::get('FieldDataType', $cacheName);
334 59
			} else {
335 7
				switch ($uiType) {
336 7
					case 4:
337 59
						$fieldDataType = 'recordNumber';
338 3
						break;
339 3
					case 8:
340 59
						$fieldDataType = 'totalTime';
341 4
						break;
342 4
					case 9:
343 59
						$fieldDataType = 'percentage';
344 4
						break;
345 4
					case 12:
346 58
						$fieldDataType = 'accountName';
347
						break;
348
					case 18:
349
						$fieldDataType = 'multipicklistTags';
350 58
						break;
351 58
					case 27:
352 45
						$fieldDataType = 'fileLocationType';
353
						break;
354 33
					case 28:
355 33
						$fieldDataType = 'documentsFileUpload';
356 33
						break;
357 5
					case 31:
358 5
						$fieldDataType = 'theme';
359 31
						break;
360 14
					case 32:
361 14
						$fieldDataType = 'languages';
362 28
						break;
363 9
					case 35:
364 9
						$fieldDataType = 'country';
365 27
						break;
366 8
					case 54:
367 8
						$fieldDataType = 'multiowner';
368 27
						break;
369 26
					case 64:
370 17
						$fieldDataType = 'referenceSubProcessSL';
371 17
						break;
372 23
					case 65:
373
						$fieldDataType = 'referenceExtend';
374
						break;
375 23
					case 66:
376 18
						$fieldDataType = 'referenceProcess';
377 18
						break;
378 19
					case 67:
379
						$fieldDataType = 'referenceLink';
380 19
						break;
381 19
					case 68:
382
						$fieldDataType = 'referenceSubProcess';
383
						break;
384 58
					case 69:
385
						$fieldDataType = 'image';
386 68
						break;
387
					case 79:
388 69
					case 80:
389
						$fieldDataType = 'datetime';
390 89
						break;
391
					case 86:
392
						$fieldDataType = 'pbx';
393
						break;
394
					case 87:
395
						$fieldDataType = 'mailComposer';
396
						break;
397
					case 88:
398 6
						$fieldDataType = 'mailServer';
399
						break;
400 6
					case 89:
401 3
						$fieldDataType = 'mailFolders';
402
						break;
403 6
					case 98:
404 1
						$fieldDataType = 'userRole';
405
						break;
406 6
					case 99:
407 5
						$fieldDataType = 'password';
408 5
						break;
409 5
					case 101:
410 5
						$fieldDataType = 'userReference';
411 5
						break;
412 5
					case 115:
413
						$fieldDataType = 'picklist';
414 5
						break;
415 5
					case 117:
416 5
						$fieldDataType = 'currencyList';
417 5
						break;
418 5
					case 120:
419 5
						$fieldDataType = 'sharedOwner';
420
						break;
421 6
					case 301:
422 6
						$fieldDataType = 'modules';
423 6
						break;
424 6
					case 302:
425
						$fieldDataType = 'tree';
426
						break;
427
					case 303:
428 6
						$fieldDataType = 'taxes';
429
						break;
430 6
					case 304:
431
						$fieldDataType = 'inventoryLimit';
432
						break;
433
					case 305:
434
						$fieldDataType = 'multiReferenceValue';
435
						break;
436
					case 308:
437
						$fieldDataType = 'rangeTime';
438
						break;
439
					case 309:
440
						$fieldDataType = 'categoryMultipicklist';
441
						break;
442
					case 311:
443
						$fieldDataType = 'multiImage';
444
						break;
445
					case 312:
446
						$fieldDataType = 'authySecretTotp';
447
						break;
448
					case 313:
449
						$fieldDataType = 'twitter';
450
						break;
451
					case 314:
452
						$fieldDataType = 'multiEmail';
453
						break;
454
					case 315:
455
						$fieldDataType = 'multiDependField';
456
						break;
457
					case 316:
458
						$fieldDataType = 'smtp';
459
						break;
460
					case 317:
461
						$fieldDataType = 'currencyInventory';
462 5851
						break;
463
					case 318:
464 5851
						$fieldDataType = 'serverAccess';
465 5827
						break;
466
					case 319:
467 44
						$fieldDataType = 'multiDomain';
468
						break;
469
					case 320:
470
						$fieldDataType = 'multiListFields';
471
						break;
472
					case 321:
473
						$fieldDataType = 'multiReference';
474
						break;
475
					case 322:
476
						$fieldDataType = 'mailScannerActions';
477
						break;
478
					case 323:
479
						$fieldDataType = 'mailScannerFields';
480
						break;
481
					case 324:
482 4
						$fieldDataType = 'token';
483
						break;
484 4
					case 325:
485
						$fieldDataType = 'magentoServer';
486
						break;
487
					case 326:
488
						$fieldDataType = 'meetingUrl';
489
						break;
490
					case 327:
491
						$fieldDataType = 'barcode';
492
						break;
493
					case 328:
494 4
						$fieldDataType = 'changesJson';
495
						break;
496 4
					case 329:
497
						$fieldDataType = 'iban';
498
						break;
499 4
					case 330:
500 4
						$fieldDataType = 'multiAttachment';
501 4
						break;
502 4
					case 331:
503 3
						$fieldDataType = 'mapCoordinates';
504 3
						break;
505
					case 332:
506 2
						$fieldDataType = 'woocommerceServer';
507
						break;
508 4
					case 333:
509 1
						$fieldDataType = 'group';
510
						break;
511
					default:
512 4
						$fieldsDataType = App\Field::getFieldsTypeFromUIType();
513 3
						if (isset($fieldsDataType[$uiType])) {
514 3
							$fieldDataType = $fieldsDataType[$uiType]['fieldtype'];
515
						} else {
516
							$fieldTypeArray = explode('~', $this->get('typeofdata'));
517
							switch ($fieldTypeArray[0]) {
518
								case 'T':
519
									$fieldDataType = 'time';
520
									break;
521
								case 'D':
522 4
									$fieldDataType = 'date';
523
									break;
524
								case 'DT':
525
									$fieldDataType = 'datetime';
526
									break;
527
								case 'E':
528
									$fieldDataType = 'email';
529
									break;
530
								case 'N':
531
								case 'NN':
532
									$fieldDataType = 'double';
533
									break;
534
								case 'P':
535
									$fieldDataType = 'password';
536
									break;
537
								case 'I':
538
									$fieldDataType = 'integer';
539
									break;
540
								case 'V':
541
								default:
542
									$fieldDataType = 'string';
543
									break;
544
							}
545
						}
546
						break;
547
				}
548
				App\Cache::save('FieldDataType', $cacheName, $fieldDataType);
549
			}
550
			$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...
551
		}
552
		return $this->fieldDataType;
553
	}
554
555
	/**
556
	 * Function to get list of modules the field refernced to.
557
	 *
558
	 * @return string[] list of modules for which field is refered to
559
	 */
560 16
	public function getReferenceList()
561
	{
562 16
		if (isset($this->referenceList)) {
563 16
			return $this->referenceList;
564
		}
565
		if (\App\Cache::has('getReferenceList', $this->getId())) {
566
			return \App\Cache::get('getReferenceList', $this->getId());
567
		}
568
		if (method_exists($this->getUITypeModel(), 'getReferenceList')) {
569
			$list = $this->getUITypeModel()->getReferenceList();
570
		} else {
571 17
			if (10 === $this->getUIType()) {
572
				$query = (new \App\Db\Query())->select(['module' => 'relmodule'])
573 17
					->from('vtiger_fieldmodulerel')
574 6
					->innerJoin('vtiger_tab', 'vtiger_tab.name = vtiger_fieldmodulerel.relmodule')
575
					->where(['fieldid' => $this->getId()])
576 14
					->andWhere(['<>', 'vtiger_tab.presence', 1])
577 14
					->orderBy(['sequence' => SORT_ASC]);
578 14
			} else {
579
				$query = (new \App\Db\Query())->select(['module' => 'vtiger_ws_referencetype.type'])
580
					->from('vtiger_ws_referencetype')
581 14
					->innerJoin('vtiger_ws_fieldtype', 'vtiger_ws_referencetype.fieldtypeid = vtiger_ws_fieldtype.fieldtypeid')
582
					->innerJoin('vtiger_tab', 'vtiger_tab.name = vtiger_ws_referencetype.type')
583 14
					->where(['vtiger_ws_fieldtype.uitype' => $this->getUIType()])
584
					->andWhere(['<>', 'vtiger_tab.presence', 1]);
585
			}
586
			$list = [];
587
			foreach ($query->column() as $moduleName) {
588
				if (\App\Privilege::isPermitted($moduleName)) {
589
					$list[] = $moduleName;
590
				}
591 11
			}
592
		}
593 11
		\App\Cache::save('getReferenceList', $this->getId(), $list);
594 3
		return $list;
595
	}
596 11
597
	/**
598
	 * Function to check if the field is named field of the module.
599
	 *
600
	 * @return bool
601
	 */
602
	public function isNameField(): bool
603
	{
604 6
		$moduleModel = $this->getModule();
605
		return $moduleModel && !$this->isReferenceField() && !\in_array($this->getFieldDataType(), ['email', 'url', 'phone']) && \in_array($this->getName(), $moduleModel->getNameFields());
606
	}
607 6
608 6
	/**
609
	 * Function to get the UI Type model for the uitype of the current field.
610 4
	 *
611
	 * @return Vtiger_Base_UIType Vtiger_Base_UIType or UI Type specific model instance
612 6
	 */
613
	public function getUITypeModel(): Vtiger_Base_UIType
614
	{
615
		if (isset($this->uitypeModel)) {
616
			return $this->uitypeModel;
617
		}
618
		return $this->uitypeModel = Vtiger_Base_UIType::getInstanceFromField($this);
619
	}
620
621
	public function isRoleBased()
622
	{
623
		return 15 === $this->get('uitype') || 33 === $this->get('uitype');
624
	}
625
626
	/**
627
	 * Function to get all the available picklist values for the current field.
628
	 *
629
	 * @param bool $skipCheckingRole
630
	 *
631
	 * @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...
632
	 */
633
	public function getPicklistValues($skipCheckingRole = false)
634
	{
635
		if (isset($this->picklistValues)) {
636
			return $this->picklistValues;
637
		}
638
		$fieldDataType = $this->getFieldDataType();
639
		$fieldPickListValues = [];
640
		if ('picklist' === $fieldDataType || 'multipicklist' === $fieldDataType || 'multipicklistTags' === $fieldDataType) {
641
			if ($this->isRoleBased() && !$skipCheckingRole) {
642
				$picklistValues = \App\Fields\Picklist::getRoleBasedValues($this->getName(), \App\User::getCurrentUserModel()->getRole());
643
			} else {
644
				$picklistValues = App\Fields\Picklist::getValuesName($this->getName());
645
			}
646
			foreach ($picklistValues as $value) {
647
				$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

647
				$fieldPickListValues[$value] = \App\Language::translate($value, $this->getModuleName(), /** @scrutinizer ignore-type */ false, false);
Loading history...
648
			}
649
			// Protection against deleting a value that does not exist on the list
650
			if ('picklist' === $fieldDataType) {
651
				$fieldValue = $this->get('fieldvalue');
652
				if (!empty($fieldValue) && !isset($fieldPickListValues[$fieldValue])) {
653
					$fieldPickListValues[$fieldValue] = \App\Language::translate($fieldValue, $this->getModuleName(), false, false);
654
					$this->set('isEditableReadOnly', true);
655
				}
656
			}
657
		} elseif (method_exists($this->getUITypeModel(), 'getPicklistValues')) {
658
			$fieldPickListValues = $this->getUITypeModel()->getPicklistValues();
659
		}
660
		return $fieldPickListValues;
661
	}
662
663
	/**
664
	 * Function to get all the available picklist values for the current field.
665
	 *
666
	 * @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...
667
	 */
668
	public function getModulesListValues()
669
	{
670
		$allModules = \vtlib\Functions::getAllModules(true, false, 0);
671
		$modules = [];
672
		foreach ($allModules as $module) {
673
			$modules[$module['tabid']] = [
674
				'name' => $module['name'],
675
				'label' => App\Language::translate($module['name'], $module['name']),
676
			];
677
		}
678
		return $modules;
679
	}
680
681
	public static function showDisplayTypeList()
682
	{
683
		return [
684
			1 => 'LBL_DISPLAY_TYPE_1',
685
			2 => 'LBL_DISPLAY_TYPE_2',
686
			3 => 'LBL_DISPLAY_TYPE_3',
687
			4 => 'LBL_DISPLAY_TYPE_4',
688
			//5 => 'LBL_DISPLAY_TYPE_5',
689
			9 => 'LBL_DISPLAY_TYPE_9',
690
			10 => 'LBL_DISPLAY_TYPE_10',
691
			6 => 'LBL_DISPLAY_TYPE_6',
692
		];
693
	}
694 16
695
	/**
696 16
	 * Function to check if the current field is mandatory or not.
697 16
	 *
698 16
	 * @return bool
699
	 */
700
	public function isMandatory()
701 16
	{
702
		if ($this->get('isMandatory')) {
703
			return $this->get('isMandatory');
704
		}
705
		$typeOfData = explode('~', $this->get('typeofdata'));
706
		return isset($typeOfData[1]) && 'M' === $typeOfData[1];
707
	}
708
709
	/**
710
	 * Function to get the field type.
711
	 *
712
	 * @return string type of the field
713
	 */
714
	public function getFieldType()
715
	{
716
		if (isset($this->fieldType)) {
717
			return $this->fieldType;
718
		}
719 6
		$fieldTypeArray = explode('~', $this->get('typeofdata'));
720
		$fieldTypeArray = array_shift($fieldTypeArray);
721 6
		if ('reference' === $this->getFieldDataType()) {
722
			$fieldTypeArray = 'V';
723
		} else {
724 6
			$fieldTypeArray = \vtlib\Functions::transformFieldTypeOfData($this->get('table'), $this->get('column'), $fieldTypeArray);
725
		}
726
		return $this->fieldType = $fieldTypeArray;
727
	}
728
729
	/**
730
	 * Function to check if the field is shown in detail view.
731
	 *
732
	 * @return bool
733
	 */
734
	public function isViewEnabled()
735
	{
736
		if (6 === $this->getDisplayType() || 1 === $this->get('presence') || 3 === $this->get('presence')) {
737
			return false;
738
		}
739
		return $this->getPermissions();
740
	}
741
742 48
	/**
743
	 * Function to check if the field is shown in detail view.
744 48
	 *
745 48
	 * @return bool
746 48
	 */
747 48
	public function isViewable()
748 48
	{
749
		$return = true;
750 48
		if (isset($this->permissionsCache['isViewable'])) {
751
			return $this->permissionsCache['isViewable'];
752
		}
753
		if (
754
			!$this->isViewEnabled() || !$this->isActiveReference()
755
			|| ((306 === $this->get('uitype') || 307 === $this->get('uitype') || 311 === $this->get('uitype') || 312 === $this->get('uitype')) && 2 === $this->getDisplayType())
756
		) {
757
			$return = false;
758
		}
759
		return $this->permissionsCache['isViewable'] = $return;
760
	}
761
762
	/**
763
	 * Function to check if the field is exportable.
764
	 *
765
	 * @return bool
766
	 */
767
	public function isExportable(): bool
768
	{
769
		return $this->isViewable();
770
	}
771
772
	/**
773
	 * Function to check if the field is shown in detail view.
774
	 *
775
	 * @return bool
776
	 */
777
	public function isViewableInDetailView()
778
	{
779
		if (!$this->isViewable() || 3 === $this->getDisplayType() || 5 === $this->getDisplayType()) {
780
			return false;
781
		}
782
		return true;
783
	}
784
785
	/**
786
	 * Function to check whether the current field is writable.
787
	 *
788
	 * @param string $viewName
789
	 *
790
	 * @return bool
791
	 */
792
	public function isWritable(string $viewName = 'Edit'): bool
793
	{
794
		$return = true;
795
		$keyCache = 'isWritable' . $viewName;
796
		if (isset($this->permissionsCache[$keyCache])) {
797
			return $this->permissionsCache[$keyCache];
798
		}
799
		$displayType = $this->get('displaytype');
800
		if (!$this->isViewEnabled() || (4 === $displayType && ('Create' !== $viewName)) || 5 === $displayType
801
			|| 0 === strcasecmp($this->getFieldDataType(), 'autogenerated')
802
			|| 0 === strcasecmp($this->getFieldDataType(), 'id')
803
			|| true === $this->isReadOnly()
804
			|| !$this->getUITypeModel()->isWritable()) {
805
			$return = false;
806
		}
807
		return $this->permissionsCache[$keyCache] = $return;
808
	}
809
810
	/**
811
	 * Function to check whether the current field is editable.
812
	 *
813
	 * @param string $viewName
814
	 *
815
	 * @return bool
816
	 */
817
	public function isEditable(string $viewName = 'Edit'): bool
818
	{
819
		$return = true;
820
		$keyCache = 'isEditable' . $viewName;
821
		if (isset($this->permissionsCache[$keyCache])) {
822
			return $this->permissionsCache[$keyCache];
823
		}
824
		$displayType = $this->get('displaytype');
825
		if (!$this->isWritable($viewName) || !\in_array($displayType, [1, 4, 10])
826
			|| true === $this->isReadOnly() || (4 === $displayType && ('Create' !== $viewName))) {
827
			$return = false;
828
		}
829
		return $this->permissionsCache[$keyCache] = $return;
830 16
	}
831
832 16
	/**
833 16
	 * Function to check whether field is ajax editable.
834 16
	 *
835 16
	 * @return bool
836 16
	 */
837 16
	public function isAjaxEditable()
838 16
	{
839 16
		return !(10 === (int) $this->get('displaytype') || $this->isReferenceField() || !$this->getUITypeModel()->isAjaxEditable()
840 16
		|| !$this->isEditable() || \in_array($this->get('uitype'), [72, 12, 101]));
841 16
	}
842 16
843 16
	public function isEditableReadOnly()
844 16
	{
845 16
		if (null !== $this->get('isEditableReadOnly')) {
846
			return $this->get('isEditableReadOnly');
847 16
		}
848 16
		if (10 === (int) $this->get('displaytype')) {
849 16
			return true;
850 16
		}
851 16
		return false;
852 16
	}
853 16
854 16
	/**
855 16
	 * Function to check whether the current field is read-only.
856 16
	 *
857 16
	 * @return bool
858
	 */
859
	public function isReadOnly(): bool
860
	{
861
		if (isset($this->isReadOnly)) {
862
			return $this->isReadOnly;
863
		}
864
		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...
865 16
	}
866 16
867
	public function isQuickCreateEnabled()
868
	{
869 16
		$moduleModel = $this->getModule();
870
		$quickCreate = $this->get('quickcreate');
871
		if ((self::QUICKCREATE_MANDATORY == $quickCreate || self::QUICKCREATE_ENABLED == $quickCreate || $this->isMandatory()) && method_exists($moduleModel, 'isQuickCreateSupported') && $moduleModel->isQuickCreateSupported()) {
872 16
			return true;
873
		}
874
		return false;
875
	}
876
877 16
	/**
878 16
	 * Function to check whether summary field or not.
879 16
	 *
880
	 * @return bool true/false
881
	 */
882
	public function isSummaryField()
883
	{
884
		return ($this->get('summaryfield')) ? true : false;
885
	}
886
887
	/**
888
	 * Function to check whether the current reference field is active.
889
	 *
890
	 * @return bool
891
	 */
892
	public function isActiveReference()
893
	{
894
		if ('reference' === $this->getFieldDataType() && empty($this->getReferenceList())) {
895
			return false;
896 16
		}
897
		return true;
898
	}
899
900
	/**
901
	 * If the field is sortable in ListView.
902 16
	 */
903 16
	public function isListviewSortable()
904
	{
905
		return !$this->get('fromOutsideList') && $this->getUITypeModel()->isListviewSortable();
906 16
	}
907
908
	/**
909
	 * Static Function to get the instance fo Vtiger Field Model from a given vtlib\Field object.
910
	 *
911
	 * @param vtlib\Field $fieldObj - vtlib field object
912
	 *
913
	 * @return Vtiger_Field_Model instance
914
	 */
915
	public static function getInstanceFromFieldObject(vtlib\Field $fieldObj)
916
	{
917
		$objectProperties = get_object_vars($fieldObj);
918
		$className = Vtiger_Loader::getComponentClassName('Model', 'Field', $fieldObj->getModuleName());
919
		$fieldModel = new $className();
920 16
		foreach ($objectProperties as $properName => $propertyValue) {
921 6
			$fieldModel->{$properName} = $propertyValue;
922 6
		}
923 6
		return $fieldModel;
924 6
	}
925 10
926 10
	/**
927 10
	 * Function to get the custom view column name transformation of the field for a date field used in date filters.
928 10
	 *
929 10
	 * @return string - tablename:columnname:fieldname:module_fieldlabel
930
	 */
931
	public function getCVDateFilterColumnName()
932
	{
933 16
		$moduleName = $this->getModuleName();
934
		$tableName = $this->get('table');
935
		$columnName = $this->get('column');
936
		$fieldName = $this->get('name');
937
		$fieldLabel = $this->get('label');
938
939
		$escapedFieldLabel = str_replace(' ', '_', $fieldLabel);
940
		$moduleFieldLabel = $moduleName . '_' . $escapedFieldLabel;
941
942
		return $tableName . ':' . $columnName . ':' . $fieldName . ':' . $moduleFieldLabel;
943
	}
944
945
	/**
946
	 * Function to get value for customview.
947
	 *
948
	 * @param string $sourceFieldName
949
	 *
950
	 * @throws \Exception
951
	 *
952
	 * @return string
953
	 */
954
	public function getCustomViewSelectColumnName(string $sourceFieldName = '')
955
	{
956
		return "{$this->get('name')}:{$this->getModuleName()}" . ($sourceFieldName ? ":{$sourceFieldName}" : '');
957
	}
958
959
	/**
960
	 * Function to get the custom view column name transformation of the field.
961
	 *
962
	 * @return string - tablename:columnname:fieldname:module_fieldlabel:fieldtype
963
	 */
964
	public function getCustomViewColumnName()
965
	{
966
		$moduleName = $this->getModuleName();
967
		$tableName = $this->get('table');
968 25
		$columnName = $this->get('column');
969
		$fieldName = $this->get('name');
970 25
		$fieldLabel = $this->get('label');
971 5
		$typeOfData = $this->get('typeofdata');
972
		$fieldTypeOfData = explode('~', $typeOfData);
973 23
		$fieldTypeOfData = $fieldTypeOfData[0];
974 23
		//Special condition need for reference field as they should be treated as string field
975 23
		if ('reference' === $this->getFieldDataType()) {
976 23
			$fieldTypeOfData = 'V';
977
		} else {
978
			$fieldTypeOfData = \vtlib\Functions::transformFieldTypeOfData($tableName, $columnName, $fieldTypeOfData);
979 23
		}
980 23
		$escapedFieldLabel = str_replace(' ', '_', $fieldLabel);
981 23
		$moduleFieldLabel = "{$moduleName}_{$escapedFieldLabel}";
982 23
983 23
		return "$tableName:$columnName:$fieldName:$moduleFieldLabel:$fieldTypeOfData";
984 23
	}
985
986 23
	/**
987 23
	 * This is set from Workflow Record Structure, since workflow expects the field name
988
	 * in a different format in its filter. Eg: for module field its fieldname and for reference
989
	 * fields its reference_field_name : (reference_module_name) field - salesorder_id: (SalesOrder) subject.
990
	 *
991
	 * @return string
992
	 */
993
	public function getWorkFlowFilterColumnName()
994
	{
995
		return $this->get('workflow_columnname');
996
	}
997
998 28
	/**
999
	 * Function to get the field details.
1000 28
	 *
1001 28
	 * @return array - array of field values
1002 7
	 */
1003
	public function getFieldInfo(): array
1004 28
	{
1005 21
		return $this->getUITypeModel()->getFieldInfo();
1006 21
	}
1007
1008
	/**
1009
	 * Load field info.
1010
	 *
1011 28
	 * @return array
1012 28
	 */
1013
	public function loadFieldInfo(): array
1014
	{
1015
		if (null !== $this->fieldInfo) {
1016
			return $this->fieldInfo;
1017
		}
1018
		$this->fieldInfo['name'] = $this->get('name');
1019
		$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

1019
		$this->fieldInfo['label'] = App\Language::translate($this->get('label'), $this->getModuleName(), /** @scrutinizer ignore-type */ false, false);
Loading history...
1020
		$fieldDataType = $this->getFieldDataType();
1021
		$this->fieldInfo['type'] = $fieldDataType;
1022
		$this->fieldInfo['mandatory'] = $this->isMandatory();
1023
		$this->fieldInfo['defaultvalue'] = $this->getDefaultFieldValue();
1024
		$this->fieldInfo['presence'] = $this->isActiveField();
1025
		$this->fieldInfo['quickcreate'] = $this->isQuickCreateEnabled();
1026
		$this->fieldInfo['masseditable'] = $this->isMassEditable();
1027
		$this->fieldInfo['header_field'] = $this->getHeaderField();
1028
		$this->fieldInfo['maxlengthtext'] = $this->get('maxlengthtext');
1029
		$this->fieldInfo['maximumlength'] = $this->get('maximumlength');
1030
		$this->fieldInfo['maxwidthcolumn'] = $this->get('maxwidthcolumn');
1031
		$this->fieldInfo['tabindex'] = $this->get('tabindex');
1032
		$this->fieldInfo['fieldtype'] = explode('~', $this->get('typeofdata'))[0] ?? '';
1033
		$currentUser = \App\User::getCurrentUserModel();
1034
		switch ($fieldDataType) {
1035
			case 'picklist':
1036
			case 'multipicklist':
1037
			case 'multipicklistTags':
1038
			case 'multiowner':
1039
			case 'multiReferenceValue':
1040
			case 'inventoryLimit':
1041
			case 'languages':
1042
			case 'currencyList':
1043
			case 'fileLocationType':
1044
			case 'taxes':
1045
			case 'multiListFields':
1046
			case 'mailScannerFields':
1047
			case 'country':
1048
				$this->fieldInfo['picklistvalues'] = $this->getPicklistValues() ?: [];
1049
				break;
1050
			case 'date':
1051
			case 'datetime':
1052
				$this->fieldInfo['date-format'] = $currentUser->getDetail('date_format');
1053
				break;
1054
			case 'time':
1055
				$this->fieldInfo['time-format'] = $currentUser->getDetail('hour_format');
1056
				break;
1057
			case 'currency':
1058
				$this->fieldInfo['currency_symbol'] = $currentUser->getDetail('currency_symbol');
1059
				$this->fieldInfo['decimal_separator'] = $currentUser->getDetail('currency_decimal_separator');
1060
				$this->fieldInfo['group_separator'] = $currentUser->getDetail('currency_grouping_separator');
1061
				break;
1062
			case 'owner':
1063
			case 'userCreator':
1064
			case 'sharedOwner':
1065
				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

1065
				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...
1066
					$userList = \App\Fields\Owner::getInstance($this->getModuleName(), $currentUser)->getAccessibleUsers('', $fieldDataType);
1067
					$groupList = \App\Fields\Owner::getInstance($this->getModuleName(), $currentUser)->getAccessibleGroups('', $fieldDataType);
1068
					$pickListValues = [];
1069
					$pickListValues[\App\Language::translate('LBL_USERS', $this->getModuleName())] = $userList;
1070
					$pickListValues[\App\Language::translate('LBL_GROUPS', $this->getModuleName())] = $groupList;
1071
					$this->fieldInfo['picklistvalues'] = $pickListValues;
1072
					if (App\Config::performance('SEARCH_OWNERS_BY_AJAX')) {
1073
						$this->fieldInfo['searchOperator'] = 'e';
1074
					}
1075
				} else {
1076
					if ('owner' === $fieldDataType) {
1077
						$this->fieldInfo['searchOperator'] = 'e';
1078
					}
1079
				}
1080
				break;
1081
			case 'modules':
1082
				foreach ($this->getModulesListValues() as $module) {
1083
					$modulesList[$module['name']] = $module['label'];
1084
				}
1085
				$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 1082. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
1086
				break;
1087
			case 'categoryMultipicklist':
1088
			case 'tree':
1089
				$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

1089
				$this->fieldInfo['picklistvalues'] = \App\Fields\Tree::getPicklistValue(/** @scrutinizer ignore-type */ $this->getFieldParams(), $this->getModuleName());
Loading history...
1090
				$this->fieldInfo['treetemplate'] = $this->getFieldParams();
1091
				$this->fieldInfo['modulename'] = $this->getModuleName();
1092
				break;
1093
			case 'email':
1094
				if (\App\Config::security('EMAIL_FIELD_RESTRICTED_DOMAINS_ACTIVE') && !empty(\App\Config::security('EMAIL_FIELD_RESTRICTED_DOMAINS_VALUES'))) {
1095
					$validate = false;
1096
					if (empty(\App\Config::security('EMAIL_FIELD_RESTRICTED_DOMAINS_ALLOWED')) || \in_array($this->getModuleName(), \App\Config::security('EMAIL_FIELD_RESTRICTED_DOMAINS_ALLOWED'))) {
1097
						$validate = true;
1098
					}
1099
					if (\in_array($this->getModuleName(), \App\Config::security('EMAIL_FIELD_RESTRICTED_DOMAINS_EXCLUDED'))) {
1100
						$validate = false;
1101
					}
1102
					if ($validate) {
1103
						$this->fieldInfo['restrictedDomains'] = \App\Config::security('EMAIL_FIELD_RESTRICTED_DOMAINS_VALUES');
1104
					}
1105
				}
1106
				break;
1107
			default:
1108
				break;
1109
		}
1110
1111
		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...
1112
	}
1113
1114
	/**
1115
	 * Set field info.
1116
	 *
1117
	 * @param array $fieldInfo
1118
	 *
1119
	 * @return $this
1120
	 */
1121
	public function setFieldInfo(array $fieldInfo)
1122
	{
1123
		$this->fieldInfo = $fieldInfo;
1124
1125
		return $this;
1126
	}
1127
1128
	/**
1129
	 * Function to get the advanced filter option names by Field type.
1130
	 *
1131
	 * @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...
1132
	 */
1133
	public static function getAdvancedFilterOpsByFieldType()
1134
	{
1135
		return [
1136
			'V' => ['e', 'n', 's', 'ew', 'c', 'k', 'y', 'ny', 'om', 'wr', 'nwr'],
1137
			'N' => ['e', 'n', 'l', 'g', 'm', 'h', 'y', 'ny'],
1138
			'T' => ['e', 'n', 'l', 'g', 'm', 'h', 'bw', 'b', 'a', 'y', 'ny'],
1139
			'I' => ['e', 'n', 'l', 'g', 'm', 'h', 'y', 'ny'],
1140
			'C' => ['e', 'n', 'y', 'ny'],
1141
			'D' => ['e', 'n', 'bw', 'b', 'a', 'y', 'ny'],
1142
			'DT' => ['e', 'n', 'bw', 'b', 'a', 'y', 'ny'],
1143
			'NN' => ['e', 'n', 'l', 'g', 'm', 'h', 'y', 'ny'],
1144
			'E' => ['e', 'n', 's', 'ew', 'c', 'k', 'y', 'ny'],
1145
		];
1146
	}
1147
1148
	/**
1149
	 * Function to retrieve field model for specific block and module.
1150
	 *
1151
	 * @param vtlib\ModuleBasic $moduleModel
1152
	 *
1153
	 * @return Vtiger_Field_Model[][]
1154
	 */
1155
	public static function getAllForModule(vtlib\ModuleBasic $moduleModel)
1156
	{
1157
		if (\App\Cache::staticHas('ModuleFields', $moduleModel->id)) {
0 ignored issues
show
Bug introduced by
$moduleModel->id of type boolean is incompatible with the type string expected by parameter $key of App\Cache::staticHas(). ( Ignorable by Annotation )

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

1157
		if (\App\Cache::staticHas('ModuleFields', /** @scrutinizer ignore-type */ $moduleModel->id)) {
Loading history...
1158
			return \App\Cache::staticGet('ModuleFields', $moduleModel->id);
0 ignored issues
show
Bug introduced by
$moduleModel->id of type boolean is incompatible with the type string expected by parameter $key of App\Cache::staticGet(). ( Ignorable by Annotation )

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

1158
			return \App\Cache::staticGet('ModuleFields', /** @scrutinizer ignore-type */ $moduleModel->id);
Loading history...
1159
		}
1160
		$fieldModelList = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $fieldModelList is dead and can be removed.
Loading history...
1161
		$fieldObjects = parent::getAllForModule($moduleModel);
1162
		$fieldModelList = [];
1163
		if (!\is_array($fieldObjects)) {
0 ignored issues
show
introduced by
The condition is_array($fieldObjects) is always false.
Loading history...
1164
			$fieldObjects = [];
1165
		}
1166
		foreach ($fieldObjects as &$fieldObject) {
1167
			$fieldModel = self::getInstanceFromFieldObject($fieldObject);
1168
			$block = $fieldModel->get('block') ? $fieldModel->get('block')->id : 0;
1169
			$fieldModelList[$block][] = $fieldModel;
1170
			self::$instanceCacheById[$fieldModel->getId()] = $fieldModel;
1171
			self::$instanceCacheByName[$moduleModel->getId()][$fieldModel->getName()] = $fieldModel;
1172
		}
1173
		\App\Cache::staticSave('ModuleFields', $moduleModel->id, $fieldModelList);
0 ignored issues
show
Bug introduced by
$moduleModel->id of type boolean is incompatible with the type string expected by parameter $key of App\Cache::staticSave(). ( Ignorable by Annotation )

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

1173
		\App\Cache::staticSave('ModuleFields', /** @scrutinizer ignore-type */ $moduleModel->id, $fieldModelList);
Loading history...
1174
		return $fieldModelList;
1175
	}
1176
1177
	/**
1178
	 * Function to get new field model instance, the function creates a new object and does not pass a reference.
1179
	 *
1180
	 * @param string|int                $value  fieldname or field id
1181
	 * @param Vtiger_Module_Model|false $module optional - module instance
1182
	 *
1183
	 * @return Vtiger_Field_Model|false
1184
	 */
1185
	public static function getInstance($value, $module = false)
1186
	{
1187
		if (\is_numeric($value)) {
1188
			if (isset(self::$instanceCacheById[$value])) {
1189
				return clone self::$instanceCacheById[$value];
1190
			}
1191
		} elseif ($module) {
1192
			if (isset(self::$instanceCacheByName[$module->getId()][$value])) {
1193
				return clone self::$instanceCacheByName[$module->getId()][$value];
1194
			}
1195
		} else {
1196
			throw new \App\Exceptions\AppException("ERR_NOT_MODULE||$value||$module");
1197
		}
1198
		if ($fieldInstance = parent::getInstance($value, $module)) {
1199
			$fieldModel = self::getInstanceFromFieldObject($fieldInstance);
1200
			self::$instanceCacheById[$fieldModel->getId()] = $fieldModel;
1201 29
			self::$instanceCacheByName[$fieldModel->get('tabid')][$value] = $fieldModel;
1202
			return $fieldModel;
1203 29
		}
1204
		return false;
1205
	}
1206
1207
	/**
1208
	 * Returns instance of field.
1209
	 *
1210
	 * @param array|string $fieldInfo
1211
	 *
1212
	 * @return bool|\Vtiger_Field_Model|\vtlib\Field|null
1213
	 */
1214
	public static function getInstanceFromFilter($fieldInfo)
1215
	{
1216
		[$fieldName, $fieldModuleName, $sourceFieldName] = array_pad(explode(':', $fieldInfo), 3, false);
1217
1218
		return 'INVENTORY' === $sourceFieldName ? \Vtiger_Inventory_Model::getInstance($fieldModuleName)->getField($fieldName) : static::getInstance($fieldName, Vtiger_Module_Model::getInstance($fieldModuleName));
1219
	}
1220
1221
	/**
1222
	 * Function checks if the current Field is Read/Write.
1223
	 *
1224
	 * @return bool
1225
	 */
1226 11
	public function getProfileReadWritePermission()
1227
	{
1228 11
		return $this->getPermissions(false);
1229
	}
1230
1231
	/**
1232
	 * Gets default validator.
1233
	 *
1234
	 * @return array
1235
	 */
1236
	public function getDefaultValidator(): array
1237
	{
1238
		$validator = [];
1239
		$fieldName = $this->getName();
1240
		switch ($fieldName) {
1241
			case 'birthday':
1242
				$funcName = ['name' => 'lessThanToday'];
1243
				$validator[] = $funcName;
1244
				break;
1245
			case 'targetenddate':
1246
			case 'actualenddate':
1247
			case 'enddate':
1248
				$funcName = ['name' => 'greaterThanDependentField',
1249
					'params' => ['startdate'], ];
1250
				$validator[] = $funcName;
1251
				break;
1252
			case 'startdate':
1253
				if ('Project' === $this->getModule()->get('name')) {
1254
					$params = ['targetenddate'];
1255
				} else {
1256
					//for project task
1257
					$params = ['enddate'];
1258
				}
1259
				$funcName = ['name' => 'lessThanDependentField',
1260
					'params' => $params, ];
1261
				$validator[] = $funcName;
1262 21
				break;
1263
			case 'expiry_date':
1264 21
			case 'due_date':
1265
				$funcName = ['name' => 'greaterThanDependentField',
1266
					'params' => ['start_date'], ];
1267
				$validator[] = $funcName;
1268
				break;
1269
			case 'sales_end_date':
1270
				$funcName = ['name' => 'greaterThanDependentField',
1271
					'params' => ['sales_start_date'], ];
1272 18
				$validator[] = $funcName;
1273
				break;
1274 18
			case 'sales_start_date':
1275
				$funcName = ['name' => 'lessThanDependentField',
1276 18
					'params' => ['sales_end_date'], ];
1277
				$validator[] = $funcName;
1278
				break;
1279 16
			case 'qty_per_unit':
1280
			case 'qtyindemand':
1281 16
			case 'hours':
1282
			case 'days':
1283
				$funcName = ['name' => 'PositiveNumber'];
1284
				$validator[] = $funcName;
1285
				break;
1286
			case 'employees':
1287
				$funcName = ['name' => 'WholeNumber'];
1288
				$validator[] = $funcName;
1289
				break;
1290
			case 'related_to':
1291
				$funcName = ['name' => 'ReferenceField'];
1292
				$validator[] = $funcName;
1293
				break;
1294
			//SRecurringOrders field sepecial validators
1295
			case 'end_period':
1296 16
				$funcName1 = ['name' => 'greaterThanDependentField',
1297
					'params' => ['start_period'], ];
1298 16
				$validator[] = $funcName1;
1299
				$funcName2 = ['name' => 'lessThanDependentField',
1300
					'params' => ['duedate'], ];
1301
				$validator[] = $funcName2;
1302
1303
			// no break
1304
			case 'start_period':
1305
				$funcName = ['name' => 'lessThanDependentField',
1306
					'params' => ['end_period'], ];
1307
				$validator[] = $funcName;
1308
				break;
1309
			default:
1310
				break;
1311
		}
1312
		return $validator;
1313
	}
1314
1315
	/**
1316
	 * Function returns Client Side Validators name.
1317
	 *
1318
	 * @return array [name=>Name of the Validator, params=>Extra Parameters]
1319
	 */
1320
	public function getValidator()
1321
	{
1322
		return method_exists($this->getUITypeModel(), 'getValidator') ? $this->getUITypeModel()->getValidator() : $this->getDefaultValidator();
1323
	}
1324
1325
	/**
1326
	 * Function to retrieve display value in edit view.
1327
	 *
1328
	 * @param mixed               $value
1329
	 * @param Vtiger_Record_Model $recordModel
1330
	 *
1331
	 * @return mixed
1332
	 */
1333
	public function getEditViewDisplayValue($value, $recordModel = false)
1334
	{
1335
		return $this->getUITypeModel()->getEditViewDisplayValue($value, $recordModel);
1336
	}
1337
1338 10
	/**
1339
	 * Function to retrieve user value in edit view.
1340 10
	 *
1341
	 * @param mixed               $value
1342
	 * @param Vtiger_Record_Model $recordModel
1343
	 *
1344
	 * @return mixed
1345
	 */
1346
	public function getEditViewValue($value, $recordModel = false)
1347
	{
1348
		return $this->getUITypeModel()->getEditViewValue($value, $recordModel);
1349
	}
1350
1351
	/**
1352
	 * Function to get Display value for RelatedList.
1353
	 *
1354
	 * @param string $value
1355
	 *
1356
	 * @return string
1357
	 */
1358
	public function getRelatedListDisplayValue($value)
1359
	{
1360
		return $this->getUITypeModel()->getRelatedListDisplayValue($value);
1361
	}
1362
1363
	/**
1364
	 * Function to get Default Field Value.
1365
	 *
1366
	 * @throws \Exception
1367
	 *
1368
	 * @return mixed
1369
	 */
1370
	public function getDefaultFieldValue()
1371
	{
1372
		return $this->getUITypeModel()->getDefaultValue();
1373
	}
1374
1375
	/**
1376
	 * Function whcih will get the databse insert value format from user format.
1377
	 *
1378
	 * @param type  $value       in user format
1379
	 * @param mixed $recordModel
1380
	 *
1381
	 * @return type
1382
	 */
1383
	public function getDBValue($value, $recordModel = false)
1384
	{
1385
		return $this->getUITypeModel()->getDBValue($value, $recordModel);
0 ignored issues
show
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...
1386
	}
1387
1388
	/**
1389
	 * Function to get visibilty permissions of a Field.
1390
	 *
1391
	 * @param bool $readOnly
1392
	 *
1393
	 * @return bool
1394
	 */
1395
	public function getPermissions($readOnly = true)
1396 17
	{
1397
		if (isset($this->permissions)) {
1398 17
			return $this->permissions;
1399 17
		}
1400 17
		return \App\Field::getFieldPermission($this->getModuleId(), $this->getName(), $readOnly);
1401 17
	}
1402 16
1403
	public function __update()
1404
	{
1405 1
		$dbCommand = \App\Db::getInstance()->createCommand();
1406
		1 === $this->get('generatedtype') ? $generatedType = 1 : $generatedType = 2;
1407
		$dbCommand->update('vtiger_field', ['typeofdata' => $this->get('typeofdata'), 'presence' => $this->get('presence'), 'quickcreate' => $this->get('quickcreate'),
1408
			'masseditable' => $this->get('masseditable'), 'header_field' => $this->get('header_field'), 'maxlengthtext' => $this->get('maxlengthtext'),
1409
			'maxwidthcolumn' => $this->get('maxwidthcolumn'), 'tabindex' => $this->get('tabindex'), 'defaultvalue' => $this->get('defaultvalue'), 'summaryfield' => $this->get('summaryfield'),
1410
			'displaytype' => $this->get('displaytype'), 'helpinfo' => $this->get('helpinfo'), 'generatedtype' => $generatedType,
1411
			'fieldparams' => $this->get('fieldparams'), 'quickcreatesequence' => $this->get('quicksequence'), 'icon' => $this->get('icon'), 'fieldlabel' => $this->get('label'),
1412
		], ['fieldid' => $this->get('id')])->execute();
1413
		if ($anonymizationTarget = $this->get('anonymizationTarget')) {
1414
			$anonymizationTarget = \App\Json::encode($anonymizationTarget);
1415
			$execute = $dbCommand->update('s_#__fields_anonymization', ['anonymization_target' => $anonymizationTarget], ['field_id' => $this->getId()])->execute();
1416
			if (!$execute) {
1417
				$dbCommand->insert('s_#__fields_anonymization', ['field_id' => $this->getId(), 'anonymization_target' => $anonymizationTarget])->execute();
1418
			}
1419
		} else {
1420
			$dbCommand->delete('s_#__fields_anonymization', ['field_id' => $this->getId()])->execute();
1421
		}
1422
		$this->afterFieldChange();
1423 19
	}
1424
1425 19
	/**
1426 19
	 * Change the mandatory field.
1427 19
	 *
1428
	 * @param string $mandatoryValue
1429
	 *
1430 19
	 * @return $this
1431 19
	 */
1432 19
	public function updateTypeofDataFromMandatory($mandatoryValue = 'O')
1433
	{
1434
		$mandatoryValue = strtoupper($mandatoryValue);
1435
		$supportedMandatoryLiterals = ['O', 'M'];
1436
		if (!\in_array($mandatoryValue, $supportedMandatoryLiterals)) {
1437
			return $this;
1438
		}
1439
		$typeOfData = $this->get('typeofdata');
1440
		$components = explode('~', $typeOfData);
1441
		$components[1] = $mandatoryValue;
1442
		$this->set('typeofdata', implode('~', $components));
1443 19
1444
		return $this;
1445
	}
1446
1447
	public function isCustomField()
1448
	{
1449
		return 2 == $this->generatedtype;
1450
	}
1451
1452
	public function hasDefaultValue()
1453 21
	{
1454
		return !empty($this->defaultvalue);
1455 21
	}
1456 21
1457
	public function isActiveField()
1458
	{
1459 21
		return \in_array($this->get('presence'), [0, 2]);
1460 21
	}
1461 2
1462
	public function isMassEditable()
1463 19
	{
1464 19
		return 1 == $this->masseditable;
1465
	}
1466
1467 19
	public function isHeaderField()
1468 19
	{
1469 19
		return !empty($this->header_field);
1470 8
	}
1471 11
1472 2
	/**
1473 1
	 * Gets header field data.
1474
	 *
1475 1
	 * @throws \App\Exceptions\AppException
1476 9
	 *
1477
	 * @return mixed
1478
	 */
1479
	public function getHeaderField()
1480
	{
1481 9
		return !empty($this->header_field) ? \App\Json::decode($this->header_field) : [];
1482 2
	}
1483
1484
	/**
1485 2
	 * Gets header field value.
1486 7
	 *
1487 3
	 * @param string $type
1488 4
	 * @param mixed  $default
1489 4
	 *
1490
	 * @throws \App\Exceptions\AppException
1491
	 *
1492
	 * @return mixed
1493
	 */
1494
	public function getHeaderValue(string $type, $default = '')
1495
	{
1496
		return $this->getHeaderField()[$type] ?? $default;
1497
	}
1498
1499
	/**
1500
	 * Function which will check if empty piclist option should be given.
1501
	 *
1502
	 * @return bool
1503
	 */
1504
	public function isEmptyPicklistOptionAllowed()
1505
	{
1506
		if (method_exists($this->getUITypeModel(), 'isEmptyPicklistOptionAllowed')) {
1507
			return $this->getUITypeModel()->isEmptyPicklistOptionAllowed();
1508
		}
1509
		return true;
1510
	}
1511
1512
	/**
1513
	 * Check if it is a tree field.
1514
	 *
1515
	 * @return bool
1516
	 */
1517
	public function isTreeField(): bool
1518
	{
1519
		return \in_array($this->getFieldDataType(), ['tree', 'categoryMultipicklist']);
1520
	}
1521
1522
	public function isReferenceField()
1523
	{
1524
		return \in_array($this->getFieldDataType(), self::$referenceTypes);
1525
	}
1526
1527
	public function isOwnerField()
1528
	{
1529
		return self::OWNER_TYPE == $this->getFieldDataType();
1530
	}
1531
1532
	/**
1533
	 * Function determines whether the field value can be duplicated.
1534
	 *
1535
	 * @return bool
1536
	 */
1537
	public function isDuplicable(): bool
1538
	{
1539
		return $this->getUITypeModel()->isDuplicable();
1540
	}
1541
1542
	/**
1543
	 * Is summation field.
1544
	 *
1545
	 * @return bool
1546
	 */
1547
	public function isCalculateField()
1548
	{
1549
		return $this->isCalculateField && !$this->get('fromOutsideList') && (\in_array($this->getUIType(), [71, 7, 317, 8]) || \in_array($this->getFieldDataType(), ['integer', 'double']));
1550
	}
1551
1552
	/**
1553
	 * Function returns field instance for field ID.
1554
	 *
1555
	 * @param int $fieldId
1556
	 * @param int $moduleTabId
1557
	 *
1558
	 * @return \Vtiger_Field_Model
1559
	 */
1560
	public static function getInstanceFromFieldId($fieldId, $moduleTabId = false)
1561
	{
1562
		if (isset(self::$instanceCacheById[$fieldId])) {
1563
			return self::$instanceCacheById[$fieldId];
1564
		}
1565
		$field = \App\Field::getFieldInfo($fieldId);
1566
		$className = Vtiger_Loader::getComponentClassName('Model', 'Field', \App\Module::getModuleName($field['tabid']));
1567
		$fieldModel = new $className();
1568
		$fieldModel->initialize($field, $field['tabid']);
1569
		self::$instanceCacheById[$fieldModel->getId()] = $fieldModel;
1570
		self::$instanceCacheByName[$fieldModel->get('tabid')][$fieldModel->getName()] = $fieldModel;
1571
		return $fieldModel;
1572
	}
1573
1574
	public function getWithDefaultValue()
1575
	{
1576
		$defaultValue = $this->getDefaultFieldValue();
1577
		$recordValue = $this->get('fieldvalue');
1578
		if (empty($recordValue) && !$defaultValue) {
1579
			$this->set('fieldvalue', $defaultValue);
1580
		}
1581
		return $this;
1582
	}
1583
1584
	/**
1585
	 * Get field params.
1586
	 *
1587
	 * @return array
1588
	 */
1589
	public function getFieldParams()
1590
	{
1591
		if (!\is_array($this->get('fieldparams')) && \App\Json::isJson($this->get('fieldparams'))) {
1592
			return \App\Json::decode($this->get('fieldparams'));
0 ignored issues
show
Bug Best Practice introduced by
The expression return App\Json::decode(...is->get('fieldparams')) also could return the type string which is incompatible with the documented return type array.
Loading history...
1593
		}
1594
		return $this->get('fieldparams') ?: [];
1595
	}
1596
1597
	/**
1598
	 * Get value of a specific parameter from the fieldparams field.
1599
	 *
1600
	 * @param string $key
1601
	 *
1602
	 * @return mixed
1603
	 */
1604
	public function getParam(string $key)
1605
	{
1606
		return $this->getFieldParams()[$key] ?? null;
1607
	}
1608
1609
	/**
1610
	 * Get field icon.
1611
	 *
1612
	 * @param string $place
1613
	 *
1614
	 * @return array
1615
	 */
1616
	public function getIcon(string $place = ''): array
1617
	{
1618
		$icon = [];
1619
		if (\is_array($this->get('icon'))) {
1620
			$icon = $this->get('icon');
1621
		} elseif ($this->get('icon') && \App\Json::isJson($this->get('icon'))) {
1622
			$icon = \App\Json::decode($this->get('icon'));
1623
		}
1624
		if ($place && isset($icon['place']) && !\in_array($place, $icon['place'])) {
1625
			$icon = [];
1626
		}
1627
		return $icon;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $icon could return the type null|string which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
1628
	}
1629
1630
	/**
1631
	 * Get anonymization target.
1632
	 *
1633
	 * @see \App\Anonymization::getTypes()
1634
	 *
1635
	 * @return int[]
1636
	 */
1637
	public function getAnonymizationTarget(): array
1638
	{
1639
		if (\is_string($this->get('anonymizationTarget'))) {
1640
			$this->set('anonymizationTarget', \App\Json::decode($this->get('anonymizationTarget')));
1641
		}
1642
		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...
1643
	}
1644
1645
	/**
1646
	 * Get maximum value.
1647
	 *
1648
	 * @return int
1649
	 */
1650
	public function getMaxValue(): int
1651
	{
1652
		if (($maximumLength = $this->get('maximumlength')) && false !== strpos($maximumLength, ',')) {
1653
			return (int) explode(',', $maximumLength)[1];
1654
		}
1655
		if (empty($maximumLength)) {
1656
			$maximumLength = $this->getDbValueLength();
1657
		}
1658
1659
		return (int) $maximumLength;
1660
	}
1661
1662
	/**
1663
	 * Get minimum value.
1664
	 *
1665
	 * @return int
1666
	 */
1667
	public function getMinValue(): int
1668
	{
1669
		$min = 0;
1670
		if (($maximumLength = $this->get('maximumlength')) && false !== strpos($maximumLength, ',')) {
1671
			$min = (int) explode(',', $maximumLength)[0];
1672
		}
1673
1674
		return $min;
1675
	}
1676
1677
	/**
1678
	 * Get length value form database.
1679
	 *
1680
	 * @return int
1681
	 */
1682
	public function getDbValueLength(): int
1683
	{
1684
		$db = \App\Db::getInstance();
1685
		$tableSchema = $db->getSchema()->getTableSchema($this->getTableName());
1686
		if (empty($tableSchema)) {
1687
			throw new \App\Exceptions\AppException('ERR_TABLE_DOES_NOT_EXISTS||' . $this->getTableName());
1688
		}
1689
		return $tableSchema->getColumn($this->getColumnName())->size ?: 0;
1690
	}
1691
1692
	public function isActiveSearchView()
1693
	{
1694
		if ($this->get('fromOutsideList') || $this->get('searchLockedFields')) {
1695
			return false;
1696
		}
1697
		return $this->getUITypeModel()->isActiveSearchView();
1698
	}
1699
1700
	/**
1701
	 * Empty value search in view.
1702
	 *
1703
	 * @return bool
1704
	 */
1705
	public function searchLockedEmptyFields(): bool
1706
	{
1707
		return empty($this->get('searchLockedEmptyFields'));
1708
	}
1709
1710
	/**
1711
	 * Function returns info about field structure in database.
1712
	 *
1713
	 * @param bool $returnString
1714
	 *
1715
	 * @return array|string
1716
	 */
1717
	public function getDBColumnType($returnString = true)
1718
	{
1719
		$db = \App\Db::getInstance();
1720
		$tableSchema = $db->getSchema()->getTableSchema($this->getTableName(), true);
1721
		if (empty($tableSchema)) {
1722
			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...
1723
		}
1724
		$columnSchema = $tableSchema->getColumn($this->getColumnName());
1725
		$data = get_object_vars($columnSchema);
1726
		if ($returnString) {
1727
			$string = $data['type'];
1728
			if ($data['size']) {
1729
				if ('decimal' === $data['type']) {
1730
					$string .= '(' . $data['size'] . ',' . $data['scale'] . ')';
1731
				} else {
1732
					$string .= '(' . $data['size'] . ')';
1733
				}
1734
			}
1735
			return $string;
1736
		}
1737
		return $data;
1738
	}
1739
1740
	/**
1741
	 * Function to get range of values.
1742
	 *
1743
	 * @throws \App\Exceptions\AppException
1744
	 *
1745
	 * @return string|null
1746
	 */
1747
	public function getRangeValues()
1748
	{
1749
		$uiTypeModel = $this->getUITypeModel();
1750
		if (method_exists($uiTypeModel, 'getRangeValues')) {
1751
			return $uiTypeModel->getRangeValues();
1752
		}
1753
		$allowedTypes = $uiTypeModel->getAllowedColumnTypes();
1754
		if (null === $allowedTypes) {
0 ignored issues
show
introduced by
The condition null === $allowedTypes is always false.
Loading history...
1755
			return;
1756
		}
1757
		$data = $this->getDBColumnType(false);
1758
		if (!\in_array($data['type'], $allowedTypes)) {
1759
			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

1759
			throw new \App\Exceptions\AppException('ERR_NOT_ALLOWED_TYPE||' . $data['type'] . '||' . /** @scrutinizer ignore-type */ print_r($allowedTypes, true));
Loading history...
1760
		}
1761
		preg_match('/^([\w\-]+)/i', $data['dbType'], $matches);
1762
		$type = $matches[1] ?? $data['type'];
1763
		$uitype = $this->getUIType();
1764
		if (isset(self::$uiTypeMaxLength[$uitype])) {
1765
			$range = self::$uiTypeMaxLength[$uitype];
1766
		} elseif (isset(self::$typesMaxLength[$type])) {
1767
			$range = self::$typesMaxLength[$type];
1768
		} else {
1769
			switch ($type) {
1770
				case 'binary':
1771
				case 'string':
1772
				case 'varchar':
1773
				case 'varbinary':
1774
					$range = (int) $data['size'];
1775
					break;
1776
				case 'bigint':
1777
				case 'mediumint':
1778
					throw new \App\Exceptions\AppException("ERR_NOT_ALLOWED_TYPE||$type||integer,smallint,tinyint");
1779
				case 'integer':
1780
				case 'int':
1781
					if ($data['unsigned']) {
1782
						$range = '4294967295';
1783
					} else {
1784
						$range = '-2147483648,2147483647';
1785
					}
1786
					break;
1787
				case 'smallint':
1788
					if ($data['unsigned']) {
1789
						$range = '65535';
1790
					} else {
1791
						$range = '-32768,32767';
1792
					}
1793
					break;
1794
				case 'tinyint':
1795
					if ($data['unsigned']) {
1796
						$range = '255';
1797
					} else {
1798
						$range = '-128,127';
1799
					}
1800
					break;
1801
				case 'decimal':
1802
					$range = 10 ** (((int) $data['size']) - ((int) $data['scale'])) - 1;
1803
					break;
1804
				default:
1805
					$range = null;
1806
					break;
1807
			}
1808
		}
1809
		return $range;
1810
	}
1811
1812
	/**
1813
	 * Return allowed query operators for field.
1814
	 *
1815
	 * @return string[]
1816
	 */
1817
	public function getQueryOperatorLabels(): array
1818
	{
1819
		return \App\Condition::getOperatorLabels($this->getUITypeModel()->getQueryOperators());
1820
	}
1821
1822
	/**
1823
	 * Gets record operator labels.
1824
	 *
1825
	 * @return string[]
1826
	 */
1827
	public function getRecordOperatorLabels(): array
1828
	{
1829
		return \App\Condition::getOperatorLabels($this->getUITypeModel()->getRecordOperators());
1830
	}
1831
1832
	/**
1833
	 * Returns template for operator.
1834
	 *
1835
	 * @param string $operator
1836
	 *
1837
	 * @return string
1838
	 */
1839
	public function getOperatorTemplateName(string $operator)
1840
	{
1841
		if (\in_array($operator, App\Condition::OPERATORS_WITHOUT_VALUES)) {
1842
			return;
1843
		}
1844
		if (\in_array($operator, \App\Condition::FIELD_COMPARISON_OPERATORS)) {
1845
			return 'ConditionBuilder/FieldsListUitype.tpl';
1846
		}
1847
		return $this->getUITypeModel()->getOperatorTemplateName($operator);
1848
	}
1849
1850
	/**
1851
	 * Function to get the field model for condition builder.
1852
	 *
1853
	 * @param string $operator
1854
	 *
1855
	 * @return self
1856
	 */
1857
	public function getConditionBuilderField(string $operator): self
1858
	{
1859
		return $this->getUITypeModel()->getConditionBuilderField($operator);
1860
	}
1861
1862
	/**
1863
	 * Sets data.
1864
	 *
1865
	 * @param array $data
1866
	 *
1867
	 * @return self
1868
	 */
1869
	public function setData(array $data = [])
1870
	{
1871
		foreach ($data as $key => $value) {
1872
			$this->set($key, $value);
1873
		}
1874
		return $this;
1875
	}
1876
1877
	/**
1878
	 * TabIndex last sequence number.
1879
	 *
1880
	 * @var int
1881
	 */
1882
	public static $tabIndexLastSeq = 0;
1883
	/**
1884
	 * TabIndex default sequence number.
1885
	 *
1886
	 * @var int
1887
	 */
1888
	public static $tabIndexDefaultSeq = 0;
1889
1890
	/**
1891
	 * Get TabIndex.
1892
	 *
1893
	 * @return int
1894
	 */
1895
	public function getTabIndex(): int
1896
	{
1897
		$tabindex = 0;
1898
		if (0 !== $this->get('tabindex')) {
1899
			$tabindex = $this->get('tabindex');
1900
		} elseif (self::$tabIndexLastSeq) {
1901
			$tabindex = self::$tabIndexLastSeq;
1902
		}
1903
		return $tabindex + self::$tabIndexDefaultSeq;
1904
	}
1905
1906
	/** {@inheritdoc} */
1907
	public function delete()
1908
	{
1909
		$this->getUITypeModel()->delete();
1910
		Settings_FieldsDependency_Module_Model::removeField($this->getModuleName(), $this->getName());
1911
		\App\Utils\Kanban::deleteField($this->getModuleName(), $this->getName());
1912
		\App\Fields\Picklist::removeDependencyConditionField($this->getModuleName(), $this->getName());
1913
		$this->getModule()->clearCache();
1914
		parent::delete();
1915
	}
1916
}
1917