Passed
Push — master ( f66da6...7a87af )
by
unknown
02:36 queued 15s
created

class.taskrecurrence.php (22 issues)

Labels
Severity
1
<?php
2
/*
3
 * SPDX-License-Identifier: AGPL-3.0-only
4
 * SPDX-FileCopyrightText: Copyright 2005-2016 Zarafa Deutschland GmbH
5
 * SPDX-FileCopyrightText: Copyright 2020-2022 grommunio GmbH
6
 */
7
8
class TaskRecurrence extends BaseRecurrence {
9
	/**
10
	 * Timezone info which is always false for task.
11
	 *
12
	 * @var false
13
	 */
14
	public $tz = false;
15
16
	private $action;
17
18
	public function __construct($store, $message) {
19
		$this->store = $store;
20
		$this->message = $message;
21
22
		$properties = [];
23
		$properties["entryid"] = PR_ENTRYID;
24
		$properties["parent_entryid"] = PR_PARENT_ENTRYID;
25
		$properties["icon_index"] = PR_ICON_INDEX;
26
		$properties["message_class"] = PR_MESSAGE_CLASS;
27
		$properties["message_flags"] = PR_MESSAGE_FLAGS;
28
		$properties["subject"] = PR_SUBJECT;
29
		$properties["importance"] = PR_IMPORTANCE;
30
		$properties["sensitivity"] = PR_SENSITIVITY;
31
		$properties["last_modification_time"] = PR_LAST_MODIFICATION_TIME;
32
		$properties["status"] = "PT_LONG:PSETID_Task:" . PidLidTaskStatus;
33
		$properties["percent_complete"] = "PT_DOUBLE:PSETID_Task:" . PidLidPercentComplete;
34
		$properties["startdate"] = "PT_SYSTIME:PSETID_Task:" . PidLidTaskStartDate;
35
		$properties["duedate"] = "PT_SYSTIME:PSETID_Task:" . PidLidTaskDueDate;
36
		$properties["reset_reminder"] = "PT_BOOLEAN:PSETID_Task:0x8107";
37
		$properties["dead_occurrence"] = "PT_BOOLEAN:PSETID_Task:0x8109";
38
		$properties["datecompleted"] = "PT_SYSTIME:PSETID_Task:" . PidLidTaskDateCompleted;
39
		$properties["recurring_data"] = "PT_BINARY:PSETID_Task:0x8116";
40
		$properties["actualwork"] = "PT_LONG:PSETID_Task:0x8110";
41
		$properties["totalwork"] = "PT_LONG:PSETID_Task:0x8111";
42
		$properties["complete"] = "PT_BOOLEAN:PSETID_Task:" . PidLidTaskComplete;
43
		$properties["task_f_creator"] = "PT_BOOLEAN:PSETID_Task:0x811e";
44
		$properties["owner"] = "PT_STRING8:PSETID_Task:0x811f";
45
		$properties["recurring"] = "PT_BOOLEAN:PSETID_Task:0x8126";
46
47
		$properties["reminder_minutes"] = "PT_LONG:PSETID_Common:" . PidLidReminderDelta;
48
		$properties["reminder_time"] = "PT_SYSTIME:PSETID_Common:" . PidLidReminderTime;
49
		$properties["reminder"] = "PT_BOOLEAN:PSETID_Common:" . PidLidReminderSet;
50
51
		$properties["private"] = "PT_BOOLEAN:PSETID_Common:" . PidLidPrivate;
52
		$properties["contacts"] = "PT_MV_STRING8:PSETID_Common:0x853a";
53
		$properties["contacts_string"] = "PT_STRING8:PSETID_Common:0x8586";
54
		$properties["categories"] = "PT_MV_STRING8:PS_PUBLIC_STRINGS:Keywords";
55
56
		$properties["commonstart"] = "PT_SYSTIME:PSETID_Common:0x8516";
57
		$properties["commonend"] = "PT_SYSTIME:PSETID_Common:0x8517";
58
		$properties["commonassign"] = "PT_LONG:PSETID_Common:0x8518";
59
		$properties["flagdueby"] = "PT_SYSTIME:PSETID_Common:" . PidLidReminderSignalTime;
60
		$properties["side_effects"] = "PT_LONG:PSETID_Common:0x8510";
61
62
		$this->proptags = getPropIdsFromStrings($store, $properties);
63
64
		parent::__construct($store, $message);
65
	}
66
67
	/**
68
	 * Function which saves recurrence and also regenerates task if necessary.
69
	 *
70
	 * @param mixed $recur new recurrence properties
71
	 *
72
	 * @return array|bool of properties of regenerated task else false
73
	 */
74
	public function setRecurrence(&$recur) {
75
		$this->recur = $recur;
76
		$this->action = &$recur;
77
78
		if (!isset($this->recur["changed_occurrences"])) {
79
			$this->recur["changed_occurrences"] = [];
80
		}
81
82
		if (!isset($this->recur["deleted_occurrences"])) {
83
			$this->recur["deleted_occurrences"] = [];
84
		}
85
86
		if (!isset($this->recur['startocc'])) {
87
			$this->recur['startocc'] = 0;
88
		}
89
		if (!isset($this->recur['endocc'])) {
90
			$this->recur['endocc'] = 0;
91
		}
92
93
		// Save recurrence because we need proper startrecurrdate and endrecurrdate
94
		$this->saveRecurrence();
95
96
		// Update $this->recur with proper startrecurrdate and endrecurrdate updated after saving recurrence
97
		$msgProps = mapi_getprops($this->message, [$this->proptags['recurring_data']]);
0 ignored issues
show
The function mapi_getprops was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

97
		$msgProps = /** @scrutinizer ignore-call */ mapi_getprops($this->message, [$this->proptags['recurring_data']]);
Loading history...
98
		$recurring_data = $this->parseRecurrence($msgProps[$this->proptags['recurring_data']]);
99
		foreach ($recurring_data as $key => $value) {
100
			$this->recur[$key] = $value;
101
		}
102
103
		$this->setFirstOccurrence();
104
105
		// Let's see if next occurrence has to be generated
106
		return $this->moveToNextOccurrence();
107
	}
108
109
	/**
110
	 * Sets task object to first occurrence if startdate/duedate of task object is different from first occurrence.
111
	 */
112
	public function setFirstOccurrence() {
113
		// Check if it is already the first occurrence
114
		if ($this->action['start'] == $this->recur["start"]) {
115
			return;
116
		}
117
		$items = $this->getNextOccurrence();
118
119
		$props = [];
120
		$props[$this->proptags['startdate']] = $items[$this->proptags['startdate']];
121
		$props[$this->proptags['commonstart']] = $items[$this->proptags['startdate']];
122
123
		$props[$this->proptags['duedate']] = $items[$this->proptags['duedate']];
124
		$props[$this->proptags['commonend']] = $items[$this->proptags['duedate']];
125
126
		mapi_setprops($this->message, $props);
0 ignored issues
show
The function mapi_setprops was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

126
		/** @scrutinizer ignore-call */ 
127
  mapi_setprops($this->message, $props);
Loading history...
127
	}
128
129
	/**
130
	 * Function which creates new task as current occurrence and moves the
131
	 * existing task to next occurrence.
132
	 *
133
	 * @return array|bool properties of newly created task if moving to next occurrence succeeds
134
	 *                    false if that was last occurrence
135
	 */
136
	public function moveToNextOccurrence() {
137
		$result = false;
138
		/*
139
		 * Every recurring task should have a 'duedate'. If a recurring task is created with no start/end date
140
		 * then we create first two occurrence separately and for first occurrence recurrence has ended.
141
		 */
142
		if ((empty($this->action['startdate']) && empty($this->action['duedate'])) ||
143
			($this->action['complete'] == 1) || (isset($this->action['deleteOccurrence']) && $this->action['deleteOccurrence'])) {
144
			$nextOccurrence = $this->getNextOccurrence();
145
			$result = mapi_getprops($this->message, [PR_ENTRYID, PR_PARENT_ENTRYID, PR_STORE_ENTRYID]);
0 ignored issues
show
The function mapi_getprops was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

145
			$result = /** @scrutinizer ignore-call */ mapi_getprops($this->message, [PR_ENTRYID, PR_PARENT_ENTRYID, PR_STORE_ENTRYID]);
Loading history...
146
147
			$props = [];
148
			if (!empty($nextOccurrence)) {
149
				if (!isset($this->action['deleteOccurrence'])) {
150
					// Create current occurrence as separate task
151
					$result = $this->regenerateTask($this->action['complete']);
152
				}
153
154
				// Set reminder for next occurrence
155
				$this->setReminder($nextOccurrence);
156
157
				// Update properties for next occurrence
158
				$this->action['duedate'] = $props[$this->proptags['duedate']] = $nextOccurrence[$this->proptags['duedate']];
159
				$this->action['commonend'] = $props[$this->proptags['commonend']] = $nextOccurrence[$this->proptags['duedate']];
160
161
				$this->action['startdate'] = $props[$this->proptags['startdate']] = $nextOccurrence[$this->proptags['startdate']];
162
				$this->action['commonstart'] = $props[$this->proptags['commonstart']] = $nextOccurrence[$this->proptags['startdate']];
163
164
				// If current task as been mark as 'Complete' then next occurrence should be incomplete.
165
				if (isset($this->action['complete']) && $this->action['complete'] == 1) {
166
					$this->action['status'] = $props[$this->proptags["status"]] = olTaskNotStarted;
167
					$this->action['complete'] = $props[$this->proptags["complete"]] = false;
168
					$this->action['percent_complete'] = $props[$this->proptags["percent_complete"]] = 0;
169
				}
170
171
				$props[$this->proptags["dead_occurrence"]] = false;
172
			}
173
			else {
174
				if (isset($this->action['deleteOccurrence']) && $this->action['deleteOccurrence']) {
175
					return false;
176
				}
177
178
				// Didn't get next occurrence, probably this is the last one, so recurrence ends here
179
				$props[$this->proptags["dead_occurrence"]] = true;
180
				$props[$this->proptags["datecompleted"]] = $this->action['datecompleted'];
181
				$props[$this->proptags["task_f_creator"]] = true;
182
183
				// OL props
184
				$props[$this->proptags["side_effects"]] = 1296;
185
				$props[$this->proptags["icon_index"]] = 1280;
186
			}
187
188
			mapi_setprops($this->message, $props);
0 ignored issues
show
The function mapi_setprops was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

188
			/** @scrutinizer ignore-call */ 
189
   mapi_setprops($this->message, $props);
Loading history...
189
		}
190
191
		return $result;
192
	}
193
194
	/**
195
	 * Function which return properties of next occurrence.
196
	 *
197
	 * @return null|array|false|T startdate/enddate of next occurrence
198
	 */
199
	public function getNextOccurrence() {
200
		if ($this->recur) {
201
			// @TODO: fix start of range
202
			$start = isset($this->messageprops[$this->proptags["duedate"]]) ? $this->messageprops[$this->proptags["duedate"]] : $this->action['start'];
203
			$dayend = ($this->recur['term'] == 0x23) ? 0x7FFFFFFF : $this->dayStartOf($this->recur["end"]);
204
205
			// Fix recur object
206
			$this->recur['startocc'] = 0;
207
			$this->recur['endocc'] = 0;
208
209
			// Retrieve next occurrence
210
			$items = $this->getItems($start, $dayend, 1);
211
212
			return !empty($items) ? $items[0] : false;
213
		}
214
	}
215
216
	/**
217
	 * Function which clones current occurrence and sets appropriate properties.
218
	 * The original recurring item is moved to next occurrence.
219
	 *
220
	 * @param bool $markComplete true if existing occurrence has to be marked complete
221
	 */
222
	public function regenerateTask($markComplete) {
223
		// Get all properties
224
		$taskItemProps = mapi_getprops($this->message);
0 ignored issues
show
The function mapi_getprops was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

224
		$taskItemProps = /** @scrutinizer ignore-call */ mapi_getprops($this->message);
Loading history...
225
226
		if (isset($this->action["subject"])) {
227
			$taskItemProps[$this->proptags["subject"]] = $this->action["subject"];
228
		}
229
		if (isset($this->action["importance"])) {
230
			$taskItemProps[$this->proptags["importance"]] = $this->action["importance"];
231
		}
232
		if (isset($this->action["startdate"])) {
233
			$taskItemProps[$this->proptags["startdate"]] = $this->action["startdate"];
234
			$taskItemProps[$this->proptags["commonstart"]] = $this->action["startdate"];
235
		}
236
		if (isset($this->action["duedate"])) {
237
			$taskItemProps[$this->proptags["duedate"]] = $this->action["duedate"];
238
			$taskItemProps[$this->proptags["commonend"]] = $this->action["duedate"];
239
		}
240
241
		$folder = mapi_msgstore_openentry($this->store, $taskItemProps[PR_PARENT_ENTRYID]);
0 ignored issues
show
The function mapi_msgstore_openentry was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

241
		$folder = /** @scrutinizer ignore-call */ mapi_msgstore_openentry($this->store, $taskItemProps[PR_PARENT_ENTRYID]);
Loading history...
242
		$newMessage = mapi_folder_createmessage($folder);
0 ignored issues
show
The function mapi_folder_createmessage was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

242
		$newMessage = /** @scrutinizer ignore-call */ mapi_folder_createmessage($folder);
Loading history...
243
244
		$taskItemProps[$this->proptags["status"]] = $markComplete ? olTaskComplete : olTaskNotStarted;
245
		$taskItemProps[$this->proptags["complete"]] = $markComplete;
246
		$taskItemProps[$this->proptags["percent_complete"]] = $markComplete ? 1 : 0;
247
248
		// This occurrence has been marked as 'Complete' so disable reminder
249
		if ($markComplete) {
250
			$taskItemProps[$this->proptags["reset_reminder"]] = false;
251
			$taskItemProps[$this->proptags["reminder"]] = false;
252
			$taskItemProps[$this->proptags["datecompleted"]] = $this->action["datecompleted"];
253
254
			unset($this->action[$this->proptags['datecompleted']]);
255
		}
256
257
		// Recurrence ends for this item
258
		$taskItemProps[$this->proptags["dead_occurrence"]] = true;
259
		$taskItemProps[$this->proptags["task_f_creator"]] = true;
260
261
		// OL props
262
		$taskItemProps[$this->proptags["side_effects"]] = 1296;
263
		$taskItemProps[$this->proptags["icon_index"]] = 1280;
264
265
		// Copy recipients
266
		$recipienttable = mapi_message_getrecipienttable($this->message);
0 ignored issues
show
The function mapi_message_getrecipienttable was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

266
		$recipienttable = /** @scrutinizer ignore-call */ mapi_message_getrecipienttable($this->message);
Loading history...
267
		$recipients = mapi_table_queryallrows($recipienttable, [PR_ENTRYID, PR_DISPLAY_NAME, PR_EMAIL_ADDRESS, PR_RECIPIENT_ENTRYID, PR_RECIPIENT_TYPE, PR_SEND_INTERNET_ENCODING, PR_SEND_RICH_INFO, PR_RECIPIENT_DISPLAY_NAME, PR_ADDRTYPE, PR_DISPLAY_TYPE, PR_RECIPIENT_TRACKSTATUS, PR_RECIPIENT_TRACKSTATUS_TIME, PR_RECIPIENT_FLAGS, PR_ROWID]);
0 ignored issues
show
The function mapi_table_queryallrows was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

267
		$recipients = /** @scrutinizer ignore-call */ mapi_table_queryallrows($recipienttable, [PR_ENTRYID, PR_DISPLAY_NAME, PR_EMAIL_ADDRESS, PR_RECIPIENT_ENTRYID, PR_RECIPIENT_TYPE, PR_SEND_INTERNET_ENCODING, PR_SEND_RICH_INFO, PR_RECIPIENT_DISPLAY_NAME, PR_ADDRTYPE, PR_DISPLAY_TYPE, PR_RECIPIENT_TRACKSTATUS, PR_RECIPIENT_TRACKSTATUS_TIME, PR_RECIPIENT_FLAGS, PR_ROWID]);
Loading history...
268
269
		$copy_to_recipientTable = mapi_message_getrecipienttable($newMessage);
270
		$copy_to_recipientRows = mapi_table_queryallrows($copy_to_recipientTable, [PR_ROWID]);
271
		foreach ($copy_to_recipientRows as $recipient) {
272
			mapi_message_modifyrecipients($newMessage, MODRECIP_REMOVE, [$recipient]);
0 ignored issues
show
The function mapi_message_modifyrecipients was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

272
			/** @scrutinizer ignore-call */ 
273
   mapi_message_modifyrecipients($newMessage, MODRECIP_REMOVE, [$recipient]);
Loading history...
273
		}
274
		mapi_message_modifyrecipients($newMessage, MODRECIP_ADD, $recipients);
275
276
		// Copy attachments
277
		$attachmentTable = mapi_message_getattachmenttable($this->message);
0 ignored issues
show
The function mapi_message_getattachmenttable was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

277
		$attachmentTable = /** @scrutinizer ignore-call */ mapi_message_getattachmenttable($this->message);
Loading history...
278
		if ($attachmentTable) {
279
			$attachments = mapi_table_queryallrows($attachmentTable, [PR_ATTACH_NUM, PR_ATTACH_SIZE, PR_ATTACH_LONG_FILENAME, PR_ATTACHMENT_HIDDEN, PR_DISPLAY_NAME, PR_ATTACH_METHOD]);
280
281
			foreach ($attachments as $attach_props) {
282
				$attach_old = mapi_message_openattach($this->message, (int) $attach_props[PR_ATTACH_NUM]);
0 ignored issues
show
The function mapi_message_openattach was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

282
				$attach_old = /** @scrutinizer ignore-call */ mapi_message_openattach($this->message, (int) $attach_props[PR_ATTACH_NUM]);
Loading history...
283
				$attach_newResourceMsg = mapi_message_createattach($newMessage);
0 ignored issues
show
The function mapi_message_createattach was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

283
				$attach_newResourceMsg = /** @scrutinizer ignore-call */ mapi_message_createattach($newMessage);
Loading history...
284
285
				mapi_copyto($attach_old, [], [], $attach_newResourceMsg, 0);
0 ignored issues
show
The function mapi_copyto was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

285
				/** @scrutinizer ignore-call */ 
286
    mapi_copyto($attach_old, [], [], $attach_newResourceMsg, 0);
Loading history...
286
				mapi_savechanges($attach_newResourceMsg);
0 ignored issues
show
The function mapi_savechanges was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

286
				/** @scrutinizer ignore-call */ 
287
    mapi_savechanges($attach_newResourceMsg);
Loading history...
287
			}
288
		}
289
290
		mapi_setprops($newMessage, $taskItemProps);
0 ignored issues
show
The function mapi_setprops was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

290
		/** @scrutinizer ignore-call */ 
291
  mapi_setprops($newMessage, $taskItemProps);
Loading history...
291
		mapi_savechanges($newMessage);
292
293
		// Update body of original message
294
		$msgbody = mapi_openproperty($this->message, PR_BODY);
0 ignored issues
show
The function mapi_openproperty was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

294
		$msgbody = /** @scrutinizer ignore-call */ mapi_openproperty($this->message, PR_BODY);
Loading history...
295
		$msgbody = trim($msgbody, "\0");
296
		$separator = "------------\r\n";
297
298
		if (!empty($msgbody) && strrpos($msgbody, $separator) === false) {
299
			$msgbody = $separator . $msgbody;
300
			$stream = mapi_openproperty($this->message, PR_BODY, IID_IStream, STGM_TRANSACTED, 0);
301
			mapi_stream_setsize($stream, strlen($msgbody));
0 ignored issues
show
The function mapi_stream_setsize was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

301
			/** @scrutinizer ignore-call */ 
302
   mapi_stream_setsize($stream, strlen($msgbody));
Loading history...
302
			mapi_stream_write($stream, $msgbody);
0 ignored issues
show
The function mapi_stream_write was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

302
			/** @scrutinizer ignore-call */ 
303
   mapi_stream_write($stream, $msgbody);
Loading history...
303
			mapi_stream_commit($stream);
0 ignored issues
show
The function mapi_stream_commit was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

303
			/** @scrutinizer ignore-call */ 
304
   mapi_stream_commit($stream);
Loading history...
304
		}
305
306
		// We need these properties to notify client
307
		return mapi_getprops($newMessage, [PR_ENTRYID, PR_PARENT_ENTRYID, PR_STORE_ENTRYID]);
308
	}
309
310
	/**
311
	 * processOccurrenceItem, adds an item to a list of occurrences, but only if the
312
	 * resulting occurrence starts or ends in the interval <$start, $end>.
313
	 *
314
	 * @param array $items        reference to the array to be added to
315
	 * @param int   $start        start of timeframe in GMT TIME
316
	 * @param int   $end          end of timeframe in GMT TIME
317
	 * @param int   $basedate     (hour/sec/min assumed to be 00:00:00) in LOCAL TIME OF THE OCCURRENCE
318
	 * @param int   $startocc     start of occurrence since beginning of day in minutes
319
	 * @param int   $endocc       end of occurrence since beginning of day in minutes
320
	 * @param int   $tz           the timezone info for this occurrence ( applied to $basedate / $startocc / $endocc )
321
	 * @param bool  $reminderonly If TRUE, only add the item if the reminder is set
322
	 */
323
	public function processOccurrenceItem(&$items, $start, $end, $basedate, $startocc, $endocc, $tz, $reminderonly) {
324
		if ($basedate > $start) {
325
			$newItem = [];
326
			$newItem[$this->proptags['startdate']] = $basedate;
327
328
			// If startdate and enddate are set on task, then slide enddate according to duration
329
			if (isset($this->messageprops[$this->proptags["startdate"]], $this->messageprops[$this->proptags["duedate"]])) {
330
				$newItem[$this->proptags['duedate']] = $newItem[$this->proptags['startdate']] + ($this->messageprops[$this->proptags["duedate"]] - $this->messageprops[$this->proptags["startdate"]]);
331
			}
332
			else {
333
				$newItem[$this->proptags['duedate']] = $newItem[$this->proptags['startdate']];
334
			}
335
336
			$items[] = $newItem;
337
		}
338
	}
339
340
	/**
341
	 * Function which marks existing occurrence to 'Complete'.
342
	 *
343
	 * @param array $recur array action from client
344
	 *
345
	 * @return array|bool of properties of regenerated task else false
346
	 */
347
	public function markOccurrenceComplete(&$recur) {
348
		// Fix timezone object
349
		$this->tz = false;
350
		$this->action = &$recur;
351
		$dead_occurrence = isset($this->messageprops[$this->proptags['dead_occurrence']]) ? $this->messageprops[$this->proptags['dead_occurrence']] : false;
352
353
		if (!$dead_occurrence) {
354
			return $this->moveToNextOccurrence();
355
		}
356
357
		return false;
358
	}
359
360
	/**
361
	 * Function which sets reminder on recurring task after existing occurrence has been deleted or marked complete.
362
	 *
363
	 * @param mixed $nextOccurrence properties of next occurrence
364
	 */
365
	public function setReminder($nextOccurrence): void {
366
		$props = [];
367
		if (!empty($nextOccurrence)) {
368
			// Check if reminder is reset. Default is 'false'
369
			$reset_reminder = isset($this->messageprops[$this->proptags['reset_reminder']]) ? $this->messageprops[$this->proptags['reset_reminder']] : false;
370
			$reminder = $this->messageprops[$this->proptags['reminder']];
371
372
			// Either reminder was already set OR reminder was set but was dismissed bty user
373
			if ($reminder || $reset_reminder) {
374
				// Reminder can be set at any time either before or after the duedate, so get duration between the reminder time and duedate
375
				$reminder_time = isset($this->messageprops[$this->proptags['reminder_time']]) ? $this->messageprops[$this->proptags['reminder_time']] : 0;
376
				$reminder_difference = isset($this->messageprops[$this->proptags['duedate']]) ? $this->messageprops[$this->proptags['duedate']] : 0;
377
				$reminder_difference = $reminder_difference - $reminder_time;
378
379
				// Apply duration to next calculated duedate
380
				$next_reminder_time = $nextOccurrence[$this->proptags['duedate']] - $reminder_difference;
381
382
				$props[$this->proptags['reminder_time']] = $next_reminder_time;
383
				$props[$this->proptags['flagdueby']] = $next_reminder_time;
384
				$this->action['reminder'] = $props[$this->proptags['reminder']] = true;
385
			}
386
		}
387
		else {
388
			// Didn't get next occurrence, probably this is the last occurrence
389
			$props[$this->proptags['reminder']] = false;
390
			$props[$this->proptags['reset_reminder']] = false;
391
		}
392
393
		if (!empty($props)) {
394
			mapi_setprops($this->message, $props);
0 ignored issues
show
The function mapi_setprops was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

394
			/** @scrutinizer ignore-call */ 
395
   mapi_setprops($this->message, $props);
Loading history...
395
		}
396
	}
397
398
	/**
399
	 * Function which recurring task to next occurrence.
400
	 * It simply doesn't regenerate task.
401
	 *
402
	 * @param array $action
403
	 *
404
	 * @return array|bool
405
	 */
406
	public function deleteOccurrence($action) {
407
		$this->tz = false;
408
		$this->action = $action;
409
		$result = $this->moveToNextOccurrence();
410
411
		mapi_savechanges($this->message);
0 ignored issues
show
The function mapi_savechanges was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

411
		/** @scrutinizer ignore-call */ 
412
  mapi_savechanges($this->message);
Loading history...
412
413
		return $result;
414
	}
415
}
416