Hi guys, some time ago I submitted another similar request which was fulfilled, and now I would like to expand on it:
First, here is the original one: https://toolset.com/forums/topic/proper-post-attachment-management-via-cred/
(here I wanted to delete all files attached to the post being deleted thus not leaving anything on the server behind)
The original solution still works perfectly, however I am missing a function now that I have expanded the functionality of my project and here is where the issue lies:
Now that I am having users register their profile the on platform, then they can add multiple products to their profiles .(*profiles* and *products* being custom post types with a parent>child relationship).
However when the user deletes their profile the system will delete the parent item and all it's file attachments but will break the parent>child relationship and leave the child products with their attachments behind leaving my server clogged and database full of products that don't have parents.
What I expect to happen:
I expect once the user deletes any parent post item the system would have the ability to delete the associated child posts and their associated file attachments from the server too.
Can you help with this?
Thanks!
Diyan
Hello, it sounds like you need to add some code that handles the deletion process for products and profiles, queries the related product posts of each deleted profile, and deletes the related product and its attachments as well. A modification like this:
function delete_post_children($post_id) {
global $wpdb;
$post_type = get_post_type( $post_id );
if ( $post_type == 'bag' || $post_type == 'product' || $post_type == 'profile') {
$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);
}
if( $post_type == 'profile' ) {
// in this case, we want to force-delete the child product posts as well
$profile_products = toolset_get_related_posts(
$post_id,
'profile-products-relationship-slug',
[
'query_by_role' => 'parent',
'role_to_return' => 'child',
'limit' => 10000,
'orderby' => null,
]
);
foreach($profile_products as $profile_product ) {
wp_delete_post( $profile_product, true );
}
}
}
}
add_action('before_delete_post', 'delete_post_children');
You may need to replace the post type slugs 'product' and 'profile' in the if statement:
if ( $post_type == 'bag' || $post_type == 'product' || $post_type == 'profile') {
...as well as this if statement:
if( $post_type == 'profile' ) {
...as well as the post relationship slugprofile-products-relationship-slug, to match the actual relationship slug. Note that this code will force-delete the product posts, not just trash them. Let me know if you have questions about this.
Hi Chris,
Okay, first this is on hidden link (it is running a copy of the same code here, just no "bags" post type).
I have Users that get registered either via email or login with fb(email again).
Once they login they create profiles. They can have more than one profile.
For each profile they add products.
Here is my code:
function delete_post_children($post_id) {
global $wpdb;
$post_type = get_post_type( $post_id );
if ( $post_type == 'products' || $post_type == 'profile') {
$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);
}
if( $post_type == 'profile' ) {
// in this case, we want to force-delete the child product posts as well
$profile_products = toolset_get_related_posts(
$post_id,
'profile-product',
[
'query_by_role' => 'parent',
'role_to_return' => 'child',
'limit' => 10000,
'orderby' => null,
]
);
foreach($profile_products as $profile_product ) {
wp_delete_post( $profile_product, true );
}
}
}
}
add_action('before_delete_post', 'delete_post_children');
Note: slugs go as follows: "profile", "products", and "profile-product" for the relationship.
Unfortunately the way I got it seems to fail for now, any idea what am I missing?
Thanks!
Diyan
The updates seem to be correct at first glance. May I log in and take a look in wp-admin? Please let me know where you added this code, if it is in functions.php or in a custom code snippet somewhere.
Okay let me run some tests locally to see what the problem could be. I will give you an update shortly.
It turns out the toolset_get_related_posts API does not allow you to query for related posts of Trashed posts. I've asked my developers if there is a workaround for this problem, and I'll let you know what I find out. If you'd like to perform this action when trashing a post instead of deleting a post, there may be another option. However, the child posts would be deleted if a parent post was mistakenly trashed. This seems like a bad idea to me, but I thought I would ask for your opinion.
My goal is to allow users delete their own profiles(not trash them) via front-end.
[cred-delete-post action='trash' onsuccess='14' style="background: red; color:white; border-radius: 4px; padding: 7px 12px;"]Изтрий този Профил[/cred-delete-post]
Maybe I got this action wrong here. .. let me test with delete.
D.
One workaround would be to replace the cred-delete-post shortcode with the shortcode for a cred edit form that edits the parent Profile post. Remove all the visible inputs from the edit Form except the submit button, include a generic hidden field with a value like 'delete-profile', and change the text of the submit button to be "Delete Profile". Then you could trigger these Product post delete actions with the cred_save_data hook, in a conditional based on the value of the generic hidden field. Since the Profile post status would not be 'trash' yet, the post relationships api should be able to query the child posts. Then after deleting the Product posts, you could delete the Profile post in the same cred_save_data hook.
Your thoughts on this workaround? It might help bridge the gap until our developers can provide more feedback.
Chris, this got fixed once I changed the action to "delete" on my button. Product got deleted, product photo got deleted from the server too.
So maybe your code works after all?
D.
OK great, yes I assume since the status of the post never goes to 'trash', the problem does not occur. That's good to know - I'll keep this in mind for future tickets. Thanks for the update.
For future reference, a filter is available to allow 'trash' status posts to be both included in the response of, and queried by, the toolset_get_related_posts API. The filter can be added like so:
add_filter( 'toolset_accepted_post_statuses_for_api', static function( $accepted_post_statuses ) {
if ( is_array( $accepted_post_statuses ) ) {
$accepted_post_statuses[] = 'trash';
}
return $accepted_post_statuses;
} );
Then in the API arguments section, you can include 'trash' as one of the acceptable post_status values:
$parent_ids = toolset_get_related_posts(
123,
'book-chapter',
[
'query_by_role' => 'child',
'role_to_return' => 'other',
'args' => array(
'post_status' => 'publish,trash'
)
]
);