How to Allow Subscribers to Delete Posts from the Front End while Still Blocking the Admin Area

Let’s say you want to allow users to delete posts from the front end. That’s doable via a built in WordPress function get_delete_post_link();.

The code to do that might look something like this:

<?php if ($current_user->user_login == $author_name) { ?>
<a onclick="return confirm('Are you SURE you want to delete this post?')" href="<?php echo get_delete_post_link( $post->ID ) ?>">Delete Post</a>
<?php } ?>

That code first checks to see if the current logged in user is also the current post’s author. If they are, show the link to delete the post.

Now let’s say you’re allowing Subscribers to be post authors. Maybe you’re using Gravity Forms to allow any logged in user–even Subscribers–to be the author of a post, or maybe you’ve altered Subscribers capabilities in another way, and therefore they can be the author of a post. Note that “author” in this case is the WordPress user that a post is assigned to, as opposed to the actual “Author” role.

Now you want these subscribers to be able to delete their own posts, too. You could use a plugin to edit subscriber’s roles, or add the following to your functions.php:

function add_subscriber_delete_cap() {
$role = get_role( 'subscriber' );
$role->add_cap( 'delete_posts' );
$role->add_cap( 'delete_published_posts' );
$role->add_cap( 'delete_pages' );
$role->add_cap( 'delete_published_pages' );
}
add_action( 'admin_init', 'add_subscriber_delete_cap');

If you’re just dealing with Posts, you could delete the $role->add_cap( 'delete_pages' ); and $role->add_cap( 'delete_published_pages' ); lines, and vice versa. If you’re dealing with Custom Post Types, you need to look at the 'capability_type' that is set when you create your custom post type, it should be set to either post or page. Whatever it’s set to, that’s the add_cap() functionality you want.

Once everything above is setup, subscribers can visit the single post page of their own posts and delete posts to which they are assigned as the author.

However, this also expands their capability in WP-Admin. Normally, we could block access to WP-Admin with something like this:

add_action( 'init', 'blockusers_init' );
function blockusers_init() {
if ( is_admin() && ! current_user_can( 'administrator' ) &&
! ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
wp_redirect( home_url() );
exit;
}
}

That prevents anyone but Administrators from accessing the admin area. However, this will also break our get_delete_post_link(); functionality, because that code simply creates a link to the admin area.

If subscribers can’t access the admin, they can’t initiate that link.

So here’s how to get around it (note that you should not use that blockusers_init code above, it was just for reference.

Instead, my work around is to:

  1. Inject some CSS into the Admin area to hide everything from non-admins.
  2. Inject some Javascript to redirect non-admins back to the front end of the site.

First, our CSS. We add this to our functions.php file:

// Add CSS to hide everything in the admin while the JS above does it's trick
add_action('admin_head', 'hide_admin_via_css');
function hide_admin_via_css() {
if (!current_user_can( 'manage_options' )) {
echo '<style>body * {visibility:hidden !important;} body:before {content:"Give it a second...";}

';
}
}

That adds a style tag to the head of every page of the admin area, rendering every element within the <body> tag invisible, and then adding a little message “Give it a second…” to the page. Customize as you see fit, but the point of this is to prevent users from seeing anything in the admin while we let Javascript do it’s trick.

For the JS, add this to functions.php:

// Add Javascript to redirect anyone but administrators out of the admin area after 10 seconds
function my_enqueue( $hook ) {
if (!current_user_can( 'manage_options' )) {
wp_enqueue_script( 'my_custom_script', '/wp-content/themes/your-theme/block-admin.js' );
}
}
add_action('admin_enqueue_scripts', 'my_enqueue');

You can customize the path on the wp_enqueue_script line to point anywhere you’d like, but make sure you also create the actual block-admin.js file in that location, then add this to that file:

setTimeout(function () {
window.location.href = "/"; //will redirect to your homepage, or you could change this to any other page you'd like
}, 2000); //will call the function after 2 secs.

Theoretically you could also just have window.location.href = "/"; in that file and Javascript should redirect as soon as that file loads.

There you have it!

Improvements or suggestions are welcome, just drop them into the comments!

Up Next: How to Create Plain Text Email Notifications with Gravity Forms