Issues (3882)

Security Analysis    39 potential vulnerabilities

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting (9)
Response Splitting can be used to send arbitrary responses.
  File Manipulation (2)
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure (7)
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection (13)
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting (8)
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

app/CustomView.php (14 issues)

1
<?php
2
/**
3
 * Custom view file.
4
 *
5
 * @package App
6
 *
7
 * @copyright YetiForce S.A.
8
 * @license   YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com)
9
 * @author    Mariusz Krzaczkowski <[email protected]>
10
 * @author    RadosÅ‚aw Skrzypczak <[email protected]>
11
 */
12
13
namespace App;
14
15
/**
16
 * Custom view class.
17
 */
18
class CustomView
19
{
20
	const CV_STATUS_DEFAULT = 0;
21
	const CV_STATUS_PRIVATE = 1;
22
	const CV_STATUS_PENDING = 2;
23
	const CV_STATUS_PUBLIC = 3;
24
	const CV_STATUS_SYSTEM = 4;
25
26
	/**
27 3
	 * Do we have multiple ids.
28
	 *
29 3
	 * @param string $cvId (comma separated id list or one id)
30
	 *
31
	 * @return bool
32
	 */
33
	public static function isMultiViewId($cvId)
34
	{
35
		return false !== strpos($cvId, ',');
36
	}
37
38
	/**
39
	 * Function to get all the date filter type informations.
40
	 *
41
	 * @return array
42
	 */
43
	public static function getDateFilterTypes()
44
	{
45
		$dateFilters = Condition::DATE_OPERATORS;
46
		foreach (array_keys($dateFilters) as $filterType) {
47
			$dateValues = \DateTimeRange::getDateRangeByType($filterType);
48
			$dateFilters[$filterType]['startdate'] = $dateValues[0];
49
			$dateFilters[$filterType]['enddate'] = $dateValues[1];
50
		}
51
		return $dateFilters;
52
	}
53
54
	/**
55
	 * Get current page.
56
	 *
57
	 * @param string     $moduleName
58
	 * @param int|string $viewId
59
	 *
60
	 * @return int
61
	 */
62
	public static function getCurrentPage($moduleName, $viewId)
63
	{
64
		if (!empty($_SESSION['lvs'][$moduleName][$viewId]['start'])) {
65
			return $_SESSION['lvs'][$moduleName][$viewId]['start'];
66
		}
67
		return 1;
68
	}
69
70
	/**
71
	 * Set current page.
72
	 *
73
	 * @param string     $moduleName
74
	 * @param int|string $viewId
75
	 * @param int        $start
76
	 */
77
	public static function setCurrentPage($moduleName, $viewId, $start)
78
	{
79
		if (empty($start)) {
80
			unset($_SESSION['lvs'][$moduleName][$viewId]['start']);
81
		} else {
82
			$_SESSION['lvs'][$moduleName][$viewId]['start'] = $start;
83
		}
84
	}
85
86
	/**
87
	 * Function that sets the module filter in session.
88
	 *
89
	 * @param string     $moduleName - module name
90
	 * @param int|string $viewId     - filter id
91
	 */
92
	public static function setCurrentView($moduleName, $viewId)
93
	{
94
		$_SESSION['lvs'][$moduleName]['viewname'] = $viewId;
95
	}
96
97
	/**
98 1
	 * Function that reads current module filter.
99
	 *
100 1
	 * @param string $moduleName - module name
101
	 *
102
	 * @return int|string
103 1
	 */
104
	public static function getCurrentView($moduleName)
105
	{
106
		return $_SESSION['lvs'][$moduleName]['viewname'] ?? null;
107
	}
108
109
	/**
110
	 * Get sorted by.
111
	 *
112
	 * @param string $moduleName
113
	 *
114
	 * @return string
115
	 */
116
	public static function getSortBy($moduleName)
117
	{
118
		return empty($_SESSION['lvs'][$moduleName]['sortby']) ? [] : $_SESSION['lvs'][$moduleName]['sortby'];
0 ignored issues
show
Bug Best Practice introduced by
The expression return empty($_SESSION['...[$moduleName]['sortby'] also could return the type array which is incompatible with the documented return type string.
Loading history...
119
	}
120
121
	/**
122
	 * Set sorted by.
123
	 *
124
	 * @param string $moduleName
125
	 * @param mixed  $sortBy
126
	 */
127
	public static function setSortBy(string $moduleName, $sortBy)
128
	{
129
		if (empty($sortBy)) {
130
			unset($_SESSION['lvs'][$moduleName]['sortby']);
131
		} else {
132
			$_SESSION['lvs'][$moduleName]['sortby'] = $sortBy;
133
		}
134
	}
135
136
	/**
137
	 * Has view changed.
138
	 *
139
	 * @param string     $moduleName
140
	 * @param int|string $viewId
141
	 *
142
	 * @return bool
143
	 */
144
	public static function hasViewChanged(string $moduleName, $viewId = false): bool
145
	{
146
		return empty($_SESSION['lvs'][$moduleName]['viewname'])
147
		|| ($viewId && ($viewId !== $_SESSION['lvs'][$moduleName]['viewname']))
148
		|| !isset($_SESSION['lvs'][$moduleName]['sortby']);
149
	}
150
151
	/**
152
	 * Static Function to get the Instance of CustomView.
153
	 *
154
	 * @param string $moduleName
155
	 * @param mixed  $userModelOrId
156
	 *
157
	 * @return \self
0 ignored issues
show
The type self was not found. Maybe you did not declare it correctly or list all dependencies?

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

filter:
    dependency_paths: ["lib/*"]

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

Loading history...
158
	 */
159
	public static function getInstance($moduleName, $userModelOrId = false)
160
	{
161
		if (!$userModelOrId) {
162
			$userModelOrId = User::getCurrentUserId();
163
		}
164
		if (is_numeric($userModelOrId)) {
165
			$userModel = User::getUserModel($userModelOrId);
166
		} else {
167
			$userModel = $userModelOrId;
168
		}
169
		$cacheName = $moduleName . '.' . $userModel->getId();
170
		if (\App\Cache::staticHas('AppCustomView', $cacheName)) {
171
			return \App\Cache::staticGet('AppCustomView', $cacheName);
172
		}
173
		$instance = new self();
174
		$instance->moduleName = $moduleName;
175
		$instance->user = $userModel;
176
		\App\Cache::staticSave('AppCustomView', $cacheName, $instance);
177
178
		return $instance;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $instance returns the type App\CustomView which is incompatible with the documented return type self.
Loading history...
179
	}
180
181
	/** @var \Vtiger_Module_Model */
182
	private $module;
183
	private $moduleName;
184
	private $user;
185
	private $defaultViewId;
186
187
	/**
188
	 * Gets module object.
189
	 *
190
	 * @return false|\Vtiger_Module_Model
191
	 */
192
	public function getModule()
193
	{
194
		if (!$this->module) {
195
			$this->module = \Vtiger_Module_Model::getInstance($this->moduleName);
196
		}
197
		return $this->module;
198
	}
199
200
	/**
201
	 * Get custom view from file.
202
	 *
203
	 * @param string $cvId
204
	 *
205
	 * @throws Exceptions\AppException
206
	 */
207
	private function getCustomViewFromFile($cvId)
208
	{
209 3
		\App\Log::trace(__METHOD__ . ' - ' . $cvId);
210
		$handlerClass = \Vtiger_Loader::getComponentClassName('Filter', $cvId, $this->moduleName);
211 3
		$filter = new $handlerClass();
212 2
		Cache::staticSave('getCustomView', $cvId, $filter);
213
		return $filter;
214 3
	}
215 2
216
	/**
217 3
	 * Get custom view from file.
218
	 *
219 3
	 * @param string $cvIds (comma separated multi cdIds)
220 3
	 *
221 3
	 * @throws Exceptions\AppException
222
	 */
223 3
	public function getCustomView($cvIds)
224 3
	{
225 3
		\App\Log::trace(__METHOD__ . ' - ' . $cvIds);
226 3
		if (Cache::staticHas('getCustomView', $cvIds)) {
227
			return Cache::staticGet('getCustomView', $cvIds);
228 3
		}
229
		if (empty($cvIds) || !static::isMultiViewId($cvIds)) {
230
			return $this->getCustomViewFromFile($cvIds);
231
		}
232
		$filters = [];
233
		foreach (explode(',', $cvIds) as $cvId) {
234
			$filters[] = $this->getCustomViewFromFile($cvId);
235
		}
236
		Cache::staticSave('getCustomView', $cvIds, $filters);
237
		return $filters;
238
	}
239
240
	/**
241
	 * Columns list by cvid.
242
	 *
243
	 * @param mixed $cvId
244
	 *
245
	 * @throws Exceptions\AppException
246
	 *
247
	 * @return array
248
	 */
249
	private function getColumnsByCvidFromDb($cvId)
250
	{
251
		\App\Log::trace(__METHOD__ . ' - ' . $cvId);
252
		$columnList = [];
253
		if (is_numeric($cvId)) {
254
			$dataReader = (new Db\Query())->select(['field_name', 'module_name', 'source_field_name', 'label'])
255
				->from('vtiger_cvcolumnlist')
256
				->innerJoin('vtiger_tab', 'vtiger_tab.name=vtiger_cvcolumnlist.module_name')
257
				->innerJoin('vtiger_field', 'vtiger_tab.tabid = vtiger_field.tabid AND vtiger_field.fieldname = vtiger_cvcolumnlist.field_name')
258
				->where(['cvid' => $cvId, 'vtiger_field.presence' => [0, 2]])->orderBy('columnindex')->createCommand()->query();
259
			while ($row = $dataReader->read()) {
260
				if (!empty($row['source_field_name']) && !$this->getModule()->getFieldByName($row['source_field_name'])->isActiveField()) {
261
					continue;
262
				}
263
				$columnList[] = $row;
264
			}
265
			$dataReader->close();
266
			if ($columnList) {
267
				Cache::save('getColumnsListByCvid', $cvId, $columnList);
268
			}
269
		} else {
270
			$view = $this->getCustomViewFromFile($cvId);
271
			$columnList = $view->getColumnList();
272
			Cache::save('getColumnsListByCvid', $cvId, $columnList);
273
		}
274
		return $columnList;
275
	}
276
277
	/**
278
	 * Columns list by cvid.
279
	 *
280
	 * @param mixed $cvIds (comma separated)
281
	 *
282
	 * @throws Exceptions\AppException
283
	 *
284
	 * @return array
285
	 */
286
	public function getColumnsListByCvid($cvIds)
287 3
	{
288
		\App\Log::trace(__METHOD__ . ' - ' . $cvIds);
289 3
		if (Cache::has('getColumnsListByCvid', $cvIds)) {
290 3
			return Cache::get('getColumnsListByCvid', $cvIds);
291 3
		}
292 3
		if (empty($cvIds) || !static::isMultiViewId($cvIds)) {
293 3
			return $this->getColumnsByCvidFromDb($cvIds);
294 3
		}
295
		$columnLists = [];
296
		foreach (explode(',', $cvIds) as $cvId) {
297
			$columnLists[] = $this->getColumnsByCvidFromDb($cvId);
298
		}
299
		Cache::save('getColumnsListByCvid', $cvIds, $columnLists);
300
		return $columnLists;
301 3
	}
302
303
	/**
304
	 * Returns conditions for filter.
305
	 *
306
	 * @param int|string $id
307
	 *
308
	 * @return array
309
	 *               [
310
	 *               'condition' => "AND" or "OR"
311
	 *               'rules' => [[
312
	 *               'fieldname' => name of fields
313 3
	 *               'operator' => operator, for instance: 'e'
314
	 *               'value' => values
315 3
	 *               ]]
316 3
	 *               ]
317 1
	 */
318
	public static function getConditions($id): array
319 3
	{
320 3
		if (Cache::has('CustomView_GetConditions', $id)) {
321
			return Cache::get('CustomView_GetConditions', $id);
322
		}
323
		$dataReader = (new \App\Db\Query())->select([
324
			'u_#__cv_condition.group_id',
325
			'u_#__cv_condition.field_name',
326
			'u_#__cv_condition.module_name',
327
			'u_#__cv_condition.source_field_name',
328
			'u_#__cv_condition.operator',
329
			'u_#__cv_condition.value',
330
			'condition_index' => 'u_#__cv_condition.index',
331
			'u_#__cv_condition_group.id',
332
			'u_#__cv_condition_group.condition',
333
			'u_#__cv_condition_group.parent_id',
334
			'group_index' => 'u_#__cv_condition_group.index',
335
		])->from('u_#__cv_condition_group')
336
			->leftJoin('u_#__cv_condition', 'u_#__cv_condition.group_id = u_#__cv_condition_group.id')
337
			->where(['u_#__cv_condition_group.cvid' => $id])
338
			->orderBy(['u_#__cv_condition_group.parent_id' => SORT_ASC])
339
			->createCommand()->query();
340
		$referenceGroup = $referenceParent = $conditions = [];
341
		while ($condition = $dataReader->read()) {
342
			if ($condition['group_id']) {
343
				$isEmptyCondition = false;
344
			} else {
345 3
				$condition['group_id'] = $condition['id'];
346
				$isEmptyCondition = true;
347 3
			}
348 1
			$value = $condition['value'];
349
			$fieldName = "{$condition['field_name']}:{$condition['module_name']}" . ($condition['source_field_name'] ? ':' . $condition['source_field_name'] : '');
350 3
			if (isset($referenceParent[$condition['parent_id']], $referenceGroup[$condition['group_id']])) {
351 3
				$referenceParent[$condition['parent_id']][$condition['condition_index']] = [
352
					'fieldname' => $fieldName,
353
					'operator' => $condition['operator'],
354
					'value' => $value,
355
				];
356
			} elseif (isset($referenceGroup[$condition['parent_id']])) {
357
				if ($isEmptyCondition) {
358
					$referenceGroup[$condition['parent_id']][$condition['group_index']] = [
359
						'condition' => $condition['condition'],
360
						'rules' => [],
361
					];
362 3
				} else {
363 3
					$referenceGroup[$condition['parent_id']][$condition['group_index']] = [
364 3
						'condition' => $condition['condition'],
365 3
						'rules' => [
366 3
							$condition['condition_index'] => [
367 3
								'fieldname' => $fieldName,
368 3
								'operator' => $condition['operator'],
369
								'value' => $value,
370
							],
371
						],
372
					];
373
				}
374
				$referenceParent[$condition['parent_id']] = &$referenceGroup[$condition['parent_id']][$condition['group_index']]['rules'];
375
				$referenceGroup[$condition['group_id']] = &$referenceGroup[$condition['parent_id']][$condition['group_index']]['rules'];
376
			} else {
377
				if ($isEmptyCondition) {
378
					$conditions = [
379
						'condition' => $condition['condition'],
380
						'rules' => [],
381
					];
382
				} else {
383
					$conditions = [
384
						'condition' => $condition['condition'],
385
						'rules' => [
386
							$condition['condition_index'] => [
387
								'fieldname' => $fieldName,
388
								'operator' => $condition['operator'],
389
								'value' => $value,
390
							],
391
						],
392
					];
393
				}
394
				$referenceParent[$condition['parent_id']] = &$conditions['rules'];
395
				$referenceGroup[$condition['group_id']] = &$conditions['rules'];
396
			}
397
		}
398
		$conditions = static::sortConditions($conditions);
399
		Cache::save('CustomView_GetConditions', $id, $conditions, Cache::LONG);
400
		return $conditions;
401
	}
402
403
	/**
404
	 * Sorting conditions.
405
	 *
406
	 * @param array|null $array
407
	 * @param ?array     $arrayToSort
408
	 *
409
	 * @return array|null
410
	 */
411
	private static function sortConditions(?array $arrayToSort): ?array
412
	{
413
		if (isset($arrayToSort['rules'])) {
414
			ksort($arrayToSort['rules']);
415
			foreach ($arrayToSort['rules'] as $rule) {
416
				if (isset($rule['condition'])) {
417
					static::sortConditions($rule);
418
				}
419
			}
420
		}
421
		return $arrayToSort;
422
	}
423
424
	/**
425 3
	 * Get fields to detect duplicates.
426 3
	 *
427 3
	 * @param int|string $viewId
428
	 *
429
	 * @return array
430
	 */
431
	public static function getDuplicateFields($viewId): array
432
	{
433
		if (!is_numeric($viewId)) {
434
			return [];
435
		}
436
		if (Cache::has('CustomView_GetDuplicateFields', $viewId)) {
437
			return Cache::get('CustomView_GetDuplicateFields', $viewId);
438 3
		}
439
		$data = (new \App\Db\Query())->select(['vtiger_field.fieldname', 'u_#__cv_duplicates.ignore'])
440 3
			->from('u_#__cv_duplicates')
441
			->innerJoin('vtiger_field', 'vtiger_field.fieldid = u_#__cv_duplicates.fieldid')
442
			->where(['u_#__cv_duplicates.cvid' => $viewId])->all();
443
		Cache::save('CustomView_GetDuplicateFields', $viewId, $data);
444
		return $data;
445
	}
446
447
	/**
448 3
	 * To get the customViewId of the specified module.
449
	 *
450
	 * @param mixed $noCache
451
	 *
452
	 * @return int|string
453
	 */
454
	public function getViewId($noCache = false)
455
	{
456
		\App\Log::trace(__METHOD__);
457
		if (isset($this->defaultViewId)) {
458 3
			return $this->defaultViewId;
459
		}
460 3
		if ($noCache || Request::_isEmpty('viewname')) {
0 ignored issues
show
The method _isEmpty() does not exist on App\Request. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

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

460
		if ($noCache || Request::/** @scrutinizer ignore-call */ _isEmpty('viewname')) {
Loading history...
461
			$viewId = null;
462
			if (Request::_has('mid')) {
0 ignored issues
show
The method _has() does not exist on App\Request. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

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

462
			if (Request::/** @scrutinizer ignore-call */ _has('mid')) {
Loading history...
463 3
				$viewId = current(self::getModuleFiltersByMenuId(Request::_getInteger('mid'), $this->moduleName));
0 ignored issues
show
The method _getInteger() does not exist on App\Request. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

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

463
				$viewId = current(self::getModuleFiltersByMenuId(Request::/** @scrutinizer ignore-call */ _getInteger('mid'), $this->moduleName));
Loading history...
464 1
			}
465
			if (empty($viewId) && !$noCache && self::getCurrentView($this->moduleName)) {
466 3
				$viewId = self::getCurrentView($this->moduleName);
467 3
				if (empty($this->getFilterInfo($viewId))) {
468 3
					$viewId = null;
469 3
				}
470 3
			}
471 3
			if (empty($viewId)) {
472
				$viewId = $this->getDefaultCvId();
473
			}
474
			if (empty($viewId) || !$this->isPermittedCustomView($viewId)) {
475
				$viewId = $this->getMandatoryFilter();
476
			}
477
		} else {
478
			$viewId = Request::_get('viewname');
0 ignored issues
show
The method _get() does not exist on App\Request. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

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

478
			/** @scrutinizer ignore-call */ 
479
   $viewId = Request::_get('viewname');
Loading history...
479
			if (!is_numeric($viewId)) {
480
				if ('All' === $viewId) {
481 2
					$viewId = $this->getMandatoryFilter();
482
				} else {
483 2
					$viewId = $this->getViewIdByName($viewId);
484 2
				}
485
				if (!$viewId) {
486
					$viewId = $this->getDefaultCvId();
487 2
				}
488 2
			} else {
489
				$viewId = (int) $viewId;
490
				if (!$this->isPermittedCustomView($viewId)) {
491 2
					throw new Exceptions\NoPermitted('ERR_NO_PERMITTED_TO_VIEW');
492
				}
493 2
			}
494
		}
495
		$this->defaultViewId = $viewId;
496
		return $viewId;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $viewId also could return the type array which is incompatible with the documented return type integer|string.
Loading history...
497
	}
498
499
	/**
500
	 * Get default cvId.
501
	 *
502
	 * @return int|string
503
	 */
504
	public function getDefaultCvId()
505
	{
506
		$cacheName = $this->moduleName . $this->user->getId();
507
		if (Cache::has('GetDefaultCvId', $cacheName)) {
508
			return Cache::get('GetDefaultCvId', $cacheName);
509
		}
510
		$query = (new Db\Query())->select(['userid', 'default_cvid'])->from('vtiger_user_module_preferences')->where(['tabid' => Module::getModuleId($this->moduleName)]);
511
		$data = $query->createCommand()->queryAllByGroup();
512
		$defaultCvId = null;
513
		foreach ($this->user->getMemberStructure() as $member) {
514 2
			if (isset($data[$member]) && $this->isPermittedCustomView($data[$member])) {
515 2
				$defaultCvId = $data[$member];
516
				break;
517
			}
518
		}
519
		if (!$defaultCvId) {
520
			foreach ($this->getFilters() as $cvId => $values) {
521
				if (1 === $values['setdefault'] && $this->isPermittedCustomView($cvId)) {
522
					$defaultCvId = $cvId;
523 2
					break;
524
				}
525 2
			}
526 2
			if (!$defaultCvId) {
527 2
				$defaultCvId = $this->getMandatoryFilter();
528
			}
529
		}
530 2
		Cache::save('GetDefaultCvId', $cacheName, $defaultCvId);
531 2
		return $defaultCvId;
532 2
	}
533 2
534
	/**
535
	 * Function to check if the current user is able to see the customView.
536
	 *
537
	 * @param int|string $viewId
538 2
	 *
539 2
	 * @return bool
540 2
	 */
541
	public function isPermittedCustomView($viewId)
542
	{
543
		return self::isPermitted($viewId, $this->moduleName, $this->user->getId());
544
	}
545 2
546 2
	/**
547
	 * Get mandatory filter by module.
548
	 *
549
	 * @param bolean $returnData
0 ignored issues
show
The type App\bolean was not found. Maybe you did not declare it correctly or list all dependencies?

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

filter:
    dependency_paths: ["lib/*"]

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

Loading history...
550 2
	 *
551 2
	 * @return array|int
552 2
	 */
553
	public function getMandatoryFilter($returnData = false)
554
	{
555
		Log::trace(__METHOD__);
556
		$info = $this->getFilters();
557 2
		$returnValue = '';
558 2
		foreach ($info as $index => &$values) {
559 2
			if (0 === $values['presence']) {
560 2
				$returnValue = $index;
561 2
				break;
562
			}
563
			if (2 === $values['presence']) {
564
				$returnValue = $index;
565
			}
566
		}
567
		return $returnData ? $info[$returnValue] : $returnValue;
568
	}
569
570
	/**
571
	 * Get viewId by name.
572
	 *
573 2
	 * @param string $viewName
574
	 *
575 2
	 * @return int|null
576 2
	 */
577 2
	public function getViewIdByName(string $viewName): ?int
578 2
	{
579 2
		$viewId = null;
580 2
		foreach ($this->getFilters() as $cvId => &$values) {
0 ignored issues
show
The expression $this->getFilters() cannot be used as a reference.

Let?s assume that you have the following foreach statement:

foreach ($array as &$itemValue) { }

$itemValue is assigned by reference. This is possible because the expression (in the example $array) can be used as a reference target.

However, if we were to replace $array with something different like the result of a function call as in

foreach (getArray() as &$itemValue) { }

then assigning by reference is not possible anymore as there is no target that could be modified.

Available Fixes

1. Do not assign by reference
foreach (getArray() as $itemValue) { }
2. Assign to a local variable first
$array = getArray();
foreach ($array as &$itemValue) {}
3. Return a reference
function &getArray() { $array = array(); return $array; }

foreach (getArray() as &$itemValue) { }
Loading history...
581 2
			if ($values['viewname'] === $viewName) {
582 2
				$viewId = $cvId;
583 2
				break;
584
			}
585
		}
586
		return $viewId;
587
	}
588
589
	/**
590
	 * Function to get basic information about filter.
591
	 *
592
	 * @param int $cvId
593
	 *
594
	 * @return array
595
	 */
596
	public function getFilterInfo(int $cvId): array
597
	{
598
		return $this->getFilters()[$cvId] ?? [];
599
	}
600
601
	/**
602
	 * Function to get basic information about all filters.
603
	 *
604
	 * @param string $moduleName
605
	 *
606
	 * @return array
607
	 */
608
	public function getFilters(): array
609
	{
610
		return self::getFiltersByModule($this->moduleName);
611
	}
612
613
	/**
614
	 * Check permissions.
615
	 *
616
	 * @param int    $cvId
617 2
	 * @param string $moduleName
618
	 * @param int    $userId
619
	 *
620
	 * @return bool
621
	 */
622
	public static function isPermitted(int $cvId, string $moduleName = null, int $userId = null): bool
623
	{
624
		$userModel = $userId ? \App\User::getUserModel($userId) : \App\User::getCurrentUserModel();
625
		return ($data = self::getCVDetails($cvId, $moduleName))
626
		&& ($userModel->isAdmin()
627 2
		|| $data['userid'] === $userModel->getId()
628
		|| 0 === $data['presence']
629 2
		|| \in_array($data['status'], [self::CV_STATUS_DEFAULT, self::CV_STATUS_PUBLIC])
630 2
		|| (self::CV_STATUS_PRIVATE === $data['status'] && array_intersect($userModel->getMemberStructure(), $data['members'])));
631 2
	}
632 2
633 2
	/**
634 2
	 * Function to get basic information about all filters for module.
635
	 *
636
	 * @param string $moduleName
637
	 *
638
	 * @return array
639 2
	 */
640
	public static function getFiltersByModule(string $moduleName): array
641
	{
642
		if (Cache::has('CustomViewInfo', $moduleName)) {
643
			return Cache::get('CustomViewInfo', $moduleName);
644
		}
645
		$members = (new Db\Query())->select(['u_#__cv_privileges.cvid', 'member'])->from('u_#__cv_privileges')
646
			->innerJoin('vtiger_customview', 'u_#__cv_privileges.cvid=vtiger_customview.cvid')
647
			->where(['entitytype' => $moduleName])->createCommand()->queryAllByGroup(2);
648
		$info = (new Db\Query())->from('vtiger_customview')->where(['entitytype' => $moduleName])->indexBy('cvid')->orderBy(['sequence' => SORT_ASC])->all();
649
		foreach ($info as &$item) {
650
			$item['cvid'] = (int) $item['cvid'];
651
			$item['setdefault'] = (int) $item['setdefault'];
652
			$item['setmetrics'] = (int) $item['setmetrics'];
653
			$item['status'] = (int) $item['status'];
654
			$item['privileges'] = (int) $item['privileges'];
655
			$item['featured'] = (int) $item['featured'];
656
			$item['presence'] = (int) $item['presence'];
657
			$item['sequence'] = (int) $item['sequence'];
658
			$item['userid'] = (int) $item['userid'];
659
			$item['members'] = $members[$item['cvid']] ?? [];
660
			Cache::save('CustomViewInfo', $item['cvid'], $item);
661
		}
662
		Cache::save('CustomViewInfo', $moduleName, $info);
663
		return $info;
664
	}
665
666
	/**
667
	 * Reset current views configuration in session.
668
	 *
669
	 * @param string|bool $moduleName
670
	 */
671
	public static function resetCurrentView($moduleName = false)
672
	{
673 2
		if (\App\Session::has('lvs')) {
674
			if ($moduleName) {
675 2
				$lvs = \App\Session::get('lvs');
676 2
				if (isset($lvs[$moduleName])) {
677 2
					unset($lvs[$moduleName]);
678 2
					\App\Session::set('lvs', $lvs);
679 2
				}
680
			} else {
681
				\App\Session::set('lvs', []);
682 2
			}
683
		}
684
	}
685
686
	/**
687
	 * Get module filters by menu id.
688
	 *
689
	 * @param int    $menuId
690
	 * @param string $moduleName
691
	 *
692 3
	 * @return array
693
	 */
694 3
	public static function getModuleFiltersByMenuId(int $menuId, string $moduleName = ''): array
695 2
	{
696
		$cacheKey = 'getModuleFiltersByMenuId' . $moduleName;
697 3
		if (\App\Cache::staticHas($cacheKey, $menuId)) {
698 3
			return \App\Cache::staticGet($cacheKey, $menuId);
699 2
		}
700 2
		$filters = [];
701 2
		$userModel = User::getCurrentUserModel();
702 2
		$roleMenu = 'user_privileges/menu_' . filter_var($userModel->getDetail('roleid'), FILTER_SANITIZE_NUMBER_INT) . '.php';
703 2
		file_exists($roleMenu) ? require $roleMenu : require 'user_privileges/menu_0.php';
704 2
		if (0 === \count($menus) && file_exists($roleMenu)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $menus seems to be never defined.
Loading history...
705 2
			require 'user_privileges/menu_0.php';
706 2
		}
707 2
		if (isset($filterList[$menuId])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $filterList does not exist. Did you maybe mean $filters?
Loading history...
708 2
			$filtersMenu = explode(',', $filterList[$menuId]['filters']);
709
			$filtersCustomView = array_keys(\CustomView_Record_Model::getAll($moduleName));
710 3
			$filters = array_intersect($filtersMenu, $filtersCustomView);
711 3
		}
712 3
		\App\Cache::staticSave($cacheKey, $menuId, $filters);
713 3
		return $filters;
714 3
	}
715 3
716 3
	/**
717 3
	 * Get custom view by ID.
718 3
	 *
719 3
	 * @param int $cvId
720 3
	 *
721
	 * @return array
722
	 */
723 3
	public static function getCustomViewById(int $cvId): array
724 3
	{
725
		if (Cache::has('CustomViewById', $cvId)) {
726
			return Cache::get('CustomViewById', $cvId);
727
		}
728
		$data = (new Db\Query())->from('vtiger_customview')->where(['cvid' => $cvId])->one() ?: [];
729
		if (!empty($data['advanced_conditions'])) {
730
			$data['advanced_conditions'] = \App\Json::decode($data['advanced_conditions']);
731
		}
732
		Cache::save('CustomViewById', $cvId, $data);
733
		return $data;
734
	}
735
736
	/**
737
	 * Gets custom view details by ID.
738
	 *
739
	 * @param int         $cvId
740
	 * @param string|null $moduleName
741
	 *
742
	 * @return array
743
	 */
744
	public static function getCVDetails(int $cvId, string $moduleName = null): array
745
	{
746
		if (Cache::has('CustomViewInfo', $cvId)) {
747
			return Cache::get('CustomViewInfo', $cvId);
748
		}
749
		if (!$moduleName) {
750
			$moduleName = self::getCustomViewById($cvId)['entitytype'] ?? '';
751
		}
752
		return $moduleName ? (self::getFiltersByModule($moduleName)[$cvId] ?? []) : [];
753
	}
754
755
	/**
756
	 * Function clear cache by custom view ID.
757
	 *
758
	 * @param int         $cvId
759
	 * @param string|null $moduleName
760
	 *
761
	 * @return void
762
	 */
763
	public static function clearCacheById(int $cvId, string $moduleName = null): void
764
	{
765
		Cache::delete('CustomViewById', $cvId);
766
		Cache::delete('CustomViewInfo', $cvId);
767
		Cache::delete('getAllFilterColors', false);
0 ignored issues
show
false of type false is incompatible with the type string expected by parameter $key of App\Cache::delete(). ( Ignorable by Annotation )

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

767
		Cache::delete('getAllFilterColors', /** @scrutinizer ignore-type */ false);
Loading history...
768
		Cache::delete('getAllFilterColors', true);
0 ignored issues
show
true of type true is incompatible with the type string expected by parameter $key of App\Cache::delete(). ( Ignorable by Annotation )

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

768
		Cache::delete('getAllFilterColors', /** @scrutinizer ignore-type */ true);
Loading history...
769
		if (null === $moduleName) {
770
			foreach (\App\Module::getAllModuleNames() as $moduleName) {
771
				Cache::delete('CustomViewInfo', $moduleName);
772
			}
773
		} else {
774
			Cache::delete('CustomViewInfo', $moduleName);
775
		}
776
	}
777
}
778