Jak mogę używać PHP do dynamicznego publikowania pliku ical do odczytu przez Kalendarz Google?

107

Każde wyszukiwanie w Google w PHP ical wywołuje po prostu phpicalendar i jak analizować lub czytać pliki IN ical. Chcę tylko napisać plik PHP, który pobiera zdarzenia z mojej bazy danych i zapisuje je w formacie ical.

Mój problem polega na tym, że nie mogę znaleźć nigdzie, aby odpowiedzieć na dwa pytania:

  1. Jaki jest dokładny format ical, w tym nagłówki, format pliku, stopki itp.? Innymi słowy, co dokładnie musi mieć plik, aby został poprawnie odczytany przez Kalendarz Google itp.?
  2. Jeśli zbuduję ten plik z rozszerzeniem .php, jak opublikuję go jako ical? Czy muszę pisać do nowego pliku .ics? A może Kalendarz Google itp. Odczyta plik .php tak samo, o ile zawartość będzie w odpowiednim formacie? (Podobnie jak plik style.css.php zostanie odczytany jako plik CSS, jeśli zawartość jest w rzeczywistości CSS itp.)

Każda pomoc, którą wszyscy możecie mi dać lub wskazać, będzie bardzo mile widziana !!!

rhodesjason
źródło

Odpowiedzi:

129

Powinno to być bardzo proste, jeśli Kalendarz Google nie wymaga *.ics-rozszerzenia (co będzie wymagało przepisania adresu URL na serwerze).

$ical = "BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//hacksw/handcal//NONSGML v1.0//EN
BEGIN:VEVENT
UID:" . md5(uniqid(mt_rand(), true)) . "@yourhost.test
DTSTAMP:" . gmdate('Ymd').'T'. gmdate('His') . "Z
DTSTART:19970714T170000Z
DTEND:19970715T035959Z
SUMMARY:Bastille Day Party
END:VEVENT
END:VCALENDAR";

//set correct content-type-header
header('Content-type: text/calendar; charset=utf-8');
header('Content-Disposition: inline; filename=calendar.ics');
echo $ical;
exit;

To w zasadzie wszystko, czego potrzebujesz, aby klient pomyślał, że obsługujesz plik iCalendar, mimo że mogą wystąpić pewne problemy dotyczące pamięci podręcznej, kodowania tekstu i tak dalej. Ale możesz zacząć eksperymentować z tym prostym kodem.

Stefan Gehrig
źródło
1
Dzięki. Myślę, że te nagłówki są tym, czego mi brakowało. Zakładam, że istnieje kilka ostatnich kroków w przygotowaniu tego Kalendarza Google, ponieważ gdy próbuję przesłać ten plik do Kalendarza Google za pośrednictwem adresu URL, wyświetla się komunikat „Importowanie kalendarza z adresu URL ...”, ale zawiesza się na zawsze. Może to inne pytanie do opublikowania?
rhodesjason
3
Dokładnie. Zaktualizowałem powyższy przykład - dodałem również właściwość DTSTAMP, która poinformuje klienta, kiedy zdarzenia zostały zaktualizowane.
Stefan Gehrig,
1
Okay Gehrig, jesteś geniuszem. To się udało. Dzięki. (O ile wiem, Kalendarz Google również aktualizuje się prawie natychmiast.)
rhodesjason,
3
Jeśli się nie mylę. Programy używają identyfikatora UID, aby sprawdzić, czy zdarzenie zostało usunięte. Jeśli skrypt php zawsze generuje inny UID (-> mt_rand), programy zawsze będą myśleć, że cała zawartość się zmieniła. Wszystko zniknęło i wszystko jest nowe. Osobiście trzymałbym się tego samego UID, jeśli zdarzenie jest takie samo w bazie danych i po prostu użyłbym recordID (i niektórych informacji o hoście). DTSTAMP ma pokazać, że coś się zmieniło. To powinno wystarczyć.
Seirddriezel
3
Kalendarz Google WYMAGA rozszerzenia * .ics. Jeśli używasz .htaccess, możesz to zrobić, dodając RewriteEngine on RewriteRule ^calendar.ics$ my_php_script.php [QSA]
Fanky
19

Notatka z osobistych doświadczeń oprócz odpowiedzi Stefana Gehriga i odpowiedzi Dave'a None'a (i odpowiedzi mmmshuddup):

Miałem problemy z walidacją przy użyciu zarówno \ n, jak i PHP_EOL, kiedy użyłem walidatora ICS pod adresem http://severinghaus.org/projects/icv/

Dowiedziałem się, że muszę użyć \ r \ n, aby uzyskać poprawność, więc to było moje rozwiązanie:

function dateToCal($timestamp) {
  return date('Ymd\Tgis\Z', $timestamp);
}

function escapeString($string) {
  return preg_replace('/([\,;])/','\\\$1', $string);
}    

    $eol = "\r\n";
    $load = "BEGIN:VCALENDAR" . $eol .
    "VERSION:2.0" . $eol .
    "PRODID:-//project/author//NONSGML v1.0//EN" . $eol .
    "CALSCALE:GREGORIAN" . $eol .
    "BEGIN:VEVENT" . $eol .
    "DTEND:" . dateToCal($end) . $eol .
    "UID:" . $id . $eol .
    "DTSTAMP:" . dateToCal(time()) . $eol .
    "DESCRIPTION:" . htmlspecialchars($title) . $eol .
    "URL;VALUE=URI:" . htmlspecialchars($url) . $eol .
    "SUMMARY:" . htmlspecialchars($description) . $eol .
    "DTSTART:" . dateToCal($start) . $eol .
    "END:VEVENT" . $eol .
    "END:VCALENDAR";

    $filename="Event-".$id;

    // Set the headers
    header('Content-type: text/calendar; charset=utf-8');
    header('Content-Disposition: attachment; filename=' . $filename);

    // Dump load
    echo $load;

