【问题标题】:Has anyone created an ics iCalendar generator function that works with Google Calendar?有没有人创建了一个与谷歌日历一起使用的 ics iCalendar 生成器函数?
【发布时间】:2012-01-14 03:52:50
【问题描述】:

我正在尝试生成可成功导入 Google 日历的 .ics 文件。事实证明,Google 日历特别困难(我的 Outlook 和 Apple iCal 运行良好)。

有没有人有一个 php 函数或类来创建正确的标题并插入已被证明可以与 Google 日历一起使用的事件?

【问题讨论】:

    标签: php google-calendar-api icalendar


    【解决方案1】:

    我做了类似的事情,但只是创建了一个 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 邮件都可以通过这种方式填充日历,但不幸的是,两者都没有一个很好的工具(我可以找到),可以预先生成一个您可以使用的链接。

    希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      这是一个旧的,唯一的答案没有被接受,所以不确定下面的代码是否解决了你的问题。但是,我在自己的搜索中遇到了这个问题,试图修复我遇到的错误,现在我有了解决方案,我想我会分享它。以下代码已使用最新的 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>");
      

      【讨论】:

        【解决方案3】:

        我还看到这是一篇较旧的帖子,但没有接受答案。

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

        1. 用于生成: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 日历(或任何其他日历程序),并且它会每天 ping 它以进行更新。 (URL 必须是可公开访问的,这需要我使用 guid 作为标识符而不是 user_id,顺便说一下)

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

        希望这可以帮助其他人登陆这里!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-02-08
          • 2020-09-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-07-27
          • 1970-01-01
          相关资源
          最近更新 更多