Passed
Pull Request — developer (#16533)
by Arkadiusz
22:25 queued 03:38
created

Calendar_Module_Model::getValuesFromSource()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 7
ccs 0
cts 0
cp 0
rs 10
cc 2
nc 2
nop 2
crap 6
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
/**
14
 * Calendar Module Model Class.
15
 */
16
class Calendar_Module_Model extends Vtiger_Module_Model
17
{
18
	/** {@inheritdoc} */
19
	public $allowTypeChange = false;
20
21
	/**
22 2
	 * Function returns the default view for the Calendar module.
23
	 *
24 2
	 * @return string
25
	 */
26
	public function getDefaultViewName()
27
	{
28
		return 'Calendar';
29
	}
30
31
	/**
32 2
	 *  Function returns the url for Calendar view.
33
	 *
34 2
	 * @return string
35 2
	 */
36 2
	public function getCalendarViewUrl()
37
	{
38 2
		return 'index.php?module=' . $this->get('name') . '&view=' . $this->getDefaultViewName();
39
	}
40
41
	/**
42
	 * Function to check whether the module is summary view supported.
43
	 *
44
	 * @return bool
45
	 */
46
	public function isSummaryViewSupported()
47
	{
48
		return false;
49
	}
50
51
	/** {@inheritdoc} */
52
	public function getSideBarLinks($linkParams)
53
	{
54
		$links = Vtiger_Link_Model::getAllByType($this->getId(), ['SIDEBARLINK', 'SIDEBARWIDGET'], $linkParams);
55
		$links['SIDEBARLINK'][] = Vtiger_Link_Model::getInstanceFromValues([
56
			'linktype' => 'SIDEBARLINK',
57
			'linklabel' => 'LBL_CALENDAR_VIEW',
58
			'linkurl' => $this->getCalendarViewUrl(),
59
			'linkicon' => 'fas fa-calendar-alt',
60
		]);
61
		$links['SIDEBARLINK'][] = Vtiger_Link_Model::getInstanceFromValues([
62
			'linktype' => 'SIDEBARLINK',
63
			'linklabel' => 'LBL_RECORDS_LIST',
64
			'linkurl' => $this->getListViewUrl(),
65
			'linkicon' => 'fas fa-list',
66
		]);
67
		if (isset($linkParams['ACTION']) && 'Calendar' === $linkParams['ACTION'] && App\Config::module('Calendar', 'SHOW_LIST_BUTTON')) {
68
			$links['SIDEBARLINK'][] = Vtiger_Link_Model::getInstanceFromValues([
69
				'linktype' => 'SIDEBARLINK',
70
				'linklabel' => 'LBL_CALENDAR_LIST',
71
				'linkurl' => 'javascript:Calendar_Calendar_Js.goToRecordsList("' . $this->getListViewUrl() . '");',
72
				'linkicon' => 'far fa-calendar-minus',
73
			]);
74
		}
75
		if ($this->isPermitted('Kanban') && \App\Utils\Kanban::getBoards($this->getName(), true)) {
0 ignored issues
show
Bug introduced by
$this->getName() of type boolean is incompatible with the type string expected by parameter $moduleName of App\Utils\Kanban::getBoards(). ( Ignorable by Annotation )

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

75
		if ($this->isPermitted('Kanban') && \App\Utils\Kanban::getBoards(/** @scrutinizer ignore-type */ $this->getName(), true)) {
Loading history...
76
			$links['SIDEBARLINK'][] = Vtiger_Link_Model::getInstanceFromValues([
77
				'linktype' => 'SIDEBARLINK',
78
				'linklabel' => 'LBL_VIEW_KANBAN',
79
				'linkurl' => 'index.php?module=' . $this->getName() . '&view=Kanban',
80
				'linkicon' => 'yfi yfi-kanban',
81
			]);
82
		}
83
		return $links;
84
	}
85
86
	/**
87
	 * Function returns the url that shows Calendar Import result.
88
	 *
89
	 * @return string url
90
	 */
91
	public function getImportResultUrl()
92
	{
93
		return 'index.php?module=' . $this->getName() . '&view=ImportResult';
94
	}
95
96
	/**
97
	 * Function to get export query.
98
	 *
99
	 * @param mixed $focus
100
	 * @param mixed $where
101
	 *
102
	 * @return string query;
103
	 */
104
	public function getExportQuery($focus = '', $where = '')
0 ignored issues
show
Unused Code introduced by
The parameter $where is not used and could be removed. ( Ignorable by Annotation )

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

104
	public function getExportQuery($focus = '', /** @scrutinizer ignore-unused */ $where = '')

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $focus is not used and could be removed. ( Ignorable by Annotation )

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

104
	public function getExportQuery(/** @scrutinizer ignore-unused */ $focus = '', $where = '')

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
105
	{
106
		return (new App\Db\Query())->select(['vtiger_activity.*', 'vtiger_crmentity.description', 'assigned_user_id' => 'vtiger_crmentity.smownerid', 'vtiger_activity_reminder.reminder_time'])
107
			->from('vtiger_activity')
108
			->innerJoin('vtiger_crmentity', 'vtiger_activity.activityid = vtiger_crmentity.crmid')
109
			->leftJoin('vtiger_activity_reminder', 'vtiger_activity_reminder.activity_id = vtiger_activity.activityid')
110
			->where(['vtiger_crmentity.deleted' => 0, 'vtiger_crmentity.smownerid' => App\User::getCurrentUserId()]);
111
	}
112
113
	/**
114
	 * Function to set event fields for export.
115
	 */
116
	public function setEventFieldsForExport()
117
	{
118
		$keysToReplace = ['taskpriority'];
119
		$keysValuesToReplace = ['taskpriority' => 'priority'];
120
		foreach ($this->getFields() as $fieldName => $fieldModel) {
121
			if ($fieldModel->getPermissions()) {
122
				if (!\in_array($fieldName, $keysToReplace)) {
123
					$eventFields[$fieldName] = 'yes';
124
				} else {
125
					$eventFields[$keysValuesToReplace[$fieldName]] = 'yes';
126
				}
127
			}
128
		}
129
		$this->set('eventFields', $eventFields);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $eventFields does not seem to be defined for all execution paths leading up to this point.
Loading history...
130
	}
131
132
	/**
133
	 * Function to set todo fields for export.
134
	 */
135
	public function setTodoFieldsForExport()
136
	{
137
		$keysToReplace = ['taskpriority', 'activitystatus'];
138
		$keysValuesToReplace = ['taskpriority' => 'priority', 'activitystatus' => 'status'];
139
		foreach ($this->getFields() as $fieldName => $fieldModel) {
140
			if ($fieldModel->getPermissions()) {
141
				if (!\in_array($fieldName, $keysToReplace)) {
142
					$todoFields[$fieldName] = 'yes';
143
				} else {
144
					$todoFields[$keysValuesToReplace[$fieldName]] = 'yes';
145
				}
146
			}
147
		}
148
		$this->set('todoFields', $todoFields);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $todoFields does not seem to be defined for all execution paths leading up to this point.
Loading history...
149
	}
150
151
	/**
152
	 * Function to get the url to view Details for the module.
153
	 *
154
	 * @param mixed $id
155
	 *
156
	 * @return string - url
157
	 */
158
	public function getDetailViewUrl($id)
159
	{
160
		return 'index.php?module=Calendar&view=' . $this->getDetailViewName() . '&record=' . $id;
161
	}
162
163
	/**
164
	 * Function to get Alphabet Search Field.
165
	 */
166
	public function getAlphabetSearchField()
167
	{
168
		return 'subject';
169
	}
170
171
	/**
172
	 * Function returns Calendar Reminder record models.
173
	 *
174
	 * @return \Calendar_Record_Model[]
175
	 */
176
	public static function getCalendarReminder()
177
	{
178
		$currentUserModel = Users_Record_Model::getCurrentUserModel();
179
		$activityReminder = $currentUserModel->getCurrentUserActivityReminderInSeconds();
180
		$recordModels = [];
181
		if (!empty($activityReminder)) {
182
			$time = date('Y-m-d H:i:s', strtotime("+$activityReminder seconds"));
183
			$query = (new \App\Db\Query())
184
				->select(['recordid', 'vtiger_activity_reminder_popup.datetime'])
185
				->from('vtiger_activity_reminder_popup')
186
				->innerJoin('vtiger_activity', 'vtiger_activity_reminder_popup.recordid = vtiger_activity.activityid')
187
				->innerJoin('vtiger_crmentity', 'vtiger_activity_reminder_popup.recordid = vtiger_crmentity.crmid')
188
				->where(['vtiger_crmentity.smownerid' => $currentUserModel->getId(), 'vtiger_crmentity.deleted' => 0, 'vtiger_activity.status' => self::getComponentActivityStateLabel('current')])
189
				->andWhere(['or', ['and', ['vtiger_activity_reminder_popup.status' => Calendar_Record_Model::REMNDER_POPUP_ACTIVE], ['<=', 'vtiger_activity_reminder_popup.datetime', $time]], ['and', ['vtiger_activity_reminder_popup.status' => Calendar_Record_Model::REMNDER_POPUP_WAIT], ['<=', 'vtiger_activity_reminder_popup.datetime', date('Y-m-d H:i:s')]]])
190
				->orderBy(['vtiger_activity_reminder_popup.datetime' => SORT_DESC])
191
				->distinct()
192
				->limit(\App\Config::module('Calendar', 'maxNumberCalendarNotifications', 20));
193
			$dataReader = $query->createCommand()->query();
194
			while ($recordId = $dataReader->readColumn(0)) {
195
				$recordModels[] = Vtiger_Record_Model::getInstanceById($recordId, 'Calendar');
196
			}
197
		}
198
		return $recordModels;
199
	}
200
201
	/** {@inheritdoc} */
202
	public function getFieldsByType($type, bool $active = false): array
203
	{
204
		$restrictedField = ['picklist' => ['activitystatus', 'visibility', 'duration_minutes']];
205
		if (!\is_array($type)) {
206
			$type = [$type];
207
		}
208
		$fields = $this->getFields();
209
		$fieldList = [];
210
		foreach ($fields as $field) {
211
			$fieldType = $field->getFieldDataType();
212
			if (\in_array($fieldType, $type)) {
213
				$fieldName = $field->getName();
214
				if ('picklist' == $fieldType && \in_array($fieldName, $restrictedField[$fieldType])) {
215
				} else {
216
					$fieldList[$fieldName] = $field;
217
				}
218
			}
219
		}
220
		return $fieldList;
221
	}
222
223
	/** {@inheritdoc} */
224
	public function getSettingLinks(): array
225
	{
226
		$currentUserModel = Users_Record_Model::getCurrentUserModel();
227
		$settingLinks = [];
228
		if ($currentUserModel->isAdminUser()) {
229
			$settingLinks[] = [
230
				'linktype' => 'LISTVIEWSETTING',
231
				'linklabel' => 'LBL_EDIT_FIELDS',
232
				'linkurl' => 'index.php?parent=Settings&module=LayoutEditor&sourceModule=' . $this->getName(),
233
				'linkicon' => 'adminIcon-modules-fields',
234
			];
235
			$settingLinks[] = [
236
				'linktype' => 'LISTVIEWSETTING',
237
				'linklabel' => 'LBL_EDIT_PICKLIST_VALUES',
238
				'linkurl' => 'index.php?parent=Settings&module=Picklist&view=Index&source_module=' . $this->getName(),
239
				'linkicon' => 'adminIcon-fields-picklists',
240
			];
241
		}
242
		return $settingLinks;
0 ignored issues
show
introduced by
The expression return $settingLinks returns an array which contains values of type array<string,string> which are incompatible with the return type string mandated by Vtiger_Module_Model::getSettingLinks().
Loading history...
243
	}
244
245
	/**
246
	 * Function to get orderby sql from orderby field.
247
	 *
248
	 * @param mixed $orderBy
249
	 */
250
	public function getOrderBySql($orderBy)
251
	{
252
		if ('status' == $orderBy) {
253
			return $orderBy;
254
		}
255
		return parent::getOrderBySql($orderBy);
256
	}
257
258
	public static function getCalendarTypes()
259
	{
260
		return App\Fields\Picklist::getValuesName('activitytype');
261
	}
262
263
	/** {@inheritdoc} */
264
	public function getValuesFromSource(App\Request $request, $moduleName = false)
265
	{
266
		$data = parent::getValuesFromSource($request);
267
		if (!empty($postponeTime = $request->getInteger('postponeTime'))) {
268
			$data = $this->postponeTimeValue($data, $postponeTime);
269
		}
270
		return $data;
271
	}
272
273
	/**
274
	 * Load field  postpone values.
275
	 *
276
	 * @param array $data
277
	 * @param int   $postponeTime
278
	 *
279
	 * @return array
280
	 */
281
	public function postponeTimeValue(array $data, int $postponeTime): array
282
	{
283
		if (!empty($start = $data['date_start'])) {
284
			if (strpos($start, ' ')) {
285
				$dateStart = $start;
286
			} else {
287
				$dateStart = $start . ' ' . $data['time_start'];
288
			}
289
		}
290
		if (!empty($end = $data['due_date'])) {
291
			if (strpos($end, ' ')) {
292
				$dateEnd = $end;
293
			} else {
294
				$dateEnd = $end . ' ' . $data['time_end'];
295
			}
296
		}
297
		$data['date_start'] = (new DateTime($dateStart))->modify("+ {$postponeTime} minutes")->format('Y-m-d H:i:s');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dateStart does not seem to be defined for all execution paths leading up to this point.
Loading history...
298
		$data['due_date'] = (new DateTime($dateEnd))->modify("+ {$postponeTime} minutes")->format('Y-m-d H:i:s');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dateEnd does not seem to be defined for all execution paths leading up to this point.
Loading history...
299
		return $data;
300
	}
301
302
	public static function getCalendarState($data = [])
303
	{
304
		if ($data) {
305
			$activityStatus = $data['activitystatus'];
306
			if (\in_array($activityStatus, self::getComponentActivityStateLabel('history'))) {
307
				return false;
308
			}
309
			$dueDateTime = $data['due_date'] . ' ' . $data['time_end'];
310 1
			$startDateTime = $data['date_start'] . ' ' . $data['time_start'];
311
			$dates = ['start' => $startDateTime, 'end' => $dueDateTime, 'current' => null];
312 1
			foreach ($dates as $key => $date) {
313 1
				$date = new DateTimeField($date);
314 1
				$userFormatedString = $date->getDisplayDate();
315 1
				$timeFormatedString = $date->getDisplayTime();
316
				$dBFomatedDate = DateTimeField::convertToDBFormat($userFormatedString);
317 1
				$dates[$key] = strtotime($dBFomatedDate . ' ' . $timeFormatedString);
318 1
			}
319 1
			$activityStatusLabels = self::getComponentActivityStateLabel();
320 1
			if (!empty($data['activitystatus']) && isset($activityStatusLabels[$data['activitystatus']])) {
321 1
				$state = $activityStatusLabels[$data['activitystatus']];
322 1
			} else {
323 1
				$state = $activityStatusLabels['not_started'];
324 1
				if ($dates['end'] > $dates['current'] && $dates['start'] < $dates['current']) {
325 1
					$state = $activityStatusLabels['in_realization'];
326
				} elseif ($dates['end'] > $dates['current']) {
327 1
					$state = $activityStatusLabels['not_started'];
328 1
				} elseif ($dates['end'] < $dates['current']) {
329
					$state = $activityStatusLabels['overdue'];
330
				}
331 1
			}
332 1
			return $state;
333
		}
334 1
		return false;
335 1
	}
336
337
	/**
338
	 * The function gets the labels for a given status field.
339
	 *
340 1
	 * @param string $key
341
	 *
342
	 * @return <Array>
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Array> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Array>.
Loading history...
343
	 */
344
	public static function getComponentActivityStateLabel($key = '')
345
	{
346
		$pickListValues = App\Fields\Picklist::getValuesName('activitystatus');
347
		if (!\is_array($pickListValues)) {
0 ignored issues
show
introduced by
The condition is_array($pickListValues) is always true.
Loading history...
348
			return [];
349
		}
350
		$componentsActivityState = [];
351
		foreach ($pickListValues as $value) {
352 1
			switch ($value) {
353
				case 'PLL_PLANNED':
354 1
					$componentsActivityState['not_started'] = $value;
355 1
					break;
356
				case 'PLL_IN_REALIZATION':
357
					$componentsActivityState['in_realization'] = $value;
358 1
					break;
359 1
				case 'PLL_COMPLETED':
360 1
					$componentsActivityState['completed'] = $value;
361 1
					break;
362 1
				case 'PLL_POSTPONED':
363 1
					$componentsActivityState['postponed'] = $value;
364 1
					break;
365 1
				case 'PLL_OVERDUE':
366 1
					$componentsActivityState['overdue'] = $value;
367 1
					break;
368 1
				case 'PLL_CANCELLED':
369 1
					$componentsActivityState['cancelled'] = $value;
370 1
					break;
371 1
				default:
372 1
					break;
373 1
			}
374 1
		}
375 1
		if ('current' == $key) {
376 1
			$componentsActivityState = ['PLL_PLANNED', 'PLL_IN_REALIZATION', 'PLL_OVERDUE'];
377 1
		} elseif ('history' == $key) {
378 1
			$componentsActivityState = ['PLL_COMPLETED', 'PLL_POSTPONED', 'PLL_CANCELLED'];
379
		} elseif ($key) {
380
			return $componentsActivityState[$key];
381
		}
382
		return $componentsActivityState;
383 1
	}
384 1
385 1
	/**
386 1
	 * Import calendar rekords from ICS.
387 1
	 *
388
	 * @param string $filePath
389
	 *
390 1
	 * @throws \Exception
391
	 *
392
	 * @return array
393
	 */
394
	public function importICS(string $filePath)
395
	{
396
		$userId = \App\User::getCurrentUserRealId();
397
		$lastImport = new ICalLastImport();
398
		$lastImport->clearRecords($userId);
399
		$eventModule = 'Events';
400
		$todoModule = 'Calendar';
401
		$totalCount = $skipCount = [$eventModule => 0, $todoModule => 0];
402
		$calendar = \App\Integrations\Dav\Calendar::loadFromContent(file_get_contents($filePath));
403
		foreach ($calendar->getRecordInstance() as $recordModel) {
404
			$recordModel->set('assigned_user_id', $userId);
405
			$recordModel->save();
406
			$calendar->recordSaveAttendee($recordModel);
407
			if ('VEVENT' === (string) $calendar->getComponent()->name) {
408
				$module = $eventModule;
409
			} else {
410
				$module = $todoModule;
411
			}
412
			if ($recordModel->getId()) {
413
				++$totalCount[$module];
414
				$lastImport = new ICalLastImport();
415
				$lastImport->setFields(['userid' => $userId, 'entitytype' => $this->getName(), 'crmid' => $recordModel->getId()]);
416
				$lastImport->save();
417
			} else {
418
				++$skipCount[$module];
419
			}
420
		}
421
		return ['events' => $totalCount[$eventModule] - $skipCount[$eventModule], 'skipped_events' => $skipCount[$eventModule], 'task' => $totalCount[$todoModule] - $skipCount[$todoModule], 'skipped_task' => $skipCount[$todoModule]];
422
	}
423
424
	/** {@inheritdoc} */
425
	public function getLayoutTypeForQuickCreate(): string
426
	{
427
		return 'standard';
428
	}
429
}
430