grommunio /
grommunio-web
| 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(); |
||
| 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; |
||
| 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(); |
||
| 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) { |
||
| 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(); |
||
| 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) { |
||
| 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) { |
||
| 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
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. |
||
| 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()); |
||
| 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); |
||
| 455 | $d2 = new DateTime(); |
||
| 456 | $d2->setDate($year, $month, 1); |
||
| 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; |
||
| 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 |
||
| 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
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 |