Completed
Push — developer ( b33bdc...d235c9 )
by Błażej
26:07 queued 12:56
created

PrivilegeUtil::getUserByMember()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 6.027

Importance

Changes 0
Metric Value
dl 0
loc 27
ccs 20
cts 22
cp 0.9091
rs 8.8657
c 0
b 0
f 0
cc 6
nc 6
nop 1
crap 6.027
1
<?php
2
3
namespace App;
4
5
/**
6
 * Privilege Util basic class.
7
 *
8
 * @copyright YetiForce Sp. z o.o
9
 * @license   YetiForce Public License 3.0 (licenses/LicenseEN.txt or yetiforce.com)
10
 * @author    Mariusz Krzaczkowski <[email protected]>
11
 */
12
class PrivilegeUtil
13
{
14
	/** Function to get parent record owner
15
	 * @param $tabid    -- tabid :: Type integer
16
	 * @param $parModId -- parent module id :: Type integer
17
	 * @param $recordId -- record id :: Type integer
18
	 * @returns $parentRecOwner -- parentRecOwner:: Type integer
19
	 */
20
	public static function getParentRecordOwner($tabid, $parModId, $recordId)
21
	{
22
		Log::trace("Entering getParentRecordOwner($tabid,$parModId,$recordId) method ...");
23
		$parentRecOwner = [];
24
		$parentTabName = Module::getModuleName($parModId);
25
		$relTabName = Module::getModuleName($tabid);
26
		$fnName = 'get' . $relTabName . 'Related' . $parentTabName;
27
		$entId = static::$fnName($recordId);
28
		if ($entId !== '') {
29
			$recordMetaData = \vtlib\Functions::getCRMRecordMetadata($entId);
30
			if ($recordMetaData) {
31
				$ownerId = $recordMetaData['smownerid'];
32
				$type = \App\Fields\Owner::getType($ownerId);
33
				$parentRecOwner[$type] = $ownerId;
34
			}
35
		}
36
		Log::trace('Exiting getParentRecordOwner method ...');
37
		return $parentRecOwner;
38
	}
39
40
	/**
41
	 * Function return related account with ticket.
42
	 *
43
	 * @param int $recordId
44
	 *
45
	 * @return int
46
	 */
47 1
	private static function getHelpDeskRelatedAccounts($recordId)
48
	{
49 1
		return (new Db\Query())->select(['parent_id'])->from('vtiger_troubletickets')
50 1
			->innerJoin('vtiger_crmentity', 'vtiger_troubletickets.parent_id = vtiger_crmentity.crmid')
51 1
			->where(['ticketid' => $recordId, 'vtiger_crmentity.setype' => 'Accounts'])->scalar();
52
	}
53
54
	protected static $datashareRelatedCache = false;
55
56
	/**
57
	 * Function to get data share related modules.
58
	 *
59
	 * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be array|boolean? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
60
	 */
61 2
	public static function getDatashareRelatedModules()
62
	{
63 2
		if (static::$datashareRelatedCache === false) {
64 1
			$relModSharArr = [];
65 1
			$dataReader = (new \App\Db\Query())->from('vtiger_datashare_relatedmodules')->createCommand()->query();
66 1
			while ($row = $dataReader->read()) {
67 1
				$relTabId = $row['relatedto_tabid'];
68 1
				if (isset($relModSharArr[$relTabId]) && is_array($relModSharArr[$relTabId])) {
69
					$temArr = $relModSharArr[$relTabId];
70
					$temArr[] = $row['tabid'];
71
				} else {
72 1
					$temArr = [];
73 1
					$temArr[] = $row['tabid'];
74
				}
75 1
				$relModSharArr[$relTabId] = $temArr;
76
			}
77 1
			static::$datashareRelatedCache = $relModSharArr;
78
		}
79 2
		return static::$datashareRelatedCache;
80
	}
81
82
	protected static $defaultSharingActionCache = false;
83
84
	/**
85
	 * This Function returns the Default Organisation Sharing Action Array for all modules.
86
	 *
87
	 * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be array|boolean? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
88
	 */
89 2
	public static function getAllDefaultSharingAction()
90
	{
91 2
		if (static::$defaultSharingActionCache === false) {
92 1
			Log::trace('getAllDefaultSharingAction');
93 1
			static::$defaultSharingActionCache = array_map('intval', (new \App\Db\Query())->select(['tabid', 'permission'])->from('vtiger_def_org_share')->createCommand()->queryAllByGroup(0));
94
		}
95 2
		return static::$defaultSharingActionCache;
96
	}
97
98
	/**
99
	 * Function to get the vtiger_role related user ids.
100
	 *
101
	 * @param int $roleId RoleId :: Type varchar
102
	 *
103
	 * @return array $users -- Role Related User Array in the following format:
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
104
	 */
105 3
	public static function getUsersByRole($roleId)
106
	{
107 3
		if (Cache::has('getUsersByRole', $roleId)) {
108
			return Cache::get('getUsersByRole', $roleId);
109
		}
110 3
		$users = (new \App\Db\Query())->select(['userid'])->from('vtiger_user2role')->where(['roleid' => $roleId])->column();
111 3
		$users = array_map('intval', $users);
112 3
		Cache::save('getUsersByRole', $roleId, $users);
113 3
		return $users;
114
	}
115
116
	/**
117
	 * Function to get the users names by role.
118
	 *
119
	 * @param int $roleId
120
	 *
121
	 * @return array $users
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
122
	 */
123 2
	public static function getUsersNameByRole($roleId)
124
	{
125 2
		if (Cache::has('getUsersNameByRole', $roleId)) {
126
			return Cache::get('getUsersNameByRole', $roleId);
127
		}
128 2
		$users = static::getUsersByRole($roleId);
129 2
		$roleRelatedUsers = [];
130 2
		if ($users) {
131 1
			foreach ($users as $userId) {
0 ignored issues
show
Bug introduced by
The expression $users of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
132 1
				$roleRelatedUsers[$userId] = Fields\Owner::getUserLabel($userId);
133
			}
134
		}
135 2
		Cache::save('getUsersNameByRole', $roleId, $roleRelatedUsers);
136 2
		return $users;
137
	}
138
139
	/**
140
	 * Function to get the role related user ids.
141
	 *
142
	 * @param int $userId RoleId :: Type varchar
143
	 */
144 2 View Code Duplication
	public static function getRoleByUsers($userId)
145
	{
146 2
		if (Cache::has('getRoleByUsers', $userId)) {
147 2
			return Cache::get('getRoleByUsers', $userId);
148
		}
149 2
		$roleId = (new \App\Db\Query())->select('roleid')
150 2
			->from('vtiger_user2role')->where(['userid' => $userId])
151 2
			->scalar();
152 2
		Cache::save('getRoleByUsers', $userId, $roleId);
153 2
		return $roleId;
154
	}
155
156
	/**
157
	 * Function to get user groups.
158
	 *
159
	 * @param int $userId
160
	 *
161
	 * @return array - groupId's
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
162
	 */
163 11 View Code Duplication
	public static function getUserGroups($userId)
164
	{
165 11
		if (Cache::has('UserGroups', $userId)) {
166 4
			return Cache::get('UserGroups', $userId);
167
		}
168 11
		$groupIds = (new \App\Db\Query())->select('groupid')->from('vtiger_users2group')->where(['userid' => $userId])->column();
169 11
		$groupIds = array_map('intval', $groupIds);
170 11
		Cache::save('UserGroups', $userId, $groupIds);
171 11
		return $groupIds;
172
	}
173
174
	/**
175
	 * This function is to retreive the vtiger_profiles associated with the  the specified role.
176
	 *
177
	 * @param string $roleId
178
	 *
179
	 * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
180
	 */
181 11 View Code Duplication
	public static function getProfilesByRole($roleId)
182
	{
183 11
		$profiles = Cache::staticGet('getProfilesByRole', $roleId);
184 11
		if ($profiles) {
185 8
			return $profiles;
186
		}
187 11
		$profiles = (new \App\Db\Query())
188 11
			->select('profileid')
189 11
			->from('vtiger_role2profile')
190 11
			->where(['roleid' => $roleId])
191 11
			->column();
192 11
		$profiles = array_map('intval', $profiles);
193 11
		Cache::staticSave('getProfilesByRole', $roleId, $profiles);
194 11
		return $profiles;
195
	}
196
197
	/**
198
	 *  This function is to retreive the vtiger_profiles associated with the  the specified user.
199
	 *
200
	 * @param int $userId
201
	 *
202
	 * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
203
	 */
204 2
	public static function getProfilesByUser($userId)
205
	{
206 2
		$roleId = static::getRoleByUsers($userId);
207
208 2
		return static::getProfilesByRole($roleId);
209
	}
210
211
	const MEMBER_TYPE_USERS = 'Users';
212
	const MEMBER_TYPE_GROUPS = 'Groups';
213
	const MEMBER_TYPE_ROLES = 'Roles';
214
	const MEMBER_TYPE_ROLE_AND_SUBORDINATES = 'RoleAndSubordinates';
215
216
	protected static $membersCache = false;
217
218
	/**
219
	 * Function to get all members.
220
	 *
221
	 * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be array|boolean? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
222
	 */
223
	public static function getMembers()
224
	{
225
		if (static::$membersCache === false) {
226
			$members = [];
227
			$owner = new \App\Fields\Owner();
228 View Code Duplication
			foreach ($owner->initUsers() as $id => $user) {
0 ignored issues
show
Bug introduced by
The expression $owner->initUsers() of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
229
				$members[static::MEMBER_TYPE_USERS][static::MEMBER_TYPE_USERS . ':' . $id] = ['name' => $user['fullName'], 'id' => $id, 'type' => static::MEMBER_TYPE_USERS];
230
			}
231 View Code Duplication
			foreach ($owner->getGroups(false) as $id => $groupName) {
0 ignored issues
show
Bug introduced by
The expression $owner->getGroups(false) of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
232
				$members[static::MEMBER_TYPE_GROUPS][static::MEMBER_TYPE_GROUPS . ':' . $id] = ['name' => $groupName, 'id' => $id, 'type' => static::MEMBER_TYPE_GROUPS];
233
			}
234
			foreach (\Settings_Roles_Record_Model::getAll() as $id => $roleModel) {
235
				$members[static::MEMBER_TYPE_ROLES][static::MEMBER_TYPE_ROLES . ':' . $id] = ['name' => $roleModel->getName(), 'id' => $id, 'type' => static::MEMBER_TYPE_ROLES];
236
				$members[static::MEMBER_TYPE_ROLE_AND_SUBORDINATES][static::MEMBER_TYPE_ROLE_AND_SUBORDINATES . ':' . $id] = ['name' => $roleModel->getName(), 'id' => $id, 'type' => static::MEMBER_TYPE_ROLE_AND_SUBORDINATES];
237
			}
238
			static::$membersCache = $members;
239
		}
240
		return static::$membersCache;
241
	}
242
243
	/**
244
	 * Get list of users based on members, eg. Users:2, Roles:H2.
245
	 *
246
	 * @param string $member
247
	 *
248
	 * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
249
	 */
250 1
	public static function getUserByMember($member)
251
	{
252 1
		if (Cache::has('getUserByMember', $member)) {
253
			return Cache::get('getUserByMember', $member);
254
		}
255 1
		list($type, $id) = explode(':', $member);
256 1
		$users = [];
257 1
		switch ($type) {
258 1
			case 'Users':
259 1
				$users[] = (int) $id;
260 1
				break;
261 1
			case 'Groups':
262 1
				$users = array_merge($users, static::getUsersByGroup($id));
263 1
				break;
264 1
			case 'Roles':
265 1
				$users = array_merge($users, static::getUsersByRole($id));
266 1
				break;
267 1
			case 'RoleAndSubordinates':
268 1
				$users = array_merge($users, static::getUsersByRoleAndSubordinate($id));
269 1
				break;
270
			default:
271
				break;
272
		}
273 1
		$users = array_unique($users);
274 1
		Cache::save('getUserByMember', $member, $users, Cache::LONG);
275 1
		return $users;
276
	}
277
278
	/**
279
	 * Get list of users based on group id.
280
	 *
281
	 * @param int        $groupId
282
	 * @param bool|array $subGroups
283
	 * @param int        $i
284
	 *
285
	 * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
286
	 */
287 1
	public static function getUsersByGroup($groupId, $subGroups = false, $i = 0)
288
	{
289 1
		$cacheKey = $groupId . ($subGroups === false ? '' : '#');
290 1
		if (Cache::has('getUsersByGroup', $cacheKey)) {
291
			return Cache::get('getUsersByGroup', $cacheKey);
292
		}
293
		//Retreiving from the user2grouptable
294 1
		$users = (new \App\Db\Query())->select(['userid'])->from('vtiger_users2group')->where(['groupid' => $groupId])->column();
295
		//Retreiving from the vtiger_group2role
296 1
		$dataReader = (new \App\Db\Query())->select(['roleid'])->from('vtiger_group2role')->where(['groupid' => $groupId])->createCommand()->query();
297 1 View Code Duplication
		while ($roleId = $dataReader->readColumn(0)) {
298 1
			$roleUsers = static::getUsersByRole($roleId);
299 1
			$users = array_merge($users, $roleUsers);
300
		}
301
		//Retreiving from the vtiger_group2rs
302 1
		$dataReader = (new \App\Db\Query())->select(['roleandsubid'])->from('vtiger_group2rs')->where(['groupid' => $groupId])->createCommand()->query();
303 1 View Code Duplication
		while ($roleId = $dataReader->readColumn(0)) {
304 1
			$roleUsers = static::getUsersByRoleAndSubordinate($roleId);
305 1
			$users = array_merge($users, $roleUsers);
306
		}
307 1
		if ($i < 10) {
308 1
			if ($subGroups === true) {
309
				$subGroups = [];
310
			}
311
			//Retreving from group2group
312 1
			$dataReader = (new \App\Db\Query())->select(['containsgroupid'])->from('vtiger_group2grouprel')->where(['groupid' => $groupId])->createCommand()->query();
313 1
			$containsGroups = [];
314 1
			while ($containsGroupId = $dataReader->readColumn(0)) {
315
				$roleUsers = static::getUsersByGroup($containsGroupId, $subGroups, $i++);
316
				if ($subGroups === false) {
317
					$containsGroups = array_merge($containsGroups, $roleUsers);
318
				} else {
319
					$containsGroups = array_merge($containsGroups, $roleUsers['users']);
320
					if (!isset($subGroups[$containsGroupId])) {
321
						$subGroups[$containsGroupId] = $containsGroups;
322
					}
323
					foreach ($roleUsers['subGroups'] as $key => $value) {
324
						if (!isset($subGroups[$key])) {
325
							$subGroups[$key] = $containsGroups;
326
						}
327
					}
328
				}
329
			}
330 1
			if ($containsGroups) {
331 1
				$users = array_merge($users, $containsGroups);
332
			}
333
		} else {
334
			Log::warning('Exceeded the recursive limit, a loop might have been created. Group ID:' . $groupId);
335
		}
336 1
		$users = array_unique($users);
337 1
		$return = ($subGroups === false ? $users : ['users' => $users, 'subGroups' => $subGroups]);
338 1
		Cache::save('getUsersByGroup', $cacheKey, $return, Cache::LONG);
339 1
		return $return;
340
	}
341
342
	/**
343
	 * Function to get the roles and subordinate users.
344
	 *
345
	 * @param int $roleId
346
	 *
347
	 * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
348
	 */
349 1
	public static function getUsersByRoleAndSubordinate($roleId)
350
	{
351 1
		if (Cache::has('getUsersByRoleAndSubordinate', $roleId)) {
352
			return Cache::get('getUsersByRoleAndSubordinate', $roleId);
353
		}
354 1
		$roleInfo = static::getRoleDetail($roleId);
355 1
		$parentRole = $roleInfo['parentrole'];
356 1
		$users = (new \App\Db\Query())->select(['vtiger_user2role.userid'])->from('vtiger_user2role')->innerJoin('vtiger_role', 'vtiger_user2role.roleid = vtiger_role.roleid')
357 1
			->where(['like', 'vtiger_role.parentrole', "$parentRole%", false])->column();
358 1
		$users = array_map('intval', $users);
359 1
		Cache::save('getUsersByRoleAndSubordinate', $roleId, $users, Cache::LONG);
360
361 1
		return $users;
362
	}
363
364
	/**
365
	 * Function to get the vtiger_role information of the specified vtiger_role.
366
	 *
367
	 * @param $roleId -- RoleId :: Type varchar
368
	 * @returns $roleInfoArray-- RoleInfoArray in the following format:
369
	 */
370 16
	public static function getRoleDetail($roleId)
371
	{
372 16
		if (Cache::has('RoleDetail', $roleId)) {
373 11
			return Cache::get('RoleDetail', $roleId);
374
		}
375 15
		$row = (new Db\Query())->from('vtiger_role')->where(['roleid' => $roleId])->one();
376 15
		if ($row) {
377 15
			$parentRoleArr = explode('::', $row['parentrole']);
378 15
			array_pop($parentRoleArr);
379 15
			$row['parentRoles'] = $parentRoleArr;
380 15
			$immediateParent = array_pop($parentRoleArr);
381 15
			$row['immediateParent'] = $immediateParent;
382
		}
383 15
		Cache::save('RoleDetail', $roleId, $row);
384 15
		return $row;
385
	}
386
387
	/**
388
	 * Function to get the role name.
389
	 *
390
	 * @param int $roleId
391
	 *
392
	 * @return string
393
	 */
394 4
	public static function getRoleName($roleId)
395
	{
396 4
		$roleInfo = static::getRoleDetail($roleId);
397 4
		return $roleInfo['rolename'];
398
	}
399
400
	/**
401
	 * To retreive the parent vtiger_role of the specified vtiger_role.
402
	 *
403
	 * @param $roleid -- The Role Id:: Type varchar
404
	 *
405
	 * @return parent vtiger_role array in the following format:
406
	 */
407 2
	public static function getParentRole($roleId)
408
	{
409 2
		$roleInfo = static::getRoleDetail($roleId);
410 2
		return $roleInfo['parentRoles'];
411
	}
412
413
	/**
414
	 * To retreive the subordinate vtiger_roles of the specified parent vtiger_role.
415
	 *
416
	 * @param int $roleId
417
	 *
418
	 * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
419
	 */
420 2
	public static function getRoleSubordinates($roleId)
421
	{
422 2
		if (Cache::has('getRoleSubordinates', $roleId)) {
423
			return Cache::get('getRoleSubordinates', $roleId);
424
		}
425 2
		$roleDetails = static::getRoleDetail($roleId);
426 2
		$roleSubordinates = (new \App\Db\Query())
427 2
			->select(['roleid'])
428 2
			->from('vtiger_role')
429 2
			->where(['like', 'parentrole', $roleDetails['parentrole'] . '::%', false])
430 2
			->column();
431 2
		Cache::save('getRoleSubordinates', $roleId, $roleSubordinates, Cache::LONG);
432 2
		return $roleSubordinates;
433
	}
434
435
	/**
436
	 * Function to get the Profile Tab Permissions for the specified vtiger_profileid.
437
	 *
438
	 * @param int $profileid
439
	 *
440
	 * @return int[]
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
441
	 */
442 1
	public static function getProfileTabsPermission($profileid)
443
	{
444 1
		Log::trace('Entering getProfileTabsPermission(' . $profileid . ') method ...');
445 1
		if (Cache::has('getProfileTabsPermission', $profileid)) {
446
			return Cache::get('getProfileTabsPermission', $profileid);
447
		}
448 1
		$profileData = (new Db\Query())->select(['tabid', 'permissions'])->from('vtiger_profile2tab')->where(['profileid' => $profileid])->createCommand()->queryAllByGroup(0);
449 1
		$profileData = array_map('intval', $profileData);
450 1
		Cache::save('getProfileTabsPermission', $profileid, $profileData);
451 1
		Log::trace('Exiting getProfileTabsPermission method ...');
452 1
		return $profileData;
453
	}
454
455
	/**
456
	 * Function to get the Profile Global Information for the specified vtiger_profileid.
457
	 *
458
	 * @param int $profileid
459
	 *
460
	 * @return int[]
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
461
	 */
462 1
	public static function getProfileGlobalPermission($profileid)
463
	{
464 1
		if (Cache::has('getProfileGlobalPermission', $profileid)) {
465
			return Cache::get('getProfileGlobalPermission', $profileid);
466
		}
467 1
		$profileData = (new Db\Query())->select(['globalactionid', 'globalactionpermission'])->from('vtiger_profile2globalpermissions')
468 1
			->where(['profileid' => $profileid])->createCommand()->queryAllByGroup(0);
469 1
		$profileData = array_map('intval', $profileData);
470 1
		Cache::save('getProfileGlobalPermission', $profileid, $profileData);
471 1
		return $profileData;
472
	}
473
474
	/**
475
	 * To retreive the global permission of the specifed user from the various vtiger_profiles associated with the user.
476
	 *
477
	 * @param int $userId
478
	 *
479
	 * @return int[]
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
480
	 */
481 2
	public static function getCombinedUserGlobalPermissions($userId)
482
	{
483 2
		if (Cache::staticHas('getCombinedUserGlobalPermissions', $userId)) {
484
			return Cache::staticGet('getCombinedUserGlobalPermissions', $userId);
485
		}
486 2
		$userGlobalPerrArr = [];
487 2
		$profArr = static::getProfilesByUser($userId);
488 2
		$profileId = array_shift($profArr);
489 2 View Code Duplication
		if ($profileId) {
490 1
			$userGlobalPerrArr = static::getProfileGlobalPermission($profileId);
491 1
			foreach ($profArr as $profileId) {
492
				$tempUserGlobalPerrArr = static::getProfileGlobalPermission($profileId);
493
				foreach ($userGlobalPerrArr as $globalActionId => $globalActionPermission) {
0 ignored issues
show
Bug introduced by
The expression $userGlobalPerrArr of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
494
					if ($globalActionPermission === 1) {
495
						$permission = $tempUserGlobalPerrArr[$globalActionId];
496
						if ($permission === 0) {
497
							$userGlobalPerrArr[$globalActionId] = $permission;
498
						}
499
					}
500
				}
501
			}
502
		}
503 2
		Cache::staticSave('getCombinedUserGlobalPermissions', $userId, $userGlobalPerrArr);
0 ignored issues
show
Bug introduced by
It seems like $userGlobalPerrArr can also be of type array; however, App\Cache::staticSave() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
504 2
		return $userGlobalPerrArr;
505
	}
506
507
	/**
508
	 * To retreive the vtiger_tab permissions of the specifed user from the various vtiger_profiles associated with the user.
509
	 *
510
	 * @param int $userId
511
	 *
512
	 * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
513
	 */
514 2
	public static function getCombinedUserModulesPermissions($userId)
515
	{
516 2
		if (Cache::staticHas('getCombinedUserModulesPermissions', $userId)) {
517
			return Cache::staticGet('getCombinedUserModulesPermissions', $userId);
518
		}
519 2
		$profArr = static::getProfilesByUser($userId);
520 2
		$profileId = array_shift($profArr);
521 2 View Code Duplication
		if ($profileId) {
522 1
			$userTabPerrArr = static::getProfileTabsPermission($profileId);
523 1
			foreach ($profArr as $profileId) {
524
				$tempUserTabPerrArr = static::getProfileTabsPermission($profileId);
525
				foreach ($userTabPerrArr as $tabId => $tabPermission) {
0 ignored issues
show
Bug introduced by
The expression $userTabPerrArr of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
526
					if ($tabPermission === 1) {
527
						$permission = $tempUserTabPerrArr[$tabId];
528
						if ($permission === 0) {
529
							$userTabPerrArr[$tabId] = $permission;
530
						}
531
					}
532
				}
533
			}
534
		}
535 2
		$homeTabid = Module::getModuleId('Home');
536 2
		if (!isset($userTabPerrArr[$homeTabid])) {
537 2
			$userTabPerrArr[$homeTabid] = 0;
538
		}
539 2
		Cache::staticSave('getCombinedUserModulesPermissions', $userId, $userTabPerrArr);
0 ignored issues
show
Bug introduced by
It seems like $userTabPerrArr defined by static::getProfileTabsPermission($profileId) on line 522 can also be of type array; however, App\Cache::staticSave() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
540 2
		return $userTabPerrArr;
541
	}
542
543
	/**
544
	 * Function to get all the vtiger_tab utility action permission for the specified vtiger_profile.
545
	 *
546
	 * @param int $profileid
547
	 *
548
	 * @return array
549
	 */
550 1 View Code Duplication
	public static function getUtilityPermissions($profileid)
551
	{
552 1
		$permissions = [];
553 1
		$dataReader = (new Db\Query())->from('vtiger_profile2utility')
554 1
			->where(['profileid' => $profileid])->createCommand()->query();
555 1
		while ($row = $dataReader->read()) {
556 1
			$permissions[$row['tabid']][$row['activityid']] = (int) $row['permission'];
557
		}
558 1
		return $permissions;
559
	}
560
561
	/**
562
	 * Function to get the Profile Action Permissions for the specified vtiger_profileid.
563
	 *
564
	 * @param int $profileid
565
	 *
566
	 * @return array
567
	 */
568 1 View Code Duplication
	public static function getStandardPermissions($profileid)
569
	{
570 1
		$permissions = [];
571 1
		$dataReader = (new Db\Query())->from('vtiger_profile2standardpermissions')
572 1
			->where(['profileid' => $profileid])->createCommand()->query();
573 1
		while ($row = $dataReader->read()) {
574 1
			$permissions[$row['tabid']][$row['operation']] = (int) $row['permissions'];
575
		}
576 1
		return $permissions;
577
	}
578
579
	/**
580
	 * Function to get the Standard and Utility Profile Action Permissions for the specified vtiger_profileid.
581
	 *
582
	 * @param int $profileid
583
	 *
584
	 * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
585
	 */
586 1
	public static function getAllProfilePermissions($profileid)
587
	{
588 1
		if (Cache::staticHas(__METHOD__, $profileid)) {
589
			return Cache::staticGet(__METHOD__, $profileid);
590
		}
591 1
		$allActions = static::getStandardPermissions($profileid);
592 1
		$utilityActions = static::getUtilityPermissions($profileid);
593 1
		foreach ($utilityActions as $tabid => $utilityAction) {
594 1
			$actionTabs = $allActions[$tabid] ?? [];
595 1
			foreach ($utilityAction as $utilityId => $utilityPermission) {
596 1
				$actionTabs[$utilityId] = (int) $utilityPermission;
597
			}
598 1
			$allActions[$tabid] = $actionTabs;
599
		}
600 1
		Cache::staticSave(__METHOD__, $profileid, $allActions);
601 1
		return $allActions;
602
	}
603
604
	/**
605
	 * To retreive the vtiger_tab acion permissions of the specifed user from the various vtiger_profiles associated with the user.
606
	 *
607
	 * @param int $userId
608
	 *
609
	 * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
610
	 */
611 2
	public static function getCombinedUserActionsPermissions($userId)
612
	{
613 2
		$profiles = static::getProfilesByUser($userId);
614 2
		$actionPermissions = [];
615 2
		if (isset($profiles[0])) {
616 1
			$actionPermissions = static::getAllProfilePermissions($profiles[0]);
617 1
			unset($profiles[0]);
618
		}
619 2
		if (is_array($profiles)) {
620 2
			foreach ($profiles as $profileId) {
621
				$tempActionPerrArr = static::getAllProfilePermissions($profileId);
622
				foreach ($actionPermissions as $tabId => $permissionsInModule) {
0 ignored issues
show
Bug introduced by
The expression $actionPermissions of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
623
					foreach ($permissionsInModule as $actionId => $permission) {
624
						if ($permission == 1) {
625
							$nowPermission = $tempActionPerrArr[$tabId][$actionId];
626
							if ($nowPermission == 0 && $nowPermission != '') {
627
								$actionPermissions[$tabId][$actionId] = $nowPermission;
628
							}
629
						}
630
					}
631
				}
632
			}
633
		}
634 2
		return $actionPermissions;
635
	}
636
637
	protected static $dataShareStructure = [
638
		'role2role' => ['vtiger_datashare_role2role', 'to_roleid'],
639
		'role2rs' => ['vtiger_datashare_role2rs', 'to_roleandsubid'],
640
		'role2group' => ['vtiger_datashare_role2group', 'to_groupid'],
641
		'role2user' => ['vtiger_datashare_role2us', 'to_userid'],
642
		'rs2role' => ['vtiger_datashare_rs2role', 'to_roleid'],
643
		'rs2rs' => ['vtiger_datashare_rs2rs', 'to_roleandsubid'],
644
		'rs2group' => ['vtiger_datashare_rs2grp', 'to_groupid'],
645
		'rs2user' => ['vtiger_datashare_rs2us', 'to_userid'],
646
		'group2role' => ['vtiger_datashare_grp2role', 'to_roleid'],
647
		'group2rs' => ['vtiger_datashare_grp2rs', 'to_roleandsubid'],
648
		'group2user' => ['vtiger_datashare_grp2us', 'to_userid'],
649
		'group2group' => ['vtiger_datashare_grp2grp', 'to_groupid'],
650
		'user2user' => ['vtiger_datashare_us2us', 'to_userid'],
651
		'user2group' => ['vtiger_datashare_us2grp', 'to_groupid'],
652
		'user2role' => ['vtiger_datashare_us2role', 'to_roleid'],
653
		'user2rs' => ['vtiger_datashare_us2rs', 'to_roleandsubid'],
654
	];
655
656
	/**
657
	 * Get data share.
658
	 *
659
	 * @param int $tabId
660
	 * @param int $roleId
661
	 *
662
	 * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
663
	 */
664 2
	public static function getDatashare($type, $tabId, $data)
665
	{
666 2
		$cacheKey = "$type|$tabId|" . (is_array($data) ? implode(',', $data) : $data);
667 2
		if (Cache::staticHas('getDatashare', $cacheKey)) {
668
			return Cache::staticGet('getDatashare', $cacheKey);
669
		}
670 2
		$structure = static::$dataShareStructure[$type];
671 2
		$query = (new \App\Db\Query())->select([$structure[0] . '.*'])->from($structure[0])
672 2
			->innerJoin('vtiger_datashare_module_rel', "$structure[0].shareid = vtiger_datashare_module_rel.shareid")
673 2
			->where(['vtiger_datashare_module_rel.tabid' => $tabId]);
674 2
		if ($data) {
675 2
			$query->andWhere([$structure[1] => $data]);
676
		}
677 2
		$rows = $query->all();
678 2
		Cache::staticSave('getDatashare', $cacheKey, $rows);
679 2
		return $rows;
680
	}
681
682
	/**
683
	 * Gives an array which contains the information for what all roles, groups and user data is to be shared with the spcified user for the specified module.
684
	 *
685
	 * @param string $module            module name
686
	 * @param int    $userid            user id
687
	 * @param array  $defOrgShare       default organization sharing permission array
688
	 * @param string $currentUserRoles  roleid
689
	 * @param string $parentRoles       parent roles
690
	 * @param int    $currentUserGroups user id
691
	 *
692
	 * @return array array which contains the id of roles,group and users data shared with specifed user for the specified module
693
	 */
694 2
	public static function getUserModuleSharingObjects($module, $userid, $defOrgShare, $currentUserRoles, $parentRoles, $currentUserGroups)
695
	{
696 2
		$modTabId = Module::getModuleId($module);
697 2
		$modShareWritePermission = $modShareReadPermission = ['ROLE' => [], 'GROUP' => []];
698 2
		$modDefOrgShare = null;
699 2
		if (isset($defOrgShare[$modTabId])) {
700 2
			$modDefOrgShare = $defOrgShare[$modTabId];
701
		}
702 2
		$shareIdMembers = [];
703
		//If Sharing of leads is Private
704 2
		if ($modDefOrgShare === 3 || $modDefOrgShare === 0) {
705 2
			$roleWritePer = $roleWritePer = $grpReadPer = $grpWritePer = $roleReadPer = [];
706
			//Retreiving from vtiger_role to vtiger_role
707 2
			foreach (static::getDatashare('role2role', $modTabId, $currentUserRoles) as $row) {
0 ignored issues
show
Bug introduced by
It seems like $modTabId defined by \App\Module::getModuleId($module) on line 696 can also be of type boolean; however, App\PrivilegeUtil::getDatashare() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
The expression static::getDatashare('ro...bId, $currentUserRoles) of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
708
				$shareRoleId = $row['share_roleid'];
709
				$shareIdRoles = [];
710
				$shareIdRoles[] = $shareRoleId;
711
				$shareIdMembers[$row['shareid']] = ['ROLE' => $shareIdRoles];
712
				if ((int) $row['permission'] === 1) {
713
					if ($modDefOrgShare === 3) {
714
						if (!isset($roleReadPer[$shareRoleId])) {
715
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
716
						}
717
					}
718
					if (!isset($roleWritePer[$shareRoleId])) {
719
						$roleWritePer[$shareRoleId] = static::getUsersByRole($shareRoleId);
720
					}
721
				} elseif ((int) $row['permission'] === 0 && $modDefOrgShare === 3) {
722
					if (!isset($roleReadPer[$shareRoleId])) {
723
						$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
724
					}
725
				}
726
			}
727
			//Retreiving from role to rs
728 2
			$parRoleList = [];
729 2
			if (is_array($parentRoles)) {
730 2
				foreach ($parentRoles as $par_role_id) {
731 1
					array_push($parRoleList, $par_role_id);
732
				}
733
			}
734 2
			array_push($parRoleList, $currentUserRoles);
735 2
			foreach (static::getDatashare('role2rs', $modTabId, $parRoleList) as $row) {
0 ignored issues
show
Bug introduced by
It seems like $modTabId defined by \App\Module::getModuleId($module) on line 696 can also be of type boolean; however, App\PrivilegeUtil::getDatashare() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
The expression static::getDatashare('ro...modTabId, $parRoleList) of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
736
				$shareRoleId = $row['share_roleid'];
737
				$shareIdRoles = [];
738
				$shareIdRoles[] = $shareRoleId;
739
				$shareIdMembers[$row['shareid']] = ['ROLE' => $shareIdRoles];
740
				if ((int) $row['permission'] === 1) {
741
					if ($modDefOrgShare === 3) {
742
						if (!isset($roleReadPer[$shareRoleId])) {
743
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
744
						}
745
					}
746
					if (!isset($roleWritePer[$shareRoleId])) {
747
						$roleWritePer[$shareRoleId] = static::getUsersByRole($shareRoleId);
748
					}
749
				} elseif ((int) $row['permission'] === 0 && $modDefOrgShare === 3) {
750
					if (!isset($roleReadPer[$shareRoleId])) {
751
						$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
752
					}
753
				}
754
			}
755
			//Get roles from Role2Grp
756 2
			$groupList = $currentUserGroups;
757 2
			if (empty($groupList)) {
758 1
				$groupList = [0];
759
			}
760 2 View Code Duplication
			if ($groupList) {
761 2
				foreach (static::getDatashare('role2group', $modTabId, $groupList) as $row) {
0 ignored issues
show
Bug introduced by
It seems like $modTabId defined by \App\Module::getModuleId($module) on line 696 can also be of type boolean; however, App\PrivilegeUtil::getDatashare() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
The expression static::getDatashare('ro... $modTabId, $groupList) of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
762
					$shareRoleId = $row['share_roleid'];
763
					$shareIdRoles = [];
764
					$shareIdRoles[] = $shareRoleId;
765
					$shareIdMembers[$row['shareid']] = ['ROLE' => $shareIdRoles];
766
					if ((int) $row['permission'] === 1) {
767
						if ($modDefOrgShare === 3) {
768
							if (!isset($roleReadPer[$shareRoleId])) {
769
								$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
770
							}
771
						}
772
						if (!isset($roleWritePer[$shareRoleId])) {
773
							$roleWritePer[$shareRoleId] = static::getUsersByRole($shareRoleId);
774
						}
775
					} elseif ((int) $row['permission'] === 0 && $modDefOrgShare === 3) {
776
						if (!isset($roleReadPer[$shareRoleId])) {
777
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
778
						}
779
					}
780
				}
781
			}
782
			//Get roles from Role2Us
783 2 View Code Duplication
			if (!empty($userid)) {
784 2
				foreach (static::getDatashare('role2user', $modTabId, $userid) as $row) {
0 ignored issues
show
Bug introduced by
It seems like $modTabId defined by \App\Module::getModuleId($module) on line 696 can also be of type boolean; however, App\PrivilegeUtil::getDatashare() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
The expression static::getDatashare('ro...r', $modTabId, $userid) of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
785
					$shareRoleId = $row['share_roleid'];
786
					$shareIdRoles = [];
787
					$shareIdRoles[] = $shareRoleId;
788
					$shareIdMembers[$row['shareid']] = ['ROLE' => $shareIdRoles];
789
					if ((int) $row['permission'] === 1) {
790
						if ($modDefOrgShare === 3) {
791
							if (!isset($roleReadPer[$shareRoleId])) {
792
								$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
793
							}
794
						}
795
						if (!isset($roleWritePer[$shareRoleId])) {
796
							$roleWritePer[$shareRoleId] = static::getUsersByRole($shareRoleId);
797
						}
798
					} elseif ((int) $row['permission'] === 0 && $modDefOrgShare === 3) {
799
						if (!isset($roleReadPer[$shareRoleId])) {
800
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
801
						}
802
					}
803
				}
804
			}
805
			//Retreiving from rs to vtiger_role
806 2
			foreach (static::getDatashare('rs2role', $modTabId, $currentUserRoles) as $row) {
0 ignored issues
show
Bug introduced by
It seems like $modTabId defined by \App\Module::getModuleId($module) on line 696 can also be of type boolean; however, App\PrivilegeUtil::getDatashare() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
The expression static::getDatashare('rs...bId, $currentUserRoles) of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
807
				$shareRoleIds = static::getRoleSubordinates($row['share_roleandsubid']);
808
				$shareRoleIds[] = $row['share_roleandsubid'];
809
				foreach ($shareRoleIds as $shareRoleId) {
0 ignored issues
show
Bug introduced by
The expression $shareRoleIds of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
810
					if ((int) $row['permission'] === 1) {
811
						if ($modDefOrgShare === 3) {
812
							if (!isset($roleReadPer[$shareRoleId])) {
813
								$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
814
							}
815
						}
816
						if (!isset($roleWritePer[$shareRoleId])) {
817
							$roleWritePer[$shareRoleId] = static::getUsersByRole($shareRoleId);
818
						}
819
					} elseif ((int) $row['permission'] === 0 && $modDefOrgShare === 3) {
820
						if (!isset($roleReadPer[$shareRoleId])) {
821
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
822
						}
823
					}
824
				}
825
				$shareIdMembers[$row['shareid']] = ['ROLE' => $shareRoleIds];
826
			}
827
			//Retreiving from rs to rs
828 2
			foreach (static::getDatashare('rs2rs', $modTabId, $parRoleList) as $row) {
0 ignored issues
show
Bug introduced by
It seems like $modTabId defined by \App\Module::getModuleId($module) on line 696 can also be of type boolean; however, App\PrivilegeUtil::getDatashare() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
The expression static::getDatashare('rs...modTabId, $parRoleList) of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
829
				$shareRoleIds = static::getRoleSubordinates($row['share_roleandsubid']);
830
				$shareRoleIds[] = $row['share_roleandsubid'];
831
				foreach ($shareRoleIds as $shareRoleId) {
0 ignored issues
show
Bug introduced by
The expression $shareRoleIds of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
832
					if ((int) $row['permission'] === 1) {
833
						if ($modDefOrgShare === 3) {
834
							if (!isset($roleReadPer[$shareRoleId])) {
835
								$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
836
							}
837
						}
838
						if (!isset($roleWritePer[$shareRoleId])) {
839
							$roleWritePer[$shareRoleId] = static::getUsersByRole($shareRoleId);
840
						}
841
					} elseif ((int) $row['permission'] === 0 && $modDefOrgShare === 3) {
842
						if (!isset($roleReadPer[$shareRoleId])) {
843
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
844
						}
845
					}
846
				}
847
				$shareIdMembers[$row['shareid']] = ['ROLE' => $shareRoleIds];
848
			}
849
			//Get roles from Rs2Grp
850 2
			foreach (static::getDatashare('rs2group', $modTabId, $groupList) as $row) {
0 ignored issues
show
Bug introduced by
It seems like $modTabId defined by \App\Module::getModuleId($module) on line 696 can also be of type boolean; however, App\PrivilegeUtil::getDatashare() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
The expression static::getDatashare('rs... $modTabId, $groupList) of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
851
				$shareRoleIds = static::getRoleSubordinates($row['share_roleandsubid']);
852
				$shareRoleIds[] = $row['share_roleandsubid'];
853
				foreach ($shareRoleIds as $shareRoleId) {
0 ignored issues
show
Bug introduced by
The expression $shareRoleIds of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
854
					if ((int) $row['permission'] === 1) {
855
						if ($modDefOrgShare === 3) {
856
							if (!isset($roleReadPer[$shareRoleId])) {
857
								$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
858
							}
859
						}
860
						if (!isset($roleWritePer[$shareRoleId])) {
861
							$roleWritePer[$shareRoleId] = static::getUsersByRole($shareRoleId);
862
						}
863
					} elseif ((int) $row['permission'] === 0 && $modDefOrgShare === 3) {
864
						if (!isset($roleReadPer[$shareRoleId])) {
865
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
866
						}
867
					}
868
				}
869
				$shareIdMembers[$row['shareid']] = ['ROLE' => $shareRoleIds];
870
			}
871
			//Get roles from Rs2Us
872 2
			foreach (static::getDatashare('rs2user', $modTabId, $userid) as $row) {
0 ignored issues
show
Bug introduced by
It seems like $modTabId defined by \App\Module::getModuleId($module) on line 696 can also be of type boolean; however, App\PrivilegeUtil::getDatashare() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
The expression static::getDatashare('rs...r', $modTabId, $userid) of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
873
				$shareRoleIds = static::getRoleSubordinates($row['share_roleandsubid']);
874
				$shareRoleIds[] = $row['share_roleandsubid'];
875
				foreach ($shareRoleIds as $shareRoleId) {
0 ignored issues
show
Bug introduced by
The expression $shareRoleIds of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
876
					if ((int) $row['permission'] === 1) {
877
						if ($modDefOrgShare === 3) {
878
							if (!isset($roleReadPer[$shareRoleId])) {
879
								$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
880
							}
881
						}
882
						if (!isset($roleWritePer[$shareRoleId])) {
883
							$roleWritePer[$shareRoleId] = static::getUsersByRole($shareRoleId);
884
						}
885
					} elseif ((int) $row['permission'] === 0 && $modDefOrgShare === 3) {
886
						if (!isset($roleReadPer[$shareRoleId])) {
887
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
888
						}
889
					}
890
				}
891
				$shareIdMembers[$row['shareid']] = ['ROLE' => $shareRoleIds];
892
			}
893 2
			$modShareReadPermission['ROLE'] = $roleReadPer;
894 2
			$modShareWritePermission['ROLE'] = $roleWritePer;
895
896
			//Retreiving from the grp2role sharing
897 2 View Code Duplication
			foreach (static::getDatashare('group2role', $modTabId, $currentUserRoles) as $row) {
0 ignored issues
show
Bug introduced by
It seems like $modTabId defined by \App\Module::getModuleId($module) on line 696 can also be of type boolean; however, App\PrivilegeUtil::getDatashare() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
The expression static::getDatashare('gr...bId, $currentUserRoles) of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
898
				$shareGrpId = (int) $row['share_groupid'];
899
				$shareIdGrps = [];
900
				$shareIdGrps[] = $shareGrpId;
901
				if ((int) $row['permission'] === 1) {
902
					if ($modDefOrgShare === 3) {
903
						if (!isset($grpReadPer[$shareGrpId])) {
904
							$usersByGroup = static::getUsersByGroup($shareGrpId, true);
905
							$grpReadPer[$shareGrpId] = $usersByGroup['users'];
906
							foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
907
								if (!isset($grpReadPer[$subgrpid])) {
908
									$grpReadPer[$subgrpid] = $subgrpusers;
909
								}
910
								if (!in_array($subgrpid, $shareIdGrps)) {
911
									$shareIdGrps[] = $subgrpid;
912
								}
913
							}
914
						}
915
					}
916
					if (!isset($grpWritePer[$shareGrpId])) {
917
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
918
						$grpWritePer[$shareGrpId] = $usersByGroup['users'];
919
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
920
							if (!isset($grpWritePer[$subgrpid])) {
921
								$grpWritePer[$subgrpid] = $subgrpusers;
922
							}
923
							if (!in_array($subgrpid, $shareIdGrps)) {
924
								$shareIdGrps[] = $subgrpid;
925
							}
926
						}
927
					}
928
				} elseif ((int) $row['permission'] === 0 && $modDefOrgShare === 3) {
929
					if (!isset($grpReadPer[$shareGrpId])) {
930
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
931
						$grpReadPer[$shareGrpId] = $usersByGroup['users'];
932
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
933
							if (!isset($grpReadPer[$subgrpid])) {
934
								$grpReadPer[$subgrpid] = $subgrpusers;
935
							}
936
							if (!in_array($subgrpid, $shareIdGrps)) {
937
								$shareIdGrps[] = $subgrpid;
938
							}
939
						}
940
					}
941
				}
942
				$shareIdMembers[$row['shareid']] = ['GROUP' => $shareIdGrps];
943
			}
944
			//Retreiving from the grp2rs sharing
945 2 View Code Duplication
			foreach (static::getDatashare('group2rs', $modTabId, $parRoleList) as $row) {
0 ignored issues
show
Bug introduced by
It seems like $modTabId defined by \App\Module::getModuleId($module) on line 696 can also be of type boolean; however, App\PrivilegeUtil::getDatashare() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
The expression static::getDatashare('gr...modTabId, $parRoleList) of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
946
				$shareGrpId = (int) $row['share_groupid'];
947
				$shareIdGrps = [];
948
				$shareIdGrps[] = $shareGrpId;
949
				if ((int) $row['permission'] === 1) {
950
					if ($modDefOrgShare === 3) {
951
						if (!isset($grpReadPer[$shareGrpId])) {
952
							$usersByGroup = static::getUsersByGroup($shareGrpId, true);
953
							$grpReadPer[$shareGrpId] = $usersByGroup['users'];
954
							foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
955
								if (!isset($grpReadPer[$subgrpid])) {
956
									$grpReadPer[$subgrpid] = $subgrpusers;
957
								}
958
								if (!in_array($subgrpid, $shareIdGrps)) {
959
									$shareIdGrps[] = $subgrpid;
960
								}
961
							}
962
						}
963
					}
964
					if (!isset($grpWritePer[$shareGrpId])) {
965
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
966
						$grpWritePer[$shareGrpId] = $usersByGroup['users'];
967
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
968
							if (!isset($grpWritePer[$subgrpid])) {
969
								$grpWritePer[$subgrpid] = $subgrpusers;
970
							}
971
							if (!in_array($subgrpid, $shareIdGrps)) {
972
								$shareIdGrps[] = $subgrpid;
973
							}
974
						}
975
					}
976
				} elseif ((int) $row['permission'] === 0 && $modDefOrgShare === 3) {
977
					if (!isset($grpReadPer[$shareGrpId])) {
978
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
979
						$grpReadPer[$shareGrpId] = $usersByGroup['users'];
980
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
981
							if (!isset($grpReadPer[$subgrpid])) {
982
								$grpReadPer[$subgrpid] = $subgrpusers;
983
							}
984
							if (!in_array($subgrpid, $shareIdGrps)) {
985
								$shareIdGrps[] = $subgrpid;
986
							}
987
						}
988
					}
989
				}
990
				$shareIdMembers[$row['shareid']] = ['GROUP' => $shareIdGrps];
991
			}
992
			//Retreiving from the grp2us sharing
993 2 View Code Duplication
			foreach (static::getDatashare('group2user', $modTabId, $userid) as $row) {
0 ignored issues
show
Bug introduced by
It seems like $modTabId defined by \App\Module::getModuleId($module) on line 696 can also be of type boolean; however, App\PrivilegeUtil::getDatashare() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
The expression static::getDatashare('gr...r', $modTabId, $userid) of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
994
				$shareGrpId = (int) $row['share_groupid'];
995
				$shareIdGrps = [];
996
				$shareIdGrps[] = $shareGrpId;
997
				if ((int) $row['permission'] === 1) {
998
					if ($modDefOrgShare === 3) {
999
						if (!isset($grpReadPer[$shareGrpId])) {
1000
							$usersByGroup = static::getUsersByGroup($shareGrpId, true);
1001
							$grpReadPer[$shareGrpId] = $usersByGroup['users'];
1002
							foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
1003
								if (!isset($grpReadPer[$subgrpid])) {
1004
									$grpReadPer[$subgrpid] = $subgrpusers;
1005
								}
1006
								if (!in_array($subgrpid, $shareIdGrps)) {
1007
									$shareIdGrps[] = $subgrpid;
1008
								}
1009
							}
1010
						}
1011
					}
1012
					if (!isset($grpWritePer[$shareGrpId])) {
1013
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
1014
						$grpWritePer[$shareGrpId] = $usersByGroup['users'];
1015
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
1016
							if (!isset($grpWritePer[$subgrpid])) {
1017
								$grpWritePer[$subgrpid] = $subgrpusers;
1018
							}
1019
							if (!in_array($subgrpid, $shareIdGrps)) {
1020
								$shareIdGrps[] = $subgrpid;
1021
							}
1022
						}
1023
					}
1024
				} elseif ((int) $row['permission'] === 0 && $modDefOrgShare === 3) {
1025
					if (!isset($grpReadPer[$shareGrpId])) {
1026
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
1027
						$grpReadPer[$shareGrpId] = $usersByGroup['users'];
1028
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
1029
							if (!isset($grpReadPer[$subgrpid])) {
1030
								$grpReadPer[$subgrpid] = $subgrpusers;
1031
							}
1032
							if (!in_array($subgrpid, $shareIdGrps)) {
1033
								$shareIdGrps[] = $subgrpid;
1034
							}
1035
						}
1036
					}
1037
				}
1038
				$shareIdMembers[$row['shareid']] = ['GROUP' => $shareIdGrps];
1039
			}
1040
			//Retreiving from the grp2grp sharing
1041 2 View Code Duplication
			foreach (static::getDatashare('group2group', $modTabId, $groupList) as $row) {
0 ignored issues
show
Bug introduced by
It seems like $modTabId defined by \App\Module::getModuleId($module) on line 696 can also be of type boolean; however, App\PrivilegeUtil::getDatashare() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
The expression static::getDatashare('gr... $modTabId, $groupList) of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
1042
				$shareGrpId = (int) $row['share_groupid'];
1043
				$shareIdGrps = [];
1044
				$shareIdGrps[] = $shareGrpId;
1045
				if ((int) $row['permission'] === 1) {
1046
					if ($modDefOrgShare === 3) {
1047
						if (!isset($grpReadPer[$shareGrpId])) {
1048
							$usersByGroup = static::getUsersByGroup($shareGrpId, true);
1049
							$grpReadPer[$shareGrpId] = $usersByGroup['users'];
1050
							foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
1051
								if (!isset($grpReadPer[$subgrpid])) {
1052
									$grpReadPer[$subgrpid] = $subgrpusers;
1053
								}
1054
								if (!in_array($subgrpid, $shareIdGrps)) {
1055
									$shareIdGrps[] = $subgrpid;
1056
								}
1057
							}
1058
						}
1059
					}
1060
					if (!isset($grpWritePer[$shareGrpId])) {
1061
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
1062
						$grpWritePer[$shareGrpId] = $usersByGroup['users'];
1063
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
1064
							if (!isset($grpWritePer[$subgrpid])) {
1065
								$grpWritePer[$subgrpid] = $subgrpusers;
1066
							}
1067
							if (!in_array($subgrpid, $shareIdGrps)) {
1068
								$shareIdGrps[] = $subgrpid;
1069
							}
1070
						}
1071
					}
1072
				} elseif ((int) $row['permission'] === 0 && $modDefOrgShare === 3) {
1073
					if (!isset($grpReadPer[$shareGrpId])) {
1074
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
1075
						$grpReadPer[$shareGrpId] = $usersByGroup['users'];
1076
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
1077
							if (!isset($grpReadPer[$subgrpid])) {
1078
								$grpReadPer[$subgrpid] = $subgrpusers;
1079
							}
1080
							if (!in_array($subgrpid, $shareIdGrps)) {
1081
								$shareIdGrps[] = $subgrpid;
1082
							}
1083
						}
1084
					}
1085
				}
1086
				$shareIdMembers[$row['shareid']] = ['GROUP' => $shareIdGrps];
1087
			}
