ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
class.ilICalParser.php
Go to the documentation of this file.
1<?php
2/*
3 +-----------------------------------------------------------------------------+
4 | ILIAS open source |
5 +-----------------------------------------------------------------------------+
6 | Copyright (c) 1998-2006 ILIAS open source, University of Cologne |
7 | |
8 | This program is free software; you can redistribute it and/or |
9 | modify it under the terms of the GNU General Public License |
10 | as published by the Free Software Foundation; either version 2 |
11 | of the License, or (at your option) any later version. |
12 | |
13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | GNU General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU General Public License |
19 | along with this program; if not, write to the Free Software |
20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21 +-----------------------------------------------------------------------------+
22*/
23
24include_once('./Services/Calendar/classes/iCal/class.ilICalUtils.php');
25include_once('./Services/Calendar/classes/class.ilDateTime.php');
26include_once('./Services/Calendar/classes/class.ilCalendarEntry.php');
27include_once('./Services/Calendar/classes/class.ilTimeZone.php');
28include_once('./Services/Calendar/classes/class.ilTimeZoneException.php');
29
30include_once('./Services/Calendar/classes/iCal/class.ilICalComponent.php');
31include_once('./Services/Calendar/classes/iCal/class.ilICalProperty.php');
32include_once('./Services/Calendar/classes/iCal/class.ilICalParameter.php');
33include_once('./Services/Calendar/classes/iCal/class.ilICalValue.php');
34
35include_once './Services/Calendar/exceptions/class.ilICalParserException.php';
36
46{
47 const INPUT_STRING = 1;
48 const INPUT_FILE = 2;
49
50 protected $log = null;
51
52 protected $category = null;
53
54 protected $ical = '';
55 protected $file = '';
56 protected $default_timezone = null;
57
58 protected $container = array();
59
69 public function __construct($a_ical,$a_type)
70 {
71 global $ilLog;
72
73 if($a_type == self::INPUT_STRING)
74 {
75 $this->ical = $a_ical;
76 }
77 elseif($a_type == self::INPUT_FILE)
78 {
79 $this->file = $a_ical;
80 $this->ical = file_get_contents($a_ical);
81
82 if(!strlen($this->ical))
83 {
84 throw new ilICalParserException($GLOBALS['cal_err_no_input']);
85 }
86 #$GLOBALS['ilLog']->write(__METHOD__.': Ical content: '. $this->ical);
87 }
88 $this->log = $ilLog;
89 }
90
98 public function setCategoryId($a_id)
99 {
100 include_once('./Services/Calendar/classes/class.ilCalendarCategory.php');
101 $this->category = new ilCalendarCategory($a_id);
102 }
103
110 public function parse()
111 {
112 $this->default_timezone = ilTimeZone::_getInstance();
113
114 $lines = $this->tokenize($this->ical,ilICalUtils::ICAL_EOL);
115
116 if(count(lines) == 1)
117 {
118 $lines = $this->tokenize($this->ical, ilICalUtils::ICAL_EOL_FB);
119 }
120
121 for($i = 0; $i < count($lines); $i++)
122 {
123 $line = $lines[$i];
124
125 // Check for next multilines (they start with a space)
126 $offset = 1;
127 while(isset($lines[$i + $offset]) and
128 (strpos($lines[$i + $offset],ilICalUtils::ICAL_SPACE) === 0) or
129 (strpos($lines[$i + $offset],ilICalUtils::ICAL_TAB) === 0))
130 {
131 $lines[$i + $offset] = str_replace(ilICalUtils::ICAL_EOL,'',$lines[$i + $offset]);
132 $line = $line.substr($lines[$i + $offset],1);
133 $offset++;
134 }
135 $i += ($offset - 1);
136
137 // Parse this line
138 $this->parseLine($line);
139 }
140 }
141
147 protected function getContainer()
148 {
149 return $this->container[count($this->container) - 1];
150 }
151
158 protected function setContainer($a_container)
159 {
160 $this->container = array($a_container);
161 }
162
168 protected function dropContainer()
169 {
170 return array_pop($this->container);
171 }
172
179 protected function pushContainer($a_container)
180 {
181 $this->container[] = $a_container;
182 }
183
184
190 protected function parseLine($line)
191 {
192 switch(trim($line))
193 {
194 case 'BEGIN:VCALENDAR':
195 $this->log->write(__METHOD__.': BEGIN VCALENDAR');
196 $this->setContainer(new ilICalComponent('VCALENDAR'));
197 break;
198
199 case 'END:VCALENDAR':
200 $this->log->write(__METHOD__.': END VCALENDAR');
201 break;
202
203 case 'BEGIN:VEVENT':
204 $this->log->write(__METHOD__.': BEGIN VEVENT');
205 $this->pushContainer(new ilICalComponent('VEVENT'));
206 break;
207
208 case 'END:VEVENT':
209 $this->log->write(__METHOD__.': END VEVENT');
210
211 $this->writeEvent();
212
213 $this->dropContainer();
214 break;
215
216 case 'BEGIN:VTIMEZONE':
217 $this->log->write(__METHOD__.': BEGIN VTIMEZONE');
218 $container = new ilICalComponent('VTIMEZONE');
220 break;
221
222 case 'END:VTIMEZONE':
223 $this->log->write(__METHOD__.': END VTIMEZONE');
224
225 if($tzid = $this->getContainer()->getItemsByName('TZID'))
226 {
227 $this->default_timezone = $this->getTZ($tzid[0]->getValue());
228 }
229 $this->dropContainer();
230 break;
231
232 default:
233 if(strpos(trim($line),'BEGIN') === 0)
234 {
235 $this->log->write(__METHOD__.': Do not handling line:'.$line);
236 continue;
237 }
238 if(strpos(trim($line),'X-WR-TIMEZONE') === 0)
239 {
240 list($param,$value) = $this->splitLine($line);
241 $this->default_timezone = $this->getTZ($value);
242 }
243 else
244 {
245 list($params,$values) = $this->splitLine($line);
246 $this->storeItems($params,$values);
247 }
248 break;
249 }
250
251 }
252
258 protected function storeItems($a_param_part,$a_value_part)
259 {
260 // Check for a semicolon in param part and split it.
261
262 $items = array();
263 if($splitted_param = explode(';',$a_param_part))
264 {
265 $counter = 0;
266 foreach($splitted_param as $param)
267 {
268 if(!$counter)
269 {
270 $items[$counter]['param'] = $param;
271 $items[$counter]['value'] = $a_value_part;
272 }
273 else
274 {
275 // Split by '='
276 if($splitted_param_values = explode('=',$param))
277 {
278 $items[$counter]['param'] = $splitted_param_values[0];
279 $items[$counter]['value'] = $splitted_param_values[1];
280 }
281 }
282 ++$counter;
283 }
284 }
285
286 // Split value part
287 $substituted_values = str_replace('\;','',$a_value_part);
288
289 $values = array();
290 if($splitted_values = explode(';',$substituted_values))
291 {
292 $counter = 0;
293 foreach($splitted_values as $value)
294 {
295 // Split by '='
296 if($splitted_value_values = explode('=',$value))
297 {
298 $values[$counter]['param'] = $splitted_value_values[0];
299 $values[$counter]['value'] = $splitted_value_values[1];
300 }
301 ++$counter;
302 }
303 }
304
305 // Return if there are no values
306 if(!count($items))
307 {
308 $this->log->write(__METHOD__.': Cannot parse parameter: '.$a_param_part.', value: '.$a_value_part);
309 return false;
310 }
311
312
313 $counter = 0;
314 foreach($items as $item)
315 {
316 if(!$counter)
317 {
318 // First is ical-Parameter
319 $parameter = new ilICalProperty($item['param'],$item['value']);
320
321 if(!$this->getContainer() instanceof ilICalItem)
322 {
323 continue;
324 }
325
326 $this->getContainer()->addItem($parameter);
327 $this->pushContainer($parameter);
328
329 if(count($values) > 1)
330 {
331 foreach($values as $value)
332 {
333 $value = new ilICalValue($value['param'],$value['value']);
334 $this->getContainer()->addItem($value);
335 }
336 }
337 }
338 else
339 {
340 $value = new ilICalParameter($item['param'],$item['value']);
341 $this->getContainer()->addItem($value);
342 }
343 ++$counter;
344 }
345 $this->dropContainer();
346 }
347
348
355 protected function splitLine($a_line)
356 {
357 $matches = array();
358
359 if(preg_match('/([^:]+):(.*)/',$a_line,$matches))
360 {
361 return array($matches[1],$matches[2]);
362 }
363 else
364 {
365 $this->log->write(__METHOD__.': Found invalid parameter: '.$a_line);
366 }
367
368 return array('','');
369 }
370
376 protected function tokenize($a_string,$a_tokenizer)
377 {
378 return explode($a_tokenizer,$a_string);
379 }
380
386 protected function getTZ($a_timezone)
387 {
388 $parts = explode('/',$a_timezone);
389 $tz = array_pop($parts);
390 $continent = array_pop($parts);
391
392 if(isset($continent) and $continent)
393 {
394 $timezone = $continent.'/'.$tz;
395 }
396 else
397 {
398 $timezone = $a_timezone;
399 }
400
401 try
402 {
403 if($this->default_timezone->getIdentifier() == $timezone)
404 {
406 }
407 else
408 {
409 $this->log->write(__METHOD__.': Found new timezone: '.$timezone);
410 return ilTimeZone::_getInstance(trim($timezone));
411 }
412 }
413 catch(ilTimeZoneException $e)
414 {
415 $this->log->write(__METHOD__.': Found invalid timezone: '.$timezone);
417 }
418
419 }
420
426 protected function switchTZ(ilTimeZone $timezone)
427 {
428 try
429 {
430 $timezone->switchTZ();
431 }
432 catch(ilTimeZoneException $e)
433 {
434 $this->log->write(__METHOD__.': Found invalid timezone: '.$timezone);
435 return false;
436 }
437 }
438
444 protected function restoreTZ()
445 {
446 $this->default_timezone->restoreTZ();
447 }
448
454 protected function writeEvent()
455 {
456 $entry = new ilCalendarEntry();
457
458 // Search for summary
459 foreach($this->getContainer()->getItemsByName('SUMMARY',false) as $item)
460 {
461 if(is_a($item,'ilICalProperty'))
462 {
463 $entry->setTitle($this->purgeString($item->getValue()));
464 break;
465 }
466 }
467 // Search description
468 foreach($this->getContainer()->getItemsByName('DESCRIPTION',false) as $item)
469 {
470 if(is_a($item,'ilICalProperty'))
471 {
472 $entry->setDescription($this->purgeString($item->getValue()));
473 break;
474 }
475 }
476
477 // Search location
478 foreach($this->getContainer()->getItemsByName('LOCATION',false) as $item)
479 {
480 if(is_a($item,'ilICalProperty'))
481 {
482 $entry->setLocation($this->purgeString($item->getValue()));
483 break;
484 }
485 }
486
487 foreach($this->getContainer()->getItemsByName('DTSTART') as $start)
488 {
489 $fullday = false;
490 foreach($start->getItemsByName('VALUE') as $type)
491 {
492 if($type->getValue() == 'DATE')
493 {
494 $fullday = true;
495 }
496 }
497 $start_tz = $this->default_timezone;
498 foreach($start->getItemsByName('TZID') as $param)
499 {
500 $start_tz = $this->getTZ($param->getValue());
501 }
502 if($fullday)
503 {
504 $start = new ilDate($start->getValue(),
506 }
507 else
508 {
509 $start = new ilDateTime($start->getValue(),
511 $start_tz->getIdentifier());
512 }
513 $entry->setStart($start);
514 $entry->setFullday($fullday);
515 }
516
517 foreach($this->getContainer()->getItemsByName('DTEND') as $end)
518 {
519 $fullday = false;
520 foreach($end->getItemsByName('VALUE') as $type)
521 {
522 if($type->getValue() == 'DATE')
523 {
524 $fullday = true;
525 }
526 }
527 $end_tz = $this->default_timezone;
528 foreach($end->getItemsByName('TZID') as $param)
529 {
530 $end_tz = $this->getTZ($param->getValue());
531 }
532 if($fullday)
533 {
534 $end = new ilDate($end->getValue(),
536 $end->increment(IL_CAL_DAY,-1);
537 }
538 else
539 {
540 $end = new ilDateTime($end->getValue(),
542 $end_tz->getIdentifier());
543 }
544 $entry->setEnd($end);
545 $entry->setFullday($fullday);
546 }
547 // save calendar event
548 if($this->category->getLocationType() == ilCalendarCategory::LTYPE_REMOTE)
549 {
550 $entry->setAutoGenerated(true);
551 }
552 $entry->save();
553
554 include_once('./Services/Calendar/classes/class.ilCalendarCategoryAssignments.php');
555 $ass = new ilCalendarCategoryAssignments($entry->getEntryId());
556 $ass->addAssignment($this->category->getCategoryID());
557
558
559 // Recurrences
560 foreach($this->getContainer()->getItemsByName('RRULE') as $recurrence)
561 {
562 #var_dump("<pre>",$recurrence,"</pre>");
563
564
565 include_once('./Services/Calendar/classes/class.ilCalendarRecurrence.php');
566 $rec = new ilCalendarRecurrence();
567 $rec->setEntryId($entry->getEntryId());
568
569 foreach($recurrence->getItemsByName('FREQ') as $freq)
570 {
571 switch($freq->getValue())
572 {
573 case 'DAILY':
574 case 'WEEKLY':
575 case 'MONTHLY':
576 case 'YEARLY':
577 $rec->setFrequenceType((string) $freq->getValue());
578 break;
579
580 default:
581 $this->log->write(__METHOD__.': Cannot handle recurring event of type: '.$freq->getValue());
582 break 3;
583 }
584 }
585
586 foreach($recurrence->getItemsByName('COUNT') as $value)
587 {
588 $rec->setFrequenceUntilCount((string) $value->getValue());
589 break;
590 }
591 foreach($recurrence->getItemsByName('UNTIL') as $until)
592 {
593 $rec->setFrequenceUntilDate(new ilDate($until->getValue(),IL_CAL_DATE));
594 break;
595 }
596 foreach($recurrence->getItemsByName('INTERVAL') as $value)
597 {
598 $rec->setInterval((string) $value->getValue());
599 break;
600 }
601 foreach($recurrence->getItemsByName('BYDAY') as $value)
602 {
603 $rec->setBYDAY((string) $value->getValue());
604 break;
605 }
606 foreach($recurrence->getItemsByName('BYWEEKNO') as $value)
607 {
608 $rec->setBYWEEKNO((string) $value->getValue());
609 break;
610 }
611 foreach($recurrence->getItemsByName('BYMONTH') as $value)
612 {
613 $rec->setBYMONTH((string) $value->getValue());
614 break;
615 }
616 foreach($recurrence->getItemsByName('BYMONTHDAY') as $value)
617 {
618 $rec->setBYMONTHDAY((string) $value->getValue());
619 break;
620 }
621 foreach($recurrence->getItemsByName('BYYEARDAY') as $value)
622 {
623 $rec->setBYYEARDAY((string) $value->getValue());
624 break;
625 }
626 foreach($recurrence->getItemsByName('BYSETPOS') as $value)
627 {
628 $rec->setBYSETPOS((string) $value->getValue());
629 break;
630 }
631 foreach($recurrence->getItemsByName('WKST') as $value)
632 {
633 $rec->setWeekstart((string) $value->getValue());
634 break;
635 }
636 $rec->save();
637 }
638 }
639
645 protected function purgeString($a_string)
646 {
647 $a_string = str_replace("\;",";",$a_string);
648 $a_string = str_replace("\,",",",$a_string);
649 $a_string = str_replace("\:",":",$a_string);
650 return ilUtil::stripSlashes($a_string);
651
652 }
653}
654?>
const IL_CAL_DATE
const IL_CAL_DATETIME
const IL_CAL_DAY
Stores calendar categories.
Model for a calendar entry.
@classDescription Date and time handling
Class for single dates.
Represents a ical component.
Abstract base class for all ical items (Component, Parameter and Value)
This class represents a ical parameter E.g VALUE=DATETIME.
getContainer()
get container
parseLine($line)
parse a line
storeItems($a_param_part, $a_value_part)
store items
writeEvent()
write a new event
switchTZ(ilTimeZone $timezone)
Switch timezone.
splitLine($a_line)
parse parameters
setContainer($a_container)
set container
pushContainer($a_container)
push container
parse()
Parse input.
purgeString($a_string)
purge string
__construct($a_ical, $a_type)
Constructor.
setCategoryId($a_id)
set category id
restoreTZ()
restore time
tokenize($a_string, $a_tokenizer)
tokenize string
getTZ($a_timezone)
get timezone
Represents a ical property.
Used for storage og multiple values E.g RRULE:FREQ=WEEKLY;COUNT=20;INTERVAL=2;BYDAY=TU.
Class for TimeZone exceptions.
This class offers methods for timezone handling.
static _getInstance($a_tz='')
get instance by timezone
switchTZ()
Switch timezone to given timezone.
static stripSlashes($a_str, $a_strip_html=true, $a_allow="")
strip slashes if magic qoutes is enabled
$params
Definition: example_049.php:96
$GLOBALS['PHPCAS_CLIENT']
This global variable is used by the interface class phpCAS.
Definition: CAS.php:276