Tout savoir sur WordPress

Afficher une bulle notification pour les articles en attente de relecture

Cette astuce va vous permettre d’ajouter une notification à côté du menu Article pour afficher les articles en attente de publication.

Aujourd’hui, je vous propose une astuce qui va vous permettre d’afficher une bulle de notification sur le menu “Articles” avec le nombre d’articles en attente de relecture. Cette bulle est celle utilisée pour les alertes de mise à jour des extensions ou du nombre de commentaires en attente.

Pour les besoins de l’exemple, j’opte pour des articles qui ont le statut pending, mais l’astuce fonctionne également avec tous les autres statuts (une liste de tous les statuts des articles), c’est à vous de choisir !

Copier le code ci-dessous dans le fichier functions.php présent à la racine de votre thème :

add_action('admin_head', 'add_notification_post_pending');
function add_notification_post_pending() {

    global $menu;

    if(current_user_can('publish_posts')) {

	$count = get_transient('notifition_posts_pending');

	if( false === $count ) {
	    $args = array(
                 'post_type' => 'post',
		 'post_status' => 'pending'
	    );

   	    $query = new WP_Query($args);
	    $count = count($query);
	    set_transient('notifition_posts_pending', count( $query->posts ));
	}

	if( $count >= 1 ) {

	    $bubble = '' . $count . '';
	    $menu[5][0] = __('Posts') . $bubble;

	}
    }
}

add_action('transition_post_status', 'update_cache_notification_post_pending', 10, 3);
function update_cache_notification_post_pending( $new_status, $old_status, $post ) {

    if( $post->post_type == 'post' && ( $new_status=='pending' || $old_status=='pending' ) ) {

	$args = array(
	        'post_type' =>'post',
	        'post_status' => 'pending'
	    );

   	$query = new WP_Query($args);
	set_transient('notifition_posts_pending', count( $query->posts ));
    }
}

add_action('deleted_post', 'update_cache_notification_post_pending_delete', 10, 0 );
function update_cache_notification_post_pending_delete() {
	
    $args = array(
	'post_type' => 'post',
	'post_status' => 'pending'
    );
    $query = new WP_Query( $args );
    set_transient( 'notifition_posts_pending', count( $query->posts ) );
}

Le code peut paraître long, mais il permet de mettre en cache le nombre d’articles en attente de relecture et d’éviter de faire une requête à chaque changement de page dans l’administration.

Rendu final :

Aperçu de la bulle de notification du menu "Articles"

Cet article a été publié il y a 4556 jours - Il n'est peut être plus à jour !

Article écrit par Jean-David

10 Commentaires

  1. Hello, le premier “$args” est déclaré pour rien, on peux donc le supprimer.
    Aussi, tu utilises le hook “save_post” qui va relancer la requête pour calculer le nombre de post en pending, mais si je viens de créer un post et que je le publie, il n’est pas pending, pourquoi donc recompter !?
    Je te propose plutôt de ne mettre à jour que pour les post en pending avec le hook “pending_post”.
    Sinon l’idée est bien sympa, c’est tuojours bien pour des sites qui ont des contributeurs de pouvoir voir sans aucun clic et discrètement ce genre d’informations.

  2. @Julio : oups pour $args. Code à jour.

    Par contre, je ne suis pas convaincu par pending_post. D’après le code, cela correspond à “Calls ‘{$new_status}_{$post->post_type}’ on post ID and $post.”

    Donc si on utilise pending_post, le compte ne sera pas bon si par exemple on passe de pending à publish puisque la valeur $new_status sera publish. Du coup, le compte ne sera pas à jour.

  3. Ha mais suis je bête …
    Alors il faut utiliser ‘transition_post_status’ et faire comme ceci :

    add_action('transition_post_status', 'update_cache_notification_post_pending', 10, 3);
    function update_cache_notification_post_pending( $new_status, $old_status, $post ) {
    	if( $post->post_type == 'post' && ( $new_status=='pending' || $old_status=='pending' ) ) {
    
    		$args = array(
    	        'post_type' =>'post',
    	        'post_status' => 'pending'
    	    );
    
       		$query = new WP_Query($args);
    		set_transient('notifition_posts_pending', count( $query->posts ));
    	}
    }
    

    merci Jonathan, très pro :)

  4. J’ai oublié, si on supprime un article en attente, le compteur ne change pas, ni dans le code de Jean-David, ni dans le mien, il faut aussi ajouter une fonction sur les hooks suivant ‘deleted_post’ (véritable suppression) et ‘trashed_post’ (mise en corbeille), voici le code:

    function update_cache_notification_post_pending_delete()
    {
    	$args = array(
    		'post_type' => 'post',
    		'post_status' => 'pending'
    	);
    	$query = new WP_Query( $args );
    	set_transient( 'notifition_posts_pending', count( $query->posts ) );
    }
    

    Cette fois, même si on supprime un article dont le statut n’est pas “pending”, on refait la requête mais pas le choix, me trompe-je ?

  5. J’ai oublié les hooks :
    add_action( ‘deleted_post’, ‘update_cache_notification_post_pending_delete’, 10, 0 );
    add_action( ‘trashed_post’, ‘update_cache_notification_post_pending_delete’, 10, 0 );

  6. Merci Julio.

    Par contre, comme on en a parlé en privé, trashed_post n’est pas nécessaire dans notre cas puisque l’on modifie le statut de l’article.

  7. Tu as raison, en pensant à la suppression, j’ai été trop loin ^^ Merci !

  8. Bonjour tout le monde,

    J’ai tenté d’adapter ce code à des CPT mais je n’ai pas trouvé la solution qui fonctionne.

    J’ai bien adapté le “$menu[5][0]” ainsi que les différents post_type mais j’ai du oublier de modifier une variable sur la route… Au passage, si on pourrait le faire pour plusieurs CPT dans la même fonction (qui se répercute sur les différents CPT), cela serait génial.

    Si vous avez la solution, je prend ;-)

  9. Bonjour,

    J’ai voulu mettre en pratique cette astuce sur un WordPress 3.8.1, mais j’ai rencontré un soucis. Je ne sais pas si cela vient de différences entre la version de WP utilisée dans ce tutoriel et la 3.8.1, mais voilà comment je l’ai résolu :

    Ligne 17, il faut remplacer :
    $count = count($query);

    Par :
    $count = count($query->posts);

    Car sinon $count vaut toujours au moins 1 (vu qu’on compte le nombre de requêtes au lieu de compter le nombre de résultats).