From 0d63e2773e11e8fb29769c5756e805994c1da02f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 21:34:56 +0000 Subject: [PATCH 1/5] Initial plan From 9139445ef0089289cc6ef754d5ce892907da6bca Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 21:38:23 +0000 Subject: [PATCH 2/5] Implement STDIN support for wp media import command Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/media-import.feature | 36 +++++++++++++ src/Media_Command.php | 96 +++++++++++++++++++++++++---------- 2 files changed, 106 insertions(+), 26 deletions(-) diff --git a/features/media-import.feature b/features/media-import.feature index aa8562fc..15f3dfbe 100644 --- a/features/media-import.feature +++ b/features/media-import.feature @@ -286,3 +286,39 @@ Feature: Manage WordPress attachments """ Error: Invalid value for : invalid. Expected flag or 'url'. """ + + Scenario: Import media from STDIN + Given download: + | path | url | + | {CACHE_DIR}/codeispoetry.png | http://wp-cli.org/behat-data/codeispoetry.png | + + When I run `cat {CACHE_DIR}/codeispoetry.png | wp media import - --title="From STDIN" --porcelain` + Then save STDOUT as {ATTACHMENT_ID} + + When I run `wp post get {ATTACHMENT_ID} --field=title` + Then STDOUT should be: + """ + From STDIN + """ + + Scenario: Import media from STDIN with file_name + Given download: + | path | url | + | {CACHE_DIR}/codeispoetry.png | http://wp-cli.org/behat-data/codeispoetry.png | + + When I run `cat {CACHE_DIR}/codeispoetry.png | wp media import - --file_name=my-image.png --porcelain` + Then save STDOUT as {ATTACHMENT_ID} + + When I run `wp post get {ATTACHMENT_ID} --field=name` + Then STDOUT should be: + """ + my-image-png + """ + + Scenario: Fail to import from STDIN when no input provided + When I try `wp media import - ] * : ID of the post to attach the imported files to. @@ -261,6 +262,11 @@ public function regenerate( $args, $assoc_args = array() ) { * # Get the URL for an attachment after import. * $ wp media import http://s.wordpress.org/style/images/wp-header-logo.png --porcelain | xargs -I {} wp post list --post__in={} --field=url --post_type=attachment * http://wordpress-develop.dev/wp-header-logo/ + * + * # Import an image from STDIN. + * $ curl http://example.com/image.jpg | wp media import - --title="From STDIN" + * Imported file from STDIN as attachment ID 1756. + * Success: Imported 1 of 1 items. */ public function import( $args, $assoc_args = array() ) { $assoc_args = wp_parse_args( @@ -309,41 +315,79 @@ public function import( $args, $assoc_args = array() ) { Utils\wp_clear_object_cache(); } - // phpcs:ignore WordPress.WP.AlternativeFunctions.parse_url_parse_url -- parse_url will only be used in absence of wp_parse_url. - $is_file_remote = function_exists( 'wp_parse_url' ) ? wp_parse_url( $file, PHP_URL_HOST ) : parse_url( $file, PHP_URL_HOST ); - $orig_filename = $file; - $file_time = ''; + // Handle STDIN input + if ( '-' === $file ) { + if ( ! Utils\has_stdin() ) { + WP_CLI::warning( 'Unable to import file from STDIN. Reason: No input provided.' ); + ++$errors; + continue; + } - if ( empty( $is_file_remote ) ) { - if ( ! file_exists( $file ) ) { - WP_CLI::warning( "Unable to import file '$file'. Reason: File doesn't exist." ); + // Read from STDIN and save to a temporary file + $stdin_content = file_get_contents( 'php://stdin' ); + if ( false === $stdin_content ) { + WP_CLI::warning( 'Unable to import file from STDIN. Reason: Could not read STDIN.' ); ++$errors; continue; } - if ( Utils\get_flag_value( $assoc_args, 'skip-copy' ) ) { - $tempfile = $file; - } else { - $tempfile = $this->make_copy( $file ); + + // Create a temporary file to store STDIN content + $tempfile = wp_tempnam( 'wp-media-import-' ); + if ( false === file_put_contents( $tempfile, $stdin_content ) ) { + WP_CLI::warning( 'Unable to import file from STDIN. Reason: Could not write to temporary file.' ); + ++$errors; + continue; } - $name = Utils\basename( $file ); - if ( Utils\get_flag_value( $assoc_args, 'preserve-filetime' ) ) { - $file_time = @filemtime( $file ); + // Determine the name for the imported file + if ( ! empty( $assoc_args['file_name'] ) ) { + $name = $assoc_args['file_name']; + } else { + // Try to determine file extension from content + $filetype = wp_check_filetype_and_ext( $tempfile, '' ); + $ext = ! empty( $filetype['ext'] ) ? '.' . $filetype['ext'] : ''; + $name = 'stdin-' . time() . $ext; } + + $orig_filename = 'STDIN'; + $file_time = ''; } else { - $tempfile = download_url( $file ); - if ( is_wp_error( $tempfile ) ) { - WP_CLI::warning( - sprintf( - "Unable to import file '%s'. Reason: %s", - $file, - implode( ', ', $tempfile->get_error_messages() ) - ) - ); - ++$errors; - continue; + // phpcs:ignore WordPress.WP.AlternativeFunctions.parse_url_parse_url -- parse_url will only be used in absence of wp_parse_url. + $is_file_remote = function_exists( 'wp_parse_url' ) ? wp_parse_url( $file, PHP_URL_HOST ) : parse_url( $file, PHP_URL_HOST ); + $orig_filename = $file; + $file_time = ''; + + if ( empty( $is_file_remote ) ) { + if ( ! file_exists( $file ) ) { + WP_CLI::warning( "Unable to import file '$file'. Reason: File doesn't exist." ); + ++$errors; + continue; + } + if ( Utils\get_flag_value( $assoc_args, 'skip-copy' ) ) { + $tempfile = $file; + } else { + $tempfile = $this->make_copy( $file ); + } + $name = Utils\basename( $file ); + + if ( Utils\get_flag_value( $assoc_args, 'preserve-filetime' ) ) { + $file_time = @filemtime( $file ); + } + } else { + $tempfile = download_url( $file ); + if ( is_wp_error( $tempfile ) ) { + WP_CLI::warning( + sprintf( + "Unable to import file '%s'. Reason: %s", + $file, + implode( ', ', $tempfile->get_error_messages() ) + ) + ); + ++$errors; + continue; + } + $name = strtok( Utils\basename( $file ), '?' ); } - $name = strtok( Utils\basename( $file ), '?' ); } if ( ! empty( $assoc_args['file_name'] ) ) { From 09ecad92250448ba44b45cdfe10b810e76c63698 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 21:39:41 +0000 Subject: [PATCH 3/5] Simplify STDIN file naming logic and update class documentation Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Media_Command.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Media_Command.php b/src/Media_Command.php index b04b9b75..8390f0e9 100644 --- a/src/Media_Command.php +++ b/src/Media_Command.php @@ -20,6 +20,11 @@ * Imported file '/home/person/Downloads/image.png' as attachment ID 1753 and attached to post 123 as featured image. * Success: Imported 1 of 1 images. * + * # Import an image from STDIN. + * $ curl http://example.com/image.jpg | wp media import - + * Imported file 'STDIN' as attachment ID 1754. + * Success: Imported 1 of 1 items. + * * # List all registered image sizes * $ wp media image-size * +---------------------------+-------+--------+-------+ @@ -339,15 +344,10 @@ public function import( $args, $assoc_args = array() ) { continue; } - // Determine the name for the imported file - if ( ! empty( $assoc_args['file_name'] ) ) { - $name = $assoc_args['file_name']; - } else { - // Try to determine file extension from content - $filetype = wp_check_filetype_and_ext( $tempfile, '' ); - $ext = ! empty( $filetype['ext'] ) ? '.' . $filetype['ext'] : ''; - $name = 'stdin-' . time() . $ext; - } + // Try to determine file extension from content + $filetype = wp_check_filetype_and_ext( $tempfile, '' ); + $ext = ! empty( $filetype['ext'] ) ? '.' . $filetype['ext'] : ''; + $name = 'stdin-' . time() . $ext; $orig_filename = 'STDIN'; $file_time = ''; From 9ef41067693fe303a03dec041226578c0a54f381 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 21:40:53 +0000 Subject: [PATCH 4/5] Add clarifying comment about WordPress slug sanitization in test Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/media-import.feature | 1 + 1 file changed, 1 insertion(+) diff --git a/features/media-import.feature b/features/media-import.feature index 15f3dfbe..9ef2032f 100644 --- a/features/media-import.feature +++ b/features/media-import.feature @@ -314,6 +314,7 @@ Feature: Manage WordPress attachments """ my-image-png """ + # Note: WordPress sanitizes the post_name (slug) by converting dots to hyphens Scenario: Fail to import from STDIN when no input provided When I try `wp media import - Date: Sun, 15 Feb 2026 16:53:35 +0000 Subject: [PATCH 5/5] Fix STDIN file type detection using mime_content_type Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Media_Command.php | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/Media_Command.php b/src/Media_Command.php index 8390f0e9..744eb4e3 100644 --- a/src/Media_Command.php +++ b/src/Media_Command.php @@ -330,8 +330,8 @@ public function import( $args, $assoc_args = array() ) { // Read from STDIN and save to a temporary file $stdin_content = file_get_contents( 'php://stdin' ); - if ( false === $stdin_content ) { - WP_CLI::warning( 'Unable to import file from STDIN. Reason: Could not read STDIN.' ); + if ( false === $stdin_content || empty( $stdin_content ) ) { + WP_CLI::warning( 'Unable to import file from STDIN. Reason: No input provided.' ); ++$errors; continue; } @@ -344,10 +344,24 @@ public function import( $args, $assoc_args = array() ) { continue; } - // Try to determine file extension from content - $filetype = wp_check_filetype_and_ext( $tempfile, '' ); - $ext = ! empty( $filetype['ext'] ) ? '.' . $filetype['ext'] : ''; - $name = 'stdin-' . time() . $ext; + // Determine file extension from content + $mimetype = mime_content_type( $tempfile ); + + // Map MIME type to extension + $ext = ''; + if ( $mimetype && function_exists( 'wp_get_mime_types' ) ) { + $mime_types = wp_get_mime_types(); + foreach ( $mime_types as $exts => $mime ) { + if ( $mime === $mimetype ) { + $ext_array = explode( '|', $exts ); + $ext = '.' . $ext_array[0]; + break; + } + } + } + + // Generate filename with proper extension + $name = 'stdin-' . time() . $ext; $orig_filename = 'STDIN'; $file_time = '';