L'appartement

Aller au contenu | Aller au menu | Aller à la recherche

Le PHP

Ici on parle aussi bien de Mysql, de PHP que de HTML en passant par CSS et Ajax. Pas très logique mais bon

Fil des billets - Fil des commentaires

vendredi, avril 11 2008

Script minimaliste : nettoyer une boite aux lettres avec une expression rationnelle

Dans la catégorie des scripts minimalistes (mais néanmoins utiles), je vous propose un petit script qui permet d'effacer, en ligne de commande avec PHP CLI, certains messages d'un compte mail en fonction d'une expression régulière précisée en paramètre et qui matche le sujet du mail.

Par exemple, effacer les centaines de messages de spam qui se trouvent dans une de vos nombreuses boites tant inutiles que nécessaires ;) Autre exemple, j'exécute ce script via un cron pour nettoyer tous ce qui traine dans des boites genre postmaster, abuse (encore que cette dernière n'est pas trop pourrie par le SPAM), et autres bal « no-reply » qu'il reste quand même, pour certaines, nécessaires de consulter tous les ans régulièrement.

C'est un script clairement dédié à de la maintenance. Je vous déconseille de laisser trainer ce code n'importe ou accessible via le web.

Utilisation :

cleanmail -u=nom_utilisateur -p=mot_de_passe -s=imap.mondomain.tld:143 -e="/SPAM/i"

Pour être sur que tous le monde a compris :

  • -u= nom d'utilisateur du compte mail
  • -p= mot de passe du compte mail
  • -s= serveur (pop ou imap). Toutes les options disponibles sur la fonction imap_open de PHP sont disponible
  • -e= expression régulière qui sera « passée » à preg_match

Le script :

#!/usr/bin/php
<?php
// on supprime la limite d'éxecution d'un script php
set_time_limit(0);

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * cleanmail supprimer des mails d'une boite imap avec une pattern définie
 *
 * PHP versions 5
 *
 * LICENSE: Ce programme est un logiciel libre distribue sous licence GNU/GPL
 *
 * @author     Yves Tannier <yvesSANSPAM grafactory.net>
 * @copyright  2008 Yves Tannier
 * @license    http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version    0.1.0
 * @link       http://www.grafactory.net
 */


// aide contextuelle
$help_string = "Parametres :
                -u : utilisateur
                -p : mot de passe
                -s : serveur et port (localhost:143, localhost:110, localhost:143/novalidate-cert...)
                -e : expression régulière
                -h, --help : afficher cette aide...\n\n"
;

// recuperer les parametres passe en CLI
foreach($_SERVER['argv'] as $param) {
    // utilisateur
    if(strpos($param,"u=")) {
        $login_imap = str_replace("-u=","",$param);
        continue;
    }
    // mot de passe
    if(strpos($param,"p=")) {
        $passwd_imap = str_replace("-p=","",$param);
        continue;
    }
    // serveur et port
    if(strpos($param,"s=")) {
        $server_imap = str_replace("-s=","",$param);
        continue;
    }
    // expression reguliere
    if(strpos($param,"e=")) {
        $pattern = str_replace('-e=','',$param);
        continue;
    }
    switch($param) {
      case '-h' :
      case '--help' :
        echo $help_string;
        exit();
      case $_SERVER['SCRIPT_NAME'] :
        unset ($_SERVER['argv'][0]);
        break;
      default :
        echo "\nParamètre inconnu : ".$param."\n\n";
        exit();
    }
}

// pas d'argument
if (empty($_SERVER['argv'])) {
    echo "\nVeuillez preciser au moins un paramètre !\n\n";
    echo $help_string;
    exit();
}

// connexion
$mbox = imap_open("{".$server_imap."}INBOX", $login_imap, $passwd_imap)
            or die("Impossible de se connecter : ".imap_last_error());

echo "Connexion...\n";

// recup des headers
$headers = imap_headers($mbox);

