How to cleanly delete attachment but retain original file?

wp_delete_attachment() is very comprehensive and wipes every trace of attachment from database and disk.

Is there easy way to keep original file? Forking under another name is not an option, because other functions like wp_delete_post() will still call original version.

Related posts

Leave a Reply

2 comments

  1. Year and some later with much improved skills, behold:

    Keep_Deleted_Attachment_File::on_load();
    
    /**
     * Keep original file when deleting attachments.
     */
    class Keep_Deleted_Attachment_File {
    
        static private $file;
    
        static function on_load() {
    
            add_action( 'init', array( __CLASS__, 'init' ) );
        }
    
        static function init() {
    
            add_action( 'delete_attachment', array( __CLASS__, 'delete_attachment' ) );
        }
    
        /**
         * @param int $post_id attachment being deleted
         */
        static function delete_attachment( $post_id ) {
    
            self::$file = get_attached_file( $post_id );
            add_filter( 'wp_delete_file', array( __CLASS__, 'wp_delete_file' ) );
        }
    
        /**
         * @param string $file path to file being deleted
         *
         * @return string|bool no change or boolean false to prevent file deletion
         */
        static function wp_delete_file( $file ) {
    
            if ( ! empty( self::$file ) && self::$file == $file ) {
    
                remove_filter( current_filter(), array( __CLASS__, __FUNCTION__ ) );
                return false;
            }
    
            return $file;
        }
    }
    
  2. Assuming $attachment_id is the ID of the attachment you want to delete without deleting the file, this should do it:

    $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->posts, $wpdb->postmeta WHERE $wpdb->posts.ID = %d OR $wpdb->postmeta.post_id = %d", $attachment_id, $attachment_id ) );