Comment changer de réécriture de liens ?


précédentsommairesuivant

III. Implémentation

Je vous propose de voir l'implémentation en deux étapes : une première approche nous permettra de voir comment fonctionne chaque mécanisme puis nous aborderons l'approche complète.
La raison de cette séparation est que nous avons le contrôle sur les liens figurant à l'intérieur de notre propre site, ce qui signifie que nous pouvons les modifier sans que l'utilisateur final n'en ait connaissance. Cela nous permet d'éliminer peu à peu les liens périmés.
En revanche, les liens situés à l'extérieur de notre site sont hors de notre portée. Il nous faut donc indiquer aux visiteurs qui utilisent ce type de lien qu'il est recommandé de mettre leurs favoris à jour.

III-A. Liens externes

Cela se fait au moyen d'un code HTTP/1.1 : lorsqu'un visiteur utilise une adresse que nous savons mauvaise, il nous faut employer le code 301 ("déplacé de manière permanente"). Nous indiquons ensuite au visiteur l'emplacement de l'adresse correcte.

Redirection à partir d'une adresse incorrecte
Sélectionnez
<?php

header('HTTP/1.1 301 Moved Permanently');
header('Location: nouvelle-adresse.ext');

exit; // Il ne faut rien envoyer d'autre

?>

Dans la pratique, il nous faut d'abord retrouver (restaurer) l'adresse d'origine puis utiliser notre réécriture de liens afin de rediriger vers la bonne adresse.
La première phase (la restauration) est effectuée au moyen du fichier .htaccess : nous substituons la mauvaise adresse par un script de redirection auquel nous indiquons l'adresse standard (nom physique du script + paramètres). De cette manière, il suffit au script de redirection de réécrire cette adresse selon les règles de réécriture que nous avons définies dans le tutoriel précédent.

Fichier : .htaccess
Sélectionnez
DirectoryIndex index.php
Options +FollowSymlinks
RewriteEngine on

#Restauration des URLs de base
RewriteRule ^ftopic([0-9]+).* /phpbb-test/redirect.php?url=viewtopic.php?t=$1 [L]
RewriteRule ^forum([0-9]+).* /phpbb-test/redirect.php?url=viewforum.php?f=$1 [L]

#Réécriture normale
RewriteRule ^sujet-([0-9]+).* /phpbb-test/viewtopic.php?t=$1 [L]
RewriteRule ^forum-([0-9]+).* /phpbb-test/viewforum.php?f=$1 [L]

Nous retrouvons dans ce fichier .htaccess les trois types d'URLs que nous avons vues tout à l'heure dans la Problématique : les URLs de base (viewtopic.php?t=$1), intermédiaires (ftopic[0-9]+.*) et finales (sujet-[0-9]+.*).

Fichier : redirect.php
Sélectionnez
<?php

define('IN_PHPBB', true);

$phpbb_root_path = './';

include($phpbb_root_path . 'extension.inc');
include($phpbb_root_path . 'common.'.$phpEx);


if(!empty($userdata['user_lang'])){
    $current_language = $userdata['user_lang'];
}
else{
    $current_language = $board_config['default_lang'];
}


include($phpbb_root_path.'/language/lang_'.$current_language.'/lang_urlrewrite.'.$phpEx);
if(is_array($lang['urlrewrite'])){
    require_once($phpbb_root_path.'includes/functions_urlrewrite.'.$phpEx);

    $new_url = rewrite_url(urldecode($_GET['url']), $lang['urlrewrite']);

    header('HTTP/1.1 301 Moved Permanently');
    header('Location: '.$new_url['url']);
    exit;
}

?>

L'appel à urldecode() est rendu nécessaire par les scripts utilisant plusieurs paramètres (ils sont légion) et d'une contrainte imposée par notre .htaccess, dans lequel nous avons simulé un appel à urlencode().

Pourquoi urldecode() est nécessaire :
  • /phpbb-test/redirection.php?url=viewtopic.php?t=1&start=25 ==> il y a confusion pour le paramètre "start" qui peut ici être envoyé au script "redirection.php" (ce n'est pas ce que nous voulons)
  • /phpbb-test/redirection.php?url=viewtopic.php?t=1&amp;start=25 ==> "start" n'est pas encore compris comme un paramètre mais comme faisant partie intégrante du paramètre "url" (c'est ce que nous voulons)

Si notre site a subi plusieurs réécritures successives de ses liens, il suffit de compléter la partie "Restauration des URLs de base" de notre fichier .htaccess !

Fichier : .htaccess
Sélectionnez
DirectoryIndex index.php
Options +FollowSymlinks
RewriteEngine on

#Restauration des URLs de base
RewriteRule ^ftopic([0-9]+).* /phpbb-test/redirect.php?url=viewtopic.php?t=$1 [L]
RewriteRule ^forum([0-9]+).* /phpbb-test/redirect.php?url=viewforum.php?f=$1 [L]
RewriteRule ^viewtopic.php?t=([0-9]+) /phpbb-test/redirect.php?url=viewtopic.php?t=$1 [L]
RewriteRule ^viewforum.php?f=([0-9]+) /phpbb-test/redirect.php?url=viewforum.php?f=$1 [L]

#Réécriture normale
RewriteRule ^sujet-([0-9]+).* /phpbb-test/viewtopic.php?t=$1 [L]
RewriteRule ^forum-([0-9]+).* /phpbb-test/viewforum.php?f=$1 [L]

III-B. Liens internes

Si nous observons l'un des fichiers de langue de l'autre tutoriel, nous pouvons remarquer la présence de clefs pour le tableau $lang['urlrewrite']['regexes']. Nous allons utiliser les mêmes clefs dans notre tableau actuel afin de pouvoir faire correspondre les URLs sans problème.

Pour restaurer les URLs, il nous faut mettre les adresses "brutes" dans un tableau à part que nous appelleront $raw_urls. Nous utiliserons un autre tableau, $rewritten_urls, pour contenir les différentes versions de chaque adresse réécrite : l'index "old" sert aux adresses construites par d'anciennes versions de la réécriture de liens de notre site. Chacun des autres indexes correspond à une langue installée dans notre forum phpBB : les utilisateurs ont pu poster des adresses dans toutes ces différentes langues, il faut donc uniformiser la présentation.
Dans tous ces tableaux, nous utiliserons les clefs que nous avons remarquées ci-dessus.

$raw_urls & $rewritten_urls
Sélectionnez
<?php

$raw_urls = array(
    'viewtopic_topicid_title'  => 'viewtopic.php?t=$1',
    'viewforum_id_title'       => 'viewforum.php?f=$1',
// ...
    );

$rewritten_urls['old'] = array(
    'viewtopic_topicid_title'   => array('ftopic([0-9]+)'),
    'viewforum_id_name'         => array('forum([0-9]+)'),
// ...
    );

// ...

if($directory = dir($phpbb_root_path . 'language')){
    while($entry = $directory->read()){
        if(is_file($phpbb_root_path . 'language/' . $entry . '/lang_urlrewrite.'.$phpEx)){
            include($phpbb_root_path . 'language/' . $entry . '/lang_urlrewrite.'.$phpEx);
            $rewritten_urls[basename($entry)] = $lang['urlrewrite']['regexes'];
        }
    }
}

?>

Il nous reste maintenant à restaurer les URLs par défaut de phpBB.
J'ai choisi de commencer par restaurer les URLs par défaut pour ensuite laisser le soin à notre méthode de réécriture de se charger du reste des opérations de la même manière qu'elle en a l'habitude.

Un point de sémantique : dans ce cas précis, "restaurer" signifie retrouver une URL par défaut de phpBB à partir d'une URL réécrite, tandis que "réécrire" signifie modifier l'URL par défaut en une URL réécrite. Les deux termes peuvent être utilisés dans les deux situations, c'est pourquoi je préfère être clair.

Afin de récupérer les URLs de la page, j'ai modifié le code utilisé dans includes/page_tail.php :

Récupération des URLs à restaurer puis à réécrire (fichier : includes/page_tail.php)
Sélectionnez
require_once('functions_urlrewrite.'.$phpEx);
//
// Find all the links in the page
// There are 4 parenthesized parts in these regular expressions:
//   #1: there might be an option like class="..."
//   #2: full path to the target Web page
//   #3: #1 bis
//   #4: text of the link (optional)
//

$regexes = array(
    'a'    => '#<a(.+)href="([^"]+)"([^>]*)>(.*)</a>#Usi',
    'form' => '#<form(.+)action="([^"]+)"([^>]*)>#Usi',
    'link rel'  => '#<link rel(.+)href="([^"]+)"([^>]*)>#Usi'
    );


foreach($regexes as $link_type => $pattern){
    $matches = array();
    if($link_type == 'a'){ // Restore only anchor-type links
        if(preg_match_all($pattern, $contents, $matches, PREG_SET_ORDER)){
            $contents = restore_urls($contents, $matches);
        }
    }

    $matches = array();
    if(preg_match_all($pattern, $contents, $matches, PREG_SET_ORDER)){
        $contents = rewrite_urls($contents, $matches, $link_type);
    }
}


Étudions maintenant la fonction restore_urls().
Le principe est similaire à celui de la fonction rewrite_urls() : commencer par répertorier toutes les URLs à réécrire, puis tout traiter d'un coup à l'aide de la fonction str_replace().

Fonction restore_urls() dans le fichier : includes/functions_urlrewrite.php
Sélectionnez
/*
* Restore URLs to their original (not rewrited) state
* it builds a string suitable for URLs
* @param    string     $string     The string to rewrite
* @global   array      $lang       The language variables
* @return   string                 The rewritten string
*/
function restore_urls($contents, $matches){
    global $raw_urls, $rewritten_urls;

    $patterns       = array();    // The link patterns will be added to this array
    $replacements   = array();    // The link replacements will be added to this array

    foreach($matches as $match){
        $current_url = trim($match[2]);

        if(in_array($current_url, $patterns)){
            continue; // Skip this match
        }

        foreach($rewritten_urls as $pool){
            //
            // Old and new rewriting (handled as a pool of URLs)
            //
            foreach($pool as $key => $regexes){
                //
                // Each rewrited URL in this URL pool (usually: one)
                // These URLs should be available in a generic form
                // using a regular expression syntax (without delimiters)
                //
                foreach($regexes as $key => $regex){
                    $regex = '/'.$regex.'/';
                    if(preg_match($regex, $current_url)){
                        $changed_url = preg_replace($regex, $raw_urls[$key], $current_url);
                        $patterns[] = 'href="'.$current_url.'"';
                        $replacements[] = 'href="'.$changed_url.'"';
                        break 2;
                    }
                }
            }
        }
    }

    return str_replace($patterns, $replacements, $contents);
}

précédentsommairesuivant

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2006 Guillaume Rossolini. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.