| @@ -268,23 +268,64 @@ | ||
| 268 | 268 | */ |
| 269 | 269 | public function wp_delete_file( $file ) { |
| 270 | 270 | global $wpdb; |
| 271 | 271 | |
| 272 | - $uploadpath = wp_upload_dir(); | |
| 272 | + $basefile = basename( $file ); | |
| 273 | + $upload = wp_upload_dir(); | |
| 274 | + $attached_file = trim( str_replace( $upload['basedir'], '', $file ), '/' ); | |
| 275 | + $subdir = trim( str_replace( $basefile, '', $attached_file ), '/' ); | |
| 276 | + $filetype = wp_check_filetype( $file ); | |
| 273 | 277 | |
| 274 | - // Get the main attached file. | |
| 275 | - $attached_file = substr_replace( $file, '', 0, strlen( trailingslashit( $uploadpath['basedir'] ) ) ); | |
| 276 | - $attached_file = preg_replace( '#-\d+x\d+\.([a-z]+)$#', '.$1', $attached_file ); | |
| 278 | + if ( empty( $filetype['type'] ) || ! str_starts_with( $filetype['type'], 'image/' ) ) { | |
| 279 | + /* | |
| 280 | + * For non-image files, we just have to check the '_wp_attached_file meta'. | |
| 281 | + */ | |
| 282 | + $count = $wpdb->get_var( | |
| 283 | + $wpdb->prepare( | |
| 284 | + "SELECT COUNT(*) FROM $wpdb->postmeta | |
| 285 | + WHERE meta_key = '_wp_attached_file' AND meta_value = %s", | |
| 286 | + $attached_file | |
| 287 | + ) | |
| 288 | + ); | |
| 289 | + } elseif ( ! empty( $subdir ) ) { | |
| 290 | + /* | |
| 291 | + * For images, we must take care to intermediate sizes and backup. | |
| 292 | + * - '_wp_attachment_metadata' stores the base filename without subdir | |
| 293 | + * for intermediate sizes but includes the subdir for the main file. | |
| 294 | + * - '_wp_attachment_backup_sizes' stores the base filename, without the subdir. | |
| 295 | + * - '_wp_attached_file' stores the filename with the subdir. | |
| 296 | + * | |
| 297 | + * For filenames stored without subdir, we get it from '_wp_attached_file' to | |
| 298 | + * avoid a conflict if a file has the same filename in a different subdir. | |
| 299 | + */ | |
| 300 | + $count = $wpdb->get_var( | |
| 301 | + $wpdb->prepare( | |
| 302 | + "SELECT COUNT(*) FROM $wpdb->postmeta AS pm1 | |
| 303 | + JOIN $wpdb->postmeta AS pm2 ON pm1.post_id = pm2.post_id | |
| 304 | + WHERE pm1.meta_key = '_wp_attached_file' AND pm1.meta_value LIKE %s | |
| 305 | + AND pm2.meta_key IN ( '_wp_attachment_metadata', '_wp_attachment_backup_sizes' ) | |
| 306 | + AND ( pm2.meta_value LIKE %s OR pm2.meta_value LIKE %s )", | |
| 307 | + $wpdb->esc_like( $subdir ) . '/%', // The subdir is always present in '_wp_attached_file'. | |
| 308 | + '%"' . $wpdb->esc_like( $basefile ) . '"%', // Intermediate sizes in '_wp_attachment_metadata' + '_wp_attachment_backup_sizes'. | |
| 309 | + '%"' . $wpdb->esc_like( $attached_file ) . '"%' // Main file in '_wp_attachment_metadata'. | |
| 310 | + ) | |
| 311 | + ); | |
| 312 | + } else { | |
| 313 | + /* | |
| 314 | + * The query above doesn't work if there's no subdir for uploads, so we must handle it | |
| 315 | + * as a specific case. | |
| 316 | + */ | |
| 317 | + $count = $wpdb->get_var( | |
| 318 | + $wpdb->prepare( | |
| 319 | + "SELECT COUNT(*) FROM $wpdb->postmeta | |
| 320 | + WHERE meta_key IN ( '_wp_attachment_metadata', '_wp_attachment_backup_sizes' ) | |
| 321 | + AND meta_value LIKE %s", | |
| 322 | + '%"' . $wpdb->esc_like( $basefile ) . '"%' | |
| 323 | + ) | |
| 324 | + ); | |
| 325 | + } | |
| 277 | 326 | |
| 278 | - $ids = $wpdb->get_col( | |
| 279 | - $wpdb->prepare( | |
| 280 | - "SELECT post_id FROM $wpdb->postmeta | |
| 281 | - WHERE meta_key = '_wp_attached_file' AND meta_value = %s", | |
| 282 | - $attached_file | |
| 283 | - ) | |
| 284 | - ); | |
| 285 | - | |
| 286 | - if ( ! empty( $ids ) ) { | |
| 327 | + if ( $count > 0 ) { | |
| 287 | 328 | return ''; // Prevent deleting the file. |
| 288 | 329 | } |
| 289 | 330 | |
| 290 | 331 | return $file; |