]> git.mxchange.org Git - friendica-addons.git/blob - dav/SabreDAV/lib/Sabre/VObject/FreeBusyGenerator.php
1c96a64a004b6a7055c0568f80903c122de6d9dd
[friendica-addons.git] / dav / SabreDAV / lib / Sabre / VObject / FreeBusyGenerator.php
1 <?php
2
3 /**
4  * This class helps with generating FREEBUSY reports based on existing sets of
5  * objects.
6  *
7  * It only looks at VEVENT and VFREEBUSY objects from the sourcedata, and
8  * generates a single VFREEBUSY object.
9  *
10  * VFREEBUSY components are described in RFC5545, The rules for what should
11  * go in a single freebusy report is taken from RFC4791, section 7.10.
12  *
13  * @package Sabre
14  * @subpackage VObject
15  * @copyright Copyright (C) 2007-2012 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  */
19 class Sabre_VObject_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 Sabre_VObject_Component
46      */
47     protected $baseObject;
48
49     /**
50      * Sets the VCALENDAR object.
51      *
52      * If this is set, it will not be generated for you. You are responsible
53      * for setting things like the METHOD, CALSCALE, VERSION, etc..
54      *
55      * The VFREEBUSY object will be automatically added though.
56      *
57      * @param Sabre_VObject_Component $vcalendar
58      * @return void
59      */
60     public function setBaseObject(Sabre_VObject_Component $vcalendar) {
61
62         $this->baseObject = $vcalendar;
63
64     }
65
66     /**
67      * Sets the input objects
68      *
69      * Every object must either be a string or a Sabre_VObject_Component.
70      *
71      * @param array $objects
72      * @return void
73      */
74     public function setObjects(array $objects) {
75
76         $this->objects = array();
77         foreach($objects as $object) {
78
79             if (is_string($object)) {
80                 $this->objects[] = Sabre_VObject_Reader::read($object);
81             } elseif ($object instanceof Sabre_VObject_Component) {
82                 $this->objects[] = $object;
83             } else {
84                 throw new InvalidArgumentException('You can only pass strings or Sabre_VObject_Component arguments to setObjects');
85             }
86
87         }
88
89     }
90
91     /**
92      * Sets the time range
93      *
94      * Any freebusy object falling outside of this time range will be ignored.
95      *
96      * @param DateTime $start
97      * @param DateTime $end
98      * @return void
99      */
100     public function setTimeRange(DateTime $start = null, DateTime $end = null) {
101
102         $this->start = $start;
103         $this->end = $end;
104
105     }
106
107     /**
108      * Parses the input data and returns a correct VFREEBUSY object, wrapped in
109      * a VCALENDAR.
110      *
111      * @return Sabre_VObject_Component
112      */
113     public function getResult() {
114
115         $busyTimes = array();
116
117         foreach($this->objects as $object) {
118
119             foreach($object->getBaseComponents() as $component) {
120
121                 switch($component->name) {
122
123                     case 'VEVENT' :
124
125                         $FBTYPE = 'BUSY';
126                         if (isset($component->TRANSP) && (strtoupper($component->TRANSP) === 'TRANSPARENT')) {
127                             break;
128                         }
129                         if (isset($component->STATUS)) {
130                             $status = strtoupper($component->STATUS);
131                             if ($status==='CANCELLED') {
132                                 break;
133                             }
134                             if ($status==='TENTATIVE') {
135                                 $FBTYPE = 'BUSY-TENTATIVE';
136                             }
137                         }
138
139                         $times = array();
140
141                         if ($component->RRULE) {
142
143                             $iterator = new Sabre_VObject_RecurrenceIterator($object, (string)$component->uid);
144                             if ($this->start) {
145                                 $iterator->fastForward($this->start);
146                             }
147
148                             $maxRecurrences = 200;
149
150                             while($iterator->valid() && --$maxRecurrences) {
151
152                                 $startTime = $iterator->getDTStart();
153                                 if ($this->end && $startTime > $this->end) {
154                                     break;
155                                 }
156                                 $times[] = array(
157                                     $iterator->getDTStart(),
158                                     $iterator->getDTEnd(),
159                                 );
160
161                                 $iterator->next();
162
163                             }
164
165                         } else {
166
167                             $startTime = $component->DTSTART->getDateTime();
168                             if ($this->end && $startTime > $this->end) {
169                                 break;
170                             }
171                             $endTime = null;
172                             if (isset($component->DTEND)) {
173                                 $endTime = $component->DTEND->getDateTime();
174                             } elseif (isset($component->DURATION)) {
175                                 $duration = Sabre_VObject_DateTimeParser::parseDuration((string)$component->DURATION);
176                                 $endTime = clone $startTime;
177                                 $endTime->add($duration);
178                             } elseif ($component->DTSTART->getDateType() === Sabre_VObject_Property_DateTime::DATE) {
179                                 $endTime = clone $startTime;
180                                 $endTime->modify('+1 day');
181                             } else {
182                                 // The event had no duration (0 seconds)
183                                 break;
184                             }
185
186                             $times[] = array($startTime, $endTime);
187
188                         }
189
190                         foreach($times as $time) {
191
192                             if ($this->end && $time[0] > $this->end) break;
193                             if ($this->start && $time[1] < $this->start) break;
194
195                             $busyTimes[] = array(
196                                 $time[0],
197                                 $time[1],
198                                 $FBTYPE,
199                             );
200                         }
201                         break;
202
203                     case 'VFREEBUSY' :
204                         foreach($component->FREEBUSY as $freebusy) {
205
206                             $fbType = isset($freebusy['FBTYPE'])?strtoupper($freebusy['FBTYPE']):'BUSY';
207
208                             // Skipping intervals marked as 'free'
209                             if ($fbType==='FREE')
210                                 continue;
211
212                             $values = explode(',', $freebusy);
213                             foreach($values as $value) {
214                                 list($startTime, $endTime) = explode('/', $value);
215                                 $startTime = Sabre_VObject_DateTimeParser::parseDateTime($startTime);
216
217                                 if (substr($endTime,0,1)==='P' || substr($endTime,0,2)==='-P') {
218                                     $duration = Sabre_VObject_DateTimeParser::parseDuration($endTime);
219                                     $endTime = clone $startTime;
220                                     $endTime->add($duration);
221                                 } else {
222                                     $endTime = Sabre_VObject_DateTimeParser::parseDateTime($endTime);
223                                 }
224
225                                 if($this->start && $this->start > $endTime) continue;
226                                 if($this->end && $this->end < $startTime) continue;
227                                 $busyTimes[] = array(
228                                     $startTime,
229                                     $endTime,
230                                     $fbType
231                                 );
232
233                             }
234
235
236                         }
237                         break;
238
239
240
241                 }
242
243
244             }
245
246         }
247
248         if ($this->baseObject) {
249             $calendar = $this->baseObject;
250         } else {
251             $calendar = new Sabre_VObject_Component('VCALENDAR');
252             $calendar->version = '2.0';
253             if (Sabre_DAV_Server::$exposeVersion) {
254                 $calendar->prodid = '-//SabreDAV//Sabre VObject ' . Sabre_VObject_Version::VERSION . '//EN';
255             } else {
256                 $calendar->prodid = '-//SabreDAV//Sabre VObject//EN';
257             }
258             $calendar->calscale = 'GREGORIAN';
259         }
260
261         $vfreebusy = new Sabre_VObject_Component('VFREEBUSY');
262         $calendar->add($vfreebusy);
263
264         if ($this->start) {
265             $dtstart = new Sabre_VObject_Property_DateTime('DTSTART');
266             $dtstart->setDateTime($this->start,Sabre_VObject_Property_DateTime::UTC);
267             $vfreebusy->add($dtstart);
268         }
269         if ($this->end) {
270             $dtend = new Sabre_VObject_Property_DateTime('DTEND');
271             $dtend->setDateTime($this->start,Sabre_VObject_Property_DateTime::UTC);
272             $vfreebusy->add($dtend);
273         }
274         $dtstamp = new Sabre_VObject_Property_DateTime('DTSTAMP');
275         $dtstamp->setDateTime(new DateTime('now'), Sabre_VObject_Property_DateTime::UTC);
276         $vfreebusy->add($dtstamp);
277
278         foreach($busyTimes as $busyTime) {
279
280             $busyTime[0]->setTimeZone(new DateTimeZone('UTC'));
281             $busyTime[1]->setTimeZone(new DateTimeZone('UTC'));
282
283             $prop = new Sabre_VObject_Property(
284                 'FREEBUSY',
285                 $busyTime[0]->format('Ymd\\THis\\Z') . '/' . $busyTime[1]->format('Ymd\\THis\\Z')
286             );
287             $prop['FBTYPE'] = $busyTime[2];
288             $vfreebusy->add($prop);
289
290         }
291
292         return $calendar;
293
294     }
295
296 }
297