[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