diff options
Diffstat (limited to 'vendor/sabre/vobject/lib/ITip/Broker.php')
-rw-r--r-- | vendor/sabre/vobject/lib/ITip/Broker.php | 221 |
1 files changed, 124 insertions, 97 deletions
diff --git a/vendor/sabre/vobject/lib/ITip/Broker.php b/vendor/sabre/vobject/lib/ITip/Broker.php index b1cfee367..b954cdc8d 100644 --- a/vendor/sabre/vobject/lib/ITip/Broker.php +++ b/vendor/sabre/vobject/lib/ITip/Broker.php @@ -35,8 +35,8 @@ use Sabre\VObject\Recur\EventIterator; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License */ -class Broker -{ +class Broker { + /** * This setting determines whether the rules for the SCHEDULE-AGENT * parameter should be followed. @@ -104,34 +104,37 @@ class Broker * * If the iTip message was not supported, we will always return false. * - * @param Message $itipMessage + * @param Message $itipMessage * @param VCalendar $existingObject * * @return VCalendar|null */ - public function processMessage(Message $itipMessage, VCalendar $existingObject = null) - { + function processMessage(Message $itipMessage, VCalendar $existingObject = null) { + // We only support events at the moment. - if ('VEVENT' !== $itipMessage->component) { + if ($itipMessage->component !== 'VEVENT') { return false; } switch ($itipMessage->method) { - case 'REQUEST': + + case 'REQUEST' : return $this->processMessageRequest($itipMessage, $existingObject); - case 'CANCEL': + case 'CANCEL' : return $this->processMessageCancel($itipMessage, $existingObject); - case 'REPLY': + case 'REPLY' : return $this->processMessageReply($itipMessage, $existingObject); - default: + default : // Unsupported iTip message return; + } return $existingObject; + } /** @@ -158,13 +161,13 @@ class Broker * organizer gets the 'declined' message. * * @param VCalendar|string $calendar - * @param string|array $userHref + * @param string|array $userHref * @param VCalendar|string $oldCalendar * * @return array */ - public function parseEvent($calendar = null, $userHref, $oldCalendar = null) - { + function parseEvent($calendar = null, $userHref, $oldCalendar = null) { + if ($oldCalendar) { if (is_string($oldCalendar)) { $oldCalendar = Reader::read($oldCalendar); @@ -177,15 +180,16 @@ class Broker $oldEventInfo = $this->parseEventInfo($oldCalendar); } else { $oldEventInfo = [ - 'organizer' => null, + 'organizer' => null, 'significantChangeHash' => '', - 'attendees' => [], + 'attendees' => [], ]; } - $userHref = (array) $userHref; + $userHref = (array)$userHref; if (!is_null($calendar)) { + if (is_string($calendar)) { $calendar = Reader::read($calendar); } @@ -213,6 +217,7 @@ class Broker $eventInfo['organizer'] = $oldEventInfo['organizer']; $eventInfo['organizerName'] = $oldEventInfo['organizerName']; } + } else { // The calendar object got deleted, we need to process this as a // cancellation / decline. @@ -228,17 +233,19 @@ class Broker $eventInfo['attendees'] = []; // Increasing the sequence, but only if the organizer deleted // the event. - ++$eventInfo['sequence']; + $eventInfo['sequence']++; } else { // This is an attendee deleting the event. foreach ($eventInfo['attendees'] as $key => $attendee) { if (in_array($attendee['href'], $userHref)) { - $eventInfo['attendees'][$key]['instances'] = ['master' => ['id' => 'master', 'partstat' => 'DECLINED'], + $eventInfo['attendees'][$key]['instances'] = ['master' => + ['id' => 'master', 'partstat' => 'DECLINED'] ]; } } } $baseCalendar = $oldCalendar; + } if (in_array($eventInfo['organizer'], $userHref)) { @@ -253,8 +260,8 @@ class Broker } } } - return []; + } /** @@ -264,13 +271,13 @@ class Broker * invite, or an update to an existing one. * * - * @param Message $itipMessage + * @param Message $itipMessage * @param VCalendar $existingObject * * @return VCalendar|null */ - protected function processMessageRequest(Message $itipMessage, VCalendar $existingObject = null) - { + protected function processMessageRequest(Message $itipMessage, VCalendar $existingObject = null) { + if (!$existingObject) { // This is a new invite, and we're just going to copy over // all the components from the invite. @@ -289,8 +296,8 @@ class Broker $existingObject->add(clone $component); } } - return $existingObject; + } /** @@ -300,13 +307,13 @@ class Broker * attendee got removed from an event, or an event got cancelled * altogether. * - * @param Message $itipMessage + * @param Message $itipMessage * @param VCalendar $existingObject * * @return VCalendar|null */ - protected function processMessageCancel(Message $itipMessage, VCalendar $existingObject = null) - { + protected function processMessageCancel(Message $itipMessage, VCalendar $existingObject = null) { + if (!$existingObject) { // The event didn't exist in the first place, so we're just // ignoring this message. @@ -316,8 +323,8 @@ class Broker $vevent->SEQUENCE = $itipMessage->sequence; } } - return $existingObject; + } /** @@ -326,13 +333,13 @@ class Broker * The message is a reply. This is for example an attendee telling * an organizer he accepted the invite, or declined it. * - * @param Message $itipMessage + * @param Message $itipMessage * @param VCalendar $existingObject * * @return VCalendar|null */ - protected function processMessageReply(Message $itipMessage, VCalendar $existingObject = null) - { + protected function processMessageReply(Message $itipMessage, VCalendar $existingObject = null) { + // A reply can only be processed based on an existing object. // If the object is not available, the reply is ignored. if (!$existingObject) { @@ -357,7 +364,7 @@ class Broker $masterObject = null; foreach ($existingObject->VEVENT as $vevent) { $recurId = isset($vevent->{'RECURRENCE-ID'}) ? $vevent->{'RECURRENCE-ID'}->getValue() : 'master'; - if ('master' === $recurId) { + if ($recurId === 'master') { $masterObject = $vevent; } if (isset($instances[$recurId])) { @@ -379,11 +386,9 @@ class Broker // Adding a new attendee. The iTip documentation calls this // a party crasher. $attendee = $vevent->add('ATTENDEE', $itipMessage->sender, [ - 'PARTSTAT' => $instances[$recurId], + 'PARTSTAT' => $instances[$recurId] ]); - if ($itipMessage->senderName) { - $attendee['CN'] = $itipMessage->senderName; - } + if ($itipMessage->senderName) $attendee['CN'] = $itipMessage->senderName; } unset($instances[$recurId]); } @@ -396,23 +401,24 @@ class Broker // If we got replies to instances that did not exist in the // original list, it means that new exceptions must be created. foreach ($instances as $recurId => $partstat) { + $recurrenceIterator = new EventIterator($existingObject, $itipMessage->uid); $found = false; $iterations = 1000; do { + $newObject = $recurrenceIterator->getEventObject(); $recurrenceIterator->next(); if (isset($newObject->{'RECURRENCE-ID'}) && $newObject->{'RECURRENCE-ID'}->getValue() === $recurId) { $found = true; } - --$iterations; + $iterations--; + } while ($recurrenceIterator->valid() && !$found && $iterations); // Invalid recurrence id. Skipping this object. - if (!$found) { - continue; - } + if (!$found) continue; unset( $newObject->RRULE, @@ -432,16 +438,17 @@ class Broker if (!$attendeeFound) { // Adding a new attendee $attendee = $newObject->add('ATTENDEE', $itipMessage->sender, [ - 'PARTSTAT' => $partstat, + 'PARTSTAT' => $partstat ]); if ($itipMessage->senderName) { $attendee['CN'] = $itipMessage->senderName; } } $existingObject->add($newObject); - } + } return $existingObject; + } /** @@ -453,22 +460,22 @@ class Broker * specific messages for these situations. * * @param VCalendar $calendar - * @param array $eventInfo - * @param array $oldEventInfo + * @param array $eventInfo + * @param array $oldEventInfo * * @return array */ - protected function parseEventForOrganizer(VCalendar $calendar, array $eventInfo, array $oldEventInfo) - { + protected function parseEventForOrganizer(VCalendar $calendar, array $eventInfo, array $oldEventInfo) { + // Merging attendee lists. $attendees = []; foreach ($oldEventInfo['attendees'] as $attendee) { $attendees[$attendee['href']] = [ - 'href' => $attendee['href'], + 'href' => $attendee['href'], 'oldInstances' => $attendee['instances'], 'newInstances' => [], - 'name' => $attendee['name'], - 'forceSend' => null, + 'name' => $attendee['name'], + 'forceSend' => null, ]; } foreach ($eventInfo['attendees'] as $attendee) { @@ -478,11 +485,11 @@ class Broker $attendees[$attendee['href']]['forceSend'] = $attendee['forceSend']; } else { $attendees[$attendee['href']] = [ - 'href' => $attendee['href'], + 'href' => $attendee['href'], 'oldInstances' => [], 'newInstances' => $attendee['instances'], - 'name' => $attendee['name'], - 'forceSend' => $attendee['forceSend'], + 'name' => $attendee['name'], + 'forceSend' => $attendee['forceSend'], ]; } } @@ -490,6 +497,7 @@ class Broker $messages = []; foreach ($attendees as $attendee) { + // An organizer can also be an attendee. We should not generate any // messages for those. if ($attendee['href'] === $eventInfo['organizer']) { @@ -506,6 +514,7 @@ class Broker $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. @@ -514,13 +523,8 @@ class Broker // Creating the new iCalendar body. $icalMsg = new VCalendar(); $icalMsg->METHOD = $message->method; - - foreach ($calendar->select('VTIMEZONE') as $timezone) { - $icalMsg->add(clone $timezone); - } - $event = $icalMsg->add('VEVENT', [ - 'UID' => $message->uid, + 'UID' => $message->uid, 'SEQUENCE' => $message->sequence, ]); if (isset($calendar->VEVENT->SUMMARY)) { @@ -533,14 +537,14 @@ class Broker $event->add(clone $calendar->VEVENT->DURATION); } $org = $event->add('ORGANIZER', $eventInfo['organizer']); - if ($eventInfo['organizerName']) { - $org['CN'] = $eventInfo['organizerName']; - } + if ($eventInfo['organizerName']) $org['CN'] = $eventInfo['organizerName']; $event->add('ATTENDEE', $attendee['href'], [ 'CN' => $attendee['name'], ]); $message->significantChange = true; + } else { + // The attendee gets the updated event body $message->method = 'REQUEST'; @@ -561,13 +565,15 @@ class Broker // difference in instances that the attendee is invited to. $message->significantChange = - 'REQUEST' === $attendee['forceSend'] || + $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 ('master' === $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 = []; @@ -604,18 +610,24 @@ class Broker if (!isset($attendee['PARTSTAT'])) { $attendee['PARTSTAT'] = 'NEEDS-ACTION'; } + } + } $icalMsg->add($currentEvent); + } + } $message->message = $icalMsg; $messages[] = $message; + } return $messages; + } /** @@ -624,21 +636,21 @@ class Broker * This function figures out if we need to send a reply to an organizer. * * @param VCalendar $calendar - * @param array $eventInfo - * @param array $oldEventInfo - * @param string $attendee + * @param array $eventInfo + * @param array $oldEventInfo + * @param string $attendee * * @return Message[] */ - protected function parseEventForAttendee(VCalendar $calendar, array $eventInfo, array $oldEventInfo, $attendee) - { - if ($this->scheduleAgentServerRules && 'CLIENT' === $eventInfo['organizerScheduleAgent']) { + protected function parseEventForAttendee(VCalendar $calendar, array $eventInfo, array $oldEventInfo, $attendee) { + + if ($this->scheduleAgentServerRules && $eventInfo['organizerScheduleAgent'] === 'CLIENT') { return []; } // Don't bother generating messages for events that have already been // cancelled. - if ('CANCELLED' === $eventInfo['status']) { + if ($eventInfo['status'] === 'CANCELLED') { return []; } @@ -648,22 +660,26 @@ class Broker $instances = []; foreach ($oldInstances as $instance) { + $instances[$instance['id']] = [ - 'id' => $instance['id'], + 'id' => $instance['id'], 'oldstatus' => $instance['partstat'], 'newstatus' => null, ]; + } foreach ($eventInfo['attendees'][$attendee]['instances'] as $instance) { + if (isset($instances[$instance['id']])) { $instances[$instance['id']]['newstatus'] = $instance['partstat']; } else { $instances[$instance['id']] = [ - 'id' => $instance['id'], + 'id' => $instance['id'], 'oldstatus' => null, 'newstatus' => $instance['partstat'], ]; } + } // We need to also look for differences in EXDATE. If there are new @@ -671,29 +687,33 @@ class Broker // event, which means we need to send DECLINED specifically for those // instances. // We only need to do that though, if the master event is not declined. - if (isset($instances['master']) && 'DECLINED' !== $instances['master']['newstatus']) { + if (isset($instances['master']) && $instances['master']['newstatus'] !== 'DECLINED') { foreach ($eventInfo['exdate'] as $exDate) { + if (!in_array($exDate, $oldEventInfo['exdate'])) { if (isset($instances[$exDate])) { $instances[$exDate]['newstatus'] = 'DECLINED'; } else { $instances[$exDate] = [ - 'id' => $exDate, + 'id' => $exDate, 'oldstatus' => null, 'newstatus' => 'DECLINED', ]; } } + } } // Gathering a few extra properties for each instance. foreach ($instances as $recurId => $instanceInfo) { + if (isset($eventInfo['instances'][$recurId])) { $instances[$recurId]['dtstart'] = clone $eventInfo['instances'][$recurId]->DTSTART; } else { $instances[$recurId]['dtstart'] = $recurId; } + } $message = new Message(); @@ -712,13 +732,14 @@ class Broker $hasReply = false; foreach ($instances as $instance) { - if ($instance['oldstatus'] == $instance['newstatus'] && 'REPLY' !== $eventInfo['organizerForceSend']) { + + if ($instance['oldstatus'] == $instance['newstatus'] && $eventInfo['organizerForceSend'] !== 'REPLY') { // Skip continue; } $event = $icalMsg->add('VEVENT', [ - 'UID' => $message->uid, + 'UID' => $message->uid, 'SEQUENCE' => $message->sequence, ]); $summary = isset($calendar->VEVENT->SUMMARY) ? $calendar->VEVENT->SUMMARY->getValue() : ''; @@ -752,7 +773,7 @@ class Broker $event->add('SUMMARY', $summary); } } - if ('master' !== $instance['id']) { + if ($instance['id'] !== 'master') { $dt = DateTimeParser::parse($instance['id'], $eventInfo['timezone']); // Treat is as a DATE field if (strlen($instance['id']) <= 8) { @@ -766,21 +787,22 @@ class Broker $organizer['CN'] = $message->recipientName; } $attendee = $event->add('ATTENDEE', $message->sender, [ - 'PARTSTAT' => $instance['newstatus'], + 'PARTSTAT' => $instance['newstatus'] ]); if ($message->senderName) { $attendee['CN'] = $message->senderName; } $hasReply = true; + } if ($hasReply) { $message->message = $icalMsg; - return [$message]; } else { return []; } + } /** @@ -802,13 +824,12 @@ class Broker * based on. * 11. significantChangeHash * 12. status - * * @param VCalendar $calendar * * @return array */ - protected function parseEventInfo(VCalendar $calendar = null) - { + protected function parseEventInfo(VCalendar $calendar = null) { + $uid = null; $organizer = null; $organizerName = null; @@ -847,7 +868,7 @@ class Broker $organizer = $vevent->ORGANIZER->getNormalizedValue(); $organizerName = isset($vevent->ORGANIZER['CN']) ? $vevent->ORGANIZER['CN'] : null; } else { - if (strtoupper($organizer) !== strtoupper($vevent->ORGANIZER->getNormalizedValue())) { + if ($organizer !== $vevent->ORGANIZER->getNormalizedValue()) { throw new SameOrganizerForAllComponentsException('Every instance of the event must have the same organizer.'); } } @@ -857,7 +878,7 @@ class Broker null; $organizerScheduleAgent = isset($vevent->ORGANIZER['SCHEDULE-AGENT']) ? - strtoupper((string) $vevent->ORGANIZER['SCHEDULE-AGENT']) : + strtoupper((string)$vevent->ORGANIZER['SCHEDULE-AGENT']) : 'SERVER'; } if (is_null($sequence) && isset($vevent->SEQUENCE)) { @@ -873,7 +894,7 @@ class Broker foreach ($vevent->select('RRULE') as $rr) { foreach ($rr->getParts() as $key => $val) { // ignore default values (https://github.com/sabre-io/vobject/issues/126) - if ('INTERVAL' === $key && 1 == $val) { + if ($key === 'INTERVAL' && $val == 1) { continue; } if (is_array($val)) { @@ -890,7 +911,7 @@ class Broker $recurId = isset($vevent->{'RECURRENCE-ID'}) ? $vevent->{'RECURRENCE-ID'}->getValue() : 'master'; if (is_null($timezone)) { - if ('master' === $recurId) { + if ($recurId === 'master') { $timezone = $vevent->DTSTART->getDateTime()->getTimeZone(); } else { $timezone = $vevent->{'RECURRENCE-ID'}->getDateTime()->getTimeZone(); @@ -898,9 +919,10 @@ class Broker } if (isset($vevent->ATTENDEE)) { foreach ($vevent->ATTENDEE as $attendee) { + if ($this->scheduleAgentServerRules && isset($attendee['SCHEDULE-AGENT']) && - 'CLIENT' === strtoupper($attendee['SCHEDULE-AGENT']->getValue()) + strtoupper($attendee['SCHEDULE-AGENT']->getValue()) === 'CLIENT' ) { continue; } @@ -914,42 +936,45 @@ class Broker strtoupper($attendee['SCHEDULE-FORCE-SEND']) : null; + if (isset($attendees[$attendee->getNormalizedValue()])) { $attendees[$attendee->getNormalizedValue()]['instances'][$recurId] = [ - 'id' => $recurId, - 'partstat' => $partStat, + 'id' => $recurId, + 'partstat' => $partStat, 'forceSend' => $forceSend, ]; } else { $attendees[$attendee->getNormalizedValue()] = [ - 'href' => $attendee->getNormalizedValue(), + 'href' => $attendee->getNormalizedValue(), 'instances' => [ $recurId => [ - 'id' => $recurId, + 'id' => $recurId, 'partstat' => $partStat, ], ], - 'name' => isset($attendee['CN']) ? (string) $attendee['CN'] : null, + 'name' => isset($attendee['CN']) ? (string)$attendee['CN'] : null, 'forceSend' => $forceSend, ]; } + } $instances[$recurId] = $vevent; + } foreach ($this->significantChangeProperties as $prop) { if (isset($vevent->$prop)) { $propertyValues = $vevent->select($prop); - $significantChangeHash .= $prop.':'; + $significantChangeHash .= $prop . ':'; - if ('EXDATE' === $prop) { - $significantChangeHash .= implode(',', $exdate).';'; - } elseif ('RRULE' === $prop) { - $significantChangeHash .= implode(',', $rrule).';'; + if ($prop === 'EXDATE') { + $significantChangeHash .= implode(',', $exdate) . ';'; + } elseif ($prop === 'RRULE') { + $significantChangeHash .= implode(',', $rrule) . ';'; } else { foreach ($propertyValues as $val) { - $significantChangeHash .= $val->getValue().';'; + $significantChangeHash .= $val->getValue() . ';'; } } } @@ -971,5 +996,7 @@ class Broker 'significantChangeHash', 'status' ); + } + } |