Live Blogging avec #WP custom post type / taxo

Publié le

par

Crédits Photo Live On Air from the Isle of Wight by adambowie, on Flickr

Ça faisait un moment que je n’avais pas consacré un article à WordPress, trop occupé sans doute à explorer les possibilités de BuddyPress… Aujourd’hui je vous propose un petit tutoriel pour créer une page de Live Blogging.

En fait l’idée est de disposer d’un outil simple pour « retransmettre en direct » un évènement, un peu à la manière de « yahoo live », sauf que dans mon cas il s’agit de conférences dans le cadre de mon taf :).

2013-02-13 : Update !!

Voici un child thème pour twentytwelve qui adapte le tuto en profitant notamment des tax query. Il suffit d’ajouter le shortcode expliqué dans la suite du tuto, de définir un post meta du nom de duration avec une valeur en millisecondes pour la page qui accueillera vos live posts. Tested on WP 3.5.1.


2012-04-25 : Update !!

Thanks to Roger, i’ve fixed the ajaxurl issue.. To make things easier i’ve packed the scripts into a twentyeleven child theme. Tested on WordPress 3.4 beta 3.


Pour arriver à cet objectif voici ma recette :

  1. Votre WordPress (version 3.0 minimum)
  2. Un custom post type
  3. Une custom taxonomy de type tag
  4. Un soupçon de shortcode API
  5. Une pincée d’ajax
  6. Une page « LIve » WP assaisonnée d’un post-meta
  7. 0 plugin
  8. Garniture optionnelle : un modèle de page 😉

Notre marmitte sera le script functions.php de notre thème actif, un script bien utile et pratique !

Commençons par le custom post type et la custom taxonomy :

Le custom post type a un avantage c’est qu’il n’est pas inclus par défaut dans le loop des posts classiques, du coup pour notre cas, nous ne prenons pas le risque de mélanger les genres ! On peut éventuellement s’en passer en utilisant une catégorie qu’on exclue du loop principal, du search, des archives… mais c’est vraiment se compliquer la vie et écrire en dur des ID de catégorie, j’aime pas trop. Si vous souhaitez en savoir plus, je vous conseille une nouvelle fois le blog de Justin Tadlock qui explique admirablement le concept de ce contenu particulier.

Pour ajouter nos contenus personnalisés, il s’agit d’ajouter un hook à l’évènement d’init de WordPress, voici donc le début de notre tambouille :

<?php
function function imath_live_post() {
    register_post_type( 'live-post', array(
        'label'           => __( 'Live Posts' ),
        'singular_label'  => __( 'Live Post' ),
        'public'          => true,
        'show_ui'         => true,
        'capability_type' => 'post',
        'hierarchical'    => false,
        'rewrite'         => false,
        'query_var'       => true,
        'supports'        => array( 'title', 'editor', 'author' )
    ) );
    
    register_taxonomy_for_object_type( 'live-tags', 'live-post' );
}
add_action( 'init','imath_live_post' );

function imath_live_taxonomies() {
    register_taxonomy( 'live-tags','live-post', array(
        'hierarchical' => false,
        'label'        => 'Live Tags',
        'query_var'    => true,
        'rewrite'      => false
    ) );
}
add_action( 'init', 'imath_live_taxonomies' );

NB : si vous préférez un type catégorie pour la taxo, changer dans le register_taxonomy la valeur de hierarchical pour true. Une fois que vous avez ajouté et enregistré ce code dans votre functions.php, vous allez retrouver un nouveau menu dans votre administration WordPress, comme illustré ci-dessous :

Tada ! On retrouve donc le lien vers la liste des « live posts », celui de l’ajout et vers la définition de nos tags persos

Si on clique sur Ajouter, nous retrouvons l’ambiance des posts classiques tout en disposant de la box pour ajouter nos tags directement

Poursuivons par la shortcode API

Pour que ça soit plus simple au moment de configurer notre page « Live », l’utilisation de cette API est très intéressante puisqu’en fait elle nous permet de directement et simplement déclencher notre loop personnalisé tout en lui passant des paramètres. Dans notre cas nous lui passerons le « slug » du tag, vous l’aurez compris ce tag nous permettra le cas échéant d’organiser plusieurs retransmissions différentes

