Aller au contenu | Aller au menu | Aller à la recherche

Site membre du réseau Izardev et LCNET

Ajax et les plugins Wordpress

Ajax est un protocole qui permet d'envoyer des requêtes http à partir de Javascript, si vous n'êtes pas familier avec ce protocole, vous pouvez en savoir plus sur cet article sur Ajax xmlHttpRequest. Cette article n'est pas forcément intéressant pour tous les développeurs de plugin wordpress car ils ne requièrent pas tous la technologie Ajax. Si vous en avez besoin et que vous ne maîtrisez pas cette techno, je vous invite vivement à vous documenter à ce sujet car lire cet article risque de provoquer chez vous quelques démangeaisons crâniennes ;-)

Vous pouvez donc passer à l'article suivant si Ajax ne vous intéresse pas dans le cadre du développement de votre plugin. Concernant notre plugin exemple wp_jschat, nous allons utiliser Ajax pour récupérer les messages et en envoyer : c'est beaucoup plus confortable pour les utilisateurs du chat.

2 méthodes à implémenter pour nos requêtes Ajax

  • Une méthode qui récupère les derniers messages envoyés dans la base de données,
  • Une méthode pour envoyer un nouveau message.

Nous utilisons Ajax pour ne pas avoir à recharger les pages de notre blog wordpress : Ajax est particulièrement utile à ce niveau, en terme d'accessibilité numérique, ce n'est pas idéal car un client sans Javascript ne pourra ainsi pas utiliser notre Chat (c'est à dire pas grand monde).

Récupérer les derniers messages

Cette méthode devra récupérer les derniers messages que l'utilisateur n'a pas lu, et éventuellement afficher les messages immédiatement précédents.
Elle accepte un argument $last_date et, s'il est définit, ne récupérera que les messages succédant à cette date. En revanche, si cet argument n'est pas définit ou vide, le chat renverra les 9 derniers messages. Nous avons décrit cette méthode dans le tutoriel sur l'accès aux bases de données wordpress.

/**
 * Renvoi les derniers messages du chat
 * @global wpdb $wpdb
 * @return array $messages
 */
function getLastMessages($channel = 1,$last_date = null)
{
    global $wpdb;
    $options = get_option($this->adminOptionsName);
    $excludes = preg_split('@\s*,\s*@', $options['exclude_ips']);
    if($options['enabled']!='false' && !in_array($_SERVER['REMOTE_ADDR'], $excludes))
    {
        $table_name = $wpdb->prefix.'jschat_messages';
        //print "-$last_date-";
        if($last_date==null || trim($last_date)=='')
        {
            $sql = $wpdb->prepare("SELECT * FROM $table_name WHERE canal='%s' ORDER BY created_at DESC LIMIT 0,9", $channel);
            $messages = $wpdb->get_results($sql);
        }
        else
        {
            $sql = $wpdb->prepare("SELECT * FROM $table_name WHERE UNIX_TIMESTAMP(created_at)>UNIX_TIMESTAMP('%s') AND canal='%s' ORDER BY created_at DESC LIMIT 0,9", $last_date,$channel);
            $messages = $wpdb->get_results($sql);
        }
        return $messages;
    }
    return '';
}

Appel Ajax de cette méthode

Afin de renvoyer un résultat au navigateur, nous créons une autre méthode dans notre classe wp_jschat qui va se charger d'appeler la méthode précédente et de la transmettre au navigateur pour l'affichage.

/**
 * Renvoi le résultat des messages au navigateur
 */
function ajax_getLastMessages()
{
    $options = get_option($this->adminOptionsName);
    $excludes = preg_split('@\s*,\s*@', $options['exclude_ips']);
    if($options['enabled']!='false' && !in_array($_SERVER['REMOTE_ADDR'], $excludes))
    {
        $channel = (isset($_POST['wp_jschat_channel']) && is_numeric($_POST['wp_jschat_channel']))? $_POST['wp_jschat_channel'] : 1;
        $messages = $this->getLastMessages($channel, $_POST['wp_jschat_last_date']);
        $ret = array(
            'hasResult' => (count($messages)>0),
            'result' => $messages
        );
        print json_encode($ret);
    }
    die();
}

C'est cette méthode que nous devons appeler lors de notre appel Ajax, et c'est celle qui affiche le résultat au navigateur.

Poster un nouveau message

Même principe, nous créons une méthode dans notre classe principale pour poster un nouveau message et l'insérer dans la table de notre base de données :

/**
 * Post un message sur le chat
 * @global wpdb $wpdb
 * @global user $current_user
 */
function postMessage()
{
    global $wpdb;
    global $current_user;
    $options = get_option($this->adminOptionsName);
    $excludes = preg_split('@\s*,\s*@', $options['exclude_ips']);
    if($options['enabled']!='false' && !in_array($_SERVER['REMOTE_ADDR'], $excludes))
    {
        require_once (ABSPATH . WPINC . '/pluggable.php');
        get_currentuserinfo();

        $pseudo = '';
        $user_ip = $_SERVER['REMOTE_ADDR'];

        if(isset($current_user->user_login) && !empty($current_user->user_login))
        {
            $pseudo = $current_user->user_login;
        }
        else
        {
            $options = get_option($this->userPseudoOptions);
            if(isset($options) && isset($options[$user_ip]))
                $pseudo = $options[$user_ip];
            else
            {
                $alea = rand(0,9999);
                $pseudo = 'anonym'.$alea;
                $options[$user_ip] = $pseudo;
                update_option($this->userPseudoOptions, $options);
            }
        }

        $table_name = $wpdb->prefix.'jschat_messages';
        $table_canal_name = $wpdb->prefix.'jschat_canal';
        $wp_jschat_text = $_POST['wp_jschat_text'];
        $submit = $_POST['wp_jschat_submit'];
        $query = $wpdb->prepare("SELECT * FROM $table_canal_name WHERE id='%s'",$_POST['wp_jschat_canal']);
        $canal = $wpdb->get_results($query);
        $channel = (count($canal))? $_POST['wp_jschat_canal'] : '1';

        if(isset($submit) && trim($wp_jschat_text)!='')
        {
            $wpdb->insert($table_name, array(
                'id_user' => $current_user->ID,
                'pseudo' =>  $pseudo,
                'message' => strip_tags(trim($wp_jschat_text)),
                'created_at' => current_time('mysql'),
                'canal' => $channel,
                'ip' => $_SERVER['REMOTE_ADDR']
            ));
        }
    }
    die();
}

Cette méthode ajoute simple une ligne dans la base de données, nous prenons soin d'échapper le texte écrit des chevrons que les utilisateurs maveillants pourraient ajouter, afin d'éviter l'exploitation d'une faille XSS sur notre chat (mesure de sécurité).

Toujours dans le but d'éviter le SQL Injection, nous utilisons la méthode insert() de l'objet $wpdb.

Traitement des requêtes Ajax

Lorsque notre plugin reçoit une requête Ajax, il faut la traiter, c'est l'objet de ce bout de code :

if(isset($_POST['action']))
{
    switch($_POST['action'])
    {
        case 'retrieve':
            $inst_wp_jschat->ajax_getLastMessages();
            break;
        case 'post':
            $inst_wp_jschat->postMessage();
            break;
        case 'add_channel':
            if(is_admin())
                $inst_wp_jschat->ajax_addChannel();
            break;
        case 'delete_channel':
            if(is_admin())
                $inst_wp_jschat->ajax_deleteChannel();
            break;
        default:
            break;
    }
}

Si une requête POST est transmise à cette page, nous traitons donc la demande en conséquence selon l'action demandée.

Important : Notez que nous effectuons un appel à la base de données wordpress dans ces appels Ajax via les méthodes getLastMessages() et postMessage(), cela posera un problème car la variable globale $wpdb ne sera pas accessible (Cf article sur l'accès à la base de données Wordpress), mais heureusement, les développeurs de Wordpress ont encore pensé à nous pour cette utilisation. Ce problème sera traité dans l'appel Javascript.

Appel Ajax Javascript

Nous devons effectuer notre requête sur un fichier php de notre plugin. Effectuer une requête Ajax sur notre fichier principal (ou un autre fichier de notre plugin wordpress) ne poserait pas de problème particulier si nous n'utilisions pas de variable globale Wordpress (en l'occurrence $wpdb). Or, ces variables globales wordpress ne sont pas accessibles car nos fichiers de plugin ne comportent aucune inclusion de fichiers Wordpress du tout.

C'est à cela que sert le fichier /wp-admin/admin-ajax.php, nous allons passer par ce fichier pour envoyer notre requête :

retrieveData = function()
{
    var nbre = jQuery('.wp_jschat_widget_form').length;
    var index = 1;
    jQuery('.wp_jschat_widget_form').each(function(){
        var t = jQuery(this);
        var _dateStr = t.find('.wp_jschat_last_date').val();
        jQuery.ajax({
           type: "POST",
           url:  t.find('.wp_jschat_widget_form').attr('action'),
           data: { wp_jschat_last_date: (_dateStr.trim()!='')? _dateStr : '', action : 'retrieve', wp_jschat_channel: t.find('.wp_jschat_canal').val() },
           dataType :'json',
           success: function(_data)
           {
             if(null!=_data && _data.hasResult)
             {
                for(var i=0;i<_data.result.length;i++)
                {
                    var _urlPath = t.find('.blog_url').val();
                    var bSmiles = (t.find('.hasSmileys').val()=='true');
                    var _message = _data.result[i].message;
                    if(bSmiles)
                    {
                        var oReg = new RegExp(":([a-z]+):",'g');
                        _message = _message.replace(oReg,'<img src="'+_urlPath+'/wp-includes/images/smilies/icon_$1.gif" alt="$1" />');
                    }
                    var _html = '<p><span class="author"><u>'+_data.result[i].pseudo+'</u></span> : '+_message+'</p>';
                     t.find('.wp_jschat_widget_text').append(_html);
                     t.find('.wp_jschat_widget_text').attr({scrollTop: t.find('.wp_jschat_widget_text').attr('scrollHeight')})
                     t.find('.wp_jschat_last_date').val(_data.result[i].created_at);
                }
             }
             if(nbre==index)
             {
                setTimeout(retrieveData,500);
             }
             index++;
           }
         });
        });
}

La requête n'est donc ainsi pas effectuée sur notre fichier de plugin, mais sur le fichier wp-admin/admin-ajax.php qui la transite à notre plugin.

Note : l'envoi de requête Ajax n'est pas l'objet de cet article, si vous n'êtes pas familier avec ces envois, je vous recommande la lecture d'articles à ce propos. En clair, cette fonction retrieveData :

  • gère toutes les fenêtres de chat d'un page,
  • récupère la valeur du champ caché de date,
  • envoi un requête Ajax POST (json) avec comme paramètres wp_jschat_last_date (la date) et action (le traitement à effectuer),
  • s'il y a des résultats et que la requête réussi, elle affiche les données dans le chat concerné.

Il ne reste qu'à appeler cette fonction toutes les 500ms afin que le chat soit "vivant", c'est l'objet de ce bout de code :

setTimeout(retrieveData,500);

Note : afin de ne pas envoyer plusieurs requêtes en même temps, nous utilisons setTimeout à la dernière itération de la function jQuery each().

De la même manière, nous envoyons une requête Ajax lorsqu'un message est posté dans notre formulaire :

jQuery('.wp_jschat_widget_form').submit(function(){
    var t = jQuery(this);
    var obj = {};
    obj.wp_jschat_text = t.find('.wp_jschat_text').val();
    obj.action = 'post';
    obj.wp_jschat_canal = t.find('.wp_jschat_canal').val();
    obj.wp_jschat_submit = 'true';
    jQuery.ajax({
       type: jQuery(this).attr('method'),
       url: jQuery(this).attr('action'),
       data: obj,
       success: function(){
         t.find('.wp_jschat_text').val('');
         t.find('.wp_jschat_text').focus();
       }
     });
     return false;
});

Voilà pour les requêtes Ajax dans un plugin Wordpress !

Développement d'un plugin wordpress :

  • Plugin chat Javascript pour Wordpress  

    Ce plugin de chat Javascript pour wordpress est distribué sous licence GPLv2, il est surtout développé à titre d'exemple dans le cadre d'un cours sur la création d'un plugin Wordpress.

  • Créer un plugin Wordpress 3.X  

    Créer un plugin Wordpress 3.X

  • Structure des plugins Wordpress  

    Tous les plugins wordpress seront installés dans le répertoire wp-content/plugins. Certains plugins peuvent se limiter à l'inclusion d'un seul fichier PHP, mais il est recommandé de toujours créer un dossier pour stocker les plugins....

  • Actions  

    Après avoir défini la structure de notre plugin wordpress, nous pouvons ajouter des actions, dans cet exemple, nous allons ajouter un bout de code qui va s'exécuter dans la balise <head> du blog Wordpress.

  • Filtres  

    Les filtres wordpress sont les fonctions que votre plugin peut accrocher dans le but de modifier le texte de sortie. Ce texte de sortie est généralement formaté et inséré dans une base de données, et montré à l'écran à l'utilisateur.

  • Créer le panneau d'administration d'un plugin wordpress  

    Tous les plugins devraient idéalement posséder un panneau d'administration. Créer ce panneau d'administration n'est pas très complexe, c'est donc un peu pénible de la part des auteurs de plugin de demander à leurs utilisateurs d'éditer eux-mêmes le code PHP (Ce qui n'est généralement pas une bonne idée).

  • Création d'une widget Wordpress  

    Nous allons maintenant créer une widget sous forme de plugin. Les widgets wordpress permettent d'insérer des parties de code facilement sous forme de bloc pour l'utilisateur final. Elles peuvent être ensuite ajoutées dans les barres d'outils prédéfinies selon les thèmes que vous utilisez.

  • Plugin - créer un panneau utilisateur  

    Il peut y avoir des situations où les utilisateurs peuvent être amenés à gérer leurs propres paramètres pour votre plugin : dans le cas de notre projet de chat Javascript, nous allons permettre d'une part aux utilisateur d'afficher ou non le chat, et d'utiliser les smileys ou non.

  • Installation/Désinstallation base de données | plugin Wordpress  

    Maintenant que nous savons créer des panneaux d'administration et des panneaux utilisateurs, nous allons attaquer l'accès au model : en interagissant avec la base de données. C'est une partie très importante du tutoriel wordpress, car lorsque l'on écrit un plugin, on a dans la majorité des cas besoin de stocker des données dans une base.

  • Traitement et affichage des requêtes dans base de données wordpress  

    C'est bien joli d'avoir nos tables dans base de données, maintenant, nous allons afficher les résultats de nos insertions.

  • Inclure les fichiers Javascript dans le header  

    Dans le cadre de notre application, nous aurons besoin d'inclure des fichiers Javascript dans le header des pages de notre blog Wordpress. Nous pourrions bien entendu le faire en ajoutant sauvagement du code HTML au fichier de template, mais on va éviter :)

  • Inclure les feuilles de style CSS  

    De la même manière que nous avons inclut les scripts Javascript dans le header de notre blog wordpress, nous allons maintenant inclure la feuille de style CSS de notre plugin wp_jschat. Nous allons également placer cette inclusion dans la méthode addHeaderCode() de notre classe principale créée lors de l'article sur les actions wordpress.

  • Ajax et les plugins Wordpress  

    Ajax est un protocole qui permet d'envoyer des requêtes http à partir de Javascript, si vous n'êtes pas familier avec ce protocole, vous pouvez en savoir plus sur cet article sur Ajax xmlHttpRequest.

  • Internationalisation du plugin  

    Depuis le début de cette suite d'articles, nous utilisons systématiquement les fonctions e() et __() pour afficher du texte. Nous l'avions déjà évoqué au cours d'articles précédents : c'est dans le but d'internationaliser notre plugin. Tous les textes pourrons ainsi être traduits par les utilisateurs de votre plugin dans des fichiers de langue.

  • Création de shortcode/bbcode Wordpress  

    Nous pouvons déjà créer des pages personnalisées grâce aux filtres wordpress, cependant, dans le cadre de notre plugin, il peut être intéressant d'ajouter des fenêtres de chat dans les pages de notre blog.

  • Distribuer un plugin Wordpress  

    Maintenant que votre plugin fonctionne, il a peut être vocation à être redistribué à la communauté ! Pour cela, rien de plus simple, cet article a vocation à vous expliquer comment vous y prendre.

Partagez cet article !

  • Delicious
  • Stumbleupon
  • Digg
  • Facebook
  • Google
  • Linkedin
  • Yahoo Buzz
  • Twitter
Vous avez apprécié cet article ?

Commentaires S'abonner au flux RSS des commentaires

  1. test du plugin commentaire avec ajax

Ajouter un commentaire

Les commentaires sont tous validés par un modérateur, votre commentaire n'apparaît pas directement sur le site.
Aucun support n'est assuré ici, vous pouvez néanmoins laisser vos remarques et critiques sur l'article, les points de vue pertinents sont toujours les bienvenus.