ILIAS  Release_4_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
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 
24 include_once('./Services/Calendar/classes/iCal/class.ilICalUtils.php');
25 include_once('./Services/Calendar/classes/class.ilDateTime.php');
26 include_once('./Services/Calendar/classes/class.ilCalendarEntry.php');
27 include_once('./Services/Calendar/classes/class.ilTimeZone.php');
28 include_once('./Services/Calendar/classes/class.ilTimeZoneException.php');
29 
30 include_once('./Services/Calendar/classes/iCal/class.ilICalComponent.php');
31 include_once('./Services/Calendar/classes/iCal/class.ilICalProperty.php');
32 include_once('./Services/Calendar/classes/iCal/class.ilICalParameter.php');
33 include_once('./Services/Calendar/classes/iCal/class.ilICalValue.php');
34 
44 {
45  const INPUT_STRING = 1;
46  const INPUT_FILE = 2;
47 
48  protected $log = null;
49 
50  protected $category = null;
51 
52  protected $ical = '';
53  protected $file = '';
54  protected $default_timezone = null;
55 
56  protected $container = array();
57 
65  public function __construct($a_ical,$a_type)
66  {
67  global $ilLog;
68 
69  if($a_type == self::INPUT_STRING)
70  {
71  $this->ical = $a_ical;
72  }
73  elseif($a_type == self::INPUT_FILE)
74  {
75  $this->file = $a_ical;
76  $this->ical = file_get_contents($a_ical);
77  }
78  $this->log = $ilLog;
79  }
80 
88  public function setCategoryId($a_id)
89  {
90  include_once('./Services/Calendar/classes/class.ilCalendarCategory.php');
91  $this->category = new ilCalendarCategory($a_id);
92  }
93 
100  public function parse()
101  {
102  $this->default_timezone = ilTimeZone::_getInstance();
103 
104  $lines = $this->tokenize($this->ical,ilICalUtils::ICAL_EOL);
105  for($i = 0; $i < count($lines); $i++)
106  {
107  $line = $lines[$i];
108 
109  // Check for next multilines (they start with a space)
110  $offset = 1;
111  while(isset($lines[$i + $offset]) and
112  (strpos($lines[$i + $offset],ilICalUtils::ICAL_SPACE) === 0) or
113  (strpos($lines[$i + $offset],ilICalUtils::ICAL_TAB) === 0))
114  {
115  $lines[$i + $offset] = str_replace(ilICalUtils::ICAL_EOL,'',$lines[$i + $offset]);
116  $line = $line.substr($lines[$i + $offset],1);
117  $offset++;
118  }
119  $i += ($offset - 1);
120 
121  // Parse this line
122  $this->parseLine($line);
123  }
124  }
125 
131  protected function getContainer()
132  {
133  return $this->container[count($this->container) - 1];
134  }
135 
142  protected function setContainer($a_container)
143  {
144  $this->container = array($a_container);
145  }
146 
152  protected function dropContainer()
153  {
154  return array_pop($this->container);
155  }
156 
163  protected function pushContainer($a_container)
164  {
165  $this->container[] = $a_container;
166  }
167 
168 
174  protected function parseLine($line)
175  {
176  switch(trim($line))
177  {
178  case 'BEGIN:VCALENDAR':
179  $this->log->write(__METHOD__.': BEGIN VCALENDAR');
180  $this->setContainer(new ilICalComponent('VCALENDAR'));
181  break;
182 
183  case 'END:VCALENDAR':
184  $this->log->write(__METHOD__.': END VCALENDAR');
185  break;
186 
187  case 'BEGIN:VEVENT':
188  $this->log->write(__METHOD__.': BEGIN VEVENT');
189  $this->pushContainer(new ilICalComponent('VEVENT'));
190  break;
191 
192  case 'END:VEVENT':
193  $this->log->write(__METHOD__.': END VEVENT');
194 
195  $this->writeEvent();
196 
197  $this->dropContainer();
198  break;
199 
200  case 'BEGIN:VTIMEZONE':
201  $this->log->write(__METHOD__.': BEGIN VTIMEZONE');
202  $container = new ilICalComponent('VTIMEZONE');
203  $this->pushContainer($container);
204  break;
205 
206  case 'END:VTIMEZONE':
207  $this->log->write(__METHOD__.': END VTIMEZONE');
208 
209  if($tzid = $this->getContainer()->getItemsByName('TZID'))
210  {
211  $this->default_timezone = $this->getTZ($tzid[0]->getValue());
212  }
213  $this->dropContainer();
214  break;
215 
216  default:
217  if(strpos(trim($line),'BEGIN') === 0)
218  {
219  $this->log->write(__METHOD__.': Do not handling line:'.$line);
220  continue;
221  }
222  list($params,$values) = $this->splitLine($line);
223  $this->storeItems($params,$values);
224  break;
225  }
226 
227  }
228 
234  protected function storeItems($a_param_part,$a_value_part)
235  {
236  // Check for a semicolon in param part and split it.
237 
238  $items = array();
239  if($splitted_param = explode(';',$a_param_part))
240  {
241  $counter = 0;
242  foreach($splitted_param as $param)
243  {
244  if(!$counter)
245  {
246  $items[$counter]['param'] = $param;
247  $items[$counter]['value'] = $a_value_part;
248  }
249  else
250  {
251  // Split by '='
252  if($splitted_param_values = explode('=',$param))
253  {
254  $items[$counter]['param'] = $splitted_param_values[0];
255  $items[$counter]['value'] = $splitted_param_values[1];
256  }
257  }
258  ++$counter;
259  }
260  }
261 
262  // Split value part
263  $substituted_values = str_replace('\;','',$a_value_part);
264 
265  $values = array();
266  if($splitted_values = explode(';',$substituted_values))
267  {
268  $counter = 0;
269  foreach($splitted_values as $value)
270  {
271  // Split by '='
272  if($splitted_value_values = explode('=',$value))
273  {
274  $values[$counter]['param'] = $splitted_value_values[0];
275  $values[$counter]['value'] = $splitted_value_values[1];
276  }
277  ++$counter;
278  }
279  }
280 
281  // Return if there are no values
282  if(!count($items))
283  {
284  $this->log->write(__METHOD__.': Cannot parse parameter: '.$a_param_part.', value: '.$a_value_part);
285  return false;
286  }
287 
288 
289  $counter = 0;
290  foreach($items as $item)
291  {
292  if(!$counter)
293  {
294  // First is ical-Parameter
295  $parameter = new ilICalProperty($item['param'],$item['value']);
296  $this->getContainer()->addItem($parameter);
297  $this->pushContainer($parameter);
298 
299  if(count($values) > 1)
300  {
301  foreach($values as $value)
302  {
303  $value = new ilICalValue($value['param'],$value['value']);
304  $this->getContainer()->addItem($value);
305  }
306  }
307  }
308  else
309  {
310  $value = new ilICalParameter($item['param'],$item['value']);
311  $this->getContainer()->addItem($value);
312  }
313  ++$counter;
314  }
315  $this->dropContainer();
316  }
317 
318 
325  protected function splitLine($a_line)
326  {
327  $matches = array();
328 
329  if(preg_match('/([^:]+):(.*)/',$a_line,$matches))
330  {
331  return array($matches[1],$matches[2]);
332  }
333  else
334  {
335  $this->log->write(__METHOD__.': Found invalid parameter: '.$a_line);
336  }
337 
338  return array('','');
339  }
340 
346  protected function tokenize($a_string,$a_tokenizer)
347  {
348  return explode($a_tokenizer,$a_string);
349  }
350 
356  protected function getTZ($a_timezone)
357  {
358  $parts = explode('/',$a_timezone);
359  $tz = array_pop($parts);
360  $continent = array_pop($parts);
361 
362  if(isset($continent) and $continent)
363  {
364  $timezone = $continent.'/'.$tz;
365  }
366  else
367  {
368  $timezone = $a_timezone;
369  }
370 
371  try
372  {
373  if($this->default_timezone->getIdentifier() == $timezone)
374  {
376  }
377  else
378  {
379  $this->log->write(__METHOD__.': Found new timezone: '.$timezone);
380  return ilTimeZone::_getInstance($timezone);
381  }
382  }
383  catch(ilTimeZoneException $e)
384  {
385  $this->log->write(__METHOD__.': Found invalid timezone: '.$timezone);
387  }
388 
389  }
390 
396  protected function switchTZ(ilTimeZone $timezone)
397  {
398  try
399  {
400  $timezone->switchTZ();
401  }
402  catch(ilTimeZoneException $e)
403  {
404  $this->log->write(__METHOD__.': Found invalid timezone: '.$timezone);
405  return false;
406  }
407  }
408 
414  protected function restoreTZ()
415  {
416  $this->default_timezone->restoreTZ();
417  }
418 
424  protected function writeEvent()
425  {
426  $entry = new ilCalendarEntry();
427 
428  // Search for summary
429  foreach($this->getContainer()->getItemsByName('SUMMARY',false) as $item)
430  {
431  if(is_a($item,'ilICalProperty'))
432  {
433  $entry->setTitle($this->purgeString($item->getValue()));
434  break;
435  }
436  }
437  // Search description
438  foreach($this->getContainer()->getItemsByName('DESCRIPTION',false) as $item)
439  {
440  if(is_a($item,'ilICalProperty'))
441  {
442  $entry->setDescription($this->purgeString($item->getValue()));
443  break;
444  }
445  }
446 
447  // Search location
448  foreach($this->getContainer()->getItemsByName('LOCATION',false) as $item)
449  {
450  if(is_a($item,'ilICalProperty'))
451  {
452  $entry->setLocation($this->purgeString($item->getValue()));
453  break;
454  }
455  }
456 
457  foreach($this->getContainer()->getItemsByName('DTSTART') as $start)
458  {
459  $fullday = false;
460  foreach($start->getItemsByName('VALUE') as $type)
461  {
462  if($type->getValue() == 'DATE')
463  {
464  $fullday = true;
465  }
466  }
467  $start_tz = $this->default_timezone;
468  foreach($start->getItemsByName('TZID') as $param)
469  {
470  $start_tz = $this->getTZ($param->getValue());
471  }
472  if($fullday)
473  {
474  $start = new ilDate($start->getValue(),
475  IL_CAL_DATE);
476  }
477  else
478  {
479  $start = new ilDateTime($start->getValue(),
481  $start_tz->getIdentifier());
482  }
483  $entry->setStart($start);
484  $entry->setFullday($fullday);
485  }
486 
487  foreach($this->getContainer()->getItemsByName('DTEND') as $end)
488  {
489  $fullday = false;
490  foreach($end->getItemsByName('VALUE') as $type)
491  {
492  if($type->getValue() == 'DATE')
493  {
494  $fullday = true;
495  }
496  }
497  $end_tz = $this->default_timezone;
498  foreach($end->getItemsByName('TZID') as $param)
499  {
500  $end_tz = $this->getTZ($param->getValue());
501  }
502  if($fullday)
503  {
504  $end = new ilDate($end->getValue(),
505  IL_CAL_DATE);
506  }
507  else
508  {
509  $end = new ilDateTime($end->getValue(),
511  $end_tz->getIdentifier());
512  }
513  $entry->setEnd($end);
514  $entry->setFullday($fullday);
515  }
516  // save calendar event
517  $entry->save();
518 
519  include_once('./Services/Calendar/classes/class.ilCalendarCategoryAssignments.php');
520  $ass = new ilCalendarCategoryAssignments($entry->getEntryId());
521  $ass->addAssignment($this->category->getCategoryID());
522 
523 
524  // Recurrences
525  foreach($this->getContainer()->getItemsByName('RRULE') as $recurrence)
526  {
527  #var_dump("<pre>",$recurrence,"</pre>");
528 
529 
530  include_once('./Services/Calendar/classes/class.ilCalendarRecurrence.php');
531  $rec = new ilCalendarRecurrence();
532  $rec->setEntryId($entry->getEntryId());
533 
534  foreach($recurrence->getItemsByName('FREQ') as $freq)
535  {
536  switch($freq->getValue())
537  {
538  case 'DAILY':
539  case 'WEEKLY':
540  case 'MONTHLY':
541  case 'YEARLY':
542  $rec->setFrequenceType($freq->getValue());
543  break;
544 
545  default:
546  $this->log->write(__METHOD__.': Cannot handle recurring event of type: '.$freq->getValue());
547  break 3;
548  }
549  }
550 
551  foreach($recurrence->getItemsByName('COUNT') as $value)
552  {
553  $rec->setFrequenceUntilCount($value->getValue());
554  break;
555  }
556  foreach($recurrence->getItemsByName('UNTIL') as $until)
557  {
558  $rec->setFrequenceUntilDate(new ilDate($until->getValue(),IL_CAL_DATE));
559  break;
560  }
561  foreach($recurrence->getItemsByName('INTERVAL') as $value)
562  {
563  $rec->setInterval($value->getValue());
564  break;
565  }
566  foreach($recurrence->getItemsByName('BYDAY') as $value)
567  {
568  $rec->setBYDAY($value->getValue());
569  break;
570  }
571  foreach($recurrence->getItemsByName('BYWEEKNO') as $value)
572  {
573  $rec->setBYWEEKNO($value->getValue());
574  break;
575  }
576  foreach($recurrence->getItemsByName('BYMONTH') as $value)
577  {
578  $rec->setBYMONTH($value->getValue());
579  break;
580  }
581  foreach($recurrence->getItemsByName('BYMONTHDAY') as $value)
582  {
583  $rec->setBYMONTHDAY($value->getValue());
584  break;
585  }
586  foreach($recurrence->getItemsByName('BYYEARDAY') as $value)
587  {
588  $rec->setBYYEARDAY($value->getValue());
589  break;
590  }
591  foreach($recurrence->getItemsByName('BYSETPOS') as $value)
592  {
593  $rec->setBYSETPOS($value->getValue());
594  break;
595  }
596  foreach($recurrence->getItemsByName('WKST') as $value)
597  {
598  $rec->setWeekstart($value->getValue());
599  break;
600  }
601  $rec->save();
602  }
603  }
604 
610  protected function purgeString($a_string)
611  {
612  $a_string = str_replace("\;",";",$a_string);
613  $a_string = str_replace("\,",",",$a_string);
614  $a_string = str_replace("\:",":",$a_string);
615  return ilUtil::stripSlashes($a_string);
616 
617  }
618 }
619 ?>