1<?php
2
3namespace Sabre\VObject\Component;
4
5use DateTimeInterface;
6use Sabre\VObject;
7
8/**
9 * The VFreeBusy component.
10 *
11 * This component adds functionality to a component, specific for VFREEBUSY
12 * components.
13 *
14 * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
15 * @author Evert Pot (http://evertpot.com/)
16 * @license http://sabre.io/license/ Modified BSD License
17 */
18class VFreeBusy extends VObject\Component {
19
20    /**
21     * Checks based on the contained FREEBUSY information, if a timeslot is
22     * available.
23     *
24     * @param DateTimeInterface $start
25     * @param DateTimeInterface $end
26     *
27     * @return bool
28     */
29    function isFree(DateTimeInterface $start, DatetimeInterface $end) {
30
31        foreach ($this->select('FREEBUSY') as $freebusy) {
32
33            // We are only interested in FBTYPE=BUSY (the default),
34            // FBTYPE=BUSY-TENTATIVE or FBTYPE=BUSY-UNAVAILABLE.
35            if (isset($freebusy['FBTYPE']) && strtoupper(substr((string)$freebusy['FBTYPE'], 0, 4)) !== 'BUSY') {
36                continue;
37            }
38
39            // The freebusy component can hold more than 1 value, separated by
40            // commas.
41            $periods = explode(',', (string)$freebusy);
42
43            foreach ($periods as $period) {
44                // Every period is formatted as [start]/[end]. The start is an
45                // absolute UTC time, the end may be an absolute UTC time, or
46                // duration (relative) value.
47                list($busyStart, $busyEnd) = explode('/', $period);
48
49                $busyStart = VObject\DateTimeParser::parse($busyStart);
50                $busyEnd = VObject\DateTimeParser::parse($busyEnd);
51                if ($busyEnd instanceof \DateInterval) {
52                    $busyEnd = $busyStart->add($busyEnd);
53                }
54
55                if ($start < $busyEnd && $end > $busyStart) {
56                    return false;
57                }
58
59            }
60
61        }
62
63        return true;
64
65    }
66
67    /**
68     * A simple list of validation rules.
69     *
70     * This is simply a list of properties, and how many times they either
71     * must or must not appear.
72     *
73     * Possible values per property:
74     *   * 0 - Must not appear.
75     *   * 1 - Must appear exactly once.
76     *   * + - Must appear at least once.
77     *   * * - Can appear any number of times.
78     *   * ? - May appear, but not more than once.
79     *
80     * @var array
81     */
82    function getValidationRules() {
83
84        return [
85            'UID'     => 1,
86            'DTSTAMP' => 1,
87
88            'CONTACT'   => '?',
89            'DTSTART'   => '?',
90            'DTEND'     => '?',
91            'ORGANIZER' => '?',
92            'URL'       => '?',
93
94            'ATTENDEE'       => '*',
95            'COMMENT'        => '*',
96            'FREEBUSY'       => '*',
97            'REQUEST-STATUS' => '*',
98        ];
99
100    }
101
102}
103