// parcourir les messages
if(!empty($headers)) {
    echo "Recherche avec l'expression : ".$pattern."\n";
        $msgnum = 0;
        foreach ($headers as $val) {
            $msgnum = $msgnum + 1;
            $header = imap_headerinfo($mbox, $msgnum);
            $subject = $header->subject;
            if (preg_match($pattern, $subject)) {
                $mailmarked = imap_delete($mbox, $msgnum);
                echo "Message ".$msgnum." supprimé\n";
            }
        }
} else {
    echo "Aucun message dans la boite\n";
}

echo "Fin de la transaction\n";

// quitter et vider en meme temps
imap_close($mbox,CL_EXPUNGE);
?>

Bientôt le même mais en perl ;)

lundi, mars 24 2008

A la découverte de Jelix, l'essayer c'est l'adopter

Logo JelixMalgré tous les avantages que j'ai pu trouver à mon framework mes bouts de codes personnels basés sur plusieurs librairies PEAR, je me suis tourné vers quelques choses de plus "moderne" et plus homogène pour mes nouveaux développements. Après pas mal de recherches et d'essais, mon choix c'est porté sur Jelix.

Ca tombe bien. Un nouveau projet dont les contraintes correspondent parfaitement à l'utilisation de ce framework me permet donc actuellement de me frotter à la bête... Et je ne suis pas déçu !

Je ne vais pas rentrer dans le détail des fonctionnalités mais il y a tous ce qu'on peux rechercher dans un framework PHP5 orienté objet et de classe américaine. Jelix ne pas fait le café comme Symfony (que j'ai essayé également et qui possède de nombreux avantages) et c'est justement pas ce que je lui demande car je souhaite garder la compréhension globale de ce que j'utilise. C'est léger, rapide et extensible. Bref, que du bon pour l'instant ;)

Voici ce que j'en retiens principalement (liste non exhaustive). J'ai précisé, pour mémoire, les équivalents de ce que j'utilisais comme librairies PEAR :

  • ORM puissant. J'utilisais PEAR::MDB2 très efficace aussi. Surtout la gestion transactions
  • système de templates. Beaucoup mieux que PEAR::HTML_Template_Flexy pour lequel la syntaxe dans le template reste assez réduite (exemple : impossible d'utiliser des opérateurs de comparaisons)
  • localisation. PEAR::Translation2 ne m'a jamais réellement séduit.
  • génération de formulaire. Quand on a prit l'habitude d'utiliser PEAR::HTML_Quickform, on recherche forcément quelque chose de similaire.
  • système de cache. Je n'ai pas encore eu la possibilité de comparer avec les performances de PEAR::Cache_Lite mais ça semble équivalent.
  • Quelques modules bien utiles comme la génération de CRUD, le module d'authentification, les acls...

La présentation détaillée et une application de tests sont disponibles sur le site officiel. Il ne vous reste plus qu'à essayer ;)

Si vous aviez l'intention de vous rendre aux Rencontres Mondiales du Logiciel Libre 2008 à Mont-de-Marsan, assistez à la conférence sur Jelix de Laurent Jouanneau et vous en apprendrez encore plus !

vendredi, novembre 9 2007

Petite mise à jour du script de mass mailing

Mass

C'est une mise à jour mineure. Les fonctionnalités sont les même que celles de la première version

J'ai eu quelques soucis avec la classe Zend_Mail. Lors d'un envoi, suite à une mise à jour de Zend_Mail, je me suis retrouvé avec des groupes de destinataires en copie au lieu d'un envoi unitaire (pas très sérieux !).

J'ai donc utilisé le "bon vieux" PHPMailer. J'en ai aussi profité pour remplacer PEAR::DB par PDO. Ce qui rend le script plus léger et plus simple à installer ;) . Je l'ai également doté d'un fichier de configuration séparé.

Changelog :

  • Utilisation de PHPMailer à la place de Zend_Mail
  • Utilisation de PDO à la place de PEAR::DB
  • Changement esthétique.
  • Un fichier de configuration séparé.

Documentation

