Heartbeat API

Pour mettre à jour en temps réel les données d’un site on peut utiliser différentes techniques : le long polling, les Server Sent Events ou les Websockets.

Au sein de WordPress on peut utiliser l’API intitulée Heartbeat API.

J’explique ici comment ça marche à partir de tutoriels décrits ici 1 (en français) ici 2 et enfin ici 3.

Il y a aussi des exemples de code : à cet endroit, et à celui-ci.

Je cite 1.

Cette API définit un « pouls » dans WordPress, à chaque « battement » elle va collecter et exécuter les actions souhaitées par le core, le thème ou les plugins.
Plus vulgairement, il s’agit surtout d’une requête ajax dans un setInterval. On va donc y retrouver quelques similitudes avec les méthodes d’admin-ajax.

La documentation de l’API est assez pauvre (et c’est un euphémisme).

Comme l’indique le plugin https://github.com/hereswhatidid/wp-heartbeat-api-demo

On a :

Filters

  • heartbeat_nopriv_received – applied when heartbeat data is received (not logged in)
    • $response – Response sent
    • $data – Data received
    • $screen_id – ID of the screen the heartbeat occurred on
  • heartbeat_nopriv_send – applied when heartbeat data is sent (not logged in)
    • $response – Response sent
    • $screen_id – ID of the screen the heartbeat occurred on
  • heartbeat_received – applied when heartbeat data is received (logged in)
    • $response – Response sent
    • $data – Data received
    • $screen_id – ID of the screen the heartbeat occurred on
  • heartbeat_send – applied when heartbeat data is sent (logged in)
    • $response – Response sent
    • $screen_id – ID of the screen the heartbeat occurred on
  • heartbeat_settings – applied to the settings prior to being enabled
    • $settings – array – Current available settings

Actions

  • heartbeat_nopriv_tick – Occurs on front end heartbeat tick (if enabled)
    • $response – Response sent
    • $screen_id – ID of the screen the heartbeat occurred on
  • heartbeat_tick – Occurs on back end (logged in) heartbeat tick
    • $response – Response sent
    • $screen_id – ID of the screen the heartbeat occurred on

jQuery Events:

  • heartbeat-connection-lost – Connection error, has one parameter [error], contains error message information
  • heartbeat-connection-restored – Connection has been restored AFTER a connection lost error
  • heartbeat-send – Information is sent to the server, has one parameter [data] that contains the data to be sent, can be modified via the event
  • heartbeat-nonces-expired – nonces have expired
  • heartbeat-tick – Occurs only when new data has been enqueued
  • heartbeat-error

Notable jQuery Methods

  • interval( speed, ticks ) – used to get or set the interval speed.
    • speed – string – “fast”, “slow” or “long-polling”
      • fast – 5 seconds
      • slow – 60 seconds
      • long-polling – experimental, not sure what it does for now
    • ticks – integer – number of ticks before it returns to the current default pace. maximum value of 30 is accepted
    • returns – integer – the current value of the interval
  • enqueue( handle, data, dont_overwrite ) – enqueue data to be sent on the next available heartbeat
    • handle – string – unique identifier for the data. used by isQueued and by the receiving PHP
    • data – mixed – data that will be sent
    • dont_overwrite – boolean – whether or not to overwrite any data that already exists with an identical handle
    • return – boolean – whether or not the data was successfully enqueued
  • isQueued( handle ) – check if handle with data is enqueued
    • handle – string – unique ID for the data to be checked
    • return – mixed – the data matching the handle or null
  • hasConnectionError – checks if there is a connection error currently
    • return – boolean

Tutoriel

Je vais reprendre l’exemple donné en (2) .

Cet exemple, affiche toutes les minutes un alert (avec un message) dans votre panneau d’administration.

Si vous n’êtes pas connecté, rien ne se passe.

Il y a 3 parties :

  • L’envoi de données vers le serveur
  • L’envoi de données vers le client
  • L’écoute et le traitement de la réponse (du tick)

L’envoi de données vers le serveur

L’exemple donné pour l’envoi vers le serveur de la documentation WordPress est :

Cet exemple envoie des données lorsqu’on est connecté. Si on veut que ça marche lorsque l’utilisateur est déconnecté, il faut remplacer heartbeat-send par  heartbeat_nopriv_send et si on veut que ça marche dans tous les cas, on utilisera

Autre exemple (dans le plugin de test) – dans cet exemple on utilise un namespace (pulse)

Qu fait-on ? Sur l’événement heartbeat-send , on ajoute à la queue les données qu’on veut transmettre au prochain tick.

Dans cet autre exemple, on procède un peu différemment. On regarde s’il y a déjà des data dans la queue d’émission (isQueued), si oui on fait un ajout.

L’envoi de données vers le client par PHP

Quelques modifications au tutoriel sont nécessaires pour que ça marche.

D’abord il faut déclarer le plugin, ensuite il faut déclarer le script.
C’est pourquoi j’ai ajouté :

et :

D’autres (voir ici) font différemment pour l’enqueue du script. Ils passent d’abord par un register afin de récupérer un handle qu’ils utilisent ensuite dans le enqueue

est l’équivalent de :

Ce qu’il est important de noter :

  • dans le add-action, le wp_enqueue_scripts indique que le script doit être appelé dans le  front-end alors que  admin_enqueue_scripts indique un appel dans l’administration
  • le script requiert jQuery et surtout heartbeat (je ne suis pas sûr qu’il faille le préciser pour jQuery mais pour heartbeat si)

