Search

Display Dashboard Notifications alongside Menu Name for Custom Post Types

    Ashwin Parthasarathi
Listen to this article

Creating cDashboard Notification Bubbleustom post types, has it’s challenges. Well, some are easy to handle. Some are tricky. We had developed a plugin for a client, which allowed users to submit articles(custom post type), from the front end. These articles could be published, only upon admin approval. Thus, when the site admin logged on to the dashboard, he had to be notified of the number articles pending approval.

In WordPress, notification bubbles alongside the menu name, are displayed, when there are comments pending approval, or plugins in need of update, or other similar cases. In accordance to this standard, notifications for the number of custom posts pending approval, had to be displayed alongside the name of the custom post type.

[space]

The Labels for Dashboard Menus

A dashboard menu item name is contained in the field $labels[‘menu_name’]. The notification should be displayed using this field. Usually, everything contained in this field is printed as the menu label. But to dynamically display the count of posts pending approval, we need to write some HTML code. But any HTML in $labels[‘menu_name’] is removed, and the value of the field is wrapped in esc_attr.

[space]

Using the esc_attr function to Display the Count

The esc_attr function fires a filter hook attribute_escape, which can be used to calculate the count of posts pending approval. But remember, this function is a very important function and should not be messed with. It is widely used in WordPress, and is related to security. Hence we need to ensure that the changes we make are only for the admin menu, and are applied only in specific use cases.

If we identify the right menu, we can display the count. To identify the menu we wish to modify, we can use special string in the labels->menu_name of the custom post type. This has to be done, while registering the custom post type. We can use a string like %%SpecialString%%, with the name. This string acts like an identifier and a placeholder.

$mycptlabels = array(
'menu_name' => _x('My CPT %%SpecialString%%', 'My CPT label menu_name', 'mytextdomain'),
// other labels as usual …
)
$mycptargs = array( 'labels' => $mycptlabels, ... other arguments here );
register_post_type( 'mycpt', $mycptargs );

Before the esc_attr function will be called, we have to specify our own filter, instead of the default filter. We can add our filter on auth_redirect hook. The actions on auth_redirect hook are called when a user views the dashboard page.

<?php
// modify esc_attr on auth_redirect
add_action('auth_redirect', 'add_cpt_pending_approval_count_filter');
function add_cpt_pending_approval_count_filter() {
   add_filter('attribute_escape', 'display_count_cpt_posts_pending_approval', 20, 2);
}

function display_count_cpt_posts_pending_approval( $safe_text = '', $text = '' ) {
   if ( substr_count($text, '%%SpecialString%%') ) {
   // this is the menu name we want to modify
   $text = trim( str_replace('%%SpecialString%%', '', $text) );

   // once you have found the string you want to modify, no need to use the filter
   remove_filter('attribute_escape', 'display_count_cpt_posts_pending_approval', 20, 2);

   $safe_text = esc_attr($text);

   $count = (int)wp_count_posts( 'my_cpt', 'readable' )->pending;
   if ( $count > 0 ) {
      // if there are posts pending approval
      $text = esc_attr($text) . '<span>' . $count . '</span>';
      return $text;
    }
   }
   return $safe_text;
}

[space]

Upon all menu structures being displayed in the dashboard, the actions on admin_menu hook are called. Thus, using this hook, we can immediately remove the filter we applied, so that we do not affect other cases when esc_attr function is called.

// restore on admin_menu function
add_action('admin_menu','remove_cpt_pending_approval_count_filter');
function remove_cpt_pending_approval_count_filter() {
   remove_filter('attribute_escape','display_count_cpt_posts_pending_approval', 20, 2);
}

[space]

This is just one method, which allows you to add notification bubbles alongside menu names. There are several other methods you could try. Do let me know your views or questions about this approach in the comment section below.

 

Picture of Ashwin Parthasarathi

Ashwin Parthasarathi

2 Responses

  1. Hmmm…this isn’t working for me. I just get %%SpecialString%% printing in the menu. I wonder what I might be doing wrong. I added this to my custom post type labels: ‘menu_name’ => _x(‘Trouble Tickets %%SpecialString%%’, ‘Trouble Tickets label menu_name’, ‘trouble_tickets’),

    And then added all of the following to my functions.php file (sorry, I’m not seeing a way to post code here in the comments):

    //Add Pending count to custom post type //
    add_action(‘auth_redirect’, ‘add_pending_count_filter’); // modify esc_attr on auth_redirect
    add_action(‘admin_menu’, ‘esc_attr_restore’); // restore on admin_menu (very soon)

    function add_pending_count_filter() {
    add_filter(‘attribute_escape’, ‘remove_esc_attr_and_count’, 20, 2);
    }

    function esc_attr_restore() {
    remove_filter(‘attribute_escape’, ‘remove_esc_attr_and_count’, 20, 2);
    }

    function remove_esc_attr_and_count( $safe_text = ”, $text = ” ) {
    if ( substr_count($text, ‘%%PENDING_COUNT%%’) ) {
    $text = trim( str_replace(‘%%PENDING_COUNT%%’, ”, $text) );
    // run only once!
    remove_filter(‘attribute_escape’, ‘remove_esc_attr_and_count’, 20, 2);
    $safe_text = esc_attr($text);
    // remember to set the right cpt name below
    $count = (int)wp_count_posts( ‘trouble_tickets’, ‘readable’ )->pending;
    if ( $count > 0 ) {
    // we have pending, add the count
    $text = esc_attr($text) . ” . $count . ”;
    return $text;
    }
    }
    return $safe_text;
    }

    // restore on admin_menu function
    add_action(‘admin_menu’,’remove_trouble_tickets_pending_approval_count_filter’);
    function remove_trouble_tickets_pending_approval_count_filter() {
    remove_filter(‘attribute_escape’,’display_count_trouble_tickets_posts_pending_approval’, 20, 2);
    }

  2. Great post, thank you! The only thing I had to change was add styling classes to the outputted with the number.

Leave a Reply

Your email address will not be published. Required fields are marked *

Get The Latest Updates

Subscribe to our Newsletter

A key to unlock the world of open-source. We promise not to spam your inbox.

Suggested Reads

Join our 55,000+ Subscribers

    The Wisdm Digest delivers all the latest news, and resources from the world of open-source businesses to your inbox.

    Suggested Reads