Vous devez télécharger PHPMailer, disposer de PHP5 et l'extension PDO.

Pour le reste, la documentation de la première mouture est toujours valable. Vous pouvez également utiliser toutes les options disponibles dans PHPMailer pour adapter ce script à votre convenance (je vous laisse chercher dans le script).

Important : Ce programme est fourni sans aucune garantie même si je l'utilise toutes les semaines pour une newsletter de 30 000 abonnés.

A faire :

  • une option pour préciser le chemin du fichier de configuration
  • en extra, toujours le gros boulot qui consiste à analyser les retours de mail (Delivery Error).

Téléchargement

télécharger le script

mardi, juillet 17 2007

Passage sur Dotclear 2 Beta7

Apparement, il y avait une grosse faille de sécurité chez Dotclear. J'ai donc mis à jour. Pour mon blog, pas de problème. Pour la plateforme multiblogs que je gère, ca a été plus compliqué.

Le moteur utilisé par Dotclear 2 avec Mysql maintenant InnoDB. C'est bien. Il y a des belles contraintes d'intégrité partout ;)

Va savoir pourquoi, l'intégrité n'était plus de mise sur la base multiblogs, il y avait des enregistrements orphelins qui ne faisaient plus référence. J'ai du donc nettoyer un peu :

DELETE FROM `dc_post` WHERE blog_id NOT IN (SELECT blog_id FROM dc_blog);
DELETE FROM `dc_category` WHERE blog_id NOT IN (SELECT blog_id FROM dc_blog);
DELETE FROM `dc_link` WHERE blog_id NOT IN (SELECT blog_id FROM dc_blog);
DELETE FROM `dc_permissions` WHERE blog_id NOT IN (SELECT blog_id FROM dc_blog);
DELETE FROM `dc_setting` WHERE blog_id NOT IN (SELECT blog_id FROM dc_blog);
DELETE FROM `dc_spamrule` WHERE blog_id NOT IN (SELECT blog_id FROM dc_blog);
DELETE FROM `dc_media` WHERE user_id NOT IN (SELECT user_id FROM dc_user);
DELETE FROM `dc_comment` WHERE post_id NOT IN (SELECT post_id FROM dc_post);
DELETE FROM `dc_media` WHERE user_id NOT IN (SELECT user_id FROM dc_user);
DELETE FROM `dc_post_media` WHERE media_id NOT IN (SELECT media_id FROM dc_media);
DELETE FROM `dc_post_media` WHERE post_id NOT IN (SELECT post_id FROM dc_post);

Ca pourrait-être intégré dans le code de Dotclear avant une mise à jour ?!

dimanche, juillet 15 2007

PhpMyAdmin, Vista inside ?

Phpmyadmin Erreur

Une erreur windowsienne :)

jeudi, juillet 5 2007

Plugin importer des auteurs

Logo importer des auteursUn nouvelle version de mon plugin SPIP qui permet de créer des auteurs en masse à partir d'un fichier csv.

Outre l'ajout de plusieurs fonctionnalités, j'ai fais en sorte que le code soit modifiable assez facilement pour une personne ayant quelques connaissances en PHP. On m'a en effet plusieurs fois demandé comment modifier le plugin pour choisir les identifiants et mot de passe, avoir un mot de passe identique à l'identifiant...

Plus d'informations sur l'article Importer des auteurs v-0.5

dimanche, juillet 1 2007

Passage du blog sous Dotclear 2

dotclear_pw.png Etant un utilisateur de la première heure de Dotclear, je me devais de passer sur Dotclear 2 Beta6. Utilisation du plugin Flat Export, changement des chemins d'images avec une ou deux requête SQL bien placée*, mise en place des redirections des anciennes URL vers les nouvelles... Reste plus que le thème à changer pour remettre le mien.

  • mes requêtes SQL pour le changement de /blog/images en /blog/public/images dans les champs post_content et post_content_xhtml de la table dc_post :
