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

ContactItemModule::updateAppointments()   C

Complexity

Conditions 13
Paths 144

Size

Total Lines 117
Code Lines 83

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 83
nc 144
nop 3
dl 0
loc 117
rs 5.3709
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
	/**
3
	 * Contact ItemModule
4
	 * Module which openes, creates, saves and deletes an item. It 
5
	 * extends the Module class.
6
	 */
7
	class ContactItemModule extends ItemModule
8
	{
9
		/**
10
		 * Constructor
11
		 * @param int $id unique id.
12
		 * @param array $data list of all actions.
13
		 */
14
		function __construct($id, $data)
15
		{
16
			$this->properties = $GLOBALS['properties']->getContactProperties();
0 ignored issues
show
Bug Best Practice introduced by
The property properties does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
17
18
			parent::__construct($id, $data);
19
20
			$this->plaintext = true;
21
		}
22
23
		/**
24
		 * Function which opens an item.
25
		 * @param object $store MAPI Message Store Object
26
		 * @param string $entryid entryid of the message
27
		 * @param array $action the action data, sent by the client
28
		 * @return boolean true on success or false on failure 
29
		 */
30
		function open($store, $entryid, $action)
31
		{
32
			$data = array();
33
34
			if($entryid) {
35
36
				/* Check if given entryid is shared folder distlist then
37
				* get the store of distlist for fetching it's members.
38
				*/
39
				$storeData = $this->getStoreParentEntryIdFromEntryId($entryid);
40
				$store = $storeData["store"];
41
				$message = $storeData["message"];
42
			}
43
44
			if(empty($message)) {
45
				return;
46
			}
47
48
			// Open embedded message if requested
49
			$attachNum = !empty($action['attach_num']) ? $action['attach_num'] : false;
50
			if($attachNum) {
51
				// get message props of sub message
52
				$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...
53
				$message = $GLOBALS['operations']->openMessage($store, $entryid, $attachNum);
54
55
				if(empty($message)) {
56
					return;
57
				}
58
59
				// Check if message is distlist then we need to use different set of properties
60
				$props = mapi_getprops($message, array(PR_MESSAGE_CLASS));
61
62
				if(stripos($props[PR_MESSAGE_CLASS], 'IPM.Distlist') !== false) {
63
					// for distlist we need to use different set of properties
64
					$this->properties = $GLOBALS['properties']->getDistListProperties();
0 ignored issues
show
Bug Best Practice introduced by
The property properties does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
65
				}
66
67
				$data['item'] = $GLOBALS['operations']->getEmbeddedMessageProps($store, $message, $this->properties, $parentMessage, $attachNum);
68
			} else {
69
				// Check if message is distlist then we need to use different set of properties
70
				$props = mapi_getprops($message, array(PR_MESSAGE_CLASS));
71
72
				if(stripos($props[PR_MESSAGE_CLASS], 'IPM.Distlist') !== false) {
73
					// for distlist we need to use different set of properties
74
					$this->properties = $GLOBALS['properties']->getDistListProperties();
75
				}
76
77
				// get message props of the message
78
				$data['item'] = $GLOBALS['operations']->getMessageProps($store, $message, $this->properties, $this->plaintext);
79
			}
80
81
			// By openentry from address book, the entryid will differ, make it same as the origin
82
			$data['item']['entryid'] = bin2hex($entryid);
83
84
			// Allowing to hook in just before the data sent away to be sent to the client
85
			$GLOBALS['PluginManager']->triggerHook('server.module.contactitemmodule.open.after', array(
86
				'moduleObject' =>& $this,
87
				'store' => $store,
88
				'entryid' => $entryid,
89
				'action' => $action,
90
				'message' =>& $message,
91
				'data' =>& $data
92
			));
93
94
			$this->addActionData('item', $data);
95
			$GLOBALS['bus']->addData($this->getResponseData());
96
		}
97
98
		/**
99
		 * Function which saves an item. It sets the right properties for a contact
100
		 * item (address book properties).		 
101
		 * @param object $store MAPI Message Store Object
102
		 * @param string $parententryid parent entryid of the message
103
		 * @param string $entryid entryid of the message
104
		 * @param array $action the action data, sent by the client
105
		 * @return boolean true on success or false on failure		 		 
106
		 */
107
		function save($store, $parententryid, $entryid, $action)
108
		{
109
			$properiesToDelete = array();		// create an array of properties which should be deleted 
110
												// this array is passed to $GLOBALS['operations']->saveMessage() function
111
112
			if(!$store && !$parententryid) {
0 ignored issues
show
introduced by
$store is of type object, thus it always evaluated to true.
Loading history...
113
				if(isset($action['props']['message_class'])) {
114
					$store = $GLOBALS['mapisession']->getDefaultMessageStore();
115
					$parententryid = $this->getDefaultFolderEntryID($store, $action['props']['message_class']);
116
				} else if($entryid) {
117
					$data = $this->getStoreParentEntryIdFromEntryId($entryid);
118
					$store = $data["store"];
119
					$parententryid = $data["parent_entryid"];
120
				}
121
			} else if(!$parententryid) {
122
				if(isset($action['props']['message_class']))
123
					$parententryid = $this->getDefaultFolderEntryID($store, $action['props']['message_class']);
124
			}
125
126
			if($store && $parententryid && isset($action['props'])) {
127
				if(isset($action['members'])) {
128
					// DistList
129
130
					// for distlist we need to use different set of properties
131
					$this->properties = $GLOBALS['properties']->getDistListProperties();
0 ignored issues
show
Bug Best Practice introduced by
The property properties does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
132
133
					// do conversion of client data
134
					$props = Conversion::mapXML2MAPI($this->properties, $action['props']);
135
136
					// collect members
137
					$members = array();
138
					$oneoff_members = array();
139
140
					$items = $action['members'];
141
142
					foreach($items as $item) {
143
						if(empty($item['email_address'])) {
144
							// if no email address is given then mapi_parseoneoff fails, so always give
145
							// email address, OL07 uses Unknown as email address so we do same here
146
							$item['email_address'] = 'Unknown';
147
						}
148
149
						$oneoff = mapi_createoneoff($item['display_name'], $item['address_type'], $item['email_address']);
150
151
						if ($item['distlist_type'] == DL_EXTERNAL_MEMBER) {
152
							$member = $oneoff;
153
						} else {
154
							$parts = array();
155
							$parts['distlist_guid'] = DL_GUID;
156
							$parts['distlist_type'] = $item['distlist_type'];
157
							$parts['entryid'] = hex2bin($item['entryid']);
158
							$member = pack('VA16CA*', 0, $parts['distlist_guid'], $parts['distlist_type'], $parts['entryid']);
159
						}
160
161
						$oneoff_members[] = $oneoff;
162
						$members[] = $member;
163
					}
164
165
					if (!empty($members) && !empty($oneoff_members)) {
166
						$props[$this->properties['members']] = $members;
167
						$props[$this->properties['oneoff_members']] = $oneoff_members;
168
					} else {
169
						$properiesToDelete[] = $this->properties['members'];
170
						$properiesToDelete[] = $this->properties['oneoff_members'];
171
					}
172
173
					unset($action['members']);
174
				} else {
175
					// Contact
176
177
					$isCopyGABToContact = isset($action["message_action"])
178
					&& isset($action["message_action"]["action_type"])
179
					&& $action["message_action"]["action_type"] === "copyToContact";
180
181
					if ($isCopyGABToContact) {
182
						$this->copyGABRecordProps($action);
183
					}
184
					// generate one-off entryids for email addresses
185
					for($index = 1; $index < 4; $index++)
186
					{
187
						if(!empty($action['props']['email_address_' . $index]) && !empty($action['props']['email_address_display_name_' . $index])) {
188
							$action['props']['email_address_entryid_' . $index] = bin2hex(mapi_createoneoff($action['props']['email_address_display_name_' . $index], $action['props']['email_address_type_' . $index], $action['props']['email_address_' . $index]));
189
						}
190
					}
191
192
					// set properties for primary fax number
193
					if(isset($action['props']['fax_1_email_address']) && !empty($action['props']['fax_1_email_address'])) {
194
						$action['props']['fax_1_original_entryid'] = bin2hex(mapi_createoneoff($action['props']['fax_1_original_display_name'], $action['props']['fax_1_address_type'], $action['props']['fax_1_email_address'], MAPI_UNICODE));
195
					} else {
196
						// delete properties to remove previous values
197
						$properiesToDelete[] = $this->properties['fax_1_address_type'];
198
						$properiesToDelete[] = $this->properties['fax_1_original_display_name'];
199
						$properiesToDelete[] = $this->properties['fax_1_email_address'];
200
						$properiesToDelete[] = $this->properties['fax_1_original_entryid'];
201
					}
202
203
					// set properties for business fax number
204
					if(isset($action['props']['fax_2_email_address']) && !empty($action['props']['fax_2_email_address'])) {
205
						$action['props']['fax_2_original_entryid'] = bin2hex(mapi_createoneoff($action['props']['fax_2_original_display_name'], $action['props']['fax_2_address_type'], $action['props']['fax_2_email_address'], MAPI_UNICODE));
206
					} else {
207
						$properiesToDelete[] = $this->properties['fax_2_address_type'];
208
						$properiesToDelete[] = $this->properties['fax_2_original_display_name'];
209
						$properiesToDelete[] = $this->properties['fax_2_email_address'];
210
						$properiesToDelete[] = $this->properties['fax_2_original_entryid'];
211
					}
212
213
					// set properties for home fax number
214
					if(isset($action['props']['fax_3_email_address']) && !empty($action['props']['fax_3_email_address'])) {
215
						$action['props']['fax_3_original_entryid'] = bin2hex(mapi_createoneoff($action['props']['fax_3_original_display_name'], $action['props']['fax_3_address_type'], $action['props']['fax_3_email_address'], MAPI_UNICODE));
216
					} else {
217
						$properiesToDelete[] = $this->properties['fax_3_address_type'];
218
						$properiesToDelete[] = $this->properties['fax_3_original_display_name'];
219
						$properiesToDelete[] = $this->properties['fax_3_email_address'];
220
						$properiesToDelete[] = $this->properties['fax_3_original_entryid'];
221
					}
222
223
					// check for properties which should be deleted
224
					if(isset($action['entryid']) && !empty($action['entryid'])) {
225
						// check for empty email address properties
226
						for($i = 1; $i < 4; $i++)
227
						{
228
							if(isset($action['props']['email_address_' . $i]) && empty($action['props']['email_address_' . $i])) {
229
								array_push($properiesToDelete, $this->properties['email_address_entryid_' . $i]);
230
								array_push($properiesToDelete, $this->properties['email_address_' . $i]);
231
								array_push($properiesToDelete, $this->properties['email_address_display_name_' . $i]);
232
								array_push($properiesToDelete, $this->properties['email_address_display_name_email_' . $i]);
233
								array_push($properiesToDelete, $this->properties['email_address_type_' . $i]);
234
							}
235
						}
236
237
						// check for empty address_book_mv and address_book_long properties
238
						if(isset($action['props']['address_book_long']) && $action['props']['address_book_long'] === 0) {
239
							$properiesToDelete[] = $this->properties['address_book_mv'];
240
							$properiesToDelete[] = $this->properties['address_book_long'];
241
						}
242
243
						// Check if the birthday and anniversary properties are empty. If so delete them.
244
						if(array_key_exists('birthday', $action['props']) && empty($action['props']['birthday'])){
245
							array_push($properiesToDelete, $this->properties['birthday']);
246
							array_push($properiesToDelete, $this->properties['birthday_eventid']);
247
							if(!empty($action['props']['birthday_eventid'])) {
248
								$this->deleteSpecialDateAppointment($store, $action['props']['birthday_eventid']);
249
							}
250
						}
251
252
						if(array_key_exists('wedding_anniversary', $action['props']) && empty($action['props']['wedding_anniversary'])){
253
							array_push($properiesToDelete, $this->properties['wedding_anniversary']);
254
							array_push($properiesToDelete, $this->properties['anniversary_eventid']);
255
							if(!empty($action['props']['anniversary_eventid'])) {
256
								$this->deleteSpecialDateAppointment($store, $action['props']['anniversary_eventid']);
257
							}
258
						}
259
					}
260
261
					/** 
262
					 * convert all line endings(LF) into CRLF
263
					 * XML parser will normalize all CR, LF and CRLF into LF
264
					 * but outlook(windows) uses CRLF as line ending
265
					 */
266
					if(isset($action['props']['business_address'])) {
267
						$action['props']['business_address'] = str_replace('\n', '\r\n', $action['props']['business_address']);
268
					}
269
270
					if(isset($action['props']['home_address'])) {
271
						$action['props']['home_address'] = str_replace('\n', '\r\n', $action['props']['home_address']);
272
					}
273
274
					if(isset($action['props']['other_address'])) {
275
						$action['props']['other_address'] = str_replace('\n', '\r\n', $action['props']['other_address']);
276
					}
277
278
					// check birthday props to make an appointment
279
					if(!empty($action['props']['birthday'])){
280
						$action['props']['birthday_eventid'] = $this->updateAppointments($store, $action, 'birthday');
281
					}
282
283
					// check anniversary props to make an appointment
284
					if(!empty($action['props']['wedding_anniversary'])){
285
						$action['props']['anniversary_eventid'] = $this->updateAppointments($store, $action, 'wedding_anniversary');
286
					}
287
288
					// do the conversion when all processing has been finished
289
					$props = Conversion::mapXML2MAPI($this->properties, $action['props']);
290
				}
291
292
				$messageProps = array();
293
294
				$result = $GLOBALS['operations']->saveMessage($store, $entryid, $parententryid, $props, $messageProps, array(), isset($action['attachments']) ? $action['attachments'] : array(), $properiesToDelete);
295
296
				if($result) {
297
					$GLOBALS['bus']->notify(bin2hex($parententryid), TABLE_SAVE, $messageProps);
298
299
					if ($isCopyGABToContact) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $isCopyGABToContact does not seem to be defined for all execution paths leading up to this point.
Loading history...
300
						$message = mapi_msgstore_openentry($store,$messageProps[PR_ENTRYID]);
301
						$messageProps = mapi_getprops($message, $this->properties);
302
					}
303
304
					$this->addActionData('update', array('item' => Conversion::mapMAPI2XML($this->properties, $messageProps)));
305
					$GLOBALS['bus']->addData($this->getResponseData());
306
				}
307
			}
308
		}
