Passed
Pull Request — developer (#16962)
by Arkadiusz
17:42
created

Settings_LayoutEditor_Field_Model   F

Complexity

Total Complexity 60

Size/Duplication

Total Lines 406
Duplicated Lines 0 %

Test Coverage

Coverage 34.07%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 60
eloc 192
c 3
b 0
f 0
dl 0
loc 406
ccs 46
cts 135
cp 0.3407
rs 3.6

18 Methods

Rating   Name   Duplication   Size   Complexity  
A getInstanceFromBlockIdList() 0 19 4
A getInstance() 0 9 2
F delete() 0 67 12
A isMandatoryOptionDisabled() 0 6 2
A isActiveOptionDisabled() 0 3 3
A isMassEditOptionDisabled() 0 6 4
A getFieldDataTypeLabel() 0 8 2
A isSummaryFieldOptionDisabled() 0 3 1
A updateWebserviceData() 0 9 2
A getWebserviceData() 0 6 3
A loadWebserviceData() 0 10 3
A isQuickCreateOptionDisabled() 0 7 4
A isDefaultValueOptionDisabled() 0 6 5
A getFieldInfo() 0 9 1
A makeFieldActive() 0 10 2
A isDefaultValueForWebservice() 0 3 3
A move() 0 21 4
A isEditable() 0 6 3

How to fix   Complexity   

Complex Class

Complex classes like Settings_LayoutEditor_Field_Model often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

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

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

1
<?php
2
/* +**********************************************************************************
3
 * The contents of this file are subject to the vtiger CRM Public License Version 1.1
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
class Settings_LayoutEditor_Field_Model extends Vtiger_Field_Model
13
{
14
	const WEBSERVICE_APPS_VISIBILITY = [
15
		0 => 'LBL_WSA_VISIBILITY_DEFAULT',
16
		1 => 'LBL_DISPLAY_TYPE_1',
17 21
		2 => 'LBL_DISPLAY_TYPE_2',
18
		3 => 'LBL_DISPLAY_TYPE_3',
19 21
		4 => 'LBL_DISPLAY_TYPE_4',
20 21
		9 => 'LBL_DISPLAY_TYPE_9',
21
		10 => 'LBL_DISPLAY_TYPE_10',
22 21
		6 => 'LBL_DISPLAY_TYPE_6',
23 21
	];
24 21
25 21
	/** @var array Translations of field types */
26 21
	public $fieldTypeLabel = [
27 21
		'string' => 'Text',
28 21
		'date' => 'Date',
29 21
		'integer' => 'Integer',
30
		'double' => 'Decimal',
31 21
		'percentage' => 'Percent',
32
		'phone' => 'Phone',
33 21
		'email' => 'Email',
34 21
		'time' => 'Time',
35
		'picklist' => 'Picklist',
36 21
		'url' => 'URL',
37
		'multipicklistTags' => 'MultipicklistTags',
38 21
		'text' => 'TextArea',
39
		'languages' => 'LBL_LANGUAGE',
40
		'multipicklist' => 'MultiSelectCombo',
41
		'country' => 'Country',
42
		'reference' => 'Related1M',
43
		'userCreator' => 'LBL_USER',
44 21
		'boolean' => 'Checkbox',
45 3
		'image' => 'Image',
46 3
		'datetime' => 'DateTime',
47 3
		'currency' => 'Currency',
48 3
		'skype' => 'Skype',
49 3
		'tree' => 'Tree',
50 3
		'multiReferenceValue' => 'MultiReferenceValue',
51
		'multiReference' => 'MultiReference',
52 3
		'rangeTime' => 'RangeTime',
53
		'categoryMultipicklist' => 'CategoryMultipicklist',
54
		'multiImage' => 'MultiImage',
55 3
		'twitter' => 'Twitter',
56
		'multiEmail' => 'MultiEmail',
57 3
		'smtp' => 'Smtp',
58
		'serverAccess' => 'ServerAccess',
59
		'multiDomain' => 'MultiDomain',
60
		'token' => 'Token',
61 21
		'multiAttachment' => 'MultiAttachment',
62 1
		'mapCoordinates' => 'MapCoordinates',
63 1
		'advPercentage' => 'AdvPercentage',
64 1
		'group' => 'Group'
65 1
	];
66 1
67
	/** @var array Webservice field data */
68 21
	protected $webserviceData;
69 21
70 21
	/**
71 21
	 * Get field data type label.
72 21
	 *
73 21
	 * @return string
74
	 */
75
	public function getFieldDataTypeLabel(): string
76
	{
77
		if (300 === $this->getUIType()) {
78
			$label = 'Editor';
79 21
		} else {
80
			$label = $this->fieldTypeLabel[$this->getFieldDataType()] ?? '';
81
		}
82
		return $label;
83
	}
84
85
	/**
86
	 * Function to remove field.
87
	 */
88
	public function delete()
89
	{
90
		$db = \App\Db::getInstance();
91
		try {
92
			parent::delete();
93
94
			$fldModule = $this->getModuleName();
95
			$id = $this->getId();
96
			$fieldname = $this->getName();
97
			$tablename = $this->get('table');
98
			$columnName = $this->get('column');
99
			$tabId = $this->getModuleId();
100
			if ('vtiger_crmentity' !== $tablename) {
101
				$db->createCommand()->dropColumn($tablename, $columnName)->execute();
102
			}
103
			App\Db::getInstance('admin')->createCommand()->delete('a_#__mapped_fields', ['or', ['source' => (string) $id], ['target' => (string) $id]])->execute();
104
			//we have to remove the entries in customview and report related tables which have this field ($colName)
105
			$db->createCommand()->delete('vtiger_cvcolumnlist', ['field_name' => $fieldname, 'module_name' => $fldModule])->execute();
106
			$db->createCommand()->delete('vtiger_cvcolumnlist', [
107
				'source_field_name' => $fieldname,
108
				'cvid' => (new \App\Db\Query())->select(['cvid'])->from('vtiger_customview')->where(['entitytype' => $fldModule]),
109
			])->execute();
110
			$db->createCommand()->delete('u_#__cv_condition', ['field_name' => $fieldname, 'module_name' => $fldModule])->execute();
111
			//Deleting from convert lead mapping vtiger_table- Jaguar
112
			if ('Leads' === $fldModule) {
113
				$db->createCommand()->delete('vtiger_convertleadmapping', ['leadfid' => $id])->execute();
114
			} elseif ('Accounts' === $fldModule) {
115
				$mapDelId = ['Accounts' => 'accountfid'];
116
				$db->createCommand()->update('vtiger_convertleadmapping', [$mapDelId[$fldModule] => 0], [$mapDelId[$fldModule] => $id])->execute();
117
			}
118
			switch ($this->getFieldDataType()) {
119
				case 'picklist':
120
				case 'multipicklist':
121
						$query = (new \App\Db\Query())->from('vtiger_field')
122
							->where(['fieldname' => $fieldname])
123
							->andWhere(['in', 'uitype', [15, 16, 33]]);
124
						$dataReader = $query->createCommand()->query();
125
						if (!$dataReader->count()) {
126
							$db->createCommand()->dropTable('vtiger_' . $fieldname)->execute();
127
							//To Delete Sequence Table
128
							if ($db->isTableExists('vtiger_' . $fieldname . '_seq')) {
129
								$db->createCommand()->dropTable('vtiger_' . $fieldname . '_seq')->execute();
130
							}
131
							$db->createCommand()->delete('vtiger_picklist', ['name' => $fieldname])->execute();
132
						}
133
					break;
134
					case 'mapCoordinates':
135
						\App\Fields\MapCoordinates::reloadHandler();
136
						break;
137
				default:
138
					break;
139
			}
140
			$entityInfo = \App\Module::getEntityInfo($fldModule);
141
			foreach (['fieldnameArr' => 'fieldname', 'searchcolumnArr' => 'searchcolumn'] as $key => $name) {
142
				if (false !== ($fieldNameKey = array_search($fieldname, $entityInfo[$key]))) {
143
					unset($entityInfo[$key][$fieldNameKey]);
144
					$params = [
145
						'name' => $name,
146
						'tabid' => $tabId,
147
						'value' => $entityInfo[$key],
148
					];
149
					Settings_Search_Module_Model::save($params);
150
				}
151
			}
152
		} catch (\Throwable $ex) {
153
			\App\Log::error($ex->__toString());
154
			throw $ex;
155
		}
156
	}
157
158
	/**
159
	 * Function to Move the field.
160
	 *
161
	 * @param <Array> $fieldNewDetails
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...
162
	 * @param <Array> $fieldOlderDetails
163
	 */
164
	public function move($fieldNewDetails, $fieldOlderDetails)
165
	{
166
		$db = \App\Db::getInstance();
167
		$newBlockId = $fieldNewDetails['blockId'];
168
		$olderBlockId = $fieldOlderDetails['blockId'];
169
170
		$newSequence = $fieldNewDetails['sequence'];
171
		$olderSequence = $fieldOlderDetails['sequence'];
172
173
		if ($olderBlockId == $newBlockId) {
174
			if ($newSequence > $olderSequence) {
175
				$db->createCommand()->update('vtiger_field', ['sequence' => new \yii\db\Expression('sequence - 1')], ['and', 'sequence > :olderSequence', 'sequence <= :newSequence', 'block = :olderBlockId'], [':olderSequence' => $olderSequence, ':newSequence' => $newSequence, ':olderBlockId' => $olderBlockId])->execute();
176
			} elseif ($newSequence < $olderSequence) {
177
				$db->createCommand()->update('vtiger_field', ['sequence' => new \yii\db\Expression('sequence + 1')], ['and', 'sequence < :olderSequence', 'sequence >= :newSequence', 'block = :olderBlockId'], [':olderSequence' => $olderSequence, ':newSequence' => $newSequence, ':olderBlockId' => $olderBlockId])->execute();
178
			}
179
			$db->createCommand()->update('vtiger_field', ['sequence' => $newSequence], ['fieldid' => $this->getId()])->execute();
180
		} else {
181
			$db->createCommand()->update('vtiger_field', ['sequence' => new \yii\db\Expression('sequence - 1')], ['and', 'sequence > :olderSequence', 'block = :olderBlockId'], [':olderSequence' => $olderSequence, ':olderBlockId' => $olderBlockId])->execute();
182
			$db->createCommand()->update('vtiger_field', ['sequence' => new \yii\db\Expression('sequence - 1')], ['and', 'sequence >= :newSequence', 'block = :newBlockId'], [':newSequence' => $newSequence, ':newBlockId' => $newBlockId])->execute();
183
184
			$db->createCommand()->update('vtiger_field', ['sequence' => $newSequence, 'block' => $newBlockId], ['fieldid' => $this->getId()])->execute();
185
		}
186
	}
187
188
	/**
189
	 * Function to activate field.
190
	 *
191
	 * @param int[] $fieldIdsList
192
	 * @param int   $blockId
193
	 */
194
	public static function makeFieldActive($fieldIdsList, $blockId)
195
	{
196
		$maxSequence = (new \App\Db\Query())->from('vtiger_field')
197
			->where(['block' => $blockId, 'presence' => [0, 2]])->max('sequence');
198
		foreach ($fieldIdsList as $fieldId) {
199
			++$maxSequence;
200
			$fieldInstance = self::getInstance($fieldId);
201
			$fieldInstance->set('sequence', $maxSequence);
202
			$fieldInstance->set('presence', 2);
203
			$fieldInstance->save();
204
		}
205
	}
206
207
	/**
208
	 * Function which specifies whether the field can have mandatory switch to happen.
209
	 *
210
	 * @return bool - true if we can make a field mandatory and non mandatory , false if we cant change previous state
211
	 */
212
	public function isMandatoryOptionDisabled(): bool
213
	{
214
		$focus = $this->getModule()->getEntityInstance();
215
		$compulsoryMandatoryFieldList = $focus->mandatory_fields ?? [];
216
217
		return \in_array($this->getName(), $compulsoryMandatoryFieldList) || \in_array($this->get('uitype'), ['4', '70']);
218
	}
219
220
	/**
221
	 * Function which will specify whether the active option is disabled.
222
	 *
223
	 * @return bool
224
	 */
225
	public function isActiveOptionDisabled(): bool
226
	{
227
		return 0 === (int) $this->get('presence') || 306 === (int) $this->get('uitype') || $this->isMandatoryOptionDisabled();
228
	}
229
230
	/**
231
	 * Function which will specify whether the quickcreate option is disabled.
232
	 *
233
	 * @return bool
234 21
	 */
235
	public function isQuickCreateOptionDisabled()
236 21
	{
237 21
		$moduleModel = $this->getModule();
238 21
		if (0 == $this->get('quickcreate') || 3 == $this->get('quickcreate') || !$moduleModel->isQuickCreateSupported()) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $this->get('quickcreate') of type mixed|null to 0; this is ambiguous as not only 0 == 0 is true, but null == 0 is true, too. Consider using a strict comparison ===.
Loading history...
239 21
			return true;
240 21
		}
241
		return false;
242 21
	}