UPDATE dc_post SET post_content = replace(post_content,'blog/images','blog/public/images');
UPDATE dc_post SET post_content_xhtml = replace(post_content_xhtml,'blog/images','blog/public/images');

lundi, février 5 2007

eZ Publish et "Instant Publishing" avec WebDav

eZ Publish Je n'utilise pas encore eZ Publish mais va falloir sérieusement y réfléchir. Pourquoi ? Parceque la gestion d'un site par glisser/déposer de fichiers OpenOffice (Word aussi avec OpenXML ?) via un partage WebDav, c'est trop fort ;)

Un petit ''trailer'' en Flash pour s'en convaincre. Si vous n'êtes pas patient, attaquez directement le chapitre "Instant Publishing".

Démonstration de eZ Publish

mercredi, janvier 24 2007

Un système de template ultra-minimaliste

Voici un petit bout de code php5 qui permet de créer simplement des fichiers à partir d'un modèle. Comme mon explication est loin d'être évidente ;) voici un exemple avec un fichier de zone DNS. Ici, tout ce qui est mis entre accolade doit être remplacé par sa valeur.

$TTL 3600
{domain}.               IN  SOA {ns1}.   {contactzone}. (
            {timestamp}
            10800
            3600
            604800
            3600 )

{domain}.               IN  NS      {ns1}.
{domain}.               IN  NS      {ns2}.

; Enregistrements Spf

{domain}.               IN  TXT     "v=spf1 a mx ~all"
mail.{domain}.          IN  TXT     "v=spf1 a -all"

www.{domain}.           IN  A       {ipl}
{domain}.               IN  A       {ipl}
ftp.{domain}.           IN  A       {ipl}
mail.{domain}.          IN  A       {ipl}

{domain}.               IN  MX  10  mail.{domain}.
{domain}.               IN  MX  20  mx-backup.sivit.fr.

smtp.{domain}.          IN  CNAME   mail.{domain}.
pop.{domain}.           IN  CNAME   mail.{domain}.

Voici donc la méthode en question qui s'intégrera parfaitement dans votre classe :

<?php
   /** Création de fichier de configuration
    *
    * Mini système de template pour créer des fichiers de configuration à partir d'un squelette
    * en remplaçant {pattern} par la valeur
    *
    * @access   public
    * @return    bool
    * @param    string  $orig         Fichier "template"
    * @param    string  $dest        Fichier de destination
    * @param    array   $keywords Mots à rechercher dans le template
    * @param    array   $values     Valeur de remplacement
    */

    public function setConfigFile($orig,$dest,$keywords,$values)
    {

        // contenu du fichier dans un variable
        $content = file_get_contents($orig);

        // ajout pattern
        foreach($keywords as $key=>$value) {
            $patterns[] = "/{".$value."}/imSU";
        }

        // remplacement
        $output_content = preg_replace($patterns, $values, $content);

        // variable dans un fichier ou exception
        if(!file_put_contents($dest,$output_content)) {
            throw new Exception('Erreur dans la creation du fichier');
        }

        return true;
       
    }

    // }}}
?>

Pour notre exemple, je passe sur l'instanciation de la classe, On utiliserais la méthode de la façon suivante :

<?php

// on a un objet obj

// à remplacer...
$keywords = array('domain','ns1','ns2','timestamp','contactzone');

// par :
$values = array('toto.com','ns1.toto.com','ns2.toto.com',date('Ymdi'),'technique.toto.com');

// go !
$obj->setConfigFile('zonedns.tpl','/var/cache/bind/toto.com.hosts', $keywords, $values);
?>

Ce script n'a rien de révolutionnaire mais je trouve ça pratique. Ca ressemble de très loin à un système de template minimaliste ;)

PS : pour les allergiques à l'orienté objet, vous pouvez bien entendu l'utiliser comme une simple fonction

samedi, novembre 25 2006

Découverte du framework Symfony

Symfony Voici quelques jours, j'ai décidé de me lancer à l'assaut du framework Symfony dont j'entendais parler ici et là depuis déjà quelques temps.