L’exemple WordPress se fait dans l’administration et l’autre est dans le front-end.

Une fois l’enqueue des scripts fait, il faut un hook sur la réception du hearbeat.

Dans l’exemple ci-dessous, soit le script JS n’a rien transmis et on ne fait rien, soit il a transmis des données et on fait un cryptage sha1 qu’on retourne.

L’écoute et le traitement de la réponse (du tick)

Le traitement est simple. Soit il y a une réponse du serveur et on l’affiche, soit il n’y a rien et on ne fait rien.
L’écoute se fait à chaque tick.

 

Le code complet est :

PHP

/* Plugin Name: JBS3 heartbeat-ajax 
Plugin URI: http://www.wp-rest-api.site 
Description: Heartbeat API test 
Version: 1 
Author: Jackie Boscher (completed by) 
Author URI: https://developer.wordpress.org/plugins/javascript/heartbeat-api/#sending-data-to-the-server */ 

/* Filter the Heartbeat data being sent to the client add_filter( string $tag, callable $function_to_add, int $priority = 10, int $accepted_args = 1 ) https://developer.wordpress.org/reference/functions/add_filter/ */ 

// Logged in users: 
// Add filter to receive hook, and specify we need 2 parameters. 
add_filter( 'heartbeat_received', 'myplugin_receive_heartbeat', 10, 2 ); 
// Logged out users 

/* ---------------------------------------------------------------------- 
NOTE - THIS PART IS NOT PRESENT IN THE WORDPRESS TUTORIAL */ 
add_filter( 'heartbeat_nopriv_received', 'myplugin_receive_heartbeat', 10, 2 ); 
/* ---------------------------------------------------------------------- */ 

/** * Receive Heartbeat data and respond. * * 
Processes data received via a Heartbeat request, and returns additional data to 
pass back to the front end. * * 
@param array $response Heartbeat response data to pass back to front end. * 
@param array $data Data received from the front end (unslashed). */ 

function myplugin_receive_heartbeat( $response, $data ) { 
// If we didn't receive our data, don't send any back. 
if ( empty( $data['myplugin_customfield'] ) ) { 
return $response; 
}
// Calculate our data and pass it back. For this example, we'll hash it. 
$received_data = $data['myplugin_customfield']; 
$response['myplugin_customfield_hashed'] = sha1( $received_data ); 
return $response; } 


/* ---------------------------------------------------------------------- 
NOTE - THIS PART IS NOT PRESENT IN THE WORDPRESS TUTORIAL */ 
/* Add an action to call our script enqueuing function */ 
/* Usage #Usage 1 wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer ); 
Links a script file to the generated page at the right time according to the script 
dependencies, if the script has not been already included and if all the dependencies 
have been registered. You could either link a script with a handle previously registered 
using the wp_register_script() function, or provide this function with all the 
parameters necessary to link a script. his is the recommended method of linking 
JavaScript to a WordPress generated page. The function should be called using 
the wp_enqueue_scripts action hook if you want to call it on the front-end of the site, 
like in the examples above. 
To call it on the administration screens, use the admin_enqueue_scripts action hook. 

For the login screen, use the login_enqueue_scripts action hook. 
https://developer.wordpress.org/reference/functions/wp_enqueue_script/ */ 

/* admin_enqueue_scripts is the first action hooked into the admin scripts actions. 
It provides a single parameter, the $hook_suffix for the current admin page. 
https://codex.wordpress.org/Plugin_API/Action_Reference/admin_enqueue_scripts */ 

// Pour l'ADMIN 
add_action( 'admin_enqueue_scripts', 'enqueue_jbs3_heartbeat_script' ); 

/* wp_enqueue_scripts is the proper hook to use when enqueuing items that are meant to 
appear on the front end. Despite the name, it is used for enqueuing both scripts and styles. 
https://codex.wordpress.org/Plugin_API/Action_Reference/wp_enqueue_scripts */ 

// Pour le FRONTEND 
/* ---------------------------------------------------------------------- 
NOTE - THIS PART IS NOT PRESENT IN THE WORDPRESS TUTORIAL */ 
add_action( 'wp_enqueue_scripts', 'enqueue_jbs3_heartbeat_script' ); 

/** * Enqueues our Heartbeat script */ 
function enqueue_jbs3_heartbeat_script() { 
/* Prepare the dependencies - our script requires jQuery and WordPress' Heartbeat scripts. */ 

$depends = array( 'jquery', 'heartbeat' ); 
/* Enqueue our script, using the dependencies we declared above */ 
wp_enqueue_script( 'jbs3-heartbeat-script', plugin_dir_url( __FILE__ ) . 'jbs3.js', $depends ); } 

javascritp

// https://developer.wordpress.org/plugins/javascript/heartbeat-api/#sending-data-to-the-server
// heartbeat_nopriv_send
// heartbeat-send


jQuery( document ).on( 'heartbeat-send', function ( event, data ) {
    // Add additional data to Heartbeat data.
    return ;
});


jQuery( document ).on( 'heartbeat-tick', function ( event, data ) {
    // Check for our data, and use it.
    if ( ! data.myplugin_customfield_hashed ) {
        return;
    }
 
    alert( 'The hash is ' + data.myplugin_customfield_hashed );
});

Suite de l’article : Heartbeat API #2