[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