web-dev-qa-db-fra.com

Parcourez les publications d'un type de post personnalisé (événement) et créez un fichier .ics (iCal)?

J'ai vraiment besoin de votre aide pour une fonctionnalité avec laquelle je n'ai jamais travaillé.

J'ai un type de post personnalisé nommé wr_event. Et j'ai créé ce WP_Query personnalisé pour récupérer toutes les publications de ce type de message qui sont "plus jeunes" qu'hier. Assez simple et cela fonctionne comme un charme.

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;       
} 

J'utilise cet appel de fonction dans mon index.php pour répertorier tous les événements "à venir".

Création d'un fichier .ics.

Il y a une autre caractéristique que j'aimerais avoir. Je veux créer un fichier .ics (iCal) à la volée avec tous les événements "à venir". Donc, je suppose que cela ne devrait pas être trop difficile car j'ai déjà la requête.

Des idées à ce sujet? J'apprécierais vraiment une aide avec ceci.

Mise à jour:

J'ai deux autres problèmes avec le fichier de calendrier .ics.

J'ai une fonction get_event_date($timestamp) qui renvoie un horodatage de la date de l'événement. Cependant, il y a une partie (pour moi) plutôt compliquée.

Il existe deux variables $date[0] et $time[0] qui contiennent des formats différents. Le $date[0] contient un timestamp 1347667200 et le $time[0] contient une chaîne, par ex. 14:00. Je dois maintenant calculer l’horodatage final de la "date" plus "heure" pour le transmettre à la fonction 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;
        }

La partie où j'ai défini $hours à "00" est pour quand il n'y a pas de temps défini. Dans ce cas, je veux que le temps final soit "00:00" (minuit).

Toute idée de ce que je fais mal ici. J'imagine que c'est peut-être le problème qui explique pourquoi lors de l'importation du fichier de calendrier dans iCal, seul le premier événement est importé. (Lorsque vous ouvrez le fichier avec un éditeur de texte, tous les événements s'y trouvent)

1
mathiregister

Ceci est entièrement basé sur Organisateur d'événements (un plug-in que j'ai développé). Le code est levé presque directement de la source mais avec des modifications. En tant que tel, je n'ai pas testé le code tel que donné.

Étape 1: créer un flux

C'est simple:

add_action('init','wpse63611_add_events_feed');
function wpse63611_add_events_feed(){
     add_feed('my-events','wpse63611_events_feed_output');
}

Cela ajoute un flux à votre site: www.site.com?feed=my-events ou www.site.com/feed/my-events si vous avez de jolis permaliens. Le callback wpse63611_events_feed_output() affichera le contenu du fichier ICAL. Mais d'abord ...

Étape 2: Modifier la requête

WordPress ne sait pas ce que ce flux est censé contenir. Ici, nous utilisons le pre_get_posts pour indiquer à WordPress que, pour ce flux, nous voulons des publications de type post "wr_event". Nous pourrions obtenir des événements d'une catégorie, d'un lieu ou entre certaines dates également.

En séparant la requête de la sortie, vous pouvez avoir plusieurs flux qui utilisent la même fonction de sortie, mais interrogez différents événements (en fonction de l'heure, du lieu, de la catégorie, etc.).

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);
     }
}

Étape 3: contenu du fichier ICS

Comme mentionné précédemment, wpse63611_events_feed_output() est responsable de l’impression de la sortie de notre flux.

 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();
}   

J'ai utilisé la fonction unixToiCal que vous avez définie dans votre question. J'ai également utilisé ce qui suit pour supprimer tout ce qui pourrait perturber un analyseur 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

Essaye ça:

Ajoutez d’abord ces fonctions au functions.php de votre thème.

//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;

}

Il suffit donc de mettre à jour les champs de résumé et de description, ainsi que les heures de début et de fin au bon format, et le lien de téléchargement doit ressembler à quelque chose comme:

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