1088
			//Get roles from Us2Us
1089 2 View Code Duplication
			foreach (static::getDatashare('user2user', $modTabId, $userid) as $row) {
0 ignored issues
show
Bug introduced by
It seems like $modTabId defined by \App\Module::getModuleId($module) on line 696 can also be of type boolean; however, App\PrivilegeUtil::getDatashare() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
The expression static::getDatashare('us...r', $modTabId, $userid) of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
1090
				$shareUserId = (int) $row['share_userid'];
1091
				$shareIdUsers = [];
1092
				$shareIdUsers[] = $shareUserId;
1093
				if ((int) $row['permission'] === 1) {
1094
					if ($modDefOrgShare === 3) {
1095
						if (!isset($grpReadPer[$shareUserId])) {
1096
							$grpReadPer[$shareUserId] = [$shareUserId];
1097
						}
1098
					}
1099
					if (!isset($grpWritePer[$shareUserId])) {
1100
						$grpWritePer[$shareUserId] = [$shareUserId];
1101
					}
1102
				} elseif ((int) $row['permission'] === 0 && $modDefOrgShare === 3) {
1103
					if (!isset($grpReadPer[$shareUserId])) {
1104
						$grpReadPer[$shareUserId] = [$shareUserId];
1105
					}
1106
				}
1107
				$shareIdMembers[$row['shareid']] = ['GROUP' => $shareIdUsers];
1108
			}
