Кто-нибудь создал функцию генератора ics iCalendar, которая работает с Календарем Google?

Я пытаюсь создать файл .ics, который успешно импортируется в календарь Google. Календарь Google оказывается особенно сложным (у меня отлично работают Outlook и Apple iCal).

У кого-нибудь есть функция или класс php, который создает правильные заголовки и вставляет события, которые, как было доказано, работают с календарем Google?


person rihallix    schedule 06.12.2011    source источник


Ответы (3)


Я также вижу, что это более старый пост, но без принятого ответа.

Недавно мне нужно было реализовать генерацию ical в моем веб-приложении... но мое также требовало повторяющихся событий с заданной формулой. Для этого я использовал комбинацию следующих пакетов:

  1. Для создания ical: https://github.com/markuspoerschke/iCal
  2. Для повторяющихся событий: https://github.com/simshaun/recurr.

Я использую recurr для создания списка дат на основе формулы повторения:

public function generate_dates_array(\DateTime $end_date = null) : array
{
    if(! $end_date) {
        $end_date = new \DateTime('midnight');
    }

    $rule = new \Recurr\Rule($this->recurrence_rule, $this->created_at->setTime(0,0));

    $rule->setUntil($end_date);

    $transformer = new ArrayTransformer();

    $dates = $transformer->transform($rule);

    $dateArray = [];

    foreach($dates as $date) {
        $dateArray[] = $date->getStart();
    }

    return $dateArray;
}

Затем настройте мой календарь:

$vCalendar = new \Eluceo\iCal\Component\Calendar('YourUrlHere');
$vCalendar->setName('YOUR NAME HERE');
$vCalendar->setDescription('YOUR DESCRIPTION HERE');

Затем зациклите эти даты, добавив события в мой объект календаря... убедившись, что мое время настроено на UTC из выбранного пользователем часового пояса.

$today = new Carbon();
$end_date = $today->addMonth();

foreach($events as $event) {
  $dates = $event->generate_dates_array($end_date); // function shown in above code snippet
  $duration = $event->duration ? $event->duration : 30;

  // Each Occurrence for event
  foreach($dates as $date) {
    $vEvent = new \Eluceo\iCal\Component\Event();

    $date_string = "{$date->format('Y-m-d')} {$event->time}";

    $start_time = new Carbon($date_string, $user->time_zone);
    $start_time->setTimezone('UTC');
    $vEvent->setDtStart($start_time);

    $end_time = new Carbon($date_string, $user->time_zone);
    $end_time = $end_time->addMinutes($duration);
    $end_time->setTimezone('UTC');
    $vEvent->setDtEnd($end_time);

    $vEvent->setNoTime(false);
    $vEvent->setSummary($event->name);
    $vEvent->setDescription("$event->description");
    $vCalendar->addComponent($vEvent);
  }
}

После того, как все настроено правильно, я вывожу календарь. Это означает, что я могу использовать URL-адрес, создающий этот файл, для импорта календаря в Календарь Google (или любую другую программу календаря), и он будет ежедневно проверять наличие обновлений. (URL должен быть общедоступным, для чего, кстати, я использовал guid в качестве идентификатора вместо user_id)

header('Content-Type: text/calendar; charset=utf-8');
echo $vCalendar->render();

Надеюсь, это поможет кому-нибудь еще приземлиться здесь!

person Brian Webb    schedule 02.07.2018

Я сделал то же самое, но только что создал URL вместо iCal.

Ознакомьтесь с https://support.google.com/calendar/answer/3033039.

Заполните форму и сгенерируйте HTML, затем в файле php, который я использовал для создания ical, я только что создал отдельную вещь, чтобы заменить детали переменными.

EG:

if($calType === "iCal"){
    //set correct content-type-header
    header('Content-Disposition: attachment; filename=AddToCalendar.ics');
    header('Content-Type: text/calendar; charset=utf-8');

    $desc = str_replace("\n", '\n', $desc);
    $desc = str_replace(array("\r","\n","\r"), '', $desc);

    $ical = "BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Smartershows.com//TheBatteryShow//EN
X-WR-CALNAME;CHARSET=utf-8:".$subj."
METHOD:PUBLISH
X-MS-OLK-FORCEINSPECTOROPEN:TRUE
BEGIN:VEVENT
SUMMARY;CHARSET=utf-8:".$subj."
LOCATION;CHARSET=utf-8:".$loc."
URL:".$url."
UID:30fc985de98ed0dabfeb13722e3c82259fcd33e3 
DESCRIPTION:".$desc."
DTSTART:".$sDate."T".$sTime."
DTEND:".$eDate."T".$eTime."
END:VEVENT
END:VCALENDAR";

return $ical;
exit;
}else if($calType === "gCal"){

    $href = "http://www.google.com/calendar/event?";
    $href .= "action=TEMPLATE";
    $href .= "&text=".urlencode($subj);
    $href .= "&dates=".$sDate."T".$sTime."/".$eDate."T".$eTime;
    $href .= "&details=".urlencode($desc);
    $href .= "&location=".urlencode($loc);
    $href .= "&trp=false";
    $href .= "&sprop=".urlencode($subj);
    $href .= "&sprop=name:".urlencode($url);

    return '<a href="'.$href.'" target="_blank"><strong>Download for Gmail</strong></a>';

}

