wp_delete_attachment doesn’t delete images in wp-content/uploads/

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']."https://wordpress.stackexchange.com/".$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']."https://wordpress.stackexchange.com/".$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)."https://wordpress.stackexchange.com/".$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)."https://wordpress.stackexchange.com/".$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?

4 s
4

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

Leave a Comment