Users_Privileges_Model   F
last analyzed

Complexity

Total Complexity 97

Size/Duplication

Total Lines 409
Duplicated Lines 0 %

Test Coverage

Coverage 34.15%

Importance

Changes 0
Metric Value
wmc 97
eloc 195
dl 0
loc 409
ccs 70
cts 205
cp 0.3415
rs 2
c 0
b 0
f 0

18 Methods

Rating   Name   Duplication   Size   Complexity  
A hasGlobalReadPermission() 0 5 3
A getName() 0 13 3
A hasModulePermission() 0 5 5
A hasGlobalWritePermission() 0 3 2
A getGlobalWritePermission() 0 5 1
A hasGlobalPermission() 0 9 3
A getGlobalReadPermission() 0 5 1
B hasModuleActionPermission() 0 12 9
A clearLockEditCache() 0 6 4
D getParentRecord() 0 123 40
A clearCache() 0 7 2
A checkLockEdit() 0 23 6
A getInstanceById() 0 16 4
A getCurrentUserPrivilegesModel() 0 3 1
A isPermittedByUserId() 0 3 1
A getProfiles() 0 5 1
B setSharedOwner() 0 22 9
A getInstance() 0 9 2

How to fix   Complexity   

Complex Class

Complex classes like Users_Privileges_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 Users_Privileges_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.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
 * User Privileges Model Class.
14
 */
