Test Setup Failed
Push — developer ( 804ffe...f9365b )
by Radosław
44:32 queued 26:22
created

Vtiger_RelationAjax_Action::addRelation()   B

Complexity

Conditions 7
Paths 26

Size

Total Lines 26
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 26
ccs 0
cts 17
cp 0
rs 8.8333
c 0
b 0
f 0
cc 7
nc 26
nop 1
crap 56
1
<?php
2
3
 /* +***********************************************************************************
4
 * The contents of this file are subject to the vtiger CRM Public License Version 1.0
5
 * ("License"); You may not use this file except in compliance with the License
6
 * The Original Code is:  vtiger CRM Open Source
7
 * The Initial Developer of the Original Code is vtiger.
8
 * Portions created by vtiger are Copyright (C) vtiger.
9
 * All Rights Reserved.
10
 * Contributor(s): YetiForce S.A.
11
 * *********************************************************************************** */
12
13
class Vtiger_RelationAjax_Action extends \App\Controller\Action
14
{
15
	use App\Controller\ClearProcess;
16
	use \App\Controller\ExposeMethod;
17
18
	/** {@inheritdoc} */
19
	public function __construct()
20
	{
21
		parent::__construct();
22
		$this->exposeMethod('addRelation');
23
		$this->exposeMethod('deleteRelation');
24
		$this->exposeMethod('massDeleteRelation');
25
		$this->exposeMethod('exportToExcel');
26
		$this->exposeMethod('updateRelation');
27
		$this->exposeMethod('getRelatedListPageCount');
28
		$this->exposeMethod('updateFavoriteForRecord');
29
		$this->exposeMethod('calculate');
30
		$this->exposeMethod('massDownload');
31
		$this->exposeMethod('checkFilesIntegrity');
32
	}
33
34
	/** {@inheritdoc} */
35
	public function checkPermission(App\Request $request)
36
	{
37
		$userPrivilegesModel = Users_Privileges_Model::getCurrentUserPrivilegesModel();
38
		if (!$request->isEmpty('record', true) && !\App\Privilege::isPermitted($request->getModule(), 'DetailView', $request->getInteger('record'))) {
39
			throw new \App\Exceptions\NoPermittedToRecord('ERR_NO_PERMISSIONS_FOR_THE_RECORD', 403);
40
		}
41
		if (!$request->isEmpty('src_record', true) && !\App\Privilege::isPermitted($request->getModule(), 'DetailView', $request->getInteger('src_record'))) {
42
			throw new \App\Exceptions\NoPermittedToRecord('ERR_NO_PERMISSIONS_FOR_THE_RECORD', 403);
43
		}
44
		if (!$request->isEmpty('related_module', true) && !$userPrivilegesModel->hasModulePermission($request->getByType('related_module', 2))) {
45
			throw new \App\Exceptions\NoPermitted('LBL_PERMISSION_DENIED', 403);
46
		}
47
		if (!$request->isEmpty('relatedModule', true) && !\is_array($relatedModule = $request->getByType('relatedModule', 2)) && 'ProductsAndServices' !== $relatedModule) {
48
			if ('ModTracker' === $relatedModule) {
49
				if (!$userPrivilegesModel->hasModuleActionPermission($request->getModule(), 'ModTracker')) {
50
					throw new \App\Exceptions\NoPermitted('LBL_PERMISSION_DENIED', 403);
51
				}
52
			} else {
53
				if (!$userPrivilegesModel->hasModulePermission($relatedModule)) {
54
					throw new \App\Exceptions\NoPermitted('LBL_PERMISSION_DENIED', 403);
55
				}
56
			}
57
		}
58
	}
59
60
	/**
61
	 * Get query for records list from request.
62
	 *
63
	 * @param \App\Request $request
64
	 *
65
	 * @return \App\QueryGenerator|bool
66
	 */
67
	public static function getQuery(App\Request $request)
68
	{
69
		return static::getRelationListModel($request)->getRelationQuery(true)->clearFields();
0 ignored issues
show
Bug introduced by
The method clearFields() does not exist on App\Db\Query. Since you implemented __call, 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

69
		return static::getRelationListModel($request)->getRelationQuery(true)->/** @scrutinizer ignore-call */ clearFields();
Loading history...
Bug Best Practice introduced by
The expression return static::getRelati...ry(true)->clearFields() also could return the type App\Db\Query which is incompatible with the documented return type App\QueryGenerator|boolean.
Loading history...
70
	}
71
72
	public static function getRelationListModel(App\Request $request)
73
	{
74
		$parentRecordModel = \Vtiger_Record_Model::getInstanceById($request->getInteger('record'), $request->getModule());
75
		$relationId = $request->isEmpty('relationId') ? false : $request->getInteger('relationId');
76
		$cvId = $request->isEmpty('cvId', true) ? 0 : $request->getByType('cvId', \App\Purifier::ALNUM);
77
		$relationListView = Vtiger_RelationListView_Model::getInstance($parentRecordModel, $request->getByType('relatedModule', \App\Purifier::ALNUM), $relationId, $cvId);
78
79
		$selectedIds = $request->getArray('selected_ids', \App\Purifier::ALNUM);
80
		if ($selectedIds && 'all' !== $selectedIds[0]) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $selectedIds of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
81
			$relationListView->getQueryGenerator()->addCondition('id', $selectedIds, 'e');
82
		}
83
		if ($request->has('entityState')) {
84
			$relationListView->set('entityState', $request->getByType('entityState'));
85
		}
86
		$operator = 's';
87
		if (!$request->isEmpty('operator', true)) {
88
			$operator = $request->getByType('operator');
89
			$relationListView->set('operator', $operator);
90
		}
91
		if (!$request->isEmpty('search_key', true)) {
92
			$searchKey = $request->getByType('search_key', \App\Purifier::ALNUM);
93
			$relationListView->set('search_key', $searchKey);
94
			$relationListView->set('search_value', App\Condition::validSearchValue($request->getByType('search_value', 'Text'), $relationListView->getQueryGenerator()->getModule(), $searchKey, $operator));
95
		}
96
		$searchParams = App\Condition::validSearchParams($request->getByType('relatedModule', \App\Purifier::ALNUM), $request->getArray('search_params'));
97
		if (empty($searchParams) || !\is_array($searchParams)) {
98
			$searchParams = [];
99
		}
100
		$relationListView->set('search_params', $relationListView->getQueryGenerator()->parseBaseSearchParamsToCondition($searchParams));
101
		if ($excludedIds = $request->getArray('excluded_ids', \App\Purifier::INTEGER)) {
102
			$relationListView->getQueryGenerator()->addCondition('id', $excludedIds, 'n');
103
		}
104
		if ($request->getBoolean('isSortActive') && !$request->isEmpty('orderby')) {
105
			$relationListView->set('orderby', $request->getArray('orderby', \App\Purifier::STANDARD, [], \App\Purifier::SQL));
106
		}
107
108
		return $relationListView;
109
	}