Développé à la base par une société française (sous licence MIT), ce framework veut se la jouer Ruby On Rails par sa puissance pour mettre en oeuvre rapidement une application complète.

Il a récemment connu une publicité inespérée. Yahoo! a en effet annoncé sont utilisation pour la réalisation de sa nouvelle plateforme "social networking" de gestion de bookmark.

Un "Admin Generator" puissant, des outils complet en ligne de commande, des fichiers de descriptions d'interfaces simplifiés en XML ou en YAML... Bref, tout ce qu'il faut pour construire une application fonctionnelle sans aucune ligne de PHP (j'exagère un peu quand même).

Symfony utilise à fond les possibilités objet de PHP5 et repose notamment sur le pattern ORM (Object-relational mapping) via propel pour vous générer en quelques secondes et sans effort vos modèles de base d'accès aux données (le fameux CRUD : Create, Read, Update and Delete).

Courez donc vite sur le site de Symfony pour y découvrir quelques vidéos et exemples qui vous donnerons sans doute envie d'aller plus loin.

Si vous êtes convaincu et que vous cherchez à débuter en français, voici deux liens :

Ensuite, en anglais, pour l'instant un howto en 21 épisodes pour construire de A à Z une application :

Vivement plus de documentation francophone sur le sujet ;)

jeudi, octobre 26 2006

Un plugin pour SPIP

SPIP[auto-promo] J'ai déposé un petit plugin sur Spip-contrib. C'est tout simple mais ça peut servir ;)

Importer des auteurs On a parfois besoin d’ajouter un grand nombre de rédacteurs. Ce plugin le permet simplement depuis un fichier de type csv (Comat Separated Value) placé dans ecrire/data.

dimanche, juillet 2 2006

SPIP 1.9 dans les bacs

SPIPL'un des seul CMS traduit en esperanto et en créole réunionais vient de sortir dans une version 1.9 qui apporte un bon lot de nouveautés et une évolution majeure. On notera la possibilité d'utiliser directement la syntaxe de SPIP pour interroger n'importe quelle table. Exemple :

<BOUCLE_maboucle(MATABLE)>
#CHAMP_DE_MA_TABLE>
</BOUCLE>

Bien pour les non codeurs ;)

Mais aussi un nouveau système de plugins, la possibilité de "surcharger" toutes les fonctions et pages, l'abandon (enfin) des .php3, une couche d'abstraction plus mieux etc... Plus d'informations sur cette nouvelle version 1.9 de SPIP.

vendredi, juin 9 2006

Un script simple de "mass mailing" en PHP

Mass

Mise à jour !

IMPORTANT : Une nouvelle version qui corrige un bug avec Zend_mail est disponible.

Depuis le temps qu'il fallait que j'abandonne ce misérable logiciel de gestion de newsletter sous Winchose pas pratique du tout j'ai nommé groupmail dont je tairais le nom et qui expédie depuis la (petite) ligne ADSL Wanadoo...

J'ai enfin suivi le conseil : do it your self ! Après avoir regardé avec plus ou moins d'intérêt du côté des solutions de gestion de maling list sous Linux (sympa, mailman, emzl ect...) ou des scripts de gestion de newsletter en différents languages (java, php, perl...), j'ai finalement opté pour l'utilisation de PHP en ligne de commande, CLI - Command Line Interface - pour les intimes, pour réaliser mon propre script de mass mailing.

Préface : la situation

  • un script d'abonnement à la newsletter "fait maison" composé de nombreux champs : nom, prénom, adresse, téléphone, mail, profession ect... Déclaré à la CNIL, ne m'envoyez pas la police ;)
  • une table Mysql pour stocker tout ça bien entendu
  • un serveur dédié sous Debian avec PHP5, PEAR, Zend Framework (version subersion car quelques bug sur le Zend_Mail component actuel), Postfix et une bonne bande passante
  • un message tout en html (avec quand même un texte alternatif disponible pour les fanatiques de mutt).
  • et enfin, tout de même 25000 abonnés à cette liste

