【发布时间】:2012-01-14 03:52:50
【问题描述】:
我正在尝试生成可成功导入 Google 日历的 .ics 文件。事实证明,Google 日历特别困难(我的 Outlook 和 Apple iCal 运行良好)。
有没有人有一个 php 函数或类来创建正确的标题并插入已被证明可以与 Google 日历一起使用的事件?
【问题讨论】:
标签: php google-calendar-api icalendar
我正在尝试生成可成功导入 Google 日历的 .ics 文件。事实证明,Google 日历特别困难(我的 Outlook 和 Apple iCal 运行良好)。
有没有人有一个 php 函数或类来创建正确的标题并插入已被证明可以与 Google 日历一起使用的事件?
【问题讨论】:
标签: php google-calendar-api icalendar
我做了类似的事情,但只是创建了一个 URL 而不是 iCal。
查看https://support.google.com/calendar/answer/3033039
填写表格并生成 HTML,然后在我用来创建 ical 的 php 文件中,我刚刚创建了一个单独的东西来用变量替换细节。
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 但即使那样我也不确定字符限制是多少一个网址是...
Hotmail 和 Yahoo 邮件都可以通过这种方式填充日历,但不幸的是,两者都没有一个很好的工具(我可以找到),可以预先生成一个您可以使用的链接。
希望这会有所帮助!
【讨论】:
这是一个旧的,唯一的答案没有被接受,所以不确定下面的代码是否解决了你的问题。但是,我在自己的搜索中遇到了这个问题,试图修复我遇到的错误,现在我有了解决方案,我想我会分享它。以下代码已使用最新的 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>");
【讨论】:
我还看到这是一篇较旧的帖子,但没有接受答案。
最近,我需要在我的网络应用程序中实现 ical 生成......但我的也需要使用给定公式的重复事件。为此,我使用了以下软件包的组合:
我使用 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 日历(或任何其他日历程序),并且它会每天 ping 它以进行更新。 (URL 必须是可公开访问的,这需要我使用 guid 作为标识符而不是 user_id,顺便说一下)
header('Content-Type: text/calendar; charset=utf-8');
echo $vCalendar->render();
希望这可以帮助其他人登陆这里!
【讨论】: