3
|
1 <?php
|
|
2
|
|
3 /**
|
|
4 * Kolab calendar storage class simulating a virtual calendar listing pedning/declined invitations
|
|
5 *
|
|
6 * @author Thomas Bruederli <bruederli@kolabsys.com>
|
|
7 *
|
|
8 * Copyright (C) 2014-2015, Kolab Systems AG <contact@kolabsys.com>
|
|
9 *
|
|
10 * This program is free software: you can redistribute it and/or modify
|
|
11 * it under the terms of the GNU Affero General Public License as
|
|
12 * published by the Free Software Foundation, either version 3 of the
|
|
13 * License, or (at your option) any later version.
|
|
14 *
|
|
15 * This program is distributed in the hope that it will be useful,
|
|
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
18 * GNU Affero General Public License for more details.
|
|
19 *
|
|
20 * You should have received a copy of the GNU Affero General Public License
|
|
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
22 */
|
|
23
|
|
24 class kolab_invitation_calendar
|
|
25 {
|
|
26 public $id = '__invitation__';
|
|
27 public $ready = true;
|
|
28 public $alarms = false;
|
|
29 public $rights = 'lrsv';
|
|
30 public $editable = false;
|
|
31 public $attachments = false;
|
|
32 public $subscriptions = false;
|
|
33 public $partstats = array('unknown');
|
|
34 public $categories = array();
|
|
35 public $name = 'Invitations';
|
|
36
|
|
37
|
|
38 /**
|
|
39 * Default constructor
|
|
40 */
|
|
41 public function __construct($id, $calendar)
|
|
42 {
|
|
43 $this->cal = $calendar;
|
|
44 $this->id = $id;
|
|
45
|
|
46 switch ($this->id) {
|
|
47 case kolab_driver::INVITATIONS_CALENDAR_PENDING:
|
|
48 $this->partstats = array('NEEDS-ACTION');
|
|
49 $this->name = $this->cal->gettext('invitationspending');
|
|
50 if (!empty($_REQUEST['_quickview']))
|
|
51 $this->partstats[] = 'TENTATIVE';
|
|
52 break;
|
|
53
|
|
54 case kolab_driver::INVITATIONS_CALENDAR_DECLINED:
|
|
55 $this->partstats = array('DECLINED');
|
|
56 $this->name = $this->cal->gettext('invitationsdeclined');
|
|
57 break;
|
|
58 }
|
|
59
|
|
60 // user-specific alarms settings win
|
|
61 $prefs = $this->cal->rc->config->get('kolab_calendars', array());
|
|
62 if (isset($prefs[$this->id]['showalarms']))
|
|
63 $this->alarms = $prefs[$this->id]['showalarms'];
|
|
64 }
|
|
65
|
|
66 /**
|
|
67 * Getter for a nice and human readable name for this calendar
|
|
68 *
|
|
69 * @return string Name of this calendar
|
|
70 */
|
|
71 public function get_name()
|
|
72 {
|
|
73 return $this->name;
|
|
74 }
|
|
75
|
|
76 /**
|
|
77 * Getter for the IMAP folder owner
|
|
78 *
|
|
79 * @return string Name of the folder owner
|
|
80 */
|
|
81 public function get_owner()
|
|
82 {
|
|
83 return $this->cal->rc->get_user_name();
|
|
84 }
|
|
85
|
|
86 /**
|
|
87 *
|
|
88 */
|
|
89 public function get_title()
|
|
90 {
|
|
91 return $this->get_name();
|
|
92 }
|
|
93
|
|
94 /**
|
|
95 * Getter for the name of the namespace to which the IMAP folder belongs
|
|
96 *
|
|
97 * @return string Name of the namespace (personal, other, shared)
|
|
98 */
|
|
99 public function get_namespace()
|
|
100 {
|
|
101 return 'x-special';
|
|
102 }
|
|
103
|
|
104 /**
|
|
105 * Getter for the top-end calendar folder name (not the entire path)
|
|
106 *
|
|
107 * @return string Name of this calendar
|
|
108 */
|
|
109 public function get_foldername()
|
|
110 {
|
|
111 return $this->get_name();
|
|
112 }
|
|
113
|
|
114 /**
|
|
115 * Getter for the Cyrus mailbox identifier corresponding to this folder
|
|
116 *
|
|
117 * @return string Mailbox ID
|
|
118 */
|
|
119 public function get_mailbox_id()
|
|
120 {
|
|
121 // this is a virtual collection and has no concrete mailbox ID
|
|
122 return null;
|
|
123 }
|
|
124
|
|
125 /**
|
|
126 * Return color to display this calendar
|
|
127 */
|
|
128 public function get_color()
|
|
129 {
|
|
130 // calendar color is stored in local user prefs
|
|
131 $prefs = $this->cal->rc->config->get('kolab_calendars', array());
|
|
132
|
|
133 if (!empty($prefs[$this->id]) && !empty($prefs[$this->id]['color']))
|
|
134 return $prefs[$this->id]['color'];
|
|
135
|
|
136 return 'ffffff';
|
|
137 }
|
|
138
|
|
139 /**
|
|
140 * Compose an URL for CalDAV access to this calendar (if configured)
|
|
141 */
|
|
142 public function get_caldav_url()
|
|
143 {
|
|
144 return false;
|
|
145 }
|
|
146
|
|
147 /**
|
|
148 * Check activation status of this folder
|
|
149 *
|
|
150 * @return boolean True if enabled, false if not
|
|
151 */
|
|
152 public function is_active()
|
|
153 {
|
|
154 $prefs = $this->cal->rc->config->get('kolab_calendars', array()); // read local prefs
|
|
155 return (bool)$prefs[$this->id]['active'];
|
|
156 }
|
|
157
|
|
158 /**
|
|
159 * Update properties of this calendar folder
|
|
160 *
|
|
161 * @see calendar_driver::edit_calendar()
|
|
162 */
|
|
163 public function update(&$prop)
|
|
164 {
|
|
165 // don't change anything.
|
|
166 // let kolab_driver save props in local prefs
|
|
167 return $prop['id'];
|
|
168 }
|
|
169
|
|
170 /**
|
|
171 * Getter for a single event object
|
|
172 */
|
|
173 public function get_event($id)
|
|
174 {
|
|
175 // redirect call to kolab_driver::get_event()
|
|
176 $event = $this->cal->driver->get_event($id, calendar_driver::FILTER_WRITEABLE);
|
|
177
|
|
178 if (is_array($event)) {
|
|
179 // add pointer to original calendar folder
|
|
180 $event['_folder_id'] = $event['calendar'];
|
|
181 $event = $this->_mod_event($event);
|
|
182 }
|
|
183
|
|
184 return $event;
|
|
185 }
|
|
186
|
|
187 /**
|
|
188 * Get attachment body
|
|
189 * @see calendar_driver::get_attachment_body()
|
|
190 */
|
|
191 public function get_attachment_body($id, $event)
|
|
192 {
|
|
193 // find the actual folder this event resides in
|
|
194 if (!empty($event['_folder_id'])) {
|
|
195 $cal = $this->cal->driver->get_calendar($event['_folder_id']);
|
|
196 }
|
|
197 else {
|
|
198 $cal = null;
|
|
199 foreach (kolab_storage::list_folders('', '*', 'event', null) as $foldername) {
|
|
200 $cal = $this->_get_calendar($foldername);
|
|
201 if ($cal->ready && $cal->storage && $cal->get_event($event['id'])) {
|
|
202 break;
|
|
203 }
|
|
204 }
|
|
205 }
|
|
206
|
|
207 if ($cal && $cal->storage) {
|
|
208 return $cal->get_attachment_body($id, $event);
|
|
209 }
|
|
210
|
|
211 return false;
|
|
212 }
|
|
213
|
|
214 /**
|
|
215 * @param integer Event's new start (unix timestamp)
|
|
216 * @param integer Event's new end (unix timestamp)
|
|
217 * @param string Search query (optional)
|
|
218 * @param boolean Include virtual events (optional)
|
|
219 * @param array Additional parameters to query storage
|
|
220 * @return array A list of event records
|
|
221 */
|
|
222 public function list_events($start, $end, $search = null, $virtual = 1, $query = array())
|
|
223 {
|
|
224 // get email addresses of the current user
|
|
225 $user_emails = $this->cal->get_user_emails();
|
|
226 $subquery = array();
|
|
227 foreach ($user_emails as $email) {
|
|
228 foreach ($this->partstats as $partstat) {
|
|
229 $subquery[] = array('tags', '=', 'x-partstat:' . $email . ':' . strtolower($partstat));
|
|
230 }
|
|
231 }
|
|
232
|
|
233 // aggregate events from all calendar folders
|
|
234 $events = array();
|
|
235 foreach (kolab_storage::list_folders('', '*', 'event', null) as $foldername) {
|
|
236 $cal = $this->_get_calendar($foldername);
|
|
237 if ($cal->get_namespace() == 'other')
|
|
238 continue;
|
|
239
|
|
240 foreach ($cal->list_events($start, $end, $search, 1, $query, array(array($subquery, 'OR'))) as $event) {
|
|
241 $match = false;
|
|
242
|
|
243 // post-filter events to match out partstats
|
|
244 if (is_array($event['attendees'])) {
|
|
245 foreach ($event['attendees'] as $attendee) {
|
|
246 if (in_array($attendee['email'], $user_emails) && in_array($attendee['status'], $this->partstats)) {
|
|
247 $match = true;
|
|
248 break;
|
|
249 }
|
|
250 }
|
|
251 }
|
|
252
|
|
253 if ($match) {
|
|
254 $events[$event['id'] ?: $event['uid']] = $this->_mod_event($event);
|
|
255 }
|
|
256 }
|
|
257
|
|
258 // merge list of event categories (really?)
|
|
259 $this->categories += $cal->categories;
|
|
260 }
|
|
261
|
|
262 return $events;
|
|
263 }
|
|
264
|
|
265 /**
|
|
266 *
|
|
267 * @param integer Date range start (unix timestamp)
|
|
268 * @param integer Date range end (unix timestamp)
|
|
269 * @return integer Count
|
|
270 */
|
|
271 public function count_events($start, $end = null)
|
|
272 {
|
|
273 // get email addresses of the current user
|
|
274 $user_emails = $this->cal->get_user_emails();
|
|
275 $subquery = array();
|
|
276 foreach ($user_emails as $email) {
|
|
277 foreach ($this->partstats as $partstat) {
|
|
278 $subquery[] = array('tags', '=', 'x-partstat:' . $email . ':' . strtolower($partstat));
|
|
279 }
|
|
280 }
|
|
281
|
|
282 $filter = array(
|
|
283 array('tags','!=','x-status:cancelled'),
|
|
284 array($subquery, 'OR')
|
|
285 );
|
|
286
|
|
287 // aggregate counts from all calendar folders
|
|
288 $count = 0;
|
|
289 foreach (kolab_storage::list_folders('', '*', 'event', null) as $foldername) {
|
|
290 $cal = $this->_get_calendar($foldername);
|
|
291 if ($cal->get_namespace() == 'other')
|
|
292 continue;
|
|
293
|
|
294 $count += $cal->count_events($start, $end, $filter);
|
|
295 }
|
|
296
|
|
297 return $count;
|
|
298 }
|
|
299
|
|
300 /**
|
|
301 * Get calendar object instance (that maybe already initialized)
|
|
302 */
|
|
303 private function _get_calendar($folder_name)
|
|
304 {
|
|
305 $id = kolab_storage::folder_id($folder_name, true);
|
|
306 return $this->cal->driver->get_calendar($id);
|
|
307 }
|
|
308
|
|
309 /**
|
|
310 * Helper method to modify some event properties
|
|
311 */
|
|
312 private function _mod_event($event)
|
|
313 {
|
|
314 // set classes according to PARTSTAT
|
|
315 $event = kolab_driver::add_partstat_class($event, $this->partstats);
|
|
316
|
|
317 if (strpos($event['className'], 'fc-invitation-') !== false) {
|
|
318 $event['calendar'] = $this->id;
|
|
319 }
|
|
320
|
|
321 return $event;
|
|
322 }
|
|
323
|
|
324 /**
|
|
325 * Create a new event record
|
|
326 *
|
|
327 * @see calendar_driver::new_event()
|
|
328 *
|
|
329 * @return mixed The created record ID on success, False on error
|
|
330 */
|
|
331 public function insert_event($event)
|
|
332 {
|
|
333 return false;
|
|
334 }
|
|
335
|
|
336 /**
|
|
337 * Update a specific event record
|
|
338 *
|
|
339 * @see calendar_driver::new_event()
|
|
340 * @return boolean True on success, False on error
|
|
341 */
|
|
342 public function update_event($event, $exception_id = null)
|
|
343 {
|
|
344 // forward call to the actual storage folder
|
|
345 if ($event['_folder_id']) {
|
|
346 $cal = $this->cal->driver->get_calendar($event['_folder_id']);
|
|
347 if ($cal && $cal->ready) {
|
|
348 return $cal->update_event($event, $exception_id);
|
|
349 }
|
|
350 }
|
|
351
|
|
352 return false;
|
|
353 }
|
|
354
|
|
355 /**
|
|
356 * Delete an event record
|
|
357 *
|
|
358 * @see calendar_driver::remove_event()
|
|
359 * @return boolean True on success, False on error
|
|
360 */
|
|
361 public function delete_event($event, $force = true)
|
|
362 {
|
|
363 return false;
|
|
364 }
|
|
365
|
|
366 /**
|
|
367 * Restore deleted event record
|
|
368 *
|
|
369 * @see calendar_driver::undelete_event()
|
|
370 * @return boolean True on success, False on error
|
|
371 */
|
|
372 public function restore_event($event)
|
|
373 {
|
|
374 return false;
|
|
375 }
|
|
376 }
|