[Pkg-owncloud-commits] [php-sabre-vobject] 14/46: VCalendar::expand now returns an expanded version of itself.

David Prévot taffit at moszumanska.debian.org
Thu Dec 10 02:12:38 UTC 2015


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 afa5cbf04d1fe1687ff365c3a4da698246cb844d
Author: Evert Pot <me at evertpot.com>
Date:   Wed Nov 25 20:31:45 2015 -0500

    VCalendar::expand now returns an expanded version of itself.
    
    It no longer edits itself in-place, which was not always a good idea.
    This is BC breaking.
    
    We also introduced a new InvalidData exception. We'll be switching to
    that new exception everywhere we used generic PHP exceptions before.
    
    Fixes #240.
---
 lib/Component/VCalendar.php                        | 102 ++++++++++-----------
 ...ParseException.php => InvalidDataException.php} |   5 +-
 lib/ParseException.php                             |   2 +-
 tests/VObject/Component/VCalendarTest.php          |   8 +-
 .../Recur/EventIterator/ByMonthInDailyTest.php     |   2 +-
 .../Recur/EventIterator/BySetPosHangTest.php       |   2 +-
 .../EventIterator/ExpandFloatingTimesTest.php      |  24 ++---
 .../Recur/EventIterator/HandleRDateExpandTest.php  |  11 ++-
 .../Recur/EventIterator/IncorrectExpandTest.php    |  12 +--
 .../Recur/EventIterator/MissingOverriddenTest.php  |  13 ++-
 .../Recur/EventIterator/OverrideFirstEventTest.php |  26 +++---
 11 files changed, 102 insertions(+), 105 deletions(-)

diff --git a/lib/Component/VCalendar.php b/lib/Component/VCalendar.php
index d39c31e..476b8d9 100644
--- a/lib/Component/VCalendar.php
+++ b/lib/Component/VCalendar.php
@@ -6,8 +6,10 @@ use DateTimeInterface;
 use DateTimeZone;
 use Sabre\VObject;
 use Sabre\VObject\Component;
+use Sabre\VObject\Property;
 use Sabre\VObject\Recur\EventIterator;
 use Sabre\VObject\Recur\NoInstancesException;