Introduction : comment ça marche ?

  • On exécute le script en ligne de commande (dans un screen ou en tache de fond pour le laisser tourner ensuite)
  • Le script (interactif) demande quel fichier html il doit utiliser pour le message. Par défaut, il propose le dernier fichier trouvé dans le répertoire $dir_html
  • Les messages sont envoyés un par un par paquets de 100 (nombre de messages par paquet configurable)
  • Une pause de 15 secondes est effectuée entre chaque paquets. On en profite pour réinitailiser la connection avec le serveur SMTP ( le temps de la pause est également configurable).
  • A chaque envoi réussi (la validation de l'envoi est à revoir), un champ booleen "envoye" est mis à jour dans la table des abonnés. En cas de plantage, il suffit donc de relancer le script pour reprendre l'expédition.
  • Avant de relancer le script pour une nouvelle lettre d'informations, une option permet de remettre le flag "envoye" à zéro.

Chapitres suite et fin ;)

Lire la suite...

vendredi, mai 12 2006

Une erreur PHP "intéressante"

Question à 2 cents d'Euros : Quels fichiers sur les 5000 fichiers du site produit cette erreur ?

[12-May-2006 16:18:12] PHP Warning:  Cannot modify header information - headers already sent in Unknown on line 0

Reste plus qu'à compiler Xdebug sur la machine en production ?!

mardi, mai 2 2006

Ajouter des champs richtext avec HTML Quickform

Pear Etant un fervent utilisateur des nombreuses librairies d'objets disponibles sur le repository PEAR, j'utilise très souvent la classe HTML Quickform. Elle permet, comme son nom l'indique, de générer très rapidement des formulaires complets autant au niveau de la présentation [1] que sur le contrôle (les validations peuvent se faire client side en Javascript et/ou server side en PHP).

Je ne vais pas ici vous exposer comment utiliser cette classe. La documentation officielle fournie quelques exemples et les deux tutoriaux suivants permettent également d'aborder le sujet :

Ce qu'il me manquait, en plus des classiques champs HTML text, select, textarea, checkbox etc... C'était la possibilité d'ajouter aussi facilement un champ permettant en wysiwyg la saisie de type WiKi. Ce n'est donc qu'une adapatation de la classe de gestion des textarea que j'ai réalisé.

Me basant sur la classe Wiki2xhtml d'Olivier Meunier (le site n'est plus disponible) et de la barre d'outils qu'il lui est associée dans Dotclear, je génére avec la simple ligne suivante, un maaaagnifique champ de saisie "richtext".

<?php
$form->addElement('richtext', 'texte', 'Contenu');
?>

Voici une petite capture d'écran au cas où ca ne serait pas clair.

J'ai très rapidement (excusez donc le côté très simpliste) mis tout celà dans une archive avec, en prime, une petite documentation pour ceux qui souhaiterait l'essayer.

Bien entendu, toutes les méthodes de Quickform sont utilisables avec cette classe.

Et en plus produit je vous offre la petite todo list :

  • Utiliser la classe Text Wiki disponible dans PEAR pour plus de cohérence
  • Faire himself le Javascript et les boutons associés et envisager une prévisualisation directe en Ajax
  • Proposer cet ajout au projet HTML Quickform

Commentaires, corrections et améliorations bienvenues ;)

Notes

[1] On peut aussi utiliser Quickform avec un système de template si on le souhaite. Par exemple, HTML Template Flexy

mardi, janvier 24 2006

Calendrier de spectacles en AJAX

Grâce à la sympathique classe XHRConnection de Thanh, j'ai réalisé un calendrier assez dynamique en AJAX sur le site theatre-contemporain.net que je modifie par petits bouts :

Ce qui est "sympa" :

  • la recherche avancée où l'on choisi dans des listes déroulantes et qui se construit peu à peu
  • le tri par critère sans recharger la page en cliquant sur les entêtes des colonnes
  • idem pour passer de page en page