110
111
	/**
112
	 * Get records list from request.
113
	 *
114
	 * @param \App\Request $request
115
	 *
116
	 * @return int[]
117
	 */
118
	public static function getRecordsListFromRequest(App\Request $request): array
119
	{
120
		$selectedIds = $request->getArray('selected_ids', 2);
121
		if ($selectedIds && 'all' !== $selectedIds[0]) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $selectedIds of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
122
			return $selectedIds;
123
		}
124
		$queryGenerator = static::getQuery($request);
125
		return $queryGenerator ? $queryGenerator->createQuery()->column() : [];
126
	}
127
128
	/**
129
	 * Function to add relation for specified source record id and related record id list.
130
	 *
131
	 * @param \App\Request $request
132
	 *
133
	 * @throws \App\Exceptions\NoPermittedToRecord
134
	 */
135
	public function addRelation(App\Request $request)
136
	{
137
		$sourceModule = $request->getModule();
138
		$sourceRecordId = $request->getInteger('src_record');
139
		$relatedModule = $request->getByType('related_module', App\Purifier::ALNUM);
140
		if (is_numeric($relatedModule)) {
141
			$relatedModule = \App\Module::getModuleName($relatedModule);
142
		}
143
		if (!\App\Privilege::isPermitted($sourceModule, 'DetailView', $sourceRecordId)) {
144
			throw new \App\Exceptions\NoPermittedToRecord('ERR_NO_PERMISSIONS_FOR_THE_RECORD', 406);
145
		}
146
		$sourceModuleModel = Vtiger_Module_Model::getInstance($sourceModule);
147
		if ($request->isEmpty('relationId')) {
148
			$relationModel = Vtiger_Relation_Model::getInstance($sourceModuleModel, Vtiger_Module_Model::getInstance($relatedModule));
149
		} else {
150
			$relationModel = Vtiger_Relation_Model::getInstanceById($request->getInteger('relationId'));
151
		}
152
		$recordIdsToRelate = $request->has('selected_ids') ? $this->getRecordIdsToRelate($request) : $request->getArray('related_record_list', App\Purifier::INTEGER);
153
		foreach ($recordIdsToRelate as $relatedRecordId) {
154
			if (\App\Privilege::isPermitted($relatedModule, 'DetailView', $relatedRecordId)) {
155
				$relationModel->addRelation($sourceRecordId, $relatedRecordId);
156
			}
157
		}
158
		$response = new Vtiger_Response();
159
		$response->setResult(true);
160
		$response->emit();
161
	}