Таким образом, первый блок в if создает ical, а второй берет ту же информацию для создания URL-адреса, который Google возьмет и заполнит страницу календаря.

Недостатком этого является то, что вы можете помещать в описание только основные вещи ... не так много причудливого html или чего-то еще ... если вы не htmlencode все, что я думаю, но даже тогда я не уверен, каково ограничение на количество символов в URL-адресе. ...

Hotmail и почта Yahoo также могут заполнять календари таким образом, но, к сожалению, ни один из них не имеет хорошего инструмента (который я могу найти), который заранее генерирует ссылку, которую вы можете использовать.

Надеюсь это поможет!

person Matthew Jonat    schedule 06.03.2014

Это старый, и единственный ответ не был принят, поэтому не уверен, что приведенный ниже код устранил вашу проблему. Тем не менее, я наткнулся на это в своих собственных поисках, чтобы попытаться исправить ошибку, которая у меня была, и теперь, когда у меня есть решение, я решил поделиться им. Приведенный ниже код был протестирован с последней версией Outlook и с Gmail.

С Outlook причиной моей ошибки было то, что я использовал \n вместо \r\n для сведений о событии. Итак, как вы увидите ниже, я использую \r\n для события и \n для всего остального, чтобы PHP обработал его правильно. Возможно, аналогичная проблема вызывала проблемы с gmail?

Предупреждение, этот код ничего не делает для предотвращения внедрения заголовков, пожалуйста, используйте ответственно ;-)

<?php
    date_default_timezone_set('America/New_York');
    //CONFIGURE HERE
    $fromName           = "John Doe";
    $fromEmail          = "[email protected]";
    $toName             = "Your Name";
    $toEmail            = '[email protected]';
    $start              = new DateTime('2017-08-15 15:00');
    $end                = new DateTime('2017-08-15 16:00');
    $summary            = "Hello World Event";
    //END CONFIGURATION

    $uid                = "0123456789";
    $headers            = array();
    $boundary           = "_CAL_" . uniqid("B",true) . "_B_";
    $headers[]          = "MIME-Version: 1.0";
    $headers[]          = "Content-Type: multipart/alternative; boundary=\"".$boundary."\"";
    $headers[]          = "To: \"{$toName}\" <{$toEmail}>";
    $headers[]          = "From: \"{$fromName}\" <{$fromEmail}>";

    $calendarLines      = array(
        "BEGIN:VCALENDAR",
        "METHOD:REQUEST",
        "PRODID:-//PHP//MeetingRequest//EN",
        "VERSION:2.0",
        "BEGIN:VEVENT",
        "ORGANIZER;CN={$fromName}:MAILTO:{$fromEmail}",
        "ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN={$toName}:MAILTO:{$toEmail}",
        "DESCRIPTION:{$summary}",
        "SUMMARY:{$summary}",
        "DTSTART:".$start->setTimezone(new DateTimeZone('UTC'))->format('Ymd\THis\Z'),
        "DTEND:".$end->setTimezone(new DateTimeZone('UTC'))->format('Ymd\THis\Z'),
        "UID:{$uid}",
        "CLASS:PUBLIC",
        "PRIORITY:5",
        "DTSTAMP:".gmdate('Ymd\THis\Z'),
        "TRANSP:OPAQUE",
        "STATUS:CONFIRMED",
        "SEQUENCE:0",
        "LOCATION:123 Any Street",
        "BEGIN:VALARM",
        "ACTION:DISPLAY",
        "DESCRIPTION:REMINDER",
        "TRIGGER;RELATED=START:-PT15M",
        "END:VALARM",
        "END:VEVENT",
        "END:VCALENDAR"
    );


    $calendarBase64     = base64_encode(implode("\r\n",$calendarLines));
    //ensure we don't have lines longer than 70 characters for older computers:
    $calendarResult     = wordwrap($calendarBase64,68,"\n",true);

    $emailLines = array(
        "--{$boundary}",
        "Content-Type: text/html; charset=\"iso - 8859 - 1\"",
        "Content-Transfer-Encoding: quoted-printable",
        "",
        "<html><body>",
        "<h1>Hello World</h1>",
        "<p>This is a calendar event test</p>",
        "</body></html>",
        "",
        "--{$boundary}",
        "Content-Type: text/calendar; charset=\"utf - 8\"; method=REQUEST",
        "Content-Transfer-Encoding: base64",
        "",
        $calendarResult,
        "",
        "--{$boundary}--"
    );
    $emailContent   = implode("\n",$emailLines);

    $headersResult      = implode("\n",$headers);
    mail($toEmail, $summary, $emailContent, $headersResult );
    echo("<pre>".htmlentities($headersResult)."\n\n".htmlentities($emailContent)."</pre>");
    echo("<br /><br />");
    echo("<pre>".base64_decode($calendarResult)."</pre>");
person Kevin Nelson    schedule 09.08.2017