<?php
function function imath_live_event_handle_shortcode( $atts ) {
    extract( shortcode_atts( array(
        'ref' => '0'
    ), $atts ) );
    
    // didn't manage to make ajax requests with custom taxonomies
    $custom_tag_id = get_term_by( 'slug', $ref, 'live-tags' );
    
    // to check if there's a new post
    $check_latest = 0;
    
    // time to wait till next ajax call
    $duration = get_post_meta( get_the_ID(), 'duration', true );
    
    // it works when no ajax
    query_posts( 'taxonomy=live-tags&term=' .$ref. '&posts_per_page=-1' ); ?>
        <div id="event-countdown" style="border-bottom:solid 1px #CCC;margin-bottom:10px">
            Prochaine mise á jour dans <span><?php echo $duration/1000;?></span> sec(s)
        </div
        <div id="event-container">
        
            <?php if ( have_posts() ) : while ( have_posts() ) : the_post();
                if( $check_latest == 0 ) {
                    $the_latest = get_the_ID() ;
                } ?>
                
                <div class="live-post">
                    <h5><?php the_time("G:i");?> <?php the_title();?></h5>
                    <div class="live-content"><?php the_content();?></div>
                </div>
            
            <?php $check_latest +=1;   endwhile; else:   ?>
                <b>L'évènement n'a pas démarré, merci de revenir plus tard...</b>
            <?php endif; ?>
        </div>

        <?php wp_reset_query(); ?>
        
        <!--Beginning of the auto refresh code-->
        <script type="text/javascript">
            var live_interval = <?php echo $duration;?>/1000;
            var i=1;
            
            function refreshCountDown() {
                next_live = live_interval - i;
                jQuery( '#event-countdown span' ).html( next_live );
                
                if( next_live == 0 ) { 
                    i=0;
                }
                
                i+=1;
            }
            
            jQuery( document ).ready( function( $ ) {
                set_latest( <?php echo $the_latest;?> );
                
                //funtion for the countdown
                countDown = setInterval( function() {
                    refreshCountDown();
                }, 1000 );
                
                // ajax calls each $duration/1000 seconds
                refreshLive = setInterval( function() {
                    live_event_get_latest( the_new, <?php echo $custom_tag_id->term_id;?>);
                }, <?php echo $duration;?> );
            } );

        </script>
        
        <!--End of the auto refresh code-->
    <?php
}
add_shortcode( 'live-event', 'imath_live_event_handle_shortcode' );

Le shortcode à ajouter à notre page se présentera ainsi [live-event ref= »slug-du-tag »]. Ainsi lorsque WordPress rencontre le shortcode live-event, il appelle la fonction imath_live_event_handle_shortcode en lui passant l’attribut ref lequel contiendra le slug de notre tag. $duration récupère le post-meta de la page « Live » permettant ainsi de nous laisser le choix de la durée de l’intervalle en millisecondes. Dans l’exemple de la vidéo, j’ai utilisé 10s (10000 millisecondes). Le query_posts() recherche tous les « live-posts » dont la taxonomy est « live-tags » et le slug la valeur de l’attribut ref.

Ajax pour rafraîchir les « live-posts » sans recharger la page.

Etrangement, je ne sais pour quelle raison, je ne suis pas parvenu à utiliser le query_posts sur une custom taxo en ajax, j’ai donc créé une requête spécifique pour approvisionner la liste des live-posts si toutefois un nouvel id a été publié

<?php
function imath_add_js_live_event() {
    //Your WordPress page must have a this title : Live
    if ( is_page( 'Live' ) ) {
        ?>
        <script type="text/javascript" >
            var the_new;

            function set_latest( val ){
                the_new=val;
            }

            function live_event_get_latest( latest, tag ) {
                if ( ! window.ajaxurl ) {
                    ajaxurl = "<?php bloginfo( 'wpurl' ); ?>/wp-admin/admin-ajax.php";
                }

                var data = {
                    action: 'imath_refresh_event',
                    the_latest: latest,
                    the_tag: tag
                };

                jQuery.post( ajaxurl , data, function( response ) {
                    html = response.split("|");
                    id   = jQuery.trim( html[0] );

                    if( id != 'nonew' ) {
                        jQuery( '#event-container #latest' ).attr( 'id','' );
                        jQuery( '#event-container' ).html( html[1]+jQuery('#event-container"').html() );
                        jQuery( '#latest' ).fadeOut();
                        jQuery( '#latest' ).fadeIn();

                        set_latest( id );
                    }
                } );
            }
        </script>
        <?php
        }
}
add_action( 'wp_head', 'imath_add_js_live_event' );

