bvdputte / kirby-ical

2 stars 0 forks source link

Integrate better ics parsing library #1

Open bvdputte opened 6 years ago

bvdputte commented 6 years ago

e.g. https://github.com/markuspoerschke/iCal

bnomei commented 6 years ago

i have tried that one but its using 2009 RFC 5545 standard. so i would not recommend it wholeheartedly.

had some troubles with GMT+1 timezones being set correctly for apple and outlook to be recognized correctly. https://github.com/markuspoerschke/iCal/blob/master/examples/example4b.php

also verify seems like a good idea. https://icalendar.org/validator.html

mine was also using https://github.com/mzur/kirby-calendar-plugin

here is the main factory function collecting all events. good luck.

<?php
public function icsEvents($withAttendees = false) {
    $allEvents = array();

    date_default_timezone_set('Europe/Berlin');

    if($this->calendar()->isNotEmpty()) {
      if($calendar = calendar($this->calendar()->yaml())) {
        foreach ($calendar->getAllEvents() as $event) {

          $kennung = $event->getField('kennung');
          $ts_start = $event->getBeginTimestamp();
          $ts_ende = $event->getEndTimestamp();
          $summary = $this->title()->value();
          $desc = $this->desc()->value();
          $timeZone = new \DateTimeZone('Europe/Berlin');
          $timeZoneString = 'Europe/Berlin';
          $organizer = new \Eluceo\iCal\Property\Event\Organizer(
              'MAILTO:'.site()->kontaktemail()->value(),
              ['CN' => site()->title()->value()]
            );

          $loc = $event->getField('eventlocation');
          if(strlen($loc) == 0) {
            $loc = $this->location()->value();
          }

          // https://github.com/markuspoerschke/iCal
          // https://github.com/markuspoerschke/iCal/blob/master/src/Component/Event.php
          $vEvent = new \Eluceo\iCal\Component\Event();
          $vEvent
            ->setModified(new \DateTime(date('c', $this->modified()), $timeZone))
            ->setUrl($this->url())
            ->setDtStart(new \DateTime(date('c', $ts_start), $timeZone))
            ->setDtEnd(new \DateTime(date('c', $ts_ende), $timeZone))
            //->setNoTime(true)
            ->setLocation($loc)
            ->setUseTimezone(true)
            ->setSummary($summary)
            ->setDescription($desc)
            ->setOrganizer($organizer);

          $vEvent->setTimezoneString($timeZoneString);

          if($withAttendees) {
            // get buchungen -> attendees
            $buchungen = $this->children()
              ->filterBy('terminkennung', $kennung);
            //$attendees = new Eluceo\iCal\Property\Event\Attendees();
            foreach ($buchungen as $b) {
              // http://www.kanzaki.com/docs/ical/attendee.html
              $params = [
                'CU' => 'INDIVIDUAL', // http://www.kanzaki.com/docs/ical/cutype.html
                'CN' => '#'.str::upper($b->buchungsToken()).' '.$b->vorname()->value().' '.$b->nachname()->value(),
              ];
              // http://www.kanzaki.com/docs/ical/partstat.html
              if($b->buchungsart() == self::ART_VERBINDLICH) {
                $params['PARTSTAT'] = 'ACCEPTED';
              } 
              /*
              else if($b->buchungsart() == self::ART_RESERVIERUNG) {
                $params['PARTSTAT'] = 'TENTATIVE';
              } else if($b->buchungsart() == self::ART_NACHWEIS) {
                $params['PARTSTAT'] = 'NEEDS-ACTION';
              } else if($b->buchungsart() == self::ART_STORNIERT) {
                $params['PARTSTAT'] = 'DECLINED';
              }
              */
              $email = trim($b->email()->value());
              $vEvent->addAttendee($email, $params);
            }
          }

          $allEvents[] = $vEvent;
        }
      }
    }

    return $allEvents;
  }

complemented by a class for rendering ical and serving the file

class KirbyICS {
    public static function render($page, $options = null, $events = null) {
        $t = $page ? $page->title()->value() : '';
        $title = a::get($options, 'title', $t);
        $vCalendar = new \Eluceo\iCal\Component\Calendar($title);

        if($events && is_array($events)) {
            foreach($events as $vEvent) {
                // TODO: should check class of event object
                $vCalendar->addComponent($vEvent);
            }
        }

        return $vCalendar->render();
    }

    public static function ics($page, $options = null, $events = null) {
        $title = a::get($options, 'title', $page->title()->value());
        $filename = a::get($options, 'filename', str::lower($title));
        header('Content-Type: text/calendar; charset=utf-8');
        header('Content-Disposition: attachment; filename="'.$filename.'.ics"');
        echo self::render($page, $options, $events);
    }
}