Bagaimana saya bisa menggunakan PHP untuk mempublikasikan file IC secara dinamis untuk dibaca oleh Google Kalender?

106

Pencarian Google apa pun di PHP ical hanya menampilkan phpicalendar dan cara mengurai atau membaca file IN ical. Saya hanya ingin menulis file PHP yang menarik event dari database saya dan menuliskannya dalam format ical.

Masalah saya adalah saya tidak dapat menemukan tempat yang akan menjawab dua pertanyaan:

  1. Apa format ical pastinya , termasuk header, format file, footer, dll.? Dengan kata lain, apa sebenarnya yang harus dimiliki file tersebut agar dapat dibaca dengan benar oleh Google Kalender, dll.?
  2. Jika saya membuat file ini menggunakan ekstensi .php, bagaimana cara menerbitkannya sebagai ical? Apakah saya harus menulis ke file .ics baru? Atau akankah Google Kalender dll membaca file .php sebagai ical selama isinya dalam format yang benar? (Sama seperti file style.css.php akan dibaca sebagai file CSS jika isinya sebenarnya CSS, dll.)

Bantuan apa pun yang dapat Anda berikan atau tunjukkan kepada saya akan sangat dihargai !!!

rhodesjason
sumber

Jawaban:

128

Ini seharusnya sangat sederhana jika Kalender Google tidak memerlukan *.ics-ekstensi (yang akan memerlukan beberapa penulisan ulang URL di server).

$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;

Pada dasarnya itu semua yang Anda butuhkan untuk membuat klien berpikir bahwa Anda menyajikan file iCalendar, meskipun mungkin ada beberapa masalah terkait caching, pengkodean teks, dan sebagainya. Tetapi Anda dapat mulai bereksperimen dengan kode sederhana ini.

Stefan Gehrig
sumber
1
Terima kasih. Saya pikir tajuk itu adalah apa yang saya lewatkan. Saya berasumsi bahwa ada beberapa langkah terakhir dalam membuat Kalender Google ini siap, seperti ketika saya mencoba memasukkan file ini ke Google Kalender melalui URL, dikatakan "Mengimpor kalender dari url ..." tetapi berhenti selamanya. Mungkin itu pertanyaan lain untuk dikirim?
rhodesjason
3
Persis. Saya memperbarui contoh di atas - dan saya juga menambahkan properti DTSTAMP yang akan memberi tahu klien ketika acara telah diperbarui.
Stefan Gehrig
1
Oke Gehrig, Anda jenius. Itu berhasil. Terima kasih. (Sejauh yang saya tahu, Google Kalender memperbarui hampir seketika juga.)
rhodesjason
3
Jika aku tidak salah. Program menggunakan UID untuk melihat apakah suatu acara dihapus. Jika skrip-php selalu menghasilkan UID lain (-> mt_rand), program akan selalu menganggap seluruh konten telah berubah. Semuanya lenyap dan semuanya baru. Secara pribadi saya akan tetap menggunakan UID yang sama jika acara tersebut sama dalam database dan hanya menggunakan recordID (dan beberapa informasi host). DTSTAMP ada untuk menunjukkan bahwa ada sesuatu yang berubah. Itu sudah cukup.
Seirddriezel
3
Kalender Google TIDAK memerlukan ekstensi * .ics. Jika Anda menggunakan .htaccess, Anda dapat membuatnya dengan menambahkan RewriteEngine on RewriteRule ^calendar.ics$ my_php_script.php [QSA]
Fanky
19

Catatan pengalaman pribadi selain jawaban Stefan Gehrig dan jawaban Dave None (dan balasan mmmshuddup):

Saya mengalami masalah validasi menggunakan \ n dan PHP_EOL ketika saya menggunakan validator ICS di http://severinghaus.org/projects/icv/

Saya belajar bahwa saya harus menggunakan \ r \ n untuk memvalidasi dengan benar, jadi inilah solusi saya:

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;

Itu menghentikan kesalahan parse saya dan membuat file ICS saya divalidasi dengan benar.

Kane Ford
sumber
Informasi header adalah bagian penting FYI bagi siapa pun yang melihat di masa mendatang. Sebagian besar aplikasi dan program tidak khawatir tentang jeda NewLine. Sepertinya hanya validator yang melakukannya. Tapi yang paling penting adalah bagian header. Kami mencoba beberapa saat tanpa itu dan mengalami banyak masalah.
jfreak53
1
Untuk apa escapeString? Saya berasumsi itu harus menghindari satu atau dua hal tetapi Anda tampaknya menggunakannya htmlspecialcharsuntuk itu.
Luc
1
Perbaikan cepat: tanggal ('Ymd \ THis \ Z', $ timestamp). Harus menjadi H, bukan g.
Pedro Góes
6

Ada paket eluceo / ical yang sangat baik yang memungkinkan Anda membuat file ics dengan mudah.

Berikut adalah contoh penggunaan dari dokumen:

// 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
sumber
4

http://www.kanzaki.com/docs/ical/ memiliki versi spesifikasi yang lebih lama yang sedikit lebih mudah dibaca. Ini membantu sebagai titik awal - banyak hal masih sama.

Juga di situs saya , saya punya

  1. Beberapa daftar sumber daya yang berguna (lihat kanan bawah bilah sisi) di
    • ical Spec RFC 5545
    • Sumber Daya Pengujian ical
  2. Beberapa catatan dicatat dalam perjalanan saya bekerja .icsselama beberapa tahun terakhir. Secara khusus, Anda mungkin menemukan 'lembar contekan' acara berulang ini berguna.

.ics area yang membutuhkan penanganan hati-hati:

  • acara 'sepanjang hari'
  • jenis tanggal (zona waktu, UTC, atau 'mengambang' lokal) - nb untuk memahami perbedaan
  • interoperabilitas aturan pengulangan
anmari
sumber
2
  1. Format ical yang tepat: http://www.ietf.org/rfc/rfc2445.txt
  2. Menurut speknya, itu harus diakhiri dengan .ics

Sunting: sebenarnya saya tidak yakin - baris 6186 memberikan contoh dalam format penamaan .ics, tetapi juga menyatakan Anda dapat menggunakan parameter url. Saya tidak berpikir itu penting, selama jenis MIME benar.

Edit: Contoh dari wikipedia: 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

Jenis MIME dikonfigurasi di server.

lod3n
sumber
1
Saya telah mencoba untuk membaca spesifikasi itu berkali-kali tetapi saya tidak dapat membuat kepala atau ekor sejauh seperti apa file ical akan terlihat. Dapatkah Anda setidaknya mengarahkan saya ke beberapa baris di mana ia mulai benar-benar berbicara tentang apa yang harus dimuat dalam file .ics sejauh header, di mana harus meletakkan jenis MIME, dll?
rhodesjason
2

Pastikan Anda memformat string seperti ini atau string tidak akan berfungsi

 $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 Tidak Ada
sumber
1
lebih baik digunakan PHP_EOLdaripada "\n".
Ya Barry
4
PHP_EOL adalah lingkungan khusus untuk baris akhir, jadi di windows akan menampilkan \r\njadi ingatlah itu!
Chris