7

My function lets users delete their uploaded images in the front-end. However, they're only deleted in the Media Library. That means that they're still in wp-content/uploads/.

     public static function removePhoto($ID, $attachment) {
     if(isset(self::$data['user']['photos'][$attachment])) {
    unset(self::$data['user']['photos'][$attachment]);
        wp_delete_attachment($attachment);
        core:updateUserMeta($ID, 'photos', self::$data['user']['photos']);
    }
}

This is how how the images are added:

public static function uploadImage($file) {
    require_once(ABSPATH.'wp-admin/includes/image.php');
    $attachment=array('ID' => 0);
        if(JBSUser::$data['user']['membership']['photos']<=0) {
        JBSInterface::$messages[]=__('You have exceeded the number of photos', 'epic');
         return $file;

}

    if(!empty($file['name'])) {
        $uploads=wp_upload_dir();
        $filetype=wp_check_filetype($file['name'], null);
        $filename=wp_unique_filename($uploads['path'], 'image-1.'.$filetype['ext']);
        $filepath=$uploads['path'].'/'.$filename;   

            //validate file
        if (!in_array($filetype['ext'], array('jpg', 'JPG', 'jpeg', 'JPEG', 'png', 'PNG'))) {
            JBSInterface::$messages[]=__('Only JPG and PNG images are allowed.', 'epic');
        } else if(move_uploaded_file($file['tmp_name'], $filepath)) {

                //upload image
                $attachment=array(
                    'guid' => $uploads['url'].'/'.$filename,
                    'post_mime_type' => $filetype['type'],
                    'post_title' => sanitize_title(current(explode('.', $filename))),
                    'post_content' => '',
                    'post_status' => 'inherit',
                    'post_author' => get_current_user_id(),
                );

                //add image
                $attachment['ID']=wp_insert_attachment($attachment, $attachment['guid'], 0);
                update_post_meta($attachment['ID'], '_wp_attached_file', substr($uploads['subdir'], 1).'/'.$filename);

                //add thumbnails
                $metadata=wp_generate_attachment_metadata($attachment['ID'], $filepath);
                wp_update_attachment_metadata($attachment['ID'], $metadata);

        } else {
            JBSInterface::$messages[]=__('This image is too large for uploading.','epic');
        }
    }

    return $attachment;
}

Update: Setting wp_delete_attachment, true - does not work.

I'm suspicious of: substr($uploads['subdir'], 1).'/'.$filename); Which seems to upload the files to subfolder. But the images are still uploaded to the wp-content/uploads/ regardless if the "organize" setting is on or off.

Should this really effect the wp_delete_attachment?

  • 1
    I have the same problem. I think it's because you are not adding the image via wp_handle_upload. When I add it via wp_handle_upload wp_delete_attachment works. But when adding via file_put_contents or something else it does not. Did you figure this out otherwise? I tried unlink(), but you need to provide all thumbnail images then (300x300 etc..) – trainoasis Nov 16 '15 at 9:09
  • @trainoasis Doesnt work for me either, I am adding files throughmedia_handle_upload though (after sanitization) - which basically calls wp_handle_upload inside – jave.web Oct 10 '18 at 9:46
  • Why was this closed as off topic???? This is so on topic.. I have the same issue – Tofandel Mar 13 at 18:55
0

You need to provide wp_delete_attachment a value of true for it's second argument force_delete. Your code needs to change to wp_delete_attachment( $attachment, true );

| improve this answer | |
  • 1
    Adding the value true to wp_delete_attachment doesnt fix the issue. The uploaded file is still in wp_content/uploads – dkl Mar 21 '15 at 16:43
  • What do you think about the substr($uploads['subdir'], 1).'/'.$filename); in the upload function? – dkl Apr 14 '15 at 8:06
0

You forgot to add second parameter for the function wp_delete_attachment

 <?php wp_delete_attachment( $attachmentid, $force_delete ); ?> 

$attachmentid
(integer) (required) The ID of the attachment you would like to delete.
Default: None

$force_delete (bool) (optional) Whether to bypass trash and force deletion (added in WordPress 2.9).
Default: false

| improve this answer | |
  • 2
    Thank you for the reply. But adding force_delete does not fix the issue. – dkl Mar 21 '15 at 16:39
  • What do you think about the substr($uploads['subdir'], 1).'/'.$filename); in the upload function? – dkl Apr 14 '15 at 8:06
0

For future reference, if your attachment gets deleted but not your files

There is a filter wp_delete_file, check if this filter is hooked on somewhere, if it returns null your file won't be deleted but the attachment will

For me it was due to the WPML plugin, they duplicate attachments and then checks that all the attachments are deleted before actually deleting the file

You can either add this action in your theme/plugin, that will delete all translations when using $force_delete in wp_delete_attachment

if ( ! function_exists( 'delete_attachment_translations' ) ) {
    function delete_attachment_translations( $id ) {
        remove_action( 'delete_attachment', 'delete_attachment_translations' );

        $langs = apply_filters( 'wpml_active_languages', [] );

        if ( ! empty( $langs ) ) {
            global $wp_filter;

            //We need to temporarly remove WPML's hook or they will cache the result and not delete the file
            // Sadly they used a filter on a non global class instance, so we cannot access it via regular wp hook
            $hooks = $wp_filter['wp_delete_file']->callbacks[10];
            unset( $wp_filter['wp_delete_file']->callbacks[10] );

            foreach ( $langs as $code => $info ) {
                $post_id = apply_filters( 'wpml_object_id', $id, 'attachment', false, $code );
                if ( $id == $post_id ) {
                    continue;
                }
                wp_delete_attachment( $post_id, true );
            }

            $wp_filter['wp_delete_file']->callbacks[10] = $hooks;
        }

        add_action( 'delete_attachment', 'delete_attachment_translations' );
    }

    add_action( 'delete_attachment', 'delete_attachment_translations' );
}

Or check this option in your WPML settings (But it applies to all posts types, not just attachments)

enter image description here

| improve this answer | |
0

Inside the wp-includes/post.php in the wp_delete_attachment_files there's a check to see if other attachments use the same file. This is what was happening in my case. Because I initially deleted the file manually but not the attachment, when I was uploading it again, the same name as before was used.

So when the delete function was called for the newly uploaded attachment id, the old attachment had a reference to the same file, so the DB attachment was deleted and not the file.

Make sure you manually delete all the attachments that could point to the same file from the media library.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.