#WordPress post-format-link : comment ramener dynamiquement miniatures et données du lien

Crédits Photo links by Rigmarole, on Flickr

Ce dimanche, je me suis intéressé aux post-formats de WordPress. Introduits depuis la version 3.1, un post-format est un « morceau d’information méta » (+ précisément, une taxonomie particulière que vous retrouvez dans la table wp_terms) attaché au post qui permet à votre thème lorsqu’il le prend en charge (Je vous invite à lire cet article de Ryan Taylor à ce sujet) de personnaliser son affichage.

Il existe 9 types de post-format (ou plutôt 10 si on compte le default (ou post classique) comme un post-format 😉 ) : aside, gallery, link, image, quote, status, video, audio, chat.

En fait, je me suis concentré sur le post-format « Link ». Il permet de publier facilement des liens vers des sites externes. Si on lit le codex, le thème doit se charger d’afficher le lien en utilisant pour url externe le premier <a href= »> du contenu, ou si le contenu ne contient qu’une url alors d’utiliser celle-ci comme lien externe…

Utilisation du post format link via le thème 2011

Alors, je me suis amusé à re-tester (je l’avais fait lors de la sortie de cette fonctionnalité en 2011) l’insertion d’un lien pour voir comment, mon thème (twentyeleven) gérait son affichage.

Insertion d’une url dans l’éditeur en ayant activé le format lien.

