循环浏览自定义发布类型(事件)的帖子并创建.ics(ICal)文件?

时间:2012-08-30 作者:mathiregister

我真的需要你的帮助,我到目前为止从未使用过一个功能。

我有一个名为wr_event. 我创造了这个习惯WP_Query 检索此帖子类型中比昨天“年轻”的所有帖子。这很简单,很有魅力。

function event_list_iCal() {

    $yesterday = time() - 24*60*60;
    $args = array(
        \'post_type\' => \'wr_event\',
        \'posts_per_page\' => -1, // show all posts
        \'meta_key\' => \'event_date\',
        \'orderby\' => \'meta_value_num\',
        \'order\' => \'ASC\',
        \'meta_value\' => $yesterday,
        \'meta_compare\' => \'>\',
    );

    $loop = new WP_Query( $args );
    $ical = "BEGIN:VCALENDAR
    VERSION:2.0
    PRODID:-//hacksw/handcal//NONSGML v1.0//EN";

    $posts = get_posts( $args );
    foreach( $posts as $post ) : setup_postdata($post);
        $ical .= "BEGIN:VEVENT
        UID:" . md5(uniqid(mt_rand(), true)) . "mysite.com
        DTSTAMP:" . gmdate(\'Ymd\').\'T\'. gmdate(\'His\') . "Z
        DTSTART:".unixToiCal(get_event_date($post), get_event_time($post))."00Z
        DTEND:".unixToiCal(get_event_end_date($post), get_event_end_time($post))."00Z
        SUMMARY:".get_the_title($post->ID)."
        DESCRIPTION:".get_the_content($post->ID)."
        END:VEVENT";
    endforeach;

    $ical .= "END:VCALENDAR";

    header(\'Content-type: text/calendar; charset=utf-8\');
    header(\'Content-Disposition: inline; filename=calendar.ics\');
    echo $ical;
    exit;
}

function unixToiCal($uStamp = 0, $tzone = 0.0) {
    $uStampUTC = $uStamp + ($tzone * 3600);       
    $stamp  = date("Ymd\\THis\\Z", $uStampUTC);
    return $stamp;       
} 
我在我的index.php 列出所有“即将”的事件。

Creating a .ics file.

还有一个我想要的特性。我想创建一个。ics(iCal)文件随附所有“即将到来的”活动。所以我想这应该不会太难,因为我已经有了这个问题。

对那件事有什么想法吗?我真的很感谢你的帮助。

Update:

我还有两个问题。ics日历文件。

我有一个功能get_event_date($timestamp) 返回事件日期的时间戳。然而,(对我来说)其中有一个相当复杂的部分。

有两个变量$date[0]$time[0] 包含不同格式的。这个$date[0] 保存时间戳1347667200 以及$time[0] 保存字符串,例如。14:00. 我现在需要计算“日期”加上“时间”的最终时间戳,以将其传递给unixToical() 作用

if ( $timestamp ) { 
            if ( !empty( $time[0]) ) {
                $time = explode(\':\', $time[0]);
                $hours = $time[0];
                $minutes = $time[1];
            } else { 
                //$hours = "00";
                //$minutes = "00";
            }
            $seconds = "00";
            return $date[0] + ($hours * 60)  + $minutes;
            exit;
        }
我设置的部分$hours “00”表示未设置时间。那样的话,我想在决赛中计时。ics为“00:00”(午夜)。

知道我做错了什么吗。我想这可能是为什么将日历文件导入iCal时只导入第一个事件的问题。(使用文本编辑器打开文件时,所有事件都在其中)

2 个回复
最合适的回答,由SO网友:Stephen Harris 整理而成

这完全是基于Event Organiser (我开发的一个插件)。代码几乎是直接从源代码中提取出来的,但经过了修改。因此,我没有按照给定的方式测试代码。

步骤1:创建提要这很简单:

add_action(\'init\',\'wpse63611_add_events_feed\');
function wpse63611_add_events_feed(){
     add_feed(\'my-events\',\'wpse63611_events_feed_output\');
}
这会向您的网站添加一个提要:www.site.com?feed=my-eventswww.site.com/feed/my-events 如果你有很长的头发。这个wpse63611_events_feed_output() 回调将输出ICAL文件的内容。但首先。。。

第二步:改变查询,WordPress不知道这个提要要包含什么。这里我们使用pre_get_posts 告诉WordPress,对于这个feed,我们希望帖子类型为“wr\\u event”。我们可以从特定类别、地点或特定日期之间获得活动。

通过将查询与输出分离,您可以有多个feed,它们使用相同的输出函数,但查询不同的事件(基于时间、位置、类别等)。

add_action( \'pre_get_posts\', \'wpse63611_event_feed_query\' );
function wpse63611_event_feed_query( $query ) {

     $yesterday = current_time(\'timestamp\') - 24*60*60;
     $compare = $latest ? \'>\' : \'<\';

     if( $query->is_feed(\'eo-events\') ){
         $query->set(\'post_type\', \'wr_event\');
         $query->set(\'posts_per_page\', -1);
         $query->set(\'meta_key\', \'event_date\');
         $query->set(\'orderby\', \'meta_value_num\');
         $query->set(\'order\', \'ASC\');
         $query->set(\'meta_compare\', $compare);
         $query->set(\'meta_value\', $value);
     }
}
步骤3:ICS文件的内容,如前所述,wpse63611_events_feed_output() 负责打印feed的输出。

 function wpse63611_events_feed_output(){
      //Let\'s give it a name;
      $filename = urlencode( \'my_events\' . date(\'Y-m-d\') . \'.ics\' );

      //Collect output 
      ob_start();

      // File header
      header( \'Content-Description: File Transfer\' );
      header( \'Content-Disposition: attachment; filename=\' . $filename );
      header(\'Content-type: text/calendar\');
      header("Pragma: 0");
      header("Expires: 0");
?>
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//<?php  get_bloginfo(\'name\'); ?>//NONSGML Events //EN
CALSCALE:GREGORIAN
X-WR-CALNAME:<?php echo get_bloginfo(\'name\');?> - Events

<?php

    // Loop through events
    if ( have_posts() ):

         $now = new DateTime();
         $datestamp =$now->format(\'Ymd\\THis\\Z\');

         while( have_posts() ): the_post();
              global $post;

              $uid = md5(uniqid(mt_rand(), true))."@mysite.com";

              $start = unixToiCal(get_event_date($post), get_event_time($post));
              $end = unixToiCal(get_event_end_date($post), get_event_end_time($post));

              $summary = wpse63611_escape_icalText(get_the_title())
              $description = apply_filters(\'the_excerpt_rss\',  get_the_content());
              $description = wpse63611_escape_icalText($description);

BEGIN:VEVENT
UID:<?php echo $uid;?>

DTSTAMP:<?php echo $datestamp;?>

DTSTART:<?php echo $start; ?>

DTEND:<?php echo $end; ?>

SUMMARY:<?php echo wpse63611_esc_ical_text($summary);?>

DESCRIPTION:<?php echo wpse63611_esc_ical_text($description);?>

END:VEVENT

         endwhile;

    endif;
?>
END:VCALENDAR
<?php

    //Collect output and echo 
    $eventsical = ob_get_contents();
    ob_end_clean();
    echo $eventsical;
    exit();
}   
我用过unixToiCal 您在问题中定义的函数。我还使用以下方法删除了可能会打乱ICAL解析器的任何内容:

 function wpse63611_esc_ical_text( $text=\'\' ){

    $text = str_replace("\\\\", "\\\\\\\\", $text);
    $text = str_replace(",", "\\,", $text);
    $text = str_replace(";", "\\;", $text);
    $text = str_replace("\\n", "\\n ", $text);

    return $text;
 }

SO网友:Bainternet

尝试以下操作:

首先将此函数添加到主题的函数中。php

//this will call the download function if needed
function Ical_download() {
    global $wp;
    global $wp_query;
    if (isset($wp->query_vars["ical_download"])){
        event_list_iCal();
        exit();
    }
}

add_action(\'template_redirect\', \'Ical_download\');


//this will add ical_download to the list of query vars
function ical_download_query_val() {
    global $wp;
    $wp->add_query_var(\'ical_download\');
}

add_filter(\'init\', \'ical_download_query_val\');
function event_list_iCal( $latest = true ) {

    $yesterday = time() - 24*60*60;
    $compare = $latest ? \'>\' : \'<\';

    $args = array(
        \'post_type\' => \'wr_event\',
        \'posts_per_page\' => -1, // show all posts
        \'meta_key\' => \'event_date\',
        \'orderby\' => \'meta_value_num\',
        \'order\' => \'ASC\',
        \'meta_value\' => $yesterday,
        \'meta_compare\' => $compare,
    );

    $loop = new WP_Query( $args );
    $ical = "BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//hacksw/handcal//NONSGML v1.0//EN
";
    while ( $loop->have_posts() ) : $loop->the_post();

    $ical .= "BEGIN:VEVENT
UID:" . md5(uniqid(mt_rand(), true)) . "example.com
DTSTAMP:" . gmdate(\'Ymd\').\'T\'. gmdate(\'His\') . "Z
DTSTART:".get_event_date($post)."00Z
DTEND:".get_event_end_date($post);."00Z
SUMMARY:".$post->title."
DESCRIPTION:".$post->content."
END:VEVENT
";

    endwhile;

    $ical .= "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;

}
因此,只需将Summary和description字段以及开始和结束时间更新为正确的格式,您的下载链接应该如下所示:

<a href="<?php echo get_bloginfo(\'url\').\'?ical_download\';?>">Download iCal</a>

结束