[Pkg-owncloud-commits] [php-sabre-vobject] 307/341: Created a FreeBusyData object to handle the freebusy/vavailability calcuations.

David Prévot taffit at moszumanska.debian.org
Tue Aug 11 13:35:59 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 7a9f535297b936c8dde2ce155521f23345dfdc1f
Author: Evert Pot <me at evertpot.com>
Date:   Wed Jul 8 02:24:31 2015 -0400

    Created a FreeBusyData object to handle the freebusy/vavailability
    calcuations.
---
 lib/FreeBusyData.php               | 197 +++++++++++++++++++++++
 lib/FreeBusyGenerator.php          |  32 +++-
 tests/VObject/FreeBusyDataTest.php | 320 +++++++++++++++++++++++++++++++++++++
 3 files changed, 543 insertions(+), 6 deletions(-)

diff --git a/lib/FreeBusyData.php b/lib/FreeBusyData.php
new file mode 100644
index 0000000..0ac4e61
--- /dev/null
+++ b/lib/FreeBusyData.php
@@ -0,0 +1,197 @@
+<?php
+
+namespace Sabre\VObject;
+
+use DateTimeInterface;
+
+/**
+ * FreeBusyData is a helper class that manages freebusy information.
+ *
+ * @copyright Copyright (C) 2007-2015 fruux GmbH. (https://fruux.com/)
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://sabre.io/license/ Modified BSD License
+ */
+class FreeBusyData {
+
+    /**
+     * Start timestamp
+     *
+     * @var int
+     */
+    protected $start;
+
+    /**
+     * End timestamp
+     *
+     * @var int
+     */
+    protected $end;
+
+    /**
+     * A list of free-busy times.
+     *
+     * @var array
+     */
+    protected $data;
+
+    function __construct($start, $end) {
+
+        $this->start = $start;
+        $this->end = $end;
+        $this->data = [];
+
+        $this->data[] = [
+            'start' => $this->start,
+            'end'   => $this->end,
+            'type'  => 'FREE',
+        ];
+
+    }
+
+    /**
+     * Adds free or busytime to the data.
+     *
+     * @param int $start
+     * @param int $end
+     * @param string $type FREE, BUSY, BUSY-UNAVAILABLE or BUSY-TENTATIVE
+     * @return void
+     */
+    function add($start, $end, $type) {
+
+        if ($start > $this->end || $end < $this->start) {
+
+            // This new data is outside our timerange.
+            return;
+
+        }
+
+        if ($start < $this->start) {
+            // The item starts before our requested time range
+            $start = $this->start;
+        }
+        if ($end > $this->end) {
+            // The item ends after our requested time range
+            $end = $this->end;
+        }  
+
+        // Finding out where we need to insert the new item.
+        $currentIndex = 0;
+        while($start > $this->data[$currentIndex]['end']) {
+            $currentIndex++;
+        }
+
+        // The standard insertion point will be one _after_ the first
+        // overlapping item.
+        $insertStartIndex = $currentIndex+1;
+
+        $newItem = [
+            'start' => $start,
+            'end'   => $end,
+            'type'  => $type,
+        ];
+
+        $preceedingItem = $this->data[$insertStartIndex-1];
+        if ($this->data[$insertStartIndex-1]['start'] === $start) {
+            // The old item starts at the exact same point as the new item.
+            $insertStartIndex--;
+         }
+
+        // Now we know where to insert the item, we need to know where it
+        // starts overlapping with items on the tail end. We need to start
+        // looking one item before the insertStartIndex, because it's possible
+        // that the new item 'sits inside' the previous old item.
+        if ($insertStartIndex > 0) {
+            $currentIndex = $insertStartIndex-1;
+        } else {
+            $currentIndex = 0;
+        }
+
+        while($end > $this->data[$currentIndex]['end']) {
+
+            $currentIndex++;
+
+        }
+
+        // What we are about to insert into the array
+        $newItems = [
+            $newItem
+        ];
+
+        // This is the amount of items that are completely overwritten by the
+        // new item.
+        $itemsToDelete = $currentIndex - $insertStartIndex;
+        if ($this->data[$currentIndex]['end'] <= $end) $itemsToDelete++;
+
+        // If itemsToDelete was -1, it means that the newly inserted item is
+        // actually sitting inside an existing one. This means we need to split
+        // the item at the current position in two and insert the new item in
+        // between.
+        if ($itemsToDelete === -1) {
+            $itemsToDelete = 0;
+            if ($newItem['end'] < $preceedingItem['end']) {
+                $newItems[] = [
+                    'start' => $newItem['end'] + 1,
+                    'end'   => $preceedingItem['end'],
+                    'type'  => $preceedingItem['type']
+                ];
+            }
+        } else {
+          
+        }
+
+        array_splice(
+            $this->data,
+            $insertStartIndex,
+            $itemsToDelete,
+            $newItems
+        );
+
+        $doMerge = false;
+        $mergeOffset = $insertStartIndex;
+        $mergeItem = $newItem;
+        $mergeDelete = 1;
+
+        if (isset($this->data[$insertStartIndex-1])) {
+            // Updating the start time of the previous item.
+            $this->data[$insertStartIndex-1]['end'] = $start - 1;
+
+            // If the previous and the current are of the same type, we can
+            // merge them into one item.
+            if ($this->data[$insertStartIndex-1]['type'] === $this->data[$insertStartIndex]['type']) {
+                $doMerge = true;
+                $mergeOffset--;
+                $mergeDelete++;
+                $mergeItem['start'] = $this->data[$insertStartIndex-1]['start'];
+            }
+        }
+        if (isset($this->data[$insertStartIndex+1])) {
+            // Updating the start time of the next item.
+            $this->data[$insertStartIndex+1]['start'] = $end + 1;
+
+            // If the next and the current are of the same type, we can
+            // merge them into one item.
+            if ($this->data[$insertStartIndex+1]['type'] === $this->data[$insertStartIndex]['type']) {
+                $doMerge = true;
+                $mergeDelete++;
+                $mergeItem['end'] = $this->data[$insertStartIndex+1]['end'];
+            }
+
+        }
+        if ($doMerge) {
+            array_splice(
+                $this->data,
+                $mergeOffset,
+                $mergeDelete,
+                [$mergeItem]
+            );
+        }
+
+    }
+
+    function getData() {
+
+        return $this->data;
+
+    }
+
+}
diff --git a/lib/FreeBusyGenerator.php b/lib/FreeBusyGenerator.php
index 7484c11..d812804 100644
--- a/lib/FreeBusyGenerator.php
+++ b/lib/FreeBusyGenerator.php
@@ -8,6 +8,7 @@ use DateTimeZone;
 use Sabre\VObject\Component\VCalendar;
 use Sabre\VObject\Recur\EventIterator;
 use Sabre\VObject\Recur\NoInstancesException;
