web-dev-qa-db-ja.com

Custom-post-type(イベント)の投稿をループして.ics(iCal)ファイルを作成しますか?

私は今までこれまで扱ったことがない機能について本当にあなたの助けを必要としています。

私は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でこの関数呼び出しを使用して、すべての "今後の"イベントをリストします。

.icsファイルを作成します。

私が欲しいもう一つの特徴があります。私はすべての "今後の"イベントでその場で.ics(iCal)ファイルを作成したいです。それで、私はすでに質問をしているので、これは難しいことではないと思います。

それについて何かアイデアはありますか?私は本当にこれを手伝ってくれてありがとう。

更新:

.icsカレンダーファイルにはもう2つ問題があります。

Event-dateのタイムスタンプを返す関数get_event_date($timestamp)があります。しかし、(私にとっては)かなり複雑な部分があります。

異なるフォーマットを保持する2つの変数$date[0]$time[0]があります。 $date[0]はタイムスタンプ1347667200を保持し、$time[0]は文字列を保持します。 14:00unixToical()関数に渡すには、 "date"と "time"の最後のタイムスタンプを計算する必要があります。

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に読み込むとき、最初のイベントだけが読み込まれるのは、これが問題かもしれません。 (テキストエディタでファイルを開くと、すべてのイベントがそこにあります)

1
mathiregister

これは完全に イベントオーガナイザー (私が開発したプラグイン)に基づいています。コードはソースからほとんど真っ直ぐに持ち上げられますが、変更があります。そのように私は与えられたようにコードをテストしませんでした。

ステップ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-eventsまたはwww.site.com/feed/my-eventswpse63611_events_feed_output()コールバックはICALファイルの内容を出力します。でもまず...

ステップ2:クエリを変更する

WordPressはこのフィードに何が含まれることを意味しているのかわかりません。ここではWordPressにpre_get_postsを使用しています。このフィードには投稿タイプ 'wr_event'の投稿が必要です。私たちは特定のカテゴリー、開催地から、あるいは特定の日付の間にもイベントを受け取ることができます。

クエリを出力から切り離すことで、同じ出力関数を使用する複数のフィードを持つことができます - ただし、時間、場所、カテゴリなどに基づいて異なるイベントをクエリできます。

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()はフィードの出力を印刷する責任があります。

 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;
 }
4
Stephen Harris

これを試して:

最初にこの関数をあなたのテーマのfunctions.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;

}

そのため、要約フィールドと説明フィールド、および開始時刻と終了時刻を正しい形式に更新するだけで、ダウンロードリンクは次のようになります。

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