diff --git a/README.md b/README.md index da8b6db19..5e52d9ab6 100644 --- a/README.md +++ b/README.md @@ -1965,7 +1965,7 @@ wp post Creates a new post. ~~~ -wp post create [--post_author=] [--post_date=] [--post_date_gmt=] [--post_content=] [--post_content_filtered=] [--post_title=] [--post_excerpt=] [--post_status=] [--post_type=] [--comment_status=] [--ping_status=] [--post_password=] [--post_name=] [--to_ping=] [--pinged=] [--post_modified=] [--post_modified_gmt=] [--post_parent=] [--menu_order=] [--post_mime_type=] [--guid=] [--post_category=] [--tags_input=] [--tax_input=] [--meta_input=] [] [--=] [--edit] [--porcelain] +wp post create [--post_author=] [--post_date=] [--post_date_gmt=] [--post_content=] [--post_content_filtered=] [--post_title=] [--post_excerpt=] [--post_status=] [--post_type=] [--comment_status=] [--ping_status=] [--post_password=] [--post_name=] [--from-post=] [--to_ping=] [--pinged=] [--post_modified=] [--post_modified_gmt=] [--post_parent=] [--menu_order=] [--post_mime_type=] [--guid=] [--post_category=] [--tags_input=] [--tax_input=] [--meta_input=] [] [--=] [--edit] [--porcelain] ~~~ **OPTIONS** @@ -2009,6 +2009,9 @@ wp post create [--post_author=] [--post_date=] [--post_d [--post_name=] The post name. Default is the sanitized post title when creating a new post. + [--from-post=] + Post id of a post to be duplicated. + [--to_ping=] Space or carriage return-separated list of URLs to ping. Default empty. @@ -2079,6 +2082,10 @@ wp post create [--post_author=] [--post_date=] [--post_d $ wp post create --post_title='A post' --post_content='Just a small post.' --meta_input='{"key1":"value1","key2":"value2"} Success: Created post 1923. + # Create a duplicate post from existing posts. + $ wp post create --from-post=123 --post_title='Different Title' + Success: Created post 2350. + ### wp post delete diff --git a/features/post-create-duplicate.feature b/features/post-create-duplicate.feature new file mode 100644 index 000000000..6bad8f02a --- /dev/null +++ b/features/post-create-duplicate.feature @@ -0,0 +1,82 @@ +Feature: Create Duplicate WordPress post from existing posts. + + Background: + Given a WP install + + Scenario: Generate duplicate post. + When I run `wp term create category "Test Category" --porcelain` + Then save STDOUT as {TERM_ID} + + When I run `wp term create post_tag "Test Tag" --porcelain` + Then save STDOUT as {TAG_ID} + + When I run `wp post create --post_title='Test Duplicate Post' --post_category={TERM_ID} --porcelain` + And save STDOUT as {POST_ID} + + When I run `wp post term add {POST_ID} post_tag {TAG_ID} --by=id` + Then STDOUT should contain: + """ + Success: Added term. + """ + + When I run `wp post create --from-post={POST_ID} --porcelain` + Then STDOUT should be a number + And save STDOUT as {DUPLICATE_POST_ID} + + When I run `wp post get {DUPLICATE_POST_ID} --field=title` + Then STDOUT should be: + """ + Test Duplicate Post + """ + + When I run `wp post term list {DUPLICATE_POST_ID} category --field=term_id` + Then STDOUT should be: + """ + {TERM_ID} + """ + + When I run `wp post term list {DUPLICATE_POST_ID} post_tag --field=term_id` + Then STDOUT should be: + """ + {TAG_ID} + """ + + @require-wp-4.4 + Scenario: Generate duplicate post with post metadata. + When I run `wp post create --post_title='Test Post' --meta_input='{"key1":"value1","key2":"value2"}' --porcelain` + Then save STDOUT as {POST_ID} + + When I run `wp post create --from-post={POST_ID} --porcelain` + Then save STDOUT as {DUPLICATE_POST_ID} + + When I run `wp post meta list {DUPLICATE_POST_ID} --format=table` + Then STDOUT should be a table containing rows: + | post_id | meta_key | meta_value | + | {DUPLICATE_POST_ID} | key1 | value1 | + | {DUPLICATE_POST_ID} | key2 | value2 | + + + Scenario: Generate duplicate page. + When I run `wp post create --post_type="page" --post_title="Test Page" --post_content="Page Content" --porcelain` + Then save STDOUT as {POST_ID} + + When I run `wp post create --from-post={POST_ID} --post_title="Duplicate Page" --porcelain` + Then save STDOUT as {DUPLICATE_POST_ID} + + When I run `wp post list --post_type='page' --fields="title, content, type"` + Then STDOUT should be a table containing rows: + | post_title | post_content | post_type | + | Test Page | Page Content | page | + | Duplicate Page | Page Content | page | + + Scenario: Change type of duplicate post. + When I run `wp post create --post_title='Test Post' --porcelain` + Then save STDOUT as {POST_ID} + + When I run `wp post create --from-post={POST_ID} --post_type=page --porcelain` + Then save STDOUT as {DUPLICATE_POST_ID} + + When I run `wp post get {DUPLICATE_POST_ID} --fields=type` + Then STDOUT should be a table containing rows: + | Field | Value | + | post_type | page | diff --git a/src/Post_Command.php b/src/Post_Command.php index 43ff383e2..9f811d06c 100644 --- a/src/Post_Command.php +++ b/src/Post_Command.php @@ -78,6 +78,9 @@ public function __construct() { * [--post_name=] * : The post name. Default is the sanitized post title when creating a new post. * + * [--from-post=] + * : Post id of a post to be duplicated. + * * [--to_ping=] * : Space or carriage return-separated list of URLs to ping. Default empty. * @@ -147,6 +150,10 @@ public function __construct() { * # Create a post with multiple meta values. * $ wp post create --post_title='A post' --post_content='Just a small post.' --meta_input='{"key1":"value1","key2":"value2"} * Success: Created post 1923. + * + * # Create a duplicate post from existing posts. + * $ wp post create --from-post=123 --post_title='Different Title' + * Success: Created post 2350. */ public function create( $args, $assoc_args ) { if ( ! empty( $args[0] ) ) { @@ -173,6 +180,27 @@ public function create( $args, $assoc_args ) { $array_arguments = array( 'meta_input' ); $assoc_args = \WP_CLI\Utils\parse_shell_arrays( $assoc_args, $array_arguments ); + if ( isset( $assoc_args['from-post'] ) ) { + $post = $this->fetcher->get_check( $assoc_args['from-post'] ); + $post_arr = get_object_vars( $post ); + $post_id = $post_arr['ID']; + unset( $post_arr['post_date'] ); + unset( $post_arr['post_date_gmt'] ); + unset( $post_arr['guid'] ); + unset( $post_arr['ID'] ); + + if ( empty( $assoc_args['meta_input'] ) ) { + $assoc_args['meta_input'] = $this->get_metadata( $post_id ); + } + if ( empty( $assoc_args['post_category'] ) ) { + $post_arr['post_category'] = $this->get_category( $post_id ); + } + if ( empty( $assoc_args['tags_input'] ) ) { + $post_arr['tags_input'] = $this->get_tags( $post_id ); + } + $assoc_args = array_merge( $post_arr, $assoc_args ); + } + $assoc_args = wp_slash( $assoc_args ); parent::_create( $args, $assoc_args, function ( $params ) { return wp_insert_post( $params, true ); @@ -797,4 +825,60 @@ private function get_category_ids( $arg ) { // If no category ids found, return exploded array for compat with previous WP-CLI versions. return $category_ids ? $category_ids : $categories; } + + /** + * Get post metadata. + * + * @param $post_id ID of the post. + * + * @return array + */ + private function get_metadata( $post_id ) { + $metadata = get_metadata( 'post', $post_id ); + $items = array(); + foreach ( $metadata as $key => $values ) { + foreach ( $values as $item_value ) { + $item_value = maybe_unserialize( $item_value ); + $items[$key] = $item_value; + } + } + + return $items; + } + + /** + * Get Categories of a post. + * + * @param $post_id ID of the post. + * + * @return array + */ + private function get_category( $post_id ) { + $category_data = get_the_category( $post_id ); + $category_arr = array(); + foreach ( $category_data as $cat ) { + array_push( $category_arr, $cat->term_id ); + } + + return $category_arr; + } + + /** + * Get Tags of a post. + * + * @param $post_id ID of the post. + * + * @return array + */ + private function get_tags( $post_id ) { + $tag_data = get_the_tags( $post_id ); + $tag_arr = array(); + if ( $tag_data ) { + foreach ( $tag_data as $tag ) { + array_push( $tag_arr, $tag->slug ); + } + } + + return $tag_arr; + } }