243
244
	/**
245
	 * Function which will specify whether the mass edit option is disabled.
246
	 *
247
	 * @return bool
248
	 */
249
	public function isMassEditOptionDisabled()
250
	{
251
		if (0 == $this->get('masseditable') || 1 != $this->get('displaytype') || 3 == $this->get('masseditable')) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $this->get('masseditable') of type mixed|null to 0; this is ambiguous as not only 0 == 0 is true, but null == 0 is true, too. Consider using a strict comparison ===.
Loading history...
252
			return true;
253
		}
254
		return false;
255
	}
256
257
	/**
258
	 * Function which will specify whether the default value option is disabled.
259
	 *
260
	 * @return bool
261
	 */
262
	public function isDefaultValueOptionDisabled(): bool
263
	{
264
		if ($this->isMandatoryOptionDisabled() || $this->isReferenceField() || 'image' === $this->getFieldDataType() || 'multiImage' === $this->getFieldDataType()) {
265
			return true;
266
		}
267
		return false;
268
	}
269
270
	/**
271
	 * A function that will determine if the default value option is disabled for an WebserviceApps configuration.
272
	 *
273
	 * @return bool
274
	 */
275
	public function isDefaultValueForWebservice(): bool
276
	{
277
		return !(\in_array($this->get('uitype'), ['4', '70']) || 'image' === $this->getFieldDataType() || 'multiImage' === $this->getFieldDataType());
278
	}