162
163
	/**
164
	 * Get record ids to relate.
165
	 *
166
	 * @param App\Request $request
167
	 *
168
	 * @return array
169
	 */
170
	public function getRecordIdsToRelate(App\Request $request): array
171
	{
172
		$cvId = $request->isEmpty('cvId') ? '' : $request->getByType('cvId', App\Purifier::ALNUM);
173
		$moduleName = $request->getByType('related_module', App\Purifier::ALNUM);
174
		if ((!empty($cvId) && 'undefined' === $cvId) || '0' === $cvId) {
175
			$cvId = CustomView_Record_Model::getAllFilterByModule($moduleName)->getId();
176
		}
177
		$customViewModel = CustomView_Record_Model::getInstanceById((int) $cvId);
178
		if (!$customViewModel) {
0 ignored issues
show
introduced by
$customViewModel is of type CustomView_Record_Model, thus it always evaluated to true.
Loading history...
179
			return [];
180
		}
181
		$selectedIds = $request->getArray('selected_ids', App\Purifier::ALNUM);
182
		if ($selectedIds && 'all' !== $selectedIds[0]) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $selectedIds of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
183
			$queryGenerator = new App\QueryGenerator($moduleName);
184
			$queryGenerator->initForCustomViewById($cvId);
185
			$queryGenerator->addCondition('id', $selectedIds, 'e');
186
		} else {
187
			if (!$request->isEmpty('operator')) {
188
				$operator = $request->getByType('operator');
189
				$searchKey = $request->getByType('search_key', 'Alnum');
190
				$customViewModel->set('operator', $operator);
191
				$customViewModel->set('search_key', $searchKey);
192
				$customViewModel->set('search_value', App\Condition::validSearchValue($request->getByType('search_value', App\Purifier::TEXT), $moduleName, $searchKey, $operator));
193
			}
194
			if ($request->getBoolean('isSortActive') && !$request->isEmpty('orderby')) {
195
				$customViewModel->set('orderby', $request->getArray('orderby', \App\Purifier::STANDARD, [], \App\Purifier::SQL));
196
			}
197
			$customViewModel->set('search_params', App\Condition::validSearchParams($moduleName, $request->getArray('search_params')));
198
			if ($advancedConditions = $request->has('advancedConditions') ? $request->getArray('advancedConditions') : []) {
199
				$customViewModel->set('advancedConditions', \App\Condition::validAdvancedConditions($advancedConditions));
200
			}
201
			$queryGenerator = $customViewModel->getRecordsListQuery($request->getArray('excluded_ids', App\Purifier::ALNUM), $moduleName);
202
203
			$queryGenerator->addNativeCondition(
204
				['not in', $queryGenerator->getColumnName('id'), $this->getRelatedRecordIds($request)]
205
			);
206
		}