To zatrzymało moje błędy analizy i sprawiło, że moje pliki ICS zostały poprawnie zweryfikowane.

Kane Ford
źródło
Informacje zawarte w nagłówku są ważną informacją dla każdego, kto patrzy w przyszłość. W większości przypadków większość aplikacji i programów nie martwi się o przerwy w pracy NewLine. Wydaje się, że tylko walidatorzy. Ale najważniejsza jest część nagłówkowa. Przez chwilę próbowaliśmy bez niego i mieliśmy wiele problemów.
jfreak53
1
Do czego służy escapeString? Założyłem, że powinno to uciec od rzeczy, ale wydaje się, htmlspecialcharsże zamiast tego używasz tego.
Luc
1
Szybka poprawka: data ('Ymd \ THis \ Z', $ timestamp). Powinien być literą H zamiast g.
Pedro Góes
6

Istnieje doskonały pakiet eluceo / ical , który umożliwia łatwe tworzenie plików ics.

Oto przykład użycia z dokumentów:

// 1. Create new calendar
$vCalendar = new \Eluceo\iCal\Component\Calendar('www.example.com');

// 2. Create an event
$vEvent = new \Eluceo\iCal\Component\Event();
$vEvent->setDtStart(new \DateTime('2012-12-24'));
$vEvent->setDtEnd(new \DateTime('2012-12-24'));
$vEvent->setNoTime(true);
$vEvent->setSummary('Christmas');

// Adding Timezone (optional)
$vEvent->setUseTimezone(true);

// 3. Add event to calendar
$vCalendar->addComponent($vEvent);

// 4. Set headers
header('Content-Type: text/calendar; charset=utf-8');
header('Content-Disposition: attachment; filename="cal.ics"');

// 5. Output
echo $vCalendar->render();
Ivan Yarych
źródło
4

http://www.kanzaki.com/docs/ical/ ma nieco bardziej czytelną wersję starszej specyfikacji. Pomaga jako punkt wyjścia - wiele rzeczy pozostaje niezmienionych.

Również na mojej stronie , mam

  1. Niektóre listy przydatnych zasobów (patrz pasek boczny na dole po prawej)
    • ical Spec RFC 5545
    • ical Zasoby testowe
  2. Kilka notatek nagranych podczas mojej podróży w .icsciągu ostatnich kilku lat. W szczególności przydatna może być ta „ściągawka” dotycząca powtarzających się wydarzeń .

.ics obszary wymagające ostrożnej obsługi:

  • imprezy „całodzienne”
  • rodzaje dat (strefa czasowa, UTC lub lokalna „zmienna”) - nie należy rozumieć rozróżnienia
  • interoperacyjność reguł powtarzania
anmari
źródło
2
  1. Dokładny format: http://www.ietf.org/rfc/rfc2445.txt
  2. Zgodnie ze specyfikacją musi kończyć się na .ics

Edycja: właściwie nie jestem pewien - wiersz 6186 podaje przykład w formacie nazewnictwa .ics, ale stwierdza również, że można użyć parametrów adresu URL. Myślę, że to nie ma znaczenia, o ile typ MIME jest poprawny.

Edycja: przykład z wikipedii: http://en.wikipedia.org/wiki/ICalendar

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//hacksw/handcal//NONSGML v1.0//EN
BEGIN:VEVENT
DTSTART:19970714T170000Z
DTEND:19970715T035959Z
SUMMARY:Bastille Day Party
END:VEVENT
END:VCALENDAR

Typ MIME jest skonfigurowany na serwerze.

lod3n
źródło
1
Wielokrotnie próbowałem przeczytać tę specyfikację, ale nie mogę z niej wyobrazić sobie głowy ani ogonów, jeśli chodzi o wygląd pliku ical. Czy możesz przynajmniej wskazać mi kilka wierszy, w których zaczyna się właściwie mówić o tym, co powinien zawierać plik .ics, aż do nagłówka, gdzie umieścić typ MIME itp.?
rhodesjason
2

Upewnij się, że sformatowałeś ciąg w ten sposób, inaczej nie zadziała

 $content = "BEGIN:VCALENDAR\n".
            "VERSION:2.0\n".
            "PRODID:-//hacksw/handcal//NONSGML v1.0//EN\n".
            "BEGIN:VEVENT\n".
            "UID:".uniqid()."\n".
            "DTSTAMP:".$time."\n".
            "DTSTART:".$time."\n".
            "DTEND:".$time."\n".
            "SUMMARY:".$summary."\n".
            "END:VEVENT\n".
            "END:VCALENDAR";
Dave None
źródło
1
lepiej jest używać PHP_EOLzamiast "\n".
Tak, Barry,
4
PHP_EOL jest specyficzne dla środowiska dla linii końcowych, więc w oknach wyświetli się, \r\nwięc miej to na uwadze!
Chris,