| 2988 | * Adds rel nofollow and noopener all HTML A elements in content where target=_blank. |
| 2989 | * |
| 2990 | * @param string $text Content that may contain HTML A elements. |
| 2991 | * @return string Converted content. |
| 2992 | */ |
| 2993 | function wp_rel_nofollow_noopener( $text ) { |
| 2994 | $text = preg_replace_callback( '|<a (.+_blank.+?)>|i', 'wp_rel_nofollow_noopener_callback', $text ); |
| 2995 | return $text; |
| 2996 | } |
| 2997 | |
| 2998 | /** |
| 2999 | * Callback to add rel="nofollow noopener" string to HTML A element that |
| 3000 | * has target=_blank. |
| 3001 | * |
| 3002 | * Will remove already existing nofollow and noopener from the |
| 3003 | * string to prevent from invalidating (X)HTML. |
| 3004 | * |
| 3005 | * @param array $matches Single Match |
| 3006 | * @return string HTML A Element with rel nofollow and noopener if the target is _blank |
| 3007 | */ |
| 3008 | function wp_rel_nofollow_noopener_callback( $matches ) { |
| 3009 | $text = $matches[1]; |
| 3010 | $atts = shortcode_parse_atts( $matches[1] ); |
| 3011 | $rel = 'nofollow noopener'; |
| 3012 | |
| 3013 | if ( ! isset( $atts['target'] ) || '_blank' !== $atts['target'] ) { |
| 3014 | return "<a $text>"; |
| 3015 | } |
| 3016 | |
| 3017 | if ( ! empty( $atts['rel'] ) ) { |
| 3018 | $parts = array_map( 'trim', explode( ' ', $atts['rel'] ) ); |
| 3019 | if ( false === array_search( 'nofollow', $parts ) ) { |
| 3020 | $parts[] = 'nofollow'; |
| 3021 | } |
| 3022 | if ( false === array_search( 'noopener', $parts ) ) { |
| 3023 | $parts[] = 'noopener'; |
| 3024 | } |
| 3025 | $rel = implode( ' ', $parts ); |
| 3026 | unset( $atts['rel'] ); |
| 3027 | |
| 3028 | $html = ''; |
| 3029 | foreach ( $atts as $name => $value ) { |
| 3030 | $html .= "{$name}=\"$value\" "; |
| 3031 | } |
| 3032 | $text = trim( $html ); |
| 3033 | } |
| 3034 | return "<a $text rel=\"$rel\">"; |
| 3035 | } |
| 3036 | |
| 3037 | /** |