309
310
		/**
311
		 * Function copy the some property from address book record to contact props.
312
		 *
313
		 * @param array $action the action data, sent by the client
314
		 */
315
		function copyGABRecordProps(&$action)
316
		{
317
			$addrbook = $GLOBALS["mapisession"]->getAddressbook();
318
			$abitem = mapi_ab_openentry($addrbook, hex2bin($action["message_action"]["source_entryid"]));
319
			$abItemProps = mapi_getprops($abitem, array(
320
				PR_COMPANY_NAME,
321
				PR_ASSISTANT,
322
				PR_BUSINESS_TELEPHONE_NUMBER,
323
				PR_BUSINESS2_TELEPHONE_NUMBER,
324
				PR_HOME2_TELEPHONE_NUMBER,
325
				PR_STREET_ADDRESS,
326
				PR_LOCALITY,
327
				PR_STATE_OR_PROVINCE,
328
				PR_POSTAL_CODE,
329
				PR_COUNTRY,
330
				PR_MOBILE_TELEPHONE_NUMBER,
331
			));
332
			$action["props"]["company_name"] = isset($abItemProps[PR_COMPANY_NAME]) ? $abItemProps[PR_COMPANY_NAME] : '';
333
			$action["props"]["assistant"] = isset($abItemProps[PR_ASSISTANT]) ? $abItemProps[PR_ASSISTANT] : '';
334
			$action["props"]["business_telephone_number"] = isset($abItemProps[PR_BUSINESS_TELEPHONE_NUMBER]) ? $abItemProps[PR_BUSINESS_TELEPHONE_NUMBER] : '';
335
			$action["props"]["business2_telephone_number"] = isset($abItemProps[PR_BUSINESS2_TELEPHONE_NUMBER]) ? $abItemProps[PR_BUSINESS2_TELEPHONE_NUMBER] : '';
336
			$action["props"]["home2_telephone_number"] = isset($abItemProps[PR_HOME2_TELEPHONE_NUMBER]) ? $abItemProps[PR_HOME2_TELEPHONE_NUMBER] : '';
337
			$action["props"]["home_address_street"] = isset($abItemProps[PR_STREET_ADDRESS]) ? $abItemProps[PR_STREET_ADDRESS] : '';
338
			$action["props"]["home_address_city"] = isset($abItemProps[PR_LOCALITY]) ? $abItemProps[PR_LOCALITY] : '';
339
			$action["props"]["home_address_state"] = isset($abItemProps[PR_STATE_OR_PROVINCE]) ? $abItemProps[PR_STATE_OR_PROVINCE] : '';
340
			$action["props"]["home_address_postal_code"] = isset($abItemProps[PR_POSTAL_CODE]) ? $abItemProps[PR_POSTAL_CODE] : '';
341
			$action["props"]["home_address_country"] = isset($abItemProps[PR_COUNTRY]) ? $abItemProps[PR_COUNTRY] : '';
342
343
			$action["props"]["cellular_telephone_number"] = isset($abItemProps[PR_MOBILE_TELEPHONE_NUMBER]) ? $abItemProps[PR_MOBILE_TELEPHONE_NUMBER] : '';
344
345
			
346
			// Set the home_address property value
347
			$props = ["street", "city", "state" , "postal_code", "country"];
348
			$homeAddress = "";
349
			foreach ($props as $index => $prop) {
350
				if (isset($action["props"]["home_address_" . $prop]) && !empty($action["props"]["home_address_" . $prop])) {
351
					$homeAddress .= $action["props"]["home_address_" . $prop] . " ";
352
					if ($prop == "street" || $prop == "postal_code") {
353
						$homeAddress .= PHP_EOL;
354
					}
355
				}
356
			}
357
358
			$action["props"]["home_address"] = $homeAddress;
359
		}