function imath_refresh_event_stream() {
    global $wpdb;

    $latest = $_POST['the_latest'];
    $tag    = $_POST['the_tag'];

    //didn't manage to make ajax requests with custom taxonomies
    $new_live_posts = $wpdb->get_row( "SELECT ID, post_date, post_title, post_content
        FROM {$wpdb->base_prefix}posts
        LEFT JOIN {$wpdb->base_prefix}term_relationships ON({$wpdb->base_prefix}posts.ID = {$wpdb->base_prefix}term_relationships.object_id)
        LEFT JOIN {$wpdb->base_prefix}term_taxonomy ON({$wpdb->base_prefix}term_relationships.term_taxonomy_id = {$wpdb->base_prefix}term_taxonomy.term_id) WHERE post_type = 'live-post' AND post_status = 'publish' AND term_id='$tag' ORDER BY post_date DESC LIMIT 1");

    if ( $new_live_posts && $new_live_posts->ID > $latest ) {
       echo $new_live_posts->ID."|"; ?>
       <div class="live-post" id="latest">
            <h5><?php echo mysql2date( "G:i", $new_live_posts->post_date, false );
                echo $new_live_posts->post_title;?></h5>
                <div class="live-content"
                    ><?php echo $new_live_posts->post_content;?>
                </div>
            </div>
            <?php
        } else {
            echo "nonew|";
        }

        die();
}
add_action('wp_ajax_imath_refresh_event', 'imath_refresh_event_stream');

Notons que pour éviter de trimballer le code partout dans le blog, il n’est chargé que si c’est la page « Live » qui est affichée. Après avoir ajouter ces deux derniers morceaux de code au functions.php, nous pouvons désormais utiliser notre outil de Live Blogging :).

Ajout de la page « Live »

Edition de la page Live

Il suffit de renseigner le titre « Live » pour cette page, d’insérer le shortcode dans l’éditeur (dans notre exemple, le slug du live-tag est « conference » et d’ajouter un post-meta « duration » dont l’intervalle de temps est exprimé en millisecondes (ici 10s).

Ensuite, pour les questions éventuelles, on peut charger le comment template dans le script page.php et autoriser les commentaires pour cette page. Si vous ne voulez pas toucher au script page.php, il suffit de le copier sous un autre nom, d’en faire un modèle de page et de l’affecter à cette page.

Il ne reste plus qu’à consommer !

Pour cela, il suffit d’ajouter un « live-post » depuis le sous menu « Ajouter » du menu Live posts de l’administration de WordPress, en n’oubliant pas de choisir le tag qui a été inséré dans le shortcode ;).

Voilà, si vous souhaitez télécharger une archive du fichier functions.php ainsi qu’un exemple de modèle de page..