+use SplDoublyLinkedList;
 
 /**
  * This class helps with generating FREEBUSY reports based on existing sets of
@@ -49,7 +50,7 @@ class FreeBusyGenerator {
     /**
      * VCALENDAR object.
      *
-     * @var Component
+     * @var Document
      */
     protected $baseObject;
 
@@ -69,6 +70,16 @@ class FreeBusyGenerator {
     protected $timeZone;
 
     /**
+     * A VAVAILABILITY document.
+     *
+     * If this is set, it's information will be included when calculating
+     * freebusy time.
+     *
+     * @var Document
+     */
+    protected $vavailability;
+
+    /**
      * Creates the generator.
      *
      * Check the setTimeRange and setObjects methods for details about the
@@ -103,17 +114,28 @@ class FreeBusyGenerator {
      *
      * The VFREEBUSY object will be automatically added though.
      *
-     * @param Component $vcalendar
-     *
+     * @param Document $vcalendar
      * @return void
      */
-    function setBaseObject(Component $vcalendar) {
+    function setBaseObject(Document $vcalendar) {
 
         $this->baseObject = $vcalendar;
 
     }
 
     /**
+     * Sets a VAVAILABILITY document.
+     *
+     * @param Document $vcalendar
+     * @return void
+     */
+    function setVAvailablility(Document $vcalendar) {
+
+        $this->vavailability = $vcalendar;
+
+    }
+
+    /**
      * Sets the input objects.
      *
      * You must either specify a valendar object as a strong, or as the parse
@@ -315,8 +337,6 @@ class FreeBusyGenerator {
                         }
                         break;
 
-
-
                 }
 
 
diff --git a/tests/VObject/FreeBusyDataTest.php b/tests/VObject/FreeBusyDataTest.php
new file mode 100644
index 0000000..90ce89c
--- /dev/null
+++ b/tests/VObject/FreeBusyDataTest.php
@@ -0,0 +1,320 @@
+<?php
+
+namespace Sabre\VObject;
+
+use DateTimeImmutable as DT;
+
+class FreeBusyDataTest extends \PHPUnit_Framework_TestCase {
+
+    function testGetData() {
+
+        $fb = new FreeBusyData(100, 200);
+
+        $this->assertEquals(
+            [
+                [
+                    'start' => 100,
+                    'end' => 200,
+                    'type' => 'FREE',
+                ]
+            ],
+            $fb->getData()
+        );
+
+    }
+
+    /**
+     * @depends testGetData
+     */
+    function testAddBeginning() {
+
+        $fb = new FreeBusyData(100, 200);
+
+        // Overwriting the first half
+        $fb->add(100,150,'BUSY');
+
+
+        $this->assertEquals(
+            [
+                [
+                    'start' => 100,
+                    'end' => 150,
+                    'type' => 'BUSY',
+                ],
+                [
+                    'start' => 151,
+                    'end' => 200,
+                    'type' => 'FREE',
+                ]
+            ],
+            $fb->getData()
+        );
+
+        // Overwriting the first half again
+        $fb->add(100,150,'BUSY-TENTATIVE');
+
+        $this->assertEquals(
+            [
+                [
+                    'start' => 100,
+                    'end' => 150,
+                    'type' => 'BUSY-TENTATIVE',
+                ],
+                [
+                    'start' => 151,
+                    'end' => 200,
+                    'type' => 'FREE',
+                ]
+            ],
+            $fb->getData()
+        );
+
+    }
+
+    /**
+     * @depends testAddBeginning
+     */
+    function testAddEnd() {
+
+        $fb = new FreeBusyData(100, 200);
+
+        // Overwriting the first half
+        $fb->add(151,200,'BUSY');
+
+
+        $this->assertEquals(
+            [
+                [
+                    'start' => 100,
+                    'end' => 150,
+                    'type' => 'FREE',
+                ],
+                [
+                    'start' => 151,
+                    'end' => 200,
+                    'type' => 'BUSY',
+                ],
+            ],
+            $fb->getData()
+        );
+
+
+    }
+
+    /**
+     * @depends testAddEnd
+     */
+    function testAddMiddle() {
+
+        $fb = new FreeBusyData(100, 200);
+
+        // Overwriting the first half
+        $fb->add(150,160,'BUSY');
+
+
+        $this->assertEquals(
+            [
+                [
+                    'start' => 100,
+                    'end' => 149,
+                    'type' => 'FREE',
+                ],
+                [
+                    'start' => 150,
+                    'end' => 160,
+                    'type' => 'BUSY',
+                ],
+                [
+                    'start' => 161,
+                    'end' => 200,
+                    'type' => 'FREE',
+                ],
+            ],
+            $fb->getData()
+        );
+
+    }
+
+    /**
+     * @depends testAddMiddle
+     */
+    function testAddMultiple() {
+
+        $fb = new FreeBusyData(100, 200);
+
+        $fb->add(110, 120, 'BUSY');
+        $fb->add(130, 140, 'BUSY');
+
+        $this->assertEquals(
+            [
+                [
+                    'start' => 100,
+                    'end' => 109,
+                    'type' => 'FREE',
+                ],
+                [
+                    'start' => 110,
+                    'end' => 120,
+                    'type' => 'BUSY',
+                ],
+                [
+                    'start' => 121,
+                    'end' => 129,
+                    'type' => 'FREE',
+                ],
+                [
+                    'start' => 130,
+                    'end' => 140,
+                    'type' => 'BUSY',
+                ],
+                [
+                    'start' => 141,
+                    'end' => 200,
+                    'type' => 'FREE',
+                ],
+            ],
+            $fb->getData()
+        );
+
+    }
+
+    /**
+     * @depends testAddMultiple
+     */
+    function testAddMultipleOverlap() {
+
+        $fb = new FreeBusyData(100, 200);
+
+        $fb->add(110, 120, 'BUSY');
+        $fb->add(130, 140, 'BUSY');
+
+        $this->assertEquals(
+            [
+                [
+                    'start' => 100,
+                    'end' => 109,
+                    'type' => 'FREE',
+                ],
+                [
+                    'start' => 110,
+                    'end' => 120,
+                    'type' => 'BUSY',
+                ],
+                [
+                    'start' => 121,
+                    'end' => 129,
+                    'type' => 'FREE',
+                ],
+                [
+                    'start' => 130,
+                    'end' => 140,
+                    'type' => 'BUSY',
+                ],
+                [
+                    'start' => 141,
+                    'end' => 200,
+                    'type' => 'FREE',
+                ],
+            ],
+            $fb->getData()
+        );
+
+        $fb->add(115, 135, 'BUSY-TENTATIVE');
+
+        $this->assertEquals(
+            [
+                [
+                    'start' => 100,
+                    'end' => 109,
+                    'type' => 'FREE',
+                ],
+                [
+                    'start' => 110,
+                    'end' => 114,
+                    'type' => 'BUSY',
+                ],
+                [
+                    'start' => 115,
+                    'end' => 135,
+                    'type' => 'BUSY-TENTATIVE',
+                ],
+                [
+                    'start' => 136,
+                    'end' => 140,
+                    'type' => 'BUSY',
+                ],
+                [
+                    'start' => 141,
+                    'end' => 200,
+                    'type' => 'FREE',
+                ],
+            ],
+            $fb->getData()
+        );
+    }
+
+    /**
+     * @depends testAddMultipleOverlap
+     */
+    function testAddMultipleOverlapAndMerge() {
+
+        $fb = new FreeBusyData(100, 200);
+
+        $fb->add(110, 120, 'BUSY');
+        $fb->add(130, 140, 'BUSY');
+
+        $this->assertEquals(
+            [
+                [
+                    'start' => 100,
+                    'end' => 109,
+                    'type' => 'FREE',
+                ],
+                [
+                    'start' => 110,
+                    'end' => 120,
+                    'type' => 'BUSY',
+                ],
+                [
+                    'start' => 121,
+                    'end' => 129,
+                    'type' => 'FREE',
+                ],
+                [
+                    'start' => 130,
+                    'end' => 140,
+                    'type' => 'BUSY',
+                ],
+                [
+                    'start' => 141,
+                    'end' => 200,
+                    'type' => 'FREE',
+                ],
+            ],
+            $fb->getData()
+        );
+
+        $fb->add(115, 135, 'BUSY');
+
+        $this->assertEquals(
+            [
+                [
+                    'start' => 100,
+                    'end' => 109,
+                    'type' => 'FREE',
+                ],
+                [
+                    'start' => 110,
+                    'end' => 140,
+                    'type' => 'BUSY',
+                ],
+                [
+                    'start' => 141,
+                    'end' => 200,
+                    'type' => 'FREE',
+                ],
+            ],
+            $fb->getData()
+        );
+    }
+}

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