Example #1
0
 /**
  * This method is used in cases where an event got updated, and we
  * potentially need to send emails to attendees to let them know of updates
  * in the events.
  *
  * We will detect which attendees got added, which got removed and create
  * specific messages for these situations.
  *
  * @param VCalendar $calendar
  * @param array $eventInfo
  * @param array $oldEventInfo
  * @return array
  */
 protected function parseEventForOrganizer(VCalendar $calendar, array $eventInfo, array $oldEventInfo)
 {
     // Merging attendee lists.
     $attendees = array();
     foreach ($oldEventInfo['attendees'] as $attendee) {
         $attendees[$attendee['href']] = array('href' => $attendee['href'], 'oldInstances' => $attendee['instances'], 'newInstances' => array(), 'name' => $attendee['name'], 'forceSend' => null);
     }
     foreach ($eventInfo['attendees'] as $attendee) {
         if (isset($attendees[$attendee['href']])) {
             $attendees[$attendee['href']]['name'] = $attendee['name'];
             $attendees[$attendee['href']]['newInstances'] = $attendee['instances'];
             $attendees[$attendee['href']]['forceSend'] = $attendee['forceSend'];
         } else {
             $attendees[$attendee['href']] = array('href' => $attendee['href'], 'oldInstances' => array(), 'newInstances' => $attendee['instances'], 'name' => $attendee['name'], 'forceSend' => $attendee['forceSend']);
         }
     }
     $messages = array();
     foreach ($attendees as $attendee) {
         // An organizer can also be an attendee. We should not generate any
         // messages for those.
         if ($attendee['href'] === $eventInfo['organizer']) {
             continue;
         }
         $message = new Message();
         $message->uid = $eventInfo['uid'];
         $message->component = 'VEVENT';
         $message->sequence = $eventInfo['sequence'];
         $message->sender = $eventInfo['organizer'];
         $message->senderName = $eventInfo['organizerName'];
         $message->recipient = $attendee['href'];
         $message->recipientName = $attendee['name'];
         if (!$attendee['newInstances']) {
             // If there are no instances the attendee is a part of, it
             // means the attendee was removed and we need to send him a
             // CANCEL.
             $message->method = 'CANCEL';
             // Creating the new iCalendar body.
             $icalMsg = new VCalendar();
             $icalMsg->METHOD = $message->method;
             $event = $icalMsg->add('VEVENT', array('UID' => $message->uid, 'SEQUENCE' => $message->sequence));
             if (isset($calendar->VEVENT->SUMMARY)) {
                 $event->add('SUMMARY', $calendar->VEVENT->SUMMARY->getValue());
             }
             $event->add(clone $calendar->VEVENT->DTSTART);
             $org = $event->add('ORGANIZER', $eventInfo['organizer']);
             if ($eventInfo['organizerName']) {
                 $org['CN'] = $eventInfo['organizerName'];
             }
             $event->add('ATTENDEE', $attendee['href'], array('CN' => $attendee['name']));
             $message->significantChange = true;
         } else {
             // The attendee gets the updated event body
             $message->method = 'REQUEST';
             // Creating the new iCalendar body.
             $icalMsg = new VCalendar();
             $icalMsg->METHOD = $message->method;
             foreach ($calendar->select('VTIMEZONE') as $timezone) {
                 $icalMsg->add(clone $timezone);
             }
             // We need to find out that this change is significant. If it's
             // not, systems may opt to not send messages.
             //
             // We do this based on the 'significantChangeHash' which is
             // some value that changes if there's a certain set of
             // properties changed in the event, or simply if there's a
             // difference in instances that the attendee is invited to.
             $message->significantChange = $attendee['forceSend'] === 'REQUEST' || array_keys($attendee['oldInstances']) != array_keys($attendee['newInstances']) || $oldEventInfo['significantChangeHash'] !== $eventInfo['significantChangeHash'];
             foreach ($attendee['newInstances'] as $instanceId => $instanceInfo) {
                 $currentEvent = clone $eventInfo['instances'][$instanceId];
                 if ($instanceId === 'master') {
                     // We need to find a list of events that the attendee
                     // is not a part of to add to the list of exceptions.
                     $exceptions = array();
                     foreach ($eventInfo['instances'] as $instanceId => $vevent) {
                         if (!isset($attendee['newInstances'][$instanceId])) {
                             $exceptions[] = $instanceId;
                         }
                     }
                     // If there were exceptions, we need to add it to an
                     // existing EXDATE property, if it exists.
                     if ($exceptions) {
                         if (isset($currentEvent->EXDATE)) {
                             $currentEvent->EXDATE->setParts(array_merge($currentEvent->EXDATE->getParts(), $exceptions));
                         } else {
                             $currentEvent->EXDATE = $exceptions;
                         }
                     }
                     // Cleaning up any scheduling information that
                     // shouldn't be sent along.
                     unset($currentEvent->ORGANIZER['SCHEDULE-FORCE-SEND']);
                     unset($currentEvent->ORGANIZER['SCHEDULE-STATUS']);
                     foreach ($currentEvent->ATTENDEE as $attendee) {
                         unset($attendee['SCHEDULE-FORCE-SEND']);
                         unset($attendee['SCHEDULE-STATUS']);
                         // We're adding PARTSTAT=NEEDS-ACTION to ensure that
                         // iOS shows an "Inbox Item"
                         if (!isset($attendee['PARTSTAT'])) {
                             $attendee['PARTSTAT'] = 'NEEDS-ACTION';
                         }
                     }
                 }
                 $icalMsg->add($currentEvent);
             }
         }
         $message->message = $icalMsg;
         $messages[] = $message;
     }
     return $messages;
 }
 /**
  * create calendar object from VCalendar
  * @param VCalendar $vcalendar
  * @return $this
  */
 public function fromVObject(VCalendar $vcalendar)
 {
     foreach ($this->icsMapper as $classvar => $icsproperty) {
         $setter = 'set' . ucfirst($classvar);
         $value = $vcalendar->select($icsproperty);
         if (!empty($value)) {
             $this->{$setter}(reset($value));
         }
     }
     $tzIds = $vcalendar->select('X-WR-TIMEZONE');
     $tzId = reset($tzIds);
     $tz = SabreUtility::getTimezoneFromVObject($vcalendar, $tzId);
     if ($tz) {
         $this->setTimezone($tz);
     }
     return $this;
 }