360
361
		/**
362
		 * Function which deletes an item. Extended here to also delete corresponding birthday/anniversary
363
		 * appointments from calendar.
364
		 * @param object $store MAPI Message Store Object
365
		 * @param string $parententryid parent entryid of the message
366
		 * @param string $entryid entryid of the message
367
		 * @param array $action the action data, sent by the client
368
		 */
369
		function delete($store, $parententryid, $entryid, $action)
370
		{
371
			$message = false;
372
			if(!$store && !$parententryid && $entryid) {
0 ignored issues
show
introduced by
$store is of type object, thus it always evaluated to true.
Loading history...
373
				$data = $this->getStoreParentEntryIdFromEntryId($entryid);
374
				$store = $data["store"];
375
				$message = $data["message"];
376
				$parententryid = $data["parent_entryid"];
377
			}
378
379
			if($store && $entryid) {
380
				try {
381
					if ($message === false) {
0 ignored issues
show
introduced by
The condition $message === false is always true.
Loading history...
382
						$message = $GLOBALS["operations"]->openMessage($store, $entryid);
383
					}
384
385
					$props = mapi_getprops($message, array($this->properties['anniversary_eventid'], $this->properties['birthday_eventid']));
386
387
					// if any of the appointment entryid exists then delete it
388
					if(!empty($props[$this->properties['birthday_eventid']])) {
389
						$this->deleteSpecialDateAppointment($store, bin2hex($props[$this->properties['birthday_eventid']]));
390
					}
391
392
					if(!empty($props[$this->properties['anniversary_eventid']])) {
393
						$this->deleteSpecialDateAppointment($store, bin2hex($props[$this->properties['anniversary_eventid']]));
394
					}
395
				} catch(MAPIException $e) {
396
					// if any error occurs in deleting appointments then we shouldn't block deletion of contact item
397
					// so ignore errors now
398
					$e->setHandled();
399
				}
400
401
				parent::delete($store, $parententryid, $entryid, $action);
402
			}
403
		}
404
405
		/**
406
		 * Function which retrieve the store, parent_entryid from record entryid.
407
		 * @param $entryid entryid of the message
408
		 * @return array which contains store and message object and parent entryid of that message.
409
		 */
410
		function getStoreParentEntryIdFromEntryId($entryid)
411
		{
412
			$message = $GLOBALS['mapisession']->openMessage($entryid);
413
			$messageStoreInfo = mapi_getprops($message, array(PR_STORE_ENTRYID, PR_PARENT_ENTRYID));
414
			$store = $GLOBALS['mapisession']->openMessageStore($messageStoreInfo[PR_STORE_ENTRYID]);
415
			$parentEntryid = $messageStoreInfo[PR_PARENT_ENTRYID];
416
			return array("message" => $message, "store" => $store, "parent_entryid" => $parentEntryid);
417
		}
418
419
		/**
420
		 * Function will create/update a yearly recurring appointment on the respective date of birthday or anniversary in user's calendar.	 
421
		 * @param object $store MAPI Message Store Object
422
		 * @param array $action the action data, sent by the client
423
		 * @param string $type type of appointment that should be created/updated, valid values are 'birthday' and 'wedding_anniversary'.
424
		 * @return HexString entryid of the newly created appointment in hex format.
0 ignored issues
show
Bug introduced by
The type HexString 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...
425
		 */
