1

Utiliser SPIP comme un framework

5 février 2009
par ARNO*

Je souhaite présenter, dans le présent billet, des utilisations de SPIP éloignées de ce pour quoi SPIP a été conçu : des techniques qui utilisent le système de squelettes de SPIP pour produire autre chose que du contenu éditorial en XHTML.

Il s’agit évidemment de développements avancés qui n’ont rien à voir avec une utilisation « clé en main » de SPIP. Il me semble intéressant de mettre en avant cet aspect de SPIP pour les raisons suivantes :
— montrer que c’est parfaitement réalisable avec SPIP ; beaucoup de commentaires sur le Web présentent le langage de squelettes comme un moyen de réaliser des maquettes relativement facilement, mais précisent immédiatement que pour une utilisation plus poussée (ou « professionnelle »), SPIP est inadapté ; je prétends au contraire que le système de squelettes, depuis ses origines, permet de gagner des heures de développement, y compris pour les usages avancés ;
— depuis SPIP 1.8, et officiellement avec SPIP 2.0, une grande orientation des développements de SPIP concerne l’utilisation de SPIP comme « framework » (en français : « plateforme de développement », comme nous l’expliquons dans la présentation de la version 2.0) ; la plupart des commentaires ont tendance à ne voir cet aspect « framework » que par le prisme des plugins, alors qu’il est déjà central dans les évolutions du langage de squelettes ;
— donner des idées aux bidouilleurs qui voudraient avancer dans cette direction.

Il ne s’agit pas ici d’un mode d’emploi, mais simplement de détailler quelques exemples d’utilisations de SPIP dans différentes situations.

On verra qu’on peut fabriquer, directement à partir des squelettes :
• des « noisettes » XHTML chargées dynamiquement en AJAX,
• des fichiers de commandes Javascript,
• des fichiers XML (pour interfaçage, par exemple, avec des animations Flash, ou pour importer/exporter avec d’autres systèmes informatiques),
• des fichiers CSV (même si ce format est plutôt dépassé),
• des fichiers Excel,
• des fichiers PHP directement exécutables,
• des animations Flash avec l’extension Ming de PHP,
• des feuilles de style CSS,
• des fichiers d’agendas compatibles iCal...

Plan-ciné.fr

Le site plan-ciné.fr est ma création la plus caractéristique de l’utilisation de SPIP en tant que framework : le site n’utilise carrément pas l’espace privé de SPIP (à part pour suivre les statistiques), il ne contient ni rubriques, ni articles, ni brèves.

Il s’agit d’un site doté d’une seule et unique page, constituée d’un mashup de présentation les séances de cinéma sur une Google Map. Différentes squelettes permettent d’afficher à la demande, en Ajax, des blocs d’information. Et un squelette en particulier fabrique directement un fichier entièrement en Javascript permettant d’afficher les séances d’un film.

Tout cela est réalisé avec des squelettes SPIP. Il y a quelques fonctions spécifiques en PHP dans mes_fonctions.php pour faciliter le codage, mais ces fonctions sont très simples et les squelettes eux-mêmes ne recourent à aucune « bidouille » en PHP.

Le principe est d’afficher les informations stockées dans des tables supplémentaires : spip_films stocke les films (titre, réalisateur, acteurs, affiche), spip_cinemas stocke la liste des cinémas (nom, adresse, latitude et longitude, logo du cinéma) et une table spip_seances stocke toutes les séances (identifiant du film, identifiant du cinéma, version VO ou VF, horaire).