Example #3
0
 /**
  * This method is used in cases where an event got updated, and we
  * potentially need to send emails to attendees to let them know of updates
  * in the events.
  *
  * We will detect which attendees got added, which got removed and create
  * specific messages for these situations.
  *
  * @param VCalendar $calendar
  * @param array $eventInfo
  * @param array $oldEventInfo
  * @return array
  */
 protected function parseEventForOrganizer(VCalendar $calendar, array $eventInfo, array $oldEventInfo)
 {
     // Merging attendee lists.
     $attendees = array();
     foreach ($oldEventInfo['attendees'] as $attendee) {
         $attendees[$attendee['href']] = array('href' => $attendee['href'], 'oldInstances' => $attendee['instances'], 'newInstances' => array(), 'name' => $attendee['name']);
     }
     foreach ($eventInfo['attendees'] as $attendee) {
         if (isset($attendees[$attendee['href']])) {
             $attendees[$attendee['href']]['name'] = $attendee['name'];
             $attendees[$attendee['href']]['newInstances'] = $attendee['instances'];
         } else {
             $attendees[$attendee['href']] = array('href' => $attendee['href'], 'oldInstances' => array(), 'newInstances' => $attendee['instances'], 'name' => $attendee['name']);
         }
     }
     $messages = array();
     foreach ($attendees as $attendee) {
         // An organizer can also be an attendee. We should not generate any
         // messages for those.
         if ($attendee['href'] === $eventInfo['organizer']) {
             continue;
         }
         $message = new Message();
         $message->uid = $eventInfo['uid'];
         $message->component = 'VEVENT';
         $message->sequence = $eventInfo['sequence'];
         $message->sender = $eventInfo['organizer'];
         $message->senderName = $eventInfo['organizerName'];
         $message->recipient = $attendee['href'];
         $message->recipientName = $attendee['name'];
         if (!$attendee['newInstances']) {
             // If there are no instances the attendee is a part of, it
             // means the attendee was removed and we need to send him a
             // CANCEL.
             $message->method = 'CANCEL';
             // Creating the new iCalendar body.
             $icalMsg = new VCalendar();
             $icalMsg->METHOD = $message->method;
             $event = $icalMsg->add('VEVENT', array('SEQUENCE' => $message->sequence, 'UID' => $message->uid));
             $event->add('ATTENDEE', $attendee['href'], array('CN' => $attendee['name']));
             $org = $event->add('ORGANIZER', $eventInfo['organizer']);
             if ($eventInfo['organizerName']) {
                 $org['CN'] = $eventInfo['organizerName'];
             }
         } else {
             // The attendee gets the updated event body
             $message->method = 'REQUEST';
             // Creating the new iCalendar body.
             $icalMsg = new VCalendar();
             $icalMsg->METHOD = $message->method;
             foreach ($calendar->select('VTIMEZONE') as $timezone) {
                 $icalMsg->add(clone $timezone);
             }
             foreach ($attendee['newInstances'] as $instanceId => $instanceInfo) {
                 $currentEvent = clone $eventInfo['instances'][$instanceId];
                 if ($instanceId === 'master') {
                     // We need to find a list of events that the attendee
                     // is not a part of to add to the list of exceptions.
                     $exceptions = array();
                     foreach ($eventInfo['instances'] as $instanceId => $vevent) {
                         if (!isset($attendee['newInstances'][$instanceId])) {
                             $exceptions[] = $instanceId;
                         }
                     }
                     // If there were exceptions, we need to add it to an
                     // existing EXDATE property, if it exists.
                     if ($exceptions) {
                         if (isset($currentEvent->EXDATE)) {
                             $currentEvent->EXDATE->setParts(array_merge($currentEvent->EXDATE->getParts(), $exceptions));
                         } else {
                             $currentEvent->EXDATE = $exceptions;
                         }
                     }
                 }
                 $icalMsg->add($currentEvent);
             }
         }
         $message->message = $icalMsg;
         $messages[] = $message;
     }
     return $messages;
 }
 /**
  * extract timezone-data for a certain timezone from Component\VCalendar object
  * @param Component\VCalendar $vcalendar
  * @param string $timezoneId
  * @return Timezone|null
  */
 public static function getTimezoneFromVObject(Component\VCalendar $vcalendar, $timezoneId)
 {
     foreach ($vcalendar->select('VTIMEZONE') as $vtimezone) {
         if ($vtimezone->TZID === $timezoneId) {
             return new Timezone($vtimezone);
         }
     }
     return null;
 }