function rel2abs() dans core/lib/class.plx.utils.php

bazooka07bazooka07 PluXml Lead Developer, Moderator
Bonjour,

Voici une proposition pour améliorer la fonction rel2abs() :
[== PHP ==]
<?php

include('core/lib/class.plx.utils.php');

function rel2abs($base, $html) {
	if (substr($base, -1) != '/')
		$base .= '/';
	// on protège tous les liens externes au site
	$mask = '=<<>>=';
	$result = preg_replace('/(href|src)=("|\')([a-z0-9]+):\/\//i', '\1'.$mask.'\2\3://', $html);
	// tous les autres liens relatifs sont transformés en liens absolus
	$result = preg_replace('/(href|src)=("|\')([^\/])/i', '\1=\2'.$base.'\3', $result);
	// Si $base contient le hostname
	if (preg_match('/^[a-z]+:\/\//i', $base)) {
		$result = preg_replace('/(href|src)=("|\')\/([^\/])/', '\1=\2'.$base.'\3', $result);
	}
	// on retire la protection des liens externes. Expressions régulières lentes et inutiles !!
	$result = str_replace($mask, '=', $result);
	return $result;
}

// ------- for testing -----------
$sample = <<< EOT
blabla <a href="core/admin/test.php">Test</a> le corbeau
coucou <img src='/img/bonjour/toi.jpg' /> tell me why
l'hermine <a href='http://www.pluxml.org'>Pluxml</a> sur un arbre
la belette <script src="//code.jquery.com/"></script> couché
le renard<a href="ftp://www.test.org/readme.txt'>Download</a> s'y perche

EOT;

$base ='http://www.monsite.org/test1';
$base_solo ='/test1';

echo "===== Avec hostname: ============\n";
echo "------ new rel2abs ---------------\n";
echo rel2abs($base, $sample);
echo "---- original rel2 abs ------------\n";
echo plxUtils::rel2abs($base, $sample);
echo "===== Sans hostname: ============\n";
echo "------ new rel2abs ---------------\n";
echo rel2abs($base_solo, $sample);
echo "---- original rel2 abs ------------\n";
echo plxUtils::rel2abs($base_solo, $sample);

?>

En utilisant un masque plus sophistiqué pour protéger les liens externes, on peut remplacer un preg_replace() par un str_replace() plus rapide.
De plus, on gére l'absence de '/' à la fin de $base. Et il n'est plus nécessaire que $base contienne le hostname. L'idée sous-jacente sur le dernier point est de supprimer la répétition du hostname dans tous les liens des pages HTML générés.

Cordialement.

Réponses

  • StéphaneStéphane Member, Former PluXml Project Manager
    Bonjour,

    Très intérressant.
    J'ai référencé ton post sur le github de PluXml pour avoir une trace.
    Va falloir étudier ça de pret maintenant ;)
    Merci pour cette contribution

    https://github.com/pluxml/PluXml/issues/124

    Consultant PluXml

    Ancien responsable du projet (2010 à 2018)

  • bazooka07bazooka07 PluXml Lead Developer, Moderator
    septembre 2015 modifié
    @Stéphane,

    Merci pour ton retour.

    Après lecture du manuel de php, les 3 expressions preg_replace peuvent être regroupées en une seule seule. Au final, on aboutit à ceci :
    [== PHP ==]
    <?php
    function rel2abs($base, $html) {
    	if (substr($base, -1) != '/')
    		$base .= '/';
    	// on protège tous les liens externes au site,
    	// et on transforme tous les liens relatifs en absolus.
    	// on ajoute le hostname si nécessaire
    	$mask = '=<<>>=';
    	$patterns = ['/(href|src)=("|\')([a-z0-9]+):\/\//i', '/(href|src)=("|\')([^\/])/i'];
    	$replaces = ['\1'.$mask.'\2\3://', '\1=\2'.$base.'\3'];
    	if (preg_match('/^[a-z]+:\/\//i', $base)) { 
    		$patterns[] = '/(href|src)=("|\')\/([^\/])/i';
    		$replaces[] = '\1=\2'.$base.'\3';
    	}
    	$result = preg_replace($patterns, $replaces, $html);
    	// on retire la protection des liens externes. Expressions régulières lentes et inutiles !!
    	$result = str_replace($mask, '=', $result);
    	return $result;
    }
    ?>
    
    Cela devrait bien booster la génération des pages html.

    Cordialement.
  • StéphaneStéphane Member, Former PluXml Project Manager
    J'ai des problèmes avec les liens contenant des ancres quand la réécriture d'urls est activée
    ex sur la page des commentaires: http://localhost/PluXml/#form

    Consultant PluXml

    Ancien responsable du projet (2010 à 2018)

  • bazooka07bazooka07 PluXml Lead Developer, Moderator
    Bonjour,

    Impossible de reproduire le problème.
    J'ai mis une page de test ici : http://kazimentou.fr/divers/rel2abs-test.php

    tu as un autre exemple qui bloque ?

    A++
  • bazooka07bazooka07 PluXml Lead Developer, Moderator
    Si vous avez un serveur chez Free, vous utilisez peut-être une vieille version de PHP, à savoir :5.1.3RC4-dev
    En conséquence, il vous manque certaines fonctionnalités comme celle-ci
    La déclaration explicite de tableaux comme ci-après n'est pas reconnue: $tableau =
    Il faut utiliser la fonction array comme ceci : $tableau = array('item', 'item');

    Voici la fonction rel2abs corrigée en conséquence :
    [== PHP ==]
    <?php
    function rel2abs($base, $html) {
    	if (substr($base, -1) != '/')
    		$base .= '/';
    	// on protège tous les liens externes au site,
    	// et on transforme tous les liens relatifs en absolus.
    	// on ajoute le hostname si nécessaire
    	$mask = '=<<>>=';
    	$patterns = array('/(href|src)=("|\')([a-z0-9]+):\/\//i', '/(href|src)=("|\')([^\/])/i');
    	$replaces = array('\1'.$mask.'\2\3://', '\1=\2'.$base.'\3');
    	if (preg_match('/^[a-z]+:\/\//i', $base)) { 
    		$patterns[] = '/(href|src)=("|\')\/([^\/])/i';
    		$replaces[] = '\1=\2'.$base.'\3';
    	}
    	$result = preg_replace($patterns, $replaces, $html);
    	// on retire la protection des liens externes. Expressions régulières lentes et inutiles !!
    	$result = str_replace($mask, '=', $result);
    	return $result;
    }
    ?>
    

    J'ai également corrigé la page de test évoquée dans une discussion précédente.
    A++
  • StéphaneStéphane Member, Former PluXml Project Manager
    C'est bon j'ai trouvé mon erreur. Comme je développe le nouveau système de réponse des commentaires, je me suis loupé sur des liens et donc la réécriture ne fonctionnait pas dans certains cas. Je continue mes tests avec tes modifs ;-)
    Merci

    Consultant PluXml

    Ancien responsable du projet (2010 à 2018)

  • bazooka07bazooka07 PluXml Lead Developer, Moderator
    octobre 2015 modifié
    @Stephane,

    Notes que la base du site n'est obligée de contenir le nom de l'hôte.
    /pluxml/ marche aussi bien que http://localhost/pluxml/. Et les liens vers des sites externes sont préservés.

    Si tu regardes le source de http://www.echecs-annonay.fr (faire Ctrl-U sous Firefox), tu constateras que j'ai fait le ménage de ce côté. Pour les classes de style aussi. Et cela marche très bien sur une tablette ou un smartphone.
Connectez-vous ou Inscrivez-vous pour répondre.