15 réponses à “Live Blogging avec #WP custom post type / taxo”

  1. […] Pour réaliser cette FAQ, j’ai commencé par créer un nouveau type de contenu afin de le séparer des articles classiques (les fameux custom post types). Ensuite, j’ai ajouté un shortcode afin d’appeler facilement la FAQ depuis une page de mon choix. Ça ne vous rappelle pas quelque chose ?? […]

  2. Avatar de josemv

    Bonjour Monsieur,

    I would like to try your code live tweeting a football match (real football, not american sh*t)
    From what I can understand (I am by no means a coder) there’s a php function which inserts actual time.
    How can I change this in order to show match time (and considering each game is divided into two 45′ halves) ?

    1. Avatar de imath

      What about using a postmeta ?

  3. Avatar de Roger
    Roger

    Hi, imath. I have been looking for something similar to this and this looks wonderful. (Your other work looks very interesting as well!) I’m running into a problem though, when using your example. I can get the duration timer to count down, but the AJAX for refreshing doesn’t seem to be working and I’m not sure what I’m doing incorrectly. If I refresh the page manually, my posts are there. Will this work on WordPress 3.3.2 or even 3.4 Beta 3 or is it too outdated? Thank you for any help.

  4. Avatar de imath

    Hi @ Roger,

    Thanks for your feedback and comment.

    Just added a child theme to fix the ajax issue, i’ve built it in WP 3.4 beta 3. It should work in 3.3.2

    Check the grey box at the beginning of the post.

    Tell me if anything goes wrong 😉

  5. Avatar de Roger
    Roger

    Hi imath! Thank you so much for the quick response. I didn’t know you would actually go out of your way to edit anything. I was honestly looking for direction to find the issue myself. I’m a huge fan of learning and your tutorials here on this site are invaluable to me. I’ve learned a lot already, and I want to thank you for your contribution to the community.

    With that said, the update did not work for me right away, but it helped me spot an issue (at least on my end). On my debug.log file, it gave me 2 interesting notices:

    PHP Notice: Undefined variable: the_latest in /path/wp-content/themes/live-blogging/functions.php on line 94
    PHP Notice: Trying to get property of non-object in /path/wp-content/themes/live-blogging/functions.php on line 98

    This lead me to believe there was something wrong with the query that returns new live posts. After some editing, I got it to work. I’m not sure why what you provided for me did not work, but just in case any of your other users run into the same issue, I want to share the edit:

    http://pastebin.com/mdjWXvhT

    I thank you very much for the help, and I’m sorry to have bothered you. I love your explanations when you post new material. Please continue to do that, so that your users may also thoroughly learn WordPress/BuddyPress. You have a new reader here, for sure!

    1. Avatar de imath

      Hello Roger,

      Thanks for the fix on the query and for your comment. Unfortunately, yesterday morning i didn’t have time to check the query as i wrote it when WP version was 3.0, i think it can be optimized (since WP introduced new features in custom taxo queries in newest versions). I’ll check it soon 🙂
      You didnt bother me, i’m actually very happy you like my little contributions to the WordPress Community 😉
      Thanks for your fidelity and feedbacks.

  6. Avatar de seichan
    seichan

    Bonjour imath,
    Premièrement super script ! merci.
    Je l’ai testé sur wp version 3.3.2 et je n’ai pas été déçu, ça fonctionne bien.
    Par contre depuis j’ai fait la MAJ de wordpress (3.5.1) et le script ne fonctionne plus.
    J’ai vu que le code faisait référence à la page wp-admin/admin.php qui a depuis bien changé. Je n’y connais pas grand chose en ajax, j’ai testé de mettre dans l’entête de mon thème la même version jquery que celle de wp 3.3.2 c’est à dire la version jquery 1.7.1 et 1.7.2 mais rien à faire ! donc je ne sais pas si c’est un problème de jquery ou si cela faisait appel à quelque chose de bien particulier dans l’ancienne page admin.php.
    En vous remerciant de votre aide.

    1. Avatar de imath

      Salut Seichan,

      En haut de l’article, j’avais ajouté un child thème pour WP 3.4.1, tu l’as essayé ?
      child theme (english & français)

      1. Avatar de seichan
        seichan

        oui je l’ai testé aussi. j’ai vu dans celui-ci qu’il lançait le wp_enqueue_script(‘jquery’); , mais rien n’y fait !
        ça fonctionne pour vous sous la dernière version wp 3.5.1 ?
        Merci de votre réponse super rapide !!!!!

        1. Avatar de imath

          Le truc date un peu en même temps 🙁 Y a pas un plugin fait par WordPress sur le sujet ou dans jetpack peut être.. Je regarde et te tiens au courant pour ce tuto.
          À+

        2. Avatar de seichan
          seichan

          re,
          Oui effectivement quand j’ai vu la date des derniers commentaires j’avais un peu peur qu’il n’y ai pas de suite voir de réponse.
          Et bien j’ai pas mal chercher, dans les plugins je n’ai pas trouvé mon bonheur … là c’était bien c’était juste une page et non tout le site.
          Jetpack je ne pense pas non plus qu’il le fasse malgré sa panoplie…
          Par contre j’avais trouvé le plugin « live bogging »
          http://wordpress.org/extend/plugins/live-blogging/

          Mais ce n’est pas encore ça ! c’est un message qui apparait dans un article existant…
          En tout cas merci c’est sympa, y a pas urgence.
          Mais vous aviez un bon script là …

          1. Avatar de imath

            Salut,

            Je viens d’ajouter un child thème pour 2012. Testé sur WP 3.5.1. Il est important de rattacher les live post au tag inséré dans le shortcode et de bien définir le post meta (champ personnalisé) « duration » avec une valeur en millisecondes pour permettre à l’intervalle js de faire les requêtes ajax.
            Live Blogging 2012 child

            A+

  7. Avatar de seichan
    seichan

    Bonsoir iMath,
    Excellent !!!!!!!!!!!
    ça fonctionne ! je te remercie encore une fois de ta rapidité et pour ton travail. ça fait plaisir de tomber sur une personne réactive.

    Très bon site, et super tutos…
    @+

    1. Avatar de imath

      Hello, you’re welcome 🙂