Skip to content

Commit 65fbd48

Browse files
committed
Simplify optimize_image and address PR feedback
- Return only file path from optimize_image instead of array with changed flag - Let WordPress auto-detect mime type instead of manually setting it - Add temp file extension handling for proper mime type detection - Add get_unique_path helper to prevent file collisions during format conversion - Move WP_Filesystem initialization to function start
1 parent ba20c5b commit 65fbd48

File tree

2 files changed

+63
-53
lines changed

2 files changed

+63
-53
lines changed

includes/class-attachments.php

Lines changed: 61 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -427,13 +427,14 @@ private static function save_attachment( $attachment_data, $post_id, $author_id
427427
require_once ABSPATH . 'wp-admin/includes/image.php';
428428
}
429429

430+
// Initialize filesystem.
431+
\WP_Filesystem();
432+
global $wp_filesystem;
433+
430434
$is_local = ! preg_match( '#^https?://#i', $attachment_data['url'] );
431435

432436
if ( $is_local ) {
433437
// Read local file from disk.
434-
\WP_Filesystem();
435-
global $wp_filesystem;
436-
437438
if ( ! $wp_filesystem->exists( $attachment_data['url'] ) ) {
438439
/* translators: %s: file path */
439440
return new \WP_Error( 'file_not_found', sprintf( \__( 'File not found: %s', 'activitypub' ), $attachment_data['url'] ) );
@@ -451,18 +452,24 @@ private static function save_attachment( $attachment_data, $post_id, $author_id
451452
}
452453
}
453454

454-
// Optimize images before sideloading (resize and convert to WebP).
455-
$optimized = self::optimize_image( $tmp_file, self::MAX_IMAGE_DIMENSION );
456-
if ( $optimized['changed'] ) {
457-
$tmp_file = $optimized['path'];
455+
// Get original filename from URL.
456+
$original_name = \basename( \wp_parse_url( $attachment_data['url'], PHP_URL_PATH ) );
457+
458+
// Rename temp file to have proper extension for optimize_image to detect mime type.
459+
$original_ext = \pathinfo( $original_name, PATHINFO_EXTENSION );
460+
if ( $original_ext ) {
461+
$renamed_tmp = $tmp_file . '.' . $original_ext;
462+
if ( $wp_filesystem->move( $tmp_file, $renamed_tmp, true ) ) {
463+
$tmp_file = $renamed_tmp;
464+
}
458465
}
459466

460-
// Prepare file array for WordPress.
461-
$original_name = \basename( \wp_parse_url( $attachment_data['url'], PHP_URL_PATH ) );
467+
// Optimize images before sideloading (resize and convert to WebP).
468+
$tmp_file = self::optimize_image( $tmp_file, self::MAX_IMAGE_DIMENSION );
462469

463-
// Update filename extension if format changed.
464-
if ( $optimized['changed'] ) {
465-
$new_ext = \pathinfo( $tmp_file, PATHINFO_EXTENSION );
470+
// Update filename extension to match optimized file.
471+
$new_ext = \pathinfo( $tmp_file, PATHINFO_EXTENSION );
472+
if ( $new_ext ) {
466473
$original_name = \preg_replace( '/\.[^.]+$/', '.' . $new_ext, $original_name );
467474
}
468475

@@ -472,14 +479,12 @@ private static function save_attachment( $attachment_data, $post_id, $author_id
472479
);
473480

474481
// Prepare attachment post data.
475-
// Clear mime type if format changed so WordPress auto-detects it.
476-
$mime_type = $optimized['changed'] ? '' : ( $attachment_data['mediaType'] ?? '' );
482+
// Let WordPress auto-detect the mime type from the file.
477483
$post_data = array(
478-
'post_mime_type' => $mime_type,
479-
'post_title' => $attachment_data['name'] ?? '',
480-
'post_content' => $attachment_data['name'] ?? '',
481-
'post_author' => $author_id,
482-
'meta_input' => array(
484+
'post_title' => $attachment_data['name'] ?? '',
485+
'post_content' => $attachment_data['name'] ?? '',
486+
'post_author' => $author_id,
487+
'meta_input' => array(
483488
'_source_url' => $attachment_data['url'],
484489
),
485490
);
@@ -579,11 +584,8 @@ private static function save_file( $attachment_data, $object_id, $object_type, $
579584
}
580585

581586
// Optimize images (resize and convert to WebP).
582-
$optimized = self::optimize_image( $file_path, $max_dimension );
583-
if ( $optimized['changed'] ) {
584-
$file_path = $optimized['path'];
585-
$file_name = \basename( $file_path );
586-
}
587+
$file_path = self::optimize_image( $file_path, $max_dimension );
588+
$file_name = \basename( $file_path );
587589

588590
// Get mime type and validate file.
589591
$file_info = \wp_check_filetype_and_ext( $file_path, $file_name );
@@ -596,6 +598,32 @@ private static function save_file( $attachment_data, $object_id, $object_type, $
596598
);
597599
}
598600

601+
/**
602+
* Get a unique file path by appending a counter if the file already exists.
603+
*
604+
* @param string $file_path The desired file path.
605+
*
606+
* @return string A unique file path that doesn't exist.
607+
*/
608+
private static function get_unique_path( $file_path ) {
609+
if ( ! \file_exists( $file_path ) ) {
610+
return $file_path;
611+
}
612+
613+
$path_info = \pathinfo( $file_path );
614+
$dir = $path_info['dirname'];
615+
$base_name = $path_info['filename'];
616+
$extension = isset( $path_info['extension'] ) ? '.' . $path_info['extension'] : '';
617+
$counter = 1;
618+
619+
do {
620+
$new_path = $dir . '/' . $base_name . '-' . $counter . $extension;
621+
++$counter;
622+
} while ( \file_exists( $new_path ) );
623+
624+
return $new_path;
625+
}
626+
599627
/**
600628
* Optimize an image file by resizing and converting to WebP.
601629
*
@@ -605,32 +633,23 @@ private static function save_file( $attachment_data, $object_id, $object_type, $
605633
* @param string $file_path Path to the image file.
606634
* @param int $max_dimension Maximum width/height in pixels.
607635
*
608-
* @return array{path: string, changed: bool}|\WP_Error The optimized file path and whether it changed, or WP_Error.
636+
* @return string The optimized file path.
609637
*/
610638
private static function optimize_image( $file_path, $max_dimension ) {
611639
// Check if it's an image.
612640
$mime_type = \wp_check_filetype( $file_path )['type'] ?? '';
613641
if ( ! $mime_type || ! \str_starts_with( $mime_type, 'image/' ) ) {
614-
return array(
615-
'path' => $file_path,
616-
'changed' => false,
617-
);
642+
return $file_path;
618643
}
619644

620645
// Skip SVG and GIF files (GIFs may be animated).
621646
if ( \in_array( $mime_type, array( 'image/svg+xml', 'image/gif' ), true ) ) {
622-
return array(
623-
'path' => $file_path,
624-
'changed' => false,
625-
);
647+
return $file_path;
626648
}
627649

628650
$editor = \wp_get_image_editor( $file_path );
629651
if ( \is_wp_error( $editor ) ) {
630-
return array(
631-
'path' => $file_path,
632-
'changed' => false,
633-
);
652+
return $file_path;
634653
}
635654

636655
$size = $editor->get_size();
@@ -647,29 +666,23 @@ private static function optimize_image( $file_path, $max_dimension ) {
647666
// Determine output format and save.
648667
if ( $can_webp ) {
649668
// Convert to WebP.
650-
$new_path = \preg_replace( '/\.[^.]+$/', '.webp', $file_path );
669+
$new_path = self::get_unique_path( \preg_replace( '/\.[^.]+$/', '.webp', $file_path ) );
651670
$result = $editor->save( $new_path, 'image/webp' );
652671
} elseif ( \in_array( $mime_type, array( 'image/png', 'image/webp' ), true ) ) {
653672
// Keep original format for potentially transparent images when WebP not available.
654673
if ( ! $needs_resize ) {
655674
// No changes needed.
656-
return array(
657-
'path' => $file_path,
658-
'changed' => false,
659-
);
675+
return $file_path;
660676
}
661677
$result = $editor->save( $file_path );
662678
} else {
663679
// Convert to JPEG when WebP not available.
664-
$new_path = \preg_replace( '/\.[^.]+$/', '.jpg', $file_path );
680+
$new_path = self::get_unique_path( \preg_replace( '/\.[^.]+$/', '.jpg', $file_path ) );
665681
$result = $editor->save( $new_path, 'image/jpeg' );
666682
}
667683

668684
if ( \is_wp_error( $result ) ) {
669-
return array(
670-
'path' => $file_path,
671-
'changed' => false,
672-
);
685+
return $file_path;
673686
}
674687

675688
// Handle result - $result is always an array from $editor->save().
@@ -680,10 +693,7 @@ private static function optimize_image( $file_path, $max_dimension ) {
680693
\wp_delete_file( $file_path );
681694
}
682695

683-
return array(
684-
'path' => $result_path,
685-
'changed' => true,
686-
);
696+
return $result_path;
687697
}
688698

689699
/**

tests/phpunit/tests/includes/class-test-attachments.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -789,9 +789,9 @@ public function test_mixed_attachments_images_video_audio() {
789789
$this->assertIsArray( $result );
790790
$this->assertCount( 3, $result );
791791

792-
// Image should be downloaded to local storage.
792+
// Image should be downloaded to local storage (may be converted to WebP).
793793
$this->assertStringContainsString( 'activitypub/ap_posts', $result[0]['url'] );
794-
$this->assertEquals( 'image/jpeg', $result[0]['mime_type'] );
794+
$this->assertContains( $result[0]['mime_type'], array( 'image/jpeg', 'image/webp' ) );
795795

796796
// Video should use remote URL.
797797
$this->assertEquals( 'https://example.com/video.mp4', $result[1]['url'] );

0 commit comments

Comments
 (0)