• When using wp-admin, on a post with post_type=”attachment”, if I click “delete permanently”, both the post AND the attached files (originals and thumbs, stored on s3) are deleted.

    However, when using WP CLI and other methods, it removes only the DB record and not the attached files. Is there an option or other suggested method to remove both the DB record and the file? In fact, if there was an easy way to delete the attached files first, I could easily delete the DB records after that.

    I appreciate any advice on this matter!

    PS: We are talking about ~1,000,000 attachment posts and several million images, so the manual process mentioned first doesn’t scale for me, although technically it “works”.

Viewing 7 replies - 1 through 7 (of 7 total)
  • Thread Starter gregzimerman

    (@gregzimerman)

    As an update, I’ve been able to write a script using the WordPress CLI as well as one using WordPress API and wp_delete_post. Both remove the post record only, but not the attached files or thumbnails. Again, clicking “delete permanently” from the CMS does delete those thumbnails.

    The big question is — What does “delete permanently” from post.php fire that the WP CLI and standalone script don’t?

    I could also write a custom script including wp_delete_post and wp_delete_attachment? The confusing part is that wp_delete_post should call wp_delete_attachment when post_type=”attachment”, which is true here, but it’s not clear if that’s happening.

    Any ideas?

    Moderator bcworkz

    (@bcworkz)

    Disclaimer – I have no CLI experience or detailed knowledge. I’m partly replying to add the WP-CLI tag to your topic so the CLI support community will be able to find your topic.

    I can answer your questions about WP core functions if that is what you are asking about and not the equivalent API or CLI methods. The core function wp_delete_post() does indeed call wp_delete_attachment() for attachment post types. The post.php code itself also differentiates between attachments and other post types, even though simply calling wp_delete_post() would suffice in all cases.

    You should know that besides deleting associated attachment files, wp_delete_attachment() also deletes related meta data and any taxonomy term associations that might be directly added to the attachment post (but not remove term associations added to any parent posts). The function also clears any related data from the internal WP cache.

    The reason deleting attachment posts through the API does not do all of this is it’s intended as a lower level “developer” interface where we are capable of creating our own higher level functionality. There are possible needs of developers where attachment posts are no longer needed but their associated media files are still required. Deleting attachments through the CMS admin interface must of necessity be a high level interface that anticipates user needs and handles it for them, since most users wouldn’t know enough to do all that’s required themselves.

    If the API’s default post deletion method is inadequate for your needs, you can develop your own route/endpoint that calls the wp_delete_attachment() core function.

    I can only assume similar logic goes into the CLI, as I said, I’ve no direct experience with it. Hopefully someone more knowledgeable can confirm or deny this for us.

    Thread Starter gregzimerman

    (@gregzimerman)

    @bcworkz Thanks for your response and the tag. I agree 100% on the need for granular control, but it’s crazy how hard I need to fight with WordPress to do this fairly normal administrative task, which I still haven’t been able to automate.

    I’ve moved on from WP CLI to write a simple script of my own, bootstrapping WordPress with “require_once( ‘wp-load.php’ );”, such that I can successfully run all kinds of WordPress queries and functions from a PHP script. But no matter what I try with wp_delete_post and wp_delete_attachment, the attachment post and it’s metadata are removed from the DB, but the file and it’s thumbnails are NOT removed from storage (S3).

    So there’s really no way high level way to delete a bunch of media files, given the IDs of their attachment posts? Again, I just need to replicate the functionality of the “delete permanently” link from the CMS (which obviously exists), but for 1,000,000+ records. I’m an engineer so I can handle some code, but I’m new to hands-on WP development — is there a hook or action that might help me here? I see do_action(‘before_delete_post’) mentioned as a possibility, but haven’t gotten that working yet either. I feel like I must be missing something obvious. Thanks in advance!

    PS: I realized I hadn’t mentioned, but my site is running on WordPress v4.5.2 and uses the plugins Amazon S3 and CloudFront v0.6.1 & Amazon Web Services v0.1.

    Moderator bcworkz

    (@bcworkz)

    Straight PHP in the WP environment gets us into territory where I’m much more comfortable. wp_delete_post() or wp_delete_attachment() should both remove associated media files. You should be able to compile a list of attachment IDs and run it through a loop or array_map using one of those functions and have all associated files removed.

    Possible causes why that would not happen:
    Some sort of alternative file storage scheme beyond wp-content/uploads/ is managing media files and is not playing well with wp_delete_attachment().

    Some sort of file permissions issue with the user PHP is running as.

    Something quirky about your Amazon resources that I’m not familiar with.

    Something I haven’t even thought of.

    FYI, loading the WP environment through including wp-load.php when executing custom PHP is frowned upon because it can fail in other installations. It’s OK for your own code on your own site. Just know that it may not transfer well to other sites and will be cause for rejection in any plugins submitted to the WP repository. Other than that, using it is fine 🙂

    Thread Starter gregzimerman

    (@gregzimerman)

    Thanks, it’s good to confirm that the functions above should be deleting the source files. Neither the originals or the attachments are being deleted. I’m using $force_delete=true if that has any significance on it.

    I want to debug pathing next. I know deletion works from a WordPress perspective since my CMS does it, but something different is happening on the command line or PHP script.

    And understood about wp-load.php. My code here was never meant for distribution, just the fastest way to get access to WP functionality for short term use scripts. I ran into a few errors myself when I first tried it, but I was able to resolve them.

    Moderator bcworkz

    (@bcworkz)

    Bah, the fact it works from the back end blows holes in most of my theories. Here’s a thought: Some requests need to go through wp-admin for certain code to work correctly. I didn’t see any code checking for this in wp_delete_attachment(), but maybe it’s buried in a sub-function call. Instead of requiring wp-load.php, try running your request through admin-ajax.php or admin-post.php.

    Using admin-post.php isn’t well documented, it’s similar to using Ajax, except you don’t need JavaScript. Just make a POST or GET request that includes a value keyed as “action”, which is used to construct an action tag which admin-post.php fires to cause a callback you’ve added to execute. Examining the source code of admin-post.php pretty much explains this further and reveals how the tag is constructed. No guarantees, but I think it’s worth a try.

    Requests through these two files are a couple acceptable, portable ways to invoke the WP environment. I figured your usage of wp-load.php was as you just described, I just didn’t want anyone landing here from a search to get the idea that that was a good way to invoke the environment. It’s a popular issue to search for, lots of coders new to WP struggle with getting their custom code to use WP resources 😉

    One more thought, check your error logs or define WP_DEBUG as true for possible clues for the failure of file removal.

    Thread Starter gregzimerman

    (@gregzimerman)

    Ha, sorry to debunk your theories!

    I’ll try the admin-ajax.php/admin-post.php methods tonight. It’s a great idea to try. I’m less familiar with constructing those requests, but I should be able to figure it out!

    And yes, I’m tailing my error logs while I test. I haven’t seen related warnings/errors yet, but hopefully something will bubble up with these new methods, or maybe it will just work. 🙂

    Thanks again for all the advice — I will let you know how it goes!

Viewing 7 replies - 1 through 7 (of 7 total)
  • The topic ‘WP CLI – removing attachment post AND media files’ is closed to new replies.