有人创建了一个与Google Calendar一起工作的ics iCalendar生成器函数吗?


Has anyone created an ics iCalendar generator function that works with Google Calendar?

我正在尝试生成一个.ics文件,成功导入到Google日历。事实证明,谷歌日历特别难用(我用的Outlook和Apple iCal运行得很好)。

有没有人有一个php函数或类,创建正确的标题和插入事件,已被证明与谷歌日历工作?

我也看到这是一个旧的帖子,但没有接受的答案。

最近,我需要在我的web应用程序中实现ical generation…但我也需要在给定的公式中重复发生事件。为此,我使用了以下包的组合:

  1. ical generation: https://github.com/markuspoerschke/iCal
  2. 对于重复事件:https://github.com/simshaun/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 calendar(或任何其他日历程序),并且它将每天ping它以获取更新。(URL必须是可公开访问的,这要求我使用guid作为标识符,而不是user_id,顺便说一下)

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

希望这有助于其他人登陆这里!

这是一个老问题,唯一的答案不被接受,所以不确定下面的代码是否解决了您的问题。然而,我在自己的搜索中遇到了这个问题,试图修复我遇到的一个bug,现在我有了一个解决方案,我想我应该分享它。下面的代码已经在最新的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          = "john.doe@example.com";
    $toName             = "Your Name";
    $toEmail            = 'yourname@example.com';
    $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>");

我已经做了类似的事情,但只是创建了一个URL而不是一个iCal。

查看https://support.google.com/calendar/answer/3033039

填写表单并生成HTML,然后在php文件中我用来创建ical,我只是创建了一个单独的东西,用变量代替细节。

,

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,谷歌将接受并填充日历页面。

这样做的缺点是你只能把基本的东西放进描述中…没有很多花哨的HTML或其他东西……除非你用htmlencode所有东西,但即使这样,我也不确定url的字符限制是什么…

Hotmail和Yahoo mail都可以用这种方式填充日历,但不幸的是,它们都没有一个很好的工具(我可以找到),可以预先生成一个链接,你可以使用

希望这对你有帮助!