Le souci, comme vous pourrez le constater, c’est qu’une fois publié j’ai bien un affichage particulier par mon thème (ajout de la mention LINK à la place du titre du post) mais aucune gestion de l’ajout du lien vers l’url externe :(. Il faut donc ajouter un vrai lien (<a href=’url’>) et non une simple url pour ce thème…

Affichage du post-format lien

Rendre le lien externe cliquable, ou mieux…

Dans son article, Ryan nous propose d’utiliser une méta box pour stocker l’url dans un post meta et remplacer le titre du post non pas par la mention LINK mais par le lien externe cliquable. C’est une solution intéressante mais, j’observe que sur les différents outils de partage de liens (faceboook, delicious, google+, linkedin..) lorsqu’on ajoute une url, alors sont automatiquement rapatriés titre et description de la page ainsi qu’un choix de miniatures pour illustrer ce lien.

Si vous êtes intéressé par ce dernier comportement, je vous propose de tester un plugin utilitaire pour y parvenir. Je l’ai appelé « imath-sharelinks » (je reconnais que je n’ai pas été super inspiré sur ce coup !).

Sur click du radio post-format-link, lancement de thickbox

Ce plugin ajoute un composant pour récupérer en Ajax les éléments descriptifs de l’url (titre et description de la page) et toutes les images attachées à cette url pour permettre au rédacteur de choisir l’illustration qu’il souhaite retenir pour son lien. En passant, merci à l’ API HTTP de WordPress qui comme je l’ai écrit plus tôt nous rend de grands services 😉 . Pour afficher la fenêtre modale ci-dessus, il suffit d’activer le champ radio du post-format lien. Ensuite, ajoutez votre url dans le champ et cliquer sur le bouton « Ajouter ce lien ».

Une fois les infos dispos, il ne reste plus qu’à choisir la miniature et à insérer!

Une fois les infos de l’url chargées, vous avez sur la partie gauche le sélecteur de l’image et sur la droite les metas titre et description du lien. Dés que le bouton « insérer » est cliqué, alors le contenu de l’éditeur est mis à jour des éléments retenus pour ce lien. Il ne reste plus qu’à publier.

Bye Bye Thickbox, merci pour send_to_editor !

Résultat final, téléchargement du plugin utilitaire et ouvrons le champ des possibles 🙂

Sympa non ?

Depuis le front-end, on retrouve bien le lien, les infos de la page et la miniature choisie pour l’illustrer. Pour télécharger le plugin (disponible en français et en anglais), je vous invite à cliquer sur le lien ci-après :

imath Share Links a été développé sous la 3.4 beta 3 de WordPress. Je l’ai testé avec succès sur la version 3.3.2

A la fin d’une dissertation, on conseille généralement à l’étudiant d’élargir le sujet vers d’autres perspectives.. Ainsi, après avoir conçu BP Bookmarklet, je ne peux m’empêcher de penser qu’il pourrait être intéressant de créer un bookmarklet pour gagner encore plus de temps et directement poster des liens sur notre blog tout en naviguant sur d’autres sites.. Pas vous ?

Remerciements à Casparro pour son travail sur ce script qui m’a grandement simplifié la tâche..

14 commentaires sur “#WordPress post-format-link : comment ramener dynamiquement miniatures et données du lien

  1. Again in the exact point… and again one suggestion.

    If you know the proccess to fetch any link address? why not implement for embedding links on buddypress activity update.

    Just like facebook, you insert the url on your update box and link shows as you did here!

    Good work.

  2. Hi Imath, I had been using for a long time bp activity plus, which is really a good starting point, but…

    click to link, click and erase the address field, click to insert the content and finally and the fourth click to insert the link.

    The way I say, insert text on update form, automatic fetch content, click on publish.

    Anyway another suggestion about bookmarklet, its possible to made embedded in another web to share as the tweet, pinterest or share facebook button? Its a great plugin the bookmaarklet (i tried also)

  3. Bonjour,
    Tout d’abord merci pour cette extension qui est très utile.
    Je rencontre cependant certains problème pour différents site où le formatage du code html et assez aléatoire… notamment des balises de fin > au lieu de />…
    J’ai essayé de comprendre le code de l’extension et d’y apporter des modifs, le problème pour moi se trouve dans la partie « regexp » mais je n’arrive pas à mettre la main dessus.
    Avez vous trouvez une solution pour rendre l’extension adaptable à un grand nom de site ?
    Merci.

  4. Re,

    Après différentes recherches et tests, il s’avère que j’ai à priori un problème d’encodage, les caractères avec accents et apostrophes contenus dans les balises soit title soit description ont pour effet de me renvoyer une valeur « null » pour ces champs, j’essaye différentes pistes comme htmlentities…mais pas de résultat auriez vous peut être une solution ?
    merci beaucoup.

  5. Bonjour,

    J’ai réussi ! (enfin presque…)

    Tu m’as inspiré, du coup j’ai rajouter deux lignes :

    dans la partie /title :
    $url_data[‘title’] = utf8_encode(html_entity_decode( $url_data[‘title’], ENT_QUOTES, ‘UTF-8’ ));

    et j’ai décommenté et modifier la ligne :
    $value = utf8_encode(html_entity_decode( $value, ENT_QUOTES, ‘UTF-8’ ));

    Le seul petit soucis qu’il me reste c’est que c’est bon pour un site qui est encodé en iso-8859-15 mais j’ai des caractères pas terribles quand c’est un encodage en utf-8.

    Je suis auto didacte donc je tatonne !

    Merci beaucoup pour ton aide.

  6. Quand tu auras quelques minutes, tu pourrais me dire s’il y a moyen de rendre conditionnelle le utf8_decode du style : si la page que l’on veut récupérée est en iso…. on l’applique et sinon on ne l’applique pas…

    Merci.

    1. Cool, tu as presque résolu la difficulté 🙂 Pour connaître l’encodage de la page, de la même manière qu’on récupère les metas title ou description, tu peux commencer par tester la valeur du meta charset en disant si charset != utf-8 alors utf8_encode. Bravo en tout cas et je suis très intéressé par tes adaptations !! Tu peux coller un pastebin dans un commentaire ?

  7. Bonjour je te joins le fichier avec les modifs que j’ai apporté :

    post_type==’post’) {
    ?>

    var listImages = new Array();
    var nbreImage, currentImage, imgWidth, islTbCaption, islSecondary, islPrimary, islNonce;
    islTbCaption = «  »;
    islSecondary = «  »;
    islPrimary = «  »;
    islNonce = «  »
    imgWidth = Number(«  »);

    if(!imgWidth)
    imgWidth = 100;

    jQuery(document).ready(function($){
    $(‘#post-formats-select .post-format’).click(function(){

    if( $(this).attr(‘id’) == ‘post-format-link’ ) {
    tb_show(islTbCaption, ‘#TB_inline?height=400&width=600&inlineId=null’);

    var linkForm = ‘<input type="text" id="link-value" placeholder="http://« >‘+islSecondary+’‘;

    $(« #TB_ajaxContent »).html( linkForm );
    $(« #TB_ajaxContent »).css(‘overflow’, ‘hidden’);

    }

    });

    $(‘#link-request’).live(‘click’, function(){

    $(‘#link-result’).html( »);

    imathSlAjax($(‘#link-value’).val());
    return false;
    });

    $(‘#imath_ls_next’).live(‘click’, function(){

    if( currentImage + 1 = 0 ) {
    currentImage -= 1;
    $(‘.link-image-container ul li img’).attr(‘src’, listImages[currentImage]);
    $(‘.link-image-container ul li’).attr(‘id’, ‘img-‘+currentImage);
    $(‘#imath_ls_next’).removeClass(‘imath-ls-disabled’);

    } else {
    $(this).addClass(‘imath-ls-disabled’);
    }
    return false;
    });

    $(‘#imath-ls-insert’).live(‘click’, function(){

    var win = window.dialogArguments || opener || parent || top;

    win.send_to_editor(‘‘+$(‘.link-desc’).html()+ »);

    tb_remove();
    });

    function imathSlAjax( link ) {
    var data = {
    action: ‘imath_sl_get_url’,
    url: link,
    _wpnonce:islNonce
    };

    jQuery.post(ajaxurl, data, function(response) {
    if(response.http_request_failed){
    $(‘#link-result’).html(response.http_request_failed[0]);
    return;
    }
    imgResult= »;
    nbreImage = Number( response.total_images );
    listImages = new Array();

    if( nbreImage > 0 ) {
    imgResult =  »;

    for(i = 0; i < nbreImage ; i++ ) {
    listImages.push(response.images[i]['img']);
    }
    imgResult += '’;
    currentImage = 0;
    imgResult +=  »;
    }

    htmlResult =  »+imgResult+’ ‘;
    htmlResult += ‘<a href="'+link+'" target="_blank" title=" ‘+response.title+' »>’+response.title+’‘+response.description+’‘+islPrimary+’‘;
    $(‘#link-result’).html(htmlResult);

    }, ‘json’ );
    }
    });

    array(__(‘OOops, you forgot to add the url’, ‘imath-sharelinks’) ) ) );
    die();
    }

    if (! wp_verify_nonce($_REQUEST[‘_wpnonce’], ‘imath_ls_add_link’) ) {
    echo json_encode( array(‘http_request_failed’ =>array(__(‘OOops, cheating?’, ‘imath-sharelinks’) ) ) );
    die();
    }

    $url_data = array();
    $url = $_POST[‘url’];
    $request = new WP_Http;
    $result = $request->request( $url );
    if($result->errors) {
    echo json_encode($result->errors);
    die();
    }

    $html_string = $result[‘body’];

    /* base */
    $base_override = false;
    $base_regex = ‘/]*’.’href=[« |’](.*)[« |’]/Ui’;
    preg_match_all($base_regex, $string, $base_match, PREG_PATTERN_ORDER);
    if(strlen($base_match[1][0]) > 0)
    {
    $base_url = $base_match[1][0];
    $base_override = true;
    }

    /* title */

    $title_parse = imath_sl_extract_tags( $html_string, ‘title’ );
    $url_data[‘title’] = trim( $title_parse[0][‘contents’] );
    $url_data[‘title’] = utf8_encode($url_data[‘title’]);

    /* description */
    $url_data[‘description’] =  »;
    $description_parse = imath_sl_extract_tags( $html_string, ‘meta’ );
    foreach($description_parse as $desc)
    {
    if (strtolower($desc[‘attributes’][‘name’]) == ‘description’)
    $url_data[‘description’] = trim($desc[‘attributes’][‘content’]);
    }

    /* images */
    $images_parse = imath_sl_extract_tags( $html_string, ‘img’ );
    $images = array();
    for ($i=0;$i 199 || $height > 199 )
    {
    if (
    (($width > 0 && $height > 0 && (($width / $height) .2))
    || ($width > 0 && $height == 0 && $width 0 && $height $img, « width » => $width, « height » => $height, ‘area’ => ($width * $height),’offset’ => $images_parse[$i][‘offset’]);
    }
    }

    }
    }
    $url_data[‘images’] = array_values(($images));
    $url_data[‘total_images’] = count($url_data[‘images’]);

    header(‘Cache-Control: no-cache, must-revalidate’);
    header(‘Expires: Sat, 21 Apr 2012 05:00:00 GMT’);
    header(‘Content-type: application/json’);

    echo json_encode($url_data);

    die();
    }

    /**
    * Many thanks to casparro for his script
    * http://www.redsunsoft.com/2011/01/parse-link-like-facebook-with-jquery-and-php/
    *
    */
    function imath_sl_extract_tags( $html, $tag, $selfclosing = null, $return_the_entire_tag = false, $charset = ‘UTF-8’ ){

    if ( is_array($tag) ){
    $tag = implode(‘|’, $tag);
    }

    //If the user didn’t specify if $tag is a self-closing tag we try to auto-detect it
    //by checking against a list of known self-closing tags.
    $selfclosing_tags = array( ‘img’, ‘meta’ );
    if ( is_null($selfclosing) ){
    $selfclosing = in_array( $tag, $selfclosing_tags );
    }

    //The regexp is different for normal and self-closing tags because I can’t figure out
    //how to make a sufficiently robust unified one.
    if ( $selfclosing ){
    $tag_pattern =
    ‘@<(?P’.$tag.’) # <tag
    (?Ps[^>]+)? # attributes, if any
    s*/?> # /> or just >, being lenient here
    @xsi’;
    } else {
    $tag_pattern =
    ‘@<(?P’.$tag.’) # <tag
    (?Ps[^>]+)? # attributes, if any
    s*> # >
    (?P.*?) # tag contents
    # the closing
    @xsi’;
    }

    $attribute_pattern =
    ‘@
    (?Pw+) # attribute name
    s*=s*
    (
    (?P[« ‘])(?P.*?)(?P=quote) # a quoted value
    | # or
    (?P[^s »‘]+?)(?:s+|$) # an unquoted value (terminated by whitespace or EOF)
    )
    @xsi’;

    //Find all tags
    if ( !preg_match_all($tag_pattern, $html, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE ) ){
    //Return an empty array if we didn’t find anything
    return array();
    }

    $tags = array();
    foreach ($matches as $match){

    //Parse tag attributes, if any
    $attributes = array();
    if ( !empty($match[‘attributes’][0]) ){

    if ( preg_match_all( $attribute_pattern, $match[‘attributes’][0], $attribute_data, PREG_SET_ORDER ) ){
    //Turn the attribute data into a name->value array
    foreach($attribute_data as $attr){
    if( !empty($attr[‘value_quoted’]) ){
    $value = $attr[‘value_quoted’];
    } else if( !empty($attr[‘value_unquoted’]) ){
    $value = $attr[‘value_unquoted’];
    } else {
    $value =  »;
    }

    //Passing the value through html_entity_decode is handy when you want
    //to extract link URLs or something like that. You might want to remove
    //or modify this call if it doesn’t fit your situation.

    $value = utf8_encode($value);

    $attributes[$attr[‘name’]] = $value;
    }
    }

    }

    $tag = array(
    ‘tag_name’ => $match[‘tag’][0],
    ‘offset’ => $match[0][1],
    ‘contents’ => !empty($match[‘contents’])?$match[‘contents’][0]: », //empty for self-closing tags
    ‘attributes’ => $attributes,
    );
    if ( $return_the_entire_tag ){
    $tag[‘full_tag’] = $match[0][0];
    }

    $tags[] = $tag;
    }

    return $tags;
    }

    add_action(‘admin_menu’, ‘imath_sl_options_menu’);

    function imath_sl_options_menu() {
    add_options_page(‘imath SL Options’, ‘imath SL Options’, ‘manage_options’, ‘imath-sl’, ‘imath_sl_settings’);
    }

    function imath_sl_settings() {

    if( $_POST[‘imath_ls_save_option’] ) {
    if($_POST[‘imath_ls_img_width’]) {
    $img_width = intval($_POST[‘imath_ls_img_width’]);
    update_option(‘_imath_ls_img_width’, $img_width );
    }
    }

    $img_width = get_option(‘_imath_ls_img_width’);

    ?>

    <input type="text" name="imath_ls_img_width" id="imath_ls_img_width" value=" »/>

    <input type="submit" value=" » name= »imath_ls_save_option » class= »button-primary »>

  8. Merci pour ce superbe article. J’ai une question : Est-il possible d’utiliser ton plugin en frontend ? C’est-à dire permettre aux utilisateurs de mon blog depuis un formulaire frontend de coller un lien et d’avoir le résultat obtenu avec ton plugin ? j’ai besoin d’une réponse. C’est vraiment urgent ! Merci

    1. Je crois que cet article date un peu donc je ne recommande pas trop. J’avais amélioré le système pour les activités de BuddyPress avec BP Bookmarklet.

Les commentaires sont fermés.