Ce qu'il reste à faire :

  • la recherche qui se fait au fur et à mesure qu'on choisi les critères
  • améliorer la version sans javascript (mais elle a le mérite d'exister).
  • autres ?

L'AJAX c'est bien quand on en abuse pas ;)

jeudi, décembre 22 2005

Message à caractère informatif

dotclear Mon blog avec un Dotclear passé aujourd'hui en version 1.2.3 (mise à jour de sécurité notament). Et installation d'un filtre antispam sur les trackbacks et les commentaires car je commence à en avoir pas mal :(

J'espère dire adieu au monde du Viagra, des logiciels à 1 $ ect...

mardi, novembre 15 2005

Dotclear, c'est rien que du PHP5

dotclear Hormis le fait qu'il faut si mettre sérieusement vu les nombreuses nouveautés, Olivier Meunier, le développeur en chef de Dotclear (qui "propulse" ce blog) nous annonce sur son blog que la version 2.0 sera exclusivement en PHP5 ! Vu qu'un client me demande depuis quelques temps un système de multiblog , il faut que je me dépêche de mettre à jour le dédié car ça sera aussi une des nouveautés de la prochaine mouture.

Bref, PHP4 est mort, vive PHP5... Quoi PHP6 vient de sortir ;) ?!

mercredi, octobre 26 2005

Simple pour générer des listes de date

Une toute toute petite et minuscule fonction PHP pour générer des listes déroulantes HTML mois / date / année ... Par exemple pour un sytème de recherche dans un calendrier (c'est mon utilisation). C'est pas le code qui va révolutionner le monde mais ca peut toujours servir ;)

<?php
 function generer_liste_date($nom,$periode,$debut,$fin){
     $liste = "<select name=\"".$nom."\">";
     for($i = $debut; $i <= $fin; $i++) {
         $liste .= "<option value=\"".$i."\"";
             if ($i == date($periode))
                 $liste .= "selected=\"selected\" ";
                     if (strlen($i)==1) $i = "0".$i;
        $liste .= ">".$i."</option>";
     }
     $liste .= "</select>";
     return $liste;
 }
 ?>

Utilisation : par exemple pour générer la liste des jours du mois

<?php echo generer_liste_date("nomchamp","d",1,31); ?>

mardi, juillet 5 2005

Tidy, ton extension est formidable

Je suis plus que ravi d'avoir découvert cet outils qui permet de corriger les petites erreurs de syntaxe XHTML, d'indenter correctement le code, de supprimer les commentaires HTML, de nettoyer du code Word 2002 (enfin presque) ect... Ce n'est pas non plus une solution miracle (non, Tidy ne fait pas la café) et rien n'y fera si vous avez vraiment codé comme un vilain avec un M$ Frontpage d'avant-guerre.

Ainsi, et tout de même, tout un site de publication de contenu peut vite devenir "Full XHTML compliant" même si le code n'était pas des plus parfait au départ ou suite à la saisie fantaisiste de quelques rédacteurs zélés.

Cerise sur le W3C, SPIP, mon CMS préféré du moment, intègre dans sa version 1.8 la correction des pages via cette fameuse extension Tidy. On peux l'utiliser au choix en extension PHP ou en ligne de commande (puisque l'outil en question est à la base un correcteur syntaxique en ligne de commande).

Je vous laisse admirer sur le site spatial-modelling.info qui tourne sous SPIP, le maaaagnifique code source bien indenté par la version de Tidy en ligne de commande. Est-ce lent ? Absolument pas car pour le cas de ce système de gestion de contenu, la sortie est ensuite directement mise en cache !

Alors, la question vous brûle les lèvres : pour une utilisation de Tidy sur son propre site en PHP, comment faire ? Attention, c'est du tutorial ultra rapide qui ne remplace pas une bonne lecture de la page de PHP et des options de Tidy.

