diff --git a/src/wp-admin/includes/post.php b/src/wp-admin/includes/post.php index bd13630062..13d9d44bd8 100644 --- a/src/wp-admin/includes/post.php +++ b/src/wp-admin/includes/post.php @@ -314,6 +314,47 @@ function edit_post( $post_data = null ) { $post_data = apply_filters( 'attachment_fields_to_save', $post_data, $attachment_data ); } + // Convert taxonomy input to term IDs, to avoid ambiguity. + if ( isset( $post_data['tax_input'] ) ) { + foreach ( (array) $post_data['tax_input'] as $taxonomy => $terms ) { + // Hierarchical taxonomy data is already sent as term IDs, so no conversion is necessary. + if ( is_taxonomy_hierarchical( $taxonomy ) ) { + continue; + } + + /* + * Assume that a 'tax_input' string is a comma-separated list of term names. + * Some languages may use a character other than a comma as a delimiter, so we standardize on + * commas before parsing the list. + */ + if ( ! is_array( $terms ) ) { + $comma = _x( ',', 'tag delimiter' ); + if ( ',' !== $comma ) { + $terms = str_replace( $comma, ',', $terms ); + } + $terms = explode( ',', trim( $terms, " \n\t\r\0\x0B," ) ); + } + + $clean_terms = array(); + foreach ( $terms as $term ) { + $_term = get_terms( $taxonomy, array( + 'name' => $term, + 'fields' => 'ids', + 'hide_empty' => false, + ) ); + + if ( ! empty( $_term ) ) { + $clean_terms[] = intval( $_term[0] ); + } else { + // No existing term was found, so pass the string. A new term will be created. + $clean_terms[] = $term; + } + } + + $post_data['tax_input'][ $taxonomy ] = $clean_terms; + } + } + add_meta( $post_ID ); update_post_meta( $post_ID, '_edit_last', get_current_user_id() ); diff --git a/tests/phpunit/tests/admin/includesPost.php b/tests/phpunit/tests/admin/includesPost.php index 4ba3de71df..647ff61ecd 100644 --- a/tests/phpunit/tests/admin/includesPost.php +++ b/tests/phpunit/tests/admin/includesPost.php @@ -136,6 +136,45 @@ class Tests_Admin_includesPost extends WP_UnitTestCase { $this->assertEquals( 'draft', get_post( $post->ID )->post_status ); } + /** + * @ticket 30615 + */ + public function test_edit_post_should_parse_tax_input_by_name_rather_than_slug_for_nonhierarchical_taxonomies() { + $u = $this->factory->user->create( array( 'role' => 'editor' ) ); + wp_set_current_user( $u ); + + register_taxonomy( 'wptests_tax', array( 'post' ) ); + $t1 = $this->factory->term->create( array( + 'taxonomy' => 'wptests_tax', + 'name' => 'foo', + 'slug' => 'bar', + ) ); + $t2 = $this->factory->term->create( array( + 'taxonomy' => 'wptests_tax', + 'name' => 'bar', + 'slug' => 'foo', + ) ); + + $p = $this->factory->post->create(); + + $post_data = array( + 'post_ID' => $p, + 'tax_input' => array( + 'wptests_tax' => 'foo,baz', + ), + ); + + edit_post( $post_data ); + + $found = wp_get_post_terms( $p, 'wptests_tax' ); + + // Should contain the term with the name 'foo', not the slug. + $this->assertContains( $t1, wp_list_pluck( $found, 'term_id' ) ); + + // The 'baz' tag should have been created. + $this->assertContains( 'baz', wp_list_pluck( $found, 'name' ) ); + } + /** * @ticket 27792 */