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-2024 grommunio GmbH |
||||
6 | */ |
||||
7 | |||||
8 | /* |
||||
9 | * In general |
||||
10 | * |
||||
11 | * This class never actually modifies a task item unless we receive a task request update. This means |
||||
12 | * that setting all the properties to make the task item itself behave like a task request is up to the |
||||
13 | * caller. |
||||
14 | * |
||||
15 | * The only exception to this is the generation of the TaskGlobalObjId, the unique identifier identifying |
||||
16 | * this task request to both the organizer and the assignee. The globalobjectid is generated when the |
||||
17 | * task request is sent via sendTaskRequest. |
||||
18 | */ |
||||
19 | |||||
20 | /* The TaskMode value is only used for the IPM.TaskRequest items. |
||||
21 | * It must 0 (tdmtNothing) on IPM.Task items. |
||||
22 | * |
||||
23 | * It is used to indicate the type of change that is being |
||||
24 | * carried in the IPM.TaskRequest item (although this information seems |
||||
25 | * redundant due to that information already being available in PR_MESSAGE_CLASS). |
||||
26 | */ |
||||
27 | define('tdmtNothing', 0); // Value in IPM.Task items |
||||
28 | define('tdmtTaskReq', 1); // Assigner -> Assignee |
||||
29 | define('tdmtTaskAcc', 2); // Assignee -> Assigner |
||||
30 | define('tdmtTaskDec', 3); // Assignee -> Assigner |
||||
31 | define('tdmtTaskUpd', 4); // Assignee -> Assigner |
||||
32 | define('tdmtTaskSELF', 5); // Assigner -> Assigner (?) |
||||
33 | |||||
34 | /* The TaskHistory is used to show the last action on the task |
||||
35 | * on both the assigner and the assignee's side. |
||||
36 | * |
||||
37 | * It is used in combination with 'task_assigned_time' and 'tasklastdelegate' |
||||
38 | * or 'tasklastuser' to show the information at the top of the task request in |
||||
39 | * the format 'Accepted by <user> on 01-01-2010 11:00'. |
||||
40 | */ |
||||
41 | define('thNone', 0); |
||||
42 | define('thAccepted', 1); // Set by assignee |
||||
43 | define('thDeclined', 2); // Set by assignee |
||||
44 | define('thUpdated', 3); // Set by assignee |
||||
45 | define('thDueDateChanged', 4); |
||||
46 | define('thAssigned', 5); // Set by assigner |
||||
47 | |||||
48 | /* The TaskState value is used to differentiate the version of a task |
||||
49 | * in the assigner's folder and the version in the |
||||
50 | * assignee's folder. The buttons shown depend on this and |
||||
51 | * the 'taskaccepted' boolean (for the assignee) |
||||
52 | */ |
||||
53 | define('tdsNOM', 0); // Got a response to a deleted task, and re-created the task for the assigner |
||||
54 | define('tdsOWNNEW', 1); // Not assigned |
||||
55 | define('tdsOWN', 2); // Assignee version |
||||
56 | define('tdsACC', 3); // Assigner version |
||||
57 | define('tdsDEC', 4); // Assigner version, but assignee declined |
||||
58 | |||||
59 | /* The TaskAcceptanceState is used for the assigner to indicate state */ |
||||
60 | define('olTaskNotDelegated', 0); |
||||
61 | define('olTaskDelegationUnknown', 1); // After sending req |
||||
62 | define('olTaskDelegationAccepted', 2); // After receiving accept |
||||
63 | define('olTaskDelegationDeclined', 3); // After receiving decline |
||||
64 | |||||
65 | /* The task ownership indicates the role of the current user relative to the task. */ |
||||
66 | define('olNewTask', 0); |
||||
67 | define('olDelegatedTask', 1); // Task has been assigned |
||||
68 | define('olOwnTask', 2); // Task owned |
||||
69 | |||||
70 | /* taskmultrecips indicates whether the task request sent or received has multiple assignees or not. */ |
||||
71 | define('tmrNone', 0); |
||||
72 | define('tmrSent', 1); // Task has been sent to multiple assignee |
||||
73 | define('tmrReceived', 2); // Task Request received has multiple assignee |
||||
74 | |||||
75 | // Task icon index. |
||||
76 | define('ICON_TASK_ASSIGNEE', 0x00000502); |
||||
77 | define('ICON_TASK_DECLINE', 0x00000506); |
||||
78 | define('ICON_TASK_ASSIGNER', 0x00000503); |
||||
79 | |||||
80 | class TaskRequest { |
||||
81 | private $props; |
||||
82 | |||||
83 | /** |
||||
84 | * @var resource |
||||
85 | */ |
||||
86 | private $store; |
||||
87 | |||||
88 | /** |
||||
89 | * @var resource |
||||
90 | */ |
||||
91 | private $message; |
||||
92 | |||||
93 | /** |
||||
94 | * @var resource |
||||
95 | */ |
||||
96 | private $session; |
||||
97 | |||||
98 | /** |
||||
99 | * @var string |
||||
100 | */ |
||||
101 | private $taskCommentsInfo; |
||||
102 | |||||
103 | // All recipient properties |
||||
104 | public $recipProps = [ |
||||
105 | PR_ENTRYID, |
||||
106 | PR_DISPLAY_NAME, |
||||
107 | PR_EMAIL_ADDRESS, |
||||
108 | PR_RECIPIENT_ENTRYID, |
||||
109 | PR_RECIPIENT_TYPE, |
||||
110 | PR_SEND_INTERNET_ENCODING, |
||||
111 | PR_SEND_RICH_INFO, |
||||
112 | PR_RECIPIENT_DISPLAY_NAME, |
||||
113 | PR_ADDRTYPE, |
||||
114 | PR_DISPLAY_TYPE, |
||||
115 | PR_RECIPIENT_TRACKSTATUS, |
||||
116 | PR_RECIPIENT_TRACKSTATUS_TIME, |
||||
117 | PR_RECIPIENT_FLAGS, |
||||
118 | PR_ROWID, |
||||
119 | PR_SEARCH_KEY, |
||||
120 | ]; |
||||
121 | |||||
122 | /** |
||||
123 | * Constructor. |
||||
124 | * |
||||
125 | * Constructs a TaskRequest object for the specified message. This can be either the task request |
||||
126 | * message itself (in the inbox) or the task in the tasks folder, depending on the action to be performed. |
||||
127 | * |
||||
128 | * As a general rule, the object message passed is the object 'in view' when the user performs one of the |
||||
129 | * actions in this class. |
||||
130 | * |
||||
131 | * @param resource $store MAPI Store in which $message resides. This is also the store where the tasks folder is assumed to be in |
||||
132 | * @param resource $message MAPI Message to which the task request refers (can be an email or a task) |
||||
133 | * @param resource $session MAPI Session which is used to open tasks folders for delegated task requests or responses |
||||
134 | */ |
||||
135 | public function __construct($store, $message, $session) { |
||||
136 | $this->store = $store; |
||||
137 | $this->message = $message; |
||||
138 | $this->session = $session; |
||||
139 | $this->taskCommentsInfo = ''; |
||||
140 | |||||
141 | $properties = []; |
||||
142 | $properties["owner"] = "PT_STRING8:PSETID_Task:0x811f"; |
||||
143 | $properties["updatecount"] = "PT_LONG:PSETID_Task:0x8112"; |
||||
144 | $properties["taskstate"] = "PT_LONG:PSETID_Task:0x8113"; |
||||
145 | $properties["taskmultrecips"] = "PT_LONG:PSETID_Task:0x8120"; |
||||
146 | $properties["taskupdates"] = "PT_BOOLEAN:PSETID_Task:0x811b"; |
||||
147 | $properties["tasksoc"] = "PT_BOOLEAN:PSETID_Task:0x8119"; |
||||
148 | $properties["taskhistory"] = "PT_LONG:PSETID_Task:0x811a"; |
||||
149 | $properties["taskmode"] = "PT_LONG:PSETID_Common:0x8518"; |
||||
150 | $properties["task_goid"] = "PT_BINARY:PSETID_Common:0x8519"; |
||||
151 | $properties["complete"] = "PT_BOOLEAN:PSETID_Common:" . PidLidTaskComplete; |
||||
152 | $properties["task_assigned_time"] = "PT_SYSTIME:PSETID_Task:0x8115"; |
||||
153 | $properties["taskfcreator"] = "PT_BOOLEAN:PSETID_Task:0x0x811e"; |
||||
154 | $properties["tasklastuser"] = "PT_STRING8:PSETID_Task:0x8122"; |
||||
155 | $properties["tasklastdelegate"] = "PT_STRING8:PSETID_Task:0x8125"; |
||||
156 | $properties["taskaccepted"] = "PT_BOOLEAN:PSETID_Task:0x8108"; |
||||
157 | $properties["task_acceptance_state"] = "PT_LONG:PSETID_Task:0x812a"; |
||||
158 | $properties["ownership"] = "PT_LONG:PSETID_Task:0x8129"; |
||||
159 | |||||
160 | $properties["complete"] = "PT_BOOLEAN:PSETID_Task:" . PidLidTaskComplete; |
||||
161 | $properties["datecompleted"] = "PT_SYSTIME:PSETID_Task:" . PidLidTaskDateCompleted; |
||||
162 | $properties["recurring"] = "PT_BOOLEAN:PSETID_Task:0x8126"; |
||||
163 | $properties["startdate"] = "PT_SYSTIME:PSETID_Task:" . PidLidTaskStartDate; |
||||
164 | $properties["duedate"] = "PT_SYSTIME:PSETID_Task:" . PidLidTaskDueDate; |
||||
165 | $properties["status"] = "PT_LONG:PSETID_Task:" . PidLidTaskStatus; |
||||
166 | $properties["percent_complete"] = "PT_DOUBLE:PSETID_Task:" . PidLidPercentComplete; |
||||
167 | $properties["totalwork"] = "PT_LONG:PSETID_Task:0x8111"; |
||||
168 | $properties["actualwork"] = "PT_LONG:PSETID_Task:0x8110"; |
||||
169 | $properties["categories"] = "PT_MV_STRING8:PS_PUBLIC_STRINGS:Keywords"; |
||||
170 | $properties["companies"] = "PT_MV_STRING8:PSETID_Common:0x8539"; |
||||
171 | $properties["mileage"] = "PT_STRING8:PSETID_Common:0x8534"; |
||||
172 | $properties["billinginformation"] = "PT_STRING8:PSETID_Common:0x8535"; |
||||
173 | |||||
174 | $this->props = getPropIdsFromStrings($store, $properties); |
||||
175 | } |
||||
176 | |||||
177 | // General functions |
||||
178 | |||||
179 | /** |
||||
180 | * Returns TRUE if the message pointed to is an incoming task request and should |
||||
181 | * therefore be replied to with doAccept or doDecline(). |
||||
182 | * |
||||
183 | * @param mixed $messageClass message class to use for checking |
||||
184 | * |
||||
185 | * @return bool true if this is a task request else false |
||||
186 | */ |
||||
187 | public function isTaskRequest($messageClass = false) { |
||||
188 | if ($messageClass === false) { |
||||
189 | $props = mapi_getprops($this->message, [PR_MESSAGE_CLASS]); |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
190 | $messageClass = isset($props[PR_MESSAGE_CLASS]) ? $props[PR_MESSAGE_CLASS] : false; |
||||
191 | } |
||||
192 | |||||
193 | if ($messageClass !== false && $messageClass === "IPM.TaskRequest") { |
||||
194 | return true; |
||||
195 | } |
||||
196 | |||||
197 | return false; |
||||
198 | } |
||||
199 | |||||
200 | /** |
||||
201 | * Returns TRUE if the message pointed to is a returning task request response. |
||||
202 | * |
||||
203 | * @param mixed $messageClass message class to use for checking |
||||
204 | * |
||||
205 | * @return bool true if this is a task request else false |
||||
206 | */ |
||||
207 | public function isTaskRequestResponse($messageClass = false) { |
||||
208 | if ($messageClass === false) { |
||||
209 | $props = mapi_getprops($this->message, [PR_MESSAGE_CLASS]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
210 | $messageClass = isset($props[PR_MESSAGE_CLASS]) ? $props[PR_MESSAGE_CLASS] : false; |
||||
211 | } |
||||
212 | |||||
213 | if ($messageClass !== false && strpos($messageClass, "IPM.TaskRequest.") === 0) { |
||||
214 | return true; |
||||
215 | } |
||||
216 | |||||
217 | return false; |
||||
218 | } |
||||
219 | |||||
220 | /** |
||||
221 | * Returns TRUE if the message pointed to is an incoming task request/response. |
||||
222 | * |
||||
223 | * @param array $props The MAPI properties to check message is an incoming task request/response |
||||
224 | * |
||||
225 | * @return bool true if this is an incoming task request/response else false |
||||
226 | */ |
||||
227 | public function isReceivedItem($props) { |
||||
228 | return isset($props[PR_MESSAGE_TO_ME]) ? $props[PR_MESSAGE_TO_ME] : false; |
||||
229 | } |
||||
230 | |||||
231 | /** |
||||
232 | * Gets the task associated with an IPM.TaskRequest message. |
||||
233 | * |
||||
234 | * If the task does not exist yet, it is created, using the attachment object in the |
||||
235 | * task request item. |
||||
236 | * |
||||
237 | * @param bool $create true - try create task in user's task folder if task does not exist |
||||
238 | * false - find the associated task in user's task folder |
||||
239 | * |
||||
240 | * @return bool|resource associated task of task request else false |
||||
241 | */ |
||||
242 | public function getAssociatedTask($create) { |
||||
243 | $props = mapi_getprops($this->message, [PR_MESSAGE_CLASS, $this->props['task_goid']]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
244 | |||||
245 | if ($props[PR_MESSAGE_CLASS] == "IPM.Task") { |
||||
246 | // Message itself is task, so return that |
||||
247 | return $this->message; |
||||
248 | } |
||||
249 | |||||
250 | $taskFolder = $this->getDefaultTasksFolder(); |
||||
251 | $goid = $props[$this->props['task_goid']]; |
||||
252 | |||||
253 | // Find the task by looking for the task_goid |
||||
254 | $restriction = [ |
||||
255 | RES_PROPERTY, |
||||
256 | [ |
||||
257 | RELOP => RELOP_EQ, |
||||
258 | ULPROPTAG => $this->props['task_goid'], |
||||
259 | VALUE => $goid, |
||||
260 | ], |
||||
261 | ]; |
||||
262 | |||||
263 | $contents = mapi_folder_getcontentstable($taskFolder); |
||||
0 ignored issues
–
show
It seems like
$taskFolder can also be of type false ; however, parameter $fld of mapi_folder_getcontentstable() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
264 | |||||
265 | $rows = mapi_table_queryallrows($contents, [PR_ENTRYID], $restriction); |
||||
266 | |||||
267 | if (empty($rows)) { |
||||
268 | // None found, create one if possible |
||||
269 | if (!$create) { |
||||
270 | return false; |
||||
271 | } |
||||
272 | |||||
273 | $task = mapi_folder_createmessage($taskFolder); |
||||
0 ignored issues
–
show
It seems like
$taskFolder can also be of type false ; however, parameter $fld of mapi_folder_createmessage() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
274 | |||||
275 | $sub = $this->getEmbeddedTask(); |
||||
276 | mapi_copyto($sub, [], [$this->props['categories']], $task); |
||||
0 ignored issues
–
show
$sub of type boolean|resource is incompatible with the type resource expected by parameter $src of mapi_copyto() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
277 | |||||
278 | $senderProps = [ |
||||
279 | PR_SENT_REPRESENTING_NAME, |
||||
280 | PR_SENT_REPRESENTING_EMAIL_ADDRESS, |
||||
281 | PR_SENT_REPRESENTING_ENTRYID, |
||||
282 | PR_SENT_REPRESENTING_ADDRTYPE, |
||||
283 | PR_SENT_REPRESENTING_SEARCH_KEY, |
||||
284 | PR_SENDER_NAME, |
||||
285 | PR_SENDER_EMAIL_ADDRESS, |
||||
286 | PR_SENDER_ENTRYID, |
||||
287 | PR_SENDER_ADDRTYPE, |
||||
288 | PR_SENDER_SEARCH_KEY, ]; |
||||
289 | |||||
290 | // Copy sender information from the e-mail |
||||
291 | $props = mapi_getprops($this->message, $senderProps); |
||||
292 | $props[PR_MESSAGE_CLASS] = 'IPM.Task'; |
||||
293 | mapi_setprops($task, $props); |
||||
294 | } |
||||
295 | else { |
||||
296 | // If there are multiple, just use the first |
||||
297 | $entryid = $rows[0][PR_ENTRYID]; |
||||
298 | |||||
299 | $store = $this->getTaskFolderStore(); |
||||
300 | $task = mapi_msgstore_openentry($store, $entryid); |
||||
0 ignored issues
–
show
It seems like
$store can also be of type false and resource ; however, parameter $store of mapi_msgstore_openentry() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
301 | } |
||||
302 | |||||
303 | return $task; |
||||
0 ignored issues
–
show
|
|||||
304 | } |
||||
305 | |||||
306 | /** |
||||
307 | * Function which checks that if we have received a task request/response |
||||
308 | * for an already updated task in task folder. |
||||
309 | * |
||||
310 | * @return bool true if task request is updated later |
||||
311 | */ |
||||
312 | public function isTaskRequestUpdated() { |
||||
313 | $props = mapi_getprops($this->message, [PR_MESSAGE_CLASS, $this->props['task_goid'], $this->props['updatecount']]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
314 | $result = false; |
||||
315 | $associatedTask = $this->getAssociatedTask(false); |
||||
316 | if ($this->isTaskRequest($props[PR_MESSAGE_CLASS])) { |
||||
317 | if ($associatedTask) { |
||||
0 ignored issues
–
show
|
|||||
318 | return true; |
||||
319 | } |
||||
320 | $folder = $this->getDefaultTasksFolder(); |
||||
321 | $goid = $props[$this->props['task_goid']]; |
||||
322 | |||||
323 | // Find the task by looking for the task_goid |
||||
324 | $restriction = [ |
||||
325 | RES_PROPERTY, |
||||
326 | [ |
||||
327 | RELOP => RELOP_EQ, |
||||
328 | ULPROPTAG => $this->props['task_goid'], |
||||
329 | VALUE => $goid, |
||||
330 | ], |
||||
331 | ]; |
||||
332 | |||||
333 | $table = mapi_folder_getcontentstable($folder, MAPI_DEFERRED_ERRORS | SHOW_SOFT_DELETES); |
||||
0 ignored issues
–
show
It seems like
$folder can also be of type false ; however, parameter $fld of mapi_folder_getcontentstable() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
334 | $softDeletedItems = mapi_table_queryallrows($table, [PR_ENTRYID], $restriction); |
||||
335 | if (!empty($softDeletedItems)) { |
||||
336 | return true; |
||||
337 | } |
||||
338 | } |
||||
339 | |||||
340 | if ($associatedTask !== false) { |
||||
0 ignored issues
–
show
|
|||||
341 | $taskItemProps = mapi_getprops($associatedTask, [$this->props['updatecount']]); |
||||
342 | /* |
||||
343 | * if(message_counter < task_counter) task object is newer then task response (task is updated) |
||||
344 | * if(message_counter >= task_counter) task is not updated, do normal processing |
||||
345 | */ |
||||
346 | if (isset($taskItemProps[$this->props['updatecount']], $props[$this->props['updatecount']])) { |
||||
347 | if ($props[$this->props['updatecount']] < $taskItemProps[$this->props['updatecount']]) { |
||||
348 | $result = true; |
||||
349 | } |
||||
350 | } |
||||
351 | } |
||||
352 | |||||
353 | return $result; |
||||
354 | } |
||||
355 | |||||
356 | // Organizer functions (called by the organizer) |
||||
357 | |||||
358 | /** |
||||
359 | * Processes a task request response, which can be any of the following: |
||||
360 | * - Task accept (task history is marked as accepted) |
||||
361 | * - Task decline (task history is marked as declined) |
||||
362 | * - Task update (updates completion %, etc). |
||||
363 | * |
||||
364 | * @return true |
||||
365 | */ |
||||
366 | public function processTaskResponse(): bool { |
||||
367 | $messageProps = mapi_getprops($this->message, [PR_PROCESSED, $this->props["taskupdates"], PR_MESSAGE_TO_ME]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
368 | if (isset($messageProps[PR_PROCESSED]) && $messageProps[PR_PROCESSED]) { |
||||
369 | return true; |
||||
370 | } |
||||
371 | mapi_setprops($this->message, [PR_PROCESSED => true]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_setprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
372 | mapi_savechanges($this->message); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_savechanges() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
373 | |||||
374 | // Get the embedded task information. |
||||
375 | $sub = $this->getEmbeddedTask(); |
||||
376 | // OL saves the task related properties in the embedded message |
||||
377 | $subProps = mapi_getprops($sub, [$this->props["taskupdates"]]); |
||||
0 ignored issues
–
show
$sub of type boolean|resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
378 | |||||
379 | // If task is updated in task folder then we don't need to process |
||||
380 | // old response |
||||
381 | if ($this->isTaskRequestUpdated()) { |
||||
382 | return true; |
||||
383 | } |
||||
384 | |||||
385 | $isReceivedItem = $this->isReceivedItem($messageProps); |
||||
386 | |||||
387 | $taskHistory = 0; |
||||
388 | $taskState = 0; |
||||
389 | $taskAcceptanceState = 0; |
||||
390 | $taskOwner = 0; |
||||
391 | $isCreateAssociatedTask = false; |
||||
392 | $isAllowUpdateAssociatedTask = $subProps[$this->props["taskupdates"]]; |
||||
393 | $props = mapi_getprops($this->message, [PR_MESSAGE_CLASS]); |
||||
394 | |||||
395 | // Set correct taskmode and taskhistory depending on response type |
||||
396 | switch ($props[PR_MESSAGE_CLASS]) { |
||||
397 | case 'IPM.TaskRequest.Accept': |
||||
398 | $taskHistory = thAccepted; |
||||
399 | $taskState = $isReceivedItem ? tdsACC : tdsOWN; |
||||
400 | $taskOwner = $isReceivedItem ? olDelegatedTask : olOwnTask; |
||||
401 | $taskAcceptanceState = $isReceivedItem ? olTaskDelegationAccepted : olTaskNotDelegated; |
||||
402 | break; |
||||
403 | |||||
404 | case 'IPM.TaskRequest.Decline': |
||||
405 | $isCreateAssociatedTask = $isReceivedItem; |
||||
406 | $isAllowUpdateAssociatedTask = $isReceivedItem; |
||||
407 | $taskHistory = thDeclined; |
||||
408 | $taskState = $isReceivedItem ? tdsDEC : tdsACC; |
||||
409 | $taskOwner = $isReceivedItem ? olOwnTask : olDelegatedTask; |
||||
410 | $taskAcceptanceState = $isReceivedItem ? olTaskDelegationDeclined : olTaskDelegationUnknown; |
||||
411 | break; |
||||
412 | |||||
413 | case 'IPM.TaskRequest.Update': |
||||
414 | case 'IPM.TaskRequest.Complete': |
||||
415 | $taskHistory = thUpdated; |
||||
416 | $taskState = $isReceivedItem ? tdsACC : tdsOWN; |
||||
417 | $taskAcceptanceState = olTaskNotDelegated; |
||||
418 | $taskOwner = $isReceivedItem ? olDelegatedTask : olOwnTask; |
||||
419 | break; |
||||
420 | } |
||||
421 | |||||
422 | $props = [ |
||||
423 | $this->props['taskhistory'] => $taskHistory, |
||||
424 | $this->props['taskstate'] => $taskState, |
||||
425 | $this->props['task_acceptance_state'] => $taskAcceptanceState, |
||||
426 | $this->props['ownership'] => $taskOwner, |
||||
427 | ]; |
||||
428 | |||||
429 | // Get the task for this response |
||||
430 | $task = $this->getAssociatedTask($isCreateAssociatedTask); |
||||
431 | if ($task && $isAllowUpdateAssociatedTask) { |
||||
0 ignored issues
–
show
|
|||||
432 | // To avoid duplication of attachments in associated task. we simple remove the |
||||
433 | // all attachments from associated task. |
||||
434 | $taskAttachTable = mapi_message_getattachmenttable($task); |
||||
435 | $taskAttachments = mapi_table_queryallrows($taskAttachTable, [PR_ATTACH_NUM]); |
||||
436 | foreach ($taskAttachments as $taskAttach) { |
||||
437 | mapi_message_deleteattach($task, $taskAttach[PR_ATTACH_NUM]); |
||||
438 | } |
||||
439 | |||||
440 | $ignoreProps = [ |
||||
441 | $this->props['taskstate'], |
||||
442 | $this->props['taskhistory'], |
||||
443 | $this->props['taskmode'], |
||||
444 | $this->props['taskfcreator'], |
||||
445 | ]; |
||||
446 | // Ignore PR_ICON_INDEX when task request response |
||||
447 | // is not received item. |
||||
448 | if ($isReceivedItem === false) { |
||||
449 | $ignoreProps[] = PR_ICON_INDEX; |
||||
450 | } |
||||
451 | |||||
452 | // We copy all properties except taskstate, taskhistory, taskmode and taskfcreator properties |
||||
453 | // from $sub message to $task even also we copy all attachments from $sub to $task message. |
||||
454 | mapi_copyto($sub, [], $ignoreProps, $task); |
||||
455 | $senderProps = mapi_getprops($this->message, [ |
||||
456 | PR_SENDER_NAME, |
||||
457 | PR_SENDER_EMAIL_ADDRESS, |
||||
458 | PR_SENDER_ENTRYID, |
||||
459 | PR_SENDER_ADDRTYPE, |
||||
460 | PR_SENDER_SEARCH_KEY, |
||||
461 | PR_MESSAGE_DELIVERY_TIME, |
||||
462 | PR_SENT_REPRESENTING_NAME, |
||||
463 | PR_SENT_REPRESENTING_EMAIL_ADDRESS, |
||||
464 | PR_SENT_REPRESENTING_ADDRTYPE, |
||||
465 | PR_SENT_REPRESENTING_ENTRYID, |
||||
466 | PR_SENT_REPRESENTING_SEARCH_KEY, ]); |
||||
467 | |||||
468 | mapi_setprops($task, $senderProps); |
||||
469 | |||||
470 | // Update taskstate and task history (last action done by the assignee) |
||||
471 | mapi_setprops($task, $props); |
||||
472 | |||||
473 | // Copy missing properties from embedded task |
||||
474 | $subProperties = $this->getSubProperties(); |
||||
475 | $subprops = mapi_getprops($sub, $subProperties); |
||||
476 | mapi_setprops($task, $subprops); |
||||
477 | |||||
478 | mapi_savechanges($task); |
||||
479 | } |
||||
480 | |||||
481 | mapi_setprops($this->message, $props); |
||||
482 | mapi_savechanges($this->message); |
||||
483 | |||||
484 | if ($isReceivedItem) { |
||||
485 | $this->updateSentTaskRequest(); |
||||
486 | } |
||||
487 | |||||
488 | return true; |
||||
489 | } |
||||
490 | |||||
491 | /** |
||||
492 | * Update the sent task request in sent items folder. |
||||
493 | * |
||||
494 | * @return bool |
||||
495 | */ |
||||
496 | public function updateSentTaskRequest() { |
||||
497 | $props = mapi_getprops($this->message, [ |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
498 | $this->props['taskhistory'], |
||||
499 | $this->props["taskstate"], |
||||
500 | $this->props["ownership"], |
||||
501 | $this->props['task_goid'], |
||||
502 | $this->props['task_acceptance_state'], |
||||
503 | $this->props["tasklastuser"], |
||||
504 | $this->props["tasklastdelegate"], ]); |
||||
505 | |||||
506 | $store = $this->getDefaultStore(); |
||||
507 | $storeProps = mapi_getprops($store, [PR_IPM_SENTMAIL_ENTRYID]); |
||||
0 ignored issues
–
show
It seems like
$store can also be of type false ; however, parameter $any of mapi_getprops() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
508 | |||||
509 | $sentFolder = mapi_msgstore_openentry($store, $storeProps[PR_IPM_SENTMAIL_ENTRYID]); |
||||
0 ignored issues
–
show
It seems like
$store can also be of type false ; however, parameter $store of mapi_msgstore_openentry() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
510 | if (!$sentFolder) { |
||||
0 ignored issues
–
show
|
|||||
511 | return false; |
||||
512 | } |
||||
513 | |||||
514 | // Find the task by looking for the task_goid |
||||
515 | $restriction = [ |
||||
516 | RES_PROPERTY, |
||||
517 | [ |
||||
518 | RELOP => RELOP_EQ, |
||||
519 | ULPROPTAG => $this->props['task_goid'], |
||||
520 | VALUE => $props[$this->props['task_goid']], |
||||
521 | ], |
||||
522 | ]; |
||||
523 | |||||
524 | $contentsTable = mapi_folder_getcontentstable($sentFolder); |
||||
525 | |||||
526 | $rows = mapi_table_queryallrows($contentsTable, [PR_ENTRYID], $restriction); |
||||
527 | |||||
528 | if (!empty($rows)) { |
||||
529 | foreach ($rows as $row) { |
||||
530 | $sentTaskRequest = mapi_msgstore_openentry($store, $row[PR_ENTRYID]); |
||||
531 | mapi_setprops($sentTaskRequest, $props); |
||||
532 | mapi_setprops($sentTaskRequest, [PR_PROCESSED => true]); |
||||
533 | mapi_savechanges($sentTaskRequest); |
||||
534 | } |
||||
535 | } |
||||
536 | |||||
537 | return true; |
||||
538 | } |
||||
539 | |||||
540 | /** |
||||
541 | * Creates a new message in the current user's outbox and submits it. |
||||
542 | * |
||||
543 | * Takes the task passed in the constructor as the task to be sent; recipient should |
||||
544 | * be pre-existing. The task request will be sent to all recipients. |
||||
545 | * |
||||
546 | * @param string $prefix |
||||
547 | * |
||||
548 | * @return true |
||||
549 | */ |
||||
550 | public function sendTaskRequest($prefix): bool { |
||||
551 | // Generate a TaskGlobalObjectId |
||||
552 | $taskid = $this->createTGOID(); |
||||
553 | $messageprops = mapi_getprops($this->message, [PR_SUBJECT]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
554 | |||||
555 | // Set properties on Task Request |
||||
556 | mapi_setprops($this->message, [ |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_setprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
557 | $this->props['task_goid'] => $taskid, // our new task_goid |
||||
558 | $this->props['taskstate'] => tdsACC, // state for our outgoing request |
||||
559 | $this->props['taskmode'] => tdmtNothing, // we're not sending a change |
||||
560 | $this->props['updatecount'] => 2, // version 2 (no idea) |
||||
561 | $this->props['task_acceptance_state'] => olTaskDelegationUnknown, // no reply yet |
||||
562 | $this->props['ownership'] => olDelegatedTask, // Task has been assigned |
||||
563 | $this->props['taskhistory'] => thAssigned, // Task has been assigned |
||||
564 | PR_CONVERSATION_TOPIC => $messageprops[PR_SUBJECT], |
||||
565 | PR_ICON_INDEX => ICON_TASK_ASSIGNER, |
||||
566 | ]); |
||||
567 | $this->setLastUser(); |
||||
568 | $this->setOwnerForAssignor(); |
||||
569 | mapi_savechanges($this->message); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_savechanges() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
570 | |||||
571 | // Create outgoing task request message |
||||
572 | $outgoing = $this->createOutgoingMessage(); |
||||
573 | |||||
574 | // No need to copy PR_ICON_INDEX and PR_SENT_* information in to outgoing message. |
||||
575 | $ignoreProps = [PR_ICON_INDEX, PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_EMAIL_ADDRESS, PR_SENT_REPRESENTING_ADDRTYPE, PR_SENT_REPRESENTING_ENTRYID, PR_SENT_REPRESENTING_SEARCH_KEY]; |
||||
576 | mapi_copyto($this->message, [], $ignoreProps, $outgoing); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $src of mapi_copyto() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
577 | |||||
578 | // Make it a task request, and put it in sent items after it is sent |
||||
579 | mapi_setprops($outgoing, [ |
||||
580 | PR_MESSAGE_CLASS => "IPM.TaskRequest", // class is task request |
||||
581 | $this->props['taskstate'] => tdsOWN, // for the recipient he is the task owner |
||||
582 | $this->props['taskmode'] => tdmtTaskReq, // for the recipient it's a request |
||||
583 | $this->props['updatecount'] => 1, // version 2 is in the attachment |
||||
584 | PR_SUBJECT_PREFIX => $prefix, |
||||
585 | PR_SUBJECT => $prefix . $messageprops[PR_SUBJECT], |
||||
586 | ]); |
||||
587 | |||||
588 | $attach = mapi_message_createattach($outgoing); |
||||
589 | mapi_setprops($attach, [ |
||||
590 | PR_ATTACH_METHOD => ATTACH_EMBEDDED_MSG, |
||||
591 | PR_ATTACHMENT_HIDDEN => true, |
||||
592 | PR_DISPLAY_NAME => $messageprops[PR_SUBJECT], ]); |
||||
593 | |||||
594 | $sub = mapi_attach_openproperty($attach, PR_ATTACH_DATA_OBJ, IID_IMessage, 0, MAPI_MODIFY | MAPI_CREATE); |
||||
0 ignored issues
–
show
The function
mapi_attach_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
![]() |
|||||
595 | |||||
596 | mapi_copyto($this->message, [], [], $sub); |
||||
597 | mapi_setprops($sub, [PR_MESSAGE_CLASS => 'IPM.Task']); |
||||
598 | |||||
599 | mapi_savechanges($sub); |
||||
600 | |||||
601 | mapi_savechanges($attach); |
||||
602 | |||||
603 | mapi_savechanges($outgoing); |
||||
604 | mapi_message_submitmessage($outgoing); |
||||
605 | |||||
606 | return true; |
||||
607 | } |
||||
608 | |||||
609 | // Assignee functions (called by the assignee) |
||||
610 | |||||
611 | /** |
||||
612 | * Updates task version counter. |
||||
613 | * |
||||
614 | * Must be called before each update to increase counter. |
||||
615 | */ |
||||
616 | public function updateTaskRequest(): void { |
||||
617 | $messageprops = mapi_getprops($this->message, [$this->props['updatecount']]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
618 | |||||
619 | if (isset($messageprops)) { |
||||
620 | ++$messageprops[$this->props['updatecount']]; |
||||
621 | } |
||||
622 | else { |
||||
623 | $messageprops[$this->props['updatecount']] = 1; |
||||
624 | } |
||||
625 | |||||
626 | mapi_setprops($this->message, $messageprops); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_setprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
627 | } |
||||
628 | |||||
629 | /** |
||||
630 | * Processes a task request. |
||||
631 | * |
||||
632 | * Message passed should be an IPM.TaskRequest message. The task request is then processed to create |
||||
633 | * the task in the tasks folder if needed. |
||||
634 | * |
||||
635 | * @return bool |
||||
636 | */ |
||||
637 | public function processTaskRequest() { |
||||
638 | if (!$this->isTaskRequest()) { |
||||
639 | return false; |
||||
640 | } |
||||
641 | $messageProps = mapi_getprops($this->message, [PR_PROCESSED, $this->props["taskupdates"], PR_MESSAGE_TO_ME]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
642 | if (isset($messageProps[PR_PROCESSED]) && $messageProps[PR_PROCESSED]) { |
||||
643 | return true; |
||||
644 | } |
||||
645 | |||||
646 | // if task is updated in task folder then we don't need to process |
||||
647 | // old request. |
||||
648 | if ($this->isTaskRequestUpdated()) { |
||||
649 | return true; |
||||
650 | } |
||||
651 | |||||
652 | $isReceivedItem = $this->isReceivedItem($messageProps); |
||||
653 | |||||
654 | $props = []; |
||||
655 | $props[PR_PROCESSED] = true; |
||||
656 | $props[$this->props["taskstate"]] = $isReceivedItem ? tdsOWN : tdsACC; |
||||
657 | $props[$this->props["ownership"]] = $isReceivedItem ? olOwnTask : olDelegatedTask; |
||||
658 | |||||
659 | mapi_setprops($this->message, $props); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_setprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
660 | mapi_savechanges($this->message); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_savechanges() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
661 | |||||
662 | // Don't create associated task in task folder if "taskupdates" is not true. |
||||
663 | if (!$isReceivedItem && !$messageProps[$this->props["taskupdates"]]) { |
||||
664 | return true; |
||||
665 | } |
||||
666 | // create an associated task in task folder while |
||||
667 | // reading/loading task request on client side. |
||||
668 | $task = $this->getAssociatedTask(true); |
||||
669 | |||||
670 | $taskProps = mapi_getprops($task, [$this->props['taskmultrecips']]); |
||||
671 | $taskProps[$this->props["taskstate"]] = $isReceivedItem ? tdsOWN : tdsACC; |
||||
672 | $taskProps[$this->props["taskhistory"]] = thAssigned; |
||||
673 | $taskProps[$this->props["taskmode"]] = tdmtNothing; |
||||
674 | $taskProps[$this->props["taskaccepted"]] = false; |
||||
675 | $taskProps[$this->props["taskfcreator"]] = false; |
||||
676 | $taskProps[$this->props["ownership"]] = $isReceivedItem ? olOwnTask : olDelegatedTask; |
||||
677 | $taskProps[$this->props["task_acceptance_state"]] = olTaskNotDelegated; |
||||
678 | $taskProps[PR_ICON_INDEX] = ICON_TASK_ASSIGNEE; |
||||
679 | |||||
680 | mapi_setprops($task, $taskProps); |
||||
681 | $this->setAssignorInRecipients($task); |
||||
682 | |||||
683 | mapi_savechanges($task); |
||||
684 | |||||
685 | return true; |
||||
686 | } |
||||
687 | |||||
688 | /** |
||||
689 | * Accepts a task request and sends the response. |
||||
690 | * |
||||
691 | * Message passed should be an IPM.Task (eg the task from getAssociatedTask()) |
||||
692 | * |
||||
693 | * Copies the task to the user's task folder, sets it to accepted, and sends the acceptation |
||||
694 | * message back to the organizer. The caller is responsible for removing the message. |
||||
695 | * |
||||
696 | * @return array|false PR_ENTRYID, PR_STORE_ENTRYID and PR_PARENT_ENTRYID of the task |
||||
697 | */ |
||||
698 | public function doAccept() { |
||||
699 | $prefix = _("Task Accepted:") . " "; |
||||
700 | $messageProps = mapi_getprops($this->message, [PR_MESSAGE_CLASS, $this->props['taskstate']]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
701 | |||||
702 | if (!isset($messageProps[$this->props['taskstate']]) || $messageProps[$this->props['taskstate']] != tdsOWN) { |
||||
703 | // Can only accept assignee task |
||||
704 | return false; |
||||
705 | } |
||||
706 | |||||
707 | $this->setLastUser(); |
||||
708 | $this->updateTaskRequest(); |
||||
709 | |||||
710 | $props = [ |
||||
711 | $this->props['taskhistory'] => thAccepted, |
||||
712 | $this->props['task_assigned_time'] => time(), |
||||
713 | $this->props['taskaccepted'] => true, |
||||
714 | $this->props['task_acceptance_state'] => olTaskNotDelegated, ]; |
||||
715 | |||||
716 | // Message is TaskRequest then update the associated task as well. |
||||
717 | if ($this->isTaskRequest($messageProps[PR_MESSAGE_CLASS])) { |
||||
718 | $task = $this->getAssociatedTask(false); |
||||
719 | if ($task) { |
||||
0 ignored issues
–
show
|
|||||
720 | mapi_setprops($task, $props); |
||||
721 | mapi_savechanges($task); |
||||
722 | } |
||||
723 | } |
||||
724 | |||||
725 | // Set as accepted |
||||
726 | mapi_setprops($this->message, $props); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_setprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
727 | |||||
728 | // As we copy the all properties from received message we need to remove following |
||||
729 | // properties from accept response. |
||||
730 | mapi_deleteprops($this->message, [PR_MESSAGE_RECIP_ME, PR_MESSAGE_TO_ME, PR_MESSAGE_CC_ME, PR_PROCESSED]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_deleteprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
731 | |||||
732 | mapi_savechanges($this->message); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_savechanges() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
733 | |||||
734 | $this->sendResponse(tdmtTaskAcc, $prefix); |
||||
735 | |||||
736 | return $this->deleteReceivedTR(); |
||||
737 | } |
||||
738 | |||||
739 | /** |
||||
740 | * Declines a task request and sends the response. |
||||
741 | * |
||||
742 | * Passed message must be a task request message, ie isTaskRequest() must return TRUE. |
||||
743 | * |
||||
744 | * Sends the decline message back to the organizer. The caller is responsible for removing the message. |
||||
745 | * |
||||
746 | * @return array|false TRUE on success, FALSE on failure |
||||
747 | */ |
||||
748 | public function doDecline() { |
||||
749 | $prefix = _("Task Declined:") . " "; |
||||
750 | $messageProps = mapi_getprops($this->message, [$this->props['taskstate']]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
751 | |||||
752 | if (!isset($messageProps[$this->props['taskstate']]) || $messageProps[$this->props['taskstate']] != tdsOWN) { |
||||
753 | return false; // Can only decline assignee task |
||||
754 | } |
||||
755 | |||||
756 | $this->setLastUser(); |
||||
757 | $this->updateTaskRequest(); |
||||
758 | |||||
759 | // Set as declined |
||||
760 | mapi_setprops($this->message, [ |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_setprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
761 | $this->props['taskhistory'] => thDeclined, |
||||
762 | $this->props['task_acceptance_state'] => olTaskDelegationDeclined, |
||||
763 | ]); |
||||
764 | mapi_deleteprops($this->message, [PR_MESSAGE_RECIP_ME, PR_MESSAGE_TO_ME, PR_MESSAGE_CC_ME, PR_PROCESSED]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_deleteprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
765 | mapi_savechanges($this->message); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_savechanges() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
766 | |||||
767 | $this->sendResponse(tdmtTaskDec, $prefix); |
||||
768 | |||||
769 | // Delete the associated task when task request is declined by the assignee. |
||||
770 | $task = $this->getAssociatedTask(false); |
||||
771 | if ($task) { |
||||
0 ignored issues
–
show
|
|||||
772 | $taskFolder = $this->getDefaultTasksFolder(); |
||||
773 | $props = mapi_getprops($task, [PR_ENTRYID]); |
||||
774 | mapi_folder_deletemessages($taskFolder, [$props[PR_ENTRYID]]); |
||||
775 | } |
||||
776 | |||||
777 | return $this->deleteReceivedTR(); |
||||
778 | } |
||||
779 | |||||
780 | /** |
||||
781 | * Sends an update of the task if requested, and sends the Status-On-Completion report if complete and requested. |
||||
782 | * |
||||
783 | * If no updates were requested from the organizer, this function does nothing. |
||||
784 | * |
||||
785 | * @return bool TRUE if the update succeeded, FALSE otherwise |
||||
786 | */ |
||||
787 | public function doUpdate() { |
||||
788 | $messageProps = mapi_getprops($this->message, [$this->props['taskstate'], PR_SUBJECT]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
789 | |||||
790 | if (!isset($messageProps[$this->props['taskstate']]) || $messageProps[$this->props['taskstate']] != tdsOWN) { |
||||
791 | return false; // Can only update assignee task |
||||
792 | } |
||||
793 | |||||
794 | $this->setLastUser(); |
||||
795 | $this->updateTaskRequest(); |
||||
796 | |||||
797 | // Set as updated |
||||
798 | mapi_setprops($this->message, [$this->props['taskhistory'] => thUpdated]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_setprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
799 | |||||
800 | mapi_savechanges($this->message); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_savechanges() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
801 | |||||
802 | $props = mapi_getprops($this->message, [$this->props['taskupdates'], $this->props['tasksoc'], $this->props['recurring'], $this->props['complete']]); |
||||
803 | if (!$props[$this->props['complete']] && $props[$this->props['taskupdates']] && !(isset($props[$this->props['recurring']]) && $props[$this->props['recurring']])) { |
||||
804 | $this->sendResponse(tdmtTaskUpd, _("Task Updated:") . " "); |
||||
805 | } |
||||
806 | elseif ($props[$this->props['complete']]) { |
||||
807 | $this->sendResponse(tdmtTaskUpd, _("Task Completed:") . " "); |
||||
808 | } |
||||
809 | |||||
810 | return true; |
||||
811 | } |
||||
812 | |||||
813 | /** |
||||
814 | * Gets the store associated with the task. |
||||
815 | * |
||||
816 | * Normally this will just open the store that the processed message is in. However, if the message is opened |
||||
817 | * by a delegate, this function opens the store that the message was delegated from. |
||||
818 | */ |
||||
819 | public function getTaskFolderStore() { |
||||
820 | $ownerentryid = false; |
||||
821 | |||||
822 | $rcvdprops = mapi_getprops($this->message, [PR_RCVD_REPRESENTING_ENTRYID]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
823 | if (isset($rcvdprops[PR_RCVD_REPRESENTING_ENTRYID])) { |
||||
824 | $ownerentryid = $rcvdprops[PR_RCVD_REPRESENTING_ENTRYID]; |
||||
825 | } |
||||
826 | |||||
827 | if (!$ownerentryid) { |
||||
828 | $store = $this->store; |
||||
829 | } |
||||
830 | else { |
||||
831 | $ab = mapi_openaddressbook($this->session); |
||||
0 ignored issues
–
show
$this->session of type resource is incompatible with the type resource expected by parameter $session of mapi_openaddressbook() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
832 | if (!$ab) { |
||||
0 ignored issues
–
show
|
|||||
833 | return false; |
||||
834 | } |
||||
835 | |||||
836 | $mailuser = mapi_ab_openentry($ab, $ownerentryid); |
||||
837 | if (!$mailuser) { |
||||
0 ignored issues
–
show
|
|||||
838 | return false; |
||||
839 | } |
||||
840 | |||||
841 | $mailuserprops = mapi_getprops($mailuser, [PR_EMAIL_ADDRESS]); |
||||
842 | if (!isset($mailuserprops[PR_EMAIL_ADDRESS])) { |
||||
843 | return false; |
||||
844 | } |
||||
845 | |||||
846 | $storeid = mapi_msgstore_createentryid($this->store, $mailuserprops[PR_EMAIL_ADDRESS]); |
||||
0 ignored issues
–
show
$this->store of type resource is incompatible with the type resource expected by parameter $store of mapi_msgstore_createentryid() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
847 | |||||
848 | $store = mapi_openmsgstore($this->session, $storeid); |
||||
0 ignored issues
–
show
$this->session of type resource is incompatible with the type resource expected by parameter $ses of mapi_openmsgstore() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
849 | } |
||||
850 | |||||
851 | return $store; |
||||
852 | } |
||||
853 | |||||
854 | /** |
||||
855 | * Opens the default task folder for the current user, or the specified user if passed. |
||||
856 | */ |
||||
857 | public function getDefaultTasksFolder() { |
||||
858 | $store = $this->getTaskFolderStore(); |
||||
859 | |||||
860 | $inbox = mapi_msgstore_getreceivefolder($store); |
||||
0 ignored issues
–
show
It seems like
$store can also be of type false and resource ; however, parameter $store of mapi_msgstore_getreceivefolder() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
861 | $inboxprops = mapi_getprops($inbox, [PR_IPM_TASK_ENTRYID]); |
||||
862 | if (!isset($inboxprops[PR_IPM_TASK_ENTRYID])) { |
||||
863 | return false; |
||||
864 | } |
||||
865 | |||||
866 | return mapi_msgstore_openentry($store, $inboxprops[PR_IPM_TASK_ENTRYID]); |
||||
0 ignored issues
–
show
It seems like
$store can also be of type false and resource ; however, parameter $store of mapi_msgstore_openentry() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
867 | } |
||||
868 | |||||
869 | /** |
||||
870 | * Prepares the sent representing properties from given MAPI store. |
||||
871 | * |
||||
872 | * @param mixed $store MAPI store object |
||||
873 | * |
||||
874 | * @return array[][][][][]|false if store is not mail box owner entryid then return false else prepare the sent representing props and return it |
||||
875 | * |
||||
876 | * @psalm-return array<array<array<array<array<array<never, never>>>>>>|false |
||||
877 | */ |
||||
878 | public function getSentReprProps($store) { |
||||
879 | $storeprops = mapi_getprops($store, [PR_MAILBOX_OWNER_ENTRYID]); |
||||
880 | if (!isset($storeprops[PR_MAILBOX_OWNER_ENTRYID])) { |
||||
881 | return false; |
||||
882 | } |
||||
883 | |||||
884 | $ab = mapi_openaddressbook($this->session); |
||||
0 ignored issues
–
show
$this->session of type resource is incompatible with the type resource expected by parameter $session of mapi_openaddressbook() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
885 | $mailuser = mapi_ab_openentry($ab, $storeprops[PR_MAILBOX_OWNER_ENTRYID]); |
||||
886 | $mailuserprops = mapi_getprops($mailuser, [PR_ADDRTYPE, PR_EMAIL_ADDRESS, PR_DISPLAY_NAME, PR_SEARCH_KEY, PR_ENTRYID]); |
||||
887 | |||||
888 | $props = []; |
||||
889 | $props[PR_SENT_REPRESENTING_ADDRTYPE] = $mailuserprops[PR_ADDRTYPE]; |
||||
890 | $props[PR_SENT_REPRESENTING_EMAIL_ADDRESS] = $mailuserprops[PR_EMAIL_ADDRESS]; |
||||
891 | $props[PR_SENT_REPRESENTING_NAME] = $mailuserprops[PR_DISPLAY_NAME]; |
||||
892 | $props[PR_SENT_REPRESENTING_SEARCH_KEY] = $mailuserprops[PR_SEARCH_KEY]; |
||||
893 | $props[PR_SENT_REPRESENTING_ENTRYID] = $mailuserprops[PR_ENTRYID]; |
||||
894 | |||||
895 | return $props; |
||||
896 | } |
||||
897 | |||||
898 | /** |
||||
899 | * Creates an outgoing message based on the passed message - will set delegate information |
||||
900 | * and sent mail folder. |
||||
901 | */ |
||||
902 | public function createOutgoingMessage() { |
||||
903 | // Open our default store for this user (that's the only store we can submit in) |
||||
904 | $store = $this->getDefaultStore(); |
||||
905 | $storeprops = mapi_getprops($store, [PR_IPM_OUTBOX_ENTRYID, PR_IPM_SENTMAIL_ENTRYID]); |
||||
0 ignored issues
–
show
It seems like
$store can also be of type false ; however, parameter $any of mapi_getprops() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
906 | |||||
907 | $outbox = mapi_msgstore_openentry($store, $storeprops[PR_IPM_OUTBOX_ENTRYID]); |
||||
0 ignored issues
–
show
It seems like
$store can also be of type false ; however, parameter $store of mapi_msgstore_openentry() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
908 | if (!$outbox) { |
||||
0 ignored issues
–
show
|
|||||
909 | return false; |
||||
910 | } |
||||
911 | |||||
912 | $outgoing = mapi_folder_createmessage($outbox); |
||||
913 | if (!$outgoing) { |
||||
0 ignored issues
–
show
|
|||||
914 | return false; |
||||
915 | } |
||||
916 | |||||
917 | // Set SENT_REPRESENTING in case we're sending as a delegate |
||||
918 | $ownerstore = $this->getTaskFolderStore(); |
||||
919 | $sentreprprops = $this->getSentReprProps($ownerstore); |
||||
920 | mapi_setprops($outgoing, $sentreprprops); |
||||
0 ignored issues
–
show
$sentreprprops of type false is incompatible with the type array expected by parameter $propvals of mapi_setprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
921 | |||||
922 | mapi_setprops($outgoing, [PR_SENTMAIL_ENTRYID => $storeprops[PR_IPM_SENTMAIL_ENTRYID]]); |
||||
923 | |||||
924 | return $outgoing; |
||||
925 | } |
||||
926 | |||||
927 | /** |
||||
928 | * Sends a response message (from assignee back to organizer). |
||||
929 | * |
||||
930 | * @param int $type Type of response (tdmtTaskAcc, tdmtTaskDec, tdmtTaskUpd) |
||||
931 | * @param mixed $prefix |
||||
932 | * |
||||
933 | * @return bool TRUE on success |
||||
934 | */ |
||||
935 | public function sendResponse($type, $prefix) { |
||||
936 | // Create a message in our outbox |
||||
937 | $outgoing = $this->createOutgoingMessage(); |
||||
938 | $messageprops = mapi_getprops($this->message, [PR_CONVERSATION_TOPIC, PR_MESSAGE_CLASS, $this->props['complete']]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
939 | |||||
940 | $attach = mapi_message_createattach($outgoing); |
||||
941 | mapi_setprops($attach, [PR_ATTACH_METHOD => ATTACH_EMBEDDED_MSG, PR_DISPLAY_NAME => $messageprops[PR_CONVERSATION_TOPIC], PR_ATTACHMENT_HIDDEN => true]); |
||||
942 | $sub = mapi_attach_openproperty($attach, PR_ATTACH_DATA_OBJ, IID_IMessage, 0, MAPI_CREATE | MAPI_MODIFY); |
||||
0 ignored issues
–
show
The function
mapi_attach_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
![]() |
|||||
943 | |||||
944 | $message = !$this->isTaskRequest() ? $this->message : $this->getAssociatedTask(false); |
||||
945 | |||||
946 | $ignoreProps = [PR_ICON_INDEX, $this->props["categories"], PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_EMAIL_ADDRESS, PR_SENT_REPRESENTING_ADDRTYPE, PR_SENT_REPRESENTING_ENTRYID, PR_SENT_REPRESENTING_SEARCH_KEY]; |
||||
947 | |||||
948 | mapi_copyto($message, [], $ignoreProps, $outgoing); |
||||
0 ignored issues
–
show
$message of type resource is incompatible with the type resource expected by parameter $src of mapi_copyto() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
949 | mapi_copyto($message, [], [], $sub); |
||||
950 | |||||
951 | if (!$this->setRecipientsForResponse($outgoing, $type)) { |
||||
952 | return false; |
||||
953 | } |
||||
954 | |||||
955 | $props = []; |
||||
956 | |||||
957 | switch ($type) { |
||||
958 | case tdmtTaskAcc: |
||||
959 | $props[PR_MESSAGE_CLASS] = "IPM.TaskRequest.Accept"; |
||||
960 | mapi_setprops($sub, [PR_ICON_INDEX => ICON_TASK_ASSIGNER]); |
||||
961 | break; |
||||
962 | |||||
963 | case tdmtTaskDec: |
||||
964 | $props[PR_MESSAGE_CLASS] = "IPM.TaskRequest.Decline"; |
||||
965 | mapi_setprops($sub, [PR_ICON_INDEX => ICON_TASK_DECLINE]); |
||||
966 | break; |
||||
967 | |||||
968 | case tdmtTaskUpd: |
||||
969 | mapi_setprops($sub, [PR_ICON_INDEX => ICON_TASK_ASSIGNER]); |
||||
970 | if ($messageprops[$this->props['complete']]) { |
||||
971 | $props[PR_MESSAGE_CLASS] = "IPM.TaskRequest.Complete"; |
||||
972 | } |
||||
973 | else { |
||||
974 | $props[PR_MESSAGE_CLASS] = "IPM.TaskRequest.Update"; |
||||
975 | } |
||||
976 | |||||
977 | break; |
||||
978 | } |
||||
979 | |||||
980 | mapi_savechanges($sub); |
||||
981 | mapi_savechanges($attach); |
||||
982 | |||||
983 | $props[PR_SUBJECT] = $prefix . $messageprops[PR_CONVERSATION_TOPIC]; |
||||
984 | $props[$this->props['taskmode']] = $type; |
||||
985 | $props[$this->props['task_assigned_time']] = time(); |
||||
986 | |||||
987 | mapi_setprops($outgoing, $props); |
||||
988 | |||||
989 | // taskCommentsInfo contains some comments which added by assignee while |
||||
990 | // edit response before sending task response. |
||||
991 | if ($this->taskCommentsInfo != '') { |
||||
992 | $comments = $this->getTaskCommentsInfo(); |
||||
993 | $stream = mapi_openproperty($outgoing, PR_BODY, IID_IStream, STGM_TRANSACTED, MAPI_CREATE | MAPI_MODIFY); |
||||
0 ignored issues
–
show
The call to
mapi_openproperty() has too many arguments starting with IID_IStream .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||
994 | mapi_stream_setsize($stream, strlen($comments)); |
||||
995 | mapi_stream_write($stream, $comments); |
||||
996 | mapi_stream_commit($stream); |
||||
997 | } |
||||
998 | |||||
999 | mapi_savechanges($outgoing); |
||||
1000 | mapi_message_submitmessage($outgoing); |
||||
1001 | |||||
1002 | return true; |
||||
1003 | } |
||||
1004 | |||||
1005 | public function getDefaultStore() { |
||||
1006 | $table = mapi_getmsgstorestable($this->session); |
||||
0 ignored issues
–
show
$this->session of type resource is incompatible with the type resource expected by parameter $session of mapi_getmsgstorestable() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1007 | $rows = mapi_table_queryallrows($table, [PR_DEFAULT_STORE, PR_ENTRYID]); |
||||
1008 | |||||
1009 | foreach ($rows as $row) { |
||||
1010 | if ($row[PR_DEFAULT_STORE]) { |
||||
1011 | return mapi_openmsgstore($this->session, $row[PR_ENTRYID]); |
||||
0 ignored issues
–
show
$this->session of type resource is incompatible with the type resource expected by parameter $ses of mapi_openmsgstore() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1012 | } |
||||
1013 | } |
||||
1014 | |||||
1015 | return false; |
||||
1016 | } |
||||
1017 | |||||
1018 | /** |
||||
1019 | * Creates a new TaskGlobalObjId. |
||||
1020 | * |
||||
1021 | * Just 16 bytes of random data |
||||
1022 | */ |
||||
1023 | public function createTGOID(): string { |
||||
1024 | $goid = ""; |
||||
1025 | for ($i = 0; $i < 16; ++$i) { |
||||
1026 | $goid .= chr(rand(0, 255)); |
||||
1027 | } |
||||
1028 | |||||
1029 | return $goid; |
||||
1030 | } |
||||
1031 | |||||
1032 | /** |
||||
1033 | * Gets the embedded task of task request. Further used to |
||||
1034 | * create/update associated task of assigner/assignee. |
||||
1035 | * |
||||
1036 | * @return bool|resource embedded task if found else false |
||||
1037 | */ |
||||
1038 | public function getEmbeddedTask() { |
||||
1039 | $task = false; |
||||
1040 | $goid = mapi_getprops($this->message, [$this->props["task_goid"]]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1041 | $attachmentTable = mapi_message_getattachmenttable($this->message); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $msg of mapi_message_getattachmenttable() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1042 | $restriction = [RES_PROPERTY, |
||||
1043 | [RELOP => RELOP_EQ, |
||||
1044 | ULPROPTAG => PR_ATTACH_METHOD, |
||||
1045 | VALUE => ATTACH_EMBEDDED_MSG, ], |
||||
1046 | ]; |
||||
1047 | $rows = mapi_table_queryallrows($attachmentTable, [PR_ATTACH_NUM], $restriction); |
||||
1048 | |||||
1049 | if (empty($rows)) { |
||||
1050 | return $task; |
||||
1051 | } |
||||
1052 | |||||
1053 | foreach ($rows as $row) { |
||||
1054 | try { |
||||
1055 | $attach = mapi_message_openattach($this->message, $row[PR_ATTACH_NUM]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $msg of mapi_message_openattach() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1056 | $task = mapi_attach_openobj($attach); |
||||
1057 | } |
||||
1058 | catch (MAPIException $e) { |
||||
1059 | continue; |
||||
1060 | } |
||||
1061 | |||||
1062 | $taskGoid = mapi_getprops($task, [$this->props["task_goid"]]); |
||||
1063 | if ($goid[$this->props["task_goid"]] === $taskGoid[$this->props["task_goid"]]) { |
||||
1064 | mapi_setprops($attach, [PR_ATTACHMENT_HIDDEN => true]); |
||||
1065 | mapi_savechanges($attach); |
||||
1066 | mapi_savechanges($this->message); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_savechanges() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1067 | break; |
||||
1068 | } |
||||
1069 | } |
||||
1070 | |||||
1071 | return $task; |
||||
0 ignored issues
–
show
|
|||||
1072 | } |
||||
1073 | |||||
1074 | /** |
||||
1075 | * Sets the user name who has last used this task. Update the |
||||
1076 | * tasklastdelegate and task_assigned_time. |
||||
1077 | */ |
||||
1078 | public function setLastUser(): void { |
||||
1079 | $delegatestore = $this->getDefaultStore(); |
||||
1080 | $taskstore = $this->getTaskFolderStore(); |
||||
1081 | |||||
1082 | $delegateprops = mapi_getprops($delegatestore, [PR_MAILBOX_OWNER_NAME]); |
||||
0 ignored issues
–
show
It seems like
$delegatestore can also be of type false ; however, parameter $any of mapi_getprops() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1083 | $taskprops = mapi_getprops($taskstore, [PR_MAILBOX_OWNER_NAME]); |
||||
0 ignored issues
–
show
It seems like
$taskstore can also be of type false and resource ; however, parameter $any of mapi_getprops() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1084 | |||||
1085 | // The owner of the task |
||||
1086 | $username = $delegateprops[PR_MAILBOX_OWNER_NAME]; |
||||
1087 | // This is me (the one calling the script) |
||||
1088 | $delegate = $taskprops[PR_MAILBOX_OWNER_NAME]; |
||||
1089 | |||||
1090 | if ($this->isTaskRequest()) { |
||||
1091 | $task = $this->getAssociatedTask(false); |
||||
1092 | mapi_setprops($task, [ |
||||
0 ignored issues
–
show
$task of type resource is incompatible with the type resource expected by parameter $any of mapi_setprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1093 | $this->props["tasklastuser"] => $username, |
||||
1094 | $this->props["tasklastdelegate"] => $delegate, |
||||
1095 | $this->props['task_assigned_time'] => time(), |
||||
1096 | ]); |
||||
1097 | mapi_savechanges($task); |
||||
0 ignored issues
–
show
$task of type resource is incompatible with the type resource expected by parameter $any of mapi_savechanges() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1098 | } |
||||
1099 | mapi_setprops($this->message, [ |
||||
1100 | $this->props["tasklastuser"] => $username, |
||||
1101 | $this->props["tasklastdelegate"] => $delegate, |
||||
1102 | $this->props['task_assigned_time'] => time(), |
||||
1103 | ]); |
||||
1104 | } |
||||
1105 | |||||
1106 | /** |
||||
1107 | * Sets assignee as owner in the assignor's copy of task. |
||||
1108 | * Assignee becomes the owner when a user/assignor assigns any task to someone. |
||||
1109 | * There can be more than one assignee. |
||||
1110 | */ |
||||
1111 | public function setOwnerForAssignor(): void { |
||||
1112 | $recipTable = mapi_message_getrecipienttable($this->message); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $msg of mapi_message_getrecipienttable() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1113 | $recips = mapi_table_queryallrows($recipTable, [PR_DISPLAY_NAME]); |
||||
1114 | |||||
1115 | if (!empty($recips)) { |
||||
1116 | $owner = []; |
||||
1117 | foreach ($recips as $value) { |
||||
1118 | $owner[] = $value[PR_DISPLAY_NAME]; |
||||
1119 | } |
||||
1120 | |||||
1121 | $props = [$this->props['owner'] => implode("; ", $owner)]; |
||||
1122 | mapi_setprops($this->message, $props); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_setprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1123 | } |
||||
1124 | } |
||||
1125 | |||||
1126 | /** |
||||
1127 | * Sets assignor as recipients in assignee's copy of task. |
||||
1128 | * |
||||
1129 | * If assignor has requested task updates then the assignor is added as recipient type MAPI_CC. |
||||
1130 | * |
||||
1131 | * Also if assignor has request SOC then the assignor is also add as recipient type MAPI_BCC |
||||
1132 | * |
||||
1133 | * @param mixed $task assignee's copy of task |
||||
1134 | */ |
||||
1135 | public function setAssignorInRecipients($task): void { |
||||
1136 | $recipTable = mapi_message_getrecipienttable($task); |
||||
1137 | |||||
1138 | // Delete all MAPI_TO recipients |
||||
1139 | $recips = mapi_table_queryallrows($recipTable, [PR_ROWID], [ |
||||
1140 | RES_PROPERTY, |
||||
1141 | [ |
||||
1142 | RELOP => RELOP_EQ, |
||||
1143 | ULPROPTAG => PR_RECIPIENT_TYPE, |
||||
1144 | VALUE => MAPI_TO, |
||||
1145 | ], |
||||
1146 | ]); |
||||
1147 | foreach ($recips as $recip) { |
||||
1148 | mapi_message_modifyrecipients($task, MODRECIP_REMOVE, [$recip]); |
||||
1149 | } |
||||
1150 | |||||
1151 | $recips = []; |
||||
1152 | $taskReqProps = mapi_getprops($this->message, [ |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1153 | PR_SENT_REPRESENTING_NAME, |
||||
1154 | PR_SENT_REPRESENTING_EMAIL_ADDRESS, |
||||
1155 | PR_SENT_REPRESENTING_ENTRYID, |
||||
1156 | PR_SENT_REPRESENTING_ADDRTYPE, |
||||
1157 | PR_SENT_REPRESENTING_SEARCH_KEY, |
||||
1158 | ]); |
||||
1159 | $associatedTaskProps = mapi_getprops($task, [ |
||||
1160 | $this->props['taskupdates'], |
||||
1161 | $this->props['tasksoc'], |
||||
1162 | $this->props['taskmultrecips'], |
||||
1163 | ]); |
||||
1164 | |||||
1165 | // Build assignor info |
||||
1166 | $assignor = [ |
||||
1167 | PR_ENTRYID => $taskReqProps[PR_SENT_REPRESENTING_ENTRYID], |
||||
1168 | PR_DISPLAY_NAME => $taskReqProps[PR_SENT_REPRESENTING_NAME], |
||||
1169 | PR_EMAIL_ADDRESS => $taskReqProps[PR_SENT_REPRESENTING_EMAIL_ADDRESS], |
||||
1170 | PR_RECIPIENT_DISPLAY_NAME => $taskReqProps[PR_SENT_REPRESENTING_NAME], |
||||
1171 | PR_ADDRTYPE => empty($taskReqProps[PR_SENT_REPRESENTING_ADDRTYPE]) ? 'SMTP' : $taskReqProps[PR_SENT_REPRESENTING_ADDRTYPE], |
||||
1172 | PR_RECIPIENT_FLAGS => recipSendable, |
||||
1173 | PR_SEARCH_KEY => $taskReqProps[PR_SENT_REPRESENTING_SEARCH_KEY], |
||||
1174 | ]; |
||||
1175 | |||||
1176 | // Assignor has requested task updates, so set him/her as MAPI_CC in recipienttable. |
||||
1177 | if ((isset($associatedTaskProps[$this->props['taskupdates']]) && $associatedTaskProps[$this->props['taskupdates']]) && |
||||
1178 | !(isset($associatedTaskProps[$this->props['taskmultrecips']]) && $associatedTaskProps[$this->props['taskmultrecips']] == tmrReceived)) { |
||||
1179 | $assignor[PR_RECIPIENT_TYPE] = MAPI_CC; |
||||
1180 | $recips[] = $assignor; |
||||
1181 | } |
||||
1182 | |||||
1183 | // Assignor wants to receive an email report when task is mark as 'Complete', so in recipients as MAPI_BCC |
||||
1184 | if ($associatedTaskProps[$this->props['tasksoc']]) { |
||||
1185 | $assignor[PR_RECIPIENT_TYPE] = MAPI_BCC; |
||||
1186 | $recips[] = $assignor; |
||||
1187 | } |
||||
1188 | |||||
1189 | if (!empty($recips)) { |
||||
1190 | mapi_message_modifyrecipients($task, MODRECIP_ADD, $recips); |
||||
1191 | } |
||||
1192 | } |
||||
1193 | |||||
1194 | /** |
||||
1195 | * Deletes incoming task request from Inbox. |
||||
1196 | * |
||||
1197 | * @returns array|bool PR_ENTRYID, PR_STORE_ENTRYID and PR_PARENT_ENTRYID of the deleted task request |
||||
1198 | * |
||||
1199 | * @return array|false |
||||
1200 | */ |
||||
1201 | public function deleteReceivedTR() { |
||||
1202 | $store = $this->getTaskFolderStore(); |
||||
1203 | $storeType = mapi_getprops($store, [PR_MDB_PROVIDER]); |
||||
0 ignored issues
–
show
It seems like
$store can also be of type false and resource ; however, parameter $any of mapi_getprops() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1204 | if ($storeType[PR_MDB_PROVIDER] === ZARAFA_STORE_PUBLIC_GUID) { |
||||
1205 | $store = $this->getDefaultStore(); |
||||
1206 | } |
||||
1207 | $inbox = mapi_msgstore_getreceivefolder($store); |
||||
0 ignored issues
–
show
It seems like
$store can also be of type false and resource ; however, parameter $store of mapi_msgstore_getreceivefolder() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1208 | |||||
1209 | $storeProps = mapi_getprops($store, [PR_IPM_WASTEBASKET_ENTRYID]); |
||||
1210 | $props = mapi_getprops($this->message, [$this->props['task_goid']]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1211 | $goid = $props[$this->props['task_goid']]; |
||||
1212 | |||||
1213 | // Find the task by looking for the task_goid |
||||
1214 | $restriction = [ |
||||
1215 | RES_PROPERTY, |
||||
1216 | [ |
||||
1217 | RELOP => RELOP_EQ, |
||||
1218 | ULPROPTAG => $this->props['task_goid'], |
||||
1219 | VALUE => $goid, |
||||
1220 | ], |
||||
1221 | ]; |
||||
1222 | |||||
1223 | $contents = mapi_folder_getcontentstable($inbox); |
||||
1224 | |||||
1225 | $rows = mapi_table_queryallrows($contents, [PR_ENTRYID, PR_PARENT_ENTRYID, PR_STORE_ENTRYID], $restriction); |
||||
1226 | |||||
1227 | if (!empty($rows)) { |
||||
1228 | // If there are multiple, just use the first |
||||
1229 | $entryid = $rows[0][PR_ENTRYID]; |
||||
1230 | $wastebasket = mapi_msgstore_openentry($store, $storeProps[PR_IPM_WASTEBASKET_ENTRYID]); |
||||
0 ignored issues
–
show
It seems like
$store can also be of type false and resource ; however, parameter $store of mapi_msgstore_openentry() does only seem to accept resource , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1231 | mapi_folder_copymessages($inbox, [$entryid], $wastebasket, MESSAGE_MOVE); |
||||
1232 | |||||
1233 | return [PR_ENTRYID => $entryid, PR_PARENT_ENTRYID => $rows[0][PR_PARENT_ENTRYID], PR_STORE_ENTRYID => $rows[0][PR_STORE_ENTRYID]]; |
||||
1234 | } |
||||
1235 | |||||
1236 | return false; |
||||
1237 | } |
||||
1238 | |||||
1239 | /** |
||||
1240 | * Sets recipients for the outgoing message according to type of the response. |
||||
1241 | * |
||||
1242 | * If it is a task update, then only recipient type MAPI_CC are taken from the task message. |
||||
1243 | * |
||||
1244 | * If it is accept/decline response, then PR_SENT_REPRESENTATING_XXXX are taken as recipient. |
||||
1245 | * |
||||
1246 | * @param mixed $outgoing outgoing mapi message |
||||
1247 | * @param int $responseType response type (tdmtTaskAcc, tdmtTaskDec, tdmtTaskUpd) |
||||
1248 | */ |
||||
1249 | public function setRecipientsForResponse($outgoing, $responseType): bool { |
||||
1250 | // Clear recipients from outgoing msg |
||||
1251 | $this->deleteAllRecipients($outgoing); |
||||
1252 | |||||
1253 | // If it is a task update then get MAPI_CC recipients which are assignors who has asked for task update. |
||||
1254 | if ($responseType == tdmtTaskUpd) { |
||||
1255 | $props = mapi_getprops($this->message, [$this->props['complete']]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1256 | $isComplete = $props[$this->props['complete']]; |
||||
1257 | |||||
1258 | $recipTable = mapi_message_getrecipienttable($this->message); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $msg of mapi_message_getrecipienttable() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1259 | $recips = mapi_table_queryallrows($recipTable, $this->recipProps, [ |
||||
1260 | RES_PROPERTY, |
||||
1261 | [ |
||||
1262 | RELOP => RELOP_EQ, |
||||
1263 | ULPROPTAG => PR_RECIPIENT_TYPE, |
||||
1264 | VALUE => ($isComplete ? MAPI_BCC : MAPI_CC), |
||||
1265 | ], |
||||
1266 | ]); |
||||
1267 | |||||
1268 | // No recipients found, return error |
||||
1269 | if (empty($recips)) { |
||||
1270 | return false; |
||||
1271 | } |
||||
1272 | |||||
1273 | foreach ($recips as $recip) { |
||||
1274 | $recip[PR_RECIPIENT_TYPE] = MAPI_TO; // Change recipient type to MAPI_TO |
||||
1275 | mapi_message_modifyrecipients($outgoing, MODRECIP_ADD, [$recip]); |
||||
1276 | } |
||||
1277 | |||||
1278 | return true; |
||||
1279 | } |
||||
1280 | |||||
1281 | $orgprops = mapi_getprops($this->message, [ |
||||
1282 | PR_SENT_REPRESENTING_NAME, |
||||
1283 | PR_SENT_REPRESENTING_EMAIL_ADDRESS, |
||||
1284 | PR_SENT_REPRESENTING_ADDRTYPE, |
||||
1285 | PR_SENT_REPRESENTING_ENTRYID, |
||||
1286 | PR_SUBJECT, |
||||
1287 | ]); |
||||
1288 | |||||
1289 | $recip = [ |
||||
1290 | PR_DISPLAY_NAME => $orgprops[PR_SENT_REPRESENTING_NAME], |
||||
1291 | PR_EMAIL_ADDRESS => $orgprops[PR_SENT_REPRESENTING_EMAIL_ADDRESS], |
||||
1292 | PR_ADDRTYPE => $orgprops[PR_SENT_REPRESENTING_ADDRTYPE], |
||||
1293 | PR_ENTRYID => $orgprops[PR_SENT_REPRESENTING_ENTRYID], |
||||
1294 | PR_RECIPIENT_TYPE => MAPI_TO, ]; |
||||
1295 | |||||
1296 | mapi_message_modifyrecipients($outgoing, MODRECIP_ADD, [$recip]); |
||||
1297 | |||||
1298 | return true; |
||||
1299 | } |
||||
1300 | |||||
1301 | /** |
||||
1302 | * Deletes all recipients from given message object. |
||||
1303 | * |
||||
1304 | * @param mixed $message MAPI message from which recipients are to be removed |
||||
1305 | */ |
||||
1306 | public function deleteAllRecipients($message): void { |
||||
1307 | $recipTable = mapi_message_getrecipienttable($message); |
||||
1308 | $recipRows = mapi_table_queryallrows($recipTable, [PR_ROWID]); |
||||
1309 | |||||
1310 | foreach ($recipRows as $recipient) { |
||||
1311 | mapi_message_modifyrecipients($message, MODRECIP_REMOVE, [$recipient]); |
||||
1312 | } |
||||
1313 | } |
||||
1314 | |||||
1315 | /** |
||||
1316 | * Marks the record to complete and send complete update |
||||
1317 | * notification to assigner. |
||||
1318 | * |
||||
1319 | * @return bool TRUE if the update succeeded, FALSE otherwise |
||||
1320 | */ |
||||
1321 | public function sendCompleteUpdate() { |
||||
1322 | $messageprops = mapi_getprops($this->message, [$this->props['taskstate']]); |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_getprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1323 | |||||
1324 | if (!isset($messageprops[$this->props['taskstate']]) || $messageprops[$this->props['taskstate']] != tdsOWN) { |
||||
1325 | return false; // Can only decline assignee task |
||||
1326 | } |
||||
1327 | |||||
1328 | mapi_setprops($this->message, [ |
||||
0 ignored issues
–
show
$this->message of type resource is incompatible with the type resource expected by parameter $any of mapi_setprops() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1329 | $this->props['complete'] => true, |
||||
1330 | $this->props['datecompleted'] => time(), |
||||
1331 | $this->props['status'] => 2, |
||||
1332 | $this->props['percent_complete'] => 1, |
||||
1333 | ]); |
||||
1334 | |||||
1335 | return $this->doUpdate(); |
||||
1336 | } |
||||
1337 | |||||
1338 | /** |
||||
1339 | * Returns extra info about task request comments along with message body |
||||
1340 | * which will be included in body while sending task request/response. |
||||
1341 | * |
||||
1342 | * @return string info about task request comments along with message body |
||||
1343 | */ |
||||
1344 | public function getTaskCommentsInfo() { |
||||
1345 | return $this->taskCommentsInfo; |
||||
1346 | } |
||||
1347 | |||||
1348 | /** |
||||
1349 | * Sets an extra info about task request comments along with message body |
||||
1350 | * which will be included in body while sending task request/response. |
||||
1351 | * |
||||
1352 | * @param string $taskCommentsInfo info about task request comments along with message body |
||||
1353 | */ |
||||
1354 | public function setTaskCommentsInfo($taskCommentsInfo): void { |
||||
1355 | $this->taskCommentsInfo = $taskCommentsInfo; |
||||
1356 | } |
||||
1357 | |||||
1358 | public function getSubProperties() { |
||||
1359 | $subProperties = []; |
||||
1360 | $subProperties["subject"] = PR_SUBJECT; |
||||
1361 | $subProperties["convtopic"] = PR_CONVERSATION_TOPIC; |
||||
1362 | $subProperties["complete"] = "PT_BOOLEAN:PSETID_Task:" . PidLidTaskComplete; |
||||
1363 | $subProperties["datecompleted"] = "PT_SYSTIME:PSETID_Task:" . PidLidTaskDateCompleted; |
||||
1364 | $subProperties["recurring"] = "PT_BOOLEAN:PSETID_Task:0x8126"; |
||||
1365 | $subProperties["startdate"] = "PT_SYSTIME:PSETID_Task:" . PidLidTaskStartDate; |
||||
1366 | $subProperties["duedate"] = "PT_SYSTIME:PSETID_Task:" . PidLidTaskDueDate; |
||||
1367 | $subProperties["status"] = "PT_LONG:PSETID_Task:" . PidLidTaskStatus; |
||||
1368 | $subProperties["percent_complete"] = "PT_DOUBLE:PSETID_Task:" . PidLidPercentComplete; |
||||
1369 | $subProperties["totalwork"] = "PT_LONG:PSETID_Task:0x8111"; |
||||
1370 | $subProperties["actualwork"] = "PT_LONG:PSETID_Task:0x8110"; |
||||
1371 | $subProperties["categories"] = "PT_MV_STRING8:PS_PUBLIC_STRINGS:Keywords"; |
||||
1372 | $subProperties["companies"] = "PT_MV_STRING8:PSETID_Common:0x8539"; |
||||
1373 | $subProperties["mileage"] = "PT_STRING8:PSETID_Common:0x8534"; |
||||
1374 | $subProperties["billinginformation"] = "PT_STRING8:PSETID_Common:0x8535"; |
||||
1375 | |||||
1376 | return getPropIdsFromStrings($this->store, $subProperties); |
||||
1377 | } |
||||
1378 | } |
||||
1379 |