426
		function updateAppointments($store, $action, $type)
427
		{
428
			$result = false;
429
430
			$root = mapi_msgstore_openentry($store, null);
431
			$rootProps = mapi_getprops($root, Array(PR_IPM_APPOINTMENT_ENTRYID, PR_STORE_ENTRYID));
432
			$parentEntryId = bin2hex($rootProps[PR_IPM_APPOINTMENT_ENTRYID]);
433
			$storeEntryId = bin2hex($rootProps[PR_STORE_ENTRYID]);
434
435
			$actionProps = $action['props'];
436
			$subject = !empty($actionProps['subject']) ? $actionProps['subject'] : _('Untitled');
437
			$subject = ($type === 'birthday' ? sprintf(_('%s\'s Birthday'), $subject) : sprintf(_('%s\'s Anniversary'), $subject));
438
439
			// UTC time
440
			$startDateUTC = $actionProps[$type];
441
			$dueDateUTC = $actionProps[$type] + (24 * 60 * 60);	// ONE DAY is added to set duedate of item.
442
443
			// get local time from UTC time
444
			$recur = new Recurrence($store, array());
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

444
			$recur = new Recurrence(/** @scrutinizer ignore-type */ $store, array());
Loading history...
Bug introduced by
array() of type array is incompatible with the type resource expected by parameter $message 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

444
			$recur = new Recurrence($store, /** @scrutinizer ignore-type */ array());
Loading history...
445
			$startDate = $recur->fromGMT($actionProps, $startDateUTC);
446
			$dueDate = $recur->fromGMT($actionProps, $dueDateUTC);
447
448
			// Find the number of minutes since the start of the year to the given month,
449
			// taking leap years into account.
450
			$month =  strftime('%m', $startDate);
451
			$year =  strftime('%y', $startDate);
452
453
			$d1 = new DateTime();
454
			$d1->setDate($year, 1, 1);
0 ignored issues
show
Bug introduced by
$year of type string is incompatible with the type integer expected by parameter $year of DateTime::setDate(). ( Ignorable by Annotation )

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

454
			$d1->setDate(/** @scrutinizer ignore-type */ $year, 1, 1);
Loading history...
455
			$d2 = new DateTime();
456
			$d2->setDate($year, $month, 1);
0 ignored issues
show
Bug introduced by
$month of type string is incompatible with the type integer expected by parameter $month of DateTime::setDate(). ( Ignorable by Annotation )

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

456
			$d2->setDate($year, /** @scrutinizer ignore-type */ $month, 1);
Loading history...
457
458
			$diff = $d2->diff($d1);
459
			$month = $diff->days * 24 * 60;
460
461
			$props = array (
462
				'message_class' => 'IPM.Appointment',
463
				'icon_index' => 1025,
464
				'busystatus' => fbFree,
465
				'meeting' => olNonMeeting,
466
				'object_type' => MAPI_MESSAGE,
467
				'message_flags' => MSGFLAG_READ | MSGFLAG_UNSENT,
468
				'subject' => $subject,
469
470
				'startdate' => $startDateUTC,
471
				'duedate' => $dueDateUTC,
472
				'commonstart' => $startDateUTC,
473
				'commonend' => $dueDateUTC,
474
				'alldayevent' => true,
475
				'duration' => 1440,
476
				'reminder' => true, 
477
				'reminder_minutes' => 1080,
478
				'reminder_time' => $startDateUTC,
479
				'flagdueby' => $startDateUTC - (1080 * 60),
480
481
				'recurring' => true,
482
				'recurring_reset' => true,
483
				'startocc' => 0,
484
				'endocc' => 1440,
485
				'start' => $startDate,
486
				'end' => $dueDate,
487
				'term' => 35,
488
				'everyn' => 12,
489
				'subtype' => 2,
490
				'type' => 13,
491
				'regen' => 0,
492
				'month' => $month,
493
				'monthday' => strftime('%e', $startDate),
494
				'timezone' => $actionProps['timezone'],
495
				'timezonedst' => $actionProps['timezonedst'],
496
				'dststartmonth' => $actionProps['dststartmonth'],
497
				'dststartweek' => $actionProps['dststartweek'],
498
				'dststartday' => $actionProps['dststartday'],
499
				'dststarthour' => $actionProps['dststarthour'],
500
				'dstendmonth' => $actionProps['dstendmonth'],
501
				'dstendweek' => $actionProps['dstendweek'],
502
				'dstendday' => $actionProps['dstendday'],
503
				'dstendhour' => $actionProps['dstendhour']
504
			);
505
506
			$data = array();
507
			$data['store'] = $storeEntryId;
508
			$data['parententryid'] = $parentEntryId;
509
510
			$entryid = false;
511
			// if entryid is provided then update existing appointment, else create new one
512
			if($type === 'birthday' && !empty($actionProps['birthday_eventid'])) {
513
				$entryid = $actionProps['birthday_eventid'];
514
			} else if($type === 'wedding_anniversary' && !empty($actionProps['anniversary_eventid'])) {
515
				$entryid = $actionProps['anniversary_eventid'];
516
			}
517
518
			if($entryid !== false) {
519
				$data['entryid'] = $entryid;
520
			}
521
522
			$data['props'] = $props;
523
524
			// Save appointment (saveAppointment takes care of creating/modifying exceptions to recurring
525
			// items if necessary)
526
			try {
527
				$messageProps = $GLOBALS['operations']->saveAppointment($store, hex2bin($entryid), hex2bin($parentEntryId), $data);
528
			} catch (MAPIException $e) {
529
				// if the appointment is deleted then create a new one
530
				if($e->getCode() == MAPI_E_NOT_FOUND) {
531
					$e->setHandled();
532
					$messageProps = $GLOBALS['operations']->saveAppointment($store, false, hex2bin($parentEntryId), $data);
533
				}
534
			}
535
536
			// Notify the bus if the save was OK
537
			if($messageProps && !(is_array($messageProps) && isset($messageProps['error'])) ){
538
				$GLOBALS['bus']->notify($parentEntryId, TABLE_SAVE, $messageProps);
539
				$result = bin2hex($messageProps[PR_ENTRYID]);
540
			}
541
542
			return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result returns the type false|string which is incompatible with the documented return type HexString.
Loading history...
543
		}