1109
			//Get roles from Us2Grp
1110 2 View Code Duplication
			foreach (static::getDatashare('user2group', $modTabId, $groupList) as $row) {
0 ignored issues
show
Bug introduced by
It seems like $modTabId defined by \App\Module::getModuleId($module) on line 696 can also be of type boolean; however, App\PrivilegeUtil::getDatashare() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
The expression static::getDatashare('us... $modTabId, $groupList) of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
1111
				$shareUserId = (int) $row['share_userid'];
1112
				$shareIdUsers = [];
1113
				$shareIdUsers[] = $shareUserId;
1114
				if ((int) $row['permission'] === 1) {
1115
					if ($modDefOrgShare === 3) {
1116
						if (!isset($grpReadPer[$shareUserId])) {
1117
							$grpReadPer[$shareUserId] = [$shareUserId];
1118
						}
1119
					}
1120
					if (!isset($grpWritePer[$shareUserId])) {
1121
						$grpWritePer[$shareUserId] = [$shareUserId];
1122
					}
1123
				} elseif ((int) $row['permission'] === 0 && $modDefOrgShare === 3) {
1124
					if (!isset($grpReadPer[$shareUserId])) {
1125
						$grpReadPer[$shareUserId] = [$shareUserId];
1126
					}
1127
				}
1128
				$shareIdMembers[$row['shareid']] = ['GROUP' => $shareIdUsers];
1129
			}
1130
			//Get roles from Us2role
1131 2 View Code Duplication
			foreach (static::getDatashare('user2role', $modTabId, $currentUserRoles) as $row) {
0 ignored issues
show
Bug introduced by
It seems like $modTabId defined by \App\Module::getModuleId($module) on line 696 can also be of type boolean; however, App\PrivilegeUtil::getDatashare() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
The expression static::getDatashare('us...bId, $currentUserRoles) of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
1132
				$shareUserId = (int) $row['share_userid'];
1133
				$shareIdUsers = [];
1134
				$shareIdUsers[] = $shareUserId;
1135
				if ((int) $row['permission'] === 1) {
1136
					if ($modDefOrgShare === 3) {
1137
						if (!isset($grpReadPer[$shareUserId])) {
1138
							$grpReadPer[$shareUserId] = [$shareUserId];
1139
						}
1140
					}
1141
					if (!isset($grpWritePer[$shareUserId])) {
1142
						$grpWritePer[$shareUserId] = [$shareUserId];
1143
					}
1144
				} elseif ((int) $row['permission'] === 0 && $modDefOrgShare === 3) {
1145
					if (!isset($grpReadPer[$shareUserId])) {
1146
						$grpReadPer[$shareUserId] = [$shareUserId];
1147
					}
1148
				}
1149
1150
				$shareIdMembers[$row['shareid']] = ['GROUP' => $shareIdUsers];
1151
			}
1152
			//Get roles from Us2rs
1153 2 View Code Duplication
			foreach (static::getDatashare('user2rs', $modTabId, $parRoleList) as $row) {
0 ignored issues
show
Bug introduced by
It seems like $modTabId defined by \App\Module::getModuleId($module) on line 696 can also be of type boolean; however, App\PrivilegeUtil::getDatashare() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
The expression static::getDatashare('us...modTabId, $parRoleList) of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
1154
				$shareUserId = (int) $row['share_userid'];
1155
				$shareIdUsers = [];
1156
				$shareIdUsers[] = $shareUserId;
1157
				if ((int) $row['permission'] === 1) {
1158
					if ($modDefOrgShare === 3) {
1159
						if (!isset($grpReadPer[$shareUserId])) {
1160
							$grpReadPer[$shareUserId] = [$shareUserId];
1161
						}
1162
					}
1163
					if (!isset($grpWritePer[$shareUserId])) {
1164
						$grpWritePer[$shareUserId] = [$shareUserId];
1165
					}
1166
				} elseif ((int) $row['permission'] === 0 && $modDefOrgShare === 3) {
1167
					if (!isset($grpReadPer[$shareUserId])) {
1168
						$grpReadPer[$shareUserId] = [$shareUserId];
1169
					}
1170
				}
1171
				$shareIdMembers[$row['shareid']] = ['GROUP' => $shareIdUsers];
1172
			}
1173 2
			$modShareReadPermission['GROUP'] = $grpReadPer;
1174 2
			$modShareWritePermission['GROUP'] = $grpWritePer;
1175
		}
1176
		return [
1177 2
			'read' => $modShareReadPermission,
1178 2
			'write' => $modShareWritePermission,
1179 2
			'sharingrules' => $shareIdMembers,
1180
		];
1181
	}
1182
1183
	/**
1184
	 * Get all groups by user id.
1185
	 *
1186
	 * @param int $userId
1187
	 *
1188
	 * @return int[]
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
1189
	 */
1190 2
	public static function getAllGroupsByUser($userId)
1191
	{
1192 2
		if (Cache::has('getAllGroupsByUser', $userId)) {
1193
			return Cache::get('getAllGroupsByUser', $userId);
1194
		}
1195 2
		$userGroups = static::getUserGroups($userId);
1196 2
		$userRole = static::getRoleByUsers($userId);
1197 2
		$roleGroups = (new \App\Db\Query())->select('groupid')->from('vtiger_group2role')->where(['roleid' => $userRole])->column();
1198 2
		$roles = static::getParentRole($userRole);
1199 2
		$roles[] = $userRole;
1200 2
		$rsGroups = (new \App\Db\Query())->select(['groupid'])->from('vtiger_group2rs')->where(['roleandsubid' => $roles])->column();
1201 2
		$allGroups = array_unique(array_merge($userGroups, $roleGroups, $rsGroups));
1202 2
		$parentGroups = [];
1203 2
		foreach ($allGroups as $groupId) {
1204 1
			$parentGroups = array_merge($parentGroups, static::getParentGroups($groupId));
1205
		}
1206 2
		if ($parentGroups) {
1207
			$allGroups = array_unique(array_merge($allGroups, $parentGroups));
1208
		}
1209 2
		Cache::save('getAllGroupsByUser', $userId, $allGroups, Cache::LONG);
1210
1211 2
		return $allGroups;
1212
	}
1213
1214
	/**
1215
	 * Get parent grioups by group id.
1216
	 *
1217
	 * @param int $groupId
1218
	 * @param int $i
1219
	 *
1220
	 * @return int[]
1221
	 */
1222 1
	public static function getParentGroups($groupId, $i = 0)
1223
	{
1224 1
		$groups = [];
1225 1
		if ($i < 10) {
1226 1
			$dataReader = (new \App\Db\Query())->select(['groupid'])->from('vtiger_group2grouprel')->where(['containsgroupid' => $groupId])->createCommand()->query();
1227 1
			while ($parentGroupId = $dataReader->readColumn(0)) {
1228
				$groups = array_merge($groups, [$parentGroupId], static::getParentGroups($parentGroupId, $i++));
1229
			}
1230
		} else {
1231
			Log::warning('Exceeded the recursive limit, a loop might have been created. Group ID:' . $groupId);
1232
		}
1233 1
		return $groups;
1234
	}
1235
1236
	/**
1237
	 * Tables to sharing rules.
1238
	 *
1239
	 * @var array
1240
	 */
1241
	private static $shareRulesTables = [
1242
		'US::GRP' => 'vtiger_datashare_us2grp',
1243
		'US::ROLE' => 'vtiger_datashare_us2role',
1244
		'US::RS' => 'vtiger_datashare_us2rs',
1245
		'US::US' => 'vtiger_datashare_us2us',
1246
		'GRP::GRP' => 'vtiger_datashare_grp2grp',
1247
		'GRP::ROLE' => 'vtiger_datashare_grp2role',
1248
		'GRP::RS' => 'vtiger_datashare_grp2rs',
1249
		'GRP::US' => 'vtiger_datashare_grp2us',
1250
		'ROLE::GRP' => 'vtiger_datashare_role2group',
1251
		'ROLE::ROLE' => 'vtiger_datashare_role2role',
1252
		'ROLE::RS' => 'vtiger_datashare_role2rs',
1253
		'ROLE::US' => 'vtiger_datashare_role2us',
1254
		'RS::GRP' => 'vtiger_datashare_rs2grp',
1255
		'RS::ROLE' => 'vtiger_datashare_rs2role',
1256
		'RS::RS' => 'vtiger_datashare_rs2rs',
1257
		'RS::US' => 'vtiger_datashare_rs2us',
1258
	];
1259
1260
	/**
1261
	 * List tables where sharing rules are save for users, groups and roles.
1262
	 *
1263
	 * @var array
1264
	 */
1265
	private static $shareRulesTablesIndex = [
1266
		'Users' => [
1267
			'vtiger_datashare_us2us' => 'share_userid::to_userid',
1268
			'vtiger_datashare_us2grp' => 'share_userid',
1269
			'vtiger_datashare_us2role' => 'share_userid',
1270
			'vtiger_datashare_us2rs' => 'share_userid',
1271
			'vtiger_datashare_grp2us' => 'to_userid',
1272
			'vtiger_datashare_rs2us' => 'to_userid',
1273
			'vtiger_datashare_role2us' => 'to_userid',
1274
		],
1275
		'Roles' => [
1276
			'vtiger_datashare_us2role' => 'to_roleid',
1277
			'vtiger_datashare_us2rs' => 'to_roleandsubid',
1278
			'vtiger_datashare_grp2role' => 'to_roleid',
1279
			'vtiger_datashare_grp2rs' => 'to_roleandsubid',
1280
			'vtiger_datashare_role2group' => 'share_roleid',
1281
			'vtiger_datashare_role2us' => 'share_roleid',
1282
			'vtiger_datashare_role2role' => 'share_roleid::to_roleid',
1283
			'vtiger_datashare_role2rs' => 'share_roleid::to_roleandsubid',
1284
			'vtiger_datashare_rs2grp' => 'share_roleandsubid',
1285
			'vtiger_datashare_rs2us' => 'share_roleandsubid',
1286
			'vtiger_datashare_rs2role' => 'share_roleandsubid::to_roleid',
1287
			'vtiger_datashare_rs2rs' => 'share_roleandsubid::to_roleandsubid',
1288
		],
1289
		'Groups' => [
1290
			'vtiger_datashare_grp2grp' => 'share_groupid::to_groupid',
1291
			'vtiger_datashare_grp2role' => 'share_groupid',
1292
			'vtiger_datashare_grp2rs' => 'share_groupid',
1293
			'vtiger_datashare_grp2us' => 'share_groupid',
1294
			'vtiger_datashare_role2group' => 'to_groupid',
1295
			'vtiger_datashare_rs2grp' => 'to_groupid',
1296
			'vtiger_datashare_us2grp' => 'to_groupid',
1297
		],
1298
	];
1299
1300
	/**
1301
	 * This function is to delete the organisation level sharing rule
1302
	 * It takes the following input parameters:.
1303
	 *
1304
	 * @param int $shareid Id of the Sharing Rule to be updated
1305
	 */
1306
	private static function deleteSharingRule($shareid)
1307
	{
1308
		Log::trace('Entering deleteSharingRule(' . $shareid . ') method ...');
1309
		$dbCommand = Db::getInstance()->createCommand();
1310
		$typestr = (new Db\Query())->select(['relationtype'])->from('vtiger_datashare_module_rel')->where(['shareid' => $shareid])->scalar();
1311
		$dbCommand->delete(static::$shareRulesTables[$typestr], ['shareid' => $shareid])->execute();
0 ignored issues
show
Bug introduced by
Since $shareRulesTables is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $shareRulesTables to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
1312
		$dbCommand->delete('vtiger_datashare_module_rel', ['shareid' => $shareid])->execute();
1313
		$dbCommand->delete('vtiger_datashare_relatedmodule_permission', ['shareid' => $shareid])->execute();
1314
		Log::trace('Exiting deleteSharingRule method ...');
1315
	}
1316
1317
	/**
1318
	 * Function to remove sharing rules from tables.
1319
	 *
1320
	 * @param int|string $id
1321
	 * @param string     $type
1322
	 */
1323 3
	public static function deleteRelatedSharingRules($id, $type)
1324
	{
1325 3
		Log::trace('Entering deleteRelatedSharingRules(' . $id . ') method ...');
1326 3
		foreach (static::$shareRulesTablesIndex[$type] as $tablename => $colname) {
0 ignored issues
show
Bug introduced by
Since $shareRulesTablesIndex is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $shareRulesTablesIndex to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
1327 3
			$colNameArr = explode('::', $colname);
1328 3
			$query = (new Db\Query())->select('shareid')
1329 3
				->from($tablename)
1330 3
				->where([$colNameArr[0] => $id]);
1331 3
			if (isset($colNameArr[1])) {
1332 3
				$query->orWhere([$colNameArr[1] => $id]);
1333
			}
1334 3
			$dataReader = $query->createCommand()->query();
1335 3
			while ($shareid = $dataReader->readColumn(0)) {
1336
				static::deleteSharingRule($shareid);
0 ignored issues
show
Bug introduced by
Since deleteSharingRule() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of deleteSharingRule() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
1337
			}
1338 3
			$dataReader->close();
1339
		}
1340 3
		Log::trace('Exiting deleteRelatedSharingRules method ...');
1341 3
	}
1342
1343
	/**
1344
	 * Function for test to check privilege utils.
1345
	 *
1346
	 * @param int $recordId
1347
	 */
1348 1
	public static function testPrivileges($recordId)
1349
	{
1350 1
		static::getHelpDeskRelatedAccounts($recordId);
0 ignored issues
show
Bug introduced by
Since getHelpDeskRelatedAccounts() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of getHelpDeskRelatedAccounts() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
1351 1
		return true;
1352
	}
1353
1354
	/**
1355
	 * Recalculate sharing rules by user id.
1356
	 *
1357
	 * @param int $id
1358
	 */
1359 1
	public static function recalculateSharingRulesByUser($id)
1360
	{
1361 1
		$userModel = \App\User::getUserModel($id);
1362 1
		$roles = explode('::', $userModel->getParentRolesSeq());
1363 1
		$groups = $userModel->getGroups();
1364 1
		$sharing = [];
1365 1 View Code Duplication
		foreach (\Settings_SharingAccess_Rule_Model::$dataShareTableColArr['ROLE'] as $key => $item) {
1366 1
			$row = (new \App\Db\Query())->select([$item['target_id']])->from($item['table'])->where([$item['source_id'] => $roles])->column();
1367 1
			if ($row) {
1368
				if (!isset($sharing[$key])) {
1369
					$sharing[$key] = [];
1370
				}
1371 1
				$sharing[$key] = array_merge($sharing[$key], $row);
1372
			}
1373
		}
1374 1 View Code Duplication
		foreach (\Settings_SharingAccess_Rule_Model::$dataShareTableColArr['RS'] as $key => $item) {
1375 1
			$row = (new \App\Db\Query())->select([$item['target_id']])->from($item['table'])->where([$item['source_id'] => $roles])->column();
1376 1
			if ($row) {
1377
				if (!isset($sharing[$key])) {
1378
					$sharing[$key] = [];
1379
				}
1380 1
				$sharing[$key] = array_merge($sharing[$key], $row);
1381
			}
1382
		}
1383 1
		if ($groups) {
1384 View Code Duplication
			foreach (\Settings_SharingAccess_Rule_Model::$dataShareTableColArr['GRP'] as $key => $item) {
1385
				$row = (new \App\Db\Query())->select([$item['target_id']])->from($item['table'])->where([$item['source_id'] => $groups])->column();
1386
				if ($row) {
1387
					if (!isset($sharing[$key])) {
1388
						$sharing[$key] = [];
1389
					}
1390
					$sharing[$key] = array_merge($sharing[$key], $row);
1391
				}
1392
			}
1393
		}
1394 1
		$users = [[]];
1395 1
		foreach ($sharing as $type => $item) {
1396
			switch ($type) {
1397
				case 'US':
1398
					$users[] = array_unique($item);
1399
					break;
1400
				case 'GRP':
1401
					foreach ($item as $grpId) {
1402
						$users[] = static::getUsersByGroup($grpId);
1403
					}
1404
					break;
1405
				case 'ROLE':
1406
					foreach ($item as $roleId) {
1407
						$users[] = static::getUsersByRole($roleId);
1408
					}
1409
					break;
1410
				case 'RS':
1411
					foreach ($item as $roleId) {
1412
						$users[] = static::getUsersByRoleAndSubordinate($roleId);
1413
					}
1414
					break;
1415
				default:
1416
					break;
1417
			}
1418
		}
1419 1
		foreach (array_unique(array_merge(...$users)) as $userId) {
1420
			UserPrivilegesFile::createUserSharingPrivilegesfile($userId);
1421
		}
1422 1
	}
1423
}
1424