diff options
Diffstat (limited to 'vendor/sabre/vobject/lib/FreeBusyData.php')
-rw-r--r-- | vendor/sabre/vobject/lib/FreeBusyData.php | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/vendor/sabre/vobject/lib/FreeBusyData.php b/vendor/sabre/vobject/lib/FreeBusyData.php new file mode 100644 index 000000000..0a6c72bb2 --- /dev/null +++ b/vendor/sabre/vobject/lib/FreeBusyData.php @@ -0,0 +1,193 @@ +<?php + +namespace Sabre\VObject; + +/** + * FreeBusyData is a helper class that manages freebusy information. + * + * @copyright Copyright (C) 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'] + ]; + } + } + + 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; + + // 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; + + // 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; + + } + +} |