207
		return $queryGenerator->clearFields()->createQuery()->column();
208
	}
209
210
	/**
211
	 * Get related record ids.
212
	 *
213
	 * @param App\Request $request
214
	 *
215
	 * @return \App\Db\Query
216
	 */
217
	public function getRelatedRecordIds(App\Request $request): App\Db\Query
218
	{
219
		$parentRecordModel = \Vtiger_Record_Model::getInstanceById($request->getInteger('src_record'), $request->getByType('src_module'));
220
		$relationId = $request->isEmpty('relationId') ? false : $request->getInteger('relationId');
221
		$cvId = $request->isEmpty('cvId', true) ? 0 : $request->getByType('cvId', \App\Purifier::ALNUM);
222
		$relationListView = Vtiger_RelationListView_Model::getInstance($parentRecordModel, $request->getByType('related_module', \App\Purifier::ALNUM), $relationId, $cvId);
223
		$queryGenerator = $relationListView->getRelationQuery(true)->clearFields();
224
		return $queryGenerator->createQuery();
0 ignored issues
show
Bug introduced by
The method createQuery() does not exist on App\Db\Query. Since you implemented __call, 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

224
		return $queryGenerator->/** @scrutinizer ignore-call */ createQuery();
Loading history...
225
	}
226
227
	/**
228
	 * Function to delete the relation for specified source record id and related record id list.
229
	 *
230
	 * @param \App\Request $request
231
	 *
232
	 * @throws \App\Exceptions\NoPermittedToRecord
233
	 */
234
	public function deleteRelation(App\Request $request)
235
	{
236
		$sourceModule = $request->getModule();
237
		$sourceRecordId = $request->getInteger('src_record');
238
		$relatedModule = $request->getByType('related_module', 2);
239
		$relatedRecordIdList = $request->getArray('related_record_list', 'Integer');
240
		$sourceModuleModel = Vtiger_Module_Model::getInstance($sourceModule);
241
		if ($request->isEmpty('relationId')) {
242
			$relationModel = Vtiger_Relation_Model::getInstance($sourceModuleModel, Vtiger_Module_Model::getInstance($relatedModule));
243
		} else {
244
			$relationModel = Vtiger_Relation_Model::getInstanceById($request->getInteger('relationId'));
245
		}
246
		$result = false;
247
		if ($relationModel->privilegeToDelete()) {
248
			foreach ($relatedRecordIdList as $relatedRecordId) {
249
				if (\App\Privilege::isPermitted($relatedModule, 'DetailView', $relatedRecordId)) {
250
					$result = $relationModel->deleteRelation($sourceRecordId, (int) $relatedRecordId);
251
				}
252
			}
253
		}
254
		$response = new Vtiger_Response();
255
		$response->setResult($result);
256
		$response->emit();
257
	}
258
259
	/**
260
	 * This function removes the relationship associated with the module.
261
	 *
262
	 * @param \App\Request $request
263
	 */
264
	public function massDeleteRelation(App\Request $request)
