Как я могу использовать PHP для динамической публикации файла, который будет читать Календарь Google?

107

Любой поиск Google на PHP ical просто вызывает phpicalendar и информацию о том, как анализировать или читать IN ical файлы. Я просто хочу написать файл PHP, который извлекает события из моей базы данных и записывает их в формате ical.

Моя проблема в том, что я не могу найти нигде, которая ответила бы на два вопроса:

  1. Какой точный формат ical, включая заголовки, формат файла, нижние колонтитулы и т. Д.? Другими словами, что именно должно быть в файле, чтобы его правильно прочитал Календарь Google и т. Д.?
  2. Если я создам этот файл с расширением .php, как мне опубликовать его как файл? Нужно ли мне писать в новый файл .ics? Или Календарь Google и т. Д. Будет считывать файл .php так же, как если бы его содержимое было в правильном формате? (Так же, как файл style.css.php будет читаться как файл CSS, если содержимое на самом деле является CSS и т. Д.)

Любая помощь, которую вы можете оказать или указать мне, будет принята с благодарностью !!!

Родезьясон
источник

Ответы:

129

Это должно быть очень просто, если Календарь Google не требует *.ics-расширение (что потребует некоторой перезаписи URL-адреса на сервере).

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

По сути, это все, что вам нужно, чтобы заставить клиента думать, что вы обслуживаете файл iCalendar, даже если могут возникнуть некоторые проблемы с кешированием, кодировкой текста и т. Д. Но вы можете начать экспериментировать с этим простым кодом.

Стефан Гериг
источник
1
Спасибо. Я думаю, что эти заголовки - это то, чего мне не хватало. Я предполагаю, что есть несколько заключительных шагов в подготовке этого Календаря Google, так как, когда я пытаюсь передать этот файл в Календарь Google через URL-адрес, он говорит: «Импорт календаря с URL-адреса ...», но зависает на этом навсегда. Может, это другой вопрос?
rhodesjason
3
Именно. Я обновил приведенный выше пример - и я также добавил свойство DTSTAMP, которое сообщит клиенту, когда события были обновлены.
Стефан Гериг,
1
Ладно, Гериг, ты гений. Это сработало. Спасибо. (Насколько я могу судить, Календарь Google тоже обновляется почти сразу.)
rhodesjason
3
Если я не ошибаюсь. Программы используют UID, чтобы узнать, удалено ли событие. Если php-скрипт всегда генерирует другой UID (-> mt_rand), программы всегда будут думать, что все содержимое изменилось. Все исчезло и все новое. Лично я бы придерживался того же UID, если событие в базе данных такое же, и просто использовал бы идентификатор записи (и некоторую информацию о хосте). DTSTAMP показывает, что что-то изменилось. Этого должно быть достаточно.
Seirddriezel
3
Календарь Google ДЕЙСТВИТЕЛЬНО требует расширения * .ics. Если вы используете .htaccess, вы можете сделать это, добавив RewriteEngine on RewriteRule ^calendar.ics$ my_php_script.php [QSA]
Fanky
19

Примечание из личного опыта в дополнение к ответу Стефана Герига и ответу Дэйва Ниона (и ответу mmmshuddup):

Когда я использовал валидатор ICS по адресу http://severinghaus.org/projects/icv/, у меня возникли проблемы с проверкой при использовании как \ n, так и PHP_EOL.

Я узнал, что мне нужно использовать \ r \ n, чтобы он прошел правильную проверку, поэтому это было мое решение:

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;

Это остановило мои ошибки синтаксического анализа и заставило мои файлы ICS правильно проверяться.

Кейн Форд
источник
Информация заголовка - важная часть к вашему сведению для всех, кто смотрит в будущее. По большей части большинство приложений и программ не беспокоятся о перерывах в работе NewLine. Только валидаторы вроде делают. Но самое главное - это заголовочная часть. Некоторое время мы пробовали без него, и у нас было много проблем.
jfreak53
1
Для чего нужен escapeString? Я предполагал, что от него нужно избавиться кое-что, но вы, кажется, используете htmlspecialcharsдля этого вместо этого.
Люк
1
Быстрое исправление: дата ('Ymd \ THis \ Z', $ timestamp). Должен быть H вместо g.
Педро Гоес
6

Существует отличный пакет eluceo / ical , который позволяет легко создавать файлы ics.

Вот пример использования из документации:

// 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();
Иван Ярыч
источник
4

http://www.kanzaki.com/docs/ical/ содержит немного более читаемую версию старой спецификации. Это помогает в качестве отправной точки - многие вещи остались прежними.

Также на моем сайте у меня есть

  1. Некоторые списки полезных ресурсов (см. Боковую панель внизу справа) на
    • ical Spec RFC 5545
    • Ресурсы для тестирования материалов
  2. Некоторые заметки о моем путешествии, с которыми я работал .icsза последние несколько лет. В частности, вы можете найти эту «шпаргалку» по повторяющимся событиям .

.ics области, требующие осторожного обращения:

  • мероприятия на весь день
  • типы дат (часовой пояс, UTC или местное «плавающее») - nb, чтобы понять различие
  • совместимость правил повторения
анмари
источник
2
  1. Точный формат: http://www.ietf.org/rfc/rfc2445.txt
  2. Согласно спецификации, он должен заканчиваться на .ics.

Изменить: на самом деле я не уверен - строка 6186 дает пример в формате именования .ics, но также заявляет, что вы можете использовать параметры URL. Я не думаю, что это имеет значение, если тип MIME правильный.

Изменить: пример из википедии: 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

Тип MIME настроен на сервере.

lod3n
источник
1
Я пытался прочитать эту спецификацию много раз, но не могу понять, как будет выглядеть файл ical. Можете ли вы хотя бы указать мне на несколько строк, где на самом деле начинается разговор о том, что должен содержать файл .ics, вплоть до заголовка, где разместить тип MIME и т. Д.?
rhodesjason
2

Убедитесь, что вы форматируете строку так, иначе она не сработает

 $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";
Дэйв Нет
источник
1
лучше использовать PHP_EOLвместо "\n".
Да Барри
4
PHP_EOL - это среда, специфичная для конечных строк, поэтому в Windows он будет выводиться, \r\nтак что имейте это в виду!
Крис