Il faut tout d'abord posséder l'extension PHP qui va bien ou l'outil en ligne de commande (apt-get install tidy sous Debian ou Ubuntu fera l'affaire). Pour le cas de l'extension, elle disponible pour PHP5 mais reste un petit peu bricolage pour PHP4 et j'ai. Une installation via le PEAR repository est aussi envisageable. je vous renvois à la page du manuel PHP, assez bien faîtes à ce sujet.

Ensuite, si vous n'avez pas le courage de modifier toutes vos pages proprement codé en PHP ou en HTML, voici un petit truc dont le but est de placer tout le contenu de votre page dans un "buffer".

En début de page on place un ob_start pour mettre le contenu qui suit dans un buffer. On peux éventuellement utiliser l'option gzip tant qu'on y est, afin de renvoyer des pages compressées à un navigateur moderne (ne comptez pas sur vos clients en Netscape 4 pour le comprendre). A la fin du code, un ob_get_clean nous permet de récupérer le contenu du buffer dans une variable. Il suffit ensuite de passer tout ça à Tidy pour qui il nous le corrige et un echo servira le résultat et... Ohhh la belle page qui valide :)

Voici donc un petit résumé de l'exemple :

J'ai mis tout le "nécessaire de nettoyage" dans une fonction. Des problèmes avec les caractères Word m'ont obligés à ajouter le remplacement des caractères en question. J'ai également supprimé un élément xml ajouté par Tidy et dont je ne voit pas bien l'utilité :

<?php
 // Tidy configuration
 $config_tidy = array('indent'=> true,
                                 'indent-spaces'=> 2,
                                 'output-xhtml' => true,
                                 'wrap' => 0,
                                 'add-xml-decl'=> false,
                                 'output-encoding'=> latin1,
                                 'input-encoding'=> latin1,
                                 'quote-nbsp' => false,
                                 'show-body-only' => false);

 foreach ($config_tidy as $key => $value) {
              tidy_setopt($key,$value);
 }

 // nettoyage du code
 function tidycleaner($html) {
   
    // problème avec M$ Word
    $conv = array(
     chr(129) => '',
     chr(130) => '&#8218',
     chr(131) => '&#402;',
     chr(132) => '&#8222;',
     chr(133) => '&#8230;',
     chr(134) => '&#8224;',
     chr(135) => '&#8225;',
     chr(136) => '&#710;',
     chr(137) => '&#8240;',
     chr(138) => '&#352;',
     chr(139) => '&#8249;',
     chr(140) => '&#338;',
     chr(141) => '',
     chr(142) => '',
     chr(143) => '',
     chr(144) => '',
     chr(145) => '&#8216;',
     chr(146) => '&#8217;',
     chr(147) => '&#8220;',
     chr(148) => '&#8221;',
     chr(149) => '&#8226;',
     chr(150) => '&#8211',
     chr(151) => '&#8212;',
     chr(152) => '&#732;',
     chr(153) => '&#8482;',
     chr(154) => '&#353;',
     chr(155) => '&#8250;',
     chr(156) => '&#339;',
     chr(157) => '',
     chr(158) => '',
     chr(159) => '&#376;'
     );
     
     tidy_parse_string($html);
     tidy_clean_repair();
     $html = tidy_get_output();
 
     // on remplace les caracteres M$ Word
     $html = str_replace(array_keys($conv),array_values($conv),$html);
     
     // syntaxe xml à supprimer
     $html = ereg_replace ("\<\?xml([^\>]*)\>", "", $html);
     
     return $html;
 }
?>

Voici une page type avec l'introduction de la fonction tidycleaner :

<?php
 // debut du buffer
 ob_start(gzip);
 
 // ...
 // contenu de la page, traitement divers et tout le toutim...
 // ...
 
 // fin du buffer, dans une variable et ensuite affichage de la page
 $html = ob_get_clean();
 echo tidycleaner($html);
?>
<?php echo 'test'; ?>

Pour éviter la lourdeur éventuel du traitement par Tidy, il est bien entendu fortement conseillé d'utiliser un système de cache ! Alors ? ça valide partout !?

- page 1 de 2