265
	{
266
		$sourceModule = $request->getModule();
267
		$relatedModuleName = $request->getByType('relatedModule', 2);
268
		$sourceRecordId = $request->getInteger('src_record');
269
		$parentRecordModel = Vtiger_Record_Model::getInstanceById($sourceRecordId, $sourceModule);
270
		$relationId = $request->isEmpty('relationId') ? false : $request->getInteger('relationId');
271
		$cvId = $request->isEmpty('cvId', true) ? 0 : $request->getByType('cvId', 'Alnum');
272
		$relationListView = Vtiger_RelationListView_Model::getInstance($parentRecordModel, $relatedModuleName, $relationId, $cvId);
273
		$relationModel = $relationListView->getRelationModel();
274
		if ($relationModel->privilegeToDelete()) {
275
			$rows = $this->getRecordsListFromRequest($request);
276
			foreach ($rows as $relatedRecordId) {
277
				if (\App\Privilege::isPermitted($relatedModuleName, 'DetailView', $relatedRecordId) && $relationModel->privilegeToDelete(null, $relatedRecordId)) {
278
					$relationModel->deleteRelation((int) $sourceRecordId, (int) $relatedRecordId);
279
				}
280
			}
281
		}
282
283
		$response = new Vtiger_Response();
284
		$response->setResult(['reloadList' => true]);
285
		$response->emit();
286
	}
287
288
	/**
289
	 * Export relations to excel.
290
	 *
291
	 * @param \App\Request $request
292
	 */
293
	public function exportToExcel(App\Request $request)
294
	{
295
		if (!\App\Privilege::isPermitted($request->getByType('relatedModule', \App\Purifier::ALNUM), 'QuickExportToExcel')) {
296
			throw new \App\Exceptions\NoPermitted('LBL_PERMISSION_DENIED', 403);
297
		}
298
		$relationListView = static::getRelationListModel($request);
299
		$relatedModuleName = $relationListView->getRelatedModuleModel()->getName();
300
		$headers = $relationListView->getHeaders();
301
302
		$exportModel = \App\Export\Records::getInstance($relatedModuleName, 'xls')
0 ignored issues
show
Bug introduced by
$relatedModuleName of type boolean is incompatible with the type string expected by parameter $moduleName of App\Export\Records::getInstance(). ( Ignorable by Annotation )

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

302
		$exportModel = \App\Export\Records::getInstance(/** @scrutinizer ignore-type */ $relatedModuleName, 'xls')
Loading history...
303
			->setLimit(\App\Config::performance('MAX_NUMBER_EXPORT_RECORDS'))
304
			->setFormat(\App\Export\Records::USER_FORMAT);
305
		$exportModel->queryGenerator = $relationListView->getRelationQuery(true);
306
		$exportModel->setFields(array_keys($headers));
307
		$exportModel->sendHttpHeader();
308
		$exportModel->exportData();
309
	}
310
311
	/**
312
	 * Function to update the relation for specified source record id and related record id list.
313
	 *
314
	 * @param \App\Request $request
315
	 *
316
	 * @throws \App\Exceptions\NoPermittedToRecord
317
	 * @throws \App\Exceptions\NoPermitted
318
	 */
319
	public function updateRelation(App\Request $request)