279
280
	/**
281
	 * Function to check whether summary field option is disable or not.
282
	 *
283
	 * @return bool true/false
284
	 */
285
	public function isSummaryFieldOptionDisabled()
286
	{
287
		return 70 === $this->get('uitype');
288
	}
289
290
	/**
291
	 * Function to check field is editable or not.
292
	 *
293
	 * @param string $viewName
294
	 *
295
	 * @return bool true/false
296
	 */
297
	public function isEditable(string $viewName = 'Edit'): bool
298
	{
299
		if ('ModComments' === $this->getModuleName() && \in_array($this->getName(), ['commentcontent', 'userid', 'created_user_id', 'customer', 'reasontoedit', 'parents', 'assigned_user_id', 'creator', 'modifiedtime', 'related_to', 'createdtime', 'parent_comments'])) {
300
			return false;
301
		}
302
		return true;
303
	}
304
305
	/**
306
	 * Function to get instance.
307
	 *
308
	 * @param string $value  - fieldname or fieldid
309
	 * @param <type> $module - optional - module instance
0 ignored issues
show
Documentation Bug introduced by
The doc comment <type> at position 0 could not be parsed: Unknown type name '<' at position 0 in <type>.
Loading history...
310
	 *
311
	 * @return self
312
	 */
313
	public static function getInstance($value, $module = false)
314
	{
315
		$fieldObject = parent::getInstance($value, $module);
316
		$objectProperties = get_object_vars($fieldObject);
317
		$fieldModel = new self();
318
		foreach ($objectProperties as $properName => $propertyValue) {
319
			$fieldModel->{$properName} = $propertyValue;
320
		}
321
		return $fieldModel;
322
	}
323
324
	/**
325
	 * Function to get all fields list for all blocks.
326
	 *
327
	 * @param array List of block ids
328
	 * @param Vtiger_Module_Model $moduleInstance
329
	 * @param mixed               $blockId
330
	 *
331
	 * @return array List of Field models Settings_LayoutEditor_Field_Model
332
	 */
333
	public static function getInstanceFromBlockIdList($blockId, $moduleInstance = false)
334
	{
335
		if (!\is_array($blockId)) {
336
			$blockId = [$blockId];
337
		}
338
		$query = (new \App\Db\Query())->from('vtiger_field')->where(['block' => $blockId])->orderBy('sequence');
339
		$dataReader = $query->createCommand()->query();
340
		$fieldModelsList = [];
341
		while ($row = $dataReader->read()) {
342
			$fieldModel = new self();
343
			$fieldModel->initialize($row);
344
			if ($moduleInstance) {
345
				$fieldModel->setModule($moduleInstance);
346
			}
347
			$fieldModelsList[$row['fieldname']] = $fieldModel;
348
		}
349
		$dataReader->close();
350
351
		return $fieldModelsList;
352
	}
353
354
	/** {@inheritdoc} */
355
	public function getFieldInfo(): array
356
	{
357
		$fieldInfo = parent::getFieldInfo();
358
		$fieldInfo['isQuickCreateDisabled'] = $this->isQuickCreateOptionDisabled();
359
		$fieldInfo['isSummaryField'] = $this->isSummaryField();
360
		$fieldInfo['isSummaryFieldDisabled'] = $this->isSummaryFieldOptionDisabled();
361
		$fieldInfo['isMassEditDisabled'] = $this->isMassEditOptionDisabled();
362
		$fieldInfo['isDefaultValueDisabled'] = $this->isDefaultValueOptionDisabled();
363
		return $fieldInfo;
364
	}
365
366
	/**
367
	 * Get webservice data.
368
	 *
369
	 * @param int $webserviceApp
370
	 *
371
	 * @return array
372
	 */
373
	public function getWebserviceData(int $webserviceApp): array
374
	{
375
		if (isset($this->webserviceData)) {
376
			return $this->webserviceData;
377
		}
378
		return $this->webserviceData = (new \App\Db\Query())->from('w_#__fields_server')->where(['fieldid' => $this->getId(), 'serverid' => $webserviceApp])->one(\App\Db::getInstance('webservice')) ?: [];
379
	}
380
381
	/**
382
	 * Load webservice data.
383
	 *
384
	 * @param int $webserviceApp
385
	 *
386
	 * @return void
387
	 */
388
	public function loadWebserviceData(int $webserviceApp): void
389
	{
390
		$data = $this->getWebserviceData($webserviceApp);
391
		if (empty($data['is_default'])) {
392
			$this->set('defaultvalue', '');
393
		} else {
394
			$this->set('defaultvalue', $data['default_value']);
395
		}
396
		if (!empty($data['visibility'])) {
397
			$this->set('displaytype', $data['visibility']);
398
		}
399
	}
400
401
	/**
402
	 * Update webservice data.
403
	 *
404
	 * @param array $data
405
	 * @param int   $webserviceApp
406
	 *
407
	 * @return void
408
	 */
409
	public function updateWebserviceData(array $data, int $webserviceApp): void
410
	{
411
		$createCommand = \App\Db::getInstance('webservice')->createCommand();
412
		if ($this->getWebserviceData($webserviceApp)) {
413
			$createCommand->update('w_#__fields_server', $data, ['fieldid' => $this->getId(), 'serverid' => $webserviceApp])->execute();
414
		} else {
415
			$createCommand->insert('w_#__fields_server', \App\Utils::merge($data, ['fieldid' => $this->getId(), 'serverid' => $webserviceApp]))->execute();
416
		}
417
		\App\Cache::delete('WebserviceAppsFields', $webserviceApp);
418
	}
419
}
420