WebservicesConvertLead::vtwsConvertlead()   F
last analyzed

Complexity

Conditions 20
Paths 1744

Size

Total Lines 93
Code Lines 63

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 420

Importance

Changes 0
Metric Value
eloc 63
dl 0
loc 93
ccs 0
cts 61
cp 0
rs 0
c 0
b 0
f 0
cc 20
nc 1744
nop 2
crap 420

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
12
class WebservicesConvertLead
13
{
14
	/**
15
	 * The function convert the lead.
16
	 *
17
	 * @param string             $entityvalues
18
	 * @param Users_Record_Model $user
19
	 *
20
	 * @return int
21
	 */
22
	public static function vtwsConvertlead($entityvalues, Users_Record_Model $user)
23
	{
24
		\App\Log::trace('Start ' . __METHOD__);
25
		if (empty($entityvalues['assignedTo'])) {
26
			$entityvalues['assignedTo'] = $user->id;
27
		}
28
		if (empty($entityvalues['transferRelatedRecordsTo'])) {
29
			$entityvalues['transferRelatedRecordsTo'] = 'Accounts';
30
		}
31
		$recordModel = Vtiger_Record_Model::getInstanceById($entityvalues['leadId']);
32
		$leadInfo = $recordModel->getData();
33
		$leadIdComponents = $entityvalues['leadId'];
34
		if ((new \App\Db\Query())->select(['converted'])->from('vtiger_leaddetails')->where(['converted' => 1, 'leadid' => $leadIdComponents])->exists()) {
35
			$translateAlreadyConvertedError = \App\Language::translate('LBL_LEAD_ALREADY_CONVERTED', 'Leads');
36
			\App\Log::error('Error converting a lead: ' . $translateAlreadyConvertedError);
37
			throw new WebServiceException('LEAD_ALREADY_CONVERTED', $translateAlreadyConvertedError);
38
		}
39
40
		$eventHandler = new App\EventHandler();
41
		$eventHandler->setParams(['entityValues' => $entityvalues, 'user' => $user, 'leadInfo' => $leadInfo]);
42
		$eventHandler->trigger('EntityBeforeConvertLead');
43
44
		$entityIds = [];
45
		$availableModules = ['Accounts', 'Contacts'];
46
47
		if (empty($entityvalues['entities']['Accounts']['create']) && empty($entityvalues['entities']['Contacts']['create'])) {
48
			return null;
49
		}
50
51
		foreach ($availableModules as $entityName) {
52
			if (!empty($entityvalues['entities'][$entityName]['create'])) {
53
				$entityvalue = $entityvalues['entities'][$entityName];
54
55
				$entityObjectValues = [];
56
				$entityObjectValues['assigned_user_id'] = $entityvalues['assignedTo'];
57
				$entityObjectValues = static::vtwsPopulateConvertLeadEntities($entityvalue, $entityObjectValues, $recordModel, $leadInfo);
0 ignored issues
show
Bug introduced by
$entityObjectValues of type array is incompatible with the type string expected by parameter $entity of WebservicesConvertLead::...teConvertLeadEntities(). ( Ignorable by Annotation )

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

57
				$entityObjectValues = static::vtwsPopulateConvertLeadEntities($entityvalue, /** @scrutinizer ignore-type */ $entityObjectValues, $recordModel, $leadInfo);
Loading history...
Bug introduced by
$leadInfo of type array is incompatible with the type string expected by parameter $leadinfo of WebservicesConvertLead::...teConvertLeadEntities(). ( Ignorable by Annotation )

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

57
				$entityObjectValues = static::vtwsPopulateConvertLeadEntities($entityvalue, $entityObjectValues, $recordModel, /** @scrutinizer ignore-type */ $leadInfo);
Loading history...
58
59
				//update the contacts relation
60
				if ('Contacts' == $entityvalue['name'] && !empty($entityIds['Accounts'])) {
61
					$entityObjectValues['parent_id'] = $entityIds['Accounts'];
62
				}
63
64
				try {
65
					$create = true;
66
					if ('Accounts' == $entityvalue['name'] && !empty($entityvalue['convert_to_id']) && \is_int($entityvalue['convert_to_id'])) {
67
						$entityIds[$entityName] = $entityvalue['convert_to_id'];
68
						$create = false;
69
					}
70
					if ($create) {
71
						$recordModel = Vtiger_Record_Model::getCleanInstance($entityvalue['name']);
72
						$fieldModelList = $recordModel->getModule()->getFields();
73
						foreach ($fieldModelList as $fieldName => &$fieldModel) {
74
							if (isset($entityObjectValues[$fieldName])) {
75
								$recordModel->set($fieldName, $entityObjectValues[$fieldName]);
76
							} else {
77
								$defaultValue = $fieldModel->getDefaultFieldValue();
78
								if ('' !== $defaultValue) {
79
									$recordModel->set($fieldName, $defaultValue);
80
								}
81
							}
82
						}
83
						$recordModel->save();
84
						$entityIds[$entityName] = $recordModel->getId();
85
					}
86
				} catch (Exception $e) {
87
					\App\Log::error('Error converting a lead: ' . $e->getMessage());
88
					throw new WebServiceException('UNKNOWN_OPERATION', $e->getMessage() . ' : ' . $entityvalue['name']);
89
				}
90
			}
91
		}
92
93
		try {
94
			$accountId = $entityIds['Accounts'];
95
			$contactId = $entityIds['Contacts'] ?? null;
96
			static::vtwsConvertLeadTransferHandler($leadIdComponents, $entityIds, $entityvalues);
97
98
			$relatedId = $entityIds[$entityvalues['transferRelatedRecordsTo']];
99
			\WebservicesUtils::vtwsGetRelatedActivities($leadIdComponents, $accountId, $contactId, $relatedId);
100
			static::vtwsUpdateConvertLeadStatus($entityIds, $entityvalues['leadId'], $user);
101
102
			$eventHandler->addParams('entityIds', $entityIds);
103
			$eventHandler->trigger('EntityAfterConvertLead');
104
		} catch (Exception $e) {
105
			\App\Log::error('Error converting a lead: ' . $e->getMessage());
106
			foreach ($entityIds as $id) {
107
				vtws_delete($id, $user);
108
			}
109
110
			return null;
111
		}
112
		\App\Log::trace('End ' . __METHOD__);
113
114
		return $entityIds;
115
	}
116
117
	/**
118
	 * Populate the entity fields with the lead info.
119
	 * If mandatory field is not provided populate with '????'.
120
	 *
121
	 * @param array               $entityvalue
122
	 * @param string              $entity
123
	 * @param Vtiger_Record_Model $recordModel
124
	 * @param string              $leadinfo
125
	 *
126
	 * @return entity array
0 ignored issues
show
Bug introduced by
The type entity was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
127
	 */
128
	public static function vtwsPopulateConvertLeadEntities($entityvalue, $entity, Vtiger_Record_Model $recordModel, $leadinfo)
129
	{
130
		$targetModuleModel = Vtiger_Module_Model::getInstance($entityvalue['name']);
131
		$entityName = $entityvalue['name'];
132
		$dataReader = (new \App\Db\Query())->from('vtiger_convertleadmapping')->createCommand()->query();
133
		if ($dataReader->count()) {
134
			switch ($entityName) {
135
				case 'Accounts':
136
					$column = 'accountfid';
137
					break;
138
				case 'Contacts':
139
					$column = 'contactfid';
140
					break;
141
				default:
142
					$column = 'leadfid';
143
					break;
144
			}
145
			$row = $dataReader->read();
146
			$count = 1;
147
			foreach ($targetModuleModel->getFields() as $fieldname => $field) {
148
				$defaultvalue = $field->getDefaultFieldValue();
149
				if ($defaultvalue && empty($entity[$fieldname])) {
150
					$entity[$fieldname] = $defaultvalue;
151
				}
152
			}
153
			do {
154
				$entityField = \WebservicesUtils::vtwsGetFieldfromFieldId($row[$column], $targetModuleModel);
155
				if (null === $entityField) {
156
					continue;
157
				}
158
				$leadField = \WebservicesUtils::vtwsGetFieldfromFieldId($row['leadfid'], $recordModel->getModule());
159
				if (null === $leadField) {
160
					continue;
161
				}
162
				$leadFieldName = $leadField->getFieldName();
0 ignored issues
show
Deprecated Code introduced by
The function Vtiger_Field_Model::getFieldName() has been deprecated: Use $this->getName() ( Ignorable by Annotation )

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

162
				$leadFieldName = /** @scrutinizer ignore-deprecated */ $leadField->getFieldName();

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...
163
				$entityFieldName = $entityField->getFieldName();
0 ignored issues
show
Deprecated Code introduced by
The function Vtiger_Field_Model::getFieldName() has been deprecated: Use $this->getName() ( Ignorable by Annotation )

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

163
				$entityFieldName = /** @scrutinizer ignore-deprecated */ $entityField->getFieldName();

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...
164
				$entity[$entityFieldName] = $leadinfo[$leadFieldName];
165
				++$count;
166
			} while ($row = $dataReader->read());
167
			foreach ($entityvalue as $fieldname => $fieldvalue) {
168
				if (!empty($fieldvalue)) {
169
					$entity[$fieldname] = $fieldvalue;
170
				}
171
			}
172
			$entity = static::vtwsValidateConvertLeadEntityMandatoryValues($entity, $targetModuleModel);
173
		}
174
		return $entity;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $entity returns the type string which is incompatible with the documented return type entity.
Loading history...
175
	}
176
177
	/**
178
	 * Validate convert lead entity mandatory values.
179
	 *
180
	 * @param string              $entity
181
	 * @param Vtiger_Module_Model $targetModuleModel
182
	 *
183
	 * @return string
184
	 */
185
	public static function vtwsValidateConvertLeadEntityMandatoryValues($entity, Vtiger_Module_Model $targetModuleModel)
186
	{
187
		$mandatoryFields = $targetModuleModel->getMandatoryFieldModels();
188
		foreach ($mandatoryFields as $field => $fieldModel) {
189
			if (empty($entity[$field])) {
190
				if (('picklist' === $fieldModel->getFieldDataType() || 'multipicklist' === $fieldModel->getFieldDataType() || 'date' === $fieldModel->getFieldDataType() || 'datetime' === $fieldModel->getFieldDataType()) && $fieldModel->isEditable()) {
191
					$entity[$field] = $fieldModel->getDefaultFieldValue();
192
				} else {
193
					$entity[$field] = '????';
194
				}
195
			}
196
		}
197
		return $entity;
198
	}
199
200
	/**
201
	 * function to handle the transferring of related records for lead.
202
	 *
203
	 * @param int    $leadIdComponents
204
	 * @param int    $entityIds
205
	 * @param string $entityvalues
206
	 *
207
	 * @return bool
208
	 */
209
	public static function vtwsConvertLeadTransferHandler($leadIdComponents, $entityIds, $entityvalues)
210
	{
211
		try {
212
			$entityidComponents = $entityIds[$entityvalues['transferRelatedRecordsTo']];
213
			\WebservicesUtils::vtwsTransferLeadRelatedRecords($leadIdComponents, $entityidComponents, $entityvalues['transferRelatedRecordsTo']);
214
		} catch (Exception $e) {
215
			return false;
216
		}
217
		return true;
218
	}
219
220
	/**
221
	 * The function updates the status convert lead.
222
	 *
223
	 * @param int                $entityIds
224
	 * @param int                $leadId
225
	 * @param Users_Record_Model $user
226
	 */
227
	public static function vtwsUpdateConvertLeadStatus($entityIds, $leadId, Users_Record_Model $user)
228
	{
229
		$db = \App\Db::getInstance();
230
		if ('' != $entityIds['Accounts'] || '' != $entityIds['Contacts']) {
231
			\App\Cache::delete('Leads.converted', $leadId);
232
			$result = $db->createCommand()
233
				->update('vtiger_leaddetails', ['converted' => 1], ['leadid' => $leadId])
234
				->execute();
235
			if (false === $result) {
0 ignored issues
show
introduced by
The condition false === $result is always false.
Loading history...
236
				throw new WebServiceException('FAILED_TO_MARK_LEAD_CONVERTED', 'Failed mark lead converted');
237
			}
238
			//update the modifiedtime and modified by information for the record
239
			$db->createCommand()
240
				->update('vtiger_crmentity', ['modifiedtime' => date('Y-m-d H:i:s'), 'modifiedby' => $user->getId()], ['crmid' => $leadId])
241
				->execute();
242
		}
243
		$moduleArray = ['Accounts', 'Contacts'];
244
		foreach ($moduleArray as $module) {
245
			if (!empty($entityIds[$module])) {
246
				$moduleModel = Vtiger_Module_Model::getInstance($module);
247
				$tablename = $moduleModel->getFieldByName('isconvertedfromlead')->getTableName();
248
				$db->createCommand()
249
					->update($tablename, ['isconvertedfromlead' => 1], [$moduleModel->getEntityInstance()->tab_name_index[$tablename] => $entityIds[$module]])
250
					->execute();
251
			}
252
		}
253
	}
254
}
255