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);
if (isset($calendar->VEVENT->DTEND)) {
$event->add(clone $calendar->VEVENT->DTEND);
} elseif (isset($calendar->VEVENT->DURATION)) {
$event->add(clone $calendar->VEVENT->DURATION);
}
$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;
}