Test Failed
Push — master ( 647c72...cd42b5 )
by
unknown
10:25
created

ItemModule::cancelInvitation()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 26
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 13
c 0
b 0
f 0
nc 8
nop 4
dl 0
loc 26
rs 9.5222
1
<?php
2
	/**
3
	 * ItemModule
4
	 * Module which opens, creates, saves and deletes an item. It
5
	 * extends the Module class.
6
	 */
7
	class ItemModule extends Module
8
	{
9
		/**
10
		 * The setting whether Meeting Requests should be booked directly or not.
11
		 */
12
		public $directBookingMeetingRequest;
13
14
		/**
15
		 * The array of properties which should not be copied during the copy() action.
16
		 */
17
		public $skipCopyProperties;
18
19
		/**
20
		 * Indicates that we are supporting only plain text body in the message props
21
		 */
22
		public $plaintext;
23
24
		/**
25
		 * Constructor
26
		 * @param int $id unique id.
27
		 * @param array $data list of all actions.
28
		 */
29
		function __construct($id, $data)
30
		{
31
			$this->directBookingMeetingRequest = ENABLE_DIRECT_BOOKING;
32
			$this->skipCopyProperties = array();
33
			$this->plaintext = false;
34
35
			parent::__construct($id, $data);
36
		}
37
38
		/**
39
		 * Executes all the actions in the $data variable.
40
		 * @return boolean true on success of false on fialure.
41
		 */
42
		function execute()
43
		{
44
			foreach($this->data as $actionType => $action)
45
			{
46
				if(isset($actionType)) {
47
					try {
48
						$store = $this->getActionStore($action);
49
						$parententryid = $this->getActionParentEntryID($action);
50
						$entryid = $this->getActionEntryID($action);
51
52
						switch($actionType)
53
						{
54
							case "open":
55
								$this->open($store, $entryid, $action);
0 ignored issues
show
Bug introduced by
$entryid of type object is incompatible with the type string expected by parameter $entryid of ItemModule::open(). ( Ignorable by Annotation )

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

55
								$this->open($store, /** @scrutinizer ignore-type */ $entryid, $action);
Loading history...
56
								break;
57
							case "save":
58
								if ($store && $parententryid) {
59
									/*
60
									 * The "message_action" object has been set, check the action_type field for
61
									 * the exact action which must be taken.
62
									 * Supported actions:
63
									 *   - acceptmeetingrequest: attendee has accepted mr
64
									 *   - declineMeetingRequest: attendee has declined mr
65
									 */
66
									if (isset($action["message_action"]) && isset($action["message_action"]["action_type"])) {
67
										switch($action["message_action"]["action_type"])
68
										{
69
											case "declineMeetingRequest":
70
											case "acceptMeetingRequest":
71
												$message = $GLOBALS["operations"]->openMessage($store, $entryid);
72
												$basedate = (isset($action['basedate']) ? $action['basedate'] : false);
73
												$delete = false;
74
75
												if($basedate) {
76
													$recurrence = new Recurrence($store, $message);
0 ignored issues
show
Bug introduced by
$store of type object is incompatible with the type resource expected by parameter $store of Recurrence::__construct(). ( Ignorable by Annotation )

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

76
													$recurrence = new Recurrence(/** @scrutinizer ignore-type */ $store, $message);
Loading history...
77
													$exceptionatt = $recurrence->getExceptionAttachment($basedate);
78
													if($exceptionatt) {
79
														//get properties of existing exception.
80
														$exceptionattProps = mapi_getprops($exceptionatt, array(PR_ATTACH_NUM));
81
														$attach_num = $exceptionattProps[PR_ATTACH_NUM];
82
													}
83
												}
84
85
												/**
86
												 * Get message class from original message. This can be changed to
87
												 * IPM.Appointment if the item is a Meeting Request in the maillist.
88
												 * After Accepting/Declining the message is moved and changed.
89
												 */
90
												$originalMessageProps = mapi_getprops($message, array(PR_MESSAGE_CLASS));
91
												$req = new Meetingrequest($store, $message, $GLOBALS["mapisession"]->getSession(), $this->directBookingMeetingRequest);
92
93
												// Update extra body information
94
												if(isset($action["message_action"]['meetingTimeInfo']) && !empty($action["message_action"]['meetingTimeInfo'])) {
95
													$req->setMeetingTimeInfo($action["message_action"]['meetingTimeInfo']);
96
													unset($action["message_action"]['meetingTimeInfo']);
97
												}
98
99
												// sendResponse flag if it is set then send the mail response to the organzer.
100
												$sendResponse = true;
101
												if(isset($action["message_action"]["sendResponse"]) && $action["message_action"]["sendResponse"] == false) {
102
													$sendResponse = false;
103
												}
104
105
												// @FIXME: fix body
106
												$body = false;
107
												if (isset($action["props"]["isHTML"]) && $action["props"]["isHTML"] === true) {
108
													$body = isset($action["props"]["html_body"]) ? $action["props"]["html_body"] : false;
109
												} else {
110
													$body = isset($action["props"]["body"]) ? $action["props"]["body"] : false;
111
												}
112
113
												if($action["message_action"]["action_type"] == "acceptMeetingRequest") {
114
													$tentative = $action["message_action"]["responseType"] === olResponseTentative;
115
													$newProposedStartTime = isset($action["message_action"]["proposed_starttime"]) ? $action["message_action"]["proposed_starttime"] : false;
116
													$newProposedEndTime = isset($action["message_action"]["proposed_endtime"]) ? $action["message_action"]["proposed_endtime"] : false;
117
118
													// We are accepting MR from preview-read-mail so set delete the actual mail flag.
119
													$delete = $req->isMeetingRequest($originalMessageProps[PR_MESSAGE_CLASS]);
120
121
													$req->doAccept($tentative, $sendResponse, $delete, $newProposedStartTime, $newProposedEndTime, $body, true, $store, $basedate);
0 ignored issues
show
Bug introduced by
It seems like $newProposedStartTime can also be of type false; however, parameter $newProposedStartTime of Meetingrequest::doAccept() does only seem to accept string, 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 ignore-type  annotation

121
													$req->doAccept($tentative, $sendResponse, $delete, /** @scrutinizer ignore-type */ $newProposedStartTime, $newProposedEndTime, $body, true, $store, $basedate);
Loading history...
Bug introduced by
It seems like $newProposedEndTime can also be of type false; however, parameter $newProposedEndTime of Meetingrequest::doAccept() does only seem to accept string, 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 ignore-type  annotation

121
													$req->doAccept($tentative, $sendResponse, $delete, $newProposedStartTime, /** @scrutinizer ignore-type */ $newProposedEndTime, $body, true, $store, $basedate);
Loading history...
122
												} else {
123
													$delete = $req->doDecline($sendResponse, $basedate, $body);
124
												}
125
126
												/**
127
												 * Now if the item is the Meeting Request that was sent to the attendee
128
												 * it is removed when the user has clicked on Accept/Decline. If the
129
												 * item is the appointment in the calendar it will not be moved. To only
130
												 * notify the bus when the item is a Meeting Request we are going to
131
												 * check the PR_MESSAGE_CLASS and see if it is "IPM.Meeting*".
132
												 */
133
												$messageProps = mapi_getprops($message, array(PR_ENTRYID, PR_STORE_ENTRYID, PR_PARENT_ENTRYID));
134
135
												// if opened appointment is exception then it will add
136
												// the attach_num and basedate in messageProps.
137
												if(isset($attach_num)) {
138
													$messageProps[PR_ATTACH_NUM] = array($attach_num);
139
													$messageProps[$properties["basedate"]] = $basedate;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $properties does not seem to be defined for all execution paths leading up to this point.
Loading history...
140
												}
141
142
												if($delete) {
143
													// send TABLE_DELETE event because the message has moved
144
													$this->sendFeedback(true);
145
													$GLOBALS["bus"]->notify(bin2hex($messageProps[PR_PARENT_ENTRYID]), TABLE_DELETE, $messageProps);
146
												} else {
147
													$this->addActionData("update", array("item" => Conversion::mapMAPI2XML($this->properties, $messageProps)));
148
													$GLOBALS["bus"]->addData($this->getResponseData());
149
150
													// send TABLE_SAVE event because an occurrence is deleted
151
													$GLOBALS["bus"]->notify(bin2hex($messageProps[PR_PARENT_ENTRYID]), TABLE_SAVE, $messageProps);
152
												}
153
154
											break;
155
											case "acceptTaskRequest":
156
											case "declineTaskRequest":
157
												$message = $GLOBALS["operations"]->openMessage($store, $entryid);
158
159
												if (isset($action["props"]) && !empty($action["props"])) {
160
													$properties = $GLOBALS["properties"]->getTaskProperties();
161
													mapi_setprops($message, Conversion::mapXML2MAPI($properties, $action["props"]));
162
													mapi_savechanges($message);
163
												}
164
												// The task may be a delegated task, do an update if needed (will fail for non-delegated tasks)
165
												$tr = new TaskRequest($store, $message, $GLOBALS["mapisession"]->getSession());
166
												$isAccept = $action["message_action"]["action_type"] == "acceptTaskRequest";
167
												if (isset($action["message_action"]["task_comments_info"]) && !empty($action["message_action"]["task_comments_info"])) {
168
													$tr->setTaskCommentsInfo($action["message_action"]["task_comments_info"]);
169
												}
170
												if ($isAccept) {
171
													$result = $tr->doAccept();
172
												} else {
173
													$result = $tr->doDecline();
174
												}
175
176
												$this->sendFeedback(true);
177
												if($result) {
178
													$GLOBALS["bus"]->notify(bin2hex($result[PR_PARENT_ENTRYID]), TABLE_DELETE, $result);
179
												}
180
181
												$props = mapi_getprops($message, array(PR_ENTRYID, PR_STORE_ENTRYID, PR_PARENT_ENTRYID));
182
												if(!$tr->isTaskRequest()) {
183
													unset($props[PR_MESSAGE_CLASS]);
184
													$GLOBALS["bus"]->notify(bin2hex($props[PR_PARENT_ENTRYID]), $isAccept ? TABLE_SAVE : TABLE_DELETE, $props);
185
												}
186
											break;
187
											case "copy":
188
											case "move":
189
												$this->copy($store, $parententryid, $entryid, $action);
190
												break;
191
192
											case "reply":
193
											case "replyall":
194
											case "forward":
195
											default:
196
												$this->save($store, $parententryid, $entryid, $action);
0 ignored issues
show
Bug introduced by
$parententryid of type object is incompatible with the type string expected by parameter $parententryid of ItemModule::save(). ( Ignorable by Annotation )

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

196
												$this->save($store, /** @scrutinizer ignore-type */ $parententryid, $entryid, $action);
Loading history...
197
										}
198
									} else {
199
										$this->save($store, $parententryid, $entryid, $action);
200
									}
201
								} else {
202
									/**
203
									 * if parententryid or storeentryid is not passed then we can take a guess that
204
									 * it would be  a save operation but instead of depending on server to get default
205
									 * parent and store client should always send parententryid and storeentryid
206
									 *
207
									 * we can also assume that user has permission to right in his own store
208
									 */
209
									$this->save($store, $parententryid, $entryid, $action);
210
								}
211
								break;
212
							case "delete":
213
								$subActionType = false;
214
								if (isset($action["message_action"]) && isset($action["message_action"]["action_type"])) {
215
									$subActionType = $action["message_action"]["action_type"];
216
								}
217
218
								/*
219
								 * The "message_action" object has been set, check the action_type field for
220
								 * the exact action which must be taken.
221
								 * Supported actions:
222
								 *   - cancelInvitation: organizer cancels already scheduled meeting
223
								 *   - removeFromCalendar: attendee receives meeting cancellation and wants to remove item from calendar
224
								 */
225
								switch($subActionType)
226
								{
227
									case "removeFromCalendar":
228
										$basedate = (isset($action['basedate']) && !empty($action['basedate'])) ? $action['basedate'] : false;
229
230
										$this->removeFromCalendar($store, $entryid, $basedate, $this->directBookingMeetingRequest);
0 ignored issues
show
Bug introduced by
$entryid of type object is incompatible with the type string expected by parameter $entryid of ItemModule::removeFromCalendar(). ( Ignorable by Annotation )

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

230
										$this->removeFromCalendar($store, /** @scrutinizer ignore-type */ $entryid, $basedate, $this->directBookingMeetingRequest);
Loading history...
Bug introduced by
It seems like $basedate can also be of type false; however, parameter $basedate of ItemModule::removeFromCalendar() does only seem to accept string, 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 ignore-type  annotation

230
										$this->removeFromCalendar($store, $entryid, /** @scrutinizer ignore-type */ $basedate, $this->directBookingMeetingRequest);
Loading history...
231
										$this->sendFeedback(true);
232
										break;
233
234
									case "cancelInvitation":
235
										$this->cancelInvitation($store, $entryid, $action, $this->directBookingMeetingRequest);
0 ignored issues
show
Bug introduced by
$entryid of type object is incompatible with the type string expected by parameter $entryid of ItemModule::cancelInvitation(). ( Ignorable by Annotation )

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

235
										$this->cancelInvitation($store, /** @scrutinizer ignore-type */ $entryid, $action, $this->directBookingMeetingRequest);
Loading history...
236
										$this->sendFeedback(true);
237
										break;
238
239
									case "declineMeeting":
240
										// @FIXME can we somehow merge declineMeeting and declineMeetingRequest sub actions?
241
										$message = $GLOBALS["operations"]->openMessage($store, $entryid);
242
										$basedate = (isset($action['basedate']) && !empty($action['basedate'])) ? $action['basedate'] : false;
243
244
										$req = new Meetingrequest($store, $message, $GLOBALS["mapisession"]->getSession(), $this->directBookingMeetingRequest);
245
246
										// @FIXME: may be we can remove this body check any get it while declining meeting 'body'
247
										$body = false;
248
										if (isset($action["props"]["isHTML"]) && $action["props"]["isHTML"] === true) {
249
											$body = isset($action["props"]["html_body"]) ? $action["props"]["html_body"] : false;
250
										} else {
251
											$body = isset($action["props"]["body"]) ? $action["props"]["body"] : false;
252
										}
253
										$req->doDecline(true, $basedate, $body);
0 ignored issues
show
Bug introduced by
It seems like $basedate can also be of type false; however, parameter $basedate of Meetingrequest::doDecline() does only seem to accept string, 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 ignore-type  annotation

253
										$req->doDecline(true, /** @scrutinizer ignore-type */ $basedate, $body);
Loading history...
254
255
										$messageProps = mapi_getprops($message, array(PR_ENTRYID, PR_STORE_ENTRYID, PR_PARENT_ENTRYID));
256
										$GLOBALS["bus"]->notify(bin2hex($messageProps[PR_PARENT_ENTRYID]), $basedate ? TABLE_SAVE : TABLE_DELETE, $messageProps);
257
258
										break;
259
                                    case "snooze":
260
                                    case "dismiss":
261
                                        $this->delete($store, $parententryid, $entryid, $action);
0 ignored issues
show
Bug introduced by
$entryid of type object is incompatible with the type string expected by parameter $entryid of ItemModule::delete(). ( Ignorable by Annotation )

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

261
                                        $this->delete($store, $parententryid, /** @scrutinizer ignore-type */ $entryid, $action);
Loading history...
Bug introduced by
$parententryid of type object is incompatible with the type string expected by parameter $parententryid of ItemModule::delete(). ( Ignorable by Annotation )

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

261
                                        $this->delete($store, /** @scrutinizer ignore-type */ $parententryid, $entryid, $action);
Loading history...
262
                                        break;
263
264
									default:
265
										// Deleting an occurrence means that we have to save the message to
266
										// generate an exception. So when the basedate is provided, we actually
267
										// perform a save rather then delete.
268
										if (isset($action['basedate']) && !empty($action['basedate'])) {
269
											$this->save($store, $parententryid, $entryid, $action, "delete");
0 ignored issues
show
Unused Code introduced by
The call to ItemModule::save() has too many arguments starting with 'delete'. ( Ignorable by Annotation )

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

269
											$this->/** @scrutinizer ignore-call */ 
270
                  save($store, $parententryid, $entryid, $action, "delete");

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.

Loading history...
270
										} else {
271
											$this->delete($store, $parententryid, $entryid, $action);
272
										}
273
										break;
274
								}
275
								break;
276
							default:
277
								$this->handleUnknownActionType($actionType);
278
						}
279
					} catch (MAPIException $e) {
280
						$this->processException($e, $actionType, $store, $parententryid, $entryid, $action);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $entryid does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $parententryid does not seem to be defined for all execution paths leading up to this point.
Loading history...
281
					}
282
				}
283
			}
284
		}
285
286
		/**
287
		 * Function does customization of exception based on module data.
288
		 * like, here it will generate display message based on actionType
289
		 * for particular exception.
290
		 *
291
		 * @param object $e Exception object
292
		 * @param string $actionType the action type, sent by the client
293
		 * @param MAPIobject $store Store object of message.
0 ignored issues
show
Bug introduced by
The type MAPIobject was not found. Maybe you did not declare it correctly or list all dependencies?

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

filter:
    dependency_paths: ["lib/*"]

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

Loading history...
294
		 * @param string $parententryid parent entryid of the message.
295
		 * @param string $entryid entryid of the message.
296
		 * @param array $action the action data, sent by the client
297
		 */
298
		function handleException(&$e, $actionType = null, $store = null, $parententryid = null, $entryid = null, $action = null)
299
		{
300
			if(is_null($e->displayMessage)) {
301
				switch($actionType)
302
				{
303
					case "open":
304
						if($e->getCode() == MAPI_E_NO_ACCESS) {
305
							$e->setDisplayMessage(_("You have insufficient privileges to open this message."));
306
						} elseif($e->getCode() == MAPI_E_NOT_FOUND) {
307
							$e->setDisplayMessage(_("Could not find message, either it has been moved or deleted or you don't have access to open this message."));
308
							// Show error in console instead of a pop-up
309
							if (isset($action["message_action"]['suppress_exception']) && $action["message_action"]['suppress_exception'] === true) {
310
								$e->setNotificationType('console');
311
							}
312
						} else {
313
							$e->setDisplayMessage(_("Could not open message."));
314
							$e->allowToShowDetailsMessage = true;
315
						}
316
						break;
317
318
					case "save":
319
						if($e->getCode() == MAPI_E_NO_ACCESS) {
320
							if (!empty($action["message_action"]["action_type"])) {
321
								switch($action["message_action"]["action_type"])
322
								{
323
									case "declineMeetingRequest":
324
										$e->setDisplayMessage(_("You have insufficient privileges to decline this Meeting Request") . ".");
325
										break;
326
									case "acceptMeetingRequest":
327
										$e->setDisplayMessage(_("You have insufficient privileges to accept this Meeting Request") . ".");
328
										break;
329
									case "copy":
330
										$e->setDisplayMessage(_("Could not copy message") . ".");
331
										break;
332
									case "move":
333
										$e->setDisplayMessage(_("Could not move message") . ".");
334
										break;
335
								}
336
							}
337
338
							if(empty($e->displayMessage)) {
339
								$e->setDisplayMessage(_("You have insufficient privileges to save items in this folder") . ".");
340
							}
341
						} else if($e->getCode() == MAPI_E_STORE_FULL) {
342
							$e->setDisplayMessage($this->getOverQuotaMessage($store));
343
						} else {
344
							$e->setDisplayMessage(_("Could not save message") . ".");
345
							$e->allowToShowDetailsMessage = true;
346
						}
347
						break;
348
349
					case 'delete':
350
						switch ($e->getCode()) {
351
							case MAPI_E_NO_ACCESS:
352
								if (!empty($action['message_action']['action_type'])) {
353
									switch($action['message_action']['action_type'])
354
									{
355
										case 'removeFromCalendar':
356
											$e->setDisplayMessage(_('You have insufficient privileges to remove item from the calendar.'));
357
											break;
358
									}
359
								}
360
								break;
361
							case MAPI_E_NOT_IN_QUEUE:
362
								$e->setDisplayMessage(_('Message is no longer in the outgoing queue, typically because it has already been sent.'));
363
								break;
364
							case MAPI_E_UNABLE_TO_ABORT:
365
								$e->setDisplayMessage(_('Message cannot be aborted'));
366
								break;
367
						}
368
						if(empty($e->displayMessage)) {
369
							$e->setDisplayMessage(_("You have insufficient privileges to delete items in this folder") . ".");
370
						}
371
						break;
372
373
					case "attach_items":
374
						if($e->getCode() == MAPI_E_NO_ACCESS)
375
							$e->setDisplayMessage(_("You have insufficient privileges to attach item as an attachment."));
376
						else
377
							$e->setDisplayMessage(_("Could not attach item as an attachment."));
378
						break;
379
380
					case "reclaimownership":
381
						if($e->getCode() == MAPI_E_NO_ACCESS)
382
							$e->setDisplayMessage(_("You have insufficient privileges to reclaim the ownership for the Task Request."));
383
						else
384
							$e->setDisplayMessage(_("Could not reclaim the ownership for the Task Request."));
385
						break;
386
387
					case "acceptTaskRequest":
388
						if($e->getCode() == MAPI_E_NO_ACCESS)
389
							$e->setDisplayMessage(_("You have insufficient privileges to accept this Task Request."));
390
						else
391
							$e->setDisplayMessage(_("Could not accept Task Request."));
392
						break;
393
394
					case "declineTaskRequest":
395
						if($e->getCode() == MAPI_E_NO_ACCESS)
396
							$e->setDisplayMessage(_("You have insufficient privileges to decline this Task Request."));
397
						else
398
							$e->setDisplayMessage(_("Could not decline Task Request."));
399
						break;
400
				}
401
				Log::Write(
402
					LOGLEVEL_ERROR,
403
					"itemmodule::handleException():". $actionType . ": " . $e->displayMessage,
404
					$e,
0 ignored issues
show
Unused Code introduced by
The call to Log::Write() has too many arguments starting with $e. ( Ignorable by Annotation )

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

404
				Log::/** @scrutinizer ignore-call */ 
405
         Write(

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.

Loading history...
405
					$action
406
				);
407
			}
408
409
			parent::handleException($e, $actionType, $store, $parententryid, $entryid, $action);
410
		}
411
412
		/**
413
		 * Function which opens an item.
414
		 * @param object $store MAPI Message Store Object
415
		 * @param string $entryid entryid of the message
416
		 * @param array $action the action data, sent by the client
417
		 * @return boolean true on success or false on failure
418
		 */
419
		function open($store, $entryid, $action)
420
		{
421
			$data = array();
422
423
			if($entryid) {
424
				if($store) {
0 ignored issues
show
introduced by
$store is of type object, thus it always evaluated to true.
Loading history...
425
					$message = $GLOBALS['operations']->openMessage($store, $entryid);
426
				} else {
427
					// store is not passed so we need to open the message first to get the store resource
428
					$message = $GLOBALS['mapisession']->openMessage($entryid);
429
430
					$messageStoreInfo = mapi_getprops($message, array(PR_STORE_ENTRYID));
431
					$store = $GLOBALS['mapisession']->openMessageStore($messageStoreInfo[PR_STORE_ENTRYID]);
432
				}
433
			}
434
435
			if(empty($message)) {
436
				return;
437
			}
438
439
			// Decode smime signed messages on this message
440
 			parse_smime($store, $message);
441
442
			// Open embedded message if requested
443
			$attachNum = !empty($action['attach_num']) ? $action['attach_num'] : false;
444
			if($attachNum) {
445
				// get message props of sub message
446
				$parentMessage = $message;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $message does not seem to be defined for all execution paths leading up to this point.
Loading history...
447
				$message = $GLOBALS['operations']->openMessage($store, $entryid, $attachNum, true);
448
449
				if(empty($message)) {
450
					return;
451
				}
452
453
				$data['item'] = $GLOBALS['operations']->getEmbeddedMessageProps($store, $message, $this->properties, $parentMessage, $attachNum);
454
			} else {
455
				// get message props of the message
456
				$data['item'] = $GLOBALS['operations']->getMessageProps($store, $message, $this->properties, $this->plaintext);
457
				$messageClass = !empty($data['item']['props']['message_class']) ? $data['item']['props']['message_class'] : '';
458
459
				// Check for meeting request, do processing if necessary
460
				if(stripos($messageClass, 'IPM.Schedule.Meeting') !== false) {
461
					$req = new Meetingrequest($store, $message, $GLOBALS['mapisession']->getSession(), $this->directBookingMeetingRequest);
462
463
					try {
464
						if($req->isMeetingRequestResponse()) {
465
							if($req->isLocalOrganiser()) {
466
								// We received a meeting request response, and we're the delegate/organiser
467
								$req->processMeetingRequestResponse();
468
							}
469
						} else if($req->isMeetingRequest()) {
470
							if(!$req->isLocalOrganiser()) {
471
								if ($req->isMeetingOutOfDate()) {
472
									// we know that meeting is out of date so directly set this properties
473
									$data['item']['props']['meetingtype'] = mtgOutOfDate;
474
									$data['item']['props']['icon_index'] = 1033;
475
476
									// send update to maillistmodule that meeting request is updated with out of date flag
477
									$messageProps = mapi_getprops($message, array(PR_ENTRYID, PR_PARENT_ENTRYID, PR_STORE_ENTRYID));
478
									$GLOBALS['bus']->notify(bin2hex($messageProps[PR_PARENT_ENTRYID]), TABLE_SAVE, $messageProps);
479
								} else {
480
									/**
481
									 * if meeting request is not out of date then process it for the first time
482
									 * which will create corresponding appointment in the user's calendar
483
									 */
484
									$req->doAccept(true, false, false);
485
								}
486
487
								// Show user whether meeting request conflict with other appointment or not.
488
								$meetingConflicts = $req->isMeetingConflicting();
489
490
								/**
491
								 * if $meetingConflicts is boolean and true then its a normal meeting.
492
								 * if $meetingConflicts is integer then it indicates no of instances of a recurring meeting which conflicts with Calendar.
493
								 */
494
								if($meetingConflicts !== false) {
495
									if ($meetingConflicts === true) {
496
										$data['item']['props']['conflictinfo'] = _('Conflicts with another appointment.');
497
									} else {
498
										$data['item']['props']['conflictinfo'] = sprintf(ngettext('%s occurrence of this recurring appointment conflicts with other appointment.', '%s occurrences of this recurring appointment conflicts with other appointments.', $meetingConflicts), $meetingConflicts);
499
									}
500
								}
501
							}
502
						} else if($req->isMeetingCancellation()) {
503
							$req->processMeetingCancellation();
504
						}
505
506
						if($req->isInCalendar()) {
507
							$calendarItemProps = $this->getCalendarItemProps($req);
508
							if (!empty($calendarItemProps)) {
509
								$data['item']['props'] = array_merge($data['item']['props'], $calendarItemProps);
510
							}
511
						} else {
512
							$data['item']['props']['appointment_not_found'] = true;
513
						}
514
					} catch (MAPIException $e) {
515
						// if quota is exceeded or or we don't have permission to write in calendar folder than ignore the exception.
516
						if($e->getCode() !== MAPI_E_STORE_FULL && $e->getCode() !== MAPI_E_NO_ACCESS) {
517
							// re-throw the exception if it is not one of quota/calendar permission.
518
							throw $e;
519
						}
520
					}
521
				} else if(stripos($messageClass, 'REPORT.IPM.NOTE.NDR') !== false) {
522
					// check if this message is a NDR (mail)message, if so, generate a new body message
523
					$data['item']['props']['isHTML'] = false;
524
					$data['item']['props']['body'] = $this->getNDRbody($message);
525
				}
526
			}
527
528
			$userEntryId = '';
529
			if (isset($data['item']['props']['sent_representing_entryid'])) {
530
				$userEntryId = hex2bin($data['item']['props']['sent_representing_entryid']);
531
			} else if (isset($data['item']['props']['sender_entryid'])) {
532
				$userEntryId = hex2bin($data['item']['props']['sender_entryid']);
533
			}
534
535
			// get user image saved in LDAP.
536
			if (!empty($userEntryId)) {
537
				$data['item']['props']['user_image'] = $GLOBALS['operations']->getCompressedUserImage($userEntryId);
538
			}
539
540
			// Allowing to hook in just before the data sent away to be sent to the client
541
			$GLOBALS['PluginManager']->triggerHook('server.module.itemmodule.open.after', array(
542
				'moduleObject' =>& $this,
543
				'store' => $store,
544
				'entryid' => $entryid,
545
				'action' => $action,
546
				'message' =>& $message,
547
				'data' =>& $data
548
				));
549
550
			$this->addActionData('item', $data);
551
			$GLOBALS['bus']->addData($this->getResponseData());
552
		}
553
554
		/**
555
		 * Function which saves an item.
556
		 * @param object $store MAPI Message Store Object
557
		 * @param string $parententryid parent entryid of the message
558
		 * @param array $action the action data, sent by the client
559
		 * @return boolean true on success or false on failure
560
		 */
561
		function save($store, $parententryid, $entryid, $action)
562
		{
563
			$result = false;
564
565
			if(isset($action["props"])) {
566
				if(!$store) {
0 ignored issues
show
introduced by
$store is of type object, thus it always evaluated to true.
Loading history...
567
					$store = $GLOBALS['mapisession']->getDefaultMessageStore();
568
				}
569
				if(!$parententryid) {
570
					if(isset($action['props']['message_class'])) {
571
						$parententryid = $this->getDefaultFolderEntryID($store, $action['props']['message_class']);
572
					} else {
573
						$parententryid = $this->getDefaultFolderEntryID($store, '');
574
					}
575
				}
576
577
				if($store && $parententryid) {
578
					$props = Conversion::mapXML2MAPI($this->properties, $action["props"]);
579
580
					$messageProps = array(); // props returned from saveMessage
581
582
					// Save message
583
					if(!empty($props)){
584
						$result = $GLOBALS["operations"]->saveMessage($store, $entryid, $parententryid, $props, $messageProps, array(), (!empty($action['attachments']) ? $action['attachments'] : array()));
585
					}
586
587
					if($result) {
588
						$GLOBALS["bus"]->notify(bin2hex($parententryid), TABLE_SAVE, $messageProps);
589
590
						$this->addActionData("update", array("item" => Conversion::mapMAPI2XML($this->properties, $messageProps)));
591
						$GLOBALS["bus"]->addData($this->getResponseData());
592
					} else {
593
						$this->sendFeedback(false);
594
					}
595
				}
596
			}
597
		}
598
599
		/**
600
		 * Function which deletes an item.
601
		 * @param object $store MAPI Message Store Object
602
		 * @param string $parententryid parent entryid of the message
603
		 * @param string $entryid entryid of the message
604
		 * @param array $action the action data, sent by the client
605
		 * @return boolean true on success or false on failure
606
		 */
607
		function delete($store, $parententryid, $entryid, $action)
608
		{
609
			if($store && $parententryid && $entryid) {
610
				$props = array();
611
				$props[PR_PARENT_ENTRYID] = $parententryid;
612
				$props[PR_ENTRYID] = $entryid;
613
614
				$storeprops = mapi_getprops($store, array(PR_ENTRYID));
615
				$props[PR_STORE_ENTRYID] = $storeprops[PR_ENTRYID];
616
617
				$result = $GLOBALS["operations"]->deleteMessages($store, $parententryid, $entryid, isset($action['message_action']['soft_delete']) ? $action['message_action']['soft_delete'] : false);
618
619
				if($result) {
620
					$GLOBALS["bus"]->notify(bin2hex($parententryid), TABLE_DELETE, $props);
621
					$this->sendFeedback(true);
622
				}
623
			}
624
		}
625
626
		/**
627
		 * Function which returns the entryid of a default folder.
628
		 * @param object $store MAPI Message Store Object
629
		 * @param string $messageClass the class of the folder
630
		 * @return string entryid of a default folder, false if not found
631
		 */
632
		function getDefaultFolderEntryID($store, $messageClass)
633
		{
634
			$entryid = false;
635
636
			if($store) {
0 ignored issues
show
introduced by
$store is of type object, thus it always evaluated to true.
Loading history...
637
				$rootcontainer = mapi_msgstore_openentry($store);
638
				$rootcontainerprops = mapi_getprops($rootcontainer, array(PR_IPM_DRAFTS_ENTRYID, PR_IPM_APPOINTMENT_ENTRYID, PR_IPM_CONTACT_ENTRYID, PR_IPM_JOURNAL_ENTRYID, PR_IPM_NOTE_ENTRYID, PR_IPM_TASK_ENTRYID));
639
640
				switch($messageClass)
641
				{
642
					case "IPM.Appointment":
643
						if(isset($rootcontainerprops[PR_IPM_APPOINTMENT_ENTRYID])) {
644
							$entryid = $rootcontainerprops[PR_IPM_APPOINTMENT_ENTRYID];
645
						}
646
						break;
647
					case "IPM.Contact":
648
					case "IPM.DistList":
649
						if(isset($rootcontainerprops[PR_IPM_CONTACT_ENTRYID])) {
650
							$entryid = $rootcontainerprops[PR_IPM_CONTACT_ENTRYID];
651
						}
652
						break;
653
					case "IPM.StickyNote":
654
						if(isset($rootcontainerprops[PR_IPM_NOTE_ENTRYID])) {
655
							$entryid = $rootcontainerprops[PR_IPM_NOTE_ENTRYID];
656
						}
657
						break;
658
					case "IPM.Task":
659
						if(isset($rootcontainerprops[PR_IPM_TASK_ENTRYID])) {
660
							$entryid = $rootcontainerprops[PR_IPM_TASK_ENTRYID];
661
						}
662
						break;
663
					default:
664
						if(isset($rootcontainerprops[PR_IPM_DRAFTS_ENTRYID])) {
665
							$entryid = $rootcontainerprops[PR_IPM_DRAFTS_ENTRYID];
666
						}
667
						break;
668
				}
669
			}
670
671
			return $entryid;
672
		}
673
674
		/**
675
		 * Function which copies or moves one or more items.
676
		 * @param MAPIStore $store MAPI Message Store Object
0 ignored issues
show
Bug introduced by
The type MAPIStore was not found. Maybe you did not declare it correctly or list all dependencies?

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

filter:
    dependency_paths: ["lib/*"]

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

Loading history...
677
		 * @param binString $parententryid entryid of the folder
0 ignored issues
show
Bug introduced by
The type binString was not found. Maybe you did not declare it correctly or list all dependencies?

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

filter:
    dependency_paths: ["lib/*"]

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

Loading history...
678
		 * @param array $entryid list of entryids which will be copied or moved (in binary format)
679
		 * @param array $action the action data, sent by the client
680
		 * @return boolean true on success or false on failure
681
		 */
682
		function copy($store, $parententryid, $entryids, $action)
683
		{
684
			$result = false;
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
685
686
			if($store && $parententryid && $entryids) {
0 ignored issues
show
introduced by
$parententryid is of type binString, thus it always evaluated to true.
Loading history...
687
				$dest_store = $store;
688
				if(isset($action["message_action"]["destination_store_entryid"])) {
689
					$dest_storeentryid = hex2bin($action["message_action"]["destination_store_entryid"]);
690
					$dest_store = $GLOBALS["mapisession"]->openMessageStore($dest_storeentryid);
691
				}
692
693
				$dest_folderentryid = false;
694
				if(isset($action["message_action"]["destination_parent_entryid"])) {
695
					$dest_folderentryid = hex2bin($action["message_action"]["destination_parent_entryid"]);
696
				}
697
698
				$moveMessages = false;
699
				if(isset($action["message_action"]["action_type"]) && $action["message_action"]["action_type"] == "move") {
700
					$moveMessages = true;
701
				}
702
703
				// if item has some set of props that need to be saved into the newly copied/moved item
704
				$copyProps = array();
705
				if (isset($action["message_action"]["dropmodifications"])) {
706
					$copyProps = Conversion::mapXML2MAPI($this->properties, $action["message_action"]["dropmodifications"]);
707
				}
708
709
				// if item has some changes made before choosing different calendar from create-in dropdown
710
				if (isset($action["props"]) && !empty($action["props"])) {
711
					$copyProps = Conversion::mapXML2MAPI($this->properties, $action["props"]);
712
				}
713
714
				$props = array();
715
				$props[PR_PARENT_ENTRYID] = $parententryid;
716
				$props[PR_ENTRYID] = $entryids;
717
718
				$storeprops = mapi_getprops($store, array(PR_ENTRYID));
719
				$props[PR_STORE_ENTRYID] = $storeprops[PR_ENTRYID];
720
721
				$skipCopyProperties = array();
722
				if (isset($action["message_action"]["unset_Private"])) {
723
					if ($moveMessages) {
724
						array_push($skipCopyProperties, $this->properties["private"], $this->properties["sensitivity"]);
725
					} else {
726
						array_push($this->skipCopyProperties, $this->properties["private"], $this->properties["sensitivity"]);
727
					}
728
				}
729
730
731
				$result = $GLOBALS["operations"]->copyMessages($store, $parententryid, $dest_store, $dest_folderentryid, $entryids, $moveMessages ? $skipCopyProperties : $this->skipCopyProperties, $moveMessages, $copyProps);
732
733
				if($result) {
734
					if($moveMessages) {
735
						$GLOBALS["bus"]->notify(bin2hex($parententryid), TABLE_DELETE, $props);
736
					}
737
738
					// Delete the PR_ENTRYID, the copied or moved message has a new entryid,
739
					// and at this time we have no idea what that might be. So make sure
740
					// we unset it, otherwise the notification handlers get weird ideas
741
					// and could reset the PR_PARENT_ENTRYID to the old folder again.
742
					unset($props[PR_ENTRYID]);
743
					$props[PR_PARENT_ENTRYID] = $dest_folderentryid;
744
					$props[PR_STORE_ENTRYID] = $dest_storeentryid;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dest_storeentryid does not seem to be defined for all execution paths leading up to this point.
Loading history...
745
					$GLOBALS["bus"]->notify(bin2hex($dest_folderentryid), TABLE_SAVE, $props);
0 ignored issues
show
Bug introduced by
It seems like $dest_folderentryid can also be of type false; however, parameter $string of bin2hex() does only seem to accept string, 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 ignore-type  annotation

745
					$GLOBALS["bus"]->notify(bin2hex(/** @scrutinizer ignore-type */ $dest_folderentryid), TABLE_SAVE, $props);
Loading history...
746
				}
747
748
				$this->sendFeedback($result, array());
749
			}
750
		}
751
752
		/**
753
		 * Function returns correspondent calendar item's properties attached
754
		 * with the meeting request/response/cancellation.
755
		 * @param Meetingrequest $meetingRequestObject the meeting request object
756
		 * using which function will fetch meeting request properties and return them.
757
		 */
758
		function getCalendarItemProps($meetingRequestObject)
759
		{
760
			$calendarItem = $meetingRequestObject->getCorrespondentCalendarItem();
761
			$props = array();
762
			if ($calendarItem !== false) {
0 ignored issues
show
introduced by
The condition $calendarItem !== false is always true.
Loading history...
763
				$calendarItemProps = mapi_getprops($calendarItem, array(PR_STORE_ENTRYID, PR_PARENT_ENTRYID, PR_ENTRYID, $meetingRequestObject->proptags['updatecounter'], $meetingRequestObject->proptags['goid']));
764
765
				// Store calendar item's necessary properties in props array.
766
				$props['appointment_store_entryid'] = bin2hex($calendarItemProps[PR_STORE_ENTRYID]);
767
				$props['appointment_parent_entryid'] = bin2hex($calendarItemProps[PR_PARENT_ENTRYID]);
768
				$props['appointment_entryid'] = bin2hex($calendarItemProps[PR_ENTRYID]);
769
770
				$props['appointment_updatecounter'] = isset($calendarItemProps[$meetingRequestObject->proptags['updatecounter']]) ? $calendarItemProps[$meetingRequestObject->proptags['updatecounter']] : 0;
771
772
				$messageProps = mapi_getprops($meetingRequestObject->message, array($meetingRequestObject->proptags['goid']));
773
774
				$basedate = $meetingRequestObject->getBasedateFromGlobalID($messageProps[$meetingRequestObject->proptags['goid']]);
775
776
				if($basedate) {
777
					$props['appointment_basedate'] = $basedate;
778
779
					// if basedate is provided then it is exception, so get update counter of the exception
780
					$exception = $meetingRequestObject->getExceptionItem($calendarItem, $basedate);
0 ignored issues
show
Bug introduced by
$basedate of type true is incompatible with the type Unixtime expected by parameter $basedate of Meetingrequest::getExceptionItem(). ( Ignorable by Annotation )

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

780
					$exception = $meetingRequestObject->getExceptionItem($calendarItem, /** @scrutinizer ignore-type */ $basedate);
Loading history...
781
782
					if($exception !== false) {
0 ignored issues
show
introduced by
The condition $exception !== false is always true.
Loading history...
783
						// we are able to find the exception then get updatecounter
784
						$exceptionProps = mapi_getprops($exception, array($meetingRequestObject->proptags['updatecounter']));
785
						$props['appointment_updatecounter'] = isset($exceptionProps[$meetingRequestObject->proptags['updatecounter']]) ? $exceptionProps[$meetingRequestObject->proptags['updatecounter']] : 0;
786
					}
787
				}
788
789
				if($meetingRequestObject->isMeetingRequestResponse()) {
790
					$props['meeting_updated'] = $meetingRequestObject->isMeetingUpdated($basedate);
0 ignored issues
show
Bug introduced by
$basedate of type boolean is incompatible with the type double|integer expected by parameter $basedate of Meetingrequest::isMeetingUpdated(). ( Ignorable by Annotation )

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

790
					$props['meeting_updated'] = $meetingRequestObject->isMeetingUpdated(/** @scrutinizer ignore-type */ $basedate);
Loading history...
791
				}
792
793
				return $props;
794
			}
795
796
			return false;
797
		}
798
799
		/**
800
		* Get a text body for a Non-Delivery report
801
		*
802
		* This function reads the necessary properties from the passed message and constructs
803
		* a user-readable NDR message from those properties
804
		*
805
		* @param mapimessage $message The NDR message to read the information from
0 ignored issues
show
Bug introduced by
The type mapimessage was not found. Maybe you did not declare it correctly or list all dependencies?

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

filter:
    dependency_paths: ["lib/*"]

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

Loading history...
806
		* @return string NDR body message as plaintext message.
807
		*/
808
		function getNDRbody($message)
809
		{
810
			$message_props  = mapi_getprops($message, array(PR_ORIGINAL_SUBJECT,PR_ORIGINAL_SUBMIT_TIME, PR_BODY));
811
			$body = '';
812
813
			// use PR_BODY if it's there, otherwise create a recipient failed message
814
			if(isset($message_props[PR_BODY]) || propIsError(PR_BODY, $message_props) == MAPI_E_NOT_ENOUGH_MEMORY) {
815
				$body = mapi_openproperty($message, PR_BODY);
816
			}
817
818
			if (empty($body)) {
819
				$body = _("Your message did not reach some or all of the intended recipients")."\n\n";
820
				$body .= "\t"._("Subject").": ".$message_props[PR_ORIGINAL_SUBJECT]."\n";
821
				$body .= "\t"._("Sent").":    ".strftime("%a %x %X",$message_props[PR_ORIGINAL_SUBMIT_TIME])."\n\n";
822
				$body .= _("The following recipient(s) could not be reached").":\n";
823
824
				$recipienttable = mapi_message_getrecipienttable($message);
825
				$recipientrows = mapi_table_queryallrows($recipienttable,array(PR_DISPLAY_NAME,PR_REPORT_TIME,PR_REPORT_TEXT));
826
				foreach ($recipientrows as $recipient){
827
					$body .= "\n\t".$recipient[PR_DISPLAY_NAME]." on ".strftime("%a %x %X",$recipient[PR_REPORT_TIME])."\n";
828
					$body .= "\t\t".$recipient[PR_REPORT_TEXT]."\n";
829
				}
830
			}
831
832
			return $body;
833
		}
834
835
		/**
836
		* Send a meeting cancellation
837
		*
838
		* This function sends a meeting cancellation for the meeting references by the passed entryid. It
839
		* will send the meeting cancellation and move the item itself to the waste basket.
840
		*
841
		* @param mapistore $store The store in which the meeting request resides
0 ignored issues
show
Bug introduced by
The type mapistore was not found. Maybe you did not declare it correctly or list all dependencies?

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

filter:
    dependency_paths: ["lib/*"]

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

Loading history...
842
		* @param string $entryid Entryid of the appointment for which the cancellation should be sent.
843
		* @param Object $action data sent by client.
844
		* @param boolean $directBookingMeetingRequest Indicates if a Meeting Request should use direct booking or not
845
		*/
846
		function cancelInvitation($store, $entryid, $action, $directBookingMeetingRequest) {
847
			$message = $GLOBALS['operations']->openMessage($store, $entryid);
848
849
			// @TODO move this to meeting request class ?
850
			$req = new Meetingrequest($store, $message, $GLOBALS['mapisession']->getSession(), $directBookingMeetingRequest);
851
852
			// Update extra body information
853
			if(isset($action['message_action']['meetingTimeInfo']) && !empty($action['message_action']['meetingTimeInfo'])) {
854
				$req->setMeetingTimeInfo($action["message_action"]['meetingTimeInfo']);
855
				unset($action["message_action"]['meetingTimeInfo']);
856
			}
857
858
			// get basedate from action data and pass to meeting request class
859
			$basedate = !empty($action['basedate']) ? $action['basedate'] : false;
860
861
			$req->doCancelInvitation($basedate);
0 ignored issues
show
Bug introduced by
It seems like $basedate can also be of type false; however, parameter $basedate of Meetingrequest::doCancelInvitation() does only seem to accept string, 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 ignore-type  annotation

861
			$req->doCancelInvitation(/** @scrutinizer ignore-type */ $basedate);
Loading history...
862
863
			if($basedate !== false) {
864
				// if basedate is specified then we have created exception in recurring meeting request
865
				// so send notification of creation of exception
866
				$messageProps = mapi_getprops($message, array(PR_ENTRYID, PR_STORE_ENTRYID, PR_PARENT_ENTRYID));
867
				$GLOBALS["bus"]->notify(bin2hex($messageProps[PR_PARENT_ENTRYID]), TABLE_SAVE, $messageProps);
868
			} else {
869
				// for normal/recurring meetings send delete notification
870
				$messageProps = mapi_getprops($message, array(PR_ENTRYID, PR_STORE_ENTRYID, PR_PARENT_ENTRYID));
871
				$GLOBALS["bus"]->notify(bin2hex($messageProps[PR_PARENT_ENTRYID]), TABLE_DELETE, $messageProps);
872
			}
873
		}
874
875
		/**
876
		* Remove all appointments for a certain meeting request
877
		*
878
		* This function searches the default calendar for all meeting requests for the specified
879
		* meeting. All those appointments are then removed.
880
		*
881
		* @param mapistore $store Mapi store in which the meeting request and the calendar reside
882
		* @param string $entryid Entryid of the meeting request or appointment for which all items should be deleted
883
		* @param string $basedate if specified contains starttime of day of an occurrence
884
		* @param boolean $directBookingMeetingRequest Indicates if a Meeting Request should use direct booking or not
885
		*/
886
		function removeFromCalendar($store, $entryid, $basedate, $directBookingMeetingRequest) {
887
			$message = $GLOBALS["operations"]->openMessage($store, $entryid);
888
889
			$req = new Meetingrequest($store, $message, $GLOBALS["mapisession"]->getSession(), $directBookingMeetingRequest);
890
891
			$req->doRemoveFromCalendar($basedate);
892
893
			// Notify the bus that the message has been deleted
894
			$messageProps = mapi_getprops($message, array(PR_ENTRYID, PR_STORE_ENTRYID, PR_PARENT_ENTRYID));
895
			$GLOBALS["bus"]->notify(bin2hex($messageProps[PR_PARENT_ENTRYID]), $basedate? TABLE_SAVE : TABLE_DELETE, $messageProps);
896
		}
897
	}
898
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
899