Voici le squelette qui fabrique la liste des séances pour un film dans une certaine tranche horaire :

  1. #HTTP_HEADER{'Content-Type: text/Javascript'}
  2.  
  3. <BOUCLE_cinemas(spip_cinemas)>
  4. <BOUCLE_test_cinema(spip_seances){id_cinema}{0,1}{horaire>=#ENV{film_debut}}>
  5. cinemas["#ID_CINEMA"] = new cinema (#ID_CINEMA, "#NOM", #LATITUDE, #LONGITUDE,
  6.         [(#LOGO|?{" ",""})[iconeCinema(#LOGO|md5|substr{0,5})]][(#LOGO|?{""," "})0], [(#LOGO|?{" ",""})[iconeCinema(#LOGO|md5|substr{0,5})off]][(#LOGO|?{""," "})0],
  7.         "|<BOUCLE_films_cinema(spip_seances){id_cinema}{fusion id_film}{vovf==(#ENV{afficher_vovf}|sinon{.})}{horaire>=#ENV{film_debut}}{horaire<#ENV{film_fin}}>#ID_FILM|</BOUCLE_films_cinema><BOUCLE_films_cinema_alt(spip_seances){id_cinema}{fusion id_film}{vovf==(#ENV{afficher_vovf}|sinon{.})}{horaire>=#ENV{film_debut}}>#ID_FILM|</BOUCLE_films_cinema_alt><//B_films_cinemas>");
  8. </BOUCLE_test_cinema></BOUCLE_cinemas>
  9.  
  10. afficher_cinemas();

Télécharger

Certes, le code est assez impressionnant, mais il est important de noter qu’il s’agit uniquement de commandes du langage des squelettes. Ce squelette est appelé en AJAX (avec la commande $.getScript de jQuery), il reste en cache, et provoque directement l’affichage des séances sur la carte.

On remarquera en particulier qu’il utilise des boucles « normales », sans bidouilles bizarres ; simplement on interroge ici des tables de la base de données qui ne sont pas dans le SPIP d’origine.

Les autres squelettes permettant de gérer le site sont, eux, des noisettes en HTML plus classiques, mais qui sont appelées dynamiquement en AJAX.

Voici par exemple le squelette qui fabrique directement le bandeau de navigation du bas, où l’on peut sélectionner le film dont on souhaite afficher les séances. Le code est artificiellement complexifié par le fait que j’ai développé un javascript permettant de gérer un cliquer-déplacer pour déplacer le contenu de gauche à droite avec la souris (façon « iPhone »).

  1. #HTTP_HEADER{'Content-Type: text/html'}
  2.         <B_films>
  3.         <div  id="slide_tout" onmousedown="debut_slide('#slide_tout'); return false;" style="position: absolute; left: 0px; width: [(#TOTAL_BOUCLE|multiplier_par{80})]px;">
  4.         <BOUCLE_films(spip_films){genre==#ENV{genre}|urldecode|sinon{.*}}{seances>0}{par seances}{inverse}{0,20}>
  5.        
  6.                 <div class="pave-film">
  7.                        
  8.                
  9.                         <div class="logo-film">[<a href="#" onclick="if(!slideur_actif) {map_tout_effacer();afficher_film = #ID_FILM; charger_vovf('.');} return false;"><span class="titre-film">[(#TITRE|decouper_titre)]</span>(#LOGO|sinon{squelettes/imgs/fausse-affiche.jpg}|image_reduire{80}|image_renforcement{0.1}|inserer_attribut{alt,#TITRE})]</a></div>
  10.                                 <div class="logo-reflet">[(#LOGO|sinon{squelettes/imgs/fausse-affiche.jpg}|image_reduire{80}|image_graver|image_flip_horizontal|image_graver|image_masque{masques/reflet3.png}|image_graver|image_aplatir{jpg,ffffff}|inserer_attribut{alt,x})]</div>
  11.                        
  12.                         <BOUCLE_test_vo(spip_seances){id_film}{fusion vovf}{vovf!==vf$}{horaire >= (#RIEN|debut_semaine)}{horaire <= (#RIEN|fin_semaine)}>
  13.                         </BOUCLE_test_vo>
  14.                                 <div class="vovf">
  15.                                 <BOUCLE_vovf(spip_seances){id_film}{fusion vovf}>
  16.                                         <strong><a href="#" onclick="if(!slideur_actif) {map_tout_effacer();afficher_film = #ID_FILM; charger_vovf('[(#VOVF|replace{"^en ",""})]');} return false;">[(#VOVF|replace{"^en ",""}|image_vovf)]</a></strong>
  17.                                 </BOUCLE_vovf>
  18.                                 </div>
  19.                         </B_test_vo>
  20.                 </div>
  21.         </BOUCLE_films>
  22.         </div>
  23.         </B_films>

Télécharger

Dans les deux cas, noter la présence d’un #HTTP_HEADER indiquant la nature du fichier généré (javascript ou HTML), nécessaire au bon fonctionnement d’AJAX.

Toute la complexité du code réside dans le Javascript gérant le mashup Google Map et les chargements asynchrones. Mais du côté des extractions des informations de la base de données, l’utilisation du langage de squelettes de SPIP permet de gagner des heures (des journées ?) de développement en conservant un code source particulièrement lisible.

Flip-Zone

Le magazine de mode Flip-Zone est un « site magazine » plus classique, puisqu’il s’agit bien d’articles publiés dans des rubriques.

Un des aspects spectaculaire est la construction très graphique du site, entièrement automatisée, avec de très nombreux calculs graphiques (via les filtres graphiques de SPIP) pour fabriquer les multiples « couvertures » et vignettes de navigation, et des changements de couleurs à chaque page du site (via les filtres présents dans SPIP).

Mais ce qui m’intéresse pour ce billet, c’est la création des « animations tourne-pages » en Flash qui présentent chaque collection.

Il y a eu plusieurs versions pour réaliser ce même « tourne-page ». Chaque version utilisait des techniques très différentes pour réaliser le même effet, chaque solution étant à mon avis intéressante pour le présent billet.

• La première version consistait à fabriquer directement une animation Flash dans mes_fonctions.php en utilisant la librairie Ming de PHP. J’étais assez fier de cette solution particulièrement compliquée, alors que Ming était plutôt utilisé pour faire des petites animations moches. Le problème était que chaque fichier Flash ainsi généré était lourd et différent d’une collection à l’autre, ce qui ralentissait les chargements. Et fabriquer l’ActionScript directement dans Ming rendait le code totalement impossible à faire évoluer.

• La seconde version reposait sur un fichier Flash « classique », bourré d’ActionScript, réalisé directement dans Flash, de taille beaucoup plus réduite (36 ko), auquel je passais des variables permettant à ce fichier de charger des fichiers XML. De cette façon, pour chaque collection, le fichier Flash à charger est toujours le même et très léger. La quantité de donnée (notamment graphique) est importante, mais le Flash initial se charge très rapidement, les différentes pages se chargeant ensuite de manière asynchrone.

Je passais l’identifiant de l’article en variable Flash, et le fichier Flash chargeait alors un squelette SPIP qui fabriquait le XML directement. Ainsi j’utilisais SPIP pour fabriquer du XML, très simplement.

Chaque page ainsi définie par un fichier XML chargeait alors un autre fichier Flash doté lui-même de variables spécifiques. Ca restait très lourd à maintenir, et les temps de chargement étaient encore pénalisants.

• La dernière version repose toujours sur un fichier Flash commun à toutes les collections auquel je passe des variables. En revanche, désormais, les fichiers XML contiennent l’intégralité de la description du contenu des pages, et ils sont générés directement au calcul de la page principale, en PHP, dans mes_fonctions.php. L’élégance de la fabrication des XML directement avec des squelettes est perdue, mais l’ensemble se charge désormais beaucoup plus vite, et le code est un peu plus simple à maintenir (même si ça reste un sacré mammouth).

Magnard.fr

Le site des éditions Magnard est, après le site des éditions Vuibert, le premier site où j’ai commencé à utiliser SPIP comme un « framework » : la base de données des livres et des collections n’utilise pas la structure SPIP (qui n’est évidemment pas conçue pour gérer des livres avec toutes leurs caractéristiques).

L’affichage des livres d’une collection est aussi simple que d’afficher les articles d’une rubrique :

  1. <BOUCLE_les_livres(LIVRE_VUIB){id_collection}{etat==^(publie|paraitre|proppar)$}{par ordre}{doublons livres}>
  2.         #TITRE
  3. </BOUCLE_les_livres>

Télécharger

L’aspect « framework » apparaît plus particulièrement dans deux autres fonctions spécifiques du site, invisibles pour l’utilisateur.

• Le catalogue des livres est géré sur un autre serveur, sur un système-métier très spécifique (PIONIX de MetaConcept), il faut donc récupérer les mises à jour sur le site Web.

Chaque jour, le système externe installe sur le serveur une collection de fichiers XML (ainsi que des fichiers JPEG des couvertures et des documents supplémentaires) sur le serveur par FTP. Automatiquement, le site découpe ces fichiers XML, reformate l’information et l’insère dans la base de données MySQL locale. Le moteur pour parser le XML est, sur ce site, XML Parser de Critical Development (c’était avant l’introduction de fonctions dédiées dans SPIP).

Ce type de travail porte un nom extrêmement technique : c’est une « moulinette »...

• Par ailleurs, chaque jour, le site doit exporter les commandes d’ouvrages au format CSV à destination du système de gestion des commandes, qui est lui aussi sur un système externe. Là encore, SPIP est parfaitement capable de fabriquer des fichiers CSV directement par des squelettes.

• Tout cela avec des changements d’encodage des caractères (charsets), le site étant en utf-8, les systèmes externes étant en ISO-8859-1. Les fonctions natives de SPIP sont alors utilisées.

Autres sites

Des aspects « framework » plus restreints sont utilisés sur les sites suivants.

• Le site de la Réunion des musées nationaux dispose d’un plugin spécifique permettant de synchroniser automatiquement (via XML) le site de la « boutique de la RMN » dans certains espaces du site. Là, l’aspect « framework » passe par un plugin complet développé pour l’occasion.

• Le site de la Journée du 20 Mars de l’Organisation internationale de la Francophonie gère des « événements » renseignés par les visiteurs. Une originalité ici est que les différentes informations concernant ces événements sont ensuite exportés, via des squelettes, au format Excel, à destination des administrateurs. Il s’agit là de squelettes qui fabriquent directement du PHP, utilisant un script PHP qui permet de fabriquer des fichiers au format .xls. C’est donc du PHP fabriqué dynamiquement dans des squelettes SPIP, permettant l’export direct de fichiers Excel.

• Sur un site actuellement en développement (je ne peux donc vous fournir l’adresse), des documents XML associés à des articles en tant que « documents distants » contiennent la liste des membres d’une association professionnelle. Des boucles utilisant le plugin « Boucles XML » permettent de très facilement exploiter et afficher ces informations :

  1. <B_xml>
  2.         [<script src="(#CHEMIN{thickbox.js})" type="text/javascript"></script>]
  3. <BOUCLE_xml(DOCUMENTS){id_article}{extension=xml}{titre==membres}>
  4.         [(#INCLURE{fond=xml_membres}{xml=[(#FICHIER|copie_locale{force})]})]
  5. </BOUCLE_xml>

Télécharger

Contrairement à la « moulinette » du site Magnard, ici le fichier XML est utilisé tel quel directement depuis le squelette, il n’y a pas de conversion préalable vers la base de données MySQL. On a un résultat plus limité, mais suffisant pour l’usage de ce site, et avec un développement ultra-rapide.

Conclusion

Le système de squelettes de SPIP permet, depuis l’origine, de fabriquer d’autres formats que le XHTML destiné à présenter l’information sur le Web. En particulier, on trouvera des fichiers exportant du XML assez classique de flux RSS.

Un tel squelette est : squelettes-dist/backend.html.

On trouvera également le fichier prive/ical_prive.html qui fabrique un export au format .ics pour des calendriers au format iCal (c’est une version spécifique du XML).

Et évidemment, il est très facile de réaliser des fichiers de styles CSS avec des boucles, par exemple prive/style_prive.html.

J’espère que les différentes utilisations de SPIP présentées ici vous donneront quelques pistes sur ce que peut signifier « utiliser SPIP comme un framework », et fabriquer très rapidement des types de fichiers qui ne sont pas simplement destinés à afficher de « simples » pages éditoriales en XHTML.

Je souhaitais également insister sur le fait qu’il n’est pas indispensable de se lancer immédiatement dans le développement gros plugins pour progresser et étendre les fonctionnalités d’un site.

Certaines utilisations sont particulièrement complexes, mais je pense qu’un peu de patience et de jugeotte permet de progresser dans ce domaine. Il est surtout intéressant, ici, de conjuguer ce que l’on sait déjà faire avec la flexibilité du langage des squelettes (un bon développeur Flash gagnera des heures, grâce à des squelettes en XML, pour interfacer l’information tirée de SPIP avec ses animations ; exporter l’information en XML vers un système tiers ne demande pas des compétences énormes, créer des CSS dynamiques est un vrai plaisir...).

Qui êtes-vous ?
Votre message

Ce formulaire accepte les raccourcis SPIP [->url] {{gras}} {italique} <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.