[Pkg-owncloud-commits] [php-sabre-vobject] 03/106: The broker can now process updates of events.
David Prévot
taffit at moszumanska.debian.org
Fri Aug 22 15:10:53 UTC 2014
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch master
in repository php-sabre-vobject.
commit c8bb6246f19cd6d03ab5466071e8791ddbda81b5
Author: Evert Pot <me at evertpot.com>
Date: Wed Jul 16 21:43:07 2014 -0400
The broker can now process updates of events.
---
lib/Sabre/VObject/ITip/Broker.php | 280 +++++++++++++++++----
lib/Sabre/VObject/ITip/Message.php | 7 +
.../{BrokerTest.php => BrokerNewEventTest.php} | 2 +-
.../{BrokerTest.php => BrokerUpdateEventTest.php} | 121 ++-------
4 files changed, 259 insertions(+), 151 deletions(-)
diff --git a/lib/Sabre/VObject/ITip/Broker.php b/lib/Sabre/VObject/ITip/Broker.php
index f0c2349..95fb150 100644
--- a/lib/Sabre/VObject/ITip/Broker.php
+++ b/lib/Sabre/VObject/ITip/Broker.php
@@ -63,69 +63,28 @@ class Broker {
return array();
}
- $uid = null;
- $organizer = null;
-
- // Now we need to collect a list of attendees, and which instances they
- // are a part of.
- $attendees = array();
-
- $instances = array();
-
- foreach($calendar->VEVENT as $vevent) {
- if (is_null($uid)) {
- $uid = $vevent->UID->getValue();
- } else {
- if ($uid !== $vevent->UID->getValue()) {
- throw new ITipException('If a calendar contained more than one event, they must have the same UID.');
- }
- }
- if (is_null($organizer)) {
- $organizer = $vevent->ORGANIZER->getValue();
- $organizerName = isset($vevent->ORGANIZER['CN'])?$vevent->ORGANIZER['CN']:null;
- } else {
- if ($organizer !== $vevent->ORGANIZER->getValue()) {
- throw new ITipException('Every instance of the event must have the same organizer.');
- }
- }
-
- $value = isset($vevent->{'RECURRENCE-ID'})?$vevent->{'RECURRENCE-ID'}->getValue():'master';
- foreach($vevent->ATTENDEE as $attendee) {
-
- if (isset($attendees[$attendee->getValue()])) {
- $attendees[$attendee->getValue()]['instances'][] = $value;
- } else {
- $attendees[$attendee->getValue()] = array(
- 'href' => $attendee->getValue(),
- 'instances' => array($value),
- 'name' => isset($attendee['CN'])?$attendee['CN']:null,
- );
- }
-
- }
- $instances[$value] = $vevent;
-
- }
+ $eventInfo = $this->parseEventInfo($calendar);
// Now we generate an iTip message for each attendee.
$messages = array();
- foreach($attendees as $attendee) {
+ foreach($eventInfo['attendees'] as $attendee) {
// An organizer can also be an attendee. We should not generate any
// messages for those.
- if ($attendee['href']===$organizer) {
+ if ($attendee['href']===$eventInfo['organizer']) {
continue;
}
$message = new Message();
- $message->uid = $uid;
+ $message->uid = $eventInfo['uid'];
$message->component = 'VEVENT';
$message->method = 'REQUEST';
- $message->sender = $organizer;
- $message->senderName = $organizerName;
+ $message->sender = $eventInfo['organizer'];
+ $message->senderName = $eventInfo['organizerName'];
$message->recipient = $attendee['href'];
$message->recipientName = $attendee['name'];
+ $message->sequence = $eventInfo['sequence'];
// Creating the new iCalendar body.
$icalMsg = new VCalendar();
@@ -133,13 +92,13 @@ class Broker {
foreach($attendee['instances'] as $instanceId) {
- $currentEvent = clone $instances[$instanceId];
+ $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($instances as $instanceId=>$vevent) {
+ foreach($eventInfo['instances'] as $instanceId=>$vevent) {
if (!in_array($instanceId, $attendee['instances'])) {
$exceptions[] = $instanceId;
}
@@ -173,4 +132,225 @@ class Broker {
}
+ /**
+ * 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|string $calendar
+ * @param VCalendar|string $oldCalendar
+ * @return array
+ */
+ public function updateEvent($calendar, $oldCalendar) {
+
+ if (is_string($calendar)) {
+ $calendar = Reader::read($calendar);
+ }
+ if (is_string($oldCalendar)) {
+ $oldCalendar = Reader::read($oldCalendar);
+ }
+
+ $oldEventInfo = $this->parseEventInfo($oldCalendar);
+ $newEventInfo = $this->parseEventInfo($calendar);
+
+ // Shortcut for noop
+ if (!$oldEventInfo['attendees'] && !$newEventInfo['attendees']) {
+ return array();
+ }
+
+ // 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($newEventInfo['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'],
+ );
+ }
+ }
+
+ foreach($attendees as $attendee) {
+
+ // An organizer can also be an attendee. We should not generate any
+ // messages for those.
+ if ($attendee['href']===$newEventInfo['organizer']) {
+ continue;
+ }
+
+ $message = new Message();
+ $message->uid = $newEventInfo['uid'];
+ $message->component = 'VEVENT';
+ $message->sequence = $newEventInfo['sequence'];
+ $message->sender = $newEventInfo['organizer'];
+ $message->senderName = $newEventInfo['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', $newEventInfo['organizer']);
+ if ($newEventInfo['organizerName']) $org['CN'] = $newEventInfo['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($attendee['newInstances'] as $instanceId) {
+
+ $currentEvent = clone $newEventInfo['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($newEventInfo['instances'] as $instanceId=>$vevent) {
+ if (!in_array($instanceId, $attendee['newInstances'])) {
+ $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;
+
+
+ }
+
+
+ /**
+ * Returns attendee information and information about instances of an
+ * event.
+ *
+ * Returns an array with the following keys:
+ *
+ * 1. uid
+ * 2. organizer
+ * 3. organizerName
+ * 4. attendees
+ * 5. instances
+ *
+ * @param VCalendar $calendar
+ * @return void
+ */
+ protected function parseEventInfo(VCalendar $calendar) {
+
+ $uid = null;
+ $organizer = null;
+ $sequence = null;
+
+ // Now we need to collect a list of attendees, and which instances they
+ // are a part of.
+ $attendees = array();
+
+ $instances = array();
+
+ foreach($calendar->VEVENT as $vevent) {
+ if (is_null($uid)) {
+ $uid = $vevent->UID->getValue();
+ } else {
+ if ($uid !== $vevent->UID->getValue()) {
+ throw new ITipException('If a calendar contained more than one event, they must have the same UID.');
+ }
+ }
+ if (is_null($organizer)) {
+ $organizer = $vevent->ORGANIZER->getValue();
+ $organizerName = isset($vevent->ORGANIZER['CN'])?$vevent->ORGANIZER['CN']:null;
+ } else {
+ if ($organizer !== $vevent->ORGANIZER->getValue()) {
+ throw new ITipException('Every instance of the event must have the same organizer.');
+ }
+ }
+ if (is_null($sequence) && isset($vevent->SEQUENCE)) {
+ $sequence = $vevent->SEQUENCE->getValue();
+ }
+
+ $value = isset($vevent->{'RECURRENCE-ID'})?$vevent->{'RECURRENCE-ID'}->getValue():'master';
+ if(isset($vevent->ATTENDEE)) foreach($vevent->ATTENDEE as $attendee) {
+
+ if (isset($attendees[$attendee->getValue()])) {
+ $attendees[$attendee->getValue()]['instances'][] = $value;
+ } else {
+ $attendees[$attendee->getValue()] = array(
+ 'href' => $attendee->getValue(),
+ 'instances' => array($value),
+ 'name' => isset($attendee['CN'])?(string)$attendee['CN']:null,
+ );
+ }
+
+ }
+ $instances[$value] = $vevent;
+
+ }
+
+ return array(
+ 'uid' => $uid,
+ 'organizer' => $organizer,
+ 'organizerName' => $organizerName,
+ 'instances' => $instances,
+ 'attendees' => $attendees,
+ 'sequence' => $sequence,
+ );
+
+ }
+
}
diff --git a/lib/Sabre/VObject/ITip/Message.php b/lib/Sabre/VObject/ITip/Message.php
index 89b96b5..55b3de2 100644
--- a/lib/Sabre/VObject/ITip/Message.php
+++ b/lib/Sabre/VObject/ITip/Message.php
@@ -39,6 +39,13 @@ class Message {
public $method;
/**
+ * The current sequence number for the event.
+ *
+ * @var int
+ */
+ public $sequence;
+
+ /**
* The senders' email address.
*
* Note that this does not imply that this has to be used in a From: field
diff --git a/tests/Sabre/VObject/ITip/BrokerTest.php b/tests/Sabre/VObject/ITip/BrokerNewEventTest.php
similarity index 98%
copy from tests/Sabre/VObject/ITip/BrokerTest.php
copy to tests/Sabre/VObject/ITip/BrokerNewEventTest.php
index d02f62e..5fa2bf2 100644
--- a/tests/Sabre/VObject/ITip/BrokerTest.php
+++ b/tests/Sabre/VObject/ITip/BrokerNewEventTest.php
@@ -2,7 +2,7 @@
namespace Sabre\VObject\ITip;
-class BrokerTest extends \PHPUnit_Framework_TestCase {
+class BrokerNewTest extends \PHPUnit_Framework_TestCase {
function testNoAttendee() {
diff --git a/tests/Sabre/VObject/ITip/BrokerTest.php b/tests/Sabre/VObject/ITip/BrokerUpdateEventTest.php
similarity index 58%
rename from tests/Sabre/VObject/ITip/BrokerTest.php
rename to tests/Sabre/VObject/ITip/BrokerUpdateEventTest.php
index d02f62e..1ae6b4f 100644
--- a/tests/Sabre/VObject/ITip/BrokerTest.php
+++ b/tests/Sabre/VObject/ITip/BrokerUpdateEventTest.php
@@ -2,102 +2,35 @@
namespace Sabre\VObject\ITip;
-class BrokerTest extends \PHPUnit_Framework_TestCase {
+class BrokerUpdateTest extends \PHPUnit_Framework_TestCase {
- function testNoAttendee() {
+ function testInviteChange() {
- $message = <<<ICS
-BEGIN:VCALENDAR
-BEGIN:VEVENT
-UID:foobar
-END:VEVENT
-END:VCALENDAR
-ICS;
-
- $result = $this->parse($message);
-
- }
-
- function testVTODO() {
-
- $message = <<<ICS
-BEGIN:VCALENDAR
-BEGIN:VTODO
-UID:foobar
-END:VTODO
-END:VCALENDAR
-ICS;
-
- $result = $this->parse($message);
-
- }
-
- function testSimpleInvite() {
-
- $message = <<<ICS
-BEGIN:VCALENDAR
-VERSION:2.0
-BEGIN:VEVENT
-UID:foobar
-ORGANIZER;CN=Strunk:mailto:strunk at example.org
-ATTENDEE;CN=White:mailto:white at example.org
-END:VEVENT
-END:VCALENDAR
-ICS;
-
- $version = \Sabre\VObject\Version::VERSION;
- $expectedMessage = <<<ICS
+ $oldMessage = <<<ICS
BEGIN:VCALENDAR
VERSION:2.0
-PRODID:-//Sabre//Sabre VObject $version//EN
-CALSCALE:GREGORIAN
-METHOD:REQUEST
BEGIN:VEVENT
UID:foobar
+SEQUENCE:1
ORGANIZER;CN=Strunk:mailto:strunk at example.org
-ATTENDEE;CN=White:mailto:white at example.org
+ATTENDEE;CN=One:mailto:one at example.org
+ATTENDEE;CN=Two:mailto:two at example.org
+DTSTART:20140716T120000Z
END:VEVENT
END:VCALENDAR
ICS;
- $expected = array(
- array(
- 'uid' => 'foobar',
- 'method' => 'REQUEST',
- 'component' => 'VEVENT',
- 'sender' => 'mailto:strunk at example.org',
- 'senderName' => 'Strunk',
- 'recipient' => 'mailto:white at example.org',
- 'recipientName' => 'White',
- 'message' => $expectedMessage,
- ),
- );
- $result = $this->parse($message, $expected);
-
- }
-
- function testRecurrenceInvite() {
-
- $message = <<<ICS
+ $newMessage = <<<ICS
BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
UID:foobar
-ORGANIZER;CN=Strunk:mailto:strunk at example.org
-ATTENDEE;CN=One:mailto:one at example.org
-ATTENDEE;CN=Two:mailto:two at example.org
-DTSTART:20140716T120000Z
-RRULE:FREQ=DAILY
-EXDATE:20140717T120000Z
-END:VEVENT
-BEGIN:VEVENT
-UID:foobar
-RECURRENCE-ID:20140718T120000Z
+SEQUENCE:2
ORGANIZER;CN=Strunk:mailto:strunk at example.org
ATTENDEE;CN=Two:mailto:two at example.org
ATTENDEE;CN=Three:mailto:three at example.org
-DTSTART:20140718T120000Z
+DTSTART:20140716T120000Z
END:VEVENT
END:VCALENDAR
ICS;
@@ -107,7 +40,7 @@ ICS;
$expected = array(
array(
'uid' => 'foobar',
- 'method' => 'REQUEST',
+ 'method' => 'CANCEL',
'component' => 'VEVENT',
'sender' => 'mailto:strunk at example.org',
'senderName' => 'Strunk',
@@ -118,15 +51,12 @@ BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Sabre//Sabre VObject $version//EN
CALSCALE:GREGORIAN
-METHOD:REQUEST
+METHOD:CANCEL
BEGIN:VEVENT
+SEQUENCE:2
UID:foobar
-ORGANIZER;CN=Strunk:mailto:strunk at example.org
ATTENDEE;CN=One:mailto:one at example.org
-ATTENDEE;CN=Two:mailto:two at example.org
-DTSTART:20140716T120000Z
-RRULE:FREQ=DAILY
-EXDATE:20140717T120000Z,20140718T120000Z
+ORGANIZER;CN=Strunk:mailto:strunk at example.org
END:VEVENT
END:VCALENDAR
ICS
@@ -148,20 +78,11 @@ CALSCALE:GREGORIAN
METHOD:REQUEST
BEGIN:VEVENT
UID:foobar
-ORGANIZER;CN=Strunk:mailto:strunk at example.org
-ATTENDEE;CN=One:mailto:one at example.org
-ATTENDEE;CN=Two:mailto:two at example.org
-DTSTART:20140716T120000Z
-RRULE:FREQ=DAILY
-EXDATE:20140717T120000Z
-END:VEVENT
-BEGIN:VEVENT
-UID:foobar
-RECURRENCE-ID:20140718T120000Z
+SEQUENCE:2
ORGANIZER;CN=Strunk:mailto:strunk at example.org
ATTENDEE;CN=Two:mailto:two at example.org
ATTENDEE;CN=Three:mailto:three at example.org
-DTSTART:20140718T120000Z
+DTSTART:20140716T120000Z
END:VEVENT
END:VCALENDAR
ICS
@@ -183,11 +104,11 @@ CALSCALE:GREGORIAN
METHOD:REQUEST
BEGIN:VEVENT
UID:foobar
-RECURRENCE-ID:20140718T120000Z
+SEQUENCE:2
ORGANIZER;CN=Strunk:mailto:strunk at example.org
ATTENDEE;CN=Two:mailto:two at example.org
ATTENDEE;CN=Three:mailto:three at example.org
-DTSTART:20140718T120000Z
+DTSTART:20140716T120000Z
END:VEVENT
END:VCALENDAR
ICS
@@ -195,14 +116,14 @@ ICS
),
);
- $result = $this->parse($message, $expected);
+ $result = $this->parse($oldMessage, $newMessage, $expected);
}
- function parse($message, $expected = array()) {
+ function parse($oldMessage, $newMessage, $expected = array()) {
$broker = new Broker();
- $result = $broker->createEvent($message);
+ $result = $broker->updateEvent($newMessage, $oldMessage);
$this->assertEquals(count($expected), count($result));
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/php-sabre-vobject.git
More information about the Pkg-owncloud-commits
mailing list