Class PHP pour Gestion de code, mime type, etc...
Par Stéphane HUC, samedi 28 août 2004 à 09:30 :: Web ... maestria :: #118 :: rss :: PDF
Si on créé un site, à partir de XML et que la source se veut être du XHTML Strict conforme aux recommandations du W3C, il importe d'informer le navigateur web utilisé, graphique ou non, du mime type adhoc !
Selon les recommandations, toujours, il est hautement préférable d'annoncer pour du XHTML, un mime type ayant pour information application/xhtml+xml en lieu et place du fameux text/html, et ce même pour la version 1.0.
Le problème est qu'il y a des navigateurs qui ne reconnaissent pas du tout ce format de mime type ... dans ce cas, mieux vaut dispenser du bon vieux HTML 4.01, et Strict si possible tout autant !
...
Il faut donc gèrer la reconnaissance du support du mime type et retourner autant le bon mime type qu'un code propre selon la DTD retournée, elle aussi. Hors, du code XHTML n'est pas exactement écrit pareil que du code HTML ; preuve en est au moins toutes les balises dites vides que sont par exemple les meta, link, et autres hr, br, etc...
Et créer en plus du code HTML est une redondance, dont on peut bien se passer !!!
Alors comment faire ?
Trainant une fois de plus sur le site d'un confrère, bien meilleur que moi, le véritable CyberCodeur, et lisant son article Développer avec les standards Web, mon attention a été attiré tout particulierement sur la section 5 (qui explique d'ailleurs bien mieux que moi, les raisons d'utiliser correctement le bon mime type...) ; cette section informe d'un autre article Serving up XHTML with the correct MIME type qui tient compte des spécificités dont je vous ai parlé ci-dessus, en entrée. (Pour ceux qui comprennent l'anglais, allez donc faire un tour... c'est tout autant excellent !)
Voila pour les bases qui m'ont servi pour créer une class PHP qui gère correctement le mime type à annoncer, qui gère la bonne DTD, et qui excellence de l'excellence me permet de gèrer correctement les éléments dits vides, et d'autres petites choses. Elle permet aussi, pour les navigateurs qui en sont capables, d'envoyer le code (x)HTML en format compressé ; autre méthode pour soulager la bande passante, et les ressources serveurs.
La Class(e)
Si la fameuse Class est visible ici (Choisissez "Gestion du code web à retourner selon le navigateur utilisé" !), je m'en vais essayer un peu de mieux vous expliquer...
Le constructeur de la class a pour but de chercher à savoir quel est le navigateur utilisé, ce qu'il est capable de gèrer par les informations qu'il retourne afin de retourner un mime type correct.
function set_agent () {
$this->agent = $_SERVER["HTTP_USER_AGENT"];
$this->accept = $_SERVER["HTTP_ACCEPT"];
$this->accept_encoding = $_SERVER["HTTP_ACCEPT_ENCODING"];
$this->mimes = array ("text/html", "application/xhtml+xml", "application/xml", );
$this->charsets = array ("ISO-8859-1", "UTF-8", );
$this->websrc = array ("HTML 4.01", "XHTML 1.0", "XHTML 1.1", );
if(stristr($this->accept, $this->mimes[2]) || stristr($this->agent, "W3C_Validator")) $this->mime = $this->mimes[2];
elseif(stristr($this->accept, $this->mimes[1])) $this->mime = $this->mimes[1];
else $this->mime = $this->mimes[0];
return $this->mime;
}
La méthode get_prologue nous permet, elle, de retourner les entêtes http correctes selon le mime type adopté, et de retourner et publier l'encodage choisi selon le code source qui sera "affiché" par le navigateur.
Selon ce fameux mime type, on remarquera l'appel à deux autres méthodes, dont l'une $this->buffering permet la compression des données envoyées au navigateur, et l'autre ob_start(array("set_agent","fix_code")) permet de "corriger" les élèments vides au navigateur qui ne gère pas le mime type application/xhtml+xml mais text/html à qui l'on a retourné une DTD de type HTML 4.01 Strict pour être conforme à la recommandation adéquate.
Au demeurant, l'appel à cette deuxième fonction se gère ainsi, car nous passons la méthode fix_code de la class set_agent au sein d'un buffer de sortie (cf, les commentaires sur PHP.net::ob_start...)... autrement en tant que function simple en dehors d'une class, il aurait fallu l'écrire comme elle est définit dans l'article de Keystone ci-dessus : ob_start("fix_code").
function get_prologue() {
$this->get_charset();
switch($this->mime) {
case $this->mimes[2] :
$this->buffering();
$this->prologue = "...";
break;
case $this->mimes[1] :
$this->buffering();
$this->prologue = "...";
break;
case $this->mimes[0] :
ob_start(array("set_agent","fix_code"));
$this->prologue = "...";
break;
}
header("Content-Type: ".$this->mime.";charset=".$this->charset);
header("Vary: Accept");
echo $this->prologue;
}
La fameuse function buffering, qui test si le navigateur est capable de recevoir des données compressées, si oui, elle lui sont envoyées ainsi par bufferisation de sortie, encore et toujours.
function buffering() {
if(!empty($this->accept_encoding) && eregi("gzip, deflate", $this->accept_encoding)) {
ob_start("ob_gzhandler");
}
}
Et, pour finir, la function fix_code, inspiré par l'article de Keystone, modifiée ... au départ, elle gère les éléments vides ; maintenant, elle s'occupe aussi de la gestion des attributs xml: et de l'entête html...
Ce qui permet d'écrire un "modéle" de code source en XHTML (et rien qu'un...), et quand cette function est appellée, parce que le navigateur n'est pas à même de gèrer le mime type adhoc, on obtient alors une réécriture du code XHTML en HTML par bufferisation de sortie.
function fix_code($buffer) {
$search = array (
"!html xmlns=\"http://www.w3.org/1999/xhtml\"!",
"!\s*/>!",
"!xml:!",
);
$replace = array (
"html",
">",
"",
);
return (preg_replace($search, $replace, $buffer));
}
Pour finir, je remercie encore le Hub d'être là, et surtout Anonymous... pour son soutien, et ses explications à comprendre comment gèrer les méthodes de class au sein d'une bufferisation de sortie... là, c'était chaud !

PS : Voir le code source de la class et la télécharger pour un usage GNU/LGPL ! (Car, je suis sûr qu'il y en a qui trouveront à l'améliorer sérieusement ;)...)

Commentaires
Aucun commentaire pour le moment.
Ajouter un commentaire
Les commentaires pour ce billet sont fermés.