diff --git a/src/wp-includes/category-template.php b/src/wp-includes/category-template.php index 0525ae792a0d2..9a7361688c544 100644 --- a/src/wp-includes/category-template.php +++ b/src/wp-includes/category-template.php @@ -1194,16 +1194,19 @@ function get_the_tags( $post = 0 ) { * Retrieves the tags for a post formatted as a string. * * @since 2.3.0 - * - * @param string $before Optional. String to use before the tags. Default empty. - * @param string $sep Optional. String to use between the tags. Default empty. - * @param string $after Optional. String to use after the tags. Default empty. - * @param int $post_id Optional. Post ID. Defaults to the current post ID. + * @since 6.8.0 Added the `$tag_template` parameter. + * + * @param string $before Optional. String to use before the tags. Default empty. + * @param string $sep Optional. String to use between the tags. Default empty. + * @param string $after Optional. String to use after the tags. Default empty. + * @param int $post_id Optional. Post ID. Defaults to the current post ID. + * @param string $tag_template Optional. Template for displaying a single tag in the list. + * Default ''. * @return string|false|WP_Error A list of tags on success, false if there are no terms, * WP_Error on failure. */ -function get_the_tag_list( $before = '', $sep = '', $after = '', $post_id = 0 ) { - $tag_list = get_the_term_list( $post_id, 'post_tag', $before, $sep, $after ); +function get_the_tag_list( $before = '', $sep = '', $after = '', $post_id = 0, $tag_template = '' ) { + $tag_list = get_the_term_list( $post_id, 'post_tag', $before, $sep, $after, $tag_template ); /** * Filters the tags list for a given post. @@ -1326,16 +1329,19 @@ function get_the_terms( $post, $taxonomy ) { * Terms are linked to their respective term listing pages. * * @since 2.5.0 - * - * @param int $post_id Post ID. - * @param string $taxonomy Taxonomy name. - * @param string $before Optional. String to use before the terms. Default empty. - * @param string $sep Optional. String to use between the terms. Default empty. - * @param string $after Optional. String to use after the terms. Default empty. + * @since 6.8.0 Added the `$term_template` parameter. + * + * @param int $post_id Post ID. + * @param string $taxonomy Taxonomy name. + * @param string $before Optional. String to use before the terms. Default empty. + * @param string $sep Optional. String to use between the terms. Default empty. + * @param string $after Optional. String to use after the terms. Default empty. + * @param string $term_template Optional. Template for displaying a single term in the list. + * Default ''. * @return string|false|WP_Error A list of terms on success, false if there are no terms, * WP_Error on failure. */ -function get_the_term_list( $post_id, $taxonomy, $before = '', $sep = '', $after = '' ) { +function get_the_term_list( $post_id, $taxonomy, $before = '', $sep = '', $after = '', $term_template = '' ) { $terms = get_the_terms( $post_id, $taxonomy ); if ( is_wp_error( $terms ) ) { @@ -1353,7 +1359,7 @@ function get_the_term_list( $post_id, $taxonomy, $before = '', $sep = '', $after if ( is_wp_error( $link ) ) { return $link; } - $links[] = ''; + $links[] = sprintf( $term_template, esc_url( $link ), esc_html( $term->name ) ); } /** @@ -1446,16 +1452,19 @@ function get_term_parents_list( $term_id, $taxonomy, $args = array() ) { * Displays the terms for a post in a list. * * @since 2.5.0 - * - * @param int $post_id Post ID. - * @param string $taxonomy Taxonomy name. - * @param string $before Optional. String to use before the terms. Default empty. - * @param string $sep Optional. String to use between the terms. Default ', '. - * @param string $after Optional. String to use after the terms. Default empty. + * @since 6.8.0 Added the `$term_template` parameter. + * + * @param int $post_id Post ID. + * @param string $taxonomy Taxonomy name. + * @param string $before Optional. String to use before the terms. Default empty. + * @param string $sep Optional. String to use between the terms. Default empty. + * @param string $after Optional. String to use after the terms. Default empty. + * @param string $term_template Optional. Template for displaying a single term in the list. + * Default ''. * @return void|false Void on success, false on failure. */ -function the_terms( $post_id, $taxonomy, $before = '', $sep = ', ', $after = '' ) { - $term_list = get_the_term_list( $post_id, $taxonomy, $before, $sep, $after ); +function the_terms( $post_id = 0, $taxonomy, $before = '', $sep = '', $after = '', $term_template = '' ) { + $term_list = get_the_term_list( $post_id, $taxonomy, $before, $sep, $after, $term_template ); if ( is_wp_error( $term_list ) ) { return false; diff --git a/tests/phpunit/tests/term/termTemplate.php b/tests/phpunit/tests/term/termTemplate.php new file mode 100644 index 0000000000000..c1e4c4963a3c6 --- /dev/null +++ b/tests/phpunit/tests/term/termTemplate.php @@ -0,0 +1,74 @@ +post->create(); + self::$term_id = $factory->term->create( + array( + 'taxonomy' => 'category', + 'name' => 'Test Category', + ) + ); + self::$second_term_id = $factory->term->create( + array( + 'taxonomy' => 'category', + 'name' => 'Another Category', + ) + ); + wp_set_post_terms( self::$post_id, array( self::$term_id, self::$second_term_id ), 'category' ); + } + + /** + * @ticket 30705 + */ + public function test_get_the_term_list_default_template() { + $list = get_the_term_list( self::$post_id, 'category', '', ', ', '' ); + + $this->assertMatchesRegularExpression( + '/%2$s'; + $list = get_the_term_list( self::$post_id, 'category', '', ', ', '', $custom_template ); + + $this->assertMatchesRegularExpression( + '/Test Category<\/a><\/span>/', + $list + ); + } + + /** + * @ticket 30705 + */ + public function test_get_the_term_list_escaping() { + $unsafe_term_id = self::factory()->term->create( + array( + 'taxonomy' => 'category', + 'name' => 'Test & Category ', + ) + ); + wp_set_post_terms( self::$post_id, array( $unsafe_term_id ), 'category' ); + + $list = get_the_term_list( self::$post_id, 'category', '', ', ', '' ); + + $this->assertStringContainsString( 'Test & Category', $list ); + $this->assertStringNotContainsString( '