+use Sabre\VObject\InvalidDataException;
 
 /**
  * The VCalendar component.
@@ -268,6 +270,9 @@ class VCalendar extends VObject\Document {
     }
 
     /**
+     * Expand all events in this VCalendar object and return a new VCalendar
+     * with the expanded events.
+     *
      * If this calendar object, has events with recurrence rules, this method
      * can be used to expand the event into multiple sub-events.
      *
@@ -278,52 +283,66 @@ class VCalendar extends VObject\Document {
      * In addition, this method will cause timezone information to be stripped,
      * and normalized to UTC.
      *
-     * This method will alter the VCalendar. This cannot be reversed.
-     *
-     * This functionality is specifically used by the CalDAV standard. It is
-     * possible for clients to request expand events, if they are rather simple
-     * clients and do not have the possibility to calculate recurrences.
-     *
      * @param DateTimeInterface $start
      * @param DateTimeInterface $end
      * @param DateTimeZone $timeZone reference timezone for floating dates and
      *                     times.
-     *
-     * @return void
+     * @return VCalendar
      */
     function expand(DateTimeInterface $start, DateTimeInterface $end, DateTimeZone $timeZone = null) {
 
-        $newEvents = [];
+        $newChildren = [];
+        $recurringEvents = [];
 
         if (!$timeZone) {
             $timeZone = new DateTimeZone('UTC');
         }
 
-        // An array of events. Events are indexed by UID. Each item in this
-        // array is a list of one or more events that match the UID.
-        $recurringEvents = [];
+        $stripTimezones = function(Component $component) use ($timeZone) {
 
-        foreach ($this->select('VEVENT') as $key => $vevent) {
+            foreach ($component->children() as $componentChild) {
+                if ($componentChild instanceof Property\ICalendar\DateTime && $componentChild->hasTime()) {
 
-            $uid = (string)$vevent->UID;
-            if (!$uid) {
-                throw new \LogicException('Event did not have a UID!');
-            }
-
-            if (isset($vevent->{'RECURRENCE-ID'}) || isset($vevent->RRULE) || isset($vevent->{'RDATE'})) {
-                if (isset($recurringEvents[$uid])) {
-                    $recurringEvents[$uid][] = $vevent;
-                } else {
-                    $recurringEvents[$uid] = [$vevent];
+                    $dt = $componentChild->getDateTimes($timeZone);
+                    // We only need to update the first timezone, because
+                    // setDateTimes will match all other timezones to the
+                    // first.
+                    $dt[0] = $dt[0]->setTimeZone(new DateTimeZone('UTC'));
+                    $componentChild->setDateTimes($dt);
+                } elseif ($componentChild instanceof Component) {
+                    $stripTimezones($componentChild);
                 }
-                continue;
+
             }
+            return $component;
+
+        };
 
-            if (!isset($vevent->RRULE)) {
-                if ($vevent->isInTimeRange($start, $end)) {
-                    $newEvents[] = $vevent;
+        foreach ($this->children() as $child) {
+
+            if ($child instanceof Property && $child->name !== 'PRODID') {
+                // We explictly want to ignore PRODID, because we want to
+                // overwrite it with our own.
+                $newChildren[] = clone $child;
+            } elseif ($child instanceof Component && $child->name !== 'VTIMEZONE') {
+
+                // We're also stripping all VTIMEZONE objects because we're
+                // converting everything to UTC.
+                if ($child->name === 'VEVENT' && (isset($child->{'RECURRENCE-ID'}) || isset($child->RRULE) || isset($child->RDATE))) {
+                    // Handle these a bit later.
+                    $uid = (string)$child->UID;
+                    if (!$uid) {
+                        throw new InvalidDataException('Every VEVENT object must have a UID property');
+                    }
+                    if (isset($recurringEvents[$uid])) {
+                        $recurringEvents[$uid][] = clone $child;
+                    } else {
+                        $recurringEvents[$uid] = [clone $child];
+                    }
+                } elseif ($child->name === 'VEVENT' && $child->isInTimeRange($start, $end)) {
+                    $newChildren[] = $stripTimezones(clone $child);
                 }
-                continue;
+
             }
 
         }
@@ -345,7 +364,7 @@ class VCalendar extends VObject\Document {
 
                 if ($it->getDTEnd() > $start) {
 
-                    $newEvents[] = $it->getEventObject();
+                    $newChildren[] = $stripTimezones($it->getEventObject());
 
                 }
                 $it->next();
@@ -354,30 +373,7 @@ class VCalendar extends VObject\Document {
 
         }
 
-        // Wiping out all old VEVENT objects
-        unset($this->VEVENT);
-
-        // Setting all properties to UTC time.
-        foreach ($newEvents as $newEvent) {
-
-            foreach ($newEvent->children as $childGroup) {
-                foreach ($childGroup as $child) {
-                    if ($child instanceof VObject\Property\ICalendar\DateTime && $child->hasTime()) {
-                        $dt = $child->getDateTimes($timeZone);
-                        // We only need to update the first timezone, because
-                        // setDateTimes will match all other timezones to the
-                        // first.
-                        $dt[0] = $dt[0]->setTimeZone(new DateTimeZone('UTC'));
-                        $child->setDateTimes($dt);
-                    }
-                }
-            }
-            $this->add($newEvent);
-
-        }
-
-        // Removing all VTIMEZONE components
-        unset($this->VTIMEZONE);
+        return new self($newChildren);
 
     }
 
diff --git a/lib/ParseException.php b/lib/InvalidDataException.php
similarity index 58%
copy from lib/ParseException.php
copy to lib/InvalidDataException.php
index 0327d10..c50fc10 100644
--- a/lib/ParseException.php
+++ b/lib/InvalidDataException.php
@@ -3,11 +3,12 @@
 namespace Sabre\VObject;
 
 /**
- * Exception thrown by Reader if an invalid object was attempted to be parsed.
+ * This exception is thrown whenever an invalid value is found anywhere in a
+ * iCalendar or vCard object.
  *
  * @copyright Copyright (C) 2011-2015 fruux GmbH (https://fruux.com/).
  * @author Evert Pot (http://evertpot.com/)
  * @license http://sabre.io/license/ Modified BSD License
  */
-class ParseException extends \Exception {
+class InvalidDataException extends \Exception {
 }
diff --git a/lib/ParseException.php b/lib/ParseException.php
index 0327d10..c244759 100644
--- a/lib/ParseException.php
+++ b/lib/ParseException.php
@@ -9,5 +9,5 @@ namespace Sabre\VObject;
  * @author Evert Pot (http://evertpot.com/)
  * @license http://sabre.io/license/ Modified BSD License
  */
-class ParseException extends \Exception {
+class ParseException extends InvalidDataException {
 }
diff --git a/tests/VObject/Component/VCalendarTest.php b/tests/VObject/Component/VCalendarTest.php
index 02c49f8..e13de33 100644
--- a/tests/VObject/Component/VCalendarTest.php
+++ b/tests/VObject/Component/VCalendarTest.php
@@ -5,7 +5,7 @@ namespace Sabre\VObject\Component;
 use DateTimeZone;
 use Sabre\VObject;
 
-class VCalendarTest extends \PHPUnit_Framework_TestCase {
+class VCalendarTest extends VObject\TestCase {
 
     /**
      * @dataProvider expandData
@@ -16,7 +16,7 @@ class VCalendarTest extends \PHPUnit_Framework_TestCase {
 
         $timeZone = new DateTimeZone($timeZone);
 
-        $vcal->expand(
+        $vcal = $vcal->expand(
             new \DateTime($start),
             new \DateTime($end),
             $timeZone
@@ -25,7 +25,7 @@ class VCalendarTest extends \PHPUnit_Framework_TestCase {
         // This will normalize the output
         $output = VObject\Reader::read($output)->serialize();
 
-        $this->assertEquals($output, $vcal->serialize());
+        $this->assertVObjEquals($output, $vcal->serialize());
 
     }
 
@@ -295,7 +295,7 @@ END:VCALENDAR
     }
 
     /**
-     * @expectedException LogicException
+     * @expectedException \Sabre\VObject\InvalidDataException
      */
     function testBrokenEventExpand() {
 
diff --git a/tests/VObject/Recur/EventIterator/ByMonthInDailyTest.php b/tests/VObject/Recur/EventIterator/ByMonthInDailyTest.php
index 7fa7fae..a70208a 100644
--- a/tests/VObject/Recur/EventIterator/ByMonthInDailyTest.php
+++ b/tests/VObject/Recur/EventIterator/ByMonthInDailyTest.php
@@ -37,7 +37,7 @@ ICS;
         $vcal = Reader::read($ics);
         $this->assertInstanceOf('Sabre\\VObject\\Component\\VCalendar', $vcal);
 
-        $vcal->expand(new DateTime('2013-09-28'), new DateTime('2014-09-11'));
+        $vcal = $vcal->expand(new DateTime('2013-09-28'), new DateTime('2014-09-11'));
 
         foreach ($vcal->VEVENT as $event) {
             $dates[] = $event->DTSTART->getValue();
diff --git a/tests/VObject/Recur/EventIterator/BySetPosHangTest.php b/tests/VObject/Recur/EventIterator/BySetPosHangTest.php
index 84a439b..b9bfbeb 100644
--- a/tests/VObject/Recur/EventIterator/BySetPosHangTest.php
+++ b/tests/VObject/Recur/EventIterator/BySetPosHangTest.php
@@ -32,7 +32,7 @@ ICS;
         $vcal = Reader::read($ics);
         $this->assertInstanceOf('Sabre\\VObject\\Component\\VCalendar', $vcal);
 
-        $vcal->expand(new DateTime('2015-01-01'), new DateTime('2016-01-01'));
+        $vcal = $vcal->expand(new DateTime('2015-01-01'), new DateTime('2016-01-01'));
 
         foreach ($vcal->VEVENT as $event) {
             $dates[] = $event->DTSTART->getValue();
diff --git a/tests/VObject/Recur/EventIterator/ExpandFloatingTimesTest.php b/tests/VObject/Recur/EventIterator/ExpandFloatingTimesTest.php
index f390a83..3aebd40 100644
--- a/tests/VObject/Recur/EventIterator/ExpandFloatingTimesTest.php
+++ b/tests/VObject/Recur/EventIterator/ExpandFloatingTimesTest.php
@@ -1,10 +1,13 @@
 <?php
 
-namespace Sabre\VObject;
+namespace Sabre\VObject\Recur\EventIterator;
 
 use DateTime;
+use DateTimeZone;
+use Sabre\VObject\Reader;
+use Sabre\VObject\TestCase;
 
-class ExpandFloatingTimesTest extends \PHPUnit_Framework_TestCase {
+class ExpandFloatingTimesTest extends TestCase {
 
     function testExpand() {
 
@@ -23,10 +26,7 @@ ICS;
         $vcal = Reader::read($input);
         $this->assertInstanceOf('Sabre\\VObject\\Component\\VCalendar', $vcal);
 
-        $vcal->expand(new DateTime('2015-01-01'), new DateTime('2015-01-31'));
-
-        $result = $vcal->serialize();
-
+        $vcal = $vcal->expand(new DateTime('2015-01-01'), new DateTime('2015-01-31'));
         $output = <<<ICS
 BEGIN:VCALENDAR
 VERSION:2.0
@@ -56,7 +56,7 @@ END:VEVENT
 END:VCALENDAR
 
 ICS;
-        $this->assertEquals($output, str_replace("\r", "", $result));
+        $this->assertVObjEquals($output, $vcal);
 
     }
 
@@ -77,9 +77,11 @@ ICS;
         $vcal = Reader::read($input);
         $this->assertInstanceOf('Sabre\\VObject\\Component\\VCalendar', $vcal);
 
-        $vcal->expand(new DateTime('2015-01-01'), new DateTime('2015-01-31'), new \DateTimeZone('Europe/Berlin'));
-
-        $result = $vcal->serialize();
+        $vcal = $vcal->expand(
+            new DateTime('2015-01-01'),
+            new DateTime('2015-01-31'),
+            new DateTimeZone('Europe/Berlin')
+        );
 
         $output = <<<ICS
 BEGIN:VCALENDAR
@@ -110,7 +112,7 @@ END:VEVENT
 END:VCALENDAR
 
 ICS;
-        $this->assertEquals($output, str_replace("\r", "", $result));
+        $this->assertVObjEquals($output, $vcal);
 
     }
 
diff --git a/tests/VObject/Recur/EventIterator/HandleRDateExpandTest.php b/tests/VObject/Recur/EventIterator/HandleRDateExpandTest.php
index 027fc55..69fc7d0 100644
--- a/tests/VObject/Recur/EventIterator/HandleRDateExpandTest.php
+++ b/tests/VObject/Recur/EventIterator/HandleRDateExpandTest.php
@@ -1,10 +1,11 @@
 <?php
 
-namespace Sabre\VObject;
+namespace Sabre\VObject\Recur\EventIterator;
 
 use DateTime;
 use DateTimeImmutable;
 use DateTimeZone;
+use Sabre\VObject\Reader;
 
 /**
  * This is a unittest for Issue #53.
@@ -36,22 +37,22 @@ ICS;
         $vcal = Reader::read($input);
         $this->assertInstanceOf('Sabre\\VObject\\Component\\VCalendar', $vcal);
 
-        $vcal->expand(new DateTime('2015-01-01'), new DateTime('2015-12-01'));
+        $vcal = $vcal->expand(new DateTime('2015-01-01'), new DateTime('2015-12-01'));
 
         $result = iterator_to_array($vcal->vevent);
 
         $this->assertEquals(5, count($result));
 
         $utc = new DateTimeZone('UTC');
-        $expected = array(
+        $expected = [
             new DateTimeImmutable("2015-10-12", $utc),
             new DateTimeImmutable("2015-10-15", $utc),
             new DateTimeImmutable("2015-10-17", $utc),
             new DateTimeImmutable("2015-10-18", $utc),
             new DateTimeImmutable("2015-10-20", $utc),
-        );
+        ];
 
-        $result = array_map(function($ev){return $ev->dtstart->getDateTime();}, $result);
+        $result = array_map(function($ev) {return $ev->dtstart->getDateTime();}, $result);
         $this->assertEquals($expected, $result);
     
     }
diff --git a/tests/VObject/Recur/EventIterator/IncorrectExpandTest.php b/tests/VObject/Recur/EventIterator/IncorrectExpandTest.php
index fdd1f30..b667bf3 100644
--- a/tests/VObject/Recur/EventIterator/IncorrectExpandTest.php
+++ b/tests/VObject/Recur/EventIterator/IncorrectExpandTest.php
@@ -1,13 +1,15 @@
 <?php
 
-namespace Sabre\VObject;
+namespace Sabre\VObject\Recur\EventIterator;
 
 use DateTime;
+use Sabre\VObject\Reader;
+use Sabre\VObject\TestCase;
 
 /**
  * This is a unittest for Issue #53.
  */
-class IncorrectExpandTest extends \PHPUnit_Framework_TestCase {
+class IncorrectExpandTest extends TestCase {
 
     function testExpand() {
 
@@ -32,9 +34,7 @@ ICS;
         $vcal = Reader::read($input);
         $this->assertInstanceOf('Sabre\\VObject\\Component\\VCalendar', $vcal);
 
-        $vcal->expand(new DateTime('2011-01-01'), new DateTime('2014-01-01'));
-
-        $result = $vcal->serialize();
+        $vcal = $vcal->expand(new DateTime('2011-01-01'), new DateTime('2014-01-01'));
 
         $output = <<<ICS
 BEGIN:VCALENDAR
@@ -53,7 +53,7 @@ END:VEVENT
 END:VCALENDAR
 
 ICS;
-        $this->assertEquals($output, str_replace("\r", "", $result));
+        $this->assertVObjEquals($output, $vcal);
     
     }
 
diff --git a/tests/VObject/Recur/EventIterator/MissingOverriddenTest.php b/tests/VObject/Recur/EventIterator/MissingOverriddenTest.php
index ed3efbd..eca1c6a 100644
--- a/tests/VObject/Recur/EventIterator/MissingOverriddenTest.php
+++ b/tests/VObject/Recur/EventIterator/MissingOverriddenTest.php
@@ -1,10 +1,12 @@
 <?php
 
-namespace Sabre\VObject;
+namespace Sabre\VObject\Recur\EventIterator;
 
 use DateTime;
+use Sabre\VObject\Reader;
+use Sabre\VObject\TestCase;
 
-class MissingOverriddenTest extends \PHPUnit_Framework_TestCase {
+class MissingOverriddenTest extends TestCase {
 
     function testExpand() {
 
@@ -31,9 +33,7 @@ ICS;
         $vcal = Reader::read($input);
         $this->assertInstanceOf('Sabre\\VObject\\Component\\VCalendar', $vcal);
 
-        $vcal->expand(new DateTime('2011-01-01'), new DateTime('2015-01-01'));
-
-        $result = $vcal->serialize();
+        $vcal = $vcal->expand(new DateTime('2011-01-01'), new DateTime('2015-01-01'));
 
         $output = <<<ICS
 BEGIN:VCALENDAR
@@ -52,9 +52,8 @@ DURATION:PT1H
 SUMMARY:B
 END:VEVENT
 END:VCALENDAR
-
 ICS;
-        $this->assertEquals($output, str_replace("\r", "", $result));
+        $this->assertVObjEquals($output, $vcal);
     
     }
 
diff --git a/tests/VObject/Recur/EventIterator/OverrideFirstEventTest.php b/tests/VObject/Recur/EventIterator/OverrideFirstEventTest.php
index fd691d6..22f7f61 100644
--- a/tests/VObject/Recur/EventIterator/OverrideFirstEventTest.php
+++ b/tests/VObject/Recur/EventIterator/OverrideFirstEventTest.php
@@ -3,14 +3,16 @@
 namespace Sabre\VObject\RecurrenceIterator;
 
 use Sabre\VObject\Reader;
+use Sabre\VObject\TestCase;
 use DateTime;
 
-class OverrideFirstEventTest extends \PHPUnit_Framework_TestCase {
+class OverrideFirstEventTest extends TestCase {
 
     function testOverrideFirstEvent() {
 
         $input =  <<<ICS
 BEGIN:VCALENDAR
+VERSION:2.0
 BEGIN:VEVENT
 UID:foobar
 DTSTART:20140803T120000Z
@@ -27,10 +29,11 @@ END:VCALENDAR
 ICS;
 
         $vcal = Reader::read($input);
-        $vcal->expand(new DateTime('2014-08-01'), new DateTime('2014-09-01'));
+        $vcal = $vcal->expand(new DateTime('2014-08-01'), new DateTime('2014-09-01'));
 
         $expected = <<<ICS
 BEGIN:VCALENDAR
+VERSION:2.0
 BEGIN:VEVENT
 UID:foobar
 RECURRENCE-ID:20140803T120000Z
@@ -62,14 +65,11 @@ SUMMARY:Original
 RECURRENCE-ID:20140831T120000Z
 END:VEVENT
 END:VCALENDAR
-
 ICS;
 
-        $newIcs = $vcal->serialize();
-        $newIcs = str_replace("\r\n", "\n", $newIcs);
-        $this->assertEquals(
+        $this->assertVObjEquals(
             $expected,
-            $newIcs
+            $vcal
         );
 
 
@@ -79,6 +79,7 @@ ICS;
 
         $input =  <<<ICS
 BEGIN:VCALENDAR
+VERSION:2.0
 BEGIN:VEVENT
 UID:foobar
 DTSTART:20140803T120000Z
@@ -90,10 +91,11 @@ END:VCALENDAR
 ICS;
 
         $vcal = Reader::read($input);
-        $vcal->expand(new DateTime('2014-08-01'), new DateTime('2014-08-19'));
+        $vcal = $vcal->expand(new DateTime('2014-08-01'), new DateTime('2014-08-19'));
 
         $expected = <<<ICS
 BEGIN:VCALENDAR
+VERSION:2.0
 BEGIN:VEVENT
 UID:foobar
 DTSTART:20140810T120000Z
@@ -107,16 +109,12 @@ SUMMARY:Original
 RECURRENCE-ID:20140817T120000Z
 END:VEVENT
 END:VCALENDAR
-
 ICS;
 
-        $newIcs = $vcal->serialize();
-        $newIcs = str_replace("\r\n", "\n", $newIcs);
-        $this->assertEquals(
+        $this->assertVObjEquals(
             $expected,
-            $newIcs
+            $vcal
         );
 
-
     }
 }

-- 
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