@@ -3220,34 +3220,48 @@ function _split_str_by_whitespace( $text, $goal ) {
32203220 * @return string HTML A element with the added rel attribute.
32213221 */
32223222function wp_rel_callback ( $ matches , $ rel ) {
3223- $ text = $ matches [1 ];
3224- $ atts = wp_kses_hair ( $ matches [1 ], wp_allowed_protocols () );
3223+ _deprecated_function (
3224+ __FUNCTION__ ,
3225+ '{WP_VERSION} ' ,
3226+ 'wp_include_in_all_a_rel() '
3227+ );
3228+ return wp_include_in_all_a_rel ( $ matches [0 ], $ rel );
3229+ }
32253230
3226- if ( ! empty ( $ atts ['href ' ] ) && wp_is_internal_link ( $ atts ['href ' ]['value ' ] ) ) {
3227- $ rel = trim ( str_replace ( 'nofollow ' , '' , $ rel ) );
3231+ /**
3232+ * Ensures that all A elements in the given HTML contain
3233+ * the provided and unique “rel” keywords.
3234+ *
3235+ * Example:
3236+ *
3237+ * `<a rel="nofollow">` === wp_include_in_all_a_rel( '<a>', 'nofollow' );
3238+ * `<a rel="nofollow">` === wp_include_in_all_a_rel( '<a rel="nofollow">', 'nofollow' );
3239+ * `<a rel="pingback nofollow">` === wp_include_in_all_a_rel( '<a rel="pingback">', 'nofollow' );
3240+ * `<a rel="a b c">` === wp_include_in_all_a_rel( '<a rel="a a a">`, 'a a a b b c' );
3241+ *
3242+ * @since {WP_VERSION}
3243+ *
3244+ * @param string $html Add the given `rel` keywords to every `A` tag in this HTML.
3245+ * @param string $space_separated_rel_keywords Each of these keywords will be present in the final HTML.
3246+ * @return string Modified HTML with all `A` tags containing the given `rel` keywords.
3247+ */
3248+ function wp_include_in_all_a_rel ( $ html , $ space_separated_rel_keywords ) {
3249+ if ( empty ( $ html ) || empty ( $ space_separated_rel_keywords ) ) {
3250+ return $ html ;
32283251 }
32293252
3230- if ( ! empty ( $ atts ['rel ' ] ) ) {
3231- $ parts = array_map ( 'trim ' , explode ( ' ' , $ atts ['rel ' ]['value ' ] ) );
3232- $ rel_array = array_map ( 'trim ' , explode ( ' ' , $ rel ) );
3233- $ parts = array_unique ( array_merge ( $ parts , $ rel_array ) );
3234- $ rel = implode ( ' ' , $ parts );
3235- unset( $ atts ['rel ' ] );
3253+ $ processor = new WP_HTML_Tag_Processor ( $ html );
3254+ while ( $ processor ->next_tag ( 'A ' ) ) {
3255+ $ rel = $ processor ->get_attribute ( 'rel ' );
3256+ $ rel = is_string ( $ rel ) ? $ rel : '' ;
3257+ $ rel = "{$ rel } {$ space_separated_rel_keywords }" ;
3258+ $ tokens = WP_HTML_Attribute::from_unordered_set_of_space_separated_tokens ( $ rel );
3259+ $ new_rel = empty ( $ tokens ) ? false : implode ( ' ' , $ tokens );
32363260
3237- $ html = '' ;
3238- foreach ( $ atts as $ name => $ value ) {
3239- if ( isset ( $ value ['vless ' ] ) && 'y ' === $ value ['vless ' ] ) {
3240- $ html .= $ name . ' ' ;
3241- } else {
3242- $ html .= "{$ name }= \"" . esc_attr ( $ value ['value ' ] ) . '" ' ;
3243- }
3244- }
3245- $ text = trim ( $ html );
3261+ $ processor ->set_attribute ( 'rel ' , $ new_rel );
32463262 }
32473263
3248- $ rel_attr = $ rel ? ' rel=" ' . esc_attr ( $ rel ) . '" ' : '' ;
3249-
3250- return "<a {$ text }{$ rel_attr }> " ;
3264+ return $ processor ->get_updated_html ();
32513265}
32523266
32533267/**
@@ -3261,13 +3275,7 @@ function wp_rel_callback( $matches, $rel ) {
32613275function wp_rel_nofollow ( $ text ) {
32623276 // This is a pre-save filter, so text is already escaped.
32633277 $ text = stripslashes ( $ text );
3264- $ text = preg_replace_callback (
3265- '|<a (.+?)>|i ' ,
3266- static function ( $ matches ) {
3267- return wp_rel_callback ( $ matches , 'nofollow ' );
3268- },
3269- $ text
3270- );
3278+ $ text = wp_include_in_all_a_rel ( $ text , 'nofollow ' );
32713279 return wp_slash ( $ text );
32723280}
32733281
@@ -3281,6 +3289,11 @@ static function ( $matches ) {
32813289 * @return string HTML A Element with `rel="nofollow"`.
32823290 */
32833291function wp_rel_nofollow_callback ( $ matches ) {
3292+ _deprecated_function (
3293+ __FUNCTION__ ,
3294+ '{WP_VERSION} ' ,
3295+ 'wp_include_in_all_a_rel() '
3296+ );
32843297 return wp_rel_callback ( $ matches , 'nofollow ' );
32853298}
32863299
@@ -3295,13 +3308,7 @@ function wp_rel_nofollow_callback( $matches ) {
32953308function wp_rel_ugc ( $ text ) {
32963309 // This is a pre-save filter, so text is already escaped.
32973310 $ text = stripslashes ( $ text );
3298- $ text = preg_replace_callback (
3299- '|<a (.+?)>|i ' ,
3300- static function ( $ matches ) {
3301- return wp_rel_callback ( $ matches , 'nofollow ugc ' );
3302- },
3303- $ text
3304- );
3311+ $ text = wp_include_in_all_a_rel ( $ text , 'nofollow ugc ' );
33053312 return wp_slash ( $ text );
33063313}
33073314
0 commit comments