PluginProbe
Polylang / 3.8.10
Polylang v3.8.10
3.8.10 3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 2.7 2.7.0.1 2.7.1 2.7.2 2.7.3 2.7.4 2.8 2.8.1 2.8.2 2.8.3 2.8.4 2.9 2.9.1 2.9.2 3.0 3.0.1 3.0.2 All 234 releases
← All changes | src/crud-posts.php +54 -13 3.8.3 → 3.8.10 View file →
@@ -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;