diff --git a/features/media-import.feature b/features/media-import.feature index 1ecdeeed..93aac90d 100644 --- a/features/media-import.feature +++ b/features/media-import.feature @@ -280,3 +280,35 @@ Feature: Manage WordPress attachments """ Error: Invalid value for : invalid. Expected flag or 'url'. """ + + Scenario: Upload files into a custom directory, relative to ABSPATH, when --destdir flag is applied. + Given download: + | path | url | + | {CACHE_DIR}/large-image.jpg | http://wp-cli.org/behat-data/large-image.jpg | + When I run `wp media import --destdir="foo" {CACHE_DIR}/large-image.jpg --porcelain=url` + + Then STDOUT should not contain: + """ + https://example.com/wp-content/uploads/ + """ + + And STDOUT should contain: + """ + https://example.com/foo/large-image.jpg + """ + + Scenario: Upload files into a custom directory, not relative to ABSPATH, when --destdir flag is applied. + Given download: + | path | url | + | {CACHE_DIR}/large-image.jpg | http://wp-cli.org/behat-data/large-image.jpg | + When I run `wp media import --destdir="{RUN_DIR}/foo" {CACHE_DIR}/large-image.jpg --porcelain=url` + + Then STDOUT should not contain: + """ + https://example.com/wp-content/uploads/ + """ + + And STDOUT should contain: + """ + /foo/large-image.jpg + """ diff --git a/src/Media_Command.php b/src/Media_Command.php index 8275cb45..d6f31837 100644 --- a/src/Media_Command.php +++ b/src/Media_Command.php @@ -218,6 +218,10 @@ public function regenerate( $args, $assoc_args = array() ) { * : If set, media files (local only) are imported to the library but not moved on disk. * File names will not be run through wp_unique_filename() with this set. * + * [--destdir=] + * : Path to specific directory where to upload imported files. + * Can be absolute or relative to ABSPATH. + * * [--preserve-filetime] * : Use the file modified time as the post published & modified dates. * Remote files will always use the current time. @@ -272,6 +276,7 @@ public function import( $args, $assoc_args = array() ) { 'alt' => '', 'desc' => '', 'post_name' => '', + 'destdir' => '', ) ); @@ -411,6 +416,12 @@ public function import( $args, $assoc_args = array() ) { } wp_update_attachment_metadata( $success, wp_generate_attachment_metadata( $success, $file ) ); } else { + + $destdir = Utils\get_flag_value( $assoc_args, 'destdir' ); + if ( is_string( $destdir ) && $destdir ) { + $custom_upload_dir_filter = $this->add_upload_dir_filter( $destdir ); + } + // Deletes the temporary file. $success = media_handle_sideload( $file_array, $assoc_args['post_id'], $assoc_args['title'], $post_array ); if ( is_wp_error( $success ) ) { @@ -468,6 +479,10 @@ public function import( $args, $assoc_args = array() ) { ++$successes; } + if ( ! empty( $custom_upload_dir_filter ) ) { + $this->remove_upload_dir_filter( $custom_upload_dir_filter ); + } + // Report the result of the operation if ( ! Utils\get_flag_value( $assoc_args, 'porcelain' ) ) { Utils\report_batch_operation_results( $noun, 'import', count( $args ), $successes, $errors ); @@ -939,6 +954,45 @@ private function remove_image_size_filters( $image_size_filters ) { } } + private function add_upload_dir_filter( $upload_dir ) { + + $custom_upload_dir_filter = function () use ( $upload_dir ) { + static $custom_upload_dir; + if ( $custom_upload_dir ) { + return $custom_upload_dir; + } + + if ( 0 !== strpos( $upload_dir, ABSPATH ) ) { + // $cir is absolute, $upload_dir is (maybe) relative to ABSPATH. + $dir = path_join( ABSPATH, $upload_dir ); + } else { + $dir = $upload_dir; + // normalize $upload_dir. + $upload_dir = substr( $upload_dir, strlen( ABSPATH ) ); + } + + $siteurl = get_option( 'siteurl' ); + $url = trailingslashit( $siteurl ) . $upload_dir; + + $custom_upload_dir = array( + 'path' => $dir, + 'url' => $url, + 'subdir' => '', + 'basedir' => $dir, + 'baseurl' => $url, + 'error' => false, + ); + + return $custom_upload_dir; + }; + + add_filter( 'upload_dir', $custom_upload_dir_filter, PHP_INT_MAX, 0 ); + } + + private function remove_upload_dir_filter( $upload_dir_filter ) { + remove_filter( 'upload_dir', $upload_dir_filter, PHP_INT_MAX ); + } + // Update attachment sizes metadata just for a particular intermediate image size. private function update_attachment_metadata_for_image_size( $id, $new_metadata, $image_size, $metadata ) {