diff --git a/src/wp-includes/comment-template.php b/src/wp-includes/comment-template.php index 69dcc1629a..294370c0fe 100644 --- a/src/wp-includes/comment-template.php +++ b/src/wp-includes/comment-template.php @@ -224,7 +224,7 @@ function get_comment_author_link( $comment_ID = 0 ) { if ( empty( $url ) || 'http://' == $url ) { $return = $author; } else { - $return = "$author"; + $return = "$author"; } /** diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index 423db4d540..025cabda19 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -246,7 +246,7 @@ add_filter( 'pre_kses', 'wp_pre_kses_less_than' ); add_filter( 'sanitize_title', 'sanitize_title_with_dashes', 10, 3 ); add_action( 'check_comment_flood', 'check_comment_flood_db', 10, 4 ); add_filter( 'comment_flood_filter', 'wp_throttle_comment_flood', 10, 3 ); -add_filter( 'pre_comment_content', 'wp_rel_nofollow', 15 ); +add_filter( 'pre_comment_content', 'wp_rel_ugc', 15 ); add_filter( 'comment_email', 'antispambot' ); add_filter( 'option_tag_base', '_wp_filter_taxonomy_base' ); add_filter( 'option_category_base', '_wp_filter_taxonomy_base' ); diff --git a/src/wp-includes/formatting.php b/src/wp-includes/formatting.php index eeb3eb62af..ae772b8d0d 100644 --- a/src/wp-includes/formatting.php +++ b/src/wp-includes/formatting.php @@ -3012,35 +3012,19 @@ function _split_str_by_whitespace( $string, $goal ) { } /** - * Adds rel nofollow string to all HTML A elements in content. + * Callback to add a rel attribute to HTML A element. * - * @since 1.5.0 + * Will remove already existing string before adding to prevent invalidating (X)HTML. * - * @param string $text Content that may contain HTML A elements. - * @return string Converted content. + * @since 5.3.0 + * + * @param array $matches Single match. + * @param string $rel The rel attribute to add. + * @return string HTML A element with the added rel attribute. */ -function wp_rel_nofollow( $text ) { - // This is a pre save filter, so text is already escaped. - $text = stripslashes( $text ); - $text = preg_replace_callback( '||i', 'wp_rel_nofollow_callback', $text ); - return wp_slash( $text ); -} - -/** - * Callback to add rel=nofollow string to HTML A element. - * - * Will remove already existing rel="nofollow" and rel='nofollow' from the - * string to prevent from invalidating (X)HTML. - * - * @since 2.3.0 - * - * @param array $matches Single Match - * @return string HTML A Element with rel nofollow. - */ -function wp_rel_nofollow_callback( $matches ) { +function wp_rel_callback( $matches, $rel ) { $text = $matches[1]; $atts = wp_kses_hair( $matches[1], wp_allowed_protocols() ); - $rel = 'nofollow'; if ( ! empty( $atts['href'] ) ) { if ( in_array( strtolower( wp_parse_url( $atts['href']['value'], PHP_URL_SCHEME ) ), array( 'http', 'https' ), true ) ) { @@ -3051,11 +3035,10 @@ function wp_rel_nofollow_callback( $matches ) { } if ( ! empty( $atts['rel'] ) ) { - $parts = array_map( 'trim', explode( ' ', $atts['rel']['value'] ) ); - if ( false === array_search( 'nofollow', $parts ) ) { - $parts[] = 'nofollow'; - } - $rel = implode( ' ', $parts ); + $parts = array_map( 'trim', explode( ' ', $atts['rel']['value'] ) ); + $rel_array = array_map( 'trim', explode( ' ', $rel ) ); + $parts = array_unique( array_merge( $parts, $rel_array ) ); + $rel = implode( ' ', $parts ); unset( $atts['rel'] ); $html = ''; @@ -3071,6 +3054,63 @@ function wp_rel_nofollow_callback( $matches ) { return "'; } +/** + * Adds `rel="nofollow"` string to all HTML A elements in content. + * + * @since 1.5.0 + * + * @param string $text Content that may contain HTML A elements. + * @return string Converted content. + */ +function wp_rel_nofollow( $text ) { + // This is a pre save filter, so text is already escaped. + $text = stripslashes( $text ); + $rel = 'nofollow'; + $text = preg_replace_callback( + '||i', + function( $matches ) use ( $rel ) { + return wp_rel_callback( $matches, $rel ); + }, + $text + ); + return wp_slash( $text ); +} + +/** + * Callback to add `rel="nofollow"` string to HTML A element. + * + * @since 2.3.0 + * @deprecated 5.3.0 Use wp_rel_callback() + * + * @param array $matches Single match. + * @return string HTML A Element with `rel="nofollow"`. + */ +function wp_rel_nofollow_callback( $matches ) { + return wp_rel_callback( $matches, 'nofollow' ); +} + +/** + * Adds `rel="nofollow ugc"` string to all HTML A elements in content. + * + * @since 5.3.0 + * + * @param string $text Content that may contain HTML A elements. + * @return string Converted content. + */ +function wp_rel_ugc( $text ) { + // This is a pre save filter, so text is already escaped. + $text = stripslashes( $text ); + $rel = 'nofollow ugc'; + $text = preg_replace_callback( + '||i', + function( $matches ) use ( $rel ) { + return wp_rel_callback( $matches, $rel ); + }, + $text + ); + return wp_slash( $text ); +} + /** * Adds rel noreferrer and noopener to all HTML A elements that have a target. * diff --git a/tests/phpunit/tests/formatting/WPRelUgc.php b/tests/phpunit/tests/formatting/WPRelUgc.php new file mode 100644 index 0000000000..515eebb736 --- /dev/null +++ b/tests/phpunit/tests/formatting/WPRelUgc.php @@ -0,0 +1,83 @@ +This is some cool Code

'; + $expected = '

This is some cool Code

'; + $this->assertEquals( $expected, wp_rel_ugc( $content ) ); + } + + /** + * @ticket 48022 + */ + public function test_convert_ugc() { + $content = '

This is some cool Code

'; + $expected = '

This is some cool Code

'; + $this->assertEquals( $expected, wp_rel_ugc( $content ) ); + } + + /** + * @ticket 48022 + * @dataProvider data_wp_rel_ugc + */ + public function test_wp_rel_ugc( $input, $output ) { + return $this->assertEquals( wp_slash( $output ), wp_rel_ugc( $input ) ); + } + + public function data_wp_rel_ugc() { + $home_url_http = set_url_scheme( home_url(), 'http' ); + $home_url_https = set_url_scheme( home_url(), 'https' ); + + return array( + array( + 'Double Quotes', + 'Double Quotes', + ), + array( + 'Double Quotes', + 'Double Quotes', + ), + array( + "Single Quotes", + "Single Quotes", + ), + array( + 'Multiple attributes', + 'Multiple attributes', + ), + array( + 'Multiple attributes', + 'Multiple attributes', + ), + array( + 'Multiple attributes', + 'Multiple attributes', + ), + array( + 'Everything at once', + 'Everything at once', + ), + array( + 'Home URL (http)', + 'Home URL (http)', + ), + array( + 'Home URL (https)', + 'Home URL (https)', + ), + ); + } + + public function test_append_ugc_with_valueless_attribute() { + $content = '

This is some cool Code

'; + $expected = '

This is some cool Code

'; + $this->assertEquals( $expected, wp_rel_ugc( $content ) ); + } +}