119 $this->baseObject = $vcalendar;
131 $this->vavailability = $vcalendar;
155 if (is_string($object) || is_resource($object)) {
157 } elseif ($object instanceof
Component) {
158 $this->objects[] = $object;
160 throw new \InvalidArgumentException(
'You can only pass strings or \\Sabre\\VObject\\Component arguments to setObjects');
212 $this->start->getTimeStamp(),
213 $this->end->getTimeStamp()
215 if ($this->vavailability) {
238 $vavailComps = iterator_to_array($vavailability->VAVAILABILITY);
248 $priorityA = isset($a->PRIORITY) ? (int)$a->PRIORITY->getValue() : 0;
249 $priorityB = isset($b->PRIORITY) ? (int)$b->PRIORITY->getValue() : 0;
251 if ($priorityA === 0) $priorityA = 10;
252 if ($priorityB === 0) $priorityB = 10;
254 return $priorityA - $priorityB;
269 foreach ($old as $vavail) {
271 list($compStart, $compEnd) = $vavail->getEffectiveStartEnd();
276 if (is_null($compStart) || $compStart < $this->start) {
279 if (is_null($compEnd) || $compEnd > $this->end) {
284 if ($compStart > $this->end || $compEnd < $this->start) {
290 foreach ($new as $higherVavail) {
292 list($higherStart, $higherEnd) = $higherVavail->getEffectiveStartEnd();
294 (is_null($higherStart) || $higherStart < $compStart) &&
295 (is_null($higherEnd) || $higherEnd > $compEnd)
316 foreach (array_reverse($new) as $vavail) {
318 $busyType = isset($vavail->BUSYTYPE) ? strtoupper($vavail->BUSYTYPE) :
'BUSY-UNAVAILABLE';
319 list($vavailStart, $vavailEnd) = $vavail->getEffectiveStartEnd();
323 if (!$vavailStart || $vavailStart < $this->start) {
326 if (!$vavailEnd || $vavailEnd > $this->end) {
333 $vavailStart->getTimeStamp(),
334 $vavailEnd->getTimeStamp(),
339 if (isset($vavail->AVAILABLE))
foreach ($vavail->AVAILABLE as $available) {
341 list($availStart, $availEnd) = $available->getEffectiveStartEnd();
343 $availStart->getTimeStamp(),
344 $availEnd->getTimeStamp(),
348 if ($available->RRULE) {
352 $available->RRULE->getValue(),
357 $startEndDiff = $availStart->diff($availEnd);
359 while ($rruleIterator->valid()) {
361 $recurStart = $rruleIterator->current();
362 $recurEnd = $recurStart->add($startEndDiff);
364 if ($recurStart > $vavailEnd) {
369 if ($recurEnd > $vavailEnd) {
372 $recurEnd = $vavailEnd;
376 $recurStart->getTimeStamp(),
377 $recurEnd->getTimeStamp(),
381 $rruleIterator->next();
401 foreach ($objects as
$key => $object) {
403 foreach ($object->getBaseComponents() as $component) {
405 switch ($component->name) {
410 if (isset($component->TRANSP) && (strtoupper($component->TRANSP) ===
'TRANSPARENT')) {
413 if (isset($component->STATUS)) {
414 $status = strtoupper($component->STATUS);
415 if ($status ===
'CANCELLED') {
418 if ($status ===
'TENTATIVE') {
419 $FBTYPE =
'BUSY-TENTATIVE';
425 if ($component->RRULE) {
427 $iterator =
new EventIterator($object, (
string)$component->UID, $this->timeZone);
432 unset($this->objects[
$key]);
437 $iterator->fastForward($this->start);
442 while ($iterator->valid() && --$maxRecurrences) {
444 $startTime = $iterator->getDTStart();
445 if ($this->end && $startTime > $this->end) {
449 $iterator->getDTStart(),
450 $iterator->getDTEnd(),
459 $startTime = $component->DTSTART->getDateTime($this->timeZone);
460 if ($this->end && $startTime > $this->end) {
464 if (isset($component->DTEND)) {
465 $endTime = $component->DTEND->getDateTime($this->timeZone);
466 } elseif (isset($component->DURATION)) {
468 $endTime = clone $startTime;
469 $endTime = $endTime->add($duration);
470 } elseif (!$component->DTSTART->hasTime()) {
471 $endTime = clone $startTime;
472 $endTime = $endTime->modify(
'+1 day');
478 $times[] = [$startTime, $endTime];
482 foreach ($times as
$time) {
484 if ($this->end && $time[0] > $this->end)
break;
485 if ($this->start && $time[1] < $this->start)
break;
488 $time[0]->getTimeStamp(),
489 $time[1]->getTimeStamp(),
496 foreach ($component->FREEBUSY as $freebusy) {
498 $fbType = isset($freebusy[
'FBTYPE']) ? strtoupper($freebusy[
'FBTYPE']) :
'BUSY';
501 if ($fbType ===
'FREE')
504 $values = explode(
',', $freebusy);
506 list($startTime, $endTime) = explode(
'/', $value);
509 if (substr($endTime, 0, 1) ===
'P' || substr($endTime, 0, 2) ===
'-P') {
511 $endTime = clone $startTime;
512 $endTime = $endTime->add($duration);
517 if ($this->start && $this->start > $endTime)
continue;
518 if ($this->end && $this->end < $startTime)
continue;
520 $startTime->getTimeStamp(),
521 $endTime->getTimeStamp(),
548 if ($this->baseObject) {
554 $vfreebusy =
$calendar->createComponent(
'VFREEBUSY');
558 $dtstart =
$calendar->createProperty(
'DTSTART');
559 $dtstart->setDateTime($this->start);
560 $vfreebusy->add($dtstart);
563 $dtend =
$calendar->createProperty(
'DTEND');
564 $dtend->setDateTime($this->end);
565 $vfreebusy->add($dtend);
568 $tz = new \DateTimeZone(
'UTC');
569 $dtstamp =
$calendar->createProperty(
'DTSTAMP');
571 $vfreebusy->add($dtstamp);
573 foreach ($fbData->
getData() as $busyTime) {
575 $busyType = strtoupper($busyTime[
'type']);
578 if ($busyType ===
'FREE') {
582 $busyTime[0] = new \DateTimeImmutable(
'@' . $busyTime[
'start'],
$tz);
583 $busyTime[1] = new \DateTimeImmutable(
'@' . $busyTime[
'end'],
$tz);
587 $busyTime[0]->format(
'Ymd\\THis\\Z') .
'/' . $busyTime[1]->format(
'Ymd\\THis\\Z')
592 if ($busyType !==
'BUSY') {
593 $prop[
'FBTYPE'] = $busyType;
595 $vfreebusy->add($prop);
static $maxDate
The maximum date we accept for various calculations with dates, such as recurrences.
static $minDate
The minimum date we accept for various calculations with dates, such as recurrences.
static parseDateTime($dt, DateTimeZone $tz=null)
Parses an iCalendar (rfc5545) formatted datetime and returns a DateTimeImmutable object.
setTimeRange(DateTimeInterface $start=null, DateTimeInterface $end=null)
Sets the time range.
This class helps with generating FREEBUSY reports based on existing sets of objects.
FreeBusyData is a helper class that manages freebusy information.
static $maxRecurrences
The maximum number of recurrences that will be generated.
calculateAvailability(FreeBusyData $fbData, VCalendar $vavailability)
This method takes a VAVAILABILITY component and figures out all the available times.
generateFreeBusyCalendar(FreeBusyData $fbData)
This method takes a FreeBusyData object and generates the VCALENDAR object associated with it...
setBaseObject(Document $vcalendar)
Sets the VCALENDAR object.
setVAvailability(Document $vcalendar)
Sets a VAVAILABILITY document.
This class is used to determine new for a recurring event, when the next events occur.
This exception gets thrown when a recurrence iterator produces 0 instances.
__construct(DateTimeInterface $start=null, DateTimeInterface $end=null, $objects=null, DateTimeZone $timeZone=null)
Creates the generator.
setObjects($objects)
Sets the input objects.
add($start, $end, $type)
Adds free or busytime to the data.
setTimeZone(DateTimeZone $timeZone)
Sets the reference timezone for floating times.
fastForward(DateTimeInterface $dt)
This method allows you to quickly go to the next occurrence after the specified date.
static read($data, $options=0, $charset='UTF-8')
Parses a vCard or iCalendar object, and returns the top component.
static parseDuration($duration, $asString=false)
Parses an iCalendar (RFC5545) formatted duration value.
calculateBusy(FreeBusyData $fbData, array $objects)
This method takes an array of iCalendar objects and applies its busy times on fbData.
getResult()
Parses the input data and returns a correct VFREEBUSY object, wrapped in a VCALENDAR.