[Pkg-owncloud-commits] [php-sabre-vobject] 324/341: First attempt at calculating VAVAILABILITY.

David Prévot taffit at moszumanska.debian.org
Tue Aug 11 13:36:01 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 69e55a381572b044e1cc80f0fb6b4fd60a8a5e17
Author: Evert Pot <me at evertpot.com>
Date:   Thu Jul 16 21:40:34 2015 -0400

    First attempt at calculating VAVAILABILITY.
    
    Shockingly no syntax errors on the first try.
---
 lib/Component/Available.php     |  23 ++++++
 lib/Component/VAvailability.php |  55 +++++++++++++++
 lib/FreeBusyGenerator.php       | 152 +++++++++++++++++++++++++++++++++++++++-
 3 files changed, 229 insertions(+), 1 deletion(-)

diff --git a/lib/Component/Available.php b/lib/Component/Available.php
index 832c737..8f11cf6 100644
--- a/lib/Component/Available.php
+++ b/lib/Component/Available.php
@@ -17,6 +17,29 @@ use Sabre\VObject;
 class Available extends VObject\Component {
 
     /**
+     * Returns the 'effective start' and 'effective end' of this VAVAILABILITY
+     * component.
+     *
+     * We use the DTSTART and DTEND or DURATION to determine this.
+     *
+     * The returned value is an array containing DateTimeImmutable instances.
+     * If either the start or end is 'unbounded' its value will be null
+     * instead.
+     *
+     * @return array
+     */
+    function getEffectiveStartEnd() {
+
+        $effectiveStart = $this->DTSTART->getDateTime();
+        if (isset($this->DTEND)) {
+            $effectiveEnd = $this->DTEND->getDateTime();
+        } else {
+            $effectiveEnd = $effectiveStart->add(VObject\DateTimeParser::parseDuration($this->DURATION));
+        }
+
+        return [$effectiveStart, $effectiveEnd];
+
+    /**
      * A simple list of validation rules.
      *
      * This is simply a list of properties, and how many times they either
diff --git a/lib/Component/VAvailability.php b/lib/Component/VAvailability.php
index 4f9aa24..7e40b7c 100644
--- a/lib/Component/VAvailability.php
+++ b/lib/Component/VAvailability.php
@@ -17,6 +17,61 @@ use Sabre\VObject;
 class VAvailability extends VObject\Component {
 
     /**
+     * Returns true or false depending on if the event falls in the specified
+     * time-range. This is used for filtering purposes.
+     *
+     * The rules used to determine if an event falls within the specified
+     * time-range is based on:
+     *
+     * https://tools.ietf.org/html/draft-daboo-calendar-availability-05#section-3.1
+     *
+     * @param DateTimeInterface $start
+     * @param DateTimeInterface $end
+     *
+     * @return bool
+     */
+    function isInTimeRange(DateTimeInterface $start, DateTimeInterface $end) {
+
+        list($effectiveStart, $effectiveEnd) = $this->getEffectiveStartEnd();
+        return (
+            (is_null($start) || $start < $effectiveEnd) &&
+            (is_null($end) || $end > $effectiveStart)
+        );
+
+    }
+
+    /**
+     * Returns the 'effective start' and 'effective end' of this VAVAILABILITY
+     * component.
+     *
+     * We use the DTSTART and DTEND or DURATION to determine this.
+     *
+     * The returned value is an array containing DateTimeImmutable instances.
+     * If either the start or end is 'unbounded' its value will be null
+     * instead.
+     *
+     * @return array
+     */
+    function getEffectiveStartEnd() {
+
+        $effectiveStart = null;
+        $effectiveEnd = null;
+
+        if (isset($this->DTSTART)) {
+            $effectiveStart = $this->DTSTART->getDateTime();
+        }
+        if (isset($this->DTEND)) {
+            $effectiveEnd = $this->DTEND->getDateTime();
+        } elseif ($effectiveStart && isset($this->DURATION)) {
+            $effectiveEnd = $effectiveStart->add(VObject\DateTimeParser::parseDuration($this->DURATION));
+        }
+
+        return [$effectiveStart, $effectiveEnd];
+
+    }
+
+
+    /**
      * A simple list of validation rules.
      *
      * This is simply a list of properties, and how many times they either
diff --git a/lib/FreeBusyGenerator.php b/lib/FreeBusyGenerator.php
index fd1ca77..147f491 100644
--- a/lib/FreeBusyGenerator.php
+++ b/lib/FreeBusyGenerator.php
@@ -235,6 +235,156 @@ class FreeBusyGenerator {
      */
     protected function calculateAvailability(FreeBusyData $fbData, VCalendar $vavailability) {
 
+        $vavailComps = usort(
+            iterator_to_array($vavailability->VAVAILABILITY),
+            function($a, $b) {
+
+                // We need to order the components by priority. Priority 1
+                // comes first, up until priority 9. Priority 0 comes after
+                // priority 9. No priority implies priority 0.
+                //
+                // Yes, I'm serious.
+                $priorityA = isset($a->PRIORITY) ? (int)$a->PRIORITY->getValue() : 0;
+                $priorityB = isset($b->PRIORITY) ? (int)$b->PRIORITY->getValue() : 0;
+
+                if ($priorityA === 0) $priorityA = 10;
+                if ($priorityB === 0) $priorityB = 10;
+
+                return $priorityA - $priorityB;
+
+            }
+        );
+
+        // Now we go over all the VAVAILABILITY components and figure if
+        // there's any we don't need to consider.
+        //
+        // This is can be because of one of two reasons: either the
+        // VAVAILABILITY component falls outside the time we are interested in,
+        // or a different VAVAILABILITY component with a higher priority has
+        // already completely covered the time-range.
+        $old = $vavailComps;
+        $new = [];
+
+        foreach($old as $vavail) {
+
+            list($compStart, $compEnd) = $vavail->getEffectiveStartEnd();
+
+            // We don't care about datetimes that are earlier or later than the
+            // start and end of the freebusy report, so this gets normalized
+            // first.
+            if (is_null($compStart) || $compStart < $this->start) {
+                $compStart = $this->start;
+            }
+            if (is_null($compEnd) || $compEnd < $this->end) {
+                $compEnd = $this->end;
+            }
+
+            // If the item fell out of the timerange, we can just skip it.
+            if ($compStart > $this->end || $compEnd < $this->start) {
+                continue;
+            }
+
+            // Going through our existing list of components to see if there's
+            // a higher priority component that already fully covers this one.
+            foreach($new as $higherVavail) {
+
+                list($higherStart, $higherEnd) = $higherVavail->getEffectiveStartEnd();
+                if (
+                    (is_null($higherStart) || $higherStart < $compStart) &&
+                    (is_null($higherEnd)   || $higherEnd > $compEnd)
+                ) {
+
+                    // Component is fully covered by a higher priority
+                    // component. We can skip this component.
+                    continue 2;
+
+                }
+
+            }
+
+            // We're keeping it!
+            $new[] = $vavail;
+
+        }
+
+        // Lastly, we need to traverse the remaining components and fill in the
+        // freebusydata slots.
+        //
+        // We traverse the components in reverse, because we want the higher
+        // priority components to override the lower ones.
+        foreach(array_reverse($new) as $vavail) {
+
+            $busyType = isset($vavail->busyType) ? strtoupper($vavail->busyType) : 'BUSY-UNAVAILABLE';
+            list($vavailStart, $vavailEnd) = $vavail->getEffectiveStartEnd();
+
+            // Making the component size no larger than the requested free-busy
+            // report range.
+            if (!$vavailStart || $vavailStart < $this->start) {
+                $vavailStart = $this->start;
+            }
+            if (!$vavailEnd || $vavailEnd > $this->end) {
+                $vavailEnd = $this->end;
+            }
+
+            // Marking the entire time range of the VAVAILABILITY component as
+            // busy.
+            $fbData->add(
+                $vavailStart->getTimeStamp(),
+                $vavailEnd->getTimeStamp(),
+                $busyType
+            );
+
+            // Looping over the AVAILABLE components.
+            foreach($vavail->AVAILABLE as $available) {
+
+                list($availStart, $availEnd) = $available->getEffectiveStartEnd();
+                $fbData->add(
+                    $availStart->getTimeStamp(),
+                    $availEnd->getTimeStamp(),
+                    'FREE'
+                );
+
+                if ($available->RRULE) {
+                    // Our favourite thing: recurrence!!
+
+                    $rruleIterator = new Recur\RRuleIterator(
+                        $available->RRULE->getValue(),
+                        $availStart
+                    );
+                    $rruleIterator->fastForward($vavailStart);
+
+                    $startEndDiff = $availStart->diff($availEnd);
+
+                    while($rruleIterator->valid()) {
+
+                        $recurStart = $rruleIterator->current();
+                        $recurEnd = $recurStart->add($startEndDiff);
+
+                        if ($recurStart > $vavailEnd) {
+                            // We're beyond the legal timerange.
+                            break;
+                        }
+
+                        if ($recurEnd > $vavailEnd) {
+                            // Truncating the end if it exceeds the
+                            // VAVAILABILITY end.
+                            $recurEnd = $vavailEnd;
+                        }
+
+                        $fbData->add(
+                            $recurStart->getTimeStamp(),
+                            $recurEnd->getTimeStamp(),
+                            'FREE'
+                        );
+
+                        $rruleIterator->next();
+
+                    }
+                }
+
+            }
+
+        }
 
     }
 
@@ -392,7 +542,7 @@ class FreeBusyGenerator {
      *
      * @return VCalendar
      */
-    function generateFreeBusyCalendar(FreeBusyData $fbData) {
+    protected function generateFreeBusyCalendar(FreeBusyData $fbData) {
 
         if ($this->baseObject) {
             $calendar = $this->baseObject;

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