Web Development by Solarise

The Solarise.dev Blog

Adding content above and below the WordPress wp-admin `All Posts` table

Blog archive Robin Metcalfe 29th November 2017

A recent project I worked on required an extension to the WordPress ‘All Posts’ index listings page to display small amounts of content above and below the default table view.

New administration headings within the dashboard for WordPress
Here’s what we’re trying to achieve. Notice the new notification boxes above and below the standard ‘All Posts’ index listing.

But, as I outlined in an earlier post, WordPress doesn’t offer much in the way of customisation hooks when it comes to the layout and appearance of the admin index pages (as opposed to the post edit pages, which offer a lot of customisation potential)

To get around this, I had to get a little more technical and make use of a Javascript-based solution. Definitely not ideal, but since we cannot make any adjustments to the core administration files, that’s pretty much all we can do.

If you want to skip to the chase, you can grab the plugin files by clicking on the button below. There’s some additional configuration required, which is outlined at the end of this article.

Download Plugin .zip

Note: This will allow for content panels to appear for users with javascript enabled. Non-javascript users will not see this content, however, so don’t rely on it for any mission critical dialogs. Instead, it may be utilised to present content which complements the standard admin view.

The Javascript solution

The javascript for this is relatively straightforward. I decided to hook onto two seperate elements, the "status" bar at the top (which reads something like All (2) | Published (2) which I’ll place content before and the .tablenav.bottom element, which is a decent hook to place some content after.

The code is inserted directly into the <head> element of the admin pages, typically the simplest way of adding extra scripting/styling to the administration area.

This ends up reading a little something like this:

var aboveContainer = document.createElement("div");
var belowContainer = document.createElement("div");

aboveContainer.classList.add('custom-admin-table-content', 'above');
belowContainer.classList.add('custom-admin-table-content', 'below');

// These templates are generated from the output of the PHP template files, placed earlier in the <head> output
var aboveTemplate = document.querySelector('template[name=above]');
var belowTemplate = document.querySelector('template[name=below]');

// If the templates exist, apply their contents to the new
// container elements
if(aboveTemplate) {
    aboveContainer.innerHTML = aboveTemplate.innerHTML;
}

if(belowTemplate) {
    belowContainer.innerHTML = belowTemplate.innerHTML;
}

// Insert a 0 timeout to cater for initial JS initialization
setTimeout(function(){

    if(aboveTemplate) {
        // .subsubsub is the class of the container holding the All(123) | Published(2) | Trash(5) status
        var targetAbove = document.querySelector(".subsubsub");                     
        if(targetAbove) {
            // Insert the "above" container just before .subsubsub
            targetAbove.parentNode.insertBefore(aboveContainer, targetAbove.previousSibling);
        }
    }

    if(belowTemplate) {
        // We'll plop the belowContainer right after the bottom navigation element
        // of the table
        var targetBelow = document.querySelector('.tablenav.bottom');
        if(targetBelow) {
            targetBelow.parentNode.appendChild(belowContainer);
        }
    }

}, 0)

Freestylin’

Because we’re adding some custom containers, I applied some additional styling rules. Again, these have been dropped straight into the admin <head> via the admin_head hook.

<style>
    .custom-admin-table-content {
        border: 1px solid #e1e1e1;
        color: #32373c;
        background: #FFF;
        border-left: 4px solid #888;
        padding: 0 12px;
    }
    /* for the situation where there are no additional
       notification boxes above */
    .wp-header-end + .custom-admin-table-content {
        margin-top: 1em;
    }
    .custom-admin-table-content p {
        margin: 0.5em 0;
        padding: 2px;
    }
    .custom-admin-table-content.below {
        margin-top: 1em;
    }
</style>

I’ve added a below and above class to each respective container, so you can adjust the styles as you see fit.

Defining the content

I wanted to create a robust solution, so I allowed for the content to be defined within PHP files located inside the currently active theme directory. That way, you can apply any content changes directly to your template files, and keep everything safely tucked away in version control.

To define the content, I’ve set up this code so that you can create files inside a /admin-above-below directory within your theme. Inside this folder, place the files post-admin-above.php and post-admin-below.php

Here’s a couple of sample files you can make use of initially:

Above the table

I’ve put a couple of bits of functionality in here,

  1. Grab the current user’s name, and give them a nice little welcome.
  2. Locate all posts by the current user. If they’ve already made some posts, let them know when their last post was added, and prompt them to add another. If not, just ask them to make a new one.

Extra content above the table

{your_theme_folder}/above-below-admin-tables/post-above-all.php

// Get the logged in user's user name
$user = wp_get_current_user();
$name = $user->data->display_name;

$post_type = isset($_GET['post_type']) ? $_GET['post_type'] : 'post';

// Check to see what posts this user has written
$args = array(
    'author' => $user->ID, // I could also use $user_ID, right?
    'orderby' => 'post_date',
    'post_type' => $post_type,
    'order' => 'DESC',
    'numberposts' => 1
);

$posts = get_posts($args);

// Show a different message depending on whether they've already contributed or not
if($posts):
    $editMessage = sprintf("Welcome back! Your last post was <a href='%s'>%s</a>, created %s ago",
                                get_edit_post_link($posts[0]->ID),
                                $posts[0]->post_title,
                                human_time_diff(time(), strtotime($posts[0]->post_date)));
else:
    $editMessage = "Get started by creating a <a href=''>new post</a>";
endif;

printf("<p>Hi, %s. %s</p>", $name, $editMessage);

Below the table

Underneath the posts table, a snippet of code that lets the user know how many revisions have been made in the last 7 days. Useful? Not useful? Who can say. But there we go.

Extra content below the table

{your_theme_folder}/above-below-admin-tables/post-below-all.php

$post_type = isset($_GET['post_type']) ? $_GET['post_type'] : 'post';

global $wpdb;

// Returns all 'revision' posts within the last 7 days of a given post type
$sql = <<<SQL
    SELECT DISTINCT P0.ID, P1.post_type FROM
    {$wpdb->prefix}posts as P0
    LEFT JOIN {$wpdb->prefix}posts as P1 ON (P0.post_parent = P1.ID)
    WHERE P0.post_type = 'revision'
    AND P1.post_type = '%s'
    AND P1.post_name NOT LIKE '%-autosave-%'
    AND P1.post_status != 'trash'
    AND P0.post_modified >= DATE(NOW()) - INTERVAL 7 DAY
SQL;

$results = $wpdb->get_results($wpdb->prepare($sql, $post_type));

$count = sizeof($results);

printf("<p>There have been <b>%d %s</b> in the past 7 days</p>", $count, $count == 1 ? 'revision' : 'revisions');

Download the plugin

Here’s the code in all its glory. I’ve encased it within a plugin, so you can install it directly via the WordPress plugins panel, or grab the code straight from the files and add to your functions.php

There’s some additional code to check what the current screen is, display the containers only for the specific post types as defined by the filenames of your content files within the above-and-below-admin-tables folder and some other minor tweaks.

There are two content files already defined within the plugin folder. You can use these by copying them into the {your_theme_folder}/above-below-admin-tables/ folder.

Download Plugin .zip

Installation

  1. Copy the folder within the .zip archive into your /plugins folder, then activate via the WordPress admin Plugins page.
  2. To set up the initial themes, copy the template files from within the plugin’s /templates directory and place them within a folder named above-below-admin-tables in your theme directory
  3. To create additional content boxes for other custom post types, use the filname format {$post_name}-above-all.php and {$post_name}-below-all.php
Author Image

About the author

Robin is the dedicated developer behind Solarise.dev. With years of experience in web development, he's committed to delivering high-quality solutions and ensuring websites run smoothly. Always eager to learn and adapt to the ever-changing digital landscape, Robin believes in the power of collaboration and sharing knowledge. Outside of coding, he enjoys diving into tech news and exploring new tools in the industry.

If you'd like to get in touch to discuss a project, or if you'd just like to ask a question, fill in the form below.

Get in touch

Send me a message and I'll get back to you as soon as possible. Ask me about anything - web development, project proposals or just say hi!

Please enable JavaScript in your browser to complete this form.

Solarise.dev Services

Maintenance Retainers

Min 3 hours per month, no contract

Project Planning

Get in touch to discuss your project details

Consultancy

Face-to-face chats. Solve your problems!