15
class Users_Privileges_Model extends Users_Record_Model
16
{
17
	/**
18
	 * Function to get the Display Name for the record.
19
	 *
20
	 * @return string - Entity Display Name for the record
21
	 */
22
	public function getName(): string
23
	{
24
		if (!isset($this->label)) {
25
			$entityData = \App\Module::getEntityInfo('Users');
26
			$separator = $entityData['separator'] ?? ' ';
27
			$labelName = [];
28
			foreach ($entityData['fieldnameArr'] as $columnName) {
29
				$fieldModel = $this->getModule()->getFieldByColumn($columnName);
30
				$labelName[] = $fieldModel->getDisplayValue($this->get($fieldModel->getName()), $this->getId(), $this, true);
31
			}
32
			$this->label = \App\Purifier::encodeHtml(implode($separator, $labelName));
33
		}
34
		return $this->label;
35
	}
36
37
	/**
38
	 * Function to get the Global Read Permission for the user.
39
	 *
40
	 * @return <Number> 0/1
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Number> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Number>.
Loading history...
41
	 */
42
	protected function getGlobalReadPermission()
43
	{
44
		$profileGlobalPermissions = $this->get('profile_global_permission');
45
46
		return $profileGlobalPermissions[Settings_Profiles_Module_Model::GLOBAL_ACTION_VIEW];
47
	}
48
49
	/**
50
	 * Function to get the Global Write Permission for the user.
51
	 *
52
	 * @return <Number> 0/1
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Number> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Number>.
Loading history...
53
	 */
54
	protected function getGlobalWritePermission()
55
	{
56
		$profileGlobalPermissions = $this->get('profile_global_permission');
57
58
		return $profileGlobalPermissions[Settings_Profiles_Module_Model::GLOBAL_ACTION_EDIT];
59
	}
60
61
	/**
62
	 * Function to check if the user has Global Read Permission.
63
	 *
64
	 * @return bool true/false
65
	 */
66
	public function hasGlobalReadPermission()
67
	{
68
		return $this->isAdminUser()
69
			|| Settings_Profiles_Module_Model::IS_PERMITTED_VALUE === $this->getGlobalReadPermission()
70
			|| Settings_Profiles_Module_Model::IS_PERMITTED_VALUE === $this->getGlobalWritePermission();
71
	}
72
73
	/**
74
	 * Function to check if the user has Global Write Permission.
75
	 *
76
	 * @return bool true/false
77
	 */
78
	public function hasGlobalWritePermission()
79
	{
80
		return $this->isAdminUser() || Settings_Profiles_Module_Model::IS_PERMITTED_VALUE === $this->getGlobalWritePermission();
81
	}
82
83
	public function hasGlobalPermission($actionId)
84
	{
85
		if (Settings_Profiles_Module_Model::GLOBAL_ACTION_VIEW == $actionId) {
86
			return $this->hasGlobalReadPermission();
87
		}
88
		if (Settings_Profiles_Module_Model::GLOBAL_ACTION_EDIT == $actionId) {
89
			return $this->hasGlobalWritePermission();
90
		}
91
		return false;
92
	}
93
94
	/**
95
	 * Function to check whether the user has access to a given module by tabid.
96
	 *
97
	 * @param int $mixed
98
	 *
99
	 * @return bool true/false
100
	 */
101
	public function hasModulePermission($mixed)
102
	{
103
		$profileTabsPermissions = $this->get('profile_tabs_permission');
104
		$moduleModel = Vtiger_Module_Model::getInstance($mixed);
105
		return !empty($moduleModel) && $moduleModel->isActive() && ($this->isAdminUser() || (isset($profileTabsPermissions[$moduleModel->getId()]) && 0 === $profileTabsPermissions[$moduleModel->getId()]));
106
	}
107
108
	/**
109
	 * Function to check whether the user has access to the specified action/operation on a given module by tabid.
110
	 *
111 3
	 * @param <Number>        $tabId
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Number> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Number>.
Loading history...
112
	 * @param <String/Number> $action
113 3
	 * @param mixed           $mixed
114 3
	 *
115
	 * @return bool true/false
116 3
	 */
117 3
	public function hasModuleActionPermission($mixed, $action)
118 3
	{
119
		if (!is_a($action, 'Vtiger_Action_Model')) {
120
			$action = Vtiger_Action_Model::getInstance($action);
121 3
		}
122 3
		$actionId = $action->getId();
123
		$profileTabsPermissions = $this->get('profile_action_permission');
124
		if ((is_numeric($mixed) && 3 === $mixed) || 'Home' === $mixed) {
125
			$mixed = 1;
126
		}
127
		$moduleModel = Vtiger_Module_Model::getInstance($mixed);
128
		return $moduleModel->isActive() && $this->hasModulePermission($mixed) && (($this->isAdminUser() || (isset($profileTabsPermissions[$moduleModel->getId()][$actionId]) && Settings_Profiles_Module_Model::IS_PERMITTED_VALUE === $profileTabsPermissions[$moduleModel->getId()][$actionId])));
129
	}
130
131
	/**
132 6
	 * Static Function to get the instance of the User Privileges model from the given list of key-value array.
133
	 *
134 6
	 * @param <Array> $valueMap
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...
135 6
	 *
136 6
	 * @return \Users_Privileges_Model object
137
	 */
138 6
	public static function getInstance($valueMap)
139
	{
140 6
		$instance = new self();
141
		foreach ($valueMap as $key => $value) {
142
			$instance->{$key} = $value;
143
		}
144
		$instance->setData($valueMap);
145
		$instance->setModule('Users');
146
		return $instance;
147
	}
148
149
	protected static $userPrivilegesModelCache = [];
150
151
	/**
152 16
	 * Static Function to get the instance of the User Privileges model, given the User id.
153
	 *
154 16
	 * @param <Number>   $userId
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Number> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Number>.
Loading history...
155
	 * @param mixed|null $module
156
	 *
157
	 * @return \Users_Privileges_Model object
158 16
	 */
159 12
	public static function getInstanceById($userId, $module = null)
160
	{
161 6
		if (empty($userId)) {
162 6
			return null;
163 6
		}
164
		if (isset(self::$userPrivilegesModelCache[$userId])) {
165 6
			return self::$userPrivilegesModelCache[$userId];
166 6
		}
167
		$valueMap = App\User::getPrivilegesFile($userId);
168 6
		if (\is_array($valueMap['user_info'])) {
169
			$valueMap = array_merge($valueMap, $valueMap['user_info']);
170
		}
171
		$instance = self::getInstance($valueMap);
172
		$instance->setId($userId);
173
		self::$userPrivilegesModelCache[$userId] = $instance;
174
		return $instance;
175
	}
176 14
177
	/**
178 14
	 * Static function to get the User Privileges Model for the current user.
179
	 *
180
	 * @return \Users_Privileges_Model object
181
	 */
182
	public static function getCurrentUserPrivilegesModel()
183 1
	{
184
		return self::getInstanceById(App\User::getCurrentUserId());
185 1
	}
186 1
187
	protected static $lockEditCache = [];
188
189 1
	public static function checkLockEdit($moduleName, Vtiger_Record_Model $recordModel)
190 1
	{
191
		$recordId = $recordModel->getId();
192
		if (isset(self::$lockEditCache[$moduleName . $recordId])) {
193
			return self::$lockEditCache[$moduleName . $recordId];
194
		}
195 1
		$return = false;
196 1
		if (empty($recordId)) {
197 1
			self::$lockEditCache[$moduleName . $recordId] = $return;
198 1
			return $return;
199
		}
200
		Vtiger_Loader::includeOnce('~~modules/com_vtiger_workflow/include.php');
201
		Vtiger_Loader::includeOnce('~~modules/com_vtiger_workflow/VTEntityMethodManager.php');
202
		$workflows = (new VTWorkflowManager())->getWorkflowsForModule($moduleName, VTWorkflowManager::$BLOCK_EDIT);
203
		if (\count($workflows)) {
204
			foreach ($workflows as &$workflow) {
205 1
				if ($workflow->evaluate($recordModel)) {
206
					$return = true;
207 1
				}
208
			}
209
		}
210
		self::$lockEditCache[$moduleName . $recordId] = $return;
211
		return $return;
212
	}
213
214
	/**
215
	 * Clear LockEdit Cache.
216
	 *
217
	 * @param string $cacheName
218
	 */
219
	public static function clearLockEditCache(string $cacheName = '')
220
	{
221
		if ($cacheName && isset(self::$lockEditCache[$cacheName])) {
222
			unset(self::$lockEditCache[$cacheName]);
223
		} elseif (!$cacheName) {
224
			self::$lockEditCache = [];
225
		}
226
	}
227
228
	/**
229 5778
	 * Clear user cache.
230
	 *
231 5778
	 * @param int|bool $userId
232 5778
	 */
233 5778
	public static function clearCache($userId = false)
234
	{
235
		self::$lockEditCache = [];
236
		if ($userId) {
237 5778
			unset(self::$userPrivilegesModelCache[$userId]);
238
		} else {
239
			self::$userPrivilegesModelCache = [];
240
		}
241
	}
242
243
	/**
244
	 * Function to set Shared Owner.
245 25
	 *
246
	 * @param int|array|string $userIds
247 25
	 * @param int              $record
248
	 */
249 25
	public static function setSharedOwner($userIds, $record)
250 25
	{
251
		$saveFull = true;
252
		$db = \App\Db::getInstance();
253 25
		if ('SaveAjax' == \App\Request::_get('action') && \App\Request::_has('field') && 'shownerid' != \App\Request::_get('field')) {
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

253
		if ('SaveAjax' == \App\Request::/** @scrutinizer ignore-call */ _get('action') && \App\Request::_has('field') && 'shownerid' != \App\Request::_get('field')) {
Loading history...
Bug introduced by
The method _has() 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

253
		if ('SaveAjax' == \App\Request::_get('action') && \App\Request::/** @scrutinizer ignore-call */ _has('field') && 'shownerid' != \App\Request::_get('field')) {
Loading history...
254 25
			$saveFull = false;
255 25
		}
256 25
		if ($saveFull) {
257
			$db->createCommand()->delete('u_#__crmentity_showners', ['crmid' => $record])->execute();
258
			if (empty($userIds)) {
259
				return false;
260
			}
261
			if (!\is_array($userIds) && $userIds) {
262
				$userIds = explode(',', $userIds);
263
			}
264
			foreach (array_unique($userIds) as $userId) {
265
				$db->createCommand()->insert('u_#__crmentity_showners', [
266
					'crmid' => $record,
267
					'userid' => $userId,
268
				])->execute();
269
			}
270
			\App\Cache::delete('SharedOwnerFieldValue', $record);
271
		}
272
	}
273
274
	public static function isPermittedByUserId($userId, $moduleName, $actionName = '', $record = false)
275
	{
276
		return \App\Privilege::isPermitted($moduleName, $actionName, $record, $userId);
277
	}
278
279
	/**
280
	 * Get parent record id.
281
	 *
282
	 * @param int         $record
283
	 * @param string|bool $moduleName
284
	 * @param int         $type
285
	 * @param type        $actionid
286
	 *
287
	 * @return int|bool
288
	 */
289
	public static function getParentRecord($record, $moduleName = false, $type = 1, $actionid = false)
290
	{
291
		$cacheKey = "$record,$moduleName,$type,$actionid";
292
		if (\App\Cache::staticHas('PrivilegesParentRecord', $cacheKey)) {
293
			return \App\Cache::staticGet('PrivilegesParentRecord', $cacheKey);
294
		}
295
		$userModel = App\User::getCurrentUserModel();
296
		$currentUserId = $userModel->getId();
297
		$currentUserGroups = (array) $userModel->get('groups');
298
		if (!$moduleName) {
299
			$recordMetaData = vtlib\Functions::getCRMRecordMetadata($record);
300
			$moduleName = $recordMetaData['setype'];
301
		}
302
		$parentRecord = false;
303
		if ($parentModule = \App\ModuleHierarchy::getModulesMap1M($moduleName)) {
304
			$parentModuleModel = Vtiger_Module_Model::getInstance($moduleName);
305
			$parentModelFields = $parentModuleModel->getFields();
306
307
			foreach ($parentModelFields as $fieldName => $fieldModel) {
308
				if ($fieldModel->isReferenceField() && \count(array_intersect($parentModule, $fieldModel->getReferenceList())) > 0) {
309
					$recordModel = Vtiger_Record_Model::getInstanceById($record);
310
					$value = $recordModel->get($fieldName);
311
					if (!empty($value) && \App\Record::isExists($value)) {
312
						$parentRecord = $value;
313
					}
314
				}
315
			}
316
			if ($parentRecord && 2 == $type) {
317
				$rparentRecord = self::getParentRecord($parentRecord, false, $type, $actionid);
318
				if ($rparentRecord) {
319
					$parentRecord = $rparentRecord;
320
				}
321
			}
322
			$parentRecord = $record != $parentRecord ? $parentRecord : false;
323
		} elseif (\in_array($moduleName, \App\ModuleHierarchy::getModulesMapMMBase())) {
324
			$role = $userModel->getRoleInstance();
325
			$dataReader = (new \App\Db\Query())->select(['relcrmid', 'crmid'])
326
				->from('vtiger_crmentityrel')
327
				->where(['or', ['crmid' => $record], ['relcrmid' => $record]])
328
				->createCommand()->query();
329
			while ($row = $dataReader->read()) {
330
				$id = $row['crmid'] == $record ? $row['relcrmid'] : $row['crmid'];
331
				$recordMetaData = vtlib\Functions::getCRMRecordMetadata($id);
332
				$permissionsRoleForRelatedField = $role->get('permissionsrelatedfield');
333 1
				$permissionsRelatedField = '' == $permissionsRoleForRelatedField ? [] : explode(',', $role->get('permissionsrelatedfield'));
334
				$relatedPermission = false;
335 1
				foreach ($permissionsRelatedField as $row) {
336 1
					if (!$relatedPermission) {
337
						switch ($row) {
338
							case 0:
339 1
								$relatedPermission = $recordMetaData['smownerid'] == $currentUserId || \in_array($recordMetaData['smownerid'], $currentUserGroups);
340 1
								break;
341 1
							case 1:
342 1
								$relatedPermission = \in_array($currentUserId, \App\Fields\SharedOwner::getById($id));
343 1
								break;
344 1
							case 2:
345
								$relatedPermission = \App\Privilege::isPermittedBySharing($recordMetaData['setype'], \App\Module::getModuleId($recordMetaData['setype']), $actionid, $id, $currentUserId);
346 1
								break;
347 1
							case 3:
348 1
								$relatedPermission = \App\Privilege::isPermitted($recordMetaData['setype'], 'DetailView', $id);
349 1
								break;
350
							default:
351 1
								break;
352 1
						}
353 1
					}
354 1
				}
355 1
				if ($relatedPermission) {
356
					$parentRecord = $id;
357
					break;
358
				}
359
				if (2 == $type) {
360 1
					$rparentRecord = self::getParentRecord($id, $recordMetaData['setype'], $type, $actionid);
361
					if ($rparentRecord) {
362
						$parentRecord = $rparentRecord;
363
					}
364
				}
365
			}
366 1
			$dataReader->close();
367
		} elseif ($relationInfo = \App\ModuleHierarchy::getModulesMapMMCustom($moduleName)) {
368
			$role = $userModel->getRoleInstance();
369
			$dataReader = (new \App\Db\Query())->select(['crmid' => $relationInfo['rel']])->from($relationInfo['table'])
370
				->where([$relationInfo['base'] => $record])
371
				->createCommand()->query();
372
			while ($id = $dataReader->readColumn(0)) {
373
				$recordMetaData = vtlib\Functions::getCRMRecordMetadata($id);
374
				$permissionsRelatedField = '' == $role->get('permissionsrelatedfield') ? [] : explode(',', $role->get('permissionsrelatedfield'));
375
				$relatedPermission = false;
376
				foreach ($permissionsRelatedField as $row) {
377
					if (!$relatedPermission) {
378
						switch ($row) {
379
							case 0:
380
								$relatedPermission = $recordMetaData['smownerid'] == $currentUserId || \in_array($recordMetaData['smownerid'], $currentUserGroups);
381
								break;
382
							case 1:
383
								$relatedPermission = \in_array($currentUserId, \App\Fields\SharedOwner::getById($id));
384
								break;
385
							case 2:
386
								$relatedPermission = \App\Privilege::isPermittedBySharing($recordMetaData['setype'], \App\Module::getModuleId($recordMetaData['setype']), $actionid, $id, $currentUserId);
387
								break;
388
							case 3:
389
								$relatedPermission = \App\Privilege::isPermitted($recordMetaData['setype'], 'DetailView', $id);
390
								break;
391
							default:
392
								break;
393
						}
394
					}
395
				}
396
				if ($relatedPermission) {
397
					$parentRecord = $id;
398
					break;
399
				}
400
				if (2 == $type) {
401
					$rparentRecord = self::getParentRecord($id, $recordMetaData['setype'], $type, $actionid);
402
					if ($rparentRecord) {
403
						$parentRecord = $rparentRecord;
404
					}
405
				}
406
			}
407
			$dataReader->close();
408
		}
409
		\App\Cache::staticSave('PrivilegesParentRecord', $cacheKey, $parentRecord);
410
411
		return $parentRecord;
412
	}
413
414
	/**
415
	 * Get profiles ids.
416
	 *
417
	 * @return array
418
	 */
419
	public function getProfiles()
420
	{
421
		\App\Log::trace('Get profile list');
422
423
		return $this->get('profiles');
424
	}
425
}
426