Skip Navigation

[Resolved] Delete post attachments when deleting post with cred_delete_post_link

This thread is resolved. Here is a description of the problem and solution.

Problem: I am using cred_delete_post_link to delete posts on the front-end of the site. I would like to delete all the images attached to the post as well, including the featured image and posts added to post content.

Solution: You can use some custom code to delete the attachments:

function delete_post_children($post_id) {
  global $wpdb;
  if ( get_post_type( $post_id ) == 'bag' ) {
    $ids = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE post_parent = $post_id AND post_type = 'attachment'");
    foreach ( $ids as $id ) {
        wp_delete_attachment($id, true);
    }
    if(has_post_thumbnail( $post_id )) {
      $tn_id = get_post_thumbnail_id( $post_id );
      wp_delete_attachment($tn_id, true);
    }
  }
}
add_action('before_delete_post', 'delete_post_children');

Relevant Documentation:
https://developer.wordpress.org/reference/functions/wp_delete_attachment/
https://codex.wordpress.org/Plugin_API/Action_Reference/before_delete_post

This support ticket is created 5 years, 9 months ago. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Sun Mon Tue Wed Thu Fri Sat
8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 - -
13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 - -

Supporter timezone: America/New_York (GMT-04:00)

This topic contains 7 replies, has 2 voices.

Last updated by diyanK 5 years, 9 months ago.

Assisted by: Christian Cox.

Author
Posts
#1209963

Hi guys,

I would like to address this topic once again as this is an essential part of many of the projects I develop and is a general issue I have on all of my projects.

I build membership sites and all of them include a custom user role that can create a custom post type via CRED forms on the front end. However the general issue that is preventing me to grow my projects is proper file management. I can not risk creating a mess on the server by opening my projects to thousands of users without setting up proper post attachment management. My general issue is not being able to clean-up old files when deleting outdated posts.

Here is what I do:

First I add a function that will separate every user's uploads in his own folder on the server, it looks like this:

/* PER USER UPLOAD DIR FUNCTION */
function per_user_upload_dir( $original ){
    // use the original array for initial setup
    $modified = $original;
    // set our own replacements
    if ( is_user_logged_in() ) {
        $current_user = wp_get_current_user();
        $subdir = $current_user->user_login;
        $modified['subdir'] = $subdir;
        $modified['url'] = $original['baseurl'] . '/' . $subdir;
        $modified['path'] = $original['basedir'] . DIRECTORY_SEPARATOR . $subdir;
    }
    return $modified;
}
add_filter( 'upload_dir', 'per_user_upload_dir');

Then with the help of this snippet I can easily keep track of how files move when creating and deleting a post.

I used this snippet from another support ticket that would address file attachments removal upon post deletion.

/* DELETE POST Attachments / CHILDREN / and Featured Image too */
function delete_post_children($post_id) {
global $wpdb;
global $post_type;   
    if ( $post_type == 'bag' ) {
		$ids = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE post_parent = $post_id AND post_type = 'attachment'");
		foreach ( $ids as $id )
			wp_delete_attachment($id);
		}		
	}
add_action('delete_post', 'delete_post_children'); 

HOWEVER it does not seem to do the job and my files remain on the server

I have found another snippet from a third party source that seems to successfully delete the "featured image" file, but it does not look for other post attachments, so these are left behind on the server..

add_action( 'before_delete_post', 'wps_remove_attachment_with_post', 10 );
function wps_remove_attachment_with_post($post_id)
{
    if(has_post_thumbnail( $post_id ))
        {
      $attachment_id = get_post_thumbnail_id( $post_id );
      wp_delete_attachment($attachment_id, true);
    }
}

So here is my request:
Could I get a working snippet that will both look for featured images as well as other post attachments and delete everything altogether. If we can limit this to work only on a specific post type (like the first snipped tried to do) that'd be awesome!

Thanks, if we can get this sorted out this will be major breakthrough for my projects as this has been a major show stopper.

PS. I miss the "formatting instructions" when starting a new ticket, we have it in the reply form but not when we open a new ticket.

#1210177

Try this updated snippet, it should delete attached images and featured images too:

/* DELETE POST Attachments / CHILDREN / and Featured Image too */
function delete_post_children($post_id) {
global $wpdb;
global $post_type;   
if ( $post_type == 'bag' ) {
  $ids = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE post_parent = $post_id AND post_type = 'attachment'");
  foreach ( $ids as $id ) {
      wp_delete_attachment($id, true);
  }
  if(has_post_thumbnail( $post_id )) {
    $tn_id = get_post_thumbnail_id( $post_id );
    wp_delete_attachment($tn_id, true);
  }
}
}
add_action('before_delete_post', 'delete_post_children');
#1210203

I am testing it.

PS. It was missing an "}", I put it at the end.. hope it is correct.

#1210211

Nope, it does nothing.. now both files(featured and attachment) were left behind on the server.

Note the missing "}" which I added at the end, maybe it needs to go somewhere else?
If I don't add it I got an "unexpected end of file.." error.

I tried adding it before and after the last line #15 in your code snippet.
Still nothing.

#1210268

You're right, the missing parenthesis should go before line 15. After I make that change, this code is working for me (for posts, not bags):

function delete_post_children($post_id) {
  global $wpdb;
  global $post_type;
  if ( $post_type == 'post' ) {
    $ids = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE post_parent = $post_id AND post_type = 'attachment'");
    foreach ( $ids as $id ) {
        wp_delete_attachment($id, true);
    }
    if(has_post_thumbnail( $post_id )) {
      $tn_id = get_post_thumbnail_id( $post_id );
      wp_delete_attachment($tn_id, true);
    }
  }
}
add_action('before_delete_post', 'delete_post_children');

How are you deleting the posts? Are you sending an individual post to the trash, then deleting it permanently? Or bulk-trashing several posts at the same time, or some other delete process?

#1210277

Still not working.

I am using this for my post type with a post type slug = "bag".

I am deleting my "bags" via the front-end as a user with the help of this:

[wpv-if evaluate="'[wpv-current-user info='id']' = '[wpv-post-author format='meta' meta='ID']' OR '[wpv-current-user info='role']' = 'administrator'"]
.....
[cred_delete_post_link class='cred-refresh-after-delete' text='Delete' message='Are you sure?' message_show='1' action='delete']
[/wpv-if]
#1210279

Okay to work with the cred_delete_post_link shortcode you'll have to make a small adjustment, since the global $post_type isn't necessarily going to match. Here's the update:

function delete_post_children($post_id) {
  global $wpdb;
  if ( get_post_type( $post_id ) == 'bag' ) {
    $ids = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE post_parent = $post_id AND post_type = 'attachment'");
    foreach ( $ids as $id ) {
        wp_delete_attachment($id, true);
    }
    if(has_post_thumbnail( $post_id )) {
      $tn_id = get_post_thumbnail_id( $post_id );
      wp_delete_attachment($tn_id, true);
    }
  }
}
add_action('before_delete_post', 'delete_post_children');
#1210280

WOW, Finally - It works!!

Thanks Christian! Once again you did an awesome job at helping with this.

I hope this will be helpful for others seeking to do proper file management for custom post types.

P.S. This one has been a pain for more than a year now. Finally the time has come and my hosting INODE count will not go crazy over a hundred or even thousand active users!!