source: pmb4.2/trunk/fuentes/pmb/admin/connecteurs/out/webdav/vendor/sabre/vobject/lib/Sabre/VObject/FreeBusyGenerator.php @ 815

Last change on this file since 815 was 815, checked in by jrpelegrina, 4 years ago

Initial release of pmb 4.2

  • Property svn:executable set to *
File size: 9.8 KB
Line 
1<?php
2
3namespace Sabre\VObject;
4
5/**
6 * This class helps with generating FREEBUSY reports based on existing sets of
7 * objects.
8 *
9 * It only looks at VEVENT and VFREEBUSY objects from the sourcedata, and
10 * generates a single VFREEBUSY object.
11 *
12 * VFREEBUSY components are described in RFC5545, The rules for what should
13 * go in a single freebusy report is taken from RFC4791, section 7.10.
14 *
15 * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved.
16 * @author Evert Pot (http://www.rooftopsolutions.nl/)
17 * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
18 */
19class FreeBusyGenerator {
20
21    /**
22     * Input objects
23     *
24     * @var array
25     */
26    protected $objects;
27
28    /**
29     * Start of range
30     *
31     * @var DateTime|null
32     */
33    protected $start;
34
35    /**
36     * End of range
37     *
38     * @var DateTime|null
39     */
40    protected $end;
41
42    /**
43     * VCALENDAR object
44     *
45     * @var Component
46     */
47    protected $baseObject;
48
49    /**
50     * Creates the generator.
51     *
52     * Check the setTimeRange and setObjects methods for details about the
53     * arguments.
54     *
55     * @param DateTime $start
56     * @param DateTime $end
57     * @param mixed $objects
58     * @return void
59     */
60    public function __construct(\DateTime $start = null, \DateTime $end = null, $objects = null) {
61
62        if ($start && $end) {
63            $this->setTimeRange($start, $end);
64        }
65
66        if ($objects) {
67            $this->setObjects($objects);
68        }
69
70    }
71
72    /**
73     * Sets the VCALENDAR object.
74     *
75     * If this is set, it will not be generated for you. You are responsible
76     * for setting things like the METHOD, CALSCALE, VERSION, etc..
77     *
78     * The VFREEBUSY object will be automatically added though.
79     *
80     * @param Component $vcalendar
81     * @return void
82     */
83    public function setBaseObject(Component $vcalendar) {
84
85        $this->baseObject = $vcalendar;
86
87    }
88
89    /**
90     * Sets the input objects
91     *
92     * You must either specify a valendar object as a strong, or as the parse
93     * Component.
94     * It's also possible to specify multiple objects as an array.
95     *
96     * @param mixed $objects
97     * @return void
98     */
99    public function setObjects($objects) {
100
101        if (!is_array($objects)) {
102            $objects = array($objects);
103        }
104
105        $this->objects = array();
106        foreach($objects as $object) {
107
108            if (is_string($object)) {
109                $this->objects[] = Reader::read($object);
110            } elseif ($object instanceof Component) {
111                $this->objects[] = $object;
112            } else {
113                throw new \InvalidArgumentException('You can only pass strings or \\Sabre\\VObject\\Component arguments to setObjects');
114            }
115
116        }
117
118    }
119
120    /**
121     * Sets the time range
122     *
123     * Any freebusy object falling outside of this time range will be ignored.
124     *
125     * @param DateTime $start
126     * @param DateTime $end
127     * @return void
128     */
129    public function setTimeRange(\DateTime $start = null, \DateTime $end = null) {
130
131        $this->start = $start;
132        $this->end = $end;
133
134    }
135
136    /**
137     * Parses the input data and returns a correct VFREEBUSY object, wrapped in
138     * a VCALENDAR.
139     *
140     * @return Component
141     */
142    public function getResult() {
143
144        $busyTimes = array();
145
146        foreach($this->objects as $object) {
147
148            foreach($object->getBaseComponents() as $component) {
149
150                switch($component->name) {
151
152                    case 'VEVENT' :
153
154                        $FBTYPE = 'BUSY';
155                        if (isset($component->TRANSP) && (strtoupper($component->TRANSP) === 'TRANSPARENT')) {
156                            break;
157                        }
158                        if (isset($component->STATUS)) {
159                            $status = strtoupper($component->STATUS);
160                            if ($status==='CANCELLED') {
161                                break;
162                            }
163                            if ($status==='TENTATIVE') {
164                                $FBTYPE = 'BUSY-TENTATIVE';
165                            }
166                        }
167
168                        $times = array();
169
170                        if ($component->RRULE) {
171
172                            $iterator = new RecurrenceIterator($object, (string)$component->uid);
173                            if ($this->start) {
174                                $iterator->fastForward($this->start);
175                            }
176
177                            $maxRecurrences = 200;
178
179                            while($iterator->valid() && --$maxRecurrences) {
180
181                                $startTime = $iterator->getDTStart();
182                                if ($this->end && $startTime > $this->end) {
183                                    break;
184                                }
185                                $times[] = array(
186                                    $iterator->getDTStart(),
187                                    $iterator->getDTEnd(),
188                                );
189
190                                $iterator->next();
191
192                            }
193
194                        } else {
195
196                            $startTime = $component->DTSTART->getDateTime();
197                            if ($this->end && $startTime > $this->end) {
198                                break;
199                            }
200                            $endTime = null;
201                            if (isset($component->DTEND)) {
202                                $endTime = $component->DTEND->getDateTime();
203                            } elseif (isset($component->DURATION)) {
204                                $duration = DateTimeParser::parseDuration((string)$component->DURATION);
205                                $endTime = clone $startTime;
206                                $endTime->add($duration);
207                            } elseif ($component->DTSTART->getDateType() === Property\DateTime::DATE) {
208                                $endTime = clone $startTime;
209                                $endTime->modify('+1 day');
210                            } else {
211                                // The event had no duration (0 seconds)
212                                break;
213                            }
214
215                            $times[] = array($startTime, $endTime);
216
217                        }
218
219                        foreach($times as $time) {
220
221                            if ($this->end && $time[0] > $this->end) break;
222                            if ($this->start && $time[1] < $this->start) break;
223
224                            $busyTimes[] = array(
225                                $time[0],
226                                $time[1],
227                                $FBTYPE,
228                            );
229                        }
230                        break;
231
232                    case 'VFREEBUSY' :
233                        foreach($component->FREEBUSY as $freebusy) {
234
235                            $fbType = isset($freebusy['FBTYPE'])?strtoupper($freebusy['FBTYPE']):'BUSY';
236
237                            // Skipping intervals marked as 'free'
238                            if ($fbType==='FREE')
239                                continue;
240
241                            $values = explode(',', $freebusy);
242                            foreach($values as $value) {
243                                list($startTime, $endTime) = explode('/', $value);
244                                $startTime = DateTimeParser::parseDateTime($startTime);
245
246                                if (substr($endTime,0,1)==='P' || substr($endTime,0,2)==='-P') {
247                                    $duration = DateTimeParser::parseDuration($endTime);
248                                    $endTime = clone $startTime;
249                                    $endTime->add($duration);
250                                } else {
251                                    $endTime = DateTimeParser::parseDateTime($endTime);
252                                }
253
254                                if($this->start && $this->start > $endTime) continue;
255                                if($this->end && $this->end < $startTime) continue;
256                                $busyTimes[] = array(
257                                    $startTime,
258                                    $endTime,
259                                    $fbType
260                                );
261
262                            }
263
264
265                        }
266                        break;
267
268
269
270                }
271
272
273            }
274
275        }
276
277        if ($this->baseObject) {
278            $calendar = $this->baseObject;
279        } else {
280            $calendar = Component::create('VCALENDAR');
281            $calendar->version = '2.0';
282            $calendar->prodid = '-//Sabre//Sabre VObject ' . Version::VERSION . '//EN';
283            $calendar->calscale = 'GREGORIAN';
284        }
285
286        $vfreebusy = Component::create('VFREEBUSY');
287        $calendar->add($vfreebusy);
288
289        if ($this->start) {
290            $dtstart = Property::create('DTSTART');
291            $dtstart->setDateTime($this->start,Property\DateTime::UTC);
292            $vfreebusy->add($dtstart);
293        }
294        if ($this->end) {
295            $dtend = Property::create('DTEND');
296            $dtend->setDateTime($this->end,Property\DateTime::UTC);
297            $vfreebusy->add($dtend);
298        }
299        $dtstamp = Property::create('DTSTAMP');
300        $dtstamp->setDateTime(new \DateTime('now'), Property\DateTime::UTC);
301        $vfreebusy->add($dtstamp);
302
303        foreach($busyTimes as $busyTime) {
304
305            $busyTime[0]->setTimeZone(new \DateTimeZone('UTC'));
306            $busyTime[1]->setTimeZone(new \DateTimeZone('UTC'));
307
308            $prop = Property::create(
309                'FREEBUSY',
310                $busyTime[0]->format('Ymd\\THis\\Z') . '/' . $busyTime[1]->format('Ymd\\THis\\Z')
311            );
312            $prop['FBTYPE'] = $busyTime[2];
313            $vfreebusy->add($prop);
314
315        }
316
317        return $calendar;
318
319    }
320
321}
322
Note: See TracBrowser for help on using the repository browser.