544
545
		/**
546
		 * Function will delete the appointment on the respective date of birthday or anniversary in user's calendar.
547
		 * @param object $store MAPI Message Store Object
548
		 * @param $entryid of the message with will be deleted,sent by the client
0 ignored issues
show
Bug introduced by
The type of 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...
549
		 */
550
		function deleteSpecialDateAppointment($store, $entryid)
551
		{
552
			$root = mapi_msgstore_openentry($store, null);
553
			$rootProps = mapi_getprops($root, Array(PR_IPM_APPOINTMENT_ENTRYID, PR_STORE_ENTRYID));
554
			$parentEntryId = $rootProps[PR_IPM_APPOINTMENT_ENTRYID];
555
			$storeEntryId = $rootProps[PR_STORE_ENTRYID];
556
557
			$props = array();
558
			$props[PR_PARENT_ENTRYID] = $parentEntryId;
559
			$props[PR_ENTRYID] = hex2bin($entryid);
560
			$props[PR_STORE_ENTRYID] = $storeEntryId;
561
562
			$result = $GLOBALS['operations']->deleteMessages($store, $parentEntryId, $props[PR_ENTRYID]);
563
564
			if($result) {
565
				$GLOBALS['bus']->notify(bin2hex($parentEntryId), TABLE_DELETE, $props);
566
			}
567
		}
568
	}
569
?>
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...
570