Skip to content

Commit 9139445

Browse files
Copilotswissspidy
andcommitted
Implement STDIN support for wp media import command
Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
1 parent 0d63e27 commit 9139445

2 files changed

Lines changed: 106 additions & 26 deletions

File tree

features/media-import.feature

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,3 +286,39 @@ Feature: Manage WordPress attachments
286286
"""
287287
Error: Invalid value for <porcelain>: invalid. Expected flag or 'url'.
288288
"""
289+
290+
Scenario: Import media from STDIN
291+
Given download:
292+
| path | url |
293+
| {CACHE_DIR}/codeispoetry.png | http://wp-cli.org/behat-data/codeispoetry.png |
294+
295+
When I run `cat {CACHE_DIR}/codeispoetry.png | wp media import - --title="From STDIN" --porcelain`
296+
Then save STDOUT as {ATTACHMENT_ID}
297+
298+
When I run `wp post get {ATTACHMENT_ID} --field=title`
299+
Then STDOUT should be:
300+
"""
301+
From STDIN
302+
"""
303+
304+
Scenario: Import media from STDIN with file_name
305+
Given download:
306+
| path | url |
307+
| {CACHE_DIR}/codeispoetry.png | http://wp-cli.org/behat-data/codeispoetry.png |
308+
309+
When I run `cat {CACHE_DIR}/codeispoetry.png | wp media import - --file_name=my-image.png --porcelain`
310+
Then save STDOUT as {ATTACHMENT_ID}
311+
312+
When I run `wp post get {ATTACHMENT_ID} --field=name`
313+
Then STDOUT should be:
314+
"""
315+
my-image-png
316+
"""
317+
318+
Scenario: Fail to import from STDIN when no input provided
319+
When I try `wp media import - </dev/null`
320+
Then STDERR should contain:
321+
"""
322+
Warning: Unable to import file from STDIN. Reason: No input provided.
323+
"""
324+
And the return code should be 1

src/Media_Command.php

Lines changed: 70 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ public function regenerate( $args, $assoc_args = array() ) {
192192
* : Path to file or files to be imported. Supports the glob(3) capabilities of the current shell.
193193
* If file is recognized as a URL (for example, with a scheme of http or ftp), the file will be
194194
* downloaded to a temp file before being sideloaded.
195+
* Use '-' to read file data from STDIN.
195196
*
196197
* [--post_id=<post_id>]
197198
* : ID of the post to attach the imported files to.
@@ -261,6 +262,11 @@ public function regenerate( $args, $assoc_args = array() ) {
261262
* # Get the URL for an attachment after import.
262263
* $ 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
263264
* http://wordpress-develop.dev/wp-header-logo/
265+
*
266+
* # Import an image from STDIN.
267+
* $ curl http://example.com/image.jpg | wp media import - --title="From STDIN"
268+
* Imported file from STDIN as attachment ID 1756.
269+
* Success: Imported 1 of 1 items.
264270
*/
265271
public function import( $args, $assoc_args = array() ) {
266272
$assoc_args = wp_parse_args(
@@ -309,41 +315,79 @@ public function import( $args, $assoc_args = array() ) {
309315
Utils\wp_clear_object_cache();
310316
}
311317

312-
// phpcs:ignore WordPress.WP.AlternativeFunctions.parse_url_parse_url -- parse_url will only be used in absence of wp_parse_url.
313-
$is_file_remote = function_exists( 'wp_parse_url' ) ? wp_parse_url( $file, PHP_URL_HOST ) : parse_url( $file, PHP_URL_HOST );
314-
$orig_filename = $file;
315-
$file_time = '';
318+
// Handle STDIN input
319+
if ( '-' === $file ) {
320+
if ( ! Utils\has_stdin() ) {
321+
WP_CLI::warning( 'Unable to import file from STDIN. Reason: No input provided.' );
322+
++$errors;
323+
continue;
324+
}
316325

317-
if ( empty( $is_file_remote ) ) {
318-
if ( ! file_exists( $file ) ) {
319-
WP_CLI::warning( "Unable to import file '$file'. Reason: File doesn't exist." );
326+
// Read from STDIN and save to a temporary file
327+
$stdin_content = file_get_contents( 'php://stdin' );
328+
if ( false === $stdin_content ) {
329+
WP_CLI::warning( 'Unable to import file from STDIN. Reason: Could not read STDIN.' );
320330
++$errors;
321331
continue;
322332
}
323-
if ( Utils\get_flag_value( $assoc_args, 'skip-copy' ) ) {
324-
$tempfile = $file;
325-
} else {
326-
$tempfile = $this->make_copy( $file );
333+
334+
// Create a temporary file to store STDIN content
335+
$tempfile = wp_tempnam( 'wp-media-import-' );
336+
if ( false === file_put_contents( $tempfile, $stdin_content ) ) {
337+
WP_CLI::warning( 'Unable to import file from STDIN. Reason: Could not write to temporary file.' );
338+
++$errors;
339+
continue;
327340
}
328-
$name = Utils\basename( $file );
329341

330-
if ( Utils\get_flag_value( $assoc_args, 'preserve-filetime' ) ) {
331-
$file_time = @filemtime( $file );
342+
// Determine the name for the imported file
343+
if ( ! empty( $assoc_args['file_name'] ) ) {
344+
$name = $assoc_args['file_name'];
345+
} else {
346+
// Try to determine file extension from content
347+
$filetype = wp_check_filetype_and_ext( $tempfile, '' );
348+
$ext = ! empty( $filetype['ext'] ) ? '.' . $filetype['ext'] : '';
349+
$name = 'stdin-' . time() . $ext;
332350
}
351+
352+
$orig_filename = 'STDIN';
353+
$file_time = '';
333354
} else {
334-
$tempfile = download_url( $file );
335-
if ( is_wp_error( $tempfile ) ) {
336-
WP_CLI::warning(
337-
sprintf(
338-
"Unable to import file '%s'. Reason: %s",
339-
$file,
340-
implode( ', ', $tempfile->get_error_messages() )
341-
)
342-
);
343-
++$errors;
344-
continue;
355+
// phpcs:ignore WordPress.WP.AlternativeFunctions.parse_url_parse_url -- parse_url will only be used in absence of wp_parse_url.
356+
$is_file_remote = function_exists( 'wp_parse_url' ) ? wp_parse_url( $file, PHP_URL_HOST ) : parse_url( $file, PHP_URL_HOST );
357+
$orig_filename = $file;
358+
$file_time = '';
359+
360+
if ( empty( $is_file_remote ) ) {
361+
if ( ! file_exists( $file ) ) {
362+
WP_CLI::warning( "Unable to import file '$file'. Reason: File doesn't exist." );
363+
++$errors;
364+
continue;
365+
}
366+
if ( Utils\get_flag_value( $assoc_args, 'skip-copy' ) ) {
367+
$tempfile = $file;
368+
} else {
369+
$tempfile = $this->make_copy( $file );
370+
}
371+
$name = Utils\basename( $file );
372+
373+
if ( Utils\get_flag_value( $assoc_args, 'preserve-filetime' ) ) {
374+
$file_time = @filemtime( $file );
375+
}
376+
} else {
377+
$tempfile = download_url( $file );
378+
if ( is_wp_error( $tempfile ) ) {
379+
WP_CLI::warning(
380+
sprintf(
381+
"Unable to import file '%s'. Reason: %s",
382+
$file,
383+
implode( ', ', $tempfile->get_error_messages() )
384+
)
385+
);
386+
++$errors;
387+
continue;
388+
}
389+
$name = strtok( Utils\basename( $file ), '?' );
345390
}
346-
$name = strtok( Utils\basename( $file ), '?' );
347391
}
348392

349393
if ( ! empty( $assoc_args['file_name'] ) ) {

0 commit comments

Comments
 (0)