1<?php
2
3namespace Sabre\VObject\Component;
4
5use Sabre\VObject;
6
7/**
8 * The VFreeBusy component
9 *
10 * This component adds functionality to a component, specific for VFREEBUSY
11 * components.
12 *
13 * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
14 * @author Evert Pot (http://evertpot.com/)
15 * @license http://sabre.io/license/ Modified BSD License
16 */
17class VFreeBusy extends VObject\Component {
18
19    /**
20     * Checks based on the contained FREEBUSY information, if a timeslot is
21     * available.
22     *
23     * @param DateTime $start
24     * @param Datetime $end
25     * @return bool
26     */
27    public function isFree(\DateTime $start, \Datetime $end) {
28
29        foreach($this->select('FREEBUSY') as $freebusy) {
30
31            // We are only interested in FBTYPE=BUSY (the default),
32            // FBTYPE=BUSY-TENTATIVE or FBTYPE=BUSY-UNAVAILABLE.
33            if (isset($freebusy['FBTYPE']) && strtoupper(substr((string)$freebusy['FBTYPE'],0,4))!=='BUSY') {
34                continue;
35            }
36
37            // The freebusy component can hold more than 1 value, separated by
38            // commas.
39            $periods = explode(',', (string)$freebusy);
40
41            foreach($periods as $period) {
42                // Every period is formatted as [start]/[end]. The start is an
43                // absolute UTC time, the end may be an absolute UTC time, or
44                // duration (relative) value.
45                list($busyStart, $busyEnd) = explode('/', $period);
46
47                $busyStart = VObject\DateTimeParser::parse($busyStart);
48                $busyEnd = VObject\DateTimeParser::parse($busyEnd);
49                if ($busyEnd instanceof \DateInterval) {
50                    $tmp = clone $busyStart;
51                    $tmp->add($busyEnd);
52                    $busyEnd = $tmp;
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    public function getValidationRules() {
83
84        return array(
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
104