320
	{
321
		$sourceModule = $request->getModule();
322
		$sourceRecordId = $request->getInteger('src_record');
323
		$relatedModule = $request->getByType('related_module', 2);
324
		$recordsToRemove = $request->getArray('recordsToRemove', 'Integer');
325
		$recordsToAdd = $request->getArray('recordsToAdd', 'Integer');
326
		$categoryToAdd = $request->getArray('categoryToAdd', 'Alnum');
327
		$categoryToRemove = $request->getArray('categoryToRemove', 'Alnum');
328
		$sourceModuleModel = Vtiger_Module_Model::getInstance($sourceModule);
329
		if ($request->isEmpty('relationId')) {
330
			$relationModel = Vtiger_Relation_Model::getInstance($sourceModuleModel, Vtiger_Module_Model::getInstance($relatedModule));
331
		} else {
332
			$relationModel = Vtiger_Relation_Model::getInstanceById($request->getInteger('relationId'));
333
		}
334
		if (!empty($recordsToAdd)) {
335
			foreach ($recordsToAdd as $relatedRecordId) {
336
				if (\App\Privilege::isPermitted($relatedModule, 'DetailView', $relatedRecordId)) {
337
					$relationModel->addRelation($sourceRecordId, $relatedRecordId);
338
				}
339
			}
340
		}
341
		if (!empty($recordsToRemove)) {
342
			if ($relationModel->privilegeToDelete()) {
343
				foreach ($recordsToRemove as $relatedRecordId) {
344
					$relationModel->deleteRelation((int) $sourceRecordId, (int) $relatedRecordId);
345
				}
346
			} else {
347
				throw new \App\Exceptions\NoPermitted('LBL_PERMISSION_DENIED', 406);
348
			}
349
		}
350
		if (!empty($categoryToAdd) && $relationModel->isTreeRelation()) {
351
			foreach ($categoryToAdd as $category) {
352
				$relationModel->addRelationTree($sourceRecordId, $category);
353
			}
354
		}
355
		if (!empty($categoryToRemove) && $relationModel->isTreeRelation()) {
356
			if ($relationModel->privilegeToTreeDelete()) {
357
				foreach ($categoryToRemove as $category) {
358
					$relationModel->deleteRelationTree($sourceRecordId, $category);
359
				}
360
			} else {
361
				throw new \App\Exceptions\NoPermitted('LBL_PERMISSION_DENIED', 406);
362
			}
363
		}
364
		$response = new Vtiger_Response();
365
		$response->setResult(true);
366
		$response->emit();
367
	}
368
369
	/**
370
	 * Function to get the page count for related list.
371
	 *
372
	 * @param \App\Request $request
373
	 */
374
	public function getRelatedListPageCount(App\Request $request)
375
	{
376
		$moduleName = $request->getModule();
377
		$relatedModuleName = $request->getArray('relatedModule', 'Alnum');
378
		$firstRelatedModuleName = current($relatedModuleName);
379
		$parentId = $request->getInteger('record');
380
		if (!\App\Privilege::isPermitted($moduleName, 'DetailView', $parentId)) {
381
			throw new \App\Exceptions\NoPermittedToRecord('ERR_NO_PERMISSIONS_FOR_THE_RECORD', 406);
382
		}
383
		$relationId = $request->isEmpty('relationId') ? false : $request->getInteger('relationId');
384
		$cvId = $request->isEmpty('cvId', true) ? 0 : $request->getByType('cvId', 'Alnum');
385
		$totalCount = 0;
386
		$pageCount = 0;
387
		if ('ModComments' === $firstRelatedModuleName) {
388
			$totalCount = ModComments_Record_Model::getCommentsCount($parentId);
389
		} elseif ('ModTracker' === $firstRelatedModuleName) {
390
			$count = (int) ($unreviewed = current(ModTracker_Record_Model::getUnreviewed($parentId, false, true))) ? array_sum($unreviewed) : '';
391
			$totalCount = $count ?: '';
392
		} else {
393
			$relModules = !empty($relatedModuleName) && \is_array($relatedModuleName) ? $relatedModuleName : [];
394
			if ('ProductsAndServices' === $firstRelatedModuleName) {
395
				$relModules = ['Products', 'OutsourcedProducts', 'Assets', 'Services', 'OSSOutsourcedServices', 'OSSSoldServices'];
396
			}
397
			$categoryCount = ['Products', 'OutsourcedProducts', 'Services', 'OSSOutsourcedServices'];
398
			$pagingModel = new Vtiger_Paging_Model();
399
			$parentRecordModel = Vtiger_Record_Model::getInstanceById($parentId, $moduleName);
400
			$userPrivilegesModel = Users_Privileges_Model::getCurrentUserPrivilegesModel();
401
			foreach ($relModules as $relModule) {
402
				if (!$userPrivilegesModel->hasModulePermission($relModule)) {
403
					continue;
404
				}
405
				$relationListView = Vtiger_RelationListView_Model::getInstance($parentRecordModel, $relModule, $relationId, $cvId);
406
				if (!$relationListView) {
407
					continue;
408
				}
409
				if ('ProductsAndServices' === $relatedModuleName && \in_array($relModule, $categoryCount)) {
410
					$totalCount += (int) $relationListView->getRelatedTreeEntriesCount();
411
				}
412
				if ('Calendar' === $relatedModuleName && \App\Config::module($relatedModuleName, 'SHOW_ONLY_CURRENT_RECORDS_COUNT')) {
413
					$totalCount += (int) $relationListView->getRelationQuery()->andWhere(['vtiger_activity.status' => Calendar_Module_Model::getComponentActivityStateLabel('current')])->count();
0 ignored issues
show
Bug introduced by
The method count() does not exist on App\QueryGenerator. ( Ignorable by Annotation )

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

413
					$totalCount += (int) $relationListView->getRelationQuery()->andWhere(['vtiger_activity.status' => Calendar_Module_Model::getComponentActivityStateLabel('current')])->/** @scrutinizer ignore-call */ count();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method andWhere() does not exist on App\QueryGenerator. ( Ignorable by Annotation )

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

413
					$totalCount += (int) $relationListView->getRelationQuery()->/** @scrutinizer ignore-call */ andWhere(['vtiger_activity.status' => Calendar_Module_Model::getComponentActivityStateLabel('current')])->count();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
414
				} else {
415
					$totalCount += (int) $relationListView->getRelatedEntriesCount();
416
				}
417
				$pageLimit = $pagingModel->getPageLimit();
418
				$pageCount = ceil((int) $totalCount / (int) $pageLimit);
419
			}
420
		}
421
		if (0 == $pageCount) {
422
			$pageCount = 1;
423
		}
424
		$result = [];
425
		$result['numberOfRecords'] = $totalCount;
426
		$result['page'] = $pageCount;
427
		$response = new Vtiger_Response();
428
		$response->setResult($result);
429
		$response->emit();
430
	}
431
432
	public function updateFavoriteForRecord(App\Request $request)
433
	{
434
		$sourceModuleModel = Vtiger_Module_Model::getInstance($request->getModule());
435
		if ($request->isEmpty('relationId')) {
436
			$relationModel = Vtiger_Relation_Model::getInstance($sourceModuleModel, Vtiger_Module_Model::getInstance($request->getByType('relatedModule', 2)));
437
		} else {
438
			$relationModel = Vtiger_Relation_Model::getInstanceById($request->getInteger('relationId'));
439
		}
440
		if (!empty($relationModel)) {
441
			$result = $relationModel->updateFavoriteForRecord($request->getByType('actionMode'), ['crmid' => $request->getInteger('record'), 'relcrmid' => $request->getInteger('relcrmid')]);
442
		}
443
444
		$response = new Vtiger_Response();
445
		$response->setResult((bool) $result);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.
Loading history...
446
		$response->emit();
447
	}
448
449
	/**
450
	 * Function for calculating values for a list of related records.
451
	 *
452
	 * @param \App\Request $request
453
	 *
454
	 * @throws \App\Exceptions\Security
455
	 * @throws \App\Exceptions\NotAllowedMethod
456
	 */
457
	public function calculate(App\Request $request)
458
	{
459
		$queryGenerator = static::getQuery($request);
460
		$fieldQueryModel = $queryGenerator->getQueryField($request->getByType('fieldName', 2));
461
		$fieldModel = $fieldQueryModel->getField();
462
		if (!$fieldModel->isViewable()) {
463
			throw new \App\Exceptions\Security('ERR_NO_ACCESS_TO_THE_FIELD', 403);
464
		}
465
		if (!$fieldModel->isCalculateField()) {
466
			throw new \App\Exceptions\Security('ERR_NOT_SUPPORTED_FIELD', 406);
467
		}
468
		if ('sum' !== $request->getByType('calculateType')) {
469
			throw new \App\Exceptions\NotAllowedMethod('LBL_PERMISSION_DENIED', 406);
470
		}
471
472
		$columnName = $fieldQueryModel->getColumnName();
473
		$fieldName = $fieldModel->getName();
474
		$query = $queryGenerator->setFields(['id'])->setDistinct(null)->setGroup('id')->createQuery()->select([$fieldName => new \yii\db\Expression("MAX({$columnName})")]);
475
		$value = (new \App\Db\Query())->from(['c' => $query])->sum("c.{$fieldName}");
476
477
		$response = new Vtiger_Response();
478
		$response->setResult($fieldModel->getDisplayValue($value));
479
		$response->emit();
480
	}
481
482
	/**
483
	 * Mass download.
484
	 *
485
	 * @param App\Request $request
486
	 */
487
	public function massDownload(App\Request $request)
488
	{
489
		$relatedModuleName = $request->getByType('relatedModule', 2);
490
		$records = $this->getRecordsListFromRequest($request);
491
		if (1 === \count($records)) {
492
			$documentRecordModel = Vtiger_Record_Model::getInstanceById($records[0], $relatedModuleName);
493
			$documentRecordModel->downloadFile();
0 ignored issues
show
Bug introduced by
The method downloadFile() does not exist on Vtiger_Record_Model. It seems like you code against a sub-type of Vtiger_Record_Model such as Documents_Record_Model. ( Ignorable by Annotation )

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

493
			$documentRecordModel->/** @scrutinizer ignore-call */ 
494
                         downloadFile();
Loading history...
494
			$documentRecordModel->updateDownloadCount();
0 ignored issues
show
Bug introduced by
The method updateDownloadCount() does not exist on Vtiger_Record_Model. It seems like you code against a sub-type of Vtiger_Record_Model such as Documents_Record_Model. ( Ignorable by Annotation )

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

494
			$documentRecordModel->/** @scrutinizer ignore-call */ 
495
                         updateDownloadCount();
Loading history...
495
		} else {
496
			Documents_Record_Model::downloadFiles($records);
497
		}
498
	}
499
500
	/**
501
	 * Check many files integrity.
502
	 *
503
	 * @param App\Request $request
504
	 */
505
	public function checkFilesIntegrity(App\Request $request)
506
	{
507
		$relatedModuleName = $request->getByType('relatedModule', 2);
508
		$fileNotAvailable = [];
509
		$result = ['success' => true];
510
		foreach ($this->getRecordsListFromRequest($request) as $record) {
511
			$documentRecordModel = Vtiger_Record_Model::getInstanceById($record, $relatedModuleName);
512
			$resultVal = $documentRecordModel->checkFileIntegrity();
0 ignored issues
show
Bug introduced by
The method checkFileIntegrity() does not exist on Vtiger_Record_Model. It seems like you code against a sub-type of Vtiger_Record_Model such as Documents_Record_Model. ( Ignorable by Annotation )

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

512
			/** @scrutinizer ignore-call */ 
513
   $resultVal = $documentRecordModel->checkFileIntegrity();
Loading history...
513
			if (!$resultVal) {
514
				$fileNotAvailable[] = $documentRecordModel->get('notes_title');
515
			}
516
		}
517
		if (!empty($fileNotAvailable)) {
518
			$result = ['notify' => ['text' => \App\Language::translate('LBL_FILE_NOT_AVAILABLE', $relatedModuleName) . ': <br>- ' . implode('<br>- ', $fileNotAvailable)]];
519
		}
520
		$response = new Vtiger_Response();
521
		$response->setResult($result);
522
		$response->emit();
523
	}
524
}
525