web-dev-qa-db-fra.com

Comment utiliser wp_rel_nofollow pour ajouter nofollow aux liens externes uniquement?

Je veux ajouter l'attribut nofollow aux seuls liens externes dans le contenu du message. Les liens internes doivent rester follow.

Alors, puis-je utiliser wp_rel_nofollow() pour créer uniquement des liens externes nofollow? Ou dois-je utiliser une autre méthode?

2
Gixty

wp_rel_nofollow() ajoute l'attribut nofollow à tous les liens afin que nous ne puissions pas l'utiliser ou que je ne sois pas sûr de savoir comment.

Vous pouvez utiliser cette fonction pour ajouter rel="nofollow" à tous les liens externes. Cette fonction vérifie tous les liens du contenu avec l'URL de votre blog/site Web (en tant que domaine interne) et ajoute l'attribut nofollow si les deux ne correspondent pas.

function add_nofollow_external_links( $content ) {
    return preg_replace_callback( '/<a>]+/', 'auto_nofollow_callback', $content );
}
function auto_nofollow_callback( $matches ) {
    $link = $matches[0];
    $site_link = get_bloginfo('url');
    if (strpos($link, 'rel') === false) {
        $link = preg_replace("%(href=S(?!$site_link))%i", 'rel="nofollow" $1', $link);
    } elseif (preg_match("%href=S(?!$site_link)%i", $link)) {
        $link = preg_replace('/rel=S(?!nofollow)S*/i', 'rel="nofollow"', $link);
    }
    return $link;
}
add_filter( 'the_content', 'add_nofollow_external_links' );

pas testé.

2
Robert hue

Basé sur la réponse de @Robert hue et les fonctions wordpress wp_rel_nofollow () et wp_rel_nofollow_callback J'ai proposé cette solution très similaire qui fonctionne pour moi, car pour une raison quelconque, Robert n'a pas ajouté l'attribut nofollow au lien.

function add_rel_nofollow( $text ) {
    // This is a pre save filter, so text is already escaped.
    $text = stripslashes($text);
    $text = preg_replace_callback('|<a (.+?)>|i', 'add_rel_nofollow_callback', $text);
    //$text = wp_slash($text); //I had to remove this because it was adding undesired backslashes to the output
    return $text;
}

function add_rel_nofollow_callback( $matches ) {
    $text = $matches[1];
    $site_link = get_bloginfo('url');

    if (strpos($text, 'rel') === false) {
        $text = preg_replace("%(href=S(?!$site_link))%i", 'rel="nofollow" $1', $text);
    } elseif (preg_match("%href=S(?!$site_link)%i", $link)) {
        $text = str_replace(array(' rel="nofollow"', " rel='nofollow'"), '', $text);
    }       

    return "<a $text rel=\"nofollow\">";
}
add_filter( 'the_content', 'add_rel_nofollow' );

Cela ajoute un attribut rel="nofollow" à toutes les publications antérieures et à venir.

En ce qui concerne les performances, j'ai posé la même question à @Roberthue et voici ce qu'il a dit:

Je ne sais pas pourquoi ça devrait. C'est généralement la même chose que d'utiliser wp_rel_nofollow (), sauf qu'il y a une vérification supplémentaire pour le domaine externe. C'est tout, mais si vous ajoutez des tonnes de domaines à vérifier et à exclure, ce sera probablement le cas. - Robert Hue

1
Gixty

Ni le code de Gixty ni celui de Robert ne fonctionnaient pour moi. Celui de Robert ne correspond même pas correctement aux liens, et même avec le modèle correct, il ne vérifie pas si le lien est interne ou externe et ajoute le nofollow à tous les liens, tandis que celui de Gixty ajoute correctement le nofollow, mais encore à tous les liens, pas seulement internes.

Ceci est mon code, qui fonctionne bien pour moi et ajoute seulement le rel nofollow aux liens internes. Notez également que cela ne touche pas les liens qui ont déjà l'attribut rel, quelle que soit la valeur qu'il puisse avoir.

function add_nofollow_external_links( $content ) {
    return preg_replace_callback( '|<a (.+?)>|i', 'add_nofollow_callback', $content );
}

function add_nofollow_callback( $matches ) {
    $text = $matches[1];
    $site_link = get_bloginfo( 'url' );

    //If this is an internal link, don't touch it
    if( strpos( $text, $site_link ) ) {
        return "<a $text>";
    }     

    //If this doesn't have the rel attribute, append the nofollow
    if( strpos( $text, 'rel' ) === false ) {
        $text = preg_replace( "%(href=S(?!$site_link))%i", 'rel="nofollow" $1', $text );
    } 

    return "<a $text rel=\"nofollow\">";
}
0
Ste_95

J'utilise le code suivant pour que tous les liens externes ne suivent pas et ce code fonctionne.

add_filter('the_content', 'my_nofollow');
add_filter('the_excerpt', 'my_nofollow');

function my_nofollow($content) {
return preg_replace_callback('/<a[^>]+/', 'my_nofollow_callback', $content);
}
function my_nofollow_callback($matches) {
$link = $matches[0];
$site_link = get_bloginfo('url');

if (strpos($link, 'rel') === false) {
    $link = preg_replace("%(href=\S(?!$site_link))%i", 'rel="nofollow" $1', $link);
} elseif (preg_match("%href=\S(?!$site_link)%i", $link)) {
    $link = preg_replace('/rel=\S(?!nofollow)\S*/i', 'rel="nofollow"', $link);
}
return $link;
}
0
Jase

J'utilise la fonction suivante pour ajouter des balises nofollow à des liens externes:

add_filter( 'the_content', 'nofollow_enternal_links');

function nofollow_enternal_links( $content ) {

    $regexp = "<a\s[^>]*href=(\"??)([^\" >]*?)\\1[^>]*>";
    if(preg_match_all("/$regexp/siU", $content, $matches, PREG_SET_ORDER)) {
        if( !empty($matches) ) {

            $srcUrl = get_option('home');
            for ($i=0; $i < count($matches); $i++)
            {

                $tag = $matches[$i][0];
                $tag2 = $matches[$i][0];
                $url = $matches[$i][0];

                $noFollow = '';

                $pattern = '/rel\s*=\s*"\s*[n|d]ofollow\s*"/';
                preg_match($pattern, $tag2, $match, PREG_OFFSET_CAPTURE);
                if( count($match) < 1 )
                    $noFollow .= ' rel="nofollow" ';

                $pos = strpos($url,$srcUrl);
                if ($pos === false) {
                    $tag = rtrim ($tag,'>');
                    $tag .= $noFollow.'>';
                    $content = str_replace($tag2,$tag,$content);
                }
            }
        }
    }

    $content = str_replace(']]>', ']]&gt;', $content);
    return $content;

}

Cela fonctionne sur tout le site et cible tous les articles, même ceux publiés.

Cette approche est différente de l’autre qui fonctionne déjà.

Je poste ceci pour vérifier si quelqu'un peut confirmer si telle ou telle approche est meilleure pour la performance.

0
Christine Cooper

Les autres réponses ne fonctionnent pas dans tous les cas et/ou ne modifient pas les liens alors qu'elles ne devraient pas et/ou ne vérifient pas de manière fiable l'attribut rel s'il existe.

Cette solution est un peu plus complète et permet plus de flexibilité.

// Takes an string of html attr and adds an attribute value; if attr is present and $replace=false, space and the new value is added to end of the attribute; otherwise attr is added to end.
function inject_html_attr($attr_str, $new_attr_name, $attr_value, $replace=false) {
    return preg_replace_callback(
      '/(((?:^|\s)'.$new_attr_name.'=[\'"])(.*?))([\'"])|$/i', 
      function($m)use($new_attr_name,$attr_value, $replace){
        if( $m[0] ){
            $m[1] = $replace ? $m[2] : $m[1].($m[3]?' ':'');
        }else{
            $m[1] = ' '.$new_attr_name.'="'; 
            $m[4] = '"';
        }
        return $m[1].$attr_value.$m[4];
      }, 
    $attr_str, 1 );
}

add_filter('the_content', 'apply_external_link_markup');
function apply_external_link_markup($content) {
    // Assumes attributes are quoted (single or double)
    return preg_replace_callback(
      '/<a ([^>]*)(href=(["\'])(?:https?:)?\\/\\/([^\\/\'">]+)(.*?)\3)([^>]*)>/i', 
      function($m) {
        if( $m[4] === $_SERVER['HTTP_Host'] )
            return $m[0];
        $attr = ' '.trim(trim($m[1]).' '.trim($m[6]));
        //$attr = inject_html_attr( $attr, 'class', 'external-link' );
        //$attr = inject_html_attr( $attr, 'target', '_blank', true );
        $attr = inject_html_attr( $attr, 'rel', 'nofollow', true );
        return '<a '.$m[2].$attr.'>';
      }, 
    $content );
}
0