VTCreateEntityTask::doTask()   F
last analyzed

Complexity

Conditions 35
Paths 273

Size

Total Lines 91
Code Lines 71

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 1260

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 71
c 3
b 0
f 0
dl 0
loc 91
ccs 0
cts 65
cp 0
rs 2.4208
cc 35
nc 273
nop 1
crap 1260

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/* +**********************************************************************************
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
require_once 'modules/com_vtiger_workflow/VTWorkflowUtils.php';
12
13
class VTCreateEntityTask extends VTTask
14
{
15
	public $executeImmediately = true;
16
17
	public function getFieldNames()
18
	{
19
		return ['entity_type', 'reference_field', 'field_value_mapping', 'mappingPanel', 'verifyIfExists', 'relationId'];
20
	}
21
22
	/**
23
	 * Execute task.
24
	 *
25
	 * @param Vtiger_Record_Model $recordModel
26
	 */
27
	public function doTask($recordModel)
28
	{
29
		$moduleName = $recordModel->getModuleName();
30
		$recordId = $recordModel->getId();
31
		$entityType = $this->entity_type;
0 ignored issues
show
Bug Best Practice introduced by
The property entity_type does not exist on VTCreateEntityTask. Did you maybe forget to declare it?
Loading history...
32
		if (!\App\Module::isModuleActive($entityType)) {
33
			return;
34
		}
35
		$fieldValueMapping = [];
36
		if (!empty($this->field_value_mapping)) {
37
			$fieldValueMapping = \App\Json::decode($this->field_value_mapping);
0 ignored issues
show
Bug Best Practice introduced by
The property field_value_mapping does not exist on VTCreateEntityTask. Did you maybe forget to declare it?
Loading history...
38
		}
39
		if (!$this->mappingPanel && !empty($entityType) && !empty($fieldValueMapping) && \count($fieldValueMapping) > 0) {
0 ignored issues
show
Bug Best Practice introduced by
The property mappingPanel does not exist on VTCreateEntityTask. Did you maybe forget to declare it?
Loading history...
40
			$newRecordModel = Vtiger_Record_Model::getCleanInstance($entityType);
41
			$ownerFields = array_keys($newRecordModel->getModule()->getFieldsByType('owner'));
42
			foreach ($fieldValueMapping as $fieldInfo) {
43
				$fieldName = $fieldInfo['fieldname'];
44
				$destinyModuleName = $this->getDestinyModuleName($fieldInfo['modulename']);
45
				$sourceModuleName = $destinyModuleName ?? $fieldInfo['modulename'];
46
				$fieldValueType = $fieldInfo['valuetype'];
47
				$fieldValue = trim($fieldInfo['value']);
48
				if ('fieldname' === $fieldValueType) {
49
					if ($this->relationId) {
0 ignored issues
show
Bug Best Practice introduced by
The property relationId does not exist on VTCreateEntityTask. Did you maybe forget to declare it?
Loading history...
50
						$fieldValue = $destinyModuleName ? $newRecordModel->get($fieldValue) : $recordModel->get($fieldValue);
51
					} else {
52
						$fieldValue = $sourceModuleName === $entityType ? $newRecordModel->get($fieldValue) : $fieldValue = $recordModel->get($fieldValue);
0 ignored issues
show
Unused Code introduced by
The assignment to $fieldValue is dead and can be removed.
Loading history...
53
					}
54
				} elseif ('expression' === $fieldValueType) {
55
					require_once 'modules/com_vtiger_workflow/expression_engine/include.php';
56
57
					$parser = new VTExpressionParser(new VTExpressionSpaceFilter(new VTExpressionTokenizer($fieldValue)));
58
					$expression = $parser->expression();
59
					$exprEvaluater = new VTFieldExpressionEvaluater($expression);
60
					if ($sourceModuleName === $entityType) {
61
						$fieldValue = $exprEvaluater->evaluate($newRecordModel);
62
					} else {
63
						$fieldValue = $exprEvaluater->evaluate($recordModel);
64
					}
65
				} elseif (preg_match('/([^:]+):boolean$/', $fieldValue, $match)) {
66
					$fieldValue = $match[1];
67
					if ('true' == $fieldValue) {
68
						$fieldValue = '1';
69
					} else {
70
						$fieldValue = '0';
71
					}
72
				} elseif (!\in_array($fieldName, $ownerFields)) {
73
					$fieldValue = $newRecordModel->getField($fieldName)->getUITypeModel()->getDBValue($fieldValue);
74
				}
75
				if (\in_array($fieldName, $ownerFields)) {
76
					if ('triggerUser' === $fieldValue) {
77
						$fieldValue = $recordModel->executeUser;
0 ignored issues
show
Bug introduced by
The property executeUser does not seem to exist on Vtiger_Record_Model.
Loading history...
78
					} elseif (!is_numeric($fieldValue)) {
79
						$userId = App\User::getUserIdByName($fieldValue);
80
						$groupId = \App\Fields\Owner::getGroupId($fieldValue);
81
						if (!$userId && !$groupId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $userId of type integer|null is loosely compared to false; this is ambiguous if the integer can be 0. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
82
							$fieldValue = $recordModel->get($fieldName);
83
						} else {
84
							$fieldValue = (!$userId) ? $groupId : $userId;
85
						}
86
					}
87
				}
88
				$newRecordModel->set($fieldName, $fieldValue);
89
			}
90
			$newRecordModel->set($this->reference_field, $recordId);
0 ignored issues
show
Bug Best Practice introduced by
The property reference_field does not exist on VTCreateEntityTask. Did you maybe forget to declare it?
Loading history...
91
			// To handle cyclic process
92
			$newRecordModel->setHandlerExceptions(['disableHandlerClasses' => ['Vtiger_Workflow_Handler']]);
93
			$newRecordModel->save();
94
95
			$relationModel = \Vtiger_Relation_Model::getInstance($recordModel->getModule(), $newRecordModel->getModule(), $this->relationId);
96
			if ($relationModel) {
0 ignored issues
show
introduced by
$relationModel is of type Vtiger_Relation_Model, thus it always evaluated to true.
Loading history...
97
				$relationModel->addRelation($recordModel->getId(), $newRecordModel->getId());
98
			}
99
		} elseif ($this->mappingPanel && $entityType) {
100
			if (!empty($this->verifyIfExists) && ($relationListView = Vtiger_RelationListView_Model::getInstance($recordModel, $entityType, false)) && (int) $relationListView->getRelatedEntriesCount() > 0) {
101
				return true;
102
			}
103
			$saveContinue = true;
104
			$newRecordModel = Vtiger_Record_Model::getCleanInstance($entityType);
105
			$parentRecordModel = Vtiger_Record_Model::getInstanceById($recordId, $moduleName);
106
			$newRecordModel->setRecordFieldValues($parentRecordModel);
107
			$mandatoryFields = $newRecordModel->getModule()->getMandatoryFieldModels();
108
			if (!empty($fieldValueMapping) && \is_array($fieldValueMapping)) {
109
				$newRecordModel = $this->setFieldMapping($fieldValueMapping, $newRecordModel, $parentRecordModel);
110
			}
111
			foreach ($mandatoryFields as $field) {
112
				if ('' === $newRecordModel->get($field->getName()) || null === $newRecordModel->get($field->getName())) {
113
					$saveContinue = false;
114
				}
115
			}
116
			if ($saveContinue) {
117
				$newRecordModel->save();
118
			}
119
		}
120
	}
121
122
	public function setFieldMapping($fieldValueMapping, $recordModel, $parentRecordModel)
123
	{
124
		$ownerFields = [];
125
		$entityType = $this->entity_type;
0 ignored issues
show
Bug Best Practice introduced by
The property entity_type does not exist on VTCreateEntityTask. Did you maybe forget to declare it?
Loading history...
126
		foreach ($recordModel->getModule()->getFields() as $name => $fieldModel) {
127
			if ('owner' === $fieldModel->getFieldDataType()) {
128
				$ownerFields[] = $name;
129
			}
130
		}
131
		foreach ($fieldValueMapping as $fieldInfo) {
132
			$fieldName = $fieldInfo['fieldname'];
133
			$fieldValueType = $fieldInfo['valuetype'];
134
			$fieldValue = trim($fieldInfo['value']);
135
			$destinyModuleName = $this->getDestinyModuleName($fieldInfo['modulename']);
136
			$sourceModuleName = $destinyModuleName ?? $fieldInfo['modulename'];
137
			if ('fieldname' === $fieldValueType) {
138
				if ($this->relationId) {
0 ignored issues
show
Bug Best Practice introduced by
The property relationId does not exist on VTCreateEntityTask. Did you maybe forget to declare it?
Loading history...
139
					$fieldValue = $destinyModuleName ? $parentRecordModel->get($fieldValue) : $recordModel->get($fieldValue);
140
				} else {
141
					$fieldValue = $sourceModuleName === $entityType ? $fieldValue = $recordModel->get($fieldValue) : $fieldValue = $parentRecordModel->get($fieldValue);
0 ignored issues
show
Unused Code introduced by
The assignment to $fieldValue is dead and can be removed.
Loading history...
142
				}
143
			} elseif ('expression' == $fieldValueType) {
144
				require_once 'modules/com_vtiger_workflow/expression_engine/include.php';
145
146
				$parser = new VTExpressionParser(new VTExpressionSpaceFilter(new VTExpressionTokenizer($fieldValue)));
147
				$expression = $parser->expression();
148
				$exprEvaluater = new VTFieldExpressionEvaluater($expression);
149
				if ($sourceModuleName === $entityType) {
150
					$fieldValue = $exprEvaluater->evaluate($recordModel);
151
				} else {
152
					$fieldValue = $exprEvaluater->evaluate($parentRecordModel);
153
				}
154
			} elseif (preg_match('/([^:]+):boolean$/', $fieldValue, $match)) {
155
				$fieldValue = $match[1];
156
				if ('true' == $fieldValue) {
157
					$fieldValue = 1;
158
				} else {
159
					$fieldValue = 0;
160
				}
161
			} elseif (!\in_array($fieldName, $ownerFields)) {
162
				$fieldValue = $recordModel->getField($fieldName)->getUITypeModel()->getDBValue($fieldValue);
163
			}
164
			if (\in_array($fieldName, $ownerFields) && !is_numeric($fieldValue)) {
165
				$userId = App\User::getUserIdByName($fieldValue);
166
				$groupId = \App\Fields\Owner::getGroupId($fieldValue);
167
				if (!$userId && !$groupId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $userId of type integer|null is loosely compared to false; this is ambiguous if the integer can be 0. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
168
					$fieldValue = $parentRecordModel->get($fieldName);
169
				} else {
170
					$fieldValue = (!$userId) ? $groupId : $userId;
171
				}
172
			}
173
			$recordModel->set($fieldName, $fieldValue);
174
		}
175
		return $recordModel;
176
	}
177
178
	/**
179
	 * Get destiny module name.
180
	 *
181
	 * @param string $destinyModuleName
182
	 *
183
	 * @return string|null
184
	 */
185
	private function getDestinyModuleName(string $destinyModuleName): ?string
186
	{
187
		$moduleName = null;
188
		if (strpos($destinyModuleName, 'destinyModule') > 0) {
189
			$moduleName = explode('::', $destinyModuleName)[1];
190
		}
191
		return $moduleName;
192
	}
193
}
194