Contacts   A
last analyzed

Complexity

Total Complexity 40

Size/Duplication

Total Lines 272
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 40
eloc 152
dl 0
loc 272
ccs 0
cts 118
cp 0
rs 9.2
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
C getHierarchyData() 0 43 14
A setRelationTables() 0 13 2
B getParent() 0 49 11
B getChild() 0 45 9
A getHierarchy() 0 23 4

How to fix   Complexity   

Complex Class

Complex classes like Contacts 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 Contacts, and based on these observations, apply Extract Interface, too.

1
<?php
2
/* * *******************************************************************************
3
 * The contents of this file are subject to the SugarCRM Public License Version 1.1.2
4
 * ("License"); You may not use this file except in compliance with the
5
 * License. You may obtain a copy of the License at http://www.sugarcrm.com/SPL
6
 * Software distributed under the License is distributed on an  "AS IS"  basis,
7
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
8
 * the specific language governing rights and limitations under the License.
9
 * The Original Code is:  SugarCRM Open Source
10
 * The Initial Developer of the Original Code is SugarCRM, Inc.
11
 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.;
12
 * All Rights Reserved.
13
 * Contributor(s): ______________________________________.
14
 * ****************************************************************************** */
15
/* * *******************************************************************************
16
 * $Header: /advent/projects/wesat/vtiger_crm/sugarcrm/modules/Contacts/Contacts.php,v 1.70 2005/04/27 11:21:49 rank Exp $
17
 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
18
 * All Rights Reserved.
19
 * Contributor(s): ______________________________________..
20
 * ******************************************************************************
21
 * Contributor(s): YetiForce S.A.
22
 */
23
24
// Contact is used to store customer information.
25
class Contacts extends CRMEntity
26
{
27
	public $table_name = 'vtiger_contactdetails';
28
	public $table_index = 'contactid';
29
	public $tab_name = ['vtiger_crmentity', 'vtiger_contactdetails', 'vtiger_contactaddress', 'vtiger_contactsubdetails', 'vtiger_contactscf', 'vtiger_customerdetails', 'vtiger_entity_stats'];
30
	public $tab_name_index = ['vtiger_crmentity' => 'crmid', 'vtiger_contactdetails' => 'contactid', 'vtiger_contactaddress' => 'contactaddressid', 'vtiger_contactsubdetails' => 'contactsubscriptionid', 'vtiger_contactscf' => 'contactid', 'vtiger_customerdetails' => 'customerid', 'vtiger_entity_stats' => 'crmid'];
31
32
	/**
33
	 * Mandatory table for supporting custom fields.
34
	 */
35
	public $customFieldTable = ['vtiger_contactscf', 'contactid'];
36
	public $column_fields = [];
37
38
	public $list_fields_name = [
39
		'First Name' => 'firstname',
40
		'Last Name' => 'lastname',
41
		'Member Of' => 'parent_id',
42
		'Email' => 'email',
43
		'Office Phone' => 'phone',
44
		'Assigned To' => 'assigned_user_id',
45
	];
46
	public $search_fields = [
47
		'First Name' => ['contactdetails' => 'firstname'],
48
		'Last Name' => ['contactdetails' => 'lastname'],
49
		'Member Of' => ['contactdetails' => 'parent_id'],
50
		'Assigned To' => ['crmentity' => 'smownerid'],
51
	];
52
	public $search_fields_name = [];
53
54
	/**
55
	 * @var string[] List of fields in the RelationListView
56
	 */
57
	public $relationFields = [];
58
	// Used when enabling/disabling the mandatory fields for the module.
59
	// Refers to vtiger_field.fieldname values.
60
	public $mandatory_fields = ['assigned_user_id', 'lastname', 'createdtime', 'modifiedtime'];
61
	//Default Fields for Email Templates -- Pavani
62
	public $emailTemplate_defaultFields = ['firstname', 'lastname', 'title', 'email', 'department', 'phone', 'mobile'];
63
	//Added these variables which are used as default order by and sortorder in ListView
64
	public $default_order_by = '';
65
	public $default_sort_order = 'ASC';
66
	// For Alphabetical search
67
	public $def_basicsearch_col = 'lastname';
68
69
	/**
70
	 * Function to get the relation tables for related modules.
71
	 *
72
	 * @param bool|string $secModule secondary module name
73
	 *
74
	 * @return array with table names and fieldnames storing relations between module and this module
75
	 */
76
	public function setRelationTables($secModule = false)
77
	{
78
		$relTables = [
79
			'Products' => ['vtiger_seproductsrel' => ['crmid', 'productid'], 'vtiger_contactdetails' => 'contactid'],
80
			'Campaigns' => ['vtiger_campaign_records' => ['crmid', 'campaignid'], 'vtiger_contactdetails' => 'contactid'],
81
			'Documents' => ['vtiger_senotesrel' => ['crmid', 'notesid'], 'vtiger_contactdetails' => 'contactid'],
82
			'OSSMailView' => ['vtiger_ossmailview_relation' => ['crmid', 'ossmailviewid'], 'vtiger_contactdetails' => 'contactid'],
83
		];
84
		if (false === $secModule) {
85
			return $relTables;
86
		}
87
88
		return $relTables[$secModule];
89
	}
90
91
	/**
92
	 * Function to get contacts hierarchy.
93
	 *
94
	 * @param int  $id
95
	 * @param bool $getRawData
96
	 * @param bool $getLinks
97
	 *
98
	 * @return array
99
	 */
100
	public function getHierarchy($id, $getRawData = false, $getLinks = true)
101
	{
102
		$listviewHeader = [];
103
		$listviewEntries = [];
104
		$listColumns = App\Config::module('Contacts', 'COLUMNS_IN_HIERARCHY');
105
		if (empty($listColumns)) {
106
			$listColumns = $this->list_fields_name;
107
		}
108
		foreach ($listColumns as $fieldname => $colname) {
109
			if (\App\Field::getFieldPermission('Contacts', $colname)) {
110
				$listviewHeader[] = App\Language::translate($fieldname, 'Contacts');
111
			}
112
		}
113
		$rows = [];
114
		$encountered = [$id];
115
		$rows = $this->getParent($id, $rows, $encountered);
116
		$baseId = current(array_keys($rows));
117
		$rows = [$baseId => $rows[$baseId]];
118
		$rows[$baseId] = $this->getChild($baseId, $rows[$baseId], $rows[$baseId]['depth']);
119
120
		$this->getHierarchyData($id, $rows[$baseId], $baseId, $listviewEntries, $getRawData, $getLinks);
121
122
		return ['header' => $listviewHeader, 'entries' => $listviewEntries];
123
	}
124
125
	/**
126
	 * Function to create array of all the contacts in the hierarchy.
127
	 *
128
	 * @param int   $id
129
	 * @param array $baseInfo
130
	 * @param int   $recordId        - id
131
	 * @param array $listviewEntries
132
	 * @param bool  $getRawData
133
	 * @param bool  $getLinks
134
	 *
135
	 * @return array
136
	 */
137
	public function getHierarchyData($id, $baseInfo, $recordId, &$listviewEntries, $getRawData = false, $getLinks = true)
138
	{
139
		\App\Log::trace('Entering getHierarchyData(' . $id . ',' . $recordId . ') method ...');
140
		$currentUser = Users_Privileges_Model::getCurrentUserModel();
141
		$hasRecordViewAccess = $currentUser->isAdminUser() || \App\Privilege::isPermitted('Contacts', 'DetailView', $recordId);
142
		$listColumns = App\Config::module('Contacts', 'COLUMNS_IN_HIERARCHY');
143
		if (empty($listColumns)) {
144
			$listColumns = $this->list_fields_name;
145
		}
146
		$infoData = [];
147
		foreach ($listColumns as $colname) {
148
			if (\App\Field::getFieldPermission('Contacts', $colname)) {
149
				$data = \App\Purifier::encodeHtml($baseInfo[$colname]);
150
				if (false === $getRawData && 'firstname' === $colname) {
151
					if ($recordId != $id) {
152
						if ($getLinks) {
153
							if ($hasRecordViewAccess) {
154
								$data = '<a href="index.php?module=Contacts&action=DetailView&record=' . $recordId . '">' . $data . '</a>';
155
							} else {
156
								$data = '<span>' . $data . '&nbsp;<span class="fas fa-exclamation-circle"></span></span>';
157
							}
158
						}
159
					} else {
160
						$data = '<strong>' . $data . '</strong>';
161
					}
162
					$rowDepth = str_repeat(' .. ', $baseInfo['depth']);
163
					$data = $rowDepth . $data;
164
				} elseif ('parent_id' === $colname) {
165
					$data = \App\Record::getLabel($data);
166
				}
167
			}
168
			$infoData[] = $data;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $data does not seem to be defined for all execution paths leading up to this point.
Loading history...
169
		}
170
171
		$listviewEntries[$recordId] = $infoData;
172
		foreach ($baseInfo as $accId => $rowInfo) {
173
			if (\is_array($rowInfo) && (int) $accId) {
174
				$listviewEntries = $this->getHierarchyData($id, $rowInfo, $accId, $listviewEntries, $getRawData, $getLinks);
175
			}
176
		}
177
		\App\Log::trace('Exiting getHierarchyData method ...');
178
179
		return $listviewEntries;
180
	}
181
182
	/**
183
	 * Function to Recursively get all the parent.
184
	 *
185
	 * @param int   $id
186
	 * @param array $parent
187
	 * @param array $encountered
188
	 * @param int   $depthBase
189
	 *
190
	 * @return array
191
	 */
192
	public function getParent(int $id, array &$parent, array &$encountered, int $depthBase = 0)
193
	{
194
		\App\Log::trace('Entering getParent(' . $id . ') method ...');
195
		if ($depthBase == App\Config::module('Contacts', 'MAX_HIERARCHY_DEPTH')) {
196
			\App\Log::error('Exiting getParent method ... - exceeded maximum depth of hierarchy');
197
198
			return $parent;
199
		}
200
		$userNameSql = App\Module::getSqlForNameInDisplayFormat('Users');
201
		$row = (new App\Db\Query())->select([
202
			'vtiger_contactdetails.*',
203
			new \yii\db\Expression("CASE when (vtiger_users.user_name not like '') THEN {$userNameSql} ELSE vtiger_groups.groupname END as user_name"),
204
		])->from('vtiger_contactdetails')
205
			->innerJoin('vtiger_crmentity', 'vtiger_crmentity.crmid = vtiger_contactdetails.contactid')
206
			->leftJoin('vtiger_groups', 'vtiger_groups.groupid = vtiger_crmentity.smownerid')
207
			->leftJoin('vtiger_users', 'vtiger_users.id = vtiger_crmentity.smownerid')
208
			->where(['vtiger_crmentity.deleted' => 0, 'vtiger_contactdetails.contactid' => $id])
209
			->one();
210
		if ($row) {
211
			$parentid = $row['reportsto'];
212
			if ('' !== $parentid && 0 != $parentid && !\in_array($parentid, $encountered)) {
213
				$encountered[] = $parentid;
214
				$this->getParent($parentid, $parent, $encountered, $depthBase + 1);
215
			}
216
			$parentInfo = [];
217
			$depth = 0;
218
			if (isset($parent[$parentid])) {
219
				$depth = $parent[$parentid]['depth'] + 1;
220
			}
221
			$parentInfo['depth'] = $depth;
222
			$listColumns = App\Config::module('Contacts', 'COLUMNS_IN_HIERARCHY');
223
			if (empty($listColumns)) {
224
				$listColumns = $this->list_fields_name;
225
			}
226
			foreach ($listColumns as $columnname) {
227
				if ('assigned_user_id' === $columnname) {
228
					$parentInfo[$columnname] = $row['user_name'];
229
				} elseif ('parent_id' === $columnname) {
230
					$parentInfo[$columnname] = $row['parentid'];
231
				} else {
232
					$parentInfo[$columnname] = $row[$columnname];
233
				}
234
			}
235
236
			$parent[$id] = $parentInfo;
237
		}
238
		\App\Log::trace('Exiting getParent method ...');
239
240
		return $parent;
241
	}
242
243
	/**
244
	 * Function to Recursively get all the child.
245
	 *
246
	 * @param int   $id
247
	 * @param array $childRow
248
	 * @param int   $depthBase
249
	 *
250
	 * @return array
251
	 */
252
	public function getChild(int $id, array &$childRow, int $depthBase)
253
	{
254
		\App\Log::trace('Entering getChild(' . $id . ',' . $depthBase . ') method ...');
255
		if (empty($id) || $depthBase == App\Config::module('Contacts', 'MAX_HIERARCHY_DEPTH')) {
256
			\App\Log::error('Exiting getChild method ... - exceeded maximum depth of hierarchy');
257
258
			return $childRow;
259
		}
260
		$userNameSql = App\Module::getSqlForNameInDisplayFormat('Users');
261
		$dataReader = (new App\Db\Query())->select([
262
			'vtiger_contactdetails.*',
263
			new \yii\db\Expression("CASE when (vtiger_users.user_name NOT LIKE '') THEN $userNameSql ELSE vtiger_groups.groupname END as user_name"),
264
		])->from('vtiger_contactdetails')
265
			->innerJoin('vtiger_crmentity', 'vtiger_crmentity.crmid = vtiger_contactdetails.contactid')
266
			->leftJoin('vtiger_groups', 'vtiger_groups.groupid = vtiger_crmentity.smownerid')
267
			->leftJoin('vtiger_users', 'vtiger_users.id = vtiger_crmentity.smownerid')
268
			->where(['vtiger_crmentity.deleted' => 0, 'vtiger_contactdetails.reportsto' => $id])
269
			->createCommand()->query();
270
		$listColumns = App\Config::module('Contacts', 'COLUMNS_IN_HIERARCHY');
271
		if (empty($listColumns)) {
272
			$listColumns = $this->list_fields_name;
273
		}
274
		if ($dataReader->count() > 0) {
275
			$depth = $depthBase + 1;
276
			while ($row = $dataReader->read()) {
277
				$childId = $row['contactid'];
278
				$childContactsInfo = [];
279
				$childContactsInfo['depth'] = $depth;
280
				foreach ($listColumns as $columnname) {
281
					if ('assigned_user_id' === $columnname) {
282
						$childContactsInfo[$columnname] = $row['user_name'];
283
					} elseif ('parent_id' === $columnname) {
284
						$childContactsInfo[$columnname] = $row['parentid'];
285
					} else {
286
						$childContactsInfo[$columnname] = $row[$columnname];
287
					}
288
				}
289
				$childRow[$childId] = $childContactsInfo;
290
				$this->getChild($childId, $childRow[$childId], $depth);
291
			}
292
			$dataReader->close();
293
		}
294
		\App\Log::trace('Exiting getChild method ...');
295
296
		return $childRow;
297
	}
298
}
299