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 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 URL 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'URL que nous avons vus tout à l'heure dans la Problématique : les URL 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 URL de base » de notre fichier .htaccess !

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

#Restauration des URL 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 URL sans problème.

Pour restaurer les URL, il nous faut mettre les adresses « brutes » dans un tableau à part que nous appellerons $raw_URL. Nous utiliserons un autre tableau, $rewritten_URL, 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 index 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_URL & $rewritten_URL
Sélectionnez
<?php

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

$rewritten_URL['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_URL[basename($entry)] = $lang['urlrewrite']['regexes'];
        }
    }
}

?>

Il nous reste maintenant à restaurer les URL par défaut de phpBB.
J'ai choisi de commencer par restaurer les URL 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 URL de la page, j'ai modifié le code utilisé dans includes/page_tail.php :

Récupération des URL à 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_URL($contents, $matches);
        }
    }

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


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

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

    $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_URL as $pool){
            //
            // Old and new rewriting (handled as a pool of URL)
            //
            foreach($pool as $key => $regexes){
                //
                // Each rewrited URL in this URL pool (usually: one)
                // These URL 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_URL[$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 ni 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.