Plone pour les intégrateurs Version 1.0.0 plone-fr 17-April-2017 Table des matières 1 A propos de ce document 1.1 Organisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Liste des thèmes abordés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Ressources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Présentation de Plone 2.1 Les besoins . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Pourquoi Plone . . . . . . . . . . . . . . . . . . . . . . . 2.3 Centralisation des documents . . . . . . . . . . . . . . . 2.4 Édition des contenus . . . . . . . . . . . . . . . . . . . . 2.5 Visualisation des documents . . . . . . . . . . . . . . . . 2.6 Classement des documents . . . . . . . . . . . . . . . . . 2.7 Stockage des documents . . . . . . . . . . . . . . . . . . 2.8 Authentification . . . . . . . . . . . . . . . . . . . . . . 2.9 Permissions, rôles et groupes d’utilisateurs . . . . . . . . 2.10 Indexation . . . . . . . . . . . . . . . . . . . . . . . . . 2.11 Photothèques . . . . . . . . . . . . . . . . . . . . . . . . 2.12 Fonction d’alerte . . . . . . . . . . . . . . . . . . . . . . 2.13 Actualités, événements, calendrier, lettres d’informations . 2.14 Espace projet . . . . . . . . . . . . . . . . . . . . . . . . 2.15 Répertoires dynamiques . . . . . . . . . . . . . . . . . . 2.16 Références croisées . . . . . . . . . . . . . . . . . . . . 2.17 Modération du contenu . . . . . . . . . . . . . . . . . . . 2.18 Historique des changements effectués sur le contenu . . . 2.19 Flux RSS . . . . . . . . . . . . . . . . . . . . . . . . . . 2.20 Langue du portail, Multilinguisme, Traduction . . . . . . 2.21 Charte graphique . . . . . . . . . . . . . . . . . . . . . . 2.22 Trombinoscope et annuaires . . . . . . . . . . . . . . . . 2.23 Génération de documents à partir de modèles . . . . . . . 3 3 3 3 . . . . . . . . . . . . . . . . . . . . . . . 5 5 5 6 6 11 12 12 12 12 14 14 14 15 15 15 15 15 17 18 18 20 20 20 3 Les nouveautés de Plone 3.1 Les nouveautés de Plone 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Les nouveautés de Plone 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 23 26 4 Paramétrer votre site Plone 4.1 Objectif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2 Accéder au menu de configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3 Configurer les paramètres de messagerie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 31 33 33 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . i 4.4 4.5 4.6 4.7 4.8 4.9 4.10 4.11 4.12 4.13 4.14 4.15 4.16 4.17 4.18 4.19 4.20 4.21 4.22 4.23 4.24 5 6 7 8 9 ii Paramètres du site . . . . . . . . . . . . . . . . . Paramètres de base de la sécurité du site . . . . . . Paramétrage du calendrier . . . . . . . . . . . . . Paramétrage de la navigation . . . . . . . . . . . . Paramètres de la recherche . . . . . . . . . . . . . Configurer le thème . . . . . . . . . . . . . . . . Paramétrage des modules . . . . . . . . . . . . . Paramétrage des règles de contenu . . . . . . . . . Paramétrer l’édition de contenus . . . . . . . . . . Paramétrer le filtrage du contenu ajouté en HTML Paramétrer le comportement wiki . . . . . . . . . Gestion des tailles d’images . . . . . . . . . . . . Maintenance du serveur et de la base . . . . . . . Choix de la langue du Site . . . . . . . . . . . . . Paramétrer les types de contenu . . . . . . . . . . Gestion des utilisateurs et groupes . . . . . . . . . Caching . . . . . . . . . . . . . . . . . . . . . . . Discussion . . . . . . . . . . . . . . . . . . . . . Registre de configuration . . . . . . . . . . . . . . Syndication . . . . . . . . . . . . . . . . . . . . . Éditeur de texte riche TinyMCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 35 39 45 49 53 53 55 55 58 62 62 62 64 64 69 72 72 72 72 72 Choix et ajout d’un module 5.1 Introduction . . . . . . . . . . . . . 5.2 Rechercher et sélectionner un module 5.3 Installer un module . . . . . . . . . . 5.4 Tester le module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 73 73 74 76 Le protocole HTTP et ses tests 6.1 Définition . . . . . . . . . 6.2 Savoir . . . . . . . . . . . 6.3 Exercice . . . . . . . . . 6.4 Ressources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 77 78 82 83 Rappel HTML et XML 7.1 Définition . . . . . 7.2 Savoir . . . . . . . 7.3 Exercices . . . . . 7.4 Ressources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 85 86 89 89 Concept de Python eggs 8.1 Définition . . . . . . . . . . . . . . . . . . . . . . . . . 8.2 Savoir . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.3 Installation de Python et Distribute . . . . . . . . . . . 8.4 Packaging Python . . . . . . . . . . . . . . . . . . . . 8.5 Passons au développement . . . . . . . . . . . . . . . . 8.6 L’API pkg_resources . . . . . . . . . . . . . . . . . . . 8.7 Les entry points . . . . . . . . . . . . . . . . . . . . . 8.8 Mise en place d’un Pypi privé avec PloneSoftwareCenter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 . 91 . 92 . 92 . 92 . 99 . 103 . 104 . 105 Introduction à zc.buildout 9.1 Définition . . . . . . . . . . . . . . . . 9.2 Introduction . . . . . . . . . . . . . . 9.3 Organisation d’un buildout . . . . . . . 9.4 Section principale [buildout] . . . . . . 9.5 Partage du dossier eggs et downloads . 9.6 Pinning des versions . . . . . . . . . . 9.7 Extension buildout.dumppickedversions 9.8 Option extends . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 109 110 110 110 112 113 113 114 9.9 9.10 9.11 9.12 9.13 9.14 Recipe collective.recipe.omelette . . . . . Utilisation de variable . . . . . . . . . . . Repinning et fusion de section de données . Ordre d’installation des parts . . . . . . . . L’option develop . . . . . . . . . . . . . . Option index et find-links . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 116 117 117 118 118 10 Installation et création d’une instance Plone 121 10.1 Savoir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 10.2 Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 11 Création d’un buildout Plone avec ZopeSkel 11.1 Création du buildout . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2 Installation de produits tierces . . . . . . . . . . . . . . . . . . . . . . . 11.3 Création d’un policy package contenant la configuration du site Plone . . 11.4 À propos des versions . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.5 Releaser le policy package . . . . . . . . . . . . . . . . . . . . . . . . . 11.6 Repasser au développement . . . . . . . . . . . . . . . . . . . . . . . . 11.7 Utilisation de mr.developer pour gérer les composants en développement 11.8 Fabric . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.9 Ressources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 130 131 132 137 137 138 139 140 141 12 Déploiement et backup 12.1 Définition . . . . . . . . . . . . . . . . . . . . . 12.2 Savoir . . . . . . . . . . . . . . . . . . . . . . . 12.3 Profil de déploiement . . . . . . . . . . . . . . . 12.4 Supervisor . . . . . . . . . . . . . . . . . . . . 12.5 Support des backups . . . . . . . . . . . . . . . 12.6 Cron job pour zeopack et backup . . . . . . . . 12.7 Configuration d’Apache . . . . . . . . . . . . . 12.8 Configuration des DNS . . . . . . . . . . . . . . 12.9 Installation et configuration de plone.app.caching 12.10 Ressources . . . . . . . . . . . . . . . . . . . . 12.11 Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 143 144 144 148 149 150 150 152 152 153 153 13 Zope External Editor 13.1 Activation du lien “Modifier avec une application externe” 13.2 Installation du client External Editor sous Ubuntu . . . . . 13.3 Installation du client External Editor sous Windows . . . 13.4 Problèmes de cache avec l’External Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 155 155 156 156 14 Monitoring avec Munin 14.1 Plugins Zope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.2 Plugins Varnish . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.3 Ressources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 160 161 161 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 PloneFormGen 163 15.1 Présentation de PloneFormGen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 15.2 Exercice : Réalisation d’un formulaire de sondage . . . . . . . . . . . . . . . . . . . . . . . . . 174 16 Le theming Plone avec Diazo 175 16.1 Diazo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 16.2 Produit de skin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 17 Ecrire des scripts Plone : bases 17.1 Introduction . . . . . . . . . . . . . . . . . . . 17.2 Mon premier script . . . . . . . . . . . . . . . . 17.3 Créer et gérer des contenus par script . . . . . . 17.4 Connaître et exploiter les informations utilisateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 196 196 199 203 iii 17.5 Utiliser le catalogue de Plone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 18 Ecrire des templates Plone : bases 18.1 Introduction . . . . . . . . . . . . . . . . . . . . . . 18.2 Ma première template . . . . . . . . . . . . . . . . . 18.3 Appel à un script . . . . . . . . . . . . . . . . . . . . 18.4 Utiliser la master template de Plone . . . . . . . . . . 18.5 Utiliser une structure plus complexe dans une template 18.6 Appeler une template depuis une autre template . . . . 18.7 Exercices . . . . . . . . . . . . . . . . . . . . . . . . 18.8 Ecrire la template sous la forme d’une vue . . . . . . 18.9 Une vue pour un export csv . . . . . . . . . . . . . . 18.10 Une viewlet pour ajouter un lien vers une vue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209 209 210 210 211 212 213 213 213 214 216 19 TAL/Metal : les templates de Zope et Plone 19.1 Le langage TAL . . . . . . . . . . . . 19.2 TALES . . . . . . . . . . . . . . . . . 19.3 METAL . . . . . . . . . . . . . . . . . 19.4 Ressources . . . . . . . . . . . . . . . 19.5 Namespaces . . . . . . . . . . . . . . 19.6 Variables globales . . . . . . . . . . . 19.7 Présentation des ZPT . . . . . . . . . . 19.8 Le langage TAL . . . . . . . . . . . . 19.9 TALES . . . . . . . . . . . . . . . . . 19.10 METAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219 220 221 221 221 221 222 222 223 224 226 20 Paramétrage local des workflows 20.1 Préparation . . . . . . . . . . . . . 20.2 Installation du module . . . . . . . 20.3 Gestion des politiques de workflow 20.4 Affectation des workflows locaux . 20.5 Export Generic Setup . . . . . . . 20.6 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 229 229 232 235 235 235 21 Déclenchement d’événements avec les règles de contenu 21.1 Objectif de la formation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.2 Préparation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.3 Créer une règle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.4 Paramétrer une règle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.5 Créer une condition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.6 Créer une action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.7 Activer la règle pour une partie du site . . . . . . . . . . . . . . . . . . . . . . . . . 21.8 Tester la règle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.9 Exemple 2 : Logguer les suppressions de documents . . . . . . . . . . . . . . . . . 21.10 Exemple 3 : Déplacer les événements dans un même dossier, où qu’ils soient ajoutés 21.11 Export Generic Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.12 Extensibilité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.13 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 239 240 240 240 242 242 243 245 245 246 247 247 248 22 Créer des pages composées en ligne avec Collage 22.1 Préparation . . . . . . . . . . . . . . . . . . 22.2 Objectif de la formation . . . . . . . . . . . 22.3 Installer Products.Collage . . . . . . . . . . 22.4 Créer un Collage . . . . . . . . . . . . . . . 22.5 Ajouter les éléments du Collage . . . . . . . 22.6 Utiliser le collage comme page d’accueil . . 22.7 Paramétrer l’affichage du collage . . . . . . 22.8 Extensibilité . . . . . . . . . . . . . . . . . 22.9 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 249 249 249 250 250 254 254 258 258 iv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 Glossaire 267 24 Indexes et tables 271 25 Contributeurs 273 Index 275 v vi Plone pour les intégrateurs, Version 1.0.0 Astuce : Pour voir cette documentation dans son site original et accéder à son moteur de recherche, veuillez vous rendre ici. Lire la dernière version de ce document au format PDF Ce document constitué à partir de contributions de la communauté Plone francophone, notamment : – Le manuel de formation intégrateur Plone par Vincent Fretin (Ecréall) – Les travaux, les relectures et les très nombreuses contributions de Gilles Lenfant, Thomas Desvenain et Michael Launay – La documentation sur le theming par Éric Bréhault (Makina Corpus) Cette création est mise à disposition selon le Contrat Paternité-Partage des Conditions Initiales à l’Identique 2.0 France disponible en ligne http ://creativecommons.org/licenses/by-sa/2.0/fr/ ou par courrier postal à Creative Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA. Table des matières 1 Plone pour les intégrateurs, Version 1.0.0 2 Table des matières CHAPITRE 1 A propos de ce document 1.1 Organisation La formation est découpée en thèmes. Presque chaque thème comprend : – un objectif, – un savoir à acquérir, – un exercice pratique permettant de fixer le savoir acquis, – un bilan oral, résumant ce qui a été acquis. 1.2 Liste des thèmes abordés – – – – – – – – – – – – Présentation de Plone Concept de Python eggs Création d’un buildout Création d’un thème Moteur de template (TAL/Metal) Concepts de base Zope 3 (composants) Internationalisation Moteur de règle (pour réagir à un événement) Notions avancées de formulaire d’édition Migration d’une version de Plone à l’autre Déploiement et backup [deprecated] ArchgenXML 1.3 Ressources Livres de Packt Publishing, en anglais : – Professional Plone 4 Development Martin Aspeli Aout 2011 – A users guide to Plone september 2010 – Practical Plone 3 : A Beginner’s Guide to Building Powerful Websites, Alex Clark, Clayton Parker, Darci Hanning, David Convent, John DeStefano, Jon Stahl, Martin Aspeli, Matt Bowen, Ricardo Newbery, Sam Knox, Steve McMahon, Tom Conklin, Veda Williams, février 2009 – Plone 3 Theming, Veda Williams, juillet 2009 – Plone 3 for Education, Erik Rose, décembre 2009 – Plone 3.3 Site Administration, Alex Clark, mars 2010 – Plone 3.3 Multimedia, Tom Gross, juin 2010 3 Plone pour les intégrateurs, Version 1.0.0 4 Chapitre 1. A propos de ce document CHAPITRE 2 Présentation de Plone Author Michael Launay Version 0.1.0 Copyright (C) 2010 Michael Launay <michaellaunay AT ecreall.com>. Chacun est autorisé à copier, distribuer et/ou modifier ce document suivant les termes de la licence Paternité-Pas d’Utilisation Commerciale-Partage des Conditions Initiales à l’Identique 2.0 France accessible à http ://creativecommons.org/licenses/by-nc-sa/2.0/fr Le code source présent dans ce document est soumis aux conditions de la « Zope Public License », Version 2.1 (ZPL). THE SOURCE CODE IN THIS DOCUMENT AND THE DOCUMENT ITSELF IS PROVIDED “AS IS” AND ANY AND ALL EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. 2.1 Les besoins Plone permet de satisfaire les besoins d’espaces collaboratifs pour organiser, partager et diffuser des informations et des documents. Il permet de centraliser et référencer l’information pour l’utilisateur via une interface web intuitive. Il fournit une vitrine et un outil d’animation. Nous montrerons comment le CMS open source Plone répond aux exigences fortes que sont : – Un usage simple et ergonomique pour l’utilisateur. – Un fort niveau de paramétrage pour l’administrateur. 2.2 Pourquoi Plone Plone est une solution open source multiplateforme, performante, stable et sûre qui existe depuis 2001. Le CMS Plone évolue constamment sans perte de compatibilité. Il est maintenu par une communauté de sociétés qui en assure la pérennité et l’adéquation avec le besoin des clients. En France on trouve pas moins de 14 sociétés spécialisées réalisant en support expert sur cette technologie sur les 369 sociétés mondiales réparties sur 62 pays (C.f. http ://plone.org/support/providers). 5 Plone pour les intégrateurs, Version 1.0.0 2.3 Centralisation des documents Le portail collaboratif Plone est un un espace unique où trouver et échanger des informations. Il se présente sous la forme d’un site internet accessible en intranet comme en extranet. Le fonctionnement client-serveur d’internet offre naturellement la centralisation voulue. Les utilisateurs saisissent l’URL du portail depuis leur navigateur internet, s’authentifient, et accèdent alors aux documents de l’entreprise. 2.4 Édition des contenus L’édition des contenus se fait par une étape de création, suivie automatiquement d’une édition, d’un enregistrement puis éventuellement d’un changement d’état. L’utilisateur se place dans une partie de l’arborescence du site en utilisant la navigation. S’il en a les droits il peut alors ajouter un contenu qui peut être un document, d’événement, de répertoire, de fichier ou tout type créé spécifiquement, etc. F IGURE 2.1 – Exemple de navigation Une fois placé à l’endroit voulu dans l’arborescence, l’utilisateur choisit le type d’élément voulu dans le menu “Ajout d’un élément”. Une page sur l’édition du nouveau document s’ouvre et l’on peut saisir le contenu du document : Le portail vérifie les saisies lorsqu’on passe d’un champ à l’autre. Une fois la saisie réalisée, il suffit de cliquer sur le bouton “Enregistrer”. Tant que l’enregistrement n’est pas fait le nouveau contenu est en mode brouillon, c’est-à-dire qu’il n’est pas réellement ajouté à l’arborescence. 6 Chapitre 2. Présentation de Plone Plone pour les intégrateurs, Version 1.0.0 F IGURE 2.2 – Ajout d’un élément F IGURE 2.3 – Création d’un document 2.4. Édition des contenus 7 Plone pour les intégrateurs, Version 1.0.0 L’édition des contenus se fait par l’intermédiaire de formulaires propres à chaque type. F IGURE 2.4 – Exemple d’édition d’un document On peut remarquer dans cette capture l’éditeur en ligne qui permet une mise en forme riche avec création de titre, changement de police, de couleur, insertion de listes numérotées, d’images pouvant être retaillées... De nombreuses fonctionnalités de cet éditeur peuvent être paramétrées par l’administrateur (boutons disponibles, etc) Chaque type de document possède une liste de méta-informations telles que l’auteur, la date de création, la date de publication, la date de retrait du document, etc. Il est à noter que toutes les méta-informations sont remplies par défaut avec les valeurs issues du contexte. L’édition des méta-informations se fait par clic sur l’onglet voulu, ici nous avons appuyé sur “Catégorisation”. Pour ajouter de nouveaux mots-clés, il suffit lorsqu’on a les droits de les entrer dans l’encart “Nouveaux motsclés”. L’onglet date permet de préciser la période de publication d’un élément. Ici le document sera visible entre le 16 juin 2010 et le 30 juillet. 8 Chapitre 2. Présentation de Plone Plone pour les intégrateurs, Version 1.0.0 F IGURE 2.5 – Association de mots clés aux documents F IGURE 2.6 – Date de publication d’un document 2.4. Édition des contenus 9 Plone pour les intégrateurs, Version 1.0.0 F IGURE 2.7 – Propriété d’un élément 10 Chapitre 2. Présentation de Plone Plone pour les intégrateurs, Version 1.0.0 L’onglet propriété permet de gérer les notions de droit d’auteur. F IGURE 2.8 – Paramètres d’un document L’onglet paramètres permet de préciser comment le document sera visible dans l’arborescence et si l’on autorise les commentaires. Seul l’onglet “contenu” est obligatoire, les autres sont remplis par défaut et peuvent être cachés aux utilisateurs. Une fois que l’on a “enregistré”, le document s’affiche en mode consultation et l’on peut alors changer son état en cliquant sur l’onglet affichant l’état (ici “Privé”). 2.5 Visualisation des documents La visualisation des documents, que ce soient des fichiers, des pages, des images, des liens, des actualités, des événements, permet des mises en formes élaborées reposant sur les dernières techniques du web. Si les documents à partager via le portail sont des images ou des fichiers produits par les outils de bureautique classique (suite Microsoft office, Open Office, PDF, etc.), ils pourront être prévisualisés directement sur le navigateur internet des utilisateurs. Plone peut embarquer des outils permettant de transformer des documents Word, Excel, PowerPoint, etc, en page web. Dès lors un simple navigateur internet suffit pour les consulter. 2.5. Visualisation des documents 11 Plone pour les intégrateurs, Version 1.0.0 2.6 Classement des documents La création et le dépôt des documents peuvent suivre les règles de classement des documents édictées par les habitudes des utilisateurs. Il est donc possible de garantir le respect d’un plan documentaire défini par des procédures qualités. Ce classement est naturel, le portail possède un espace de navigation qui se présente comme une arborescence de fichiers, en conséquence Plone ne permet de créer les documents et sous-répertoires que là où ils ont du sens. On peut définir des types de sous-répertoires n’acceptant que certains types d’éléments, par exemple un répertoire Photothèque ne contiendra que des images. Autre exemple, le répertoire Présentation ne permettra que le dépôt des documents respectant le modèle des présentations. Le plan documentaire peut être établi dynamiquement en ligne par les utilisateurs du site – selon leurs droits et/ou être défini de manière statique. 2.7 Stockage des documents Le portail est une zone d’échange et d’archivage des contenus, qui permet de savoir qui a déposé un document, et quand. Il gère le temps de visibilité des documents et les droits de consultation ou de modification. Les documents, les changements effectués, la liste des membres sont stockés par défaut dans une base de données objet. Il est possible d’utiliser notre solution avec d’autres bases de données, relationnelles ou non. 2.8 Authentification Seules les personnes habilitées à voir les documents les voient, seules celles habilitées à les modifier peuvent le faire. Chaque utilisateur de Plone possède son propre login et mot de passe. Ils peuvent être spécifiques au site ou issus d’une source externe, comme un annuaire LDAP (l’Active Directory de Microsoft par exemple). Il est très aisé de combiner différentes sources. Des solutions existent pour gérer la connexion par SSO. Dans ce cas, l’utilisateur connecté à sa session de Windows (par exemple) est automatiquement logué au site quand il y accède. 2.9 Permissions, rôles et groupes d’utilisateurs Chaque état d’un type de contenu définit les permissions nécessaires à sa création, sa consultation, à son édition et sa suppression. Un utilisateur possède un ou plusieurs rôles qui lui attribuent ou non les permissions sur les contenus parcourus. On peut définir autant de rôles que voulus. Il est possible de réunir plusieurs rôles dans des groupes auxquels appartiennent plusieurs utilisateurs (administrateur, relecteur, membre, anonyme, authentifié, etc). En conséquence, un utilisateur possède un ou plusieurs rôles, et un rôle peut lui être attribué de façon locale dans un dossier, ou attribué par les groupes auxquels il appartient. Les administrateurs peuvent aisément créer des groupes et les gérer. 12 Chapitre 2. Présentation de Plone Plone pour les intégrateurs, Version 1.0.0 F IGURE 2.9 – Authentification par login et mot de passe F IGURE 2.10 – Gestion des utilisateurs 2.9. Permissions, rôles et groupes d’utilisateurs 13 Plone pour les intégrateurs, Version 1.0.0 La gestion des permissions se fait à travers le mécanisme des ACL (Access Control List). La gestion des utilisateurs, des rôles, et des groupes se fait à travers une interface relativement simple. 2.10 Indexation Le portail offre des fonctions de recherche simple et complexe, sur le contenu des documents et les métainformations. Le texte des documents saisis en ligne ou téléchargés (pour les formats les plus courants : Word, Excel, Power Point, pdf, etc.) est indexé. Le moteur de recherche rapide est constitué d’un champ présent en permanence sur toute les pages. Il permet d’effectuer des recherches rapides. La recherche de l’utilisateur est analysée au fur et à mesure de la saisie, des propositions sont faites automatiquement à partir des données de la base. Un formulaire de recherche détaillé permet de filtrer la recherche en fonction des méta-informations, et de lier les critères entre-eux avec les mots-clés OR et AND. F IGURE 2.11 – Recherche dynamique L’indexation des éléments (document, fichier, événements) est entièrement paramétrable. 2.11 Photothèques Les images, dessins, photos peuvent être gérées dans des galeries permettant leur manipulation, visualisation, recherche et intégration aux documents rédigés en ligne. Plone permet de retailler les images, de les afficher sous forme de vignettes, ou dans des diaporamas. 2.12 Fonction d’alerte Les membres du portail peuvent être prévenus lorsque des mises à jour ou des modifications ont été réalisées sur les documents. Un mécanisme événementiel permet de réaliser des actions lorsque certaines choses se produisent sur le portail (nouvel utilisateur, publication d’un document...). Toutefois, la façon standard de notifier les contenus modifiés récemment, ou à modérer est d’afficher leur liste à droite ou à gauche du contenu publié. 14 Chapitre 2. Présentation de Plone Plone pour les intégrateurs, Version 1.0.0 2.13 Actualités, événements, calendrier, lettres d’informations Les actualités et les événements sont des types de base de Plone, le calendrier affiche les événements que l’on est autorisé à voir en fonction de ses rôles, ou groupes. La liste des événements est accessible par simple clic sur l’onglet “Événements”. Les dernières actualités sont accessibles en cliquant sur l’onglet “Actualités”. Ces deux listes peuvent être affichées directement à gauche ou à droite du contenu. Ce placement est paramétrable en ligne par l’administrateur (par exemple en dessous du calendrier). Plusieurs types de lettres d’informations sont possibles, il est facile de modifier la charte graphique des lettres. Le système de lettres d’informations permet de gérer les abonnements désabonnements et peut déléguer à l’émetteur de choisir les membres ou groupes devant la recevoir. 2.14 Espace projet Le portail permet facilement de mettre en place la notion de projet, et offre donc : 1. un calendrier qui tient compte de vos droits pour afficher les événements, 2. des listes de tâches, 3. des classeurs de documents (containers), 4. des forums, 5. des sondages, 6. des actualités. 2.15 Répertoires dynamiques Il est également possible de créer ses propres “collections” de documents : il s’agit de répertoires dont le contenu est en réalité le résultat d’un recherche basée sur des filtres. Il peuvent être emboité les uns dans les autres et en modifiant les critère de recherche, on peut ainsi créer des répertoires transversaux au plan documentaire. 2.16 Références croisées Le portail permet de “lier” des documents entre-eux. Exemples : 1. Fiche descriptive d’un produit et différentes photos d’applications de ce produit. 2. Associer un document en anglais et des traductions faites à partir de ce document. La notion de lien internet est fortement utilisée et permet à Plone de créer des références entre documents. 2.17 Modération du contenu Certaines personnes peuvent avoir pour charge d’accepter ou non la publication des documents sur le portail. Plone permet ceci comme la plupart des CMS (Content Management System) du marché, mais il ne fige pas la chaîne de validation (Workflow), que l’on peut modifier. Par exemple nous avons défini le workflow des tâches de la gestion des projets comme suit : Les états définissent les permissions à avoir pour par exemple voir ou modifier les documents, en les attribuant ou non à des rôles. 2.13. Actualités, événements, calendrier, lettres d’informations 15 Plone pour les intégrateurs, Version 1.0.0 F IGURE 2.12 – Exemple de workflow 16 Chapitre 2. Présentation de Plone Plone pour les intégrateurs, Version 1.0.0 Les transitions définissent qui a le droit de changer les états des documents, dans quelles conditions et quels sont alors les traitements à réaliser. Les utilisateurs voient les transitions qu’ils peuvent exécuter. F IGURE 2.13 – Changement d’état d’un élément La mise en place de chaîne de validation des documents autres que ceux prévus par défaut, passe par la création d’états et transitions. Ceci se fait soit directement à travers l’interface d’administration de Plone soit par l’utilisation d’outils spécifiques. La possibilité de créer simplement et efficacement les workflows associés aux documents déposés ou créés sur le portail est l’un des grands atouts de Plone. La précision de paramétrage des permissions permet de cacher ou montrer les champs d’un document en fonction de l’état du document et des rôles de l’utilisateur. Il est possible de modéliser les workflows en utilisant les outils graphiques basés sur UML (Unified Model Language), Argouml et ArchgenXML. Les administrateurs peuvent modifier les workflows soit en utilisant ces même outils, soit le faire directement à travers le web une fois authentifiés sur le portail. 2.18 Historique des changements effectués sur le contenu Le système trace toutes actions. De plus il permet de revenir à l’état précédent pour chaque action. Ainsi pour les document nous avons un historique pour les changement d’états et pour les modifications apportées. L’historique permet de voir les changements du document que ce soit les états ou les modifications du contenu. En comparant deux versions ensemble on peut voir les modifications apportées. 2.18. Historique des changements effectués sur le contenu 17 Plone pour les intégrateurs, Version 1.0.0 F IGURE 2.14 – Affichage de l’historique d’un élément Ici nous voyons que l’image a été déplacée et qu’un paragraphe a été ajouté. Il est facile de revenir à une version précédente, puisqu’il suffit de cliquer sur les boutons “revenir à cette version” que l’on voit dans l’historique. 2.19 Flux RSS Plone propose nativement l’intégration des flux RSS, ce qui permet aux habitués d’utiliser leur lecteur de flux rss pour savoir s’ils ont des documents à lire. 2.20 Langue du portail, Multilinguisme, Traduction Plone est multi-langue et permet de traduire chaque document ou formulaire en plusieurs langues. Actuellement prés de 80 langues sont supportées et 32 le sont complètement. Pour rajouter une langue non encore supportée par exemple le “Picard”, il suffit de traduire un ensemble de fichiers linguistiques. Les contributeurs peuvent traduire les articles dans une des langues activées pour le site. Quand un contenu est traduit, les visiteurs du site le consultent dans leur propre langue. S’il n’est pas traduit dans leur langue, ils le consultent dans la langue par défaut. 18 Chapitre 2. Présentation de Plone Plone pour les intégrateurs, Version 1.0.0 F IGURE 2.15 – Différences entre deux versions d’un élément 2.20. Langue du portail, Multilinguisme, Traduction 19 Plone pour les intégrateurs, Version 1.0.0 2.21 Charte graphique Plone utilise la technologie CSS2 pour réaliser les feuilles de styles permettant d’avoir le design approprié. Le placement des composants tels que le calendrier est facilement effectué en ligne ou par fichier de configuration. F IGURE 2.16 – Exemple de style basique Il est possible d’adapter des chartes existantes à vos besoins en changeant par exemple les couleurs, les icônes. 2.22 Trombinoscope et annuaires Le portail, fournit un trombinoscope des membres. 2.23 Génération de documents à partir de modèles Il est possible de créer des formulaires permettant aux utilisateurs de n’avoir à saisir que les informations à forte valeur ajoutée d’un document et de laisser le portail générer les documents en les complétant avec les données pouvant être automatisées. Ces documents pourraient aussi bien être des documents textes que des feuilles de calcul, des organigrammes, des tableaux, des diagrammes et autres courbes. 2.23.1 Sécurité Plone est reconnu pour le souci de la sécurité qui fait parti de son design initial. Il a été choisi par la CIA, le FBI, le ministère français de la défense pour cette raison. 20 Chapitre 2. Présentation de Plone Plone pour les intégrateurs, Version 1.0.0 2.23.2 Montée en charge Plone fournit des mécanismes de dimensionnement permettant de déployer plusieurs processus sur une ou plusieurs machines en fonction des besoins. Il est également possible d’utiliser un proxy cache permettant de limiter la sollicitation du serveur. F IGURE 2.17 – Exemple d’architecture de déploiement pour un site conséquent 2.23.3 Serveur virtuel GNU/Linux vs Serveur W2K8 Plone est compatible avec Windows 2008 mais nous lui préférons GNU/Linux en raison de la puissance du scripting shell qui permet de réaliser simplement et à moindre frais l’intégration de composants complexes. Avec GNU/Linux, il est possible de réaliser des montages vidéos, photos, ou gérer de la génération de documents sans interface graphique, ce qui permet par exemple de réaliser des conversions de vidéos avec incrustation et watermarking avec pour seul investissement celui d’une formation. 2.23.4 Tests Unitaires, tests d’intégrations, tests fonctionnels La communauté assure un haut niveau de qualité en automatisant les tests unitaires qui vérifient le bon fonctionnement du code, les tests d’intégration quant à eux permettent de tester que les différents composants n’entrent pas en conflit. Les tests de validation vérifient que les fonctionnalités continuent de fonctionner comme prévu. Pour les tests de validation nous enregistrons des scénarios d’utilisation avec des outils comme Selenium. Ainsi nous pouvons les rejouer à chaque changement, ce qui permet de détecter les effets de bord. 2.23.5 Besoin de formation / Transfert technique L’ensemble des développements, fichiers de configuration, sont réalisés sous licence compatible GPL. Nos supports de cours sont reversés à la communauté Plone sous licence Creative-Common Share Alike By, ils sont donc librement téléchargeables et peuvent être partagés, modifiés tant qu’à votre tour vous redistribuez vos améliorations sous les même termes de licence. 2.23.6 Sécurisation La sécurité de tout site Internet passe par l’utilisation du protocole ssl et vous devez donc acheter un certificat X509 auprès d’une autorité reconnue par les navigateurs internet ou en générer un autosigné. 2.23. Génération de documents à partir de modèles 21 Plone pour les intégrateurs, Version 1.0.0 2.23.7 Statistiques Les rapports sur la fréquentation sont donnés par des outils libres complémentaires tels que piwik, ou fournissant les même services que Google Analytics pour les sites web. Piwik offre une solution très avancée pour réaliser l’analyse du trafic sur votre site Internet. Le module plone collective.piwik.core Ceci est rendu possible par l’utilisation d’un script javascript exécuté par le navigateur chaque fois qu’une page du portail est affichée. F IGURE 2.18 – Statistiques avec Piwik La solution Google analytics est supportée grace au module collective.googleanalytics qui met à disposition une intégration très avancée des événements suivant : – téléchargement – lien externe – commentaire – lien sur un email (contact) De plus ce module est intégré automatiquement avec les modules suivants et donc votre analyse pourra bénéficier des actions utilisateurs supplémentaires correspondant au module : – collective.addthis (partage sur réseaux sociaux) – Products.PloneFormGen (définition d’objectifs) 22 Chapitre 2. Présentation de Plone CHAPITRE 3 Les nouveautés de Plone 3.1 Les nouveautés de Plone 4 Présentation des nouveautés de Plone 4 par rapport à Plone 3.3. Vidéo disponible – – – – – – – – – – – – – – – – – – – – Performances Thème Ergonomie Amélioration de l’administration du site Ordonnancement dans les dossiers amélioré Interface améliorée de gestion des groupes Tableaux de bord des groupes Possibilité de masquer les portlets Authentification par email Amélioration de la customisation du site Gestion des icones d’actions Suppression du base_properties Améliorations techniques Utilisation de Python 2.6 et Zope 2.12 Gestion des pièces jointes avec les blobs Refonte de l’outil de migration JQuery Tools de base Support de l’indexation des langues asiatiques Les dossiers sont tous des BTree Migration de Plone 3.3 vers Plone 4 3.1.1 Performances Plone 4 est centrée sur l’amélioration des performances. Il est en environ deux fois plus rapide que Plone 3, et jusqu’à quatre fois plus rapide que Plone 2.5 aussi bien pour les anonymes que pour les utilisateurs connectés. Il consomme beaucoup moins de mémoire que les anciennes versions. Plone 4 est, à la date de sa sortie l’une des plateformes open source CMS les plus rapides du marché. Cela est dû à la fois à un effort majeur sur l’optimisation du code de Plone, qu’au passage à Python 2.6 plus rapide et moins gourmand que Python 2.4. En savoir plus (fr) 23 Plone pour les intégrateurs, Version 1.0.0 3.1.2 Thème Plone 4 possède un nouveau thème par défaut appelé “Sunburst”, élégant et, minimaliste. Il est conçu comme un composant à part, mais inclus par défaut. Il est donc facile à remplacer. Il n’utilise plus de tableaux. La css a été très fortement simplifiée. Il reste compatible avec Internet Explorer 6. Il est prévu pour être compatible avec le futur outil de mise en page Deco prévu pour Plone 5. En savoir plus (en) 3.1.3 Ergonomie L’interface utilisateur de Plone 4 a été améliorée. Il est plus facile de créer un site Plone , via une page dédiée. Plone 4 inclut par défaut un nouvel éditeur wysiwyg (TinyMCE), et offre de nouveaux paramètres de configuration. TinyMCE remplace kupu. Il existe un produit en remplacement de l’éditeur complet FCKeditor : ckeditor. En savoir plus (en) Amélioration du formulaire de recherche : les options non pertinentes ont été retirées, les critères sont choisis par un système de plié/déplié beaucoup plus clair. En savoir plus (en) 3.1.4 Amélioration de l’administration du site 3.1.5 Ordonnancement dans les dossiers amélioré L’interface pour ordonner les documents dans les dossiers a été améliorée. L’intégration entre ‘tri’ et ‘ordonnancement’ a été améliorée. 24 Chapitre 3. Les nouveautés de Plone Plone pour les intégrateurs, Version 1.0.0 3.1.6 Interface améliorée de gestion des groupes L’interface a été améliorée pour chercher des groupes, associer des utilisateurs à des groupes, etc. Plone 4 permet de mieux gérer les groupes imbriqués. Dans Plone 3.3, vous ne voyiez pas que vous aviez un rôle récupéré grâce un super groupe. Plone 4 a été modifié pour le voir, un peu comme la présentation faite dans l’onglet partage pour les rôles locaux. En savoir plus (en) 3.1.7 Tableaux de bord des groupes Il est maintenant possible de paramétrer des tableaux de bord par défaut pour tous les utilisateurs d’un groupe. En savoir plus (en) 3.1.8 Possibilité de masquer les portlets Un simple clic dans l’outil de management des portlets permet de masquer/afficher un portlet. 3.1.9 Authentification par email Plone 4 prévoit la possibilité d’autoriser l’authentification de l’utilisateur par son email plutôt que par son login. 3.1.10 Amélioration de la customisation du site 3.1.11 Gestion des icones d’actions Les icones d’actions ne sont plus gérées séparément des actions (disparition du tool portal_actionicons) 3.1.12 Suppression du base_properties Les css ne sont plus écrites en dtml, mais en texte pur. L’expérience d’utilisation a montré que l’utilisation de variables dans les css posait plus de risques qu’elle ne faisait gagner de temps. 3.1.13 Améliorations techniques 3.1.14 Utilisation de Python 2.6 et Zope 2.12 Plone 2.5 et 3.x fonctionnaient sous Python 2.4. Python 2.6 est plus rapide et beaucoup moins gourmand en mémoire. Zope 2.12 est compatible avec la version 2.9.x de la ZODB supportant nativement les blobs. Totalement eggifié, il est plus facile à déployer. En savoir plus (en) En savoir plus (en) 3.1. Les nouveautés de Plone 4 25 Plone pour les intégrateurs, Version 1.0.0 3.1.15 Gestion des pièces jointes avec les blobs La ZODB gère maintenant les pièces jointes (images et fichiers) de Plone dans des fichiers à part de la Data.fs, appelés “blobs”. Cela limite l’impact des modifications de pièces jointes sur la taille des transactions : la zodb est plus rapide et grossit moins rapidement entre chaque pack. En savoir plus (en) 3.1.16 Refonte de l’outil de migration Plone utilise maintenant Generic Setup comme outil de migration. On a maintenant le même système de mise à jour pour les modules tierces et pour Plone lui-même. En savoir plus (en) 3.1.17 JQuery Tools de base La bibliothèque Javascript JQuery Tools est incluse de base. Cela permet d’avoir des popups améliorant l’expérience utilisateur. En savoir plus (en) 3.1.18 Support de l’indexation des langues asiatiques Le moteur d’indexation plain texte gère maintenant les langues asiatiques (Chinois, Japonais, Coréen). En savoir plus (en) 3.1.19 Les dossiers sont tous des BTree Il y avait auparavant deux types de dossiers : Folder et Large Folder, les seconds étant des BTree. Les Folder sont maintenant des BTree et les Large Folder ont été retirés. En savoir plus (en) 3.1.20 Migration de Plone 3.3 vers Plone 4 Plone 4 apporte quelques changements radicaux. Il vous faudra sans doute adapter le code de vos produits. Il existe une documentation pour vous y aider. 3.2 Les nouveautés de Plone 3 Présentation des nouveautés de Plone 3 par rapport à Plone 2.5. 26 Chapitre 3. Les nouveautés de Plone Plone pour les intégrateurs, Version 1.0.0 – – – – – – – – – – – – – Édition en ligne Validation des champs via AJAX Support des copies de travail Vérification de l’intégrité des liens Verrouillage d’un document lors de l’édition Nouvel onglet partage Versionnement des documents Visualiser un document en mode diaporama Navigation Précédent/Suivant dans un dossier Générer une table des matières pour un document Indexage des documents Word et PDF Mais aussi Et pour le développeur 3.2.1 Édition en ligne Description de la fonctionnalité “Inline editing” Désactivé par défaut dans Plone 3.3. Pour l’activer, cochez “Activer l’édition en ligne” dans “Configuration du site -> Site” 3.2.2 Validation des champs via AJAX La validation d’un champ d’un formulaire se fait dès que vous le quittez. 3.2.3 Support des copies de travail Working Copy support Installez le produit “Support des copies de travail (Iterate)” via “Configuration du site -> Produits d’extension”. Vous avez maintenant une nouvelle action “Créer un brouillon” accessible sur n’importe quel contenu. 3.2.4 Vérification de l’intégrité des liens Link and reference integrity checking Lors de la suppression d’une image, Plone regarde si des documents sont en train de l’utiliser pour éviter de casser des liens. 3.2.5 Verrouillage d’un document lors de l’édition Automatic locking and unlocking Le document est verrouillé lorsque vous l’éditez. Cela permet d’éviter à un autre utilisateur d’éditer en même temps et d’écraser votre travail. Le verrouillage a été amélioré dans Plone 3.3. Le verrouillage n’est actif que 10 minutes, reconductible si l’utilisateur est toujours en train de l’éditer. 3.2. Les nouveautés de Plone 3 27 Plone pour les intégrateurs, Version 1.0.0 3.2.6 Nouvel onglet partage Easy collaboration and sharing L’onglet partage a été amélioré, plus simple d’utilisation. Chaque intitulé des colonnes correspond à un rôle. – Peut Ajouter : Contributor – Peut modifier : Editor – Peut voir : Reader – Peut Modérer : Reviewer 3.2.7 Versionnement des documents Versioning, history and reverting content Vous pouvez activer le versionnement d’un type de contenu à partir de “Configuration du site -> Types”. Pour pouvoir visualiser les différences entre deux versions, il faut ajouter le type de contenu dans portal_diff. 3.2.8 Visualiser un document en mode diaporama Presentation mode for content Éditez le document et allez dans Paramètres pour cocher “Mode présentation”. 3.2.9 Navigation Précédent/Suivant dans un dossier Automatic previous/next navigation À partir d’un document d’un dossier, vous avez la possibilité d’ouvrir le document précédent ou le suivant. Éditez le dossier et allez dans Paramètres pour cocher “Activer la navigation ‘précédent/suivant”’. 3.2.10 Générer une table des matières pour un document Auto-generated tables of contents Éditez le document et allez dans Paramètres pour cocher “Table des matières”. 3.2.11 Indexage des documents Word et PDF Full-text indexing of Word and PDF documents Plone indexe le texte des documents Word et PDF. Il est donc ensuite possible de rechercher un terme qui est dans ces documents. Cette fonctionnalité est active si vous avez les packages Ubuntu wv (pour les documents Word) et poppler-utils (pour la commande pdftotext) d’installés. Voir howto D’autres formats peuvent être indexés avec le produit ARFilePreview, qui nécessite AROfficeTransforms ou le nouveau plone.transforms. – ARFilePreview-v2 branch (2.3.0) fonctionne avec AROfficeTransforms (utilise portal_transforms). – ARFilePreview trunk v3 fonctionne avec plone.transforms (architecture Zope 3). 28 Chapitre 3. Les nouveautés de Plone Plone pour les intégrateurs, Version 1.0.0 3.2.12 Mais aussi – – – – – – – – – Éditeur HTML visuel (WYSIWYG) amélioré Puissantes fonctionnalités de workflow Gestion flexible de l’authentification Collections Support du protocole de moteur de recherche Sitemap Support de différents formats de balises Support du wiki Moteur de règles de contenu pour la gestion d’évènements Moteur de portlets En savoir plus : Features in Plone 3 3.2.13 Et pour le développeur Technologies qui ont fait leur entrée dans Plone 2.5 et qui sont maintenant incontournables dans Plone 3 : – profils GenericSetup pour importer/exporter une configuration de site, pour une meilleure industrialisation – technologies Zope 3 (évènements, vues...), pour une meilleure maintenabilité du code Technologies qui font leur apparition dans Plone 3 : – gestion des éléments de page avec les nouvelles viewlets et portlets, pour une meilleure réutilisabilité des développements et une meilleure maintenabilité 3.2. Les nouveautés de Plone 3 29 Plone pour les intégrateurs, Version 1.0.0 30 Chapitre 3. Les nouveautés de Plone CHAPITRE 4 Paramétrer votre site Plone Author Thomas Desvenain Created 2010-10-18 Version 0.1.0 Copyright (C) 2010 Thomas Desvenain <thomas.desvenain AT gmail.com>. Chacun est autorisé à copier, distribuer et/ou modifier ce document suivant les termes de la licence Paternité-Pas d’Utilisation Commerciale-Partage des Conditions Initiales à l’Identique 2.0 France accessible à http ://creativecommons.org/licenses/by-nc-sa/2.0/fr 4.1 Objectif Nous allons présenter ici les options de paramétrage offertes de base à l’administrateur d’un site Plone. 31 Plone pour les intégrateurs, Version 1.0.0 Contents – Paramétrer votre site Plone – Objectif – Accéder au menu de configuration – Configurer les paramètres de messagerie – Paramètres du site – Paramètres de base de la sécurité du site – Auto-inscription – Mot de passe choisi par l’utilisateur – Activer les dossiers de l’utilisateur – Affichage de la ligne d’information du document pour les anonymes – Connexion par email – Paramétrage du calendrier – Ajouter un calendrier – Compléter le calendrier – Configurer le calendrier – Paramétrage de la navigation – Configuration des onglets – Configuration de la navigation – Configuration du portlet de navigation – Conclusion – Paramètres de la recherche – Configurer le thème – Paramétrage des modules – Paramétrage des règles de contenu – Paramétrer l’édition de contenus – Edition de l’identifiant – Éditeur de texte par défaut – Éditeur externe – Vérification de l’intégrité des liens – Verrouillage des documents en modification – Paramétrer le filtrage du contenu ajouté en HTML – Filtrage des balises – Balises indésirables – Balises non-XHTML autorisées – Filtrage des attributs – Filtrage des styles et des classes – Paramétrer le comportement wiki – Activer le comportement wiki – Se servir de Plone comme d’un Wiki – Gestion des tailles d’images – Maintenance du serveur et de la base – Choix de la langue du Site – Paramétrer les types de contenu – Définir le workflow par défaut – Définir le workflow de chaque type – Ajout global – Politique de versionnement – Autoriser les commentaires – Portlets spécifiques du type de contenu – Gestion des utilisateurs et groupes – Caching – Discussion – Registre de configuration – Syndication – Éditeur de texte riche TinyMCE 32 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 4.2 Accéder au menu de configuration Vous devez être connecté avec un administrateur. Pour accéder au menu de configuration, cliquez sur votre nom d’utilisateur, par défaut en haut à droite du site, Vous arrivez sur le menu de configuration du site. Cette page est composée de trois parties : – la partie supérieure, Configuration générale, contient des liens vers les différents menus de configuration de Plone, – la partie centrale contient les liens vers les menus de configuration ajoutés par les modules complémentaires que vous aurez installés, – la partie inférieure contient les informations de version et de debug. 4.3 Configurer les paramètres de messagerie Si vous arrivez sur cette page la première fois, un message vous alerte sur le fait que vous n’avez pas configuré le serveur smtp. Nous allons commencer par remédier à cela. Plusieurs fonctionnalités de Plone provoquent des envois de mail. Pour un bon fonctionnement de votre site, vous devez configurer la messagerie. Cliquez sur Envoi de courriels. Vous arrivez sur la page des Paramètres d’envoi des courriels. Entrez dans le champ ‘Serveur SMTP’ l’addresse de votre serveur d’envoi. Si vous êtes dans le réseau d’une entreprise, contactez l’administrateur système pour connaitre ce nom. Si vous êtes à votre domicile, ce nom se trouve dans le courrier d’ouverture de votre ligne envoyé par votre fournisseur d’accès internet (FAI). Il s’agit en général de smtp.nomdufai.fr ou smtp.nomdufai.com. Si vous utilisez Extended-SMTP, remplissez les champs login-mot de passe suivants. À défaut ou si vous n’êtes pas sûr, ne les remplissez pas. Les deux derniers champs, obligatoires, indiquent les informations de l’émetteur des mails envoyés par le site (champ From). Cliquez sur Enregistrer pour sauvegarder vos modifications. 4.4 Paramètres du site La page Paramètres du site permet d’éditer les métadonnées du site, et des réglages de référencement (utiles principalement si votre site est un site internet) Notamment : – le titre du site, – sa description dans les résultats du moteur de recherche Exposer les métadonnées Dublin Core : si cette option est activée, chaque page du site aura des metatags dont le contenu correspondra aux métadonnées du document affiché. Exposer sitemap.xml.gz : activé, les moteurs de recherche auront accès au sitemap, optimisant l’indexation (activez l’option, puis allez sur sitemap.xml.gz depuis la racine de votre site). 4.2. Accéder au menu de configuration 33 Plone pour les intégrateurs, Version 1.0.0 34 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 4.5 Paramètres de base de la sécurité du site La sécurité dans Plone est un vaste sujet, qui sera traité principalement dans d’autres chapitres sur les workflows, les rôles et permissions, etc. Un certain nombre d’options sont disponibles depuis le lien Sécurité de la configuration du site. 4.5.1 Auto-inscription Si l’option est choisie, une option S’inscrire apparaît dans la zone de login pour les anonymes. 4.5.2 Mot de passe choisi par l’utilisateur Si cette option est activée, lorsqu’un utilisateur est créé un mot de passe provisoire est envoyé au nouvel inscrit, qui peut le modifier immédiatement. 4.5.3 Activer les dossiers de l’utilisateur L’option ajoute un lien dossier personnel dans le menu de l’utilisateur. Il s’agit d’un dossier qui est administré par l’utilisateur, dans lequel il peut ajouter des documents qu’il peut soumettre à publication. 4.5.4 Affichage de la ligne d’information du document pour les anonymes Par défaut, seuls les membres voient la ligne de métadonnées Par xxx — Dernière modification xxx sous le titre des documents. Si cette option est activée, elle est visible par les anonymes. 4.5.5 Connexion par email Permet aux utilisateurs de se connecter en utilisant leur email à la place de leur login. 4.5. Paramètres de base de la sécurité du site 35 Plone pour les intégrateurs, Version 1.0.0 36 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 4.5. Paramètres de base de la sécurité du site 37 Plone pour les intégrateurs, Version 1.0.0 38 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 4.6 Paramétrage du calendrier Le calendrier de Plone affiche, dans un portlet, un petit calendrier dans lequel les dates comprenant des événements apparaissent en surbrillance. Nous allons d’abord ajouter un portlet calendrier sur notre site, en haut à gauche. 4.6.1 Ajouter un calendrier Rendez-vous à la racine de votre site, en cliquant sur le logo. En bas à gauche de la page, cliquez sur Gérer les portlets Vous arrivez sur la page de gestion des portlets. Cliquez sur Ajouter un portlet... sur la colonne de gauche, et sélectionnez le portlet calendrier. Cliquez sur la flèche-haut devant Calendrier pour monter le calendrier au-dessus de la navigation. Revenez sur l’accueil. Vous avez maintenant votre portlet calendrier. Il est bien vide pour le moment... 4.6.2 Compléter le calendrier Le calendrier contient des références à des contenus événement. Allez dans le dossier Événements et ajoutez-en un. Pour l’instant, rien n’a changé. Publiez-le. Il apparait dans le calendrier. 4.6. Paramétrage du calendrier 39 Plone pour les intégrateurs, Version 1.0.0 40 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 4.6. Paramétrage du calendrier 41 Plone pour les intégrateurs, Version 1.0.0 42 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 4.6. Paramétrage du calendrier 43 Plone pour les intégrateurs, Version 1.0.0 Créez un autre événement pour la veille du précédent, Préparation de la salle, et enregistrez-le, cette fois sans le publier. Vous voudriez peut-être que les événements ‘privés’ s’affichent pour leurs propriétaires et tous ceux qui y ont accès. Il est possible de configurer cela. 4.6.3 Configurer le calendrier Retournez dans la Configuration du site, puis cliquez sur Calendrier Vous pouvez ici sélectionner les états dans lesquels vos événements apparaîtront dans le calendrier. Sélectionnez Privé [private]. En France, la norme est plutôt de commencer la semaine par le lundi. Sélectionnez Lundi Enregistrez. Le document privé apparaît (ici le 18) et l’ordre des jours a changé. 44 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 4.7 Paramétrage de la navigation La page Paramètres de navigation permet de configurer deux choses : les onglets généraux du site et le portlet de navigation. 4.7.1 Configuration des onglets Par défaut, la barre de navigation supérieure affiche un onglet pour chaque dossier ajouté à la racine. La première option permet de désactiver ce comportement. (Dans ce cas, il faudra ajouter manuellement les actions sur la barre d’onglet, ce qui est plus complexe et fera l’objet d’un autre chapitre) Si la seconde option est activée, les documents de la racine seront également affichés comme onglets. Si vous voulez masquer un dossier des onglets (par exemple : Membres), rendez-vous sur le dossier, cliquez sur Modifier, puis Paramètres. Cochez Exclure de la navigation et enregistrez. Membres n’apparaît plus dans la barre de navigation supérieure. 4.7.2 Configuration de la navigation Vous pouvez également choisir ici les types de contenus affichés dans le portlet de navigation. Il est fréquent de choisir de n’afficher que les dossiers. Vous pouvez également filtrer les contenus affichés dans l’arborescence par état documentaire (sachant que, de toute façon, seuls les dossiers et documents qu’un utilisateur a le droit de voir apparaissent dans la navigation) Le plan du site utilise également ces paramètres. 4.7.3 Configuration du portlet de navigation Attention, ces paramètres ne recouvrent qu’une partie de la configuration du portlet de navigation. Pour la configurer, revenez à la racine et cliquez sur Gérer les portlets à gauche. 4.7. Paramétrage de la navigation 45 Plone pour les intégrateurs, Version 1.0.0 46 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 4.7. Paramétrage de la navigation 47 Plone pour les intégrateurs, Version 1.0.0 48 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 Cliquez maintenant sur le nom du portlet Navigation. Vous arrivez sur un menu de configuration (assez complexe) où vous définissez essentiellement trois choses : – le niveau d’affichage, qui est le nombre de niveaux à partir du niveau racine avant qu’on affiche les contenus dans la navigation – le niveau racine, qui est le niveau à partir duquel on compte le niveau d’affichage – la profondeur d’affichage, qui est le nombre de niveaux maximal qu’on affiche sous le niveau racine... Par défaut, le niveau d’affichage est 1 et le niveau racine est la racine du site : on ne voit donc que les documents contenus dans les dossiers ajoutés à la racine... (les choses sont paramétrées par défaut de cette façon de sorte que les dossiers à la racine n’apparaissent pas ET dans le portlet de navigation ET dans la barre d’onglets) Imaginons que nous voulions afficher les dossiers à la racine. Entrez 0 pour niveau d’affichage et enregistrez. 4.7.4 Conclusion Pourquoi deux pages pour configurer le portlet de navigation : dans les paramètres du site et dans les paramètres du portlet ? En fait, vous pouvez tout à fait avoir plusieurs portlets de navigation sur votre site, configurées différemment. Mais toutes sont concernées par les paramètres définis au niveau de la configuration du site... 4.8 Paramètres de la recherche La page Paramètres de la recherche permet : – D’activer / désactiver la recherche instantanée, – De sélectionner les types de contenu dans lesquels on fait nos recherches, Et de décider finement d’activer ou pas certaines options de recherche de la recherche avancée : – possibilité de chercher par état pour les anonymes, 4.8. Paramètres de la recherche 49 Plone pour les intégrateurs, Version 1.0.0 50 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 4.8. Paramètres de la recherche 51 Plone pour les intégrateurs, Version 1.0.0 52 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 – – – – possibilité de modifier l’ordre des résultats, possibilité de modifier le nombre de résultats par page, champs de recherche spécifiques Titre et Description, réduction automatique des options rarement utilisées. 4.9 Configurer le thème Cette page permet de configurer les paramètres d’apparence, notamment le thème sélectionné. Amusez-vous à sélectionner le Plone Classic Theme Il permet de s’assurer que Plone 4 est toujours compatible avec les thèmes conçus pour les anciennes versions... Ceci étant dit, vous pouvez revenir sur le thème de Plone 4 (Sunburst) :) Vous pouvez paramétrer les liens externes de sorte qu’ils soient marqués, et qu’ils s’ouvrent dans un nouvel onglet. Vous pouvez également supprimer les icônes de type de contenu dans les listes et les portlets. Enfin, vous pouvez désactiver le système de popup en superposition (dit aussi lightbox) pour les formulaires simples. 4.10 Paramétrage des modules Pour l’activation et la désactivation de modules, référez-vous au chapitre Choix et ajout d’un module. 4.9. Configurer le thème 53 Plone pour les intégrateurs, Version 1.0.0 54 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 4.11 Paramétrage des règles de contenu Pour les règles de contenu, référez-vous au chapitre Déclenchement d’événements avec les règles de contenu. 4.12 Paramétrer l’édition de contenus La page des Paramètres d’édition permet de configurer le comportement général de l’édition de documents. 4.12.1 Edition de l’identifiant Chaque contenu a un identifiant, qui est unique dans chaque dossier. Par défaut, l’identifiant est généré automatiquement à partir du titre proposé. Vu que l’identifiant est utilisé dans l’URL, de nombreux utilisateurs préfèrent le saisir eux mêmes. 4.11. Paramétrage des règles de contenu 55 Plone pour les intégrateurs, Version 1.0.0 Avec cette option activée, les utilisateurs auront une nouvelle option dans leurs préférences personnelles : Si elle est activée, l’utilisateur pourra saisir l’identifiant d’un document lorsqu’il le crée ou le modifie. 4.12.2 Éditeur de texte par défaut Par défaut sur Plone, l’éditeur de texte est TinyMCE. Cependant il est possible d’installer d’autres éditeurs (ckeditor notamment). Chaque utilisateur peut choisir son éditeur, mais par défaut, l’éditeur sera celui choisi sur cette page de configuration. Si vous avez installé un nouvel éditeur sur votre site, ckeditor par exemple, il aura une page de configuration spéciale, avec un lien ajouté dans la partie Configuration de module du menu de configuration. 4.12.3 Éditeur externe Si cette option est activée, les utilisateurs auront la possibilité d’activer l’édition externe dans leurs préférences personnelles. L’édition externe permet, à condition d’avoir installé un soft sur son poste, de modifier des documents de Plone en les éditant directement avec son logiciel préféré, sans avoir besoin de passer par un formulaire. Ce qui est particulièrement utile pour les fichiers type tableur ou traitement de texte. Veuillez vous référer au chapitre Zope External Editor pour de plus amples informations. 4.12.4 Vérification de l’intégrité des liens Si cette option est activée, lorsque vous supprimez un document, Plone vérifie qu’aucun autre document ne contient un lien vers ce document, et vous alerte le cas échéant. 56 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 Nous avons créé un document Mon document de référence et un document Mon document contenant des liens. Dans ce dernier, nous avons ajouté un lien, dans le texte principal, avec le premier. Quand nous supprimons Mon document de référence nous obtenons cette popup de confirmation : 4.12.5 Verrouillage des documents en modification Quand le verrouillage est activé, si un utilisateur est sur le formulaire de modification d’un document, les autres utilisateurs susceptibles de modifier le document sont avertis, et ils ne peuvent accéder au formulaire sans forcer le déverrouillage. 4.12. Paramétrer l’édition de contenus 57 Plone pour les intégrateurs, Version 1.0.0 4.13 Paramétrer le filtrage du contenu ajouté en HTML Les éditeurs WYSIWYG permettent aux contributeurs du site d’éditer le code html de pages qui seront ensuite affichées par les navigateurs des visiteurs du site. Il peut être dangereux ou gênant de permettre à vos utilisateurs de créer des formulaires, d’afficher des objets flash ou autre, d’ajouter des balises meta, de trop paramétrer le style de son contenu, etc. La page Paramètres du filtrage HTML permet à l’administrateur du site de contrôler les éléments html dont il permet l’introduction par les contributeurs. Dans l’autre sens, si vos utilisateurs s’étonnent que certains contenus qu’ils ajoutent ne sont pas enregistrés, c’est ici que vous pouvez étendre les autorisations. La première page permet de définir les balises qui sont filtrées. 4.13.1 Filtrage des balises Par défaut, toutes les balises XHTML sont acceptées, les autres sont filtrées : l’élément est supprimé mais pas son contenu. Éditez un document du site avec un éditeur WYSIWYG, mais avec l’option HTML (éditer le code source). Entrez le contenu <toto>Ceci est du texte dans une balise non-html</toto> Enregistrez le document. Éditez-le à nouveau. Le texte ci-dessus a été remplacé par du XHTML valide, par exemple avec TinyMCE <p>Ceci est du texte dans une balise non-html</p> 4.13.2 Balises indésirables Ajoutez maintenant ce code <script language="Javascript">while(0!=1) alert(’toto’);</script> Enregistrez. Heureusement, ce script ne s’applique pas ! Rééditez votre page sur l’édition, et cliquez sur ‘HTML’. Vous verrez que votre code a été remplacé par <!-- while(0!=1) alert(’toto’); // --> Les balises indésirables sont commentées. Là donc, même le contenu n’apparaît pas. 4.13.3 Balises non-XHTML autorisées Le troisième bloc de la page permet d’autoriser dans le html des balises qui ne sont pas XHTML. On y trouve notamment les balises HTML5. 58 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 4.13. Paramétrer le filtrage du contenu ajouté en HTML 59 Plone pour les intégrateurs, Version 1.0.0 60 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 4.13.4 Filtrage des attributs La deuxième page permet de filtrer les attributs. Le premier bloc indique la liste des attributs qui seront simplement supprimés à l’enregistrement. Le second bloc indique les attributs qui seront supprimés s’ils sont dans telle ou telle balise en particulier. Par exemple, ici on retire les attributs width et height des tables et des cellules. 4.13.5 Filtrage des styles et des classes Si l’attribut style est autorisé, vous ne voulez pas forcément que vos utilisateurs puissent attribuer n’importe quelle valeur css. De même, vous craignez peut-être que vos utilisateurs utilisent certaines classes css. Vous pouvez maitriser la liste des attributs css disponibles dans les attributs ‘styles’, ainsi que les noms de classes interdits dans toute balise ‘class’. Editez votre document, et entrez ce code <p style="font-size: 250px; text-align: right">Mon texte stylé</p> Vous observez que seul le text-align s’applique. Éditez à nouveau le contenu, vous verrez que ce code est conservé <p style="text-align: right; ">Mon texte stylé</p> 4.13. Paramétrer le filtrage du contenu ajouté en HTML 61 Plone pour les intégrateurs, Version 1.0.0 4.14 Paramétrer le comportement wiki 4.14.1 Activer le comportement wiki Plone permet d’avoir un comportement wiki, afin d’optimiser la création de contenus liés. Par défaut, cela n’est pas activé. Allez dans Paramètres du formatage de texte. Puis allez sur l’onglet Comportement wiki. Nous allons l’activer pour les documents. Cochez Documents et enregistrez. 4.14.2 Se servir de Plone comme d’un Wiki Créez maintenant un document sur votre site. Mettez entre double-parenthèses (( )) ou entre double-crochets [[ ]] les documents que vous voulez pouvoir lier par la suite. Un clic sur un lien ‘+’ crée un nouveau contenu ayant pour titre le texte lié. Le lien + se transforme en lien vers le nouveau contenu. L’identifiant (ici : CMS) peut être utilisé à plusieurs endroits (y compris sur plusieurs pages différentes), il crée automatiquement un lien vers cette nouvelle page. 4.15 Gestion des tailles d’images Quand vous ajoutez une image dans un document, vous choisissez parmi un certain nombre de tailles d’images. Ces tailles disponibles sont éditables dans la configuration du site, dans Paramètres de la gestion des images. 4.16 Maintenance du serveur et de la base Les opérations de maintenance sont disponibles depuis la page Maintenance du menu de configuration. Vous pouvez, de cette page, arrêter ou redémarrer le site, et ‘packer’ la base de données. 62 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 4.16. Maintenance du serveur et de la base 63 Plone pour les intégrateurs, Version 1.0.0 La base de données (ZODB) doit être packée régulièrement. Elle stocke toutes les transactions effectuées, ce qui est utile notamment pour la fonction Undo, mais ralentit progressivement les performances en lecture / écriture. Il est nécessaire de purger ces informations, en conservant celles des derniers jours. Un chapitre sur la ZODB est à venir dans la documentation développeur. 4.17 Choix de la langue du Site La page Paramètres linguistiques permet de choisir la langue du site. Elle est définie par défaut comme la langue du navigateur de l’utilisateur qui a créé le site. Les options de langue pour les sites multilingues ne se configurent pas ici. Nous fournirons une documentation spécifique pour les sites en plusieurs langues. 4.18 Paramétrer les types de contenu 4.18.1 Définir le workflow par défaut Première page : workflow par défaut. Changer le workflow : Enregistrer : 4.18.2 Définir le workflow de chaque type Sélectionner un type. On peut choisir son workflow spécifique. 64 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 4.18. Paramétrer les types de contenu 65 Plone pour les intégrateurs, Version 1.0.0 66 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 4.18. Paramétrer les types de contenu 67 Plone pour les intégrateurs, Version 1.0.0 68 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 4.18.3 Ajout global Si cette option est activée pour un type, un document de ce type peut être ajouté dans n’importe quel dossier qui ne comporte pas de restriction sur son contenu. 4.18.4 Politique de versionnement Activer le versionnement manuel pour les fichiers. Modifier ensuite un fichier. Cocher la case nouvelle version. 4.18.5 Autoriser les commentaires Si cette option est activée, le type de contenu est ouvert au système de commentaires. Activez les commentaires pour le type Fichier. Allez sur un contenu fichier, vous voyez maintenant une section Commentaires avec un bouton Ajouter un commentaire. Si vous cliquez sur Ajouter un commentaire, une popup s’ouvre vous permettant de saisir votre texte. Enregistrez-le, il apparaît au bas du document. Il est possible de le supprimer, ou d’y répondre. 4.18.6 Portlets spécifiques du type de contenu Vous pouvez paramétrer des portlets qui s’afficheront suivant le type de contenu de la page affichée. Sélectionnez un type de contenu (ici Fichier) sur l’écran de configuration des types. Vous avez un lien Gérer les portlets affectés à ce type de contenu. Cliquez ce lien, vous arrivez sur une page similaire à la page Gérer les portlets vue plus haut. Ajoutez un portlet, en naviguant sur le site, vous verrez que lorsque vous allez sur une page Fichier, ce portlet apparaît. 4.19 Gestion des utilisateurs et groupes Cette page permet de gérer les utilisateurs et groupes. 4.19. Gestion des utilisateurs et groupes 69 Plone pour les intégrateurs, Version 1.0.0 70 Chapitre 4. Paramétrer votre site Plone Plone pour les intégrateurs, Version 1.0.0 4.19. Gestion des utilisateurs et groupes 71 Plone pour les intégrateurs, Version 1.0.0 4.20 Caching Pour gérer les règles de cache. 4.21 Discussion Pour gérer les options liées aux commentaires. 4.22 Registre de configuration Pour configurer certaines options qui n’ont pas d’interface dédiée. 4.23 Syndication Pour gérer les options liées aux flux RSS. 4.24 Éditeur de texte riche TinyMCE Pour gérer les options de TinyMCE. 72 Chapitre 4. Paramétrer votre site Plone CHAPITRE 5 Choix et ajout d’un module Author Michael Launay Version 0.1.0 Copyright (C) 2010 Michael Launay <michaellaunay AT ecreall.com>. Chacun est autorisé à copier, distribuer et/ou modifier ce document suivant les termes de la licence Paternité-Pas d’Utilisation Commerciale-Partage des Conditions Initiales à l’Identique 2.0 France accessible à http ://creativecommons.org/licenses/by-nc-sa/2.0/fr 5.1 Introduction Plone est un Content Management System, c’est à dire un portail collaboratif qui permet de gérer des contenus tels que des documents, des images, des événements, des vidéos, etc. Il permet de créer et de gérer les cycles de publications des contenus, ainsi on peut affecter des rôles aux membres leur permettant ou non de créer, modifier, voir, ou changer les règles des contenus. Plone permet facilement la création de nouveaux types de contenu, de nouvelles règles de gestion, de nouveaux rôles ou groupes. Cette finesse de la gestion des droits associée au fait que Plone est un logiciel libre a permis la création de nombreuses extensions permettant soit de spécialiser Plone soit de l’étendre. Ces extensions ont d’abord été appelées “produits” mais à partir de la version 4 de Plone nous parlons de “modules”. La première étape consiste à identifier son besoin. Ensuite, il faut vérifier que Plone ne propose pas déjà les fonctionnalités désirées. Pour cela, nous pouvons commencer par voir si Plone fournit de base un type de contenu spécifique de ce besoin. S’il existe un contenu, il faut alors vérifier que le workflow, qui lui est associé, correspond à notre besoin et si nécessaire en développer un autre. S’il n’existe pas de contenu correspondant à notre besoin et que celui-ci est générique, alors il existe surement un module couvrant partiellement ou complètement notre besoin. On va donc chercher et sélectionner un module. 5.2 Rechercher et sélectionner un module Le site plone.org contient la vitrine des modules Plone disponibles. 73 Plone pour les intégrateurs, Version 1.0.0 http ://plone.org/products Depuis la version 4 de Plone le site de la communauté Plone possède un nouveau classement des modules qui permet entre autres de les chercher par popularité. Un article sur cette nouvelle interface a été écrit sur le site de la communauté française http ://plone.fr/news/nouveautes-plone-products Les modules suivent un cycle de vie de développement, les plus utilisés sont maintenus et sont adaptés aux nouvelles versions de Plone rapidement. Avant d’utiliser un module, il faut se poser les questions suivantes : – Ce module est-il compatible avec notre version de Plone ? – Depuis combien de temps existe le module ? – Est-il encore utilisé ? – Est-il maintenu ? – Y a-t-il eu des remontées de bogues et est-ce possible ? – Si oui y a-t-il eu des corrections apportées et au bout de combien de temps ? – La société ou les développeurs derrière ce module, sont-ils actifs dans la communauté ? – A-t-on accès au code source du module ? – Le code est-il sur le dépôt de la communauté Python ou Plone ? – Le module respecte-t-il les standards de programmation de la communauté ? – Est-il documenté ? – Modifie-t-il Plone ? Suivez ensuite la méthode d’installation indiquée sur la documentation du produit. À défaut d’être précisée, c’est toujours la même, nous la présentons plus loin. 5.3 Installer un module Les modules Plone proposés sur plone.org sont hébergés sur des dépôts. – Le dépôt des programmes open source de Python, appelé “pypi” et accessible sur le lien http ://pypi.python.org/pypi – Les dépôts des projets et sociétés dont les adresses peuvent être trouvées sur internet. Le dépôt Pypi est celui de la communauté Python qui est le langage de programmation de Plone. Pour y trouver un module spécifique de Plone il faut faire une recherche en utilisant le mot-clé Plone et les mots que vous pensez être associés à votre besoin. Pypi affichera les “egg” liées à Plone, en effet depuis les versions 3 de Plone les modules sont fournis sous forme de paquets appelés “egg” dont on détaillera l’anatomie et comment les ajouter à Plone plus loin. Plone est désormais entièrement constitué de eggs qui forment autant de bibliothèques. Les modules hébergés exclusivement par les sites de leurs développeurs sont plus durs à identifier et leur capital confiance est moins bon. Pour installer un module, il suffit en général d’ajouter le nom du module à la valeur eggs dans le fichier de configuration (buildout.cfg), et de relancer l’installation du site. (Pour plus d’information sur l’installation de Plone, consultez la documentation intégrateur). Il vous faut ensuite aller dans la configuration du site, section Modules, puis activer le module. 74 Chapitre 5. Choix et ajout d’un module Plone pour les intégrateurs, Version 1.0.0 5.3. Installer un module 75 Plone pour les intégrateurs, Version 1.0.0 De nombreux exemples d’installation de modules seront présentés dans cette documentation. 5.4 Tester le module Ensuite il faut absolument essayer le module sur une copie du site de production pour vérifier qu’il correspond à notre besoin et surtout qu’il ne casse pas nos autres modules et respecte l’intégrité de notre site. Il faut alors dérouler des tests de validation du portail pour vérifier l’intégrité du portail. Puis il faut tester le fonctionnement du module pour vérifier son adéquation avec le besoin. Si le besoin n’est pas complètement satisfait il faut alors chercher un module plus complet ou compléter le développement du module sélectionné. Le fait de compléter un module déjà existant par rapport à en créer un ex nihilo est à préférer, surtout si les évolutions que l’on souhaite apporter sont dans la logique du module. Cette attitude vertueuse permet : – de réduire les coûts en ne recréant pas ce qui existe déjà, – de bénéficier d’une communauté d’utilisateurs et de développeurs, – d’améliorer la couverture fonctionnelle d’un module ce qui du coup augmente ses chances d’être réutilisé et donc maintenu. 76 Chapitre 5. Choix et ajout d’un module CHAPITRE 6 Le protocole HTTP et ses tests – Définition – Savoir – Les versions de HTTP et leur RFC – L’envoi de requêtes – Les méthodes (HEAD, GET, POST, DELETE, PUT, CONNECT, OPTIONS, TRACE) – GET – HEAD – POST – OPTIONS – CONNECT – TRACE – PUT – DELETE – L’entête et ses champs (Host, Referer, User-Agent, etc.) – Host – Referer – User-Agent – Connection – Accept – Accept-Charset – Accept-Language – La réponse et ses champs – Date – Server – Content-Length – Content-Type – Expires – Last-Modified – Les cookies – HTTPS – Mesures de charges – Exercice – Ressources 6.1 Définition Connaître le protocole HTTP permet d’anticiper certaines limitations de déploiement. 77 Plone pour les intégrateurs, Version 1.0.0 Le protocole HyperText Transfert Protocol est un ensemble de règles qui régit la demande et l’envoi de pages web entre un client et un serveur. Le protocole HTTP délègue au protocole TCP (Transmission Control Protocole) l’envoi physique des données. Les clients sont généralement des navigateurs web qui se connectent via internet à des serveurs Web qui leur retournent les pages demandées. Toutefois il existe des applications qui utilisent ce protocole pour communiquer entre elles. Nous rappelons ce qui se passe généralement lorsqu’un utilisateur demande à son navigateur une page web : 1. L’utilisateur saisit le nom d’un site ou d’une page (adresse URL) dans la barre d’adresse de son navigateur par exemple http ://www.ecreall.com/societe ; 2. Le navigateur découpe le nom saisi pour extraire le protocole à utiliser, ici http car le préfixe est “http ://”, et le nom du serveur, ici www.ecreall.com ; 3. Le navigateur réalise alors un résolution de nom en se connectant à un serveur de nom qui lui permettra de transformer le nom en adresse IP, www.ecreall.com donnera 88.191.227.112 ; 4. Il se connectera alors au serveur via le protocole TCP/IP en se connectant au port 80 qui est celui du protocole http par défaut (il est possible de donner un autre numéro de port par exemple http ://www.ecreall.com :8080/) ; 5. Si la connexion réussit, le navigateur suivra les règles du protocole http pour demander la page “societe” en envoyant les requêtes appropriées au serveur ; 6. Le serveur retournera alors cette page au format HTML ou XHTML en utilisant à son tour le protocole HTTP et fermera la connexion ; 7. Une fois la page reçue, le navigateur analysera son contenu et appliquera les règles html ou xhtml pour réaliser la mise en forme et afficher le résultat. 6.2 Savoir 6.2.1 Les versions de HTTP et leur RFC Le protocole HTTP inventé par Tim Berners-Lee en 1989 devient un standard en 1996 et se répand sur internet en version HTTP/1.0. Le protocole est décrit par la Request For Comment RFC 1945. Cette version permet de gérer plusieurs serveurs web sur une même machine et donc de servir un contenu différent en fonction de la racine de l’URL. En 1997 sort la version HTTP/1.1 modifiée en 1999 et décrite par la RFC 2616, qui ajoute le support du pipeline (envoi de plusieurs requêtes puis réception de toutes les réponses) et la négociation de type de contenu. 6.2.2 L’envoi de requêtes Le client se connecte au serveur et lui transmet ses attentes (que l’on appelle méthodes), le serveur lui répond et se déconnecte. Cet échange s’appelle une requête. Avant d’arriver au serveur, la requête peut passer par plusieurs intermédiaires qui peuvent la modifier ou y répondre s’ils connaissent déjà la réponse (mécanisme de la mise en cache). L’un des grands avantages du protocole http est qu’il s’agit d’un protocole texte. Ainsi un humain peut à l’aide du programme “telnet” dialoguer avec un serveur en entrant directement le nom des commandes et leurs paramètres. 78 Chapitre 6. Le protocole HTTP et ses tests Plone pour les intégrateurs, Version 1.0.0 6.2.3 Les méthodes (HEAD, GET, POST, DELETE, PUT, CONNECT, OPTIONS, TRACE) GET Cette méthode permet de demander une ressource telle qu’une page, une image, etc. Elle ne modifie pas la ressource, en conséquence si la ressource n’a pas été modifiée, le résultat de la requête est toujours le même. HEAD Cette méthode permet d’obtenir des informations sur une ressource. POST Cette méthode permet d’envoyer le résultat d’un formulaire ou de transmettre un fichier vers le serveur. Les informations à envoyer se trouvent dans les données de la requête et non pas dans l’URL. OPTIONS Cette méthode permet d’obtenir les options de communication d’une ressource ou du serveur en général. CONNECT Cette méthode permet de demander aux intermédiaires de ne pas changer le contenu des requêtes et de les passer au serveur. TRACE Cette méthode demande au serveur de retourner ce qu’il a reçu, ceci pour permettre de diagnostiquer la connexion. PUT Cette méthode remplace ou ajoute une ressource sur le serveur si l’on en a les droits. DELETE Cette méthode supprime une ressource du serveur si l’on est autorisé à le faire. 6.2.4 L’entête et ses champs (Host, Referer, User-Agent, etc.) Une requête HTTP 1.0 présente le format suivant : Ligne de commande (Commande, URL, Version de protocole) En-tête de requête [Ligne vide] Corps de requête Les réponses HTTP 1.0 présentent le format suivant : Ligne de statut (Version, Code-réponse, Texte-réponse) En-tête de réponse [Ligne vide] Corps de réponse 6.2. Savoir 79 Plone pour les intégrateurs, Version 1.0.0 Exemple de requête : GET / HTTP/1.0 Host: www.ecreall.com User-Agent: Telnet Nous allons voir ici les principaux champs. Host Il permet d’indiquer au serveur le site que l’on souhaite interroger et permet donc le virtualhosting. Il est obligatoire pour le protocole 1.1. Referer Donne l’URI sur laquelle on a trouvé et cliqué le lien menant à la page demandée. Ce champ est utilisé pour les statistiques. User-Agent Donne le nom du programme utilisé pour se connecter au serveur. Le protocole HTTP/1.1 ajoute les champs suivants : Connection Ce champ permet au navigateur ou au serveur de préciser des options de connexion souhaitées ou appliquées. Le champ Connection ne contient que la liste des options. La valeur d’une option est alors précisée dans l’entête comme s’il s’agissait d’un champ, toutefois le nom du champ est le même que celui mis dans Connection. Accept Indique les types MIME gérés par le client. L’astérisque est un joker. Accept-Charset Donne les encodages de caractères supportés. Accept-Language Spécifie les langages acceptés. 6.2.5 La réponse et ses champs Réponse : 80 Chapitre 6. Le protocole HTTP et ses tests Plone pour les intégrateurs, Version 1.0.0 HTTP/1.1 200 OK Date: Fri, 19 Feb 2010 13:22:42 GMT Server: Zope/(Zope 2.10.6-final, python 2.4.5, linux2) ZServer/1.1 Plone/3.1.7 Content-Length: 16051 Expires: Sat, 01 Jan 2000 00:00:00 GMT Content-Type: text/html;charset=utf-8 Content-Language: fr Via: 1.0 www.ecreall.com Connection: close <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> ... La première ligne est le statut de la réponse : – 2xx (ici 200), pas de problème. – 3xx la ressource a été déplacée. – 4xx la ressource n’existe pas. – 5xx il y a un problème. Date Date de création de la réponse. Server Annonce le logiciel et la version ayant crée la réponse. Content-Length La taille de la ressource en octets. Content-Type Type MIME de la ressource. Expires Date de “péremption” de la réponse. Au-delà de cette date la page devra être rechargée ce qui permet au navigateur ou au cache de savoir quand transmettre les requêtes. Last-Modified Date de dernière modification de la ressource. Autres entêtes HTTP Ce qui précède est un aperçu des entêtes HTTP les plus courantes. D’autres entêtes peuvent également être échangées entre un navigateur et un serveur, notamment pour la gestion du cache. Pour plus de détails sur la négociation de cache, lire (en anglais) http ://www.mnot.net/cache_docs/ 6.2. Savoir 81 Plone pour les intégrateurs, Version 1.0.0 6.2.6 Les cookies Le cookie est un ensemble de données transmises dans l’entête des requêtes http par un serveur (Set-Cookie : name=value) à un client qui les stockes sur son disque s’il est persistant et le retransmet à chaque requête au serveur (Cookie : name=value). Il sert soit à l’authentification, soit à la gestion de la session, soit à l’enregistrement des préférences du client etc. 6.2.7 HTTPS HTTPS est l’encapsulation du protocole http dans une couche de chiffrement telle SSL ou TLS. Le serveur doit posséder un certificat X509 qui permettra d’une part de vérifier l’authenticité du serveur, et d’autre part d’échanger confidentiellement avec le client une clé permettant de chiffrer symétriquement la suite de la communication. En effet, l’une des particularités de ssl est que le serveur possède une clé publique qui sera envoyée en clair au client, et une clé privée qui permettra de déchiffrer les informations chiffrées avec la clé publique. Ce chiffrement est dit asymétrique et est complexe et lent à mettre en œuvre mais il présente l’immense avantage que le client n’a pas à partager de secret avec le serveur avant de se connecter et peut ainsi se connecter avec des serveurs qu’il ne connait pas. Le certificat X509 du serveur doit être signé par une autorité connue du client pour que le navigateur fasse confiance au serveur. Le mécanisme mis en œuvre pour cette signature repose également sur le mécanisme de chiffrement asymétrique, le client possède une liste d’autorités connues avec leurs clés publiques respectives ce qui permettra de vérifier qu’un certificat X509 est intègre et a bien été signé par l’autorité indiquée dedans. De plus le chiffrement symétrique de la communication est associé à une fonction de hachage qui permet d’assurer l’intégrité des données transmises. Le port utilisé par HTTPS est par défaut le 443. 6.2.8 Mesures de charges Pour mesurer la vitesse de réponse de notre serveur, ainsi que sa capacité à supporter plusieurs requêtes simultanées nous allons utiliser deux outils : Firebug et ab. “firebug” est un plugin de Firefox qui permet d’analyser les pages web et d’en connaître les détails. Son onglet Réseau permet de voir les ressources chargées, leur temps de chargement, leur taille. L’onglet Réseau/HTML permet de voir les entêtes des requêtes. ab est un outil fournit avec Apache qui permet de lancer des requêtes en parallèles afin de contrôler la capacité du serveur à gérer celle-ci. Exemple : $ ab http://www.ecreall.com $ ab -n 20 -c 4 http://www.ecreall.com/ \ # qui envoie 20 requêtes répartie en 4 threads Lorsqu’on rencontre des problèmes réseaux difficiles à identifier, il peut être utile d’utiliser tcpdump -i eth0 -w /tmp/nomdufichier sur le serveur, afin d’enregistrer tous les paquets circulant sur l’interface eth0 dans le fichier /tmp/nomdufichier. On peut alors utiliser ‘wireshark’ pour inspecter les trames enregistrées dans le fichier. 6.3 Exercice Utilisation de telnet pour accéder au serveur. Test de performance du serveur (la commande “ab” d’Apache). 82 Chapitre 6. Le protocole HTTP et ses tests Plone pour les intégrateurs, Version 1.0.0 6.4 Ressources – – – – – Le protocole HTTP Les cookies Les certificats électroniques Autorité de certification Le modèle OSI 6.4. Ressources 83 Plone pour les intégrateurs, Version 1.0.0 84 Chapitre 6. Le protocole HTTP et ses tests CHAPITRE 7 Rappel HTML et XML – Définition – Comment sont composées les pages internet ? – Rappel sur les bases HTML et XML – Savoir – Les nœuds – Les éléments – Les attributs – Le texte – Distinction entre HTML et XML – Le prologue – Le doctype – Les DTD et schémas – Les documents bien formés – Les documents validés – Les commentaires – Les espaces de noms – Exercices – Ressources 7.1 Définition 7.1.1 Comment sont composées les pages internet ? Les pages internet sont de simples documents texte dont certains mots sont interprétés par le navigateur pour insérer des images, mettre en forme le document comme par exemple créer des titres, proposer des liens, exécuter des scripts qui sont des suites d’instructions indiquant au navigateur ce qu’il doit faire, etc. Lorsque on utilise un logiciel produisant du HTML, il ne fait qu’écrire un fichier texte mélangeant notre contenu avec les éléments du HTML. 7.1.2 Rappel sur les bases HTML et XML Lorsqu’en 1989 Tim Berners-Lee créait le protocole HTTP, il créait aussi HTML (Hypertext Markup Language) qui est le format de données transmis par HTTP, il met aussi au point le mécanisme d’URL qui permet de localiser une ressource sur le web. Le format HTML est un format texte issu de SGML, dont la volonté est de séparer le fond de la forme. 85 Plone pour les intégrateurs, Version 1.0.0 Il permet de mettre en évidence les parties importantes d’un texte en les balisant. Pour cela, on encadre le texte avec un élément HTML qui se présente sous la forme <element attribut1="valeur1" attribut2="valeur2">texte</element>. Les différentes versions de HTML spécifient les noms des éléments et des attributs possibles. HTML évolue continuellement, nous sommes à la version 4.1 et la version 5 est à l’étude. Dès ses origines le langage de balise évolue par l’ajout des différents éditeurs de navigateur web. Jusqu’en 1992, il n’existe aucune spécification du langage, et par convention on parle de HTML 1.0 pour désigner ce qui se faisait à l’époque. En 1993, Mosaic apporte les formulaires rendant ainsi le web interactif ainsi que l’affichage des images. En 1995 sort la version 2.0 de HTML, proposée par le W3C World Wide Web Consortium qui vient d’être créé. En 1997 sort la version 3 puis la version 4.0 qui décrit le mécanisme des feuilles de styles CSS (Cascading Style Sheets). La version 4 est devenue la version la plus utilisée sur le web, les dernières corrections datent de 1999 avec la version 4.1. XML a fait son apparition en 1998 avec la version 1.0, afin de rendre plus cohérent l’usage des éléments, il demande que chaque balise ouverte soit fermée, que les attributs aient toujours une valeur entre guillemets. En 2004 sort la version 1.1. La version 2.0 de XHTML qui devait apporter XForms et XFrames a finalement été abandonnée en décembre 2009. Et HTML 5 a du coup été relancé. La grande force de XML est la possibilité d’enrichir facilement l’ensemble des balises existantes sans avoir à modifier les recommandations du w3c, contrairement à HTML. 7.2 Savoir Nous traiterons en priorité XHTML car c’est le format utilisé par Plone. 7.2.1 Les nœuds On peut représenter un texte XML ou HTML par une arborescence de nœuds contenant du texte et/ou d’autres nœuds, cela reviendrait à dire qu’un nœud est l’équivalent d’un répertoire ou d’un fichier en faisant le parallèle avec une arborescence de fichiers. 7.2.2 Les éléments Chaque nœud ayant un nom est appelée un élément, il est composé d’une balise ouvrante commençant par un chevron ouvert < puis d’un nom ne contenant que des lettres, des chiffres ou des tirets bas, de zéro à plusieurs attributs séparés par des espaces, enfin la balise finie par un chevron fermé >. Exemple : <un_element> bla bla <un_sous_element /> <un_autre_sous_element> encore du bla bla </un_autre_sous_element> <un_element_avec_un_attribut un_attribut="sa valeur"/> </un_element> Un élément doit obligatoirement être fermé soit par une balise portant le même nom mais précédé par / et ne pouvant contenir aucun attribut, soit par / avant le chevron de fermeture. 86 Chapitre 7. Rappel HTML et XML Plone pour les intégrateurs, Version 1.0.0 7.2.3 Les attributs Un attribut est un couple nom-valeur écrit à l’intérieur de la déclaration d’une balise, qui permet de préciser l’élément qu’il qualifie. En XML la valeur est entre guillemets et peut être vide “” mais ne peux être nulle. 7.2.4 Le texte Le texte dans XHTML est contenu par un élément et est en unicode par défaut, le jeu de caractère est celui de l’UTF-8 ce qui permet de traiter toutes les langues. 7.2.5 Distinction entre HTML et XML HTML peut être vu comme un XML permissif car il autorise que les balises ne soient pas fermées, qu’une balise ouvrante soit fermée par une balise dont la casse du nom soit différente de celle ouvrante, que les éléments de style soient fortement mélangés au contenu. XHTML doit respecter la forme suivante : <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-s <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr"> <head> <title>Exemple XHTML 1.0 strict</title> </head> <body> <ul> <li>Tous les éléments doivent être explicitement balisés.</li> <li>Les balises fermantes ne sont pas optionnelles.</li> <li>Les noms d’éléments et d’attributs <em class="important">doivent</em> être en minuscules.</ <li>Tous les attributs doivent avoir une valeur explicite <input type="checkbox" checked="check <li>Les guillemets sont <em class="important">toujours</em> obligatoires autour des valeurs d’a <li>Les balises auto-fermantes se terminent tous par un espace et un slash comme pour la balise ou un retour à la ligne : <br /></li> </ul> </body> </html> 7.2.6 Le prologue Le prologue est la première ligne d’un document HTML ou XHTML et a la forme <?xml version="1.0"?>. Il permet de savoir si l’on a affaire à un document XML et si c’est le cas, de connaître la version applicable. 7.2.7 Le doctype Le doctype est généralement défini tout de suite après le prologue et permet de savoir quelle DTD les éléments non qualifiés doivent suivre. Cas du HTML : <!DOCTYPE html PUBLIC "-//IETF//DTD HTML 2.0//EN"> Cas du XTHML 1.0 strict : <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> Cas du XHTML 1.0 Transitional : 7.2. Savoir 87 Plone pour les intégrateurs, Version 1.0.0 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> Cas du XHTML 1.1 : <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> 7.2.8 Les DTD et schémas Que ce soit HTML ou XHTML, chacun des deux langages est défini par une DTD (Document Type Définition) qui est une sorte de grammaire expliquant les combinaisons d’éléments et d’attributs possibles. XML permet d’utiliser des schémas à la place des DTD, qui ont l’avantage d’être en XML et de mieux détailler les éléments et attributs. Il y a ainsi moins d’interprétations possibles des spécifications. 7.2.9 Les documents bien formés On dit d’un document XML qu’il est bien formé si chaque balise ouvrante a une balise fermante, si les attributs ont bien tous des valeurs au moins vide. 7.2.10 Les documents validés Un document XML est validé lorsqu’il respecte l’organisation des éléments prévue par une DTD ou un schéma. La validation identifie la ou les DTD et Schémas à appliquer au document, va les chercher et vérifie que toutes les règles de construction décrite dedans sont respectées. 7.2.11 Les commentaires Les commentaires sont délimités par <!-- et -->. 7.2.12 Les espaces de noms Pour permettre l’extension, XML a introduit la notion d’espace de nom, ainsi il est possible dans un élément de définir un espace de nom liant un préfixe d’élément à un schéma ou une DTD et donc de mélanger des éléments de natures différentes. Le format est xmlns:NomPrefixe="URL". Exemple : <ex:exemple xmlns:formation="http://www.ecreall.com/formations/xml" xmlns="http://www.w3.org/1999/xhtml" xmlns:ex="http://example.org"> <formation:plone version="3 4"> <formation:python> <p>Python c’est bien</p> <a href="http://www.afpy.org">Association Francophone Python</p> </formation:python> </formation:plone> </ex:exemple> 88 Chapitre 7. Rappel HTML et XML Plone pour les intégrateurs, Version 1.0.0 7.3 Exercices Écriture d’une page HTML et d’un document XML. 7.4 Ressources – – – – – – – Hypertexte HTML XHTML XML URL W3C Feuilles de styles 7.3. Exercices 89 Plone pour les intégrateurs, Version 1.0.0 90 Chapitre 7. Rappel HTML et XML CHAPITRE 8 Concept de Python eggs Note : Ce chapitre utilise un dépôt subversion créé dans le chapitre La gestion des sources avec subversion – – – – – – – – Définition Savoir Installation de Python et Distribute Packaging Python – Installation d’un egg – Télécharger un package sans l’installer – Création d’un environnement isolé avec virtualenv – Suppression d’un egg – Methode “originelle” pour installer un package – Installation de virtualenvwrapper Passons au développement – Installation de la commande paster – Création de votre premier egg – Déclaration des dépendances – Egg en mode développement – Le hello world que tout le monde attend – Les espaces de nom ou namespaces L’API pkg_resources Les entry points – groupe console_scripts Mise en place d’un Pypi privé avec PloneSoftwareCenter – Installation de collective.dist pour Python 2.4 et 2.5 – Configuration des serveurs – Enregistrement et upload – Broken release 8.1 Définition Les Python eggs sont des packages distribuables. La notion de egg doit être bien comprise pour comprendre la suite. C’est la base des outils d’aujourd’hui comme zc.buildout qui sert au déploiement d’un site Plone et paster pour la génération de squelette de projet. 91 Plone pour les intégrateurs, Version 1.0.0 8.2 Savoir – – – – – – distribute/setuptools environnement isolé avec virtualenv création d’un egg avec paster metadata (description au format ReST, dépendances, extras) installation via easy_install entry points et plugins (paster utilise ce mécanisme de plugins) 8.3 Installation de Python et Distribute Dans ce qui suit, je considère que vous êtes sous Ubuntu ou Debian et que vous souhaitez travailler sur Plone 4 qui requiert Python 2.6. Si vous voulez installer un Plone 3, il vous faudra Python 2.4, dans ce cas, remplacez 2.6 par 2.4 dans les instructions suivantes. Installez les packages suivants : $ sudo apt-get install build-essential python2.6 python2.6-dev Le meta-paquet build-essential vous installera tout ce qu’il faut (compilateur gcc, make, etc.) pour compiler certains modules Python. Si par la suite vous avez une erreur disant que le fichier Python.h ne peut être trouvé, c’est très probablement que vous n’avez pas le paquet python2.6-dev d’installé. Sous Ubuntu, installez le gestionnaire de paquets distribute comme ceci : $ wget http://python-distribute.org/distribute_setup.py $ sudo python distribute_setup.py Si vous voulez être sûr de la version de Python que vous utilisez, vous pouvez vérifier la version comme ceci : $ python --version Python 2.7.3 Et savoir exactement où il se trouve comme ceci : $ which python /usr/bin/python Ce python est en fait un lien symbolique ici vers python2.7, comme on peut le voir : $ ls -l /usr/bin/python lrwxrwxrwx 1 root root 9 juil. 9 16:41 /usr/bin/python -> python2.7 À tout moment, vous pouvez exécuter ces commandes pour savoir quel Python vous utilisez réellement. Après l’installation de distribute, la commande easy_install est disponible pour installer de nouveaux eggs pour Python 2.7. 8.4 Packaging Python Un package Python peut être distribué sous la forme d’une simple archive (zip ou tar.gz). Python inclut la librairie distutils afin de réaliser ces distributions source, mais celle-ci ne gère pas les dépendances entre packages. distribute est un fork de setuptools, une extension à distutils qui ajoute de nombreuses fonctionnalités : – dépendances (metadata install_requires) – distribution binaire, egg – entry points 92 Chapitre 8. Concept de Python eggs Plone pour les intégrateurs, Version 1.0.0 Le package distribute fournit la commande easy_intall qui permet d’installer un package donné : $ easy_install zope.interface Il y a également pip qui lui propose un moyen alternatif à easy_install pour installer un package. Tarek Ziadé et d’autres personnes travaillent sur l’amélioration de la gestion des packages Python avec le nouveau package distutils2 qui remplacera distutils et distribute. – implémentation d’une fonctionnalité de désinstallation d’un package – ajout du metadata install_requires (entre autres) pour décrire les dépendances, mais la gestion des dépendances se fera toujours avec une commande tierce. Vous pouvez lire le billet de Tarek et les PEPs associés si vous êtes intéressé sur le sujet. 8.4.1 Installation d’un egg La communauté Python possède un dépôt central où sont stockés tous les packages Python, c’est le Pypi (Python Package Index), connu autrefois sous le nom de Cheese Shop. Son adresse : http ://pypi.python.org/pypi Lorsque vous installez un package Python via easy_install, c’est sur cet index que le package est recherché. En effet l’index par défaut est l’URL suivante : http ://pypi.python.org/simple Exécutez easy_install Fabric, voici ce qui est exactement fait : – connexion à l’index http ://pypi.python.org/simple – recherche de Fabric dans la liste des liens, si un lien est trouvé, il est suivi – nous arrivons donc sur http ://pypi.python.org/simple/Fabric/ Cette page contient une liste d’urls où l’on peut télécharger directement l’egg, mais également toutes les urls contenues dans la description longue du egg. – la liste fournie sur cette page est ensuite filtrée de la manière suivante : – on donne priorité au egg binaire (bdist) qu’à la distribution source (sdist) – on garde les packages liés à l’OS, donc si on est sous Windows, les eggs ayant win32 sont gardés – seul les eggs utilisant la version de Python qu’on est en train d’utiliser sont gardés – si aucun egg binaire n’est trouvé, alors on recherche une distribution source (tar.gz ou zip) – il se peut qu’il n’y ait aucun lien direct vers un egg sur cette page, mais un lien vers une ou plusieurs urls où l’on peut les télécharger (liens contenus dans long_description ou via l’option download_url précisé lors de la création du egg). Dans ce cas-là, les liens sont suivis pour aller chercher une liste des versions. Si le package n’a pas été trouvé sur l’index, alors on entame une nouvelle recherche, cette fois parmi tous les find-links (éventuellement filtré par l’option -H/--allow-hosts) : $ easy_install --find-links http://pkg.example.com/packages/ monpackage Vous pouvez par exemple autoriser seulement les connexions vers votre intranet et pypi : $ easy_install -H *.myintranet.example.com,*.python.org zope.interface L’option -H/--allow-hosts permet aussi par exemple d’installer un package sans le réseau, en interdissant toutes les URLs et en spécifiant un dossier somedir où aller chercher le package SomePackage : $ easy_install -H None -f somedir SomePackage Au lieu de préciser l’option en ligne de commande, vous pouvez le mettre dans le fichier de configuration ~/.pydistutils.cfg : [easy_install] allow_hosts = *.myintranet.example.com Dans ce cas, seul les packages téléchargeables sur myintranet.example.com pourront être installés. Il est possible de changer l’index par défaut par lequel les eggs sont recherchés via l’option -i/--index-url. Pypi possède des miroirs Voir aussi le projet pour créer et/ou utiliser des miroirs de pypi. 8.4. Packaging Python 93 Plone pour les intégrateurs, Version 1.0.0 Si l’on veut utiliser un miroir ou un index privé par exemple. Nous traiterons le cas d’un index privé avec le produit PloneSoftwareCenter par la suite. 8.4.2 Télécharger un package sans l’installer Il est possible de télécharger le code source (sdist) d’un package sans pour autant l’installer : $ easy_install -b . -e zope.interface Exécutez easy_install -h pour connaitre la signification des options. En savoir plus : Documentation EasyInstall 8.4.3 Création d’un environnement isolé avec virtualenv Il est fréquent de vouloir tester plusieurs versions d’un framework. Admettons que vous ayez zope 3.4 installé globalement, comment pouvez-vous tester zope 3.5 sans que votre installation de zope 3.4 interfère ? La solution est de créer un environnement isolé avec virtualenv. Lisez le tutoriel virtualenv sur grok.zope.org pour savoir comment l’installer et l’utiliser. Revenez ici lorsque c’est fait. Si ce n’est déjà fait, installez virtualenv avec Python 2.4 : $ easy_install-2.4 virtualenv Bien, vous êtes revenu. Maintenant expliquons comment la magie opère. Dans Python, vous avez dans sys.path la liste des chemins dans lesquels on peut trouver des packages Python : $ which python2.4 /usr/bin/python2.4 $ python2.4 >>> import sys >>> sys.path [’’, ’/usr/lib/python2.4’, ’/usr/lib/python2.4/plat-linux2’, ’/usr/lib/python2.4/lib-tk’, ’/usr/lib/python2.4/lib-dynload’, ’/usr/local/lib/python2.4/site-packages’, ’/usr/lib/python2.4/site-packages’, ’/usr/lib/python2.4/site-packages/Numeric’, ’/usr/lib/python2.4/site-packages/PIL’, ’/usr/lib/python2.4/site-packages/gst-0.10’, ’/var/lib/python-support/python2.4’, ’/usr/lib/python2.4/site-packages/gtk-2.0’, ’/var/lib/python-support/python2.4/gtk-2.0’] Créons un environnement nommé myenv : $ virtualenv myenv --distribute Ce que fait cette commande peut se résumer plus ou moins à ces commandes : $ mkdir -p myenv/bin myenv/lib/python2.4/site-packages $ cp /usr/bin/python2.4 myenv/bin/python $ cp /usr/bin/python2.4 myenv/bin/python2.4 94 Chapitre 8. Concept de Python eggs Plone pour les intégrateurs, Version 1.0.0 création de liens symboliques vers les modules de la librairies standard installation de distribute (ou setuptools à défaut du paramètre --distribute) dans cet environnement, ce qui génère les commandes command :bin/easy_install et bin/easy_install-2.4 (c’est le même exécutable) et la création d’un script bin/activate. Notez que python (sans suffixe) est la version 2.5 sous Ubuntu 8.04 et 8.10 : $ which python /usr/bin/python $ python -V Python 2.5.2 Entrons dans le dossier et activons l’environnement : $ cd myenv/ $ source bin/activate Le prompt indique que votre environnement est actif. Jetez un œil au source du fichier bin/activate, il n’y a rien de magique là dedans, il change seulement la variable d’environnement PATH pour y inclure au début le dossier myenv/bin. La partie essentielle de ce script est : $ export PATH="/home/vincentfretin/myenv/bin:$PATH" Cela a son importance, précédement python était le binaire /usr/bin/python qui est la version 2.5 de Python sous Ubuntu 8.04 et 8.10. Maintenant c’est le python de l’environnement, qui est un Python 2.4 : (myenv)$ which python .../myenv/bin/python (myenv)$ python -V Python 2.4.5 Maintenant regardons le sys.path : (myenv)$ python >>> import sys >>> sys.path [’’, ’/home/vincentfretin/myenv/lib/python2.4/site-packages/setuptools-0.6c11-py2.4.egg’, ’/home/vincentfretin/myenv/lib/python2.4’, ’/home/vincentfretin/myenv/lib/python2.4/plat-linux2’, ’/home/vincentfretin/myenv/lib/python2.4/lib-tk’, ’/home/vincentfretin/myenv/lib/python2.4/lib-dynload’, ’/usr/lib/python2.4’, ’/usr/lib64/python2.4’, ’/usr/lib/python2.4/plat-linux2’, ’/usr/lib/python2.4/lib-tk’, ’/usr/lib64/python2.4/lib-tk’, ’/home/vincentfretin/myenv/lib/python2.4/site-packages’, ’/usr/local/lib/python2.4/site-packages’, ’/usr/lib/python2.4/site-packages’, ’/usr/lib/python2.4/site-packages/Numeric’, ’/usr/lib/python2.4/site-packages/PIL’, ’/usr/lib/python2.4/site-packages/gst-0.10’, ’/var/lib/python-support/python2.4’, ’/usr/lib/python2.4/site-packages/gtk-2.0’, ’/var/lib/python-support/python2.4/gtk-2.0’] Vous voyez que les chemins vers les dossiers globaux sont toujours inclus mais que les premiers sont ceux de notre environnement. En effet vous pouvez utiliser la bibliothèque PIL qui est installé globalement : >>> import PIL Sous Ubuntu 9.04, PIL n’est pas disponible sous Python 2.4. Ici import PIL est seulement utilisé comme exemple d’import d’un package installé globalement. Le package virtualenv a aussi été installé globalement, donc vous pouvez utiliser import virtualenv à la place pour tester. 8.4. Packaging Python 95 Plone pour les intégrateurs, Version 1.0.0 En général vous voulez un environnement isolé des packages extérieurs, c’est le rôle de l’option --no-site-packages de virtualenv. Nous allons recréer l’environnement avec cette option, tout d’abord désactivez l’environnement : (myenv)$ deactivate deactivate est juste une fonction bash créée lorsque vous avez sourcé bin/activate. Supprimez votre environnement et recréez le avec l’option --no-site-packages : $ cd .. $ rm -rf myenv $ virtualenv --no-site-packages myenv Maintenant voyez par vous même la différence : $ cd myenv/ $ . bin/activate (myenv)$ python >>> import sys >>> sys.path [’’, ’/home/vincentfretin/myenv/lib/python2.4/site-packages/setuptools-0.6c9-py2.4.egg’, ’/home/vincentfretin/myenv/lib/python2.4’, ’/home/vincentfretin/myenv/lib/python2.4/plat-linux2’, ’/home/vincentfretin/myenv/lib/python2.4/lib-tk’, ’/home/vincentfretin/myenv/lib/python2.4/lib-dynload’, ’/usr/lib/python2.4’, ’/usr/lib64/python2.4’, ’/usr/lib/python2.4/plat-linux2’, ’/usr/lib/python2.4/lib-tk’, ’/usr/lib64/python2.4/lib-tk’, ’/home/vincentfretin/myenv/lib/python2.4/site-packages’] Le dossier PIL n’est plus là, comme l’atteste l’exception ImportError : >>> import PIL Traceback (most recent call last): File "<stdin>", line 1, in ? ImportError: No module named PIL Vous pouvez installer PIL dans cet environnement comme ceci : easy_install --find-links http://dist.plone.org/thirdparty/ PIL (L’archive PIL de pypi n’est pas easy installable.) Ici, nous avons installé virtualenv avec easy_install-2.4, comment créer un environnement avec une autre version de Python ? virtualenv possède une option -p pour préciser un exécutable python alternatif : $ virtualenv -p /usr/bin/python --no-site-packages --distribute myenv25 $ cd myenv25 $ . bin/activate Nous allons utiliser ce nouvel environnement pour installer Fabric qui nécessite Python >= 2.5. Vérifiez que vous avez la package Ubuntu python2.5-dev ou python2.6-dev d’installé, il est nécessaire pour compiler pycrypto, une dépendance de Fabric. Fabric est un outil pour scripter les deploiements. Nous n’allons pas utiliser easy_install Fabric ici, mais récupérer l’archive pour l’installer. Nous téléchargons l’archive avec wget et exécutons ensuite easy_install avec l’archive en paramètre pour installer le package : (myenv25)$ wget http://git.fabfile.org/cgit.cgi/fabric/snapshot/fabric-0.9a3.tar.gz (myenv25)$ easy_install fabric-0.9a3.tar.gz 96 Chapitre 8. Concept de Python eggs Plone pour les intégrateurs, Version 1.0.0 Nous aurions très bien pu faire directement easy_install http://git.fabfile.org/cgit.cgi/fabric/snapshot Vous pouvez remarquer que Fabric et ses dépendances ont été installées en eggs zippés : (myenv25)$ total 1064 -rw-r--r--rw-r--r--rw-r--r--rw-r--r--rw-r--r--rw-r--r-- ls -l lib/python2.5/site-packages/ 1 1 1 1 1 1 vincentfretin vincentfretin vincentfretin vincentfretin vincentfretin vincentfretin vincentfretin 306 2009-05-25 11:35 easy-install.pth vincentfretin 71581 2009-05-25 11:35 Fabric-0.9a3-py2.5.egg vincentfretin 296831 2009-05-25 11:35 paramiko-1.7.4-py2.5.egg vincentfretin 358122 2009-05-25 11:35 pycrypto-2.0.1-py2.5-linux-x86_64 vincentfretin 328025 2009-05-25 11:34 distribute-0.6.8-py2.5.egg vincentfretin 29 2009-05-25 11:34 setuptools.pth Tous les eggs ne sont pas installés zippés. C’est le mainteneur du package qui décide si son egg est “zip safe” ou non. Un package n’est par exemple pas zip safe s’il utilise la variable spéciale __file__ dans son code. Vous vous demandez à quoi servent ces fichiers setuptools.pth et easy-install.pth n’est-ce pas ? Un petit rappel Python va vous faire du bien alors. Que contient ces fichiers xyz.pth (pour path) ? Comme son extension le suggère, ces fichiers contiennent une liste de chemins où l’on peut trouver des packages : (myenv25)$ cat lib/python2.5/site-packages/setuptools.pth ./distribute-0.6.8-py2.5.egg (myenv25)$ cat lib/python2.5/site-packages/easy-install.pth import sys; sys.__plen = len(sys.path) ./distribute-0.6.8-py2.5.egg ./Fabric-0.9a3-py2.5.egg ./paramiko-1.7.4-py2.5.egg ./pycrypto-2.0.1-py2.5-linux-x86_64.egg import sys; new=sys.path[sys.__plen:]; del sys.path[sys.__plen:]; p=getattr(sys,’__egginsert’,0); Comme vous le voyez, la commande easy_install maintient dans le fichier easy-install.pth une liste des eggs qu’elle a installés. Au démarrage de Python, tous les packages python (dans le sens d’un dossier contenant un fichier __init__.py) se trouvant dans lib/python2.5/site-packages/ sont ajoutés au sys.path. Ça c’est la première étape, et dans notre cas, il n’y a aucun package. La deuxième étape recherche des fichiers xyz.pth, les lit et inclut les chemins inclus si un package s’y trouve. La première et dernière ligne du fichier easy-install.pth sont utilisés pour ajouter les eggs au début de sys.path pour prendre la précédence aux packages éventuellement installés. 8.4.4 Suppression d’un egg Il n’y a pas de commande uninstall pour désinstaller un egg. Une implémentation est en cours dans distutils2. Pour le moment, il faut donc désinstaller manuellement et là il faut savoir ce que l’on fait. La première chose qui vient à l’esprit est de supprimer le egg du site-packages. C’est très bien mais cela ne suffit pas comme nous allons le voir. Nous allons désinstaller Fabric pour l’installer d’une autre manière. Nous allons profiter de cette désintallation pour revenir sur le fichier xyz.pth. Notez bien que nous avons dans le sys.path setuptools, Fabric et paramiko, dans le même ordre que listé dans easy-install.pth : (myenv25)vincentfretin@lelouch:~/myenv25$ python Python 2.5.2 (r252:60911, Oct 5 2008, 19:29:17) [GCC 4.3.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. 8.4. Packaging Python 97 Plone pour les intégrateurs, Version 1.0.0 >>> import sys >>> sys.path [’’, ’/home/vincentfretin/myenv25/lib/python2.5/site-packages/setuptools-0.6c11-py2.5.egg’, ’/home/vincentfretin/myenv25/lib/python2.5/site-packages/Fabric-0.9a3-py2.5.egg’, ’/home/vincentfretin/myenv25/lib/python2.5/site-packages/paramiko-1.7.4-py2.5.egg’, ’/home/vincentfretin/myenv25/lib/python2.5/site-packages/pycrypto-2.0.1-py2.5-linux-x86_64.egg’, ’/home/vincentfretin/myenv25/lib/python2.5’, ...] Maintenant supprimons le egg de Fabric : (myenv25)vincentfretin@lelouch:~/myenv25$ rm lib/python2.5/site-packages/Fabric-0.9a3-py2.5.egg Mais nous n’avons pas supprimé l’entrée dans easy-install.pth. Allons nous encore avoir /home/vincentfretin/myenv25/lib/python2.5/site-packages/Fabric-0.9a3-py2.5.egg dans le sys.path ? Voyons voir : (myenv25)vincentfretin@lelouch:~/myenv25$ python Python 2.5.2 (r252:60911, Oct 5 2008, 19:29:17) [GCC 4.3.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> sys.path [’’, ’/home/vincentfretin/myenv25/lib/python2.5/site-packages/setuptools-0.6c9-py2.5.egg’, ’/home/vincentfretin/myenv25/lib/python2.5/site-packages/paramiko-1.7.4-py2.5.egg’, ’/home/vincentfretin/myenv25/lib/python2.5/site-packages/pycrypto-2.0.1-py2.5-linux-x86_64.egg’, ’/home/vincentfretin/myenv25/lib/python2.5’, ...] Et bien non, Python n’a trouvé aucun package Python ./Fabric-0.9a3-py2.5.egg qui n’existe plus, il ne l’a donc pas ajouté dans le sys.path. Pour faire une désintallation propre d’un egg, il faut : – supprimer le egg – supprimer l’entrée dans easy-install.pth – supprimer les éventuels scripts qui ont été générés à l’installation, ici bin/fab. 8.4.5 Methode “originelle” pour installer un package easy_install fait partie du package distribute / setuptools. Si distribute ou setuptools n’est pas disponible dans votre environnement, on peut très bien installer un package en l’extrayant et exécutant la commande python setup.py install : (myenv25)$ tar xvf fabric-0.9a3.tar.gz (myenv25)$ cd fabric-0.9a3/ (myenv25)$ python setup.py install En fait, c’est exactement ce que fait la commande easy_install. 8.4.6 Installation de virtualenvwrapper virtualenvwrapper est un ensemble de fonctions bash pour gérer vos environnements. Pour l’installer : $ sudo easy_install virtualenvwrapper 98 Chapitre 8. Concept de Python eggs Plone pour les intégrateurs, Version 1.0.0 Éditez ensuite votre ~/.bashrc pour sourcer le fichier /usr/local/bin/virtualenvwrapper.sh. Sur Ubuntu, j’ai l’habitude de décommenter dans ~/.bashrc les 3 lignes concernant l’inclusion de ~/.bash_aliases. Je met ensuite dans ce fichier tous les alias et autres variables d’environnement que je veux. Ici nous voulons ces deux lignes : TMPDIR=/tmp source /usr/local/bin/virtualenvwrapper.sh virtualenvwrapper utilise le dossier ~/.virtualenvs par défaut pour créer et chercher les environnements : $ mkdir ~/.virtualenvs Démarrez un nouveau terminal, vous avez maintenant à disposition les commandes suivantes : – workon : affiche la liste des environnements contenu dans ~/.virtualenvs – workon myenv : active l’environnement myenv – mkvirtualenv myenv : crée l’environnement myenv avec la commande virtualenv et l’active Tous les paramètres données à mkvirtualenv serons donnés à la commande command :virtualenv. – rmvirtualenv myenv : supprime l’environnement myenv – cdvirtualenv : va dans le dossier de l’environnement actif – cdsitepackages : va dans le dossier site-packages de l’environnement actif – lssitepackages : liste les eggs installés de l’environnement actif – cpvirtualenv : copie un environnement existant Donc avant pour activer un environnement, vous faisiez : $ cd myenv $ . bin/activate Maintenant vous n’avez qu’à taper workon myenv où que vous soyez. 8.5 Passons au développement 8.5.1 Installation de la commande paster Dans ce qui suit je travaille dans mon environnement myenv, je n’indiquerai plus le “(myenv)” dans le prompt. Installez le egg PasteScript. Le egg PasteScript fournit la commande paster avec laquelle on peut créer des squelettes de code. Pour lister les templates disponibles : $ paster create --list-templates Available templates: basic_package: A basic setuptools-enabled package paste_deploy: A web application deployed through paste.deploy Il n’y a pas beaucoup de templates par défaut. Installez le egg ZopeSkel qui fournit divers templates et reexécutez la commande : $ paster create --list-templates Available templates: Available templates: archetype: A Plone project that uses Archetypes content types basic_buildout: A basic buildout skeleton basic_namespace: A basic Python project with a namespace package basic_package: A basic setuptools-enabled package nested_namespace: A basic Python project with a nested namespace (2 dots in name) paste_deploy: A web application deployed through paste.deploy plone_basic: A package for Plone add-ons 8.5. Passons au développement 99 Plone pour les intégrateurs, Version 1.0.0 plone_nested: recipe: zope2_basic: zope2_nested: A A A A package for Plone add-ons with a nested namespace recipe project for zc.buildout Zope project nested-namespace Zope package Ah il y a déjà plus de choix ! Ceux que nous utiliserons par la suite sont basic_namespace, plone_basic, plone_nested. En fait, vous auriez très bien pu installer uniquement ZopeSkel car PasteScript en est une dépendance. 8.5.2 Création de votre premier egg Pour créer un squelette, vous choisissez votre template et exécutez : $ paster create -t nom_de_la_template Créez votre premier egg : $ paster create -t basic_namespace Selected and implied templates: templer.core#basic_namespace A basic Python project with a namespace package Enter project name: foo.bar Variables: egg: foo.bar package: foobar project: foo.bar Expert Mode? (What question mode would you like? (easy/expert/all)?) [’easy’]: Version (Version number for project) [’1.0’]: Description (One-line description of the project) [’’]: Creating template basic_namespace Creating directory ./foo.bar Copying setup.py_tmpl to ./foo.bar/setup.py Recursing into src Creating ./foo.bar/src/ Recursing into +namespace_package+ Creating ./foo.bar/src/foo/ Recursing into +package+ Creating ./foo.bar/src/foo/bar/ Copying __init__.py_tmpl to ./foo.bar/src/foo/bar/__init__.py Copying __init__.py_tmpl to ./foo.bar/src/foo/__init__.py Running /home/cedric/.virtualenvs/myenv/bin/python setup.py egg_info Voyons ce qu’il a généré : $ tree foo.bar foo.bar/ |-- CHANGES.txt |-- CONTRIBUTORS.txt |-- docs | |-- LICENSE.GPL | ‘-- LICENSE.txt |-- README.txt |-- setup.py ‘-- src |-- foo | |-- bar | | ‘-- __init__.py | ‘-- __init__.py ‘-- foo.bar.egg-info |-- dependency_links.txt 100 Chapitre 8. Concept de Python eggs Plone pour les intégrateurs, Version 1.0.0 |-|-|-|-|-|-‘-- entry_points.txt namespace_packages.txt not-zip-safe PKG-INFO requires.txt SOURCES.txt top_level.txt Le dossier foo.bar.egg-info est généré automatiquement avec la commande python setup.py egg_info (dernière commande exécutée par paster). Ce dossier ne sera donc pas ajouté au gestionnaire de version comme nous le verrons plus loin. Le fichier setup.py contient les données que vous avez entrées. 8.5.3 Déclaration des dépendances L’option install_requires dans setup.py permet d’indiquer des dépendances, ici notre egg dépend de setuptools. Les dépendances sont vérifiées à l’installation de l’egg. install_requires est une liste de Requirement. requirement ::= nom_egg [(“>=” | “>” | “<” | “<=” | “==” | ”!=”) version] En savoir plus : Declaring Dependencies (concepts d’extras) L’option entry_points sera expliquée plus loin. 8.5.4 Egg en mode développement Installons tout de suite ce nouvel egg pour pouvoir l’importer. La première chose a laquelle vous pensez est de faire python setup.py install et vous avez raison ! Mais l’inconvénient dans ce cas-là est qu’à chaque fois que vous allez changer quelque chose à votre package, vous devrez reexécuter cette commande. Nous avons une commande develop, qui est bien mieux pour installer un egg tout en le développant. Faites donc ceci : $ cd foo.bar $ python setup.py develop Cette commande, au lieu de copier le dossier dans site-packages, crée un fichier foo.bar.egg-link qui n’est autre finalement qu’un lien symbolique multi-plateforme qui pointe vers le dossier de votre egg en développement. En savoir plus : “Development Mode” 8.5.5 Le hello world que tout le monde attend Allez-y maintenant, ouvrez un python et importez votre package : $ python >>> import foo.bar Et le “hello world” me direz vous ? Bien je vois que vous avez l’habitude. Éditez le fichier foo/__init__.py pour y ajouter : 8.5. Passons au développement 101 Plone pour les intégrateurs, Version 1.0.0 print "Hello" Réimportez votre module : $ python >>> import foo.bar Hello Éditez le fichier foo/bar/__init__.py et ajoutez-y : print "world!" Réimportez le module : $ python >>> import foo.bar Hello world! Et voilà ! En plus l’exemple sert pour faire un petit rappel Python : Face à import foo.bar que fait l’interpréteur Python ? Eh bien il regarde dans le sys.path un package foo (dossier foo avec un fichier __init__.py dedans) ou un module foo (fichier foo.py), dans cet ordre. Ici un package foo est trouvé, et le contenu du fichier __init__.py est exécuté. On passe ensuite à bar, un package ou un module est recherché à l’intérieur du package : mod :foo. Ici un package bar est trouvé, le contenu de son fichier __init__.py est exécuté. 8.5.6 Les espaces de nom ou namespaces À quoi sert le code dans foo/__init__.py ? Très bonne question ! Créez un egg comme précédemment nommé : file :foo.rab (pas très inspiré), et installez le en mode développé. Vous l’avez fait sans regarder le texte au dessus, c’est très bien ! Vous avez usé de la flêche haute, avouez le. C’est encore mieux ! Éditez foo.rab/foo/__init__.py : print "Bonjour" Éditez foo.rab/foo/rab/__init__.py : print "le monde" On y est. Vérifions que foo.bar et foo.rab sont dans notre sys.path et sont bien dans cette ordre : $ python >>> import sys >>> sys.path [..., ’/home/vincentfretin/src/foo.bar’, ’/home/vincentfretin/src/foo.rab’, ...] 102 Chapitre 8. Concept de Python eggs Plone pour les intégrateurs, Version 1.0.0 Comme dit plus haut, Python recherche un package nommé foo, il en trouve un, exécute le contenu de __init__.py et normalement devrait s’arrêter là. Donc cela devrait donner ceci : >>> import foo Hello car foo.bar étant en premier dans le sys.path. Au lieu de ça, qu’avons-nous ? >>> import foo Bonjour Hello Il se peut que vous ayez “Hello Bonjour” comme ordre, c’est assez mystérieux. L’essentiel est que vous ayez les deux. Ensuite : >>> import foo.rab le monde >>> import foo.bar world! Le code de foo.bar/foo/__init__.py indique que : mod :foo est un espace de nom. Et cela change le comportement de l’import. Au lieu de s’arrêter au premier package foo trouvé, la recherche continue et tous les packages foo trouvés sont exécutés. Si foo n’était pas déclaré comme espace de nom dans l’egg foo.bar, alors vous auriez eu ceci : >>> import foo.rab Traceback (most recent call last) File "<stdin>", line 1, in ? ImportError: No module named rab Vous pouvez faire le test en commentant namespace_packages=[’foo’] du setup.py de foo.bar. Il faut réexécuter python setup.py egg_info (la commande egg_info est également exécutée lors d’un install ou d’un develop) pour mettre à jour les metadonnées du egg situées dans le dossier foo.bar.egg-info. Commentez également les lignes dans foo.bar/foo/__init__.py. En temps normal, ne mettez pas de code dans les fichiers __init__.py des packages servant d’espace de nom comme le dit la documentation de setuptools. En savoir plus : Namespace Packages 8.6 L’API pkg_resources setuptools fournit un module pkg_resources avec lequel on peut par exemple récupérer la version d’un egg. Cet API sert à lire les différents fichiers du dossier .egg-info. Exemple pour récupérer la version du egg foo.bar installé : $ python >>> import pkg_resources >>> d = pkg_resources.get_distribution("foo.bar") >>> d.version ’1.0dev’ 8.6. L’API pkg_resources 103 Plone pour les intégrateurs, Version 1.0.0 >>> d.location ’/home/vincentfretin/src/foo.bar’ En savoir plus : Documentation PkgResources 8.7 Les entry points Revenons sur l’option entry_points dans setup.py. Cette option sert à définir des points d’entrées pour le egg. On peut utiliser cette notion pour réaliser des plugins. Reprenons les eggs PasteScript et ZopeSkel. Comment PasteScript a fait pour découvrir les nouveaux templates installés par : mod :ZopeSkel ? ZopeSkel utilise le système templer pour générer ses templates. Templer définit des entry points pour le groupe paste.paster_create_template : $ cdsitepackages $ cat templer.plone-1.0b1-py2.7.egg-info/entry_points.txt # -*- Entry points: -*[paste.paster_create_template] plone_basic = templer.plone:Plone plone_nested = templer.plone:NestedPlone archetype = templer.plone:Archetype où plone_basic est un nom, templer.plone est un module et Plone un callable, ici une classe. et PasteScript lui fait une recherche des eggs déclarant paste.paster_create_template avec l’API pkg_resources : des entry points pour $ python >>> import pkg_resources >>> list(pkg_resources.iter_entry_points(’paste.paster_create_template’)) [..., EntryPoint.parse(’plone_basic = templer.plone:Plone’), EntryPoint.parse(’plone_nested = templer.plone:NestedPlone’), EntryPoint.parse(’archetype = templer.plone:Archetype’), ...] On peut charger le callable d’un entry point, souvent une classe : >>> entry_points = list(pkg_resources.iter_entry_points(’paste.paster_create_template’)) >>> ep = entry_points[4] >>> ep EntryPoint.parse(’plone_basic = templer.plone:Plone’) >>> PloneBasic = ep.load() >>> PloneBasic <class ’templer.plone.plone.Plone’> En savoir plus : Dynamic Discovery of Services and Plugins 8.7.1 groupe console_scripts Le groupe console_scripts est spécial. Il est utilisé lors de l’installation du egg pour générer les scripts dans le dossier bin. Pour générer un script bin/fab, le egg Fabric définit dans son setup.py : 104 Chapitre 8. Concept de Python eggs Plone pour les intégrateurs, Version 1.0.0 entry_points={ ’console_scripts’: [ ’fab = fabric.main:main’, ] }, On peut également l’écrire de la manière suivante directement : entry_points=""" [console_scripts] fab = fabric.main:main """, Dans les deux cas, le fichier entry_points.txt généré sera normalisé comme ceci : [console_scripts] fab = fabric.main:main Concrétement, exécuter la commande fab revient à faire : $ python >>> from fabric.main import main >>> main() En savoir plus : Automatic Script Creation 8.8 Mise en place d’un Pypi privé avec PloneSoftwareCenter Créez une instance Plone avec l’id “site” sur une machine servant de serveur (Installation via l’Unified Installer), nous allons l’appeler devagile, avec la résolution DNS dans /etc/hosts : 10.56.8.47 devagile Il est très facile de transformer une instance Plone en un Pypi pour votre entreprise en installant le produit Products.PloneSoftwareCenter. Créez un site Plone avec comme id site, installez le module et ajoutez un élément Software Center nommé products à la racine du site. L’URL de ce Pypi sera donc http ://devagile :8080/site/products 8.8.1 Installation de collective.dist pour Python 2.4 et 2.5 Si vous utilisez Python 2.4 ou 2.5, il vous faut installer collective.dist qui introduit deux nouvelles commandes mregister et mupload pour pouvoir enregister votre egg sur plusieurs serveurs. Si vous utilisez Python 2.6, remplacez mregister par register, et mupload par upload dans ce qui suit. En effet le support de serveurs multiples n’a été introduit qu’à partir de la version 2.6 de Python. 8.8.2 Configuration des serveurs Il faut tout d’abord configurer votre fichier ~/.pypirc : 8.8. Mise en place d’un Pypi privé avec PloneSoftwareCenter 105 Plone pour les intégrateurs, Version 1.0.0 [distutils] index-servers = pypi mycompany [pypi] username:user password:password [mycompany] repository:http://devagile:8080/site/products username:ploneuser password:password Sous Windows vous ne pouvez pas créer ce fichier .pypirc avec le gestionnaire de fichiers, mais dans un shell, vous pouvez. Dans un shell dos, allez dans C:\Profiles\User, et créez le fichier avec la commande : edit .pypirc 8.8.3 Enregistrement et upload Exécutez ensuite : Avec Python < 2.6 $ python setup.py mregister -r mycompany sdist --formats=zip mupload -r mycompany Avec Python >= 2.6 : $ python setup.py register -r mycompany sdist --formats=zip upload -r mycompany – – – – mregister permet d’enregistrer le egg sur le serveur sdist permet de créer une distribution source mupload transfère sur la distribution source vers le serveur -r mycompany précise d’enregistrer et de transfèrer sur le serveur mycompany (r pour repository dans doute). Si cette option n’est pas précisée, c’est le serveur Pypi d’origine. – --formats=zip, génère une archive au format zip. Par défaut sous Linux, une archive tar.gz est générée, le module tarfile dans Python < 2.6 semble avoir certains problèmes de lecture de ces archives. La commande mregister exécute implicitement la commande egg_info. Cette commande génère entre autres le numéro de version. Le fichier setup.cfg est lu par cette commande, il configure quelques options liées à la génération du numéro de version. Créez un fichier setup.cfg qui contient : $ cat setup.cfg [egg_info] tag_build = dev tag_svn_revision = true La version générée sera donc de la forme “1.0dev”. Pour une release stable, on supprime généralement ce fichier pour que la version soit simplement “1.0”. On peut également laisser le fichier en place et écraser la configuration en ligne de commande comme ceci : $ python setup.py egg_info -RDb "" register -r mycompany sdist --formats=zip upload -r mycompany 106 Chapitre 8. Concept de Python eggs Plone pour les intégrateurs, Version 1.0.0 L’option --formats=zip permet de générer une archive zip au lieu d’une archive tar.gz par défaut sous Linux. Avec python setup.py sdist --help-formats, vous pouvez voir la liste des formats possibles d’archives. Si vous voulez par exemple créer une archive zip et tar.gz, vous pouvez spécifier l’option --formats=zip,gztar. Regardez la signification des options avec : $ python setup.py egg_info -h --tag-build (-b) Specify explicit tag to add to version number --no-svn-revision (-R) Don’t add subversion revision ID [default] --no-date (-D) Don’t include date stamp [default] Nous verrons par la suite comment faire une release en bonne et due forme avec le gestionnaire de version subversion. On peut remplacer sdist par bdist_egg pour générer un egg, une distribution binaire. La convention est de générer un bdist_egg pour chaque version de Python pour la plateforme Windows si le egg contient des librairies C à compiler. Pour les autres OS, la distribution source sera récupérée et les librairies C seront compilées à l’installation. 8.8.4 Broken release Créez un nouvel environnement testenv : $ mkvirtualenv testenv Essayez maintenant d’installer foo.bar 1.0 à partir de votre pypi : $ easy_install -i http://devagile:8080/site/products/simple foo.bar Il y a une erreur à l’installation disant qu’il ne trouve pas le fichier CONTRIBUTORS.txt. La release est cassée car elle ne contient pas le fichier CONTRIBUTORS.txt. Et nous avons de ce fichier pour la long_description. Le dossier docs est également manquant car dans setup.py nous avons package=find_packages, ça recherche seulement les dossiers contenant un fichier __init__.py. docs n’étant pas un package, il n’a pas été inclu dans l’archive. Pour régler le problème, il faut mettre le code source dans un dépôt subversion et grâce à l’option include_package_data=True dans setup.py, tous les fichiers subversionnés seront ajoutés à l’archive. Note : Vous pouvez créer facilement un dépôt subversion comme ceci : svnadmin create Formation Et pour faire un checkout : svn co http://devagile/Formation Donc on va importer notre code dans le dépôt Formation : $ svn import foo.bar/ http://devagile/Formation/foo.bar -m "First import of foo.bar" Attention, le dossier .egg-info a été commité ! Nous allons le supprimer de subversion : 8.8. Mise en place d’un Pypi privé avec PloneSoftwareCenter 107 Plone pour les intégrateurs, Version 1.0.0 $ $ $ $ svn co http://devagile/Formation cd Formation/foo.bar svn rm foo.bar.egg-info dist svn ci -m "Delete egg-info and dist directories" Nous allons donc maintenant faire une nouvelle release de foo.bar, pour cela incrémentez la version dans setup.py, mettez 1.1, éditez le fichier docs/HISTORY.txt pour ajouter une information au changelog, commitez et refaites la release. Nous allons faire pareil pour foo.rab, mais nous allons tout d’abord configurer l’option global-ignores dans ~/.subversion/config pour ignorer le dossier .egg-info lors de l’import. Ouvrez le fichier ~/.subversion/config et configurez global-ignores comme suit : global-ignores = *.o *.lo *.la #*# .*.rej *.rej .*~ *~ .#* .DS_Store *.pyc *.pyo .installed.cfg bi Vous pouvez maintenant importer le code source dans subversion et faire la release. 108 Chapitre 8. Concept de Python eggs CHAPITRE 9 Introduction à zc.buildout Author Vincent Fretin Contributors Copyright (C) 2010 Vincent Fretin <vincentfretin AT gmail.com>. Chacun est autorisé à copier, distribuer et/ou modifier ce document suivant les termes de la licence Paternité-Pas d’Utilisation Commerciale-Partage des Conditions Initiales à l’Identique 2.0 France accessible à http ://creativecommons.org/licenses/by-nc-sa/2.0/fr Le code source présent dans ce document est soumis aux conditions de la « Zope Public License », Version 2.1 (ZPL). THE SOURCE CODE IN THIS DOCUMENT AND THE DOCUMENT ITSELF IS PROVIDED “AS IS” AND ANY AND ALL EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. – – – – – – – – – – – – – – Définition Introduction Organisation d’un buildout Section principale [buildout] Partage du dossier eggs et downloads Pinning des versions Extension buildout.dumppickedversions Option extends – Option extends-cache Recipe collective.recipe.omelette Utilisation de variable Repinning et fusion de section de données Ordre d’installation des parts L’option develop Option index et find-links 9.1 Définition Un buildout est un dossier contenant plusieurs fichiers de configuration permettant de reproduire à l’identique un environnement de développement ou de production. Paster est l’outil qui permet de générer le code squelette pour démarrer. 109 Plone pour les intégrateurs, Version 1.0.0 9.2 Introduction Buildout est un système d’installation permettant d’obtenir le même résultat d’une machine à l’autre. L’installation est reproductible. – Qu’est-ce que zc.buildout ? – Survol de Buildout zc.buildout permet d’avoir un environnement (pas forcément isolé), mais d’une autre manière que virtualenv. Une configuration buildout spécifie un ensemble de parts qui se composent : – d’une recette (recipe) – et/ou de données de configuration 9.3 Organisation d’un buildout Un buildout est organisé de la manière suivante : – buildout.cfg : contient la configuration du buildout – bootstrap.py : script d’amorçage de buildout utilisé la première fois – bin/ : dossier contenant les exécutables éventuellement générés par les parts – src/ : par convention, dossier où sont placés les eggs en développement – parts/ : dossier où sont stockées les données générées des parts si besoin – .installed.cfg : fichier caché mémorisant l’état du buildout – .mr.developer.cfg : fichier caché mémorisant l’état des packages en développement si vous utilisez l’extension mr.developer. – eggs/ : dossier contenant les eggs activés ou non. Peut ne pas exister si on utilise un dossier partagé pour plusieurs buildouts. – develop-eggs/ : dossier contenant les liens vers les eggs en développement – extends-cache/ si vous mettez en cache les fichiers de versions téléchargés. Seuls les fichiers buildout.cfg, bootstrap.py et extends-cache/ ont besoin d’être mis dans une gestionnaire de versions. Nous allons prendre comme exemple le buildout.cfg pour installer archgenxml. Suivez la page d’installation du manuel d’archgenxml2 Créez un dossier archgenxml_buildout/, placez y une copie du fichier bootstrap.py et créez un fichier buildout.cfg avec le contenu suivant : [buildout] parts = archgenxml [archgenxml] recipe = zc.recipe.egg:scripts eggs = archgenxml Note : Les versions de zc.buildout >= 1.5.2 permettent d’avoir un environnement isolé du système, cela est désactivé par défaut pour garder la compatibilité avec les versions antérieures. Pour avoir pleinement cette fonctionnalité, il faut que vous activiez l’option include-site-packages = false et que vous remplaciez zc.recipe.egg par z3c.recipe.scripts. Si vous utilisez d’autres recipes, il faut qu’elles utilisent aussi z3c.recipe.scripts en interne. Regardez dans le changelog de ces recipes, s’il est indiqué que la recipe dépend maintenant d’une version >= 1.5.0, c’est qu’elle a dû être adapté pour utiliser z3c.recipe.scripts. 9.4 Section principale [buildout] La variable parts contient la liste des parts que buildout doit installer. La convention est de mettre une part par ligne, indenté de 4 espaces. Il peut y avoir des lignes vides et des commentaires commencant au début de la ligne. 110 Chapitre 9. Introduction à zc.buildout Plone pour les intégrateurs, Version 1.0.0 Chaque part fournit une variable recipe pour indiquer comment ce part doit être installé, mis à jour et supprimé. Il se peut qu’une section ne fournisse pas de recipe. Elle sert généralement pour des données de configuration que d’autres parts utiliseront. Amorcez le buildout (choisissez bien la version de l’exécutable python) : $ python bootstrap.py -d Downloading http://pypi.python.org/packages/source/d/distribute/distribute-0.6.14.tar.gz ... Creating directory ’/home/vincentfretin/archgenxml_buildout/bin’. Creating directory ’/home/vincentfretin/archgenxml_buildout/parts’. Creating directory ’/home/vincentfretin/archgenxml_buildout/eggs’. Creating directory ’/home/vincentfretin/archgenxml_buildout/develop-eggs’. Generated script ’/home/vincentfretin/archgenxml_buildout/bin/buildout’. $ tree . |-- bin | ‘-- buildout |-- bootstrap.py |-- buildout.cfg |-- develop-eggs |-- eggs | |-- distribute-0.6.28-py2.7.egg | ‘-- zc.buildout-1.5.2-py2.7.egg ‘-- parts ‘-- buildout L’amorçage (ou bootstrapping) installe distribute et zc.buildout. L’amorçage génère le script bin/buildout. Exécutez maintenant : $ bin/buildout Getting distribution for ’zc.recipe.egg’. Got zc.recipe.egg 1.3.2. Installing archgenxml. Getting distribution for ’archgenxml’. Got archgenxml 2.6. ... Generated script ’/home/vincentfretin/archgenxml_buildout/bin/archgenxml’. Generated script ’/home/vincentfretin/archgenxml_buildout/bin/agx_argouml_profile’. Generated script ’/home/vincentfretin/archgenxml_buildout/bin/agx_stereotypes’. Generated script ’/home/vincentfretin/archgenxml_buildout/bin/agx_taggedvalues’. Le egg archgenxml et ses dépendances sont téléchargés et installés et divers scripts sont générés à la fin. C’est la recipe qui dit tout ça. À première vue, l’exécution de buildout pourrait se résumer à cet algorithme : pour chaque part de l’option parts de la section [buildout], appeler la recipe associée au part. Revenons à la ligne recipe = zc.recipe.egg:scripts. zc.recipe.egg est un egg à deux espaces de nom et le scripts après les deux points est un entry point du groupe zc.buildout. Si vous ne spécifiez pas de point d’entrée, un point d’entrée nommé default sera alors recherché dans l’egg. Jetez un œil au setup.py de zc.recipe.egg : entry_points = {’zc.buildout’: [’default = %s:Scripts’ % name, ’script = %s:Scripts’ % name, ’scripts = %s:Scripts’ % name, ’eggs = %s:Eggs’ % name, ’custom = %s:Custom’ % name, ’develop = %s:Develop’ % name, ] }, 9.4. Section principale [buildout] 111 Plone pour les intégrateurs, Version 1.0.0 Dans ce cas, nous serions arrivé au même résultat si nous avions mis l’une de ces lignes : recipe recipe recipe recipe = = = = zc.recipe.egg zc.recipe.egg:default zc.recipe.egg:scripts zc.recipe.egg:script L’entry point scripts pointe vers la classe Scripts du package zc.recipe.egg. Cette classe, comme toute recipe, contient des méthodes install et update. Voir l’API des recettes Le fichier caché .installed.cfg garde la configuration de la dernière exécution de buildout. Lorsqu’une section a été supprimée de la configuration, cette partie sera désinstallée lors de la relance de bin/buildout. Si une section a été mise à jour, cette partie sera réinstallée. Pour les nouvelles sections avec recipe, les parties seront installées. Notre algorithme de tout à l’heure est maintenant : – pour chaque part de l’option parts de la section [buildout] : – installer la recipe du part ; – récupérer l’entry point spécifié (default si non spécifié) depuis la recipe ; – si le part est actuellement installé mais sa configuration a changé, appeler la méthode update() de l’entry point ; – si le part n’a pas encore été installé, appeler la méthode install() de l’entry point ; – si un part existe dans .installed.cfg et n’est plus dans la liste des parts de [buildout], alors le part est désintallé. Jetez un œil sur les scripts générés. Rappel : les scripts bin/archgenxml et bin/agx_* sont générés car le egg archgenxml a des entry points dans le groupe console_scripts. : bin/archgenxml #!/usr/bin/python import sys sys.path[0:0] = [ ’/home/vincentfretin/archgenxml_buildout/eggs/archgenxml-2.6-py2.7.egg’, ... ] import archgenxml.ArchGenXML if __name__ == ’__main__’: archgenxml.ArchGenXML.main() La première ligne est le shebang, la version du python avec laquelle vous avez fait command :python bootstrap.py -d au début. archgenxml et toutes ses dépendances sont ajoutés au début du sys.path. 9.5 Partage du dossier eggs et downloads Lors de l’exécution de buildout, le fichier ~/.buildout/default.cfg est lu, c’est dans ce fichier que nous pouvons mettre des options qui seront partagées par tous nos buildouts. Si le dossier ~/.buildout/ n’existe pas, créez le ainsi que les sous-dossiers : $ mkdir ~/.buildout ~/.buildout/eggs ~/.buildout/downloads \ ~/.buildout/configs Créez le fichier ~/.buildout/default.cfg avec ce contenu : [buildout] eggs-directory = /home/vincentfretin/.buildout/eggs download-cache = /home/vincentfretin/.buildout/downloads #extends-cache = /home/vincentfretin/.buildout/configs 112 Chapitre 9. Introduction à zc.buildout Plone pour les intégrateurs, Version 1.0.0 Remplacez ici bien sûr vincentfretin par votre compte. Vous ne pouvez pas utiliser le caractère ~ ici. À savoir que les valeurs par défaut de ces variables sont : eggs-directory = ${buildout:directory}/eggs download-cache = pas précisé, on ne garde pas les archives par défaut extends-cache = pas de cache par défaut ${buildout:directory} étant le dossier du buildout. C’est pour cela que le dossier eggs était créé dans le buildout. Vous pouvez supprimer le dossier eggs de votre buildout, le réamorcer et reexécuter bin/buildout 9.6 Pinning des versions À chaque fois que vous exécutez bin/buildout, une requête est faite au serveur central pour savoir si nous avons la dernière version du egg. C’est le comportement par défaut. En effet nous avons l’option newest = true dans la section [buildout] par défaut. Vous pouvez faire bin/buildout -N pour ne pas vérifier les mises à jour. Si vous aviez newest = false dans votre buildout, la commande bin/buildout -n la remettrait à true pour l’exécution. Le problème est que votre buildout n’est pas reproductible à l’identique. Pour qu’il soit reproductible à l’identique il faudrait que votre buildout précise quelles versions des eggs doivent être installées. C’est là qu’intervient l’option versions de la section [buildout], vous spécifiez dans quelle section vous avez les informations sur les versions. La convention est de l’appeler également versions. Pour geler (verbe “to pin” en anglais, “pinned” au participe passé) archgenxml, modifiez votre buildout de cette manière : [buildout] versions = versions parts = archgenxml [versions] archgenxml = 2.6 # ... [archgenxml] recipe = zc.recipe.egg:scripts eggs = archgenxml Mais cela ne suffit pas pour que le buildout soit reproductible car nous n’avons pas gelé les dépendances d’archgenxml. 9.7 Extension buildout.dumppickedversions zc.buildout peut être étendu avec des extensions. Il y en a une particulièrement intéressante qui va vous sortir la liste des eggs qui ne sont pas gelés avec leur version. Une extension s’ajoute avec l’option extensions de la section [buildout] Ajoutez donc l’extension buildout.dumppickedversions à votre fichier buildout.cfg : [buildout] extensions = buildout.dumppickedversions # ... 9.6. Pinning des versions 113 Plone pour les intégrateurs, Version 1.0.0 Relancez bin/buildout et à la fin de l’exécution vous verrez apparaitre la liste des versions à geler. Ajoutez-les tous à votre section versions, et reexécutez bin/buildout, il ne devrait plus avoir de versions. Il existe aussi une option allow-picked-versions = false disponible dans le cœur de zc.buildout qui permet de stopper le buildout si un egg n’est pas gelé. Cette option et l’extension buildout.dumppickedversions sont mutuellement exclusives. Attention : Cette extension n’est plus compatible avec buildout 2. La fonctionnalité a été intégré dans le cœur. Il suffit de préciser l’option show-picked-version = true à la place de extensions = buildout.dumppickedversions. 9.8 Option extends Il est possible d’étendre le fichier buildout.cfg. Vous verrez souvent un fichier deployment.cfg ou development.cfg qui étend le fichier buildout.cfg de base. Créez un fichier development.cfg : [buildout] extends = buildout.cfg parts = omelette [omelette] recipe = collective.recipe.omelette eggs = archgenxml L’option extends dit de lire le fichier buildout.cfg, et les options que l’on spécifiera par la suite seront écrasées. Par défaut, buildout cherche un fichier buildout.cfg, l’option -c permet d’indiquer un fichier alternatif. Relancez la machinerie buildout avec ce fichier : $ bin/buildout -c development.cfg Uninstalling archgenxml. Installing omelette. Oh que s’est-il passé ? Vous avez écrasé l’option parts, il n’y a donc plus que le part omelette à installer. Vous vouliez garder aussi le part archgenxml, rectifiez ça en transformant le = par +=, ce qui donne parts += omelette. Toutes les options supportant une liste fonctionnent ainsi (parts, eggs, develop). Relancez buildout. Là les deux parts sont bien installées. Remarque imaginez toujours que vous avez implicitement extends = ~/.buildout/default.cfg dans votre buildout.cfg de base, à partir duquel vous étendez d’autres configurations, ici c’est le fichier buildout.cfg. Vous pouvez récupérer une version mis à plat de la configuration avec la commande suivante : $ bin/buildout -c development.cfg annotate ... [buildout] parts= archgenxml omelette /home/vincentfretin/archgenxml_buildout/buildout.cfg 114 Chapitre 9. Introduction à zc.buildout Plone pour les intégrateurs, Version 1.0.0 += /home/vincentfretin/archgenxml_buildout/development.cfg ... Vous voyez bien ici que l’option parts a été mis à plat, c’est la concaténation de l’option trouvée dans buildout.cfg et de development.cfg. 9.8.1 Option extends-cache L’option extends-cache disponible depuis la version 1.4.0 de zc.buildout permet de mettre en cache les fichiers référencés dans l’option extends. Prenons l’exemple suivant : extends = http://dist.plone.org/release/4.2/versions.cfg Le fichier versions.cfg sera mis en cache dans le dossier ~/.buildout/configs/, le fichier créé étant la somme md5 de l’url. Une fois mis en cache, il est possible de relancer le buildout en mode hors ligne avec la commande bin/buildout -o. 9.9 Recipe collective.recipe.omelette On ne fait pas d’omelette sans casser des eggs. Cette recipe permet de mettre à plat les eggs : [omelette] recipe = collective.recipe.omelette eggs = archgenxml Cette recipe génère une arborescence dans parts/omelette/ contenant archgenxml et toutes ses dépendances directes ou indirectes : $ tree parts/omelette/ parts/omelette |-- archgenxml -> /home/vincentfretin/.buildout/eggs/archgenxml-2.5-py2.6.egg/archgenxml |-- easy_install.py -> /usr/local/lib/python2.6/dist-packages/distribute-0.6.14-py2.6.egg/easy_ins |-- i18ndude -> /home/vincentfretin/.buildout/eggs/i18ndude-3.2-py2.6.egg/i18ndude |-- pkg_resources.py -> /usr/local/lib/python2.6/dist-packages/distribute-0.6.14-py2.6.egg/pkg_res |-- plone | |-- __init__.py | ‘-- i18n -> /home/vincentfretin/.buildout/eggs/plone.i18n-2.0-py2.6.egg/plone/i18n |-- setuptools -> /usr/local/lib/python2.6/dist-packages/distribute-0.6.14-py2.6.egg/setuptools |-- site.py -> /usr/local/lib/python2.6/dist-packages/distribute-0.6.14-py2.6.egg/site.py |-- stripogram -> /home/vincentfretin/.buildout/eggs/stripogram-1.5-py2.6.egg/stripogram |-- xmiparser -> /home/vincentfretin/.buildout/eggs/xmiparser-1.5-py2.6.egg/xmiparser ‘-- zope |-- __init__.py |-- browser -> /home/vincentfretin/.buildout/eggs/zope.browser-1.3-py2.6.egg/zope/browser |-- component -> /home/vincentfretin/.buildout/eggs/zope.component-3.10.0-py2.6.egg/zope/compo |-- configuration -> /home/vincentfretin/.buildout/eggs/zope.configuration-3.7.2-py2.6.egg/zop |-- contenttype -> /home/vincentfretin/.buildout/eggs/zope.contenttype-3.5.1-py2.6.egg/zope/co |-- documenttemplate -> /home/vincentfretin/.buildout/eggs/zope.documenttemplate-3.4.2-py2.6.e |-- event -> /home/vincentfretin/.buildout/eggs/zope.event-3.5.0_1-py2.6.egg/zope/event |-- exceptions -> /home/vincentfretin/.buildout/eggs/zope.exceptions-3.6.1-py2.6.egg/zope/exce |-- i18n -> /home/vincentfretin/.buildout/eggs/zope.i18n-3.7.4-py2.6.egg/zope/i18n |-- i18nmessageid -> /home/vincentfretin/.buildout/eggs/zope.i18nmessageid-3.5.3-py2.6-linux-x |-- interface -> /home/vincentfretin/.buildout/eggs/zope.interface-3.6.1-py2.6-linux-x86_64.eg |-- location -> /home/vincentfretin/.buildout/eggs/zope.location-3.9.0-py2.6.egg/zope/location |-- proxy -> /home/vincentfretin/.buildout/eggs/zope.proxy-3.6.1-py2.6-linux-x86_64.egg/zope/p |-- publisher -> /home/vincentfretin/.buildout/eggs/zope.publisher-3.12.4-py2.6.egg/zope/publi 9.9. Recipe collective.recipe.omelette 115 Plone pour les intégrateurs, Version 1.0.0 |-|-|-‘-- schema -> /home/vincentfretin/.buildout/eggs/zope.schema-3.7.0-py2.6.egg/zope/schema security -> /home/vincentfretin/.buildout/eggs/zope.security-3.7.4-py2.6-linux-x86_64.egg/ structuredtext -> /home/vincentfretin/.buildout/eggs/zope.structuredtext-3.5.0-py2.6.egg/z tal -> /home/vincentfretin/.buildout/eggs/zope.tal-3.5.2-py2.6.egg/zope/tal 25 directories, 5 files Cela permet d’avoir les packages à plat, ce qui facilite la recherche, exemple : $ find -L parts/omelette -name "interfaces.py" $ grep -r "register" parts/omelette Si vous développez avec Eclipse/Pydev, vous pouvez ajouter le répertoire parts/omelette/ au PYTHONPATH du projet, ceci permet l’exploration du code en mode “hypertexte” (ctrl+clic sur un symbole) et l’auto completion intelligente de fonctionner correctement. 9.10 Utilisation de variable Vous avez écrit “archgenxml” à deux endroits, une fois dans la recipe zc.recipe.egg et une autre fois dans la recipe collective.recipe.omelette. Il est plus intéressant de l’indiquer une seule fois dans une variable et d’utiliser cette variable ensuite dans les recipes. Une convention est de définir une variable eggs dans la section [buildout] et de récupérer cette variable avec ${buildout:eggs}. Voici ce que donnent les deux fichiers une fois reécrits. buildout.cfg [buildout] versions = versions parts = archgenxml eggs = archgenxml [versions] archgenxml = 2.5 distribute = 0.6.14 xmiparser = 1.5 zc.buildout = 1.5.2 zc.recipe.egg = 1.3.2 zope.contenttype = 3.5.1 zope.i18nmessageid = 3.5.3 zope.tal = 3.5.2 Unidecode = 0.04.1 i18ndude = 3.2 ordereddict = 1.1 plone.i18n = 2.0 pytz = 2010l stripogram = 1.5 zope.browser = 1.3 zope.component = 3.10.0 zope.configuration = 3.7.2 zope.documenttemplate = 3.4.2 zope.event = 3.5.0-1 zope.exceptions = 3.6.1 zope.i18n = 3.7.4 zope.interface = 3.6.1 zope.location = 3.9.0 zope.proxy = 3.6.1 zope.publisher = 3.12.4 zope.schema = 3.7.0 116 Chapitre 9. Introduction à zc.buildout Plone pour les intégrateurs, Version 1.0.0 zope.security = 3.7.4 zope.structuredtext = 3.5.0 [archgenxml] recipe = zc.recipe.egg:scripts eggs = ${buildout:eggs} development.cfg [buildout] extends = buildout.cfg parts += omelette [omelette] recipe = collective.recipe.omelette eggs = ${buildout:eggs} Vous pouvez référencer n’importe quelle variable de la section que vous souhaitez avec ${nomdesection:variable}. Vous pouvez référencer une variable de la même section avec juste ${:variable}. 9.11 Repinning et fusion de section de données Vous voyez que la recipe collective.recipe.omelette n’est pas gelé. Faites donc les modifications suivantes dans development.cfg : [buildout] # ... versions = vers [vers] collective.recipe.omelette = 0.9 Relancez buildout. Vous voyez que seul collective.recipe.omelette est gelé maintenant car l’option versions a été écrasée. Renommez vers en versions et relancez le buildout. Tous les eggs sont gélés. En effet la section versions de buildout.cfg et la section versions de development.cfg ont fusionné. En conclusion, nommez toujours versions la section contenant les versions. Mais maintenir deux listes est source d’erreur. Créez un fichier versions.cfg qui contient une section [versions] (pas de section [buildout]), et dites à buildout.cfg d’étendre versions.cfg. Relancez buildout pour voir que tout fonctionne. 9.12 Ordre d’installation des parts L’ordre d’installation des parts n’est pas forcément l’ordre donné dans l’option parts de [buildout]. Et une part peut très bien être installée si elle n’est pas listée dans parts. Modifiez votre buildout.cfg comme ceci : [buildout] # ... parts = zopeskel archgenxml [archgenxml] # ... 9.11. Repinning et fusion de section de données 117 Plone pour les intégrateurs, Version 1.0.0 packages = ZopeSkel [zopeskel] recipe = zc.recipe.egg eggs = ${archgenxml:packages} Dans cet exemple, il n’y aucune raison particulière pour installer une part avant l’autre. C’est juste pour l’exercice. L’ordre d’installation sera [archgenxml], puis [zopeskel]. Si maintenant vous supprimez la part [archgenxml] de parts, elle sera toujours installée car la part [zopeskel] en dépend, faisant référence à une de ses variables. 9.13 L’option develop Note : Cette partie dépend du chapitre Concept de Python eggs. L’option develop permet d’indiquer quels eggs sont en mode développement. Créez un dossier src/ et déplacez y vos deux eggs foo.bar et foo.rab. Ajoutez foo.bar à l’omelette et relancez bin/buildout -c development.cfg. Buildout tente d’aller chercher foo.bar sur Pypi et échoue. Nous allons donc lui dire où le trouver. Ajoutez à la section [buildout] de development.cfg : [buildout] # ... find-links += http://devagile:8080/site/products/simple develop = src/foo.bar Relancez bin/buildout -c development.cfg. Le egg foo.bar est en mode développement : $ ls -l develop-eggs/ total 12 -rw-r--r-- 1 vincentfretin vincentfretin 57 2009-05-26 18:20 foo.bar.egg-link -rw-r--r-- 1 vincentfretin vincentfretin 32 2009-05-26 15:38 setuptools.egg-link Nous pouvons également utiliser un wildcard dans l’option develop. Mettez develop = src/*, du coup les deux eggs foo.bar et foo.rab sont en développement. 9.14 Option index et find-links Note : Cette partie dépend du chapitre Concept de Python eggs. L’option index permet de spécifier un autre index que celui par défaut, par exemple un pypi proxy avec collective.eggproxy. L’option find-links permet d’indiquer des liens supplémentaires où l’on peut trouver les eggs utilisés dans le buildout. Nous allons maintenant installer foo.bar = 1.1, la release qu’il y a sur notre pypi. Supprimez donc l’option develop et dans development.cfg, ajoutez : 118 Chapitre 9. Introduction à zc.buildout Plone pour les intégrateurs, Version 1.0.0 [buildout] # ... find-links += http://devagile:8080/site/products/simple Dans buildout.cfg, ajoutez foo.bar à la liste des eggs : [buildout] # ... eggs = archgenxml foo.bar Enfin, ajoutez foo.bar = 1.1 dans versions.cfg. 9.14. Option index et find-links 119 Plone pour les intégrateurs, Version 1.0.0 120 Chapitre 9. Introduction à zc.buildout CHAPITRE 10 Installation et création d’une instance Plone – Savoir – Installation via l’Unified Installer – Installation via un template buildout – Installation sous Ubuntu/Debian – Installation sur Windows – Installation sous Mac OSX – Exercice Plusieurs types d’installation sont possibles, soit en utilisant un “template” de configuration, soit en utilisant un unified installer. 10.1 Savoir La récupération des archives et leur installation, la création d’un buildout et la compilation de Zope. Plone est disponible en plusieurs versions et selon différents modes. Note à propos des combinaisons de versions de Plone, Python et Zope : – Plone 3.3 utilise Python 2.4, Zope 2.10. – Plone 4 utilise Python 2.6 et Zope 2.12. – Plone 4.1 et 4.2 utilisent Zope 2.13, Python 2.7 ou 2.6 10.1.1 Installation via l’Unified Installer C’est la solution la plus simple. Le unified installer est un paquet qui contient toutes les sources, bibliothèques et outils nécessaires à l’exécution de Plone. Il contient aussi un script d’installation qui permet de configurer Plone. Il contient le mécanisme buildout qui permettra de facilement modifier la configuration de Plone pour ajouter des modules tierces. Pour l’installer, il suffit de récupérer le paquet sur http ://plone.org/products/plone et d’exécuter ou d’extraire le paquet selon sa plateforme. Commandes à exécuter : 121 Plone pour les intégrateurs, Version 1.0.0 $ $ $ $ $ $ wget http://launchpad.net/plone/3.3/3.3.X/+download/Plone-3.3.X-UnifiedInstaller.tgz tar xvzf Plone-3.3rc3-UnifiedInstaller.tgz cd Plone-3.3rc3-UnifiedInstaller ./install.sh --with-python=/usr/bin/python2.4 standalone cd ~/Plone/zinstance bin/plonectl start Le mode standalone crée une seule instance. Vous pouvez remplacer standalone par zeo pour créer deux clients avec un zeoserver. Si vous lancez le script en root, il créera un utilisateur plone et installera Python, Zope et Plone dans /usr/local/Plone. Python ne sera pas compilé si vous utilisez l’option --with-python. Pour plus d’informations, lisez le fichier README.txt dans l’archive et la documentation Installing Plone 3 with the Unified Installer sur plone.org L’inconvénient de cette solution est que les paquets unified installer sont réalisés pour les versions stables ou beta de Plone. Les impatients doivent suivre la procédure d’installation par buildout. 10.1.2 Installation via un template buildout Buildout est un outil qui permet de créer et déployer des configurations de projets Python. Il est possible à partir d’un outil nommé paster de créer un squelette de configuration pour buildout. Cet outil sera aussi détaillé par la suite, il se repose sur un mécanisme de patrons (template) propre à chaque projet. Pour installer une version de Plone donnée (depuis la version 2.5), il suffit donc de créer une configuration pour la version de Plone voulue en utilisant paster puis de compléter cette configuration pour enfin la construire. L’intérêt de cette méthode est de permettre l’installation de version en cours de développement ou en vue d’automatiser le déploiement sur plusieurs serveurs. Installation sous Ubuntu/Debian Installez tout d’abord quelques packages de développement qui seront nécessaires pour compiler PIL (Imaging) et python-libxml2 : $ apt-get install libxml2-dev libjpeg62-dev libfreetype6-dev zlib1g-dev – libxml2-dev pour compiler python-libxml2 – libjpeg62-dev libfreetype6-dev zlib1g-dev pour compiler PIL Dans Ubuntu Jaunty Jackalope 9.04 et suivants, les versions de Python installés par défaut sont 2.5 et 2.6. Et les packages python-imaging et python-libxml2 de la distribution ne sont compilés que pour ces versions. Il n’y a donc plus de support de ces packages pour Python 2.4. C’est pourquoi ces deux bibliothèques seront compilées à partir du buildout. Voir le billet de Maurits van Rees à ce sujet Continuez sur le chapitre Création d’un buildout Plone avec ZopeSkel. Installation sur Windows Cette section est une mise à jour pour Plone 4 et une francisation de http ://plone.org/documentation/kb/usingbuildout-on-windows Beaucoup de données vont être téléchargées vous devez donc avoir une connexion rapide. Vous devez être à l’aise avec Windows et sa console Dos. Nous réaliserons l’installation de Plone 4, mais l’installation de Plone 3 est la même à la différence qu’au lieu d’utiliser Python2.6 vous utiliserez Python2.4 : 122 Chapitre 10. Installation et création d’une instance Plone Plone pour les intégrateurs, Version 1.0.0 Python Installer Python via le msi installer en le téléchargeant depuis le site http ://python.org, sélectionner “install for all users” qui créera le répertoire c:\Python26 par défaut. Changer la variable d’environnement path pour que Windows puisse automatiquement associer la commande python à l’environnement : – Python 2.6. Pour cela ouvrez Le panneau de configuration → Les Propriétés système → Variables d’environnement → Path → Modifier – Ajoutez y en fin ;c:\Python26;c:\Python26\Scripts. – Vérifier que vos modifications sont bien prises en compte en ouvrant une invite de commandes en saisissant python -V qui doit vous afficher la version de Python. Distribute – Télécharger le gestionnaire de paquet Python distribute à l’adresse http ://pythondistribute.org/distribute_setup.py ce qui permettra de récupérer les bibliothèques tierces nécessaire à Plone. – Exécuter le dans l’environnement Python correspondant à votre distribution Plone : c:\Python26\python.exe distribute_setup.py pywin32 – Installer l’extension pywin32 qui permettra d’utiliser les applications Windows dans Python. Elle est disponible à l’adresse http ://sourceforge.net/projects/pywin32/files. Installer la version la plus récente proposée pour Python 2.6. PIL – Installer PIL la bibliothèque de traitement d’image dont a besoin Plone pour retailler les images importées, disponible à l’adresse http ://effbot.org/downloads : http ://effbot.org/downloads/PIL-1.1.7.win32-py2.6.exe Des installeurs pour PIL et votre http ://www.pythonware.com/products/pil/ version de Python sont disponibles ici : Des installeurs pour les bindings Python libxml2 et libxslt pré-compilés sont mis à votre disposition ici : http ://users.skynet.be/sbi/libxml-python/ Subversion Installation de subversion. Subversion est un système de gestion de version qui permet de conserver et de réaliser des différences entre les évolutions d’un programme. La communauté Plone l’utilise pour gérer le code source de Plone. Ainsi, nous récupèrerons les fichiers nécessaires à la configuration du buildout. – Nous allons donc le télécharger et l’installer : http ://subversion.tigris.org/files/documents/15/45953/Setup-Subversion-1.6.2.msi – Puis nous ajoutons à notre variable d’environnement Path le chemin vers subversion : c:\Program Files\Subversion\bin – Vérifier en entrant la commande svn –version dans Invite de commandes que vous avez bien une version 1.6.2 10.1. Savoir 123 Plone pour les intégrateurs, Version 1.0.0 F IGURE 10.1 – Modification du path 124 Chapitre 10. Installation et création d’une instance Plone Plone pour les intégrateurs, Version 1.0.0 MinGW Installation de MinGW. MinGW est un portage du compilateur gcc pour Windows. Nous pourrons ainsi compiler le code C de Zope. – Récupérer le sur http ://sourceforge.net/projects/mingw/files/ – Exécuter – Choisir download and install – Accepter la licence – Prendre la version actuelle – Cocher MinGW base tools et MinGW Make – Installer MinGW dans c:\MinGW et faire suivant – MinGW télécharge les outils nécessaires – Ajouter C:\MinGW\bin au Path – Copier cc1.exe et collect2.exe du répertoire c:\MinGW\libexec\gcc\mingw32\3.4.5 dans C:\MinGW\bin – Vérifier en entrant gcc –version dans l’invite de commande – Vérifier qu’il existe un fichier libpython26.a dans C:\Python26\libs sinon suivez la procédure décrite à http ://www.python.org/doc/2.4.1/inst/tweak-flags.html#SECTION000622000000000000000 – Si vous utilisez Python depuis une installation de Plone, vous devez copier – Plone\Python\PC\pyconfig.h vers Plone\Python\Include Configuration de Distutils pour utiliser MinGW Nous allons créer un fichier de configuration qui permettra à distutils de savoir qu’il doit compiler les fichiers avec MinGW. Enregistrez les lignes suivantes dans C:\Python26\Lib\distutils\distutils.cfg : [build] compiler=mingw32 Installation de paster Paster va nous permettre de créer le squelette de déploiement de notre site Plone. Il sera détaillé dans le chapitre qui lui est consacré. Pour installer Paster il suffit de faire easy_install PasteScript Pour vérifier qu’il a bien été installé nous pouvons afficher les patrons de projets existant par défaut : C:\>paster create --list-templates Available templates: basic_package: A basic setuptools-enabled package paste_deploy: A web application deployed through paste.deploy Qui n’affiche que deux types de patron. Nous allons ajouter les patrons liés aux projets Zope avec la commande easy_install ZopeSkel et vérifier les patrons disponibles : C:\>paster create --list-templates Available templates: archetype: A Plone project that uses Archetypes content types basic_namespace: A basic Python project with a namespace package basic_package: A basic setuptools-enabled package basic_zope: A Zope project kss_plugin: A project for a KSS plugin nested_namespace: A basic Python project with a nested namespace (2 dots in name) 10.1. Savoir 125 Plone pour les intégrateurs, Version 1.0.0 paste_deploy: plone: plone2.5_buildout: plone2.5_theme: plone2_theme: plone3_buildout: plone3_portlet: plone3_theme: plone_app: dots in name) plone_hosting: plone_pas: recipe: silva_buildout: A A A A A A A A A web application deployed through paste.deploy project for Plone products buildout for Plone 2.5 projects theme for Plone 2.5 theme for Plone 2.1 buildout for Plone 3 installation Plone 3 portlet theme for Plone 3 project for Plone products with a nested namespace (2 Plone hosting: buildout with ZEO and any Plone version A project for a Plone PAS plugin A recipe project for zc.buildout A buildout for Silva projects Installation de Plone 4 Nous allons procéder à l’installation de Plone en créant un buildout spécifique. Pour cela saisissez la commande paster create -t plone3_buildout monplone4. Pour l’instant on utilise le patron de Plone 3 pour un site Plone 4. En indiquant une version supérieure ou égale à 4, la génération du fichier buildout.cfg sera différente d’un Plone 3. Répondez aux questions comme ceci : Expert mode ? expert Plone version : 4.0b1-1 Zope2 Install Path : Plone Products Directory : Initial Zope Username [’admin’] : Initial User Password : admin HTTP Port [’8080’] : 9080 debug mode |’off’] : verbose mode [’off’] : Nous avons volontairement changé le port de Plone pour pouvoir faire cohabiter plusieurs versions ensemble. La plupart de ces variables peuvent être changées par la suite. L’exécution a pour conséquence de créer l’arborescence suivante : C:\Documents and Settings\utlisateur>dir monplone4 Le volume dans le lecteur C n’a pas de nom. Le numéro de série du volume est BC6D-1497 Répertoire de C:\Documents and Settings\utlisateur\monplone4 15/03/2010 15/03/2010 15/03/2010 15/03/2010 15/03/2010 15/03/2010 15/03/2010 15/03/2010 23:26 <REP> . 23:26 <REP> .. 23:26 3 901 bootstrap.py 23:26 2 285 buildout.cfg 23:26 <REP> products 23:26 10 856 README.txt 23:26 <REP> src 23:26 <REP> var 3 fichier(s) 17 042 octets 5 Rép(s) 8 233 197 568 octets libres Nous allons générer les scripts de génération : C:\Documents and Settings\utlisateur>cd monplone4 C:\Documents and Settings\utlisateur\monplone4>python bootstrap.py Creating directory ’C:\\Documents and Settings\\utlisateur\\monplone4\\bin’ 126 Chapitre 10. Installation et création d’une instance Plone Plone pour les intégrateurs, Version 1.0.0 Creating directory ’C:\\Documents and Settings\\utlisateur\\monplone4\\parts’ Creating directory ’C:\\Documents and Settings\\utlisateur\\monplone4\\eggs’ Creating directory ’C:\\Documents and Settings\\utlisateur\\monplone4\ \develop-eggs’ Generated script ’C:\\Documents and Settings\\utlisateur\\monplone4\\bin\ \buildout’ Nous allons provoquer la récupération, la compilation et l’installation de Zope et Plone : C:\Documents and Settings\utlisateur\monplone4>.\bin\buildout.exe Getting distribution for ’plone.recipe.distros’. zip_safe flag not set; analyzing archive contents... plone.__init__: module references __path__ plone.recipe.__init__: module references __path__ Got plone.recipe.distros 1.5. Getting distribution for ’plone.recipe.zope2instance==4.0a4’. Got plone.recipe.zope2instance 4.0a4. Getting distribution for ’Zope2==2.12.3’. ... Generated script ’C:\\Documents and Settings\\utlisateur\\monplone4\\bin\ \instance’.Installing zopepy. Generated interpreter ’C:\\Documents and Settings\\utlisateur\\monplone4\ \bin\\zopepy’. Si tout ce passe bien nous avons un répertoire bin qui contient les lanceurs. Pour démarrer Plone : C:\Documents and Settings\utlisateur\monplone4>bin\instance.exe fg Création de l’instance Connectez vous à l’adresse http ://localhost :8080, on vous propose de créer un site Plone. Allez y. Remarques L’installation de plone via buildout pour Windows, n’est pas recommandée par la communauté en raison de sa complexité. Pour Windows, il vaut mieux passer par unified installer qui possèdera une installation de Python, un PIL, un Zope, et un buildout prêt à l’emploi. Ce qui correspond à une installation réussie des étapes précédentes... Dans les deux cas, l’ajout des modules à Plone (anciennement appelés produit) se fait par ajout d’un egg. Les eggs sont désormais la forme standard des paquets contenant les modules d’extensions de Plone. Nous détaillerons les eggs dans un autre chapitre. Donc l’ajout d’un egg se fait par déclaration du nom du egg voulu dans le fichier buildout.cfg à la section eggs. En lançant la commande bin\buildout.exe, le egg sera téléchargé, et au prochain démarrage de Plone, il y sera accessible dans la liste des modules du menu de configuration de Plone. Installation sous Mac OSX Sous Mac OSX, installez Python 2.4 soit avec le bundle Python 2.4 .dmg proposé en téléchargement, soit en utilisant MacPorts, Si vous avez installé Python avec MacPorts, pas de problème : 10.1. Savoir 127 Plone pour les intégrateurs, Version 1.0.0 $ sudo port install py-pil $ sudo port install py-libxml2 $ sudo port install py-libxslt Autrement, vous pouvez trouver une version http ://pythonmac.org/packages/py25-fat/index.html pré-compilée statique de PIL ici : Et vous devrez compilez les binders libxml2 et libxslt ceci sur votre poste comme indiqué ici : http ://jamesclarke.net/notes/libxml2 Suivez ensuite la procédure pour Ubuntu/Debian. 10.2 Exercice Nous allons créer l’instance de test qui sera utilisée dans les exercices suivants. 128 Chapitre 10. Installation et création d’une instance Plone CHAPITRE 11 Création d’un buildout Plone avec ZopeSkel Author Vincent Fretin Contributors Version 1.0.0 Copyright (C) 2010 Vincent Fretin <vincentfretin AT ecreall.com>. Chacun est autorisé à copier, distribuer et/ou modifier ce document suivant les termes de la licence Paternité-Pas d’Utilisation Commerciale-Partage des Conditions Initiales à l’Identique 2.0 France accessible à http ://creativecommons.org/licenses/by-nc-sa/2.0/fr Le code source présent dans ce document est soumis aux conditions de la « Zope Public License », Version 2.1 (ZPL). THE SOURCE CODE IN THIS DOCUMENT AND THE DOCUMENT ITSELF IS PROVIDED “AS IS” AND ANY AND ALL EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. – Création du buildout – Installation de produits tierces – Création d’un policy package contenant la configuration du site Plone – Création du policy package – Installation de Products.Collage à l’installation de formation.policy – Déclaration de formation.policy comme plugin Plone – Installation de collective.ckeditor à l’installation de formation.policy – Configuration de ckeditor pour tous les nouveaux utilisateurs – À propos des versions – Releaser le policy package – Repasser au développement – Utilisation de mr.developer pour gérer les composants en développement – Fabric – Ressources Note : Ce chapitre utilise un dépôt subversion créé dans le chapitre La gestion des sources avec subversion ainsi qu’un Pypi privé créé via Mise en place d’un Pypi privé avec PloneSoftwareCenter. 129 Plone pour les intégrateurs, Version 1.0.0 11.1 Création du buildout Créez les répertoires buildouts et packages sur le dépôt subversion : $ svn mkdir http://devagile/Formation/buildouts $ svn mkdir http://devagile/Formation/packages Commandes : $ paster create -t basic_buildout plone4 --svn-repository=http://devagile/Formation/buildouts/ Selected and implied templates: templer.buildout#basic_buildout A basic buildout skeleton Variables: egg: plone4 package: plone4 project: plone4 Running: svn mkdir ... Running svn co ... Expert Mode? (What question mode would you like? (easy/expert/all)?) [’easy’]: Creating template basic_buildout Copying buildout.cfg_tmpl to ./plone4/buildout.cfg Note : Avec l’option –svn-directory, un bug connu de Paste-1.7.3 et ZopeSkel-2.16 produit l’erreur suivante à la fin du processus : IOError : No egg-info directory found Vous pouvez simplement l’ignorer. Vous allez éditer le fichier buildout.cfg avant d’amorcer le buildout. Remplacez le fichier buildout.cfg par : [buildout] parts = instance zopepy extends = http://dist.plone.org/release/4.2/versions.cfg versions.cfg versions = versions find-links = http://dist.plone.org/release/4.2 eggs = Pillow develop = [instance] recipe = plone.recipe.zope2instance user = admin:admin http-address = 8080 eggs = Plone ${buildout:eggs} environment-vars = zope_i18n_compile_mo_files true zcml = [zopepy] recipe = zc.recipe.egg 130 Chapitre 11. Création d’un buildout Plone avec ZopeSkel Plone pour les intégrateurs, Version 1.0.0 eggs = ${instance:eggs} interpreter = zopepy scripts = zopepy Pillow est un fork de PIL (Python Imaging Library). Créez un fichier versions.cfg que vous utiliserez pour geler les versions des modules, pour l’instant vide : [versions] Si vous voulez travailler sur la dernière version du fichier versions.cfg de Plone, vous pouvez le télécharger comme ceci : $ wget -O versions-plone.cfg http://dist.plone.org/release/4.2/versions.cfg et changez votre buildout.cfg pour que l’option extends ressemble à ceci : extends = versions-plone.cfg versions.cfg Amorcez et lancez buildout : $ cd plone4 $ python bootstrap.py -d $ bin/buildout $ ls -F bin/ bootstrap.py buildout.cfg $ ls parts buildout instance $ ls bin buildout instance zopepy develop-eggs/ parts/ var/ versions.cfg – instance : script pour contrôler l’instance zope – zopepy : interpréteur python avec l’ensemble des eggs dans le sys.path Démarrez l’instance avec bin/instance fg et connectez vous à http ://localhost :8080 pour créer votre site Plone. Note : Commitez votre buildout $ svn add versions.cfg $ svn ci -m"Created initial buildout structure" 11.2 Installation de produits tierces Prenons le produit FCKeditor comme exemple. Stoppez l’instance avec Ctrl+C. Ajoutez collective.ckeditor dans l’option eggs de la section [instance] et reexécutez le buildout : $ bin/buildout Démarrez l’instance : $ bin/instance fg 11.2. Installation de produits tierces 131 Plone pour les intégrateurs, Version 1.0.0 Pour les produits n’étant pas dans l’espace de nom (namespace en anglais) Products, il faut également l’ajouter dans l’option zcml. À moins que le produit se proclame plugin Plone comme c’est le cas des modules créés avec la commande paster que vous verrez dans la suite. Dans ce cas-là les fichiers zcml seront inclus grâce à z3c.autoinclude. 11.3 Création d’un policy package contenant la configuration du site Plone Vous allez créer un policy package contenant la configuration du site Plone. Dans ce policy package, nous allons aussi dire d’installer automatiquement les produits Products.Collage et collective.ckeditor lors de l’installation du produit. Nous allons ensuite configurer FCKeditor comme éditeur par défaut pour les utilisateurs nouvellement créés. 11.3.1 Création du policy package Créez le policy package : $ cd /tmp/ $ paster create -t plone_basic formation.policy \ --svn-repository=http://devagile/Formation/packages Selected and implied templates: templer.core#basic_namespace A basic Python project with a namespace package templer.plone#plone_basic A package for Plone add-ons Expert Mode? (What question mode would you like? (easy/expert/all)?) [’easy’]: Version (Version number for project) [’1.0’]: Description (One-line description of the project) [’’]: Projet exemple pour la formation integrate Register Profile (Should this package register a GS Profile) [False]: True $ cd formation.policy $ svn rm --force formation.policy.egg-info $ svn ci -m "Add initial structure for formation.policy" Le template plone_basic hérite du template basic_namespace, il ajoute en plus un fichier configure.zcml. Vous allez utiliser la propriété svn:externals pour faire une sorte de checkout de votre nouveau package dans le dossier src : $ cd ~/workspace/plone4/ $ mkdir src $ svn add src $ cd src $ vim EXTERNALS.txt formation.policy http://devagile/Formation/packages/formation.policy/trunk $ svn propset svn:externals -F EXTERNALS.txt . $ svn up $ svn add EXTERNALS.txt $ svn ci -m "Set svn:externals on src directory to install formation.policy" Ajoutez Products.Collage et collective.ckeditor en dépendances de formation.policy dans le fichier src/formation.policy/setup.py (option install_requires). Lorsque vous êtes dans le dossier src, la commande svn stat vous renvoie les changements faits dans les externals, ici les changements de formation.policy s’il y en a. 132 Chapitre 11. Création d’un buildout Plone avec ZopeSkel Plone pour les intégrateurs, Version 1.0.0 La commande svn up sera également faite dans les différents externals. La seule exception est la commade svn ci exécutée à partir du dossier src ou plus en amont, les fichiers modifiés ou ajoutés dans les externals ne seront pas commités. Il faut vraiment être à l’intérieur de l’external, ici le dossier formation.policy pour que le commit des changements soit réalisé. Ceci dit, commitez le changement fait au fichier setup.py. Editez buildout.cfg pour ajouter formation.policy : [buildout] #... develop += src/formation.policy [instance] #... eggs = #... formation.policy zcml = formation.policy Exécutez bin/buildout. L’ajout de formation.policy dans l’option zcml = ... génère un ZCML slug, fichier XML contenant une seule ligne : parts/instance/etc/package-includes/001-formation.policy-configure.zcml <include package="formation.policy" file="configure.zcml" /> En fait au démarrage de l’instance Zope, le fichier parts/instance/etc/site.zcml est lu, ce qui entraine la lecture de tous les fichiers situés dans le dossier package-includes, ainsi que les fichiers meta.zcml, configure.zcml et overrides.zcml des produits dans l’espace de nom Products. La chaine de lecture est donc celle-ci : – parts/instance/etc/site.zcml – parts/instance/etc/package-includes/001-formation.policy-configure.zcml – src/formation.policy/src/formation/policy/configure.zcml Ces fichiers ZCML sont les fichiers de configuration utilisés par la ZCA (Zope Component Architecture) pour enregistrer les composants au démarrage. 11.3.2 Installation de Products.Collage à l’installation de formation.policy Vous allez maintenant formation.policy. dire à Plone d’installer Products.Collage lorsque vous installez Ouvrez le fichier src/formation.policy/src/formation/policy/configure.zcml, vous avez normalement ceci : <configure xmlns="http://namespaces.zope.org/zope" xmlns:five="http://namespaces.zope.org/five" xmlns:i18n="http://namespaces.zope.org/i18n" xmlns:genericsetup="http://namespaces.zope.org/genericsetup" i18n_domain="formation.policy"> <five:registerPackage package="." initialize=".initialize" /> <genericsetup:registerProfile name="default" title="formation.policy" 11.3. Création d’un policy package contenant la configuration du site Plone 133 Plone pour les intégrateurs, Version 1.0.0 directory="profiles/default" description="Installs the formation.policy package" provides="Products.GenericSetup.interfaces.EXTENSION" /> <!-- -*- extra stuff goes here -*- --> </configure> La directive <five:registerPackage ..../> signale à Zope que c’est un module. Cette ligne est importante vu que nous ne sommes pas dans l’espace de nom Products. La directive <genericsetup:registerProfile .../> permet d’enregistrer un nouveau profil d’extension (option provides) avec le nom default (option name). Les fichiers du profil se trouvent dans le dossier profiles/default. (option directory). Dans profiles/default, éditez le fichier metadata.xml comme ceci : <?xml version="1.0"?> <metadata> <version>1000</version> <dependencies> <dependency>profile-Products.Collage:default</dependency> </dependencies> </metadata> Le produit Products.Collage utilise bien un profil donc nous pouvons l’installer de cette manière. Jetez un œil à la seule documentation qui existe sur le support des dépendances de produits dans metadata.xml. Notez que la best practice est maintenant d’utiliser un entier pour la version du profile : 1000, 1001, 1002 et 2000, 2001 pour une branche parallèle. ArchGenXML ne respecte pas encore cette convention, il faut au moins deux entiers séparés par un point, ex : 1.0. Ce sera sans doute corrigé dans une prochaine version. Dans la chaine profile-Products.Collage:default, nous avons le préfixe profile-, le package au sens Python Products.Collage, le caractère : et le nom du profil à charger default. Ici default est le name donné lors du genericsetup:registerProfile dans le fichier configure.zcml de Products.Collage. 11.3.3 Déclaration de formation.policy comme plugin Plone Plone 3.3 inclut un nouveau système de plugin. Un produit peut être déclaré plugin Plone. Dans ce cas les fichiers meta.zcml, configure.zcml et overrides.zcml du produit seront lus au démarrage, comme pour les produits dans l’espace de nom Products. Il n’est plus nécessaire d’ajouter le produit dans l’option zcml de la section [instance] dans buildout.cfg. Pour cela vérifiez que le egg src/formation.policy/setup.py : est déclaré comme plugin Plone, avec dans entry_points=""" [z3c.autoinclude.plugin] target = plone """ Supprimez formation.policy de l’option zcml de la section [instance] dans buildout.cfg. Et relancez bin/buildout qui va supprimer le fichier parts/instance/etc/package-includes/001-formation.p La commande regénère également les metadonnées associées aux eggs en développement, concrètement il regénére le fichier src/formation.policy/formation.policy.egg-info/entry_points.txt qui déclare le egg comme plugin Plone. 134 Chapitre 11. Création d’un buildout Plone avec ZopeSkel Plone pour les intégrateurs, Version 1.0.0 À quel moment est lu le fichier configure.zcml de formation.policy ? Il n’y a rien de magique, la chaine de lecture est maintenant : – parts/instance/etc/site.zcml – lecture des fichiers configure.zcml de tous les produits dans l’espace de nom Products – ~/.buildout/eggs/Products.CMFPlone-4.2.0.1-py2.7.egg/Products/CMFPlone/configure.zcml qui contient les lignes : <!-- include plone plugins with z3c.autoinclude --> <includePlugins zcml:condition="not-have disable-autoinclude" package="plone" file="configure.zcml" /> Note : includePlugins includePlugins est une nouvelle directive fournie par z3c.autoinclude. Ici tous les eggs ayant un entry point dans le groupe z3c.autoinclude.plugin sont recherchés. Nous avons dans cette directive package="plone" donc seul les entry points avec target = plone sont gardés. Pour chaque egg, le fichier configure.zcml (option file de la directive) est lu. – src/formation.policy/src/formation/policy/configure.zcml Vous avez le même principe pour les fichiers meta.zcml et overrides.zcml, jetez un œil dans Products/CMFPlone/meta.zcml et Products/CMFPlone/overrides.zcml. 11.3.4 Installation de collective.ckeditor à l’installation de formation.policy Pour dépendre de collective.ckeditor, nous ne pouvons pas utiliser cette méthode car collective.ckeditor utilise un profil. Plone depuis sa versions 3.3 inclut le package z3c.autoinclude qui permet de ne pas se répéter. Vous pouvez utiliser la directive : <includeDependencies package="." /> Cette directive recupère la liste des dépendances du egg. Petit rappel, elle le récupère à partir du fichier src/formation.policy/src/formation.policy.egg-info/requires.txt qui lui a été généré à partir des informations de setup.py. Pour chaque dépendance dans l’ordre déclaré, elle va inclure dans l’ordre les fichiers meta.zcml, configure.zmcl et overrides.zcml s’ils existent. 11.3.5 Configuration de ckeditor pour tous les nouveaux utilisateurs Vous allez configurer ckeditor comme éditeur par défaut (seulement effectif pour les nouveaux utilisateurs). Tout d’abord, dans Configuration du site, Modules, activez formation.policy. Allez dans Configuration du site, ZMI, portal_setup, Snapshots. Créez un snapshot. Retournez à la racine de la ZMI et cliquez sur portal_memberdata, cliquez sur l’onglet Properties. Éditez la propriété wysiwyg_editor, mettez la valeur CKEditor. Retournez dans portal_setup, Snapshots. Recréez un snapshot. Cliquez maintenant sur l’onglet Comparison et comparez vos deux snapshots. Vous voyez bien que la propriété wysiwyg_editor a été modifiée dans le fichier memberdata_properties.xml. Maintenant vous allez exporter cette configuration dans votre policy package. Cliquez sur portal_setup dans le fil d’arianne, et cliquez sur l’onglet Export, sélectionnez le step MemberData properties, et cliquez sur Export selected steps. 11.3. Création d’un policy package contenant la configuration du site Plone 135 Plone pour les intégrateurs, Version 1.0.0 Téléchargez l’archive tar.gz proposée, extrayez son contenu dans un dossier temporaire et copiez le fichier memberdata_properties.xml dans le dossier profiles/default de votre policy package. Éditez le fichier pour ne laisser que la propriété qui vous intéresse. Vous devez donc avoir au final un fichier profiles/default/memberdata_properties.xml avec ce contenu : <?xml version="1.0"?> <object name="portal_memberdata" meta_type="PlonePAS MemberData Tool"> <property name="wysiwyg_editor" type="string">CKEditor</property> </object> Vous pouvez exporter de cette façon presque la totalité des configurations des tools Plone. Pour être sûr que l’import fonctionne bien, remettez TinyMCE dans wysiwyg_editor en ZMI. Comme vous avez ajouté un fichier dans le profil, incrémentez la version dans metadata.xml, nous avons donc la version 1001. Maintenant si vous redémarrez l’instance et que vous allez dans Configuration du site, Modules, vous pouvez y lire : – formation.policy 1.0 Ce module a été mis à jour. L’ancienne version du profil est 1000. La nouvelle version du profil est 1001. Il n’y a pas de procédure de mise à jour pour ce module. Merci de consulter la documentation du module pour la mise à jour, ou contacter l’auteur du module. Il faut en effet écrire un procédure de migration de la version 1000 vers la version 1001. Ajoutez dans configure.zcml : <genericsetup:upgradeDepends title="formation.policy 1000 to 1001" description="Configure FCKeditor as default wysiwyg editor" profile="formation.policy:default" source="1000" destination="1001" import_steps="memberdata-properties" /> Note : Liste des import steps : typeinfo, tinymce_settings, atcttool, actions, skins, factorytool, placeful_workflow, componentregistry, controlpanel, placeful_marker, jsregistry, action-icons, cmfeditions_various, reference_catalog, viewlets, content, propertiestool, various, portlets, content_type_registry, plone-final, kssregistry, ploneopenid-various, update-workflowrolemap, sharing, uid_catalog, workflow, cssregistry, contentrules, cookie_authentication, catalog, difftool, plonecontent, toolset, properties, jquerytools-various, tinymce_various, browserlayer, plone-difftool, memberdataproperties, kss_mimetype, caching_policy_mgr, archetypetool, mailhost, rolemap, various-calendar, qiproducts, archetypes-various Si vous redémarrez l’instance, vous aurez : – formation.policy 1.0 Ce module a été mis à jour. L’ancienne version du profil est 1000. La nouvelle version du profil est 1001. Mettre à jour : formation.policy Vous n’avez plus qu’à cliquer sur le bouton pour mettre à jour votre module. L’option wysiwyg_editor devrait maintenant être FCKeditor. Note : Commitez vos changements : $ svn add formation/policy/profiles/default/memberdata_properties.xml \ formation/policy/profiles/default/products.xml $ svn ci -m "Added configuration" 136 Chapitre 11. Création d’un buildout Plone avec ZopeSkel Plone pour les intégrateurs, Version 1.0.0 11.4 À propos des versions Le panneau de configuration Modules accessible via Configuration du site est une interface à portal_quickinstaller et portal_setup. Elle permet d’installer les produits n’ayant pas de profile avec portal_quickinstaller et les produits avec profile avec portal_setup. Les versions affichées sont celles des eggs. La version est récupérée via le module pkg_resources fourni par setuptools comme vu précédemment. La version du egg et du profil peuvent être différentes. Il est même conseillé dès le départ d’utiliser des versions différentes pour la version du produit/egg, et la version du profil. La version du egg est une version de la forme 1.0.0, 1.0.1, 1.1.0 etc. Si vous modifiez du code Python ou des templates, incrémentez cette version. La version du profile est un simple entier qui est incrémenté à chaque fois qu’un fichier est modifié ou ajouté dans le dossier du profile. Vous incrémenterez généralement aussi la version du egg. 11.5 Releaser le policy package Maintenant que vous avez un policy package qui fait quelque chose, il est peut-être temps de réaliser une release pour pouvoir l’utiliser en production. En effet il n’est pas conseillé d’utiliser des produits en mode développement en production. La première chose à faire et d’éditer le changelog dans le fichier CHANGES.txt. Ce fichier texte est au format reST (reStructuredText). Il faut respecter certaines conventions d’écriture pour que ce fichier puisse être généré ensuite en HTML sur Pypi. – le soulignage d’un titre doit aller exactement jusqu’au bout du titre. – les listes doivent avoir une ligne vide au début et à la fin Pour cette première release, vous allez seulement spécifier la date de la release. Remplacez juste unreleased par 2009-06-11. Remplacez également la puce de la liste, l’étoile par un tiret qui est la convention dans les produits Plone. Votre fichier doit ressembler à ceci : Changelog ========= 1.0 (2009-06-11) ---------------- Initial release La version dans setup.py doit également être 1.0. Commitez : $ svn ci -m "Prepare release" Maintenant vous allez faire un tag, c’est-à-dire une copie d’une branche qui sera gelée, faire un checkout de ce tag et pousser la release : $ $ $ $ $ svn cp http://devagile/Formation/packages/formation.policy/trunk http://devagile/Formation/packa cd /tmp svn co http://devagile/Formation/packages/formation.policy/tags/1.0 cd 1.0/ python setup.py register -r mycompany sdist --formats=zip upload -r mycompany 11.4. À propos des versions 137 Plone pour les intégrateurs, Version 1.0.0 Retournez ensuite dans le trunk, incrémentez la version dans setup.py, donc ici 1.1. Et éditez le fichier CHANGES.txt comme ceci : Changelog ========= 1.1 (unreleased) ---------------1.0 (2009-06-11) ---------------- Initial release Et commitez : $ svn ci -m "Update version after release" Pour plus d’informations sur la manière de faire une release, voyez les liens suivants : – http ://grok.zope.org/documentation/how-to/releasing-software – http ://plone.org/documentation/tutorial/how-to-upload-your-package-to-plone.org Note : Toutes ces étapes peuvent être faites avec une seule commande fullrelease. Pour cela installez le package zest.releaser dans votre environnement : $ workon myenv (myenv)$ easy_install zest.releaser Démarrez votre instance Plone où vous avez installé votre pypi. Pour releaser votre package : (myenv)$ cd src/formation.policy (myenv)$ fullrelease La commande fullrelease exécute séquentiellement les commandes prerelease, release et postrelease. Vous allez dorénavant utiliser cette version releasée plutôt que le egg en développement. Supprimez formation.policy de l’option develop de la section [buildout] dans buildout.cfg. Ajoutez aussi le lien vers le Pypi dans find-links : [buildout] find-links += # ... http://devagile:8080/site/products/simple Précisez la version formation.policy = 1.0 dans versions.cfg. L’external ne sera plus utilisé dans la suite, donc supprimez le également : $ svn rm src/EXTERNALS.txt $ svn propdel svn:externals src/ $ svn ci -m "Removed external" 11.6 Repasser au développement Maintenant vous voulez repasser le egg formation.policy en mode développement pour travailler dessus. Il faut : – supprimer la version dans versions.cfg – ajouter le egg dans l’option develop de buildout.cfg – reconfigurer l’external pour récupérer le egg dans le dossier src 138 Chapitre 11. Création d’un buildout Plone avec ZopeSkel Plone pour les intégrateurs, Version 1.0.0 Passer du mode développement au mode production et vice-versa génère beaucoup de bruit dans les logs svn, mais surtout il faut sans cesse répéter les mêmes actions. Nous allons utiliser dans la suite une extension buildout nommée mr.developer qui s’occupe de réaliser les 3 étapes décrites ci-dessus en une commande. 11.7 Utilisation de mr.developer pour gérer les composants en développement L’extension pour zc.buildout mr.developer permet de gérer les composants en développement, et de commuter facilement d’un composant en développement à sa version “releasée” et inversement. Transformez le fichier buildout.cfg : extends = # ... sources.cfg extensions = # ... mr.developer Créez le fichier sources.cfg avec ce contenu : [buildout] always-checkout = force auto-checkout = formation.policy [sources] formation.policy = svn http://devagile/Formation/packages/formation.policy/trunk Exécutez bin/buildout et mr.developer va s’occuper de faire un checkout de formation.policy dans le dossier src. L’extension s’occupe aussi de passer en mode développement formation.policy et de supprimer formation.policy de versions.cfg pour que ce soit bien la version en développement qui soit utilisée. Cela est fait de manière interne, les fichiers ne sont pas touchés. mr.developer génère le script bin/develop qui est un script à tout faire. Exécutez bin/develop help pour obtenir la liste des commandes, qui ressemblent beaucoup à subversion. bin/develop stat vous liste les checkouts du dossier src, vous dit s’ils sont actifs ou non (c’est-à-dire en mode développement ou non) et s’ils sont dans l’option auto-checkout ou non. Exécutez bin/develop help stat pour obtenir la légende. bin/develop co plonetheme.formation fait un checkout dans le dossier src, et active le egg (le met en mode développement). bin/develop activate plonetheme.formation suivi de bin/buildout permet de passer le egg en mode développement. bin/develop deactivate plonetheme.formation suivi de bin/buildout permet de désactiver le mode développement et d’utiliser la version spécifiée dans versions.cfg. bin/develop up -vf permet de mettre à jour tous les checkouts. L’option -v permet d’afficher les messages de subversion. L’option -f permet de forcer un svn up si le checkout est dans un état pas clean. L’idée est d’ajouter dans auto-checkout les eggs qui ont été modifiés après leur dernière release. Comme ceci lorsqu’il est temps de livrer votre travail en production, vous savez exactement quels sont les eggs dont vous devez faire une release. 11.7. Utilisation de mr.developer pour gérer les composants en développement 139 Plone pour les intégrateurs, Version 1.0.0 11.8 Fabric Créez un environnement isolé Python >= 2.5 avec Fabric d’installé : $ mkvirtualenv -p /usr/bin/python2.6 --no-site-packages fab (fab)$ easy_install Fabric Création d’un script Fabric pour la maintenance de l’instance Plone à distance. Créez un fichier fabfile.py à la racine de votre buildout : from fabric.api import run, sudo, env, hosts env.user = "anthony" env.hosts = [’devagile’] def update(): """Update the checkout of the buildout """ run("cd /home/anthony/workspace/plone4; svn up") def restart(): """Restart the instance """ run("/home/anthony/workspace/plone4/bin/instance restart") def stop(): """Stop the instance """ run("/home/anthony/workspace/plone4/bin/instance stop") def start(): """Start the instance """ run("/home/anthony/workspace/plone4/bin/instance start") def buildout(): """Run bin/buildout """ run("cd /home/anthony/workspace/plone4; bin/buildout") def up_and_restart(): """Update the checkout and restart the instance """ update() restart() def full_up_and_restart(): """Do the actions stop, update, buildout, start """ stop() update() buildout() start() Pour afficher la liste des commandes disponibles : $ fab --list Available commands: buildout full_up_and_restart restart 140 Run bin/buildout Do the actions stop, update, buildout, start Restart the instance Chapitre 11. Création d’un buildout Plone avec ZopeSkel Plone pour les intégrateurs, Version 1.0.0 start stop up_and_restart update Start the instance Stop the instance Update the checkout and restart the instance Update the checkout of the buildout Pour redémarrer l’instance : $ fab restart Pour préciser un autre host qui va donc écraser le host configuré globalement dans le fichier : $ fab stop:host=ailleurs Vous pouvez aussi créer des commandes avec des paramètres, exécutez fab -h pour consulter la liste des options. Pour plus de détails, consulter la documentation de Fabric 11.9 Ressources – http ://plone.org/documentation/tutorial/buildout – http ://www.sixfeetup.com/swag/buildout-quick-reference-card 11.9. Ressources 141 Plone pour les intégrateurs, Version 1.0.0 142 Chapitre 11. Création d’un buildout Plone avec ZopeSkel CHAPITRE 12 Déploiement et backup Author Vincent Fretin Contributors Thomas Desvenain Version 1.0.0 Copyright (C) 2010 Vincent Fretin <vincentfretin AT ecreall.com>. Chacun est autorisé à copier, distribuer et/ou modifier ce document suivant les termes de la licence Paternité-Pas d’Utilisation Commerciale-Partage des Conditions Initiales à l’Identique 2.0 France accessible à http ://creativecommons.org/licenses/by-nc-sa/2.0/fr Le code source présent dans ce document est soumis aux conditions de la « Zope Public License », Version 2.1 (ZPL). THE SOURCE CODE IN THIS DOCUMENT AND THE DOCUMENT ITSELF IS PROVIDED “AS IS” AND ANY AND ALL EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. – – – – – – – – – – – Définition Savoir Profil de déploiement Supervisor Support des backups Cron job pour zeopack et backup Configuration d’Apache – Activation de la compression Configuration des DNS Installation et configuration de plone.app.caching – Installation – Le panneau de configuration de la gestion de cache – Configuration – Tester Ressources Exercice 12.1 Définition Le déploiement d’un site Plone requiert des options particulières. Par exemple, nous voulons être sûr qu’une configuration d’un buildout produit la même chose aujourd’hui ou dans un an. 143 Plone pour les intégrateurs, Version 1.0.0 Vous avez également des environnements différents, donc vous aurez un fichier de configuration par environnement (développement, intégration, production, ...). Chaque fichier principal development.cfg, deployment.cfg, deployment-backup.cfg étant une extension d’une configuration de base buildout.cfg intégrant tous les modules applicatifs. 12.2 Savoir – – – – – – – Profil buildout de déploiement Mettre en place un backup de la ZODB Apache Varnish HAproxy plone.app.caching Supervisor 12.3 Profil de déploiement Rappel Vous pouvez réviser vos connaissances sur buildout en relisant le chapitre Création d’un buildout Plone avec ZopeSkel. Vous pouvez récupérer l’exemple complet de buildout sur le collective : $ git clone git://github.com/collective/collective.trainingmanual.git $ cd collective.trainingmanual/examples/buildout Le buildout.cfg du chapitre précédent est légèrement modifié : buildout.cfg [buildout] extends = http://dist.plone.org/release/4.2.4/versions.cfg sources.cfg checkouts.cfg versions.cfg tests.cfg parts += instance1 zopepy backup omelette extensions = mr.developer buildout.dumppickedversions versions = versions allow-hosts = pypi.python.org effbot.org find-links = # http://devagile:8080/site/products/simple http://dist.plone.org/release/4.2.4 eggs += Pillow 144 Chapitre 12. Déploiement et backup Plone pour les intégrateurs, Version 1.0.0 [instance1] recipe = plone.recipe.zope2instance user = admin:admin http-address = 8280 eggs = # formation.policy ${buildout:eggs} environment-vars = PYTHON_EGG_CACHE ${buildout:directory}/tmp TMPDIR ${buildout:directory}/tmp zope_i18n_compile_mo_files true zcml = event-log-custom = <logfile> level info path ${buildout:directory}/var/log/${:_buildout_section_name_}.log max-size 1MB old-files 720 </logfile> <logfile> level error path ${buildout:directory}/var/log/error.log max-size 1MB old-files 720 </logfile> access-log-custom = <logfile> path ${buildout:directory}/var/log/${:_buildout_section_name_}-Z2.log max-size 1MB old-files 720 </logfile> mailinglogger = # <mailing-logger> # level error # flood-level 10 # smtp-server localhost:9025 # from [email protected] # to [email protected] # subject [Error on MyApp] [%(hostname)s] %(line)s # </mailing-logger> [zopepy] recipe = zc.recipe.egg eggs = ${instance1:eggs} interpreter = zopepy scripts = zopepy [backup] recipe = collective.recipe.backup keep = 2 keep_blob_days = 14 full = false gzip = true [omelette] recipe = collective.recipe.omelette eggs = ${instance1:eggs} ${test:eggs} Créez un fichier deployment.cfg : deployment.cfg 12.3. Profil de déploiement 145 Plone pour les intégrateurs, Version 1.0.0 [buildout] extends = buildout.cfg parts += zeoserver instance1 instance2 instance3 instance4 varnish-build varnish-conf varnish haproxy haproxy-conf supervisor munin1 munin2 munin3 munin4 eggs += plone.app.caching [hosts] zeoserver instance1 instance2 instance3 instance4 varnish haproxy supervisor = = = = = = = = 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 [ports] zeoserver instance1 instance2 instance3 instance4 varnish haproxy supervisor = = = = = = = = 8100 9880 9881 9882 9883 8000 5501 9001 [users] zope varnish haproxy = vincentfretin = vincentfretin = vincentfretin [zeoserver] recipe = plone.recipe.zeoserver zeo-address = ${hosts:zeoserver}:${ports:zeoserver} [instance1] shared-blob = on zeo-client = true zeo-address = ${zeoserver:zeo-address} effective-user = ${users:zope} zodb-cache-size = 30000 zeo-client-cache-size = 128MB zserver-threads = 1 http-address = ${hosts:instance1}:${ports:instance1} [instance2] 146 Chapitre 12. Déploiement et backup Plone pour les intégrateurs, Version 1.0.0 <= instance1 http-address = ${hosts:instance2}:${ports:instance2} #ftp-address = 9821 [instance3] <= instance1 http-address = ${hosts:instance3}:${ports:instance3} [instance4] <= instance1 http-address = ${hosts:instance4}:${ports:instance4} [supervisor] recipe = collective.recipe.supervisor port = ${ports:supervisor} user = admin password = admin plugins = superlance supervisord-conf = ${buildout:directory}/etc/supervisord.conf serverurl = http://${hosts:supervisor}:${ports:supervisor} programs = 10 zeoserver ${zeoserver:location}/bin/runzeo ${zeoserver:location} true ${users:zope} 20 instance1 ${buildout:bin-directory}/instance1 [console] ${instance1:location} true 30 instance2 ${buildout:bin-directory}/instance2 [console] ${instance2:location} true 40 instance3 ${buildout:bin-directory}/instance3 [console] ${instance3:location} true 50 instance4 ${buildout:bin-directory}/instance4 [console] ${instance4:location} true 60 haproxy ${buildout:bin-directory}/haproxy [-f ${buildout:directory}/etc/haproxy.conf -db] t 70 varnish (autorestart=true) ${buildout:bin-directory}/varnish ${varnish:location} true eventlisteners = # memmon TICK_60 ${buildout:bin-directory}/memmon [-p instance1=600MB -p instance2=600MB -p ins # crashmail PROCESS_STATE ${buildout:bin-directory}/crashmail [-m [email protected]] [varnish-build] recipe = zc.recipe.cmmi url = ${varnish:download-url} [varnish-conf] recipe = collective.recipe.template input = ${buildout:directory}/templates/varnish.vcl.in output = ${buildout:directory}/etc/varnish.vcl [varnish] recipe = plone.recipe.varnish daemon = ${buildout:parts-directory}/varnish-build/sbin/varnishd bind = ${hosts:varnish}:${ports:varnish} #backends = ${haproxy-conf:bind} config = ${varnish-conf:output} cache-size = 256M user = ${users:varnish} mode = foreground [haproxy] recipe = plone.recipe.haproxy #cpu = i686 target = linux26 pcre = 1 [haproxy-conf] recipe = collective.recipe.template input = ${buildout:directory}/templates/haproxy.conf.in output = ${buildout:directory}/etc/haproxy.conf maxconn = 32000 ulimit-n = 65536 12.3. Profil de déploiement 147 Plone pour les intégrateurs, Version 1.0.0 user = ${users:haproxy} group = ${users:haproxy} bind = ${hosts:haproxy}:${ports:haproxy} [munin1] recipe = zc.recipe.egg eggs = munin.zope scripts = munin=munin1 arguments = ip_address=’${hosts:instance1}’, http_address=’${ports:instance1}’, user="${instance1: [munin2] recipe = zc.recipe.egg eggs = munin.zope scripts = munin=munin2 arguments = ip_address=’${hosts:instance2}’, http_address=’${ports:instance2}’, user="${instance2: [munin3] recipe = zc.recipe.egg eggs = munin.zope scripts = munin=munin3 arguments = ip_address=’${hosts:instance3}’, http_address=’${ports:instance3}’, user="${instance3: [munin4] recipe = zc.recipe.egg eggs = munin.zope scripts = munin=munin4 arguments = ip_address=’${hosts:instance4}’, http_address=’${ports:instance4}’, user="${instance4: Vous allez créer un utilisateur zope qui servira pour lancer le proxy cache varnish, le load balancer HAproxy et les instances zope. $ sudo adduser zope Note : Si vous avez installé un Plone en root avec l’unified installer, vous pouvez utiliser le compte plone au lieu de créer un compte zope. Pour cela remplacer zope par plone dans la section [users] du fichier deployment.cfg. Note : Il faut que les fichiers appartiennent à l’utilisateur zope ou plone ou vous aurez des problèmes pour démarrer le zeoserver par exemple. Donc vérifiez que les fichiers ont bien le bon propriétaire : $ sudo chown -R zope:zope votre_buildout Relancez le buildout en tant qu’utilisateur zope avec bin/buildout -c deployment.cfg. 12.4 Supervisor Le buildout génère le fichier etc/supervisord.conf. Tous les processus sont gérés par supervisor. Pour lancer supervisor, lancez le daemon en tant que super utilisateur qui lancera tous les processus ayant autostart=true (par defaut) : $ sudo bin/supervisord (varnish et haproxy ont besoin d’être démarrés en root pour activer certaines options. Les processus sont ensuite forkés pour utiliser l’utilisateur zope) Vous pouvez voir l’état des processus avec : 148 Chapitre 12. Déploiement et backup Plone pour les intégrateurs, Version 1.0.0 $ bin/supervisorctl status Pour redémarrer un processus par exemple instance1 : $ bin/supervisorctl restart instance1 Pour stopper : stop, pour démarrer : start. Pour tout redémarrer : $ bin/supervisorctl restart all Pour arrêter supervisor et donc tous les processus : $ bin/supervisorctl shutdown 12.5 Support des backups Les backups sont configurés dans la section backup. [backup] recipe = collective.recipe.backup keep = 2 keep_blob_days = 14 full = false gzip = true [omelette] recipe = collective.recipe.omelette eggs = ${instance1:eggs} ${test:eggs} Vous avez par défaut les options suivantes : location = ${buildout-directory}/var/backups snapshotlocation = ${buildout-directory}/var/snapshotbackups Plus d’informations sur les options de la recipe Pour exécuter la sauvegarde toutes les nuits, vous pouvez ajouter un cron job (crontab -e), ici à 3h du matin : 00 3 * * * /home/zope/MyProject/bin/backup -q Vous allez voir dans la suite une configuration de buildout qui s’occupe de créer le cron job à votre place. Pour faire une restauration : $ bin/restore Si vous voulez faire un backup de la production pour travailler ensuite en local, utilisez plutôt la commande : $ bin/snapshotbackup qui créera une sauvegarde dans le dossier var/snapshotbackups/, utile pour ne pas perturber les sauvegardes normales qui se font la nuit. Vous récupérez ensuite la sauvegarde (les fichiers .fsz et .dat) via scp et vous placez la sauvegarde dans votre dossier var/snapshotbackups/ en local et exécutez bin/snapshotrestore en local. 12.5. Support des backups 149 Plone pour les intégrateurs, Version 1.0.0 12.6 Cron job pour zeopack et backup Voici un exemple de configuration qui étend deployment.cfg pour réaliser un pack de la database avec la commande bin/zeopack et faire un backup avec la commande bin/backup vue précédemment. Il synchronise également les dossiers backup/ et log/ sur un autre serveur. Tout cela est réalisé par un job cron à 4h du matin. deployment-backup.cfg [buildout] extends = deployment.cfg parts += backup-template backup-schedule zeopack-schedule [backup-template] recipe = collective.recipe.template inline = #!/bin/bash ${buildout:bin-directory}/backup -q rsync -a --delete ${backup:location}/ [email protected]:/home/save/Plone/backups/ rsync -aH --delete ${backup:blobbackuplocation}/ [email protected]:/home/save/Plone/bl output = ${buildout:bin-directory}/backup.sh mode = 755 [backup-schedule] recipe = z3c.recipe.usercrontab times = 0 4 * * * command = ${backup-template:output} # every sunday [zeopack-schedule] recipe = z3c.recipe.usercrontab times = 0 1 * * 0 command = ${buildout:bin-directory}/zeopack -B ${buildout:directory}/var/blobstorage/ Dans cet exemple, la synchronisation se fait sur le serveur de secours/backup serveur1.example.com avec le login save. Il vous faut préalablement partager une clé publique entre ces deux serveurs pour que la commande rsync ne demande aucun mot de passe. Pour utiliser cette configuration, exécutez bin/buildout -c deployment-backup.cfg. Le cron job sera automatiquement ajouté dans le crontab de l’utilisateur. 12.7 Configuration d’Apache Création d’un certificat autosigné : $ sudo mkdir -p /etc/apache2/ssl/ $ sudo make-ssl-cert /usr/share/ssl-cert/ssleay.cnf \ /etc/apache2/ssl/server.crt /etc/apache2/sites-available/devagile : NameVirtualHost 127.0.0.1 <VirtualHost 127.0.0.1:80> ServerName devagile ServerAdmin [email protected] 150 Chapitre 12. Déploiement et backup Plone pour les intégrateurs, Version 1.0.0 ErrorLog /var/log/apache2/devagile_error.log TransferLog /var/log/apache2/devagile_access.log LogLevel warn RewriteEngine On RewriteRule ^/(.*) https://ssl.devagile/$1 [NC,R=301,L] </VirtualHost> /etc/apache2/sites-available/ssl.devagile (dans la RewriteRule, changez Plone par le nom de votre site plone) : NameVirtualHost 127.0.0.1:443 <VirtualHost 127.0.0.1:443> ServerName ssl.devagile ServerAdmin [email protected] ErrorLog /var/log/apache2/devagile_error.log TransferLog /var/log/apache2/devagile_access.log LogLevel warn SSLEngine On SSLCertificateFile /etc/apache2/ssl/server.crt #SSLCertificateKeyFile /etc/apache2/ssl/server.key RewriteEngine On RewriteRule ^/(.*) http://localhost:8000/VirtualHostBase/https/%{SERVER_NAME}:443/Plone/Virtua <IfModule mod_proxy.c> <Proxy proxy:http://localhost:8000> Order deny,allow Allow from localhost </Proxy> </IfModule> </VirtualHost> Activez les sites : $ a2ensite devagile $ a2ensite ssl.devagile Activez les modules : $ $ $ $ $ a2enmod a2enmod a2enmod a2enmod a2enmod ssl dav proxy proxy_http rewrite 12.7.1 Activation de la compression Activez le module deflate : $ a2enmod deflate et éditez le fichier de configuration /etc/apache2/mods-enabled/deflate.conf (ce n’est plus nécessaire avec Ubuntu 10.04 et plus) : <IfModule mod_deflate.c> # these are known to be safe with MSIE 6 AddOutputFilterByType DEFLATE text/html text/plain text/xml # everything else may cause problems with MSIE 6 12.7. Configuration d’Apache 151 Plone pour les intégrateurs, Version 1.0.0 AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE application/x-javascript application/javascript application/ AddOutputFilterByType DEFLATE application/rss+xml </IfModule> Redémarrez Apache : $ /etc/init.d/apache2 restart 12.8 Configuration des DNS Pour configurer vos DNS ou pour tester en local, éditez /etc/hosts : 127.0.0.1 devagile ssl.devagile Redémarrez Firefox pour qu’il relise le fichier. Vous accéderez à votre site à partir de maintenant avec l’adresse http ://devagile. 12.9 Installation et configuration de plone.app.caching plone.app.caching propose une interface graphique pour gérer les règles de cache HTTP pour Plone 4. Il est construit sur z3c.caching, plone.caching et plone.cachepurging. 12.9.1 Installation plone.app.caching est livré avec Plone mais n’est pas activé. Vous avez donc juste à activer le module dans la gestion des modules. 12.9.2 Le panneau de configuration de la gestion de cache Une fois activé vous allez trouver au niveau de la configuration de votre site un lien pour configurer les règles de cache de votre site. Cette interface graphique est constituée de trois onglets : 1. Changer la configuration (Change settings) : pour gérer le comportement du cache HTTP 2. Importer une configuration (Import settings) : vous permet d’importer des politiques de cache prédéfinies 3. RAM cache : fournit des informations statistiques sur le cache en RAM et son éventuelle purge. 152 Chapitre 12. Déploiement et backup Plone pour les intégrateurs, Version 1.0.0 12.9.3 Configuration Dans notre exemple, nous avons un cache proxy varnish derrière Apache. Pour configurer cette chaine, faire ce qui suit : – Cliquer sur Import settings, sélectionner With caching proxy, cliquer sur Import – Retourner dans Change settings, dans Global settings, cocher Enable caching – Dans l’onglet Caching proxies, cocher Enable purging – Ajouter http ://127.0.0.1 :8000 dans les Caching proxies. – Cocher Virtual host rewriting takes place front of the caching proxy car les adresses sont réécrites par Apache avec le RewriteRule. – Dans Externally facing domains, mettre https ://ssl.devagile :443 – Cliquer sur Save Le mieux après est d’exporter cette configuration dans formation.policy. Pour cela aller dans portal_setup, export, Export the configuration registry schemata. Ajouter le fichier registry.xml dans votre dossier profiles/default/. Eventuellement nettoyer ce fichier, seules les clés commencant par plone.app.caching nous intéressent. Pour aller plus loin : http ://pypi.python.org/pypi/plone.app.caching 12.9.4 Tester Vous pouvez tester que votre configuration fonctionne bien en inspectant les requêtes HTTP avec l’extension Firebug de Firefox par exemple. 12.10 Ressources – Varnish Guru Meditation on timeout – Plone Scaling and Performance par Elizabeth Leddy Apache et Zope, VirtualHostMonster : – http ://plone.org/documentation/tutorial/plone-apache/vhm/ – http ://plone.org/documentation/how-to/plone-with-apache – http ://www.zope.org/Documentation/Books/ZopeBook/2_6Edition/VirtualHosting.stx – http ://wiki.zope.org/zope2/ZopeAndApache – http ://doc.ubuntu-fr.org/tutoriel/securiser_apache2_avec_ssl Erreurs PosKey dans vos ZODB storages : – Checking your ZODB storages for PosKey errors 12.11 Exercice Geler toutes les versions des eggs utilisés dans le buildout. Ajout de la recipe collective.recipe.backup dans le buildout pour réaliser un backup régulier de la base de données. 12.10. Ressources 153 Plone pour les intégrateurs, Version 1.0.0 154 Chapitre 12. Déploiement et backup CHAPITRE 13 Zope External Editor – – – – Activation du lien “Modifier avec une application externe” Installation du client External Editor sous Ubuntu Installation du client External Editor sous Windows Problèmes de cache avec l’External Editor 13.1 Activation du lien “Modifier avec une application externe” L’option Activer la fonctionalité d’éditeur externe doit être coché depuis Configuration du site, puis Edition. Cette fonctionalité requiert l’installation d’une application sur le poste des utilisateurs. Ils devront aussi l’activer dans leurs préférences personnelles. Pour forcer l’utilisation de l’éditeur externe par tous vos utilisateurs, allez dans la Configuration du site, ZMI, portal_memberdata, cliquez sur l’onglet Properties, et cochez l’option ext_editor. Cela activera le lien Modifier avec une application externe à côté des liens Envoyer cette page et Imprimer sur les documents. Note : Il y a un bogue dans Plone 3.3.2 qui empêche ce lien de fonctionner. Éditez ~/.buildout/eggs/Plone-3.3.2-py2.4.egg/Products/CMFPlone/skins/plone_scripts/external_ed et remplacez ’%s/externalEdit_/%s.zem’ par ’%s/externalEdit_/%s’. 13.2 Installation du client External Editor sous Ubuntu Le système de package d’Ubuntu propose une ancienne version de zopedit. Nous allons quand même l’installer car il associe le type mime application/x-zope-edit à /usr/bin/zopeedit Nous allons ensuite remplacer le script par une nouvelle version. Installez donc zopeedit via le système de packages : $ sudo apt-get install zopeedit TODO TODO TODO TODO http://www.atreal.net/solutions/atrealxnet/collective.zopeedit_1.0.0_all.deb/view $ sudo dpkg -i collective.zopeedit_1.0.0_all.deb Ensuite récupérer la dernière version du script Python zopeedit.py sur http ://plone.org/products/zopeexternaleditor-client 155 Plone pour les intégrateurs, Version 1.0.0 et remplacez /usr/bin/zopeedit par celui-ci : $ sudo cp zopeedit.py /usr/bin/zopeedit Supprimez éventuellement l’ancien fichier ~/.zope-external-edit et exécutez zopedit dans un terminal pour recréer un fichier de configuration. Depuis la version 0.9.11pre1, le support du versionnement des documents est supporté, mais désactivé par défaut. Pour activer le versionnement des documents, éditez le fichier ~/.zope-external-edit et remplacez : # Create a new version when the file is closed ? # version_control = 0 par : # Create a new version when the file is closed ? version_control = 1 13.3 Installation du client External Editor sous Windows Téléchargez la dernière version de l’installateur à partir de http ://plone.org/products/zope-externaleditor-client et exécutez le. 13.4 Problèmes de cache avec l’External Editor Le problème suivant peut survenir : l’utilisateur clique sur Modifier avec une application externe, il l’édite, sauvegarde et lorsqu’il reclique sur le lien, il récupère l’ancienne version. Il peut y avoir deux raisons à cela. Le navigateur n’a pas redemandé le fichier, il l’a pris de son cache. Ou bien le proxy cache a retourné une version cachée du fichier. Il semble que l’on ne puisse pas utiliser Cache-Control :no-cache à cause de IE. Voir http ://support.microsoft.com/support/kb/articles/q316/4/31.asp Pour être sûr que le navigateur redemande toujours le fichier, il faut ajouter le header expires à la requête. Vous pouvez faire cela avec le module expires d’apache. Activez le module comme ceci : $ a2enmod expires Et configurer apache pour que les fichiers avec le type mime application/x-zope-edit expirent au bout d’une seconde : $ sudo vi /etc/apache2/httpd.conf Ajoutez les lignes : ExpiresActive On ExpiresByType application/x-zope-edit A1 et rechargez apache : $ sudo /etc/init.d/apache2 reload Vous aurez les headers suivants de positionnés : Cache-Control: max-age=1 Expires: (last modified date +1s) 156 Chapitre 13. Zope External Editor Plone pour les intégrateurs, Version 1.0.0 Si vous avez le proxy cache varnish, configurez le pour ne pas mettre en cache les fichiers qui possède le type mime application/x-zope-edit. En effet par défaut le fichier est caché pendant 120s, qui est le défaut ttl (time to live). Pour désactiver cela, ajoutez dans votre varnish.vcl, dans vcl_fetch la règle suivante : if (obj.http.Content-Type == "application/x-zope-edit") { pass; } L’utilisateur doit posséder les permissions WebDAV Lock items et WebDAV Unlock items pour pouvoir verrouiller le document via External Editor. 13.4. Problèmes de cache avec l’External Editor 157 Plone pour les intégrateurs, Version 1.0.0 158 Chapitre 13. Zope External Editor CHAPITRE 14 Monitoring avec Munin – Plugins Zope – Plugins Varnish – Ressources Installez le serveur et le client Munin : $ apt-get install munin munin-node À l’installation il active les plugins en fonction de ce qui installé : apache_processes cpu df df_inode entropy forks if_err_eth0 if_err_eth1 if_eth0 if_eth1 interrupts Vous aurez les plugins mysql si vous avez mysql-server d’installé. Les plugins actifs sont des liens symboliques dans /etc/munin/plugins/. Éditez /etc/munin/munin.conf pour changer host.domain.com (ce n’est pas nécessaire dans Ubuntu 12.04) : # a simple host tree [host.domain.com] address 127.0.0.1 use_node_name yes Activer d’autres modules si vous le souhaitez : $ cd /etc/munin/plugins $ ln -s /usr/share/munin/plugins/fail2ban $ ln -s /usr/share/munin/plugins/smart_ smart_sda Tous les fichiers dans /var/lib/munin et /var/log/munin doivent appartenir à l’utilisateur munin (à exécuter seulement si vous n’avez pas de stats) : $ chown -R munin:munin /var/lib/munin /var/log/munin Reexécutez cette commande si vous n’avez toujours pas de stats après 15 minutes. Redémarrez munin-node pour reprendre en compte la configuration : $ /etc/init.d/munin-node restart 159 Plone pour les intégrateurs, Version 1.0.0 14.1 Plugins Zope Exemple de buildout de deploiement avec munin : [buildout] extends = buildout.cfg parts += zeoserver instance1 instance2 munin1 [hosts] zeoserver instance1 instance2 = 127.0.0.1 = 127.0.0.1 = 127.0.0.1 [ports] zeoserver instance1 instance2 = 8100 = 9880 = 9881 [instance-settings] eggs = ${instance:eggs} munin.zope zcml = ${instance:zcml} munin.zope products = ${instance:products} user = ${instance:user} zodb-cache-size = 8000 zeo-client-cache-size = 300MB debug-mode = off zope2-location = ${zope2:location} zeo-client = true zeo-address = ${zeoserver:zeo-address} effective-user = ${users:zope} environment-vars = ${instance:environment-vars} zserver-threads = 2 [instance1] recipe = collective.recipe.zope2cluster instance-clone = instance-settings http-address = ${hosts:instance1}:${ports:instance1} [instance2] recipe = collective.recipe.zope2cluster instance-clone = instance-settings http-address = ${hosts:instance2}:${ports:instance2} [munin1] recipe = zc.recipe.egg eggs = munin.zope scripts = munin=munin1 arguments = ip_address=’${hosts:instance1}’, http_address=’${ports:instance1}’, user=’${instance1: [munin2] recipe = zc.recipe.egg eggs = munin.zope scripts = munin=munin2 arguments = ip_address=’${hosts:instance2}’, http_address=’${ports:instance2}’, user="${instance2: 160 Chapitre 14. Monitoring avec Munin Plone pour les intégrateurs, Version 1.0.0 Installez les liens symboliques : $ sudo ./bin/munin1 install /etc/munin/plugins instance1 installed symlink /etc/munin/plugins/instance1_zopecache_plonesite installed symlink /etc/munin/plugins/instance1_zopememory_plonesite installed symlink /etc/munin/plugins/instance1_zodbactivity_plonesite installed symlink /etc/munin/plugins/instance1_zopethreads_plonesite $ sudo ./bin/munin2 install /etc/munin/plugins instance2 installed symlink /etc/munin/plugins/instance2_zopecache_plonesite installed symlink /etc/munin/plugins/instance2_zopememory_plonesite installed symlink /etc/munin/plugins/instance2_zodbactivity_plonesite installed symlink /etc/munin/plugins/instance2_zopethreads_plonesite Redémarrez munin-node pour reprendre en compte la configuration : $ /etc/init.d/munin-node restart 14.2 Plugins Varnish Il existe des plugins munin pour Varnish. Voyez la page sur pypi pour les instructions : http ://pypi.python.org/pypi/munin.varnish Les plugins utilisent la commande varnishstat. Cette commande est disponible si vous avez le package libncurses5-dev lors de la compilation de Varnish. 14.3 Ressources – – – – http ://www.debianadmin.com/monitor-servers-and-clients-using-munin-in-ubuntu.htm http ://www.debianhelp.co.uk/munin.htm http ://www.debuntu.org/how-to-monitoring-a-server-with-munin http ://www.debuntu.org/how-to-monitoring-a-server-with-munin-p2 14.2. Plugins Varnish 161 Plone pour les intégrateurs, Version 1.0.0 162 Chapitre 14. Monitoring avec Munin CHAPITRE 15 PloneFormGen – Présentation de PloneFormGen – Qu’est ce que PloneFormGen ? – Qu’est-ce que l’on peut faire avec PloneFormGen ? – Installation de PloneFormGen – Création d’un formulaire – Les différents composants d’un formulaire – Les différents types de champs – Champ de type Checkbox – Champ de type date et heure – Champ de type decimal Number – Champ de type conteneur pour groupe de champs – Champ de type saisie multiple – Champ de type sélection multiple – Champ de type mot de passe – Champ de type Rating-Scale Field – Champ de type Rich Label Field – Champ de type texte mis en forme – Champ de type sélection – Champ de type texte court – Champ de type zone de texte – Champ de type Whole Number Field – Les adaptateurs pour scripts – Les expéditeurs de méls – Les enregistreurs de données – La page de remerciement – Exercice : Réalisation d’un formulaire de sondage – Composition du formulaire – Création de l’enregistreur pour récupérer les données au format CSV – Création d’un script remplissant une base de données. 15.1 Présentation de PloneFormGen 15.1.1 Qu’est ce que PloneFormGen ? PloneFormGen est un produit permettant la création en ligne de formulaire pour Plone. On trouvera de la documentation sur http ://plone.org/products/ploneformgen/documentation 163 Plone pour les intégrateurs, Version 1.0.0 15.1.2 Qu’est-ce que l’on peut faire avec PloneFormGen ? Outre la création à travers le web des formulaires, on pourra stocker les informations qui y seront saisies en vue de les réutiliser et de les exporter au format csv. De plus la possibilité de créer des adaptateurs appelant des scripts Python en fin de saisie permettent par exemple de créer des instances de n’importe quel type de contenu et de les remplir à partir des informations préalablement saisies. 15.1.3 Installation de PloneFormGen Pour installer PloneFormGen le plus simple est de l’ajouter à son buildout. Si vous ne savez pas ce qu’est un buildout vous pouvez lire le chapitre Introduction à zc.buildout et Création d’un buildout Plone avec ZopeSkel. Pour cela ajouter Products.PloneFormGen à la section egg de la partie instance : [instance] # ... eggs = # ... Products.PloneFormGen Refaites votre buildout, démarrez, puis ajoutez le produit. 15.1.4 Création d’un formulaire La création d’un formulaire commence par la création d’un Formulaire dans la liste Ajout d’un élément. Vous obtenez alors : Le formulaire est un répertoire qui permet de définir votre formulaire et qui contiendra les éléments qui vont le constituer. Remarquez également la barre des propriétés qui va permettre d’accéder à la définition du comportement du formulaire (onglet Overrides). Saisissez un titre et une description. Vous pouvez changer le nom des boutons de soumission ou d’annulation. Par défaut le comportement d’un formulaire personnalisé est d’envoyer un mail avec les informations saisies par les utilisateurs. Ce comportement est réalisé par un “adaptateur d’action” nommé “Gestionnaire de mél”. Par la suite nous verrons comment remplacer cet adaptateur par celui que nous aurons créé. Vous pourrez aussi définir une page de remerciement qui viendra remplacer celle par défaut qui se contente d’afficher les valeurs saisies dans le formulaire. Pour des raisons de confidentialité vous pourrez forcer la saisie des informations via une connexion chiffrée à condition d’avoir configuré votre serveur pour qu’il gère le ssl et donc d’avoir un certificat X509. Vous pouvez ensuite saisir le prologue et l’épilogue du formulaire. Enregistrez. Vous êtes alors redirigé vers votre formulaire qui affiche le titre, la description, le prologue, les champs de saisie “Votre adresse mél”, “Sujet”, et “Commentaires”, le bouton “Envoyer” et pour finir votre épilogue. Nous verrons comment ajouter d’autres champs et supprimer ceux existants par défaut. Si vous avez correctement configuré le mailhost de votre instance Plone, le résultat des formulaires sera envoyé par mél à destination du contact “Adresse d’expéditeur des courriels pour le site” (modifiable en cliquant sur Configuration du site puis Envoi de courriels). 164 Chapitre 15. PloneFormGen Plone pour les intégrateurs, Version 1.0.0 F IGURE 15.1 – Ajout d’un formulaire personnalisé. 15.1. Présentation de PloneFormGen 165 Plone pour les intégrateurs, Version 1.0.0 F IGURE 15.2 – Vue d’un formulaire. Après avoir appuyé sur Envoyer l’utilisateur est redirigé sur la page de remerciement qui récapitule les valeurs entrées. 15.1.5 Les différents composants d’un formulaire Cliquez sur l’onglet édition de votre formulaire puis cliquez sur l’onglet Overrides des propriétés. F IGURE 15.3 – Onglets d’accès aux propriétés d’un formulaire Vous accédez alors à la page suivante : Le champ “Action de validation personnalisée” permet d’exécuter un script personnalisé qui sera appelé après l’action associée au formulaire (par défaut l’envoi de mél). Le champ “Action personnalisée du formulaire” permet d’exécuter un script personnalisé en lieu et place de l’envoi de mél. Le champ “Script de configuration du formulaire” permet d’exécuter un script avant l’affichage du formulaire pour par exemple remplir les champs avec des valeurs calculées. Le champ “Script post-validation” permet d’exécuter un script ayant pour objectif de valider la cohérence des valeurs saisies les une vis-à-vis des autres ou vis à vis de données extérieures. Le champ “Injection de contenu d’entête” permet de compléter la page html avec par exemple des liens vers des ressources css ou javascripts. La case à cocher “CSRF Protection” permet d’éviter les liens html ou l’insertion de javascript lors de la saisie des valeurs du formulaire. 166 Chapitre 15. PloneFormGen Plone pour les intégrateurs, Version 1.0.0 F IGURE 15.4 – Paramétrage du comportement d’un formulaire 15.1. Présentation de PloneFormGen 167 Plone pour les intégrateurs, Version 1.0.0 Plus d’informations sur l’overrides : http ://plone.org/products/ploneformgen/documentation/tutorial/customizingploneformgen Pour ajouter des champs ou des actions il suffit de cliquer sur l’un des types disponibles depuis le menu Ajout d’un élément. F IGURE 15.5 – Ajout d’un champ ou d’une action Nous allons détailler les éléments de formulaire ci-après. L’édition graphique et le placement se font après avoir cliqué sur l’onglet QuickEdit. F IGURE 15.6 – Icône d’accès à la vue de paramétrage On obtient alors une vue ressemblant à : Les colonnes “Delete” permettent de supprimer les composants, les colonnes “Edit” permettent d’éditer le composant désigné par la ligne où nous avons cliqué. La colonne “Order” permet par drag and drop de déplacer les champs pour en changer l’ordre alors que la colonne “Enable” permet d’activer ou non une action ou un page de remerciement. 168 Chapitre 15. PloneFormGen Plone pour les intégrateurs, Version 1.0.0 F IGURE 15.7 – Paramétrage des éléments du formulaire 15.1. Présentation de PloneFormGen 169 Plone pour les intégrateurs, Version 1.0.0 15.1.6 Les différents types de champs Champ de type Checkbox L’ajout d’une checkbox permet de créer une checkbox. F IGURE 15.8 – Formulaire de paramétrage d’un champ de type checkbox Signification des champs : – Le label du champ correspond au nom du champ il doit être explicite, – l’aide doit permettre à l’utilisateur de savoir à quoi sert ce checkbox, – le champ obligatoire s’il est coché oblige l’utilisateur à se prononcer, – la valeur par défaut (cochée ou non) – la chaîne de caractères affichée si la checkbox est cochée, – la chaîne de caractères affichée si la checkbox n’est pas cochée. Comme pour le formulaire les champs possèdent une propriété “Overrides”. 170 Chapitre 15. PloneFormGen Plone pour les intégrateurs, Version 1.0.0 F IGURE 15.9 – Propriétés overrides des champs de type checkbox 15.1. Présentation de PloneFormGen 171 Plone pour les intégrateurs, Version 1.0.0 “Expression par défaut” permet de remplir le champ à partir d’une expression TALES évaluée lors du rendu du formulaire, dans le cas du checkbox le résultat doit être “checked” ou la chaine vide “”. “Validateur personnalisé” permet de saisir une expression TALES validant la saisie, attention généralement le test ne concerne que la valeur du champ et non la cohérence du formulaire qui est réalisé dans le test de post validation. “Enabling Expression” permet de griser ou non le champ à l’affichage en fonction du résultat de l’expression TALES saisie. Champ de type date et heure L’ajout d’un champ date et heure permet de créer une zone de saisie année, mois, jour, heure, minute pouvant être saisie par calendrier. La valeur par défaut est saisie sous la forme AAAA MM JJ HH mm où les séparateurs peuvent être ‘ ‘, ‘/’, ‘-‘, ‘.’. Champ de type decimal Number Il permet de créer des champs de saisie de nombre flottant. Champ de type conteneur pour groupe de champs Il permet de créer un dossier qui contiendra des champs et les groupera visuellement à l’écran. Remarquer que l’édition des champs contenus par le groupe nécessite de passer par la vue Contenus. Champ de type saisie multiple Il permet de créer une zone de saisie de lignes de texte. Les propriétés Overrides offre en plus un champ “Server-Side Variable” qui permet d’utiliser le contenu du champ pour passer des valeurs aux adaptateurs d’actions. Champ de type sélection multiple Overrides permet via le champ “Vocabulaire des options” de définir une expression TALES permettant de définir le dictionnaire. Champ de type mot de passe Lors de la saisie les lettres seront remplacés par des ‘*’. Champ de type Rating-Scale Field Champ de type Rich Label Field Ce champ permet de faire de la mise en forme. Champ de type texte mis en forme Champ de type sélection Overrides permet via le champ “Vocabulaire des options” de définir une expression TALES permettant de définir le dictionnaire. 172 Chapitre 15. PloneFormGen Plone pour les intégrateurs, Version 1.0.0 Champ de type texte court Champ de type zone de texte Champ de type Whole Number Field 15.1.7 Les adaptateurs pour scripts Les adaptateurs de scripts permettent de réaliser des actions sous forme de code Python. Certaines restrictions de sécurité sont présentes, il n’est donc pas possible d’importer toutes les bibliothèques du langages. F IGURE 15.10 – Édition de l’adaptateur de script Le champ “proxy role” permet d’exécuter le script avec le rôle Administrateur. Le champ “corps du script” permet de saisir le code Python. La propriété Overrides permet de définir une “Condition d’exécution” qui si elle n’est pas vérifiée empêche l’exécution du script. Exemple d’adaptateur créant un document à partir des données saisies : # # # # # # # # # # Available parameters: fields = HTTP request form fields as key value pairs request = The current HTTP request. Access fields by request.form["myfieldname"] ploneformgen = PloneFormGen object Return value is not processed -- unless you return a dictionary with contents. That’s regarded as an error and will stop processing of actions and return the user to the form. Error dictionaries 15.1. Présentation de PloneFormGen 173 Plone pour les intégrateurs, Version 1.0.0 # should be of the form {’field_id’:’Error message’} from Products.CMFCore.utils import getToolByName portal = getToolByName(ploneformgen, ’portal_url’).getPortalObject() putils = getToolByName(ploneformgen, ’plone_utils’) title = fields[’topic’] masaisie = fields[’ma-saisie’] id=putils.normalizeString(title) portal.invokeFactory(’Document’, id=id ,title=title, text=u"\n".join(masaisie)) link=portal[id].absolute_url() request.RESPONSE.redirect(link) 15.1.8 Les expéditeurs de méls @TODO 15.1.9 Les enregistreurs de données @TODO 15.1.10 La page de remerciement @TODO 15.2 Exercice : Réalisation d’un formulaire de sondage 15.2.1 Composition du formulaire @TODO 15.2.2 Création de l’enregistreur pour récupérer les données au format CSV @TODO 15.2.3 Création d’un script remplissant une base de données. @TODO 174 Chapitre 15. PloneFormGen CHAPITRE 16 Le theming Plone avec Diazo Contents : 16.1 Diazo Author Éric Bréhault (Makina Corpus) Created 2013-04-17 Version 1.0 16.1.1 Introduction Avant Diazo, la mise en place d’un design spécifique pour un site Plone se faisait en dérivant le thème de base de Plone afin d’en modifier certains éléments : – les images (par exemple le logo, ou le favicon), – les CSS, – les templates (template principal, template de portlets ou de viewlets). Cela impliquait de changer de nombreux fichiers de déclaration, et souvent de ré-écrire certains fichiers Python. Autrement dit, il fallait rentrer dans le coeur de Plone. Diazo propose une approche extérieure : il se comporte comme un proxy web (autrement dit un service qui reçoit des URLs en entrée et renvoi le contenu HTML d’une page produite par un autre système en retour) mais il est capable d’appliquer dynamiquement un design sur le contenu qu’il renvoie. 16.1.2 Principe Le design est fourni sous forme d’une arborescence HTML statique classique : – un ou plusieurs fichiers HTML, – des images, – des CSS, – des JS. L’application de ce design aux contenus Plone est définie par un fichier de règles nommé rules.xml. Ce fichier de règles permet de mettre en correspondance des éléments du contenu dynamique (par exemple le titre du contenu Plone) avec des éléments du thème, c’est-à-dire le modèle HTML statique, (par exemple tel tag H1 ayant l’identifiant “content-title”). 175 Plone pour les intégrateurs, Version 1.0.0 16.1.3 Éditeur en ligne de Diazo Depuis la version 4.3, Plone propose un éditeur en ligne pour modifier le thème Diazo. Se rendre dans la Configuration du site, puis dans Modules. Installer Diazo theme support. Aller ensuite dans Theming. On peut créer un nouveau thème et il existe également un exemple minimal qui peut être copié. Lorqu’on édite un thème, on dispose d’un navigateur qui permet de gérer les fichiers disponibles, et d’un éditeur texte. 176 Chapitre 16. Le theming Plone avec Diazo Plone pour les intégrateurs, Version 1.0.0 On dispose également de 2 inspecteurs qui permettent de voir les pages du thème en HTML statiques et les pages Plone et d’y sélectionner à la souris les éléments qu’on veut mettre en correspondance : – un clic permet de pointer un élément, – la touche Esc permet de pointer son père, – la touche Enter place l’élement dans la sélection courante, – le bouton Build rule permet de créer une règle à partir des sélections. 16.1.4 Les directives Le fichier rules.xml peut contenir les directives suivantes. <theme /> Cette directive applique une page de thème. Exemple : <theme href="index.html" /> 16.1. Diazo 177 Plone pour les intégrateurs, Version 1.0.0 On peut rendre y ajouter des conditions afin de choisir quand utiliser telle ou telle page de thème. Exemple : <theme href="index.html" css:if-content=".section-front-page" /> <theme href="detail.html" css:if-not-content=".section-front-page" /> Les attributs possibles pour <theme/> sont : – css:if-content et css:if-not-content qui permettent de tester un sélecteur CSS sur le contenu Plone, – if-content et if-not-content qui permettent de tester un sélecteur XPath sur le contenu Plone, – if qui permet de tester une variable Plone (voir plus loin), par exemple : <theme href="theme-two-left.html" if="$have_left_portlets"/> – if-path qui permet de tester des conditions sur la requête courante, exemple : <theme href="calendrier.html" if-path="/events"/> Note : pour plus de détails sur les conditions, voir plus bas. <notheme /> Cette directive désactive le thème diazo. Exemple : <notheme css:if-content=".template-overview-controlpanel" /> Les attributs possibles pour <notheme/> sont : – css:if-content et css:if-not-content, – if-content et if-not-content, – if, – if-path. <replace /> Cette directive remplace un élément du thème par le contenu Plone. Exemple : <replace theme="/html/head/title" content="/html/head/title"/> Les attributs possibles pour <replace /> sont : – theme ou css:theme pour désigner l’élément cible dans le thème HTML, – content ou css:content pour désigner l’élément source dans le contenu Plone, – theme-children ou css:theme-children, qui permet de remplacer non pas l’élément désigné, mais tous les tags qu’il contient, – content-children ou css:content-children, qui permet d’utiliser non pas l’élément désigné, mais tous les tags qu’il contient, – attributes qui permet de remplacer des attributs plutôt que le contenu. Exemple : <replace theme="/html/body" content="/html/body" attributes="class"/> – – – – – css:if-content et css:if-not-content, if-content et if-not-content, if, if-path, method (voir plus bas). <before /> et <after /> Ces deux directives ont un comportement similaire à <replace /> mais plutôt que remplacer l’élément ciblé, elles vont faire une insertion avant ou après la cible (selon le cas). Les attributs possibles sont les mêmes que pour <replace /> sauf method. 178 Chapitre 16. Le theming Plone avec Diazo Plone pour les intégrateurs, Version 1.0.0 <append /> et <prepend /> Ces deux directives ont un comportement similaire à <replace /> mais plutôt que remplacer l’élément ciblé, elles vont faire une insertion à l’intérieur de l’élement cible à la fin ou au début (selon le cas). Les attributs possibles sont les mêmes que pour <replace /> sauf method. <drop /> Cette directive supprime des éléments du thème ou du contenu. Exemples : <drop css:content="#portal-content .documentByLine" /> <drop css:theme=".lorem-ipsum" /> Note : une même commande <drop /> ne peut pas supprimer à la fois dans le contenu et dans le thème. Les attributs possibles pour <drop /> sont : – theme ou css:theme, – content ou css:content, – theme-children ou css:theme-children, – content-children ou css:content-children, – attributes, – css:if-content et css:if-not-content, – if-content et if-not-content, – if, – if-path. <strip /> Cette directive supprime des élements sans supprimer leur contenu. Exemple : <strip css:content=".portletWrapper" /> va supprimer les tags div de classe portletWrapper mais les tags dl des portlets seront préservés. Les attributs possibles sont les mêmes que pour <drop />. <merge /> Cette directive fusionne pour un attribut donné les valeurs provenant du thème et celles provenant du contenu Plone. Exemple : <merge attributes="class" css:theme="body" css:content="body" /> Les attributs possibles sont : – attributes, qui définit les attributs concernés (séparés par des espaces), – separator, qui indique le séparateur à utiliser pour fusionner les valeurs (par défaut, c’est un espace), – theme ou css:theme, – content ou css:content, – css:if-content et css:if-not-content, – if-content et if-not-content, – if, – if-path. 16.1. Diazo 179 Plone pour les intégrateurs, Version 1.0.0 <copy /> Cette directive permet de copier un attribut venant du contenu Plone sur un élément du thème. Note : À la différence, de <replace attributes />, <copy /> va fonctionner même si l’attribut n’existe pas sur l’élément cible (et s’il existe, il est remplacé). Exemple : <copy attributes="class" css:theme="body" css:content="body"/> Les attributs possibles sont : – attributes, qui définit les attributs concernés (séparés par des espaces), – theme ou css:theme, – content ou css:content, – css:if-content et css:if-not-content, – if-content et if-not-content, – if, – if-path. 16.1.5 L’ordre d’éxecution Dans certains cas, l’ordre d’éxecution peut avoir des conséquence sur résultat, il est donc bon de le connaître. L’ordre est le suivant : 1. les directives <notheme />, 2. les directives <theme />, 3. les directives <before /> utilisant theme (et non pas theme-children), 4. les directives <drop /> sont éxécutées ensuite, 5. les directives <replace /> utilisant theme (et non pas theme-children), 6. les directives <strip />, 7. toutes les directives s’appliquant aux attributs, 8. les directives <before />, <replace /> et <after /> utilisant theme-children, 9. les directives <after /> utilisant theme (et non pas theme-children). Note : si on ajoute method="raw" sur une directive <replace />, on peut utiliser un morceau du contenu Plone même s’il appartient à un élément supprimé par un <drop />. 16.1.6 Cas des règles sans correspondance Si une règle utilise un theme (ou css:theme) ne correspondant à aucun élément dans le thème, la règle est ignorée. En revanche, si une règle utilise un content (ou css:content) ne correspondant à aucun élément dans le contenu, la règle sera appliqué (et le contenu sera simplement considéré comme vide). 16.1.7 Les conditions Conditions sur le contenu if-content permet d’indiquer une expression XPath, si cette expression trouve une correspondance dans le contenu, la règle sera appliquée. 180 Chapitre 16. Le theming Plone avec Diazo Plone pour les intégrateurs, Version 1.0.0 css:if-content fonctionne de la même manière, mais en utilisant une expression CSS plutôt qu’XPath. Exemple : <drop css:theme="#publicite" css:if-content=".userrole-authenticated"/> signifie que l’élément publicite sera supprimé si la classe userrole-authenticated est présente (autrement dit si l’utilisateur est connecté). Si on laisse if-content vide, cela revient à utiliser la même valeur que celle de content (ou css:content). Exemple : <after css:theme="#topnews dt" css:content=".portlet-topnews dd" css:if-content=""/> est équivalent à : <after css:theme="#topnews dt" css:content=".portlet-topnews dd" css:if-content=".portlet-topnews dd"/> Si plusieurs règles concernent le même élement du thème mais ont des conditions différentes, cela va être interprêté comme un bloc if ... then ... else .... Exemple : <replace theme-children="/html/body/h1" content="/html/body/h1/text()" if-content="/html/body/h1"/ <replace theme-children="/html/body/h1" content="//h1[@id=’first-heading’]/text()" if-content="//h <replace theme-children="/html/body/h1" content="/html/head/title/text()" /> va renseigner le tag H1 du body de la façon suivante : – si le contenu dispose d’un tag h1 comme fils immédiat du body, on en prend le texte, – sinon, on prend n’importe quel h1 dont l’id est ‘first-heading’, – et s’il n’y en a pas non plus, on prend la valeur du title. Conditions sur le chemin de la page L’attribut if-path permet de conditionner l’application d’une règle en fonction du chemin de la page la page demandée. Si la valeur commence par /, on cherche la correspondance à partir du début du chemin. Par exemple : <drop css:theme="#search" if-path="/blog" /> va s’appliquer pour /blog, /blog/, et /blog/recent. Si la valeur se termine par /, on cherche la correspondance à partir de la fin du chemin. Par exemple : <drop css:theme="#search" if-path="recent/" /> va s’appliquer pour /blog/recent/, et /actualites/interne/recent. Pour une correspondance exacte, il faut mettre / au début et à la fin. Par exemple : <drop css:theme="#search" if-path="/blog/" /> va s’appliquer pour /blog, et /blog/, mais pas /blog/recent. S’il n’y a de / ni à la fin ni au début, la correspondance se fait sur n’importe quelle partie du chemin. Par exemple : <drop css:theme="#search" if-path="interne/recent" /> va s’appliquer pour /interne/recent, /actualites/interne/recent/images. /actualites/interne/recent, et On peut indiquer plusieurs conditions en les séparant par des espaces : 16.1. Diazo 181 Plone pour les intégrateurs, Version 1.0.0 <drop css:theme="#search" if-path="/blog /agenda" /> Conditions sur des variables Le fichier manifest.cfg permet de définir des variables dans la section [theme:parameters]. Exemple : [theme:parameters] have_left_portlets = python:context.restrictedTraverse(’@@plone’).have_portlets(’plone.leftcolumn’ have_right_portlets = python:context.restrictedTraverse(’@@plone’).have_portlets(’plone.rightcolum have_both_portlets = python:context.restrictedTraverse(’@@plone’).have_portlets(’plone.leftcolumn’ lang = python:context.restrictedTraverse("@@plone_portal_state/language")() Note : les modifications du fichier manifest.cfg ne sont pas prises en compte lorsqu’on utilise l’éditeur en ligne. Il faut les saisir dans l’onglet Paramètres avancés. L’attribut if (ou if-not) permet d’utiliser ces variables en les préfixant par un $ : <theme href="theme-two-left.html" if="$have_left_portlets"/> <theme href="index-fr.html" if="$lang = ’fr’"/> Groupement et encapsulation de conditions On peut regrouper des règles dans des balises <rules /> afin de leur appliquer des conditions communes : <rules xmlns="http://namespaces.plone.org/diazo" xmlns:css="http://namespaces.plone.org/diazo/css" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <rules css:if-content=".portlet-alerte"> <after css:theme-children="#header" css:content=".portlet-alerte #message"/> <before css:theme-children="#main" css:content=".portlet-alerte #warning-icon"/> </rules> ... </rules> Et on peut également mettre ces balises <rules /> en cascade : <rules css:if-content=".section-Members"> <rules css:if-content=".portlet-alerte"> <after css:theme-children="#header" css:content=".portlet-alerte #message"/> </rules> <rules css:if-content=".portlet-todo"> <after css:theme-children="#header" css:content=".portlet-todo #message"/> </rules> </rules> Conditions sur <theme /> On peut fournir plusieurs directives <theme /> : <theme href="news.html" css:if-content=".section-news"/> <theme href="members.html" css:if-content=".section-Members"/> <theme href="index.html"/> 182 Chapitre 16. Le theming Plone avec Diazo Plone pour les intégrateurs, Version 1.0.0 Les différentes conditions sont testées dans l’ordre où elles sont fournies, et c’est la première qui donne une correspondance qui est retenue. En revanche les directives <notheme /> ont toujours la priorité sur les directives <theme /> quel que soit l’ordre. Toutes les règles sont appliquées quelle que soit la directive <theme /> retenue sauf si on utilise l’encapsulation : <rules css:if-content=".section-news"> <theme href="news.html"/> <copy css:content="h2.articleheading" css:theme="h1"/> </rules> 16.1.8 Modification du thème à la volée On peut utiliser une règle pour injecter non pas du contenu mais du HTML statique : <after theme-children="/html/head" if="$isUserBirthday"> <style type="text/css"> * { font-family: Comic Sans MS; } </style> </after> On peut aussi modifier les éléments du thème. Par exemple : <replace css:theme="#details"> <dl id="details"> <xsl:for-each css:select="table#details > tr"> <dt><xsl:copy-of select="td[1]/text()"/></dt> <dd><xsl:copy-of select="td[2]/node()"/></dd> </xsl:for-each> </dl> </replace> va convertir un tableau en une liste de dt/dd. Note : dans cet exemple on utilise css:select directement dans l’expression XSL car le pré-compilateur Diazo va faire la conversion en XPath. 16.1.9 Modification du contenu à la volée On peut modifier le contenu en utilisant la directive <replace /> : <replace css:content="div#portal-searchbox input.searchButton"> <button type="submit"> <img src="images/search.png" alt="Search" /> </button> </replace> 16.1.10 Modification du résultat par <xsl /> Une fois toutes les règles appliquées, le rendu final peut encore être modifié par des directives <xsl />. Par exemple : <xsl:template match="input/@type[.=’submit’]"> <xsl:attribute name="class">btn</xsl:attribute> </xsl:template> 16.1. Diazo 183 Plone pour les intégrateurs, Version 1.0.0 va mettre class="btn" sur les inputs de type submit (btn étant la classe CSS Bootstrap pour les boutons, c’est un moyen intéressant de satisfaire le markup d’un framework comme Bootstrap sans devoir modifier de l’intérieur le markup produit par Plone). Pour ajouter une classe : <xsl:template match="div/@class[contains(., ’summary’)]"> <xsl:attribute name="class">draggable <xsl:value-of select="."/></xsl:attribute> </xsl:template> va ajouter la classe draggable à tous les div portant la classe summary. Autre exemple, pour transformer les portlets Plone dont le markup est : <dl> <dt>titre</dt> <dd>un item</dd> <dd>un autre item</dd> </dl> en un markup plus simple tel que : <div> <h6>titre</h6> <div> un item un autre item </div> </div> (notamment parce qu’il est utile d’avoir un wrapper du contenu du portlet en entier, pour le rendre collapsible par exemple). Cette transformation sera assurée par le template xsl suivant : <xsl:template match="dl[@class[contains(., ’portlet’)]]"> <div class="portlet"> <h6 class="portlet-header"> <xsl:copy-of select="./dt/*" /> </h6> <xsl:apply-templates select="./dd" /> </div> </xsl:template> Note : les directives <xsl /> doivent être placées à la racine de la balises <rules /> principale, et elles sont appliquées de façon inconditionnelle. 16.1.11 Factorisation On peut ré-utiliser des règles dans différents thèmes Diazo en utilisant la balise <xi:include />. Exemple : <xi:include href="standard-rules.xml" /> 16.1.12 Insertion de contenu externe Normalement le contenu est fourni par la page Plone correspondant à l’URL demandée. Mais en utilisant l’attribut href, on peut demander à une règle d’utiliser une autre page : 184 Chapitre 16. Le theming Plone avec Diazo Plone pour les intégrateurs, Version 1.0.0 <append css:theme="#right-column" css:content="#content" href="/Plone/Members" /> On peut même aller chercher une page servie par un autre serveur si on active le mode réseau dans les Paramètres avancés de Diazo : <append css:theme="#right-column" css:content="#current" href="http://www.plone.org/" /> Note : cela rend le site courant dépendant d’un service extérieur, c’est donc relativement risqué, car si ce serveur externe n’est pas disponible, le thème est cassé. On peut utiliser des méthodes d’insertion plus robustes si on dispose d’un frontal web proposant SSI ou ESI : <after css:theme-children="#left-column" css:content="#portlet" href="/extra.html" method="ssi"/> <after css:theme-content="#left-column" css:content="#portlet" href="/extra.html" method="esi"/> Insertion d’un fichier HTML du thème Avec cette même approche, on peut inclure un fichier HTML statique du thème en utilisant son chemin propre : <append css:theme="#right-column" css:content="body" href="/Plone/++theme++montheme/footer.html" /> 16.1.13 Bonnes pratiques et techniques standards Utiliser un framework CSS Diazo facilite énormément l’adoption d’un framework CSS puisqu’il suffit de déposer les fichiers du framework directement dans le dossier des ressources statiques du thème. L’intérêt d’utiliser un framework CSS (comme 960, Bootstrap, Foundation) a déjà été largement démontré, et ne fait pas l’objet de ce document. Plone en tant que back-office Avec Diazo, les fonctionnalités de gestion de contenu de Plone sont utilisées comme un back-office qui alimente la couche de rendu. Ainsi on va par exemple ajouter des portlets non pas pour les afficher en tant que portlets mais comme fournisseurs de contenu à tel élément du thème Diazo. Un exemple typique est l’utilisation de collective.portlet.sitemap pour fournir les entrées d’un menu déroulant. De même, on peut utiliser collective.masonry pour créer des conteneurs de portlets qui permettront l’alimenter tel ou tel bloc du modèle HTML. Supprimer les commentaires et le Lorem Ipsum Il peut être utilise de mettre dans les modèles HTML du thème des commentaires ou du texte de remplissage afin que son affichage en statique soit plus représentatif qu’un markup complètement vierge. Mais bien entendu on ne souhaite pas les voir apparaître lors du rendu des contenus. Une technique simple consiste à mettre une classe (par exemple drop) sur ces éléments : 16.1. Diazo 185 Plone pour les intégrateurs, Version 1.0.0 <div id="main-content" class="cell width-1"> <p class="drop"> Suave, mari magno turbantibus aequora ventis, e terra magnum alterius spectare laborem; non quia vexari quemquamst jucunda voluptas, sed quibus ipse malis careas quia cernere suavest. </p> </div> Et on les élimine grâce à une règle de ce type : <drop css:theme=".drop" /> Cela permet également de supprimer temporairement certaines partie du design. Supprimer les paragraphes vides L’éditeur TinyMCE laisse parfois des balises <p/> vides. Cette règle permet de les éliminer : <drop content="p[not(*) and (not(normalize-space()) or text() = ’&#160;’)]"/> Les éléments du <head/> Le tag <head/> produit par Plone contient de nombreux éléments importants voire obligatorei pour un bon comportement du site. En général on reprend les éléments suivants : <replace css:theme="title" css:content="title" /> <before css:theme-children="head" css:content="base" /> <before theme-children="/html/head" content="/html/head/meta" /> <before theme-children="/html/head" content="/html/head/link | /html/head/style | /html/head/comme <before theme-children="/html/head" content="/html/head/script" /> Note : on ne peut malheureusement pas mettre les scripts à la fin du body car cela casse un bon nombres de scripts inline. Accessoirement, on peut souhaiter éliminer le viewport (et s’appuyer sur le comportement du framework CSS retenu) : <drop content=’/html/head/meta[@name="viewport"]’/> On peut aussi alimenter les meta de réseaux sociaux comme Facebook ou Twitter (à moins d’utiliser un module Plone qui s’en charge bien entendu) : <after theme-children="/html/head/meta"> <meta property="og:image" content="http://www.monsite.fr/++theme++montheme/images/logo.png" /> <meta name="twitter:card" content="summary"> <meta name="twitter:site" content="@moncomptetwitter"> </after> Le snippet javascript pour les statistiques Le snippet javascript renseigné dans la configuration du site Plone (pour les statistiques GoogleAnalytics, ou Piwic, ou autre) n’est pas injecté dans le <head/> de Plone donc les règles précédentes ne le traite pas. Il faut ajouter : <after theme-children="/html/body" content="/html/body/div[@id=’visual-portal-wrapper’]/div/script 186 Chapitre 16. Le theming Plone avec Diazo Plone pour les intégrateurs, Version 1.0.0 Créer un tag englobant Dans cet exemple, on place le titre et la description dans un <div /> englobant : <replace css:content-children="#content" css:theme-children="#content"/> <before css:theme-children="#content"> <div id="wrapper"> <xsl:apply-templates css:select=".documentFirstHeading" mode="raw"/> <xsl:apply-templates css:select=".documentDesciption" mode="raw"/> </div> </before> <drop css:content=".documentFirstHeading"/> <drop css:content=".documentDesciption"/> Explications : – le <before /> insère le tag <div /> et 2 appels xsl permettent d’y ajouter le titre et la description, – les <drop /> évitent que le titre et la description soient répétés (puisqu’ils figurent dans #content), – le mode="raw" est nécessaire car les <drop /> sont appliqués avant le <before css:theme-children /> (en XSLT, le mode raw permet qu’un noeud soit traité plusieurs fois). Ajouter ou modifier des attributs Pour un ajout : <xsl:template match="a"> <xsl:copy> <xsl:attribute name="target">_blank</xsl:attribute> <xsl:copy-of select="@*" /> <xsl:apply-templates /> </xsl:copy> </xsl:template> Explications : – on copie l’élement, – on y ajoute l’attribut (ici target), – on recopie ensuite les attributs existants (y compris target s’il était déjà défini), – puis on insère les noeuds fils Pour une modification : <xsl:template match="img/@src[not(contains(., ’@@’))]"> <xsl:attribute name="src"><xsl:value-of select="." />/@@/images/image/thumb</xsl:attribute> </xsl:template> Autre exemple, supprimer une classe CSS (sans supprimer les autres) : <xsl:template match="form/@class[contains(., ’enableFormTabbing’)]"> <xsl:attribute name="class"><xsl:value-of select="concat(substring-before(., ’enableFormTabbin </xsl:template> Debugging Lorsqu’on fait fonctionner Zope en mode debug (à priori quand on l’a lancé avec bin/ploncectl fg), on peut ajouter des commandes diazo dans l’url : – ?diazo.debug=1 (par exemple http://localhost:8080/Plone?diazo.debug=1) va afficher à l’écran les traces d’éxécution de Diazo (les erreurs, les règles appliquées (en vert), les règles écratées (en rouge)) 16.1. Diazo 187 Plone pour les intégrateurs, Version 1.0.0 – ?diazo.off=1 (par exemple http://localhost:8080/Plone?diazo.off=1) va désactiver Diazo, de manière par exemple à pouvoir inspecter la page non thémée plus facilement. Accès spécial non-thémé La configuration avancée de Diazo (Configuration du site / Theming / Advanced Settings) permet de déclarer des noms de domaine pour lesquels Diazo ne sera pas activer. Par défaut, il y a 127.0.0.1. Ainsi on peut, si on le souhaite, fournir aux conributeurs un accès “back-office” sans theming. 16.2 Produit de skin Author Éric Bréhault (Makina Corpus) Created 2013-04-17 Version 1.0 16.2.1 Introduction La création d’un thème Diazo dans l’éditeur en ligne n’est pas une solution très solide, car même si on est en mesure d’exporter le design dans une archive (et donc de pouvoir en faire une sauvegarde, ou bien de faire un déploiement d’un serveur de développement vers un serveur de production), il est plus sain de gérer son thème dans un véritable produit Plone (qui pourra être géré dans Git ou SVN, qui pourra facilement être déployé par buildout, etc.). D’autre part, cela permet d’aller au-delà de ce que propose Diazo, comme par exemple, surcharger des composants de Plone, créer des viewlets, des portlets, changer les attributs du profil utilisateur, etc. 188 Chapitre 16. Le theming Plone avec Diazo Plone pour les intégrateurs, Version 1.0.0 16.2.2 Créer un produit pour son thème Diazo Créer le module Pour créer un produit de thème vierge, on va utiliser ZopeSkel qui permet d’initialiser des modules Python en se basant sur un modèle. On va utiliser le modèle standard plone. Aller dans src/, et lancer la commande : $ ../bin/zopeskel plone Donner un nom au module (par exemple : nomprojet.theme). Et garder les choix par défaut sauf pour : Register Profile (Should this package register a GS Profile) [False]: True Le module est créé dans src/nomprojet.theme. Ajouter ce nouveau module dans buildout.cfg : develop = ... src/nomprojet.theme eggs = ... nomprojet.theme Et faire tourner le buildout : $ bin/buildout -Nv Ajouter le thème Diazo Créer un dossier pour les ressources Diazo : $ mkdir src/nomprojet.theme/nomprojet/theme/static Télécharger le thème créé avec l’éditeur en ligne Diazo et le dé-zipper dans ce dossier. Modifier le configure.zcml pour déclarer le dossier static : <configure ... xmlns:plone="http://namespaces.plone.org/plone" > ... <plone:static name="nomprojet.theme" directory="static" type="theme" /> ... </configure> 16.2. Produit de skin 189 Plone pour les intégrateurs, Version 1.0.0 Compléter le profile GenericSetup Dans src/nomprojet.theme/nomprojet/theme/profiles/default/, il faut : – Ajouter la dépendance avec plone.app.theming dans metadata.xml : <?xml version="1.0"?> <metadata> <version>1000</version> <dependencies> <dependency>profile-plone.app.theming:default</dependency> </dependencies> </metadata> – Déclarer le thème, en créant theme.xml : <?xml version="1.0"?> <theme> <name>nomprojet.theme</name> <enabled>true</enabled> </theme> On peut alors lancer Zope, et installer le nouveau produit pour activer le thème. 16.2.3 Surcharger la skin de Plone Diazo permet de contrôler le rendu global du site. Mais si on souhaite modifier le rendu d’éléments situés en profondeur qui ne sont pas forcément accessibles par un sélecteur CSS précis ou bien une image (par exemple, le portrait par défaut des membres, defaultUser.png) qui sont fournis par la skin de Plone, il faut surcharger la skin de Plone. Note : On peut le faire depuis la ZMI en allant dans ./portal_skins et en utilisant le bouton Customize qui place la ressource dans le dossier custom. Pour les surcharger dans les sources de notre produit de thème, la méthode est la suivante : Créer un dossier src/nomprojet.theme/nomprojet/theme/skins/nomprojet_custom et y placer les ressources désirées. Déclarer ce dossier dans le configure.zcml : <configure ... xmlns:cmf="http://namespaces.zope.org/cmf" > ... <cmf:registerDirectory name="nomprojet_custom"/> </configure> Et le placer en première position par rapport aux autres layer de skins en créant src/nomprojet.theme/nomprojet/theme/profiles/default/skins.xml : <?xml version="1.0"?> <object name="portal_skins" allow_any="False" cookie_persistence="False" default_skin="nompro <object name="nomprojet_custom" meta_type="Filesystem Directory View" directory="nomprojet.theme:skins/nomprojet_custom"/> <skin-path name="nomprojet.theme" based-on="Sunburst Theme"> 190 Chapitre 16. Le theming Plone avec Diazo Plone pour les intégrateurs, Version 1.0.0 <layer name="nomprojet_custom" insert-after="custom"/> </skin-path> </object> On peut alors relancer Zope et ré-installer le produit depuis la configuration du site, et les éléments du dossier nomprojet_custom prendront la main sur la skin de Plone (ou sur celle de tout autre produit installé). 16.2.4 Surcharger des BrowserViews de Plone avec jbot De très nombreux composants de l’IHM de Plone sont fournis non pas par une skin mais par des BrowserViews. C’est le cas notamment des viewlets (qu’on peut voir lorsqu’on appelle l’url ./@@manage-viewlets). Note : Pour les surcharger depuis la ZMI, on peut aller dans ./portal_view_customizations. Pour les surcharger dans les sources de notre produit de thème, la méthode la plus simple est d’utiliser z3c.jbot (Just a Bunch of Templates). Tout d’abord il faut l’ajouter dans buildout.cfg : eggs = ... z3c.jbot Et faire tourner le buildout : $ bin/buildout -Nv Ensuite créer un dossier src/nomprojet.theme/nomprojet/theme/static/overrides. Déclarer ce dossier comme dossier jbot en : – modifiant le configure.zcml : <configure ... xmlns:browser="http://namespaces.zope.org/browser" > ... <include package="z3c.jbot" file="meta.zcml" /> <interface name="nomprojet.theme" interface="nomprojet.theme.interfaces.IThemeSpecific" type="zope.publisher.interfaces.browser.IBrowserSkinType" /> <browser:jbot directory="static/overrides" /> </configure> – créant interfaces.py : from plone.theme.interfaces import IDefaultPloneLayer class IThemeSpecific(IDefaultPloneLayer): """Marker interface that defines a Zope 3 browser layer and a plone skin marker. """ – et déclarant la layer dans le profil en créant src/nomprojet.theme/nomprojet/theme/profiles/default/brows 16.2. Produit de skin 191 Plone pour les intégrateurs, Version 1.0.0 <?xml version="1.0"?> <layers> <layer name="nomprojet.theme" interface="nomprojet.theme.interfaces.IThemeSpecific"/> </layers> Ensuite il faut placer dans le dossier src/nomprojet.theme/nomprojet/theme/static/overrides les templates qu’on veut surcharger en les renommant avec leur chemin complet vers l’original. Par exemple, pour surcharger colophon.pt de plone.app.layout, sachant que ce template se trouve dans viewlets, il faut le nommer plone.app.layout.viewlets.colophon.pt. Il faut ensuite relancer Zope et ré-installer le produit depuis la configuration du site. 16.2.5 Gérer les registres CSS et JS Pour des raisons de performances, il est toujours préférable de minimiser le nombre de JS et de CSS chargés par les pages de son site. Cela réduit le nombre de requêtes, et cela optimise l’effet de cache. Pour cela, Plone propose deux registres, portal_javascript et portal_css, qui permettent de : – déclarer les ressources qu’on souhaite charger, – les ordonner, – éventuellement, fournir des conditions qui déterminent quand on doit charger la ressources. À partir de ces informations, Plone va injecter les tags correspondants (<script>, <link>, etc.) dans le <head> des pages produites, et si Zope ne tourne pas en mode debug, les différents fichiers vont être (autant que possible) regroupées et compressés. Il est donc important que les CSS et JS principaux du produit de thème soient gérés par ce biais. Il faut va donc les enlever des modèles HTML (pour ne pas les charger en double). Puis, les déclarer dans ces registres. Pour cela, il faut créer un fichier src/nomprojet.theme/nomprojet/theme/profiles/default/jsregistry.xml <?xml version="1.0"?> <object name="portal_javascripts"> <javascript id="++theme++nomprojet.theme/js/theme.js" cacheable="True" compression="none" cookable="True" enabled="True" expression="request/HTTP_X_THEME_ENABLED | nothing" inline="False" insert-after="++resource++collective.js.leaflet/leaflet.js" /> </object> Et un fichier src/nomprojet.theme/nomprojet/theme/profiles/default/cssregistry.xml : <?xml version="1.0"?> <object name="portal_css"> <stylesheet id="++theme++nomprojet.theme/css/theme.css" applyPrefix="1" media=""/> <stylesheet 192 Chapitre 16. Le theming Plone avec Diazo Plone pour les intégrateurs, Version 1.0.0 id="++theme++nomprojet.theme/bootstrap/css/bootstrap.css" applyPrefix="1" media=""/> </object> Il faut ensuite relancer Zope, et ré-installer le produit depuis la configuration du site. Note : l’expression request/HTTP_X_THEME_ENABLED | nothing renvoie True uniquement si on utilise Diazo (cele permet de ne charger la ressource que lorsque le thème Diazo est actif et pas quand affiche Plone en direct). Il faut prendre garde à l’ordre des ressources et aux conditions : les ressources sont concaténées les unes après les autres dans l’ordre où elles sont placées tant que leurs conditions sont les mêmes. Si une ressource a une condition différente, cela va fermer le regroupement courant et créer un nouveau groupe. Donc si on veut avoir le moins de ressources à charger à la fin, il faut veiller à : – mettre le moins de conditions que possible, – si on en met, essayer d’en avoir le moins de différentes que possibles, – et ré-ordonnancer de manière à ce que les conditions identiques soient consécutives. En ce qui concerne les JS ou CSS qui ne sont pas utilisés globalement mais uniquement dans un modèle HTML spécifique, il peut être au contraire pertinent de ne pas les mettre dans les registres et de les laisser en dur dans le modèle HTML en question. Note : quand on utilise un framework CSS responsive, il est souvent nécessaire de désactiver la CSS mobile.css de Plone qui risque de produire de mauvais résultats . Pour cela on ajoute ceci à cssregistry.xml : <stylesheet id="mobile.css" enabled="False" /> 16.2. Produit de skin 193 Plone pour les intégrateurs, Version 1.0.0 194 Chapitre 16. Le theming Plone avec Diazo CHAPITRE 17 Ecrire des scripts Plone : bases Author Thomas Desvenain Created 2013-02-28 Version 0.1.0 – Introduction – Mon premier script – Créer un script – Le script par défaut – Mon premier script – Renvoyer un script en HTML – Naviguer dans les documents par script – Comment connaître la liste des méthodes disponibles sur un objet ? – Protéger le script – Suivi des modifications sur un script – Créer et gérer des contenus par script – On continue notre script – Copier des contenus – Publier des contenus – Les tools – Déplacer des contenus – Modifier des contenus / retrouver la valeur d’un champ – Supprimer des contenus – Connaître et exploiter les informations utilisateur – Accéder aux propriétés de l’utilisateur – Mettre en forme les dates / les vues standard – Modifier les propriétés de l’utilisateur – Exporter en csv des informations utilisateurs – Récupérer les rôles d’un utilisateur – Vérifier un privilège de l’utilisateur connecté – Utiliser le catalogue de Plone – Une première requête catalogue Copyright (C) 2013 Thomas Desvenain <thomas.desvenain AT gmail.com>. Chacun est autorisé à copier, distribuer et/ou modifier ce document suivant les termes de la licence Paternité-Pas d’Utilisation Commerciale-Partage des Conditions Initiales à l’Identique 2.0 France accessible à http ://creativecommons.org/licenses/by-nc-sa/2.0/fr Le code source présent dans ce document est soumis aux conditions de la « Zope Public License », Version 2.1 (ZPL). 195 Plone pour les intégrateurs, Version 1.0.0 THE SOURCE CODE IN THIS DOCUMENT AND THE DOCUMENT ITSELF IS PROVIDED “AS IS” AND ANY AND ALL EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. 17.1 Introduction Zope permet aux utilisateurs d’écrire en ligne des scripts. L’idée de départ était de permettre de réaliser de véritables applications en ligne. L’idée est devenue obsolète car elle ne permettait pas une qualité de déploiement et d’organisation du code telle qu’on peut l’avoir aujourd’hui avec les eggs. Il reste que grâce à cela on a hérité de fonctions disponibles suffisamment étendues pour rendre de grands services à un webmaster. Ce chapitre permettra à un développeur débutant de comprendre comment écrire de petits scripts pour traiter du contenu d’un site Plone. A la fin de cette formation, une personne qui n’a que quelques bases de programmation sera capable de réaliser des tâches scriptées comme par exemple : - déplacer toutes les actualités créées dans le site dans un seul et même dossier, créer des sous-dossiers dans un ensemble de dossiers, compter le nombre de documents récemment ajoutés dans une partie du site, produire un fichier csv reprenant le titre, l’auteur et la date de création de tous les document etc. Ce sera l’occasion d’aborder des notions essentielles telles que : - la structure de la ZODB, les tools, les types de contenu, le catalogue de Plone. Dans le chapitre suivant : Ecrire des templates Plone : bases, nous valoriserons visuellement des données et des indicateurs extraits à l’aide de scripts dans une template. 17.2 Mon premier script Nous allons écrire un premier script qui affiche simplement une “Table des matières” de votre site, en affichant la liste des dossiers à la racine, et la liste des sous-dossiers. 17.2.1 Créer un script Warning : Attention ! Comme pour toute opération, ne testez jamais vos scripts en production, essayez-les d’abord sur un serveur de tests ! Pour créer un script, vous avez besoin d’aller dans la ZMI : : - connectez-vous en administrateur, - allez dans la configuration du site, - cliquez sur Interface d’administration de Zope (ZMI) Vous entrez dans le backoffice de Zope : la Zope Management Interface. A partir de là, vous pouvez naviguer dans vos données, et consulter les ‘tools’ (sur lesquels nous reviendrons plus tard). Vous pouvez ajouter ici votre premier script. Pour cela, sélectionnez Script dans la sélection d’ajout, en haut à droite, et cliquez sur ‘Add’. Appelez le script ‘table_of_contents’ et ajoutez-le. Vous arrivez sur une page d’édition permettant d’éditer le code du script. 196 Chapitre 17. Ecrire des scripts Plone : bases Plone pour les intégrateurs, Version 1.0.0 Note : Pour éditer vos scripts, nous vous conseillons d’utiliser Zope External Editor. Une fois celui-ci installé, vous éditez le script en cliquant sur le crayon à côté du nom du script. Vous bénéficiez ainsi de tous les avantages d’un éditeur de texte (notamment la coloration syntaxique), largements supérieurs à un simple textarea pour vous aider à saisir vos lignes de code... 17.2.2 Le script par défaut Par défaut, un script par défaut est créé qui affiche simplement des informations sur le script lui-même. Vous pouvez le tester en cliquant sur l’onglet “test” (pour plus de commodité ouvrez-le dans une nouvelle fenêtre). Nous allons commenter ce script. from Products.PythonScripts.standard import html_quote La première chose que vous notez, c’est qu’il est possible de réaliser des imports. Attention, les imports possibles sont réservés à certains modules, classes et fonctions. Pour des raisons de sécurité, en effet, seule une partie de l’API de zope est disponible en ligne. Les modules python en dehors de Zope ainsi que de nombreuses fonctions de Zope sont indisponibles. Vous êtes ainsi assurés, par exemple, que les managers de vos sites n’auront pas accès à des fonctions du système (os, sys, etc). Quand vous essayerez d’utiliser ou d’importer un élément non autorisé, vous aurez une erreur “Privilèges insuffisants” request = container.REQUEST response = request.response Un certain nombre de noms sont disponibles de base dans un script. Ils concernent des éléments permettant de retrouver le contexte du script : – container : le conteneur du script, – context : le contexte d’exécution du script (cf plus loin), – script : l’objet script lui-même. print "This is the", script.meta_type, ’"%s"’ % script.getId(), ... return printed return printed fait que le script va renvoyer l’ensemble du texte qui a été imprimé durant l’exécution du script. 17.2.3 Mon premier script Nous allons écrire un premier script permettant d’afficher une table des matières du site. folders = container.values() for folder in folders: if folder.portal_type == ’Folder’: print folder.Title(), "\n" for element in folder.values(): print " ", element.Title(), "\n" return printed Vous savez peut-être déjà que dans Zope, les éléments du site (documents, dossiers, etc) sont également des objets, des instances de classes qui fournissent des méthodes. Ces méthodes permettent de retrouver des informations sur le contenu de l’objet ou d’effectuer des traitements. Ici, la méthode “Title” permet de récupérer le titre du document ou du dossier. Les données d’un élément sont, quant à elles, des attributs de cet objet. 17.2. Mon premier script 197 Plone pour les intégrateurs, Version 1.0.0 17.2.4 Renvoyer un script en HTML Sachez que votre script peut renvoyer du HTML. A priori vous n’aurez jamais besoin de cela car vous écrirez une template. Vous pouvez néanmoins tester le script suivant : folders = container.values() for folder in folders: if folder.portal_type == ’Folder’: print "<h1>", folder.Title(), "</h1>" print "<ul>" for element in folder.values(): print "<li>", element.Title(), "</li>" print "</ul>" return printed Votre script peut aussi renvoyer tout autre format texte, comme par exemple un fichier csv. Nous verrons un exemple plus loin. Mais la plupart du temps, un script sert à renvoyer une structure python : une liste d’objets, un dictionnaire, etc. Dans ce chapitre, à des fins illustratives nous écrivons des scripts qui retournent du texte, mais dès que nous saurons écrire des templates, nous utiliserons les scripts de manière plus habituelle. 17.2.5 Naviguer dans les documents par script La méthode values() permet de récupérer la liste des contenus d’un dossier. La méthodes keys() permet de récupérer la liste des identifiants des contenus du dossier. Les dossiers se comportent comme des dictionnaires et comme des objets. Si vous avez un dossier ‘documents’ dans le container, vous pouvez y accéder par l’expression : container[’documents’] ou container.documents. Ainsi, le bloc de code suivant est strictement identique au précédent. for folder_id in container.keys(): if container[folder_id].portal_type == ’Folder’: print container[folder_id].Title(), "\n" for subfolder_id in container[folder_id].keys(): print " ", container[folder_id][subfolder_id].Title(), "\n" return printed Note : sur un objet, la méthode getParentNode() et l’attribut aq_parent permettent de récupérer le parent. 17.2.6 Comment connaître la liste des méthodes disponibles sur un objet ? Il est indispensable d’apprendre à retrouver quelles sont les méthodes disponibles sur un objet. Il existe pour cela un module : Products.DocFinderTab, qui ajoute, dans la ZMI, un onglet ‘Doc’ sur chaque objet. Cet onglet permet de retrouver la liste des classes de base de l’objet et les méthodes disponibles. 17.2.7 Protéger le script Warning : Très important ! Le script que vous venez de créer est disponible pour tous les utilisateurs du site, même non connectés. Il est extrêmement dangereux de ne pas protéger un script, en particulier si celui-ci opère des traitements sur . Pour exécuter un script, il faut avoir la permission ‘View’ sur l’objet. Allez dans l’onglet ‘Security’ de votre script, ligne ‘View’ et sélectionnez ‘Manager’ uniquement. 198 Chapitre 17. Ecrire des scripts Plone : bases Plone pour les intégrateurs, Version 1.0.0 17.2.8 Suivi des modifications sur un script L’onglet History, sur un script, vous permet d’afficher la liste des modifications effectuées, de réaliser des comparatifs et de récupérer des anciennes versions. 17.3 Créer et gérer des contenus par script Imaginons que vous utilisez un site Plone pour gérer l’intranet des services de votre entreprise. Vous avez créé un dossier pour chaque service. Vous souhaitez que chaque service rassemble ses factures par mois dans un dossier. Tant qu’à faire, autant que la structure de ce dossier soit la même dans chaque service, à savoir “factures/2013/02” (“Factures / 2013 / Février 2013” pour le titre). Vous vous dites que vous pourriez écrire un script que vous passerez chaque mois et qui créera les bons dossiers. Et vous avez raison, car Plone permet de faire cela très facilement ! Voici un premier script qui va créer le dossier factures dans chaque dossier principal à la racine de votre Plone. Créez un script generate_invoices à la racine de votre ZMI : for folder in container.values(): if folder.portal_type != ’Folder’: continue # on boucle sur la liste des contenus dont le portal_type est ’Folder’ if ’factures’ not in folder: # on vérifie que l’object identifié ’factures’ n’existe pas déjà folder.invokeFactory(’Folder’, ’factures’, title="Factures", description="Factures du serv print "factures créé dans %s" % folder.absolute_url() # %s est remplacé dans la chaine par return printed Testez ensuite le script (pour qu’il fonctionne, vous devez avoir quelques dossiers à la racine de votre site Plone). La première ligne permet de boucler sur la liste des contenus. Ensuite, si on voit que le contenu n’est pas un dossier, on reprend la boucle (mot clé continue). if ’factures’ not in folder permet de vérifier qu’il n’y a pas dans le dossier un élément dont l’identifiant est ‘factures’. Cela équivaut à if ’factures’ not in folder.keys() ou if not hasattr(folder, ’factures’) ou encore if not folder.has_key(’factures’). folder.invokeFactory(’Folder’, ’factures’, title="Factures", description="Factures du service") est l’expression la plus intéressante ! La méthode invokeFactory sur un dossier permet ici de créer un sous-contenu de portal_type ‘Folder’ avec un identifiant ‘factures’, un titre : ‘Factures’ et une description : “Factures du service”. Les arguments nommés (keyword args, ou kwargs) permettent de donner une valeur aux champs lors de la création de l’objet. La méthode invokeFactory vérifie les droits d’ajouts. Si l’utilisateur qui ajoute le script n’a pas le droit d’ajouter ce type de contenu, ou si le script essaye d’ajouter un contenu interdit à cet endroit (restriction), le script renverra une erreur de privilège. Note : Rappel sur les types de contenu Les types de contenus sont ce qui structure l’information sous Plone. Il y a deux “espèces” de types de contenu : les types de contenu “Archetypes” et les types de contenu “Dexterity”. Les seconds ont la particularité de pouvoir être définis en ligne. Les premiers sont plus anciens et, à l’heure où ces lignes sont écrites, les types de contenu de base de Plone sont encore des contenus “Archetypes”. Qu’il soit Archetypes ou Dexterity, un type de contenu est composé de deux choses : une factory et un schema. La factory, disponible dans le tool portal_types de la ZMI, contient des informations sur le type de contenu telles que son nom, sa description, les sous-contenus autorisés, les modes d’affichage. Le schéma contient la liste des champs du type de contenu, qui détermine les informations que peuvent contenir les contenus de ce type. Il permet de générer les formulaires d’ajout et de modification. 17.3. Créer et gérer des contenus par script 199 Plone pour les intégrateurs, Version 1.0.0 Pour aller plus loin, vous pouvez essayer de générer par script des contenus créés via dexterity (Pour créer des types de contenus Dexterity, allez dans Configuration du site > Types de contenu Dexterity). absolute_url() est une méthode qui permet de récupérer l’url de l’objet. Un autre méthode très utile est la méthode getPhysicalPath() qui permet de récupérer (sous la forme d’un tuple), le chemin d’accès zope à l’objet. 17.3.1 On continue notre script Nous enrichissons maintenant notre script pour qu’il crée des dossiers en fonction du mois actuel. from DateTime import DateTime today = DateTime() year = str(today.year()) month = "%02d" % today.month() # permet d’avoir des affichages du type "01", "02", ... "10", "11", for folder in container.values(): if folder.portal_type != ’Folder’: continue # on boucle sur la liste des contenus dont le portal_type est ’Folder’ if ’factures’ not in folder: # on vérifie que l’object identifié ’factures’ n’existe pas déjà folder.invokeFactory(’Folder’, ’factures’, title="Factures", description="Factures du serv print "’factures’ créé dans %s" % folder.absolute_url() if year not in folder.factures: folder.factures.invokeFactory(’Folder’, year, title=year, description="Factures de l’année month_id = ’%s-%s’ % (month, year) if month_id not in folder.factures[year]: folder.factures[year].invokeFactory(’Folder’, month_id, title=month_id) print "%s créé dans %s" % (month_title, folder.factures[year].absolute_url()) return printed DateTime est un module de dates spécifique à zope que l’on peut utiliser dans les scripts. Il prend en paramètre soit rien (auquel cas l’objet correspond à la date du jour) soit une date au format (“YYY/MM/DD”). 17.3.2 Copier des contenus Imaginons que vous ayez créé un modèle excel de synthèse annuelle “factures-synthese-anuelle.ods” des factures que vous avez stocké dans un dossier “modeles”. Vous souhaitez qu’il soit copié à chaque fois dans le dossier de factures annuel. C’est possible ! Vous allez ajouter dans la boucle les lignes suivantes : modeles_folder = container.modeles cb = container.modeles.manage_copyObjects([’factures-synthese-anuelle.ods’]) for folder in container.values(): if folder.portal_type != ’Folder’: continue ... if ’factures-synthese-anuelle.ods’ not in folder.factures[year]: folder.factures[year].manage_pasteObjects(cb) print "factures-synthese-anuelle.ods copié dans %s" % folder.factures[year].absolute_url() Le copier-coller et le couper-coller fonctionnent suivant un système de clipboard : on crée un clipboard que l’on copie ou déplace ensuite (aucun traitement n’est fait tant qu’on ne sait pas où le contenu est destiné à être coupé ou copié). 200 Chapitre 17. Ecrire des scripts Plone : bases Plone pour les intégrateurs, Version 1.0.0 17.3.3 Publier des contenus Nous souhaitons que la synthèse anuelle soit immédiatement publiée if ’factures-synthese-anuelle.ods’ not in folder.factures[year]: cb = container.modeles.manage_copyObjects([’factures-synthese-anuelle.ods’]) folder.factures[year].manage_pasteObjects(cb) container.portal_workflow.doActionFor(folder.factures[year][’factures-synthese-anuelle.ods’], print "factures-synthese-anuelle.ods copié dans %s" % folder.factures[year].absolute_url() Nous ne ferons pas de rappel ici sur les workflows, qui méritent un chapitre à part entière. Disons simplement que nous appliquons la transition “publish” (“Publier”) sur le contenu. Si pour une raison ou une autre la transition n’est pas disponible, ou si l’utilisateur qui lance le script n’a pas le droit de passer cette transition, le script renverra une erreur. 17.3.4 Les tools À la racine de la ZMI, vous avez dû observer un certain nombre d’objets spéciaux, nombre d’entre eux ayant un id commençant par portal_. Ce sont les tools. Les tools offrent deux types de service : ils permettent de stocker des propriétés utiles sur l’ensemble du site, et ils fournissent des méthodes. Pour consulter les méthodes disponibles, Pour récupérer un tool, il faut faire soit : portal_workflow = portal.portal_workflow #(où portal est l’objet ’site’) soit : from Products.CMFCore.utils import getToolByName portal_workflow = getToolByName(context, ’portal_workflow’) #(où context est n’importe quel objet Les tools ne sont pas la seule manière d’avoir accès à des méthodes de l’api. Il existe aussi les vues standard, que nous aborderons plus loin. 17.3.5 Déplacer des contenus Certains services avaient pris les devants en créant dans leur dossier un dossier “facturation” dans lequels ils avaient placé en vrac les factures. Vous souhaitez déplacer ceux qui ont été créés en février dans le nouveau dossier (vous pourrez améliorer votre script pour traiter aussi les anciens !). Dans un nouveau script : for folder in container.values(): if folder.portal_type != ’Folder’: continue if ’facturation’ in folder: cb = folder.facturation.manage_cutObjects([ content.getId() for content in folder.facturation.values() if DateTime(’2013/02/01 00:00’) < content.created() < DateTime(’2013/02/28 23: folder.factures[’2013’][’02-2013’].manage_pasteObjects(cb) En paramètre de la méthode manage_cutObjects, nous avons une comprehension list, qui génère la liste des ids des objets dont la date de création est située entre le 1er février 2013 et le 31 décembre 2013 à 23h59 (donc dans le mois). – getId() est une la méthode qui renvoit l’identifiant de l’objet. – created() renvoit la date de création 17.3. Créer et gérer des contenus par script 201 Plone pour les intégrateurs, Version 1.0.0 17.3.6 Modifier des contenus / retrouver la valeur d’un champ Imaginons que nous voulions changer le titre de tous les dossiers “02-2013” en “Février 2013”, nous allons écrire ceci : for folder in container.values(): if folder.portal_type != ’Folder’: continue folder[’factures’][’2013’][’02-2013’].setTitle("Février 2013") folder[’factures’][’2013’][’02-2013’].reindexObject() Pour modifier le contenu d’un champ (avec archetypes), en général la méthode est “set + le nom du champ dont la première lettre passe en majuscule”. la méthode suivante fonctionne également la plupart des cas : obj = folder[’factures’][’2013’][’02-2013’] obj.getField(’title’).set(obj, "Février 2013") Pour récupérer la valeur d’un champ, sous archetypes en général la méthode (accesseur) permettant de la récupérer est nommée : “getChamp”, avec le nom du champ où la première lettre est mise en majuscule. Les cas particuliers sont très fréquents. Ainsi : – Title() pour le titre – Description() pour la description – created() pour la date de création (champ CreationDate) – modified() pour la date de modification (champ ModificationDate) – Creator() pour l’auteur du document (le login de l’utilisateur qui l’a ajouté) – Language() pour la langue du document – etc. La plupart du temps (c’est notamment vrai avec dexterity), on peut récupérer la valeur sur l’objet en prenant l’attribut correspondant au nom du champ. print obj.title Warning : Ce code (en fait, tout le code qu’on écrit depuis le début) n’est pas du tout optimal. En général, on évitera de faire des “values()” et de parcourir les dossiers pour atteindre les éléments souhaités, on passera par une “requête catalogue” qui nous permet d’atteindre les éléments souhaités via une recherche à critères. Nous verrons cela lors de la 3e partie de ce chapitre. Note : Exercice : Détectez les dossiers de niveau 1 et 2 qui sont vides, affichez leur titre et leur URL et le login de l’utilisateur qui l’a créé. Indiquez ceux qui parmi eux ont été créés il y a plus d’un mois. 17.3.7 Supprimer des contenus Nous allons écrire un script pour supprimer tous les contenus que nous avons créé ! Le script suivant supprime tous les dossiers factures. for folder in container.values(): if folder.portal_type != ’Folder’: continue if ’factures’ in folder: folder.manage_delObjects([’factures’]) print "factures supprimé dans %s" % folder.absolute_url() return printed 202 Chapitre 17. Ecrire des scripts Plone : bases Plone pour les intégrateurs, Version 1.0.0 17.4 Connaître et exploiter les informations utilisateur Vous avez quelques trucs pour produire des éléments, récupérer de l’information sur ces éléments. Voyons maintenant comment récupérer des informations sur les utilisateurs. 17.4.1 Accéder aux propriétés de l’utilisateur Note : Avant tout, nous, allons cesser de créer des scripts directement à la racine du portail (car c’est parfois difficile de s’y retrouver). Nous allons les créer en tant que layer dans le portal_skins. Allez dans l’objet portal_skins. Vous voyez la liste des skins, qui sont des dossiers. Ces skins ont un système de priorités. Un layer est un objet disponible partout sur le site. Si plusieurs layers ont le même nom, c’est celui qui est dans la skin prioritaire qui est utilisé. Les priorités des skins sont indiquées dans l’onglet “Properties” du portal_skins. La skin custom est une skin éditable en ligne qui est toujours prioritaire sur les autres. Allez dans “le custom” et faites “Add -> Script”. Attention ! Ne laissez pas trainer des scripts dangereux dans le custom sans les avoir protégés ! Notre premier script va afficher quelques informations sur l’utilisateur logué. Nous l’appelerons : authenticated_user_infos. from Products.CMFCore.utils import getToolByName member = getToolByName(context, ’portal_membership’).getAuthenticatedMember() print "Login de l’utilisateur : ", member.getId() print "Email : ", member.getProperty(’email’) print "Nom complet : ", member.getProperty(’fullname’) return printed Autorisez ce script pour les utilisateurs ‘Member’. Le tool portal_membership est celui qui offre les services permettant d’accéder aux utilisateurs (liste des utilisateurs, utilisateur connecté, etc) et de vérifier leurs droits. La méthode getProperty permet de récupérer une propriété de l’utilisateur. La liste des propriétés disponibles est disponible dans le tool portal_memberdata. Vous pouvez tester ce script avec plusieurs utilisateurs. Nous allons maintenant faire un script qui permet de retrouver les informations sur un utilisateur, suivant un paramètre de la requête. Créez un nouveau script user_infos. Vous avez peut-être vu le champ “Parameter List” sur le formulaire du script. Complétez-le avec user_id=None, puis saisissez le code suivant : from Products.CMFCore.utils import getToolByName member = getToolByName(context, ’portal_membership’).getMemberById(user_id) print "Login de l’utilisateur : ", member.getId() print "Email : ", member.getProperty(’email’) print "Nom complet : ", member.getProperty(’fullname’) print "Dernière connexion : ", member.getProperty(’login_time’) print "Avant-dernière connexion : ", member.getProperty(’last_login_time’) print "Groupes de l’utilisateur : ", ", ".join(member.getGroupIds()) or "Aucun" return printed Quand vous testez le script, un formulaire est mis à votre disposition. Mais l’usage réel est d’appeler directement l’URL avec la valeur en paramètre. La méthode getMemberById permet de trouver un utilisateur suivant son identifiant. L’objet utilisateur contient, en plus de la méthode getProperty, un certain nombre de méthodes permettant de retrouver les groupes auxquels il appartient : getGroups(), getGroupIds(), etc. Le tool portal_groups, qui fonctionne à l’image du tool portal_membership, permet de récupérer l’information sur les groupes. 17.4. Connaître et exploiter les informations utilisateur 203 Plone pour les intégrateurs, Version 1.0.0 17.4.2 Mettre en forme les dates / les vues standard Dans notre affichage, les dates sont difficiles à lire, et exprimées dans un standard international. Comme tout système de publication multilingue, Plone fournit un outil pour exprimer les dates dans un format local. C’est un exemple - très utilisé - de service rendu par une vue standard de plone (en l’occurence la vue “plone”). Pour accéder à une vue standard depuis un script, on utilise la méthode restrictedTraverse. Nous expliquerons un peu plus en détail plus loin la notion de traversing - dans le chapitre sur les templates, qui en font un usage intensif. Disons pour l’instant qu’il s’agit de la méthode générique pour accéder à un élément depuis un objet Zope : un contenu depuis un contenant, une vue ou un script depuis un objet, etc. from Products.CMFCore.utils import getToolByName member = getToolByName(context, ’portal_membership’).getMemberById(user_id) plone_view = context.restrictedTraverse(’@@plone’) print "Login de l’utilisateur : ", member.getId() print "Email : ", member.getProperty(’email’) print "Nom complet : ", member.getProperty(’fullname’) print "Dernière connexion : ", plone_view.toLocalizedTime(member.getProperty(’login_time’), long_f print "Avant-dernière connexion : ", plone_view.toLocalizedTime(member.getProperty(’last_login_tim print "Groupes de l’utilisateur : ", ", ".join(member.getGroupIds()) or "Aucun" return printed Une référence complète des vues standard est disponible dans la partie ‘http ://docs.ecreall.com/developpeur‘_ développeur de ce site. 17.4.3 Modifier les propriétés de l’utilisateur Nous allons écrire un script qui permet de modifier les adresses email de tous les utilisateurs, afin que tous les emails soient remplacés par votre propre adresse, avec un préfixe. Très utile (voire indispensable) quand on récupère une base de production sur un serveur de tests. from Products.CMFCore.utils import getToolByName mtool = getToolByName(context, ’portal_membership’) members = mtool.listMembers() plone_utils = getToolByName(context, ’plone_utils’) for member in members: member_id = member.getId() old_email = member.getProperty(’email’) new_email = "monemail+%[email protected]" % member_id if old_email != new_email: plone_utils.setMemberProperties(member, email=new_email) print "Changed %s email : %s -> %s" % (member_id, old_email, mtool.getMemberById(member_id return printed Vous observez l’utilisation de la méthode setMemberProperties du tool plone_utils pour indiquer les nouvelles valeurs de propriétés utilisateur. Warning : Ce script aura des comportements inattendus si vous utilisez un plugin qui ne permet pas de sortir la liste des membres sans recherche préalable (type plugin ldap). 17.4.4 Exporter en csv des informations utilisateurs Imaginons que vous souhaitiez simplement exporter dans un fichier la liste des emails des utilisateurs du site. Nous allons réaliser pour cela un export CSV. Créez ce script all-emails.csv. 204 Chapitre 17. Ecrire des scripts Plone : bases Plone pour les intégrateurs, Version 1.0.0 from Products.CMFCore.utils import getToolByName users = getToolByName(context, ’portal_membership’).listMembers() response = context.REQUEST.response response.setHeader(’Cache-Control’, ’no-cache’) response.setHeader(’Pragma’, ’no-cache’) response.setHeader( ’Content-type’, ’application/vnd.ms-excel;charset=windows-1252’) response.setHeader( ’Content-disposition’, ’attachment; filename="all-emails.csv"’) print ’"Login";"Nom complet";"email"’ for user in users: print ’"%s";"%s";"%s"’ % ( user.getId(), user.getProperty(’fullname’).decode(’utf-8’).encode(’windows-1252’), user.getProperty(’email’)) return printed Warning : Ce script aura des comportements inattendus si vous utilisez un plugin qui ne permet pas de sortir la liste des membres sans recherche préalable (type plugin ldap). Ce script introduit quelques nouvelles notions. L’objet REQUEST est un objet qui contient des informations sur la requête de l’utilisateur (url, ip, referer, paramètres de formulaire...). Pour en connaître le contenu, vous n’aurez qu’à imprimer REQUEST.items(). Dans un script, REQUEST est disponible comme attribut de tous les objets, notamment le context. L’objet response est un object qui permet de caractériser la réponse à renvoyer à l’utilisateur. Il permet de définir une redirection, de définir les headers, etc. Ici, nous indiquons que le rendu est un fichier csv optimisé pour excel (encodé en windows-1252) et qu’il n’est pas mis en cache. Exercice : écrivez un script permettant d’exporter en csv la liste des utilisateurs qui ne se sont pas logués depuis au moins un an, avec la date de dernière connexion. (Astuce : Il y a un an = DateTime() - 365. Si votre site est ouvert depuis moins de temps que ça, vous pouvez changer la contrainte ;)) 17.4.5 Récupérer les rôles d’un utilisateur Nous allons écrire un script qui permet d’afficher les rôles d’un utilisateur sur un objet donné. Cela peut être très utile pour comprendre l’origine d’un problème (pourquoi l’utilisateur n’a pas accès à ce document ? est-ce un problème de paramétrage de ses droits ou est-ce un bug ?) Créez le script get_userroles avec un paramètre user_id. user = context.portal_membership.getMemberById(user_id) print "Roles de %s : %s" % (user_id, user.getRolesInContext(context)) return printed La méthode getRolesInContext permet de récupérer la liste des rôles d’un utilisateur sur l’objet en paramètre. Allez sur n’importe qel document ou dossier de votre site, ajoutez get_user_roles à l’URL : vous obtenez un résultat en fonction du contexte. L’objet context est bien l’élément dans le contexte duquel vous exécutez le script. 17.4.6 Vérifier un privilège de l’utilisateur connecté Vous pouvez vérifier si, oui ou non, l’utilisateur connecté a un privilège sur un élément. Le script suivant permet de montrer si l’utilisateur connecté a le droit d’ajouter, de modifier, de reviewer. 17.4. Connaître et exploiter les informations utilisateur 205 Plone pour les intégrateurs, Version 1.0.0 Voici un script user_privileges : from Products.CMFCore.utils import getToolByName mtool = getToolByName(context, ’portal_membership’) user = mtool.getAuthenticatedMember() print "Vous avez les rôles : ", ", ".join(user.getRolesInContext(context)) print "Vous avez le droit de :" print "Voir : ", mtool.checkPermission(’View’, context) and "oui" or "non" print "Modifier : ", mtool.checkPermission(’Modify portal content’, context) and "oui" or "non" print "Modérer : ", mtool.checkPermission(’Review portal content’, context) and "oui" or "non" print "Ajouter du contenu : ", mtool.checkPermission(’Add portal content’, context) and "oui" or " return printed Connectez vous avec d’autres utilisateurs et essayez le script un peu partout, en ajoutant /user_privileges aux adresses des contenus. Exercice : réalisez un script permettant, quand on l’applique sur un dossier, d’avoir la liste des utilisateurs ayant au moins un rôle Contributeur, Modérateur ou Editeur, avec leurs emails. Info : la méthode folder.users_with_local_role(role) renvoit la liste des utilisateurs ayant ce role défini localement sur le dossier. Si vous utilisez cette méthode, pensez au fait que le rôle peut également être hérité du parent. 17.5 Utiliser le catalogue de Plone Ce chapitre n’est pas un cours sur le catalogue de Plone. Nous ferons néanmoins quelques rappels : – tous les contenus de Plone font l’objet d’un enregistrement dans un catalogue, qui est le tool portal_catalog, – il est possible de retrouver des contenus de plone via des recherches multi-critères, – il est considérablement moins couteux de rechercher et d’exploiter un enregistrement dans le catalogue que de parcourir le site jusqu’à trouver un document et exploiter les données de celui-ci ; tout code destiné à être utilisé régulièrement DOIT privilégier le catalogue sur le parcours du site. – la liste des critères de recherche disponibles est dans l’onglet Index du portal_catalog, et la liste des métadonnées disponibles sur les enregistrements est dans l’onglet Metadata. Nous allons écrire un script qui permet de retrouver la liste des 50 derniers éléments créés par un utilisateur. Créez un script qui prend en paramètre user_id. 17.5.1 Une première requête catalogue Ecrivez ce premier script last_documents avec un paramètre user_id : from Products.CMFCore.utils import getToolByName portal_catalog = getToolByName(context, ’portal_catalog’) brains = portal_catalog.searchResults(Creator=user_id, sort_on=’created’, # le tri se fait sur l’index ’created’ (d sort_order=’reverse’, # le tri est inversé (antéchronologiqu sort_limit=50) # on limite à 50 résultats for brain in brains: print brain.Title or brain.getId, " ", brain.getURL() # On affiche la métadonnée Title et on c return printed La méthode searchResults prend les critères en arguments nommés. Nous présentons ici un critère classique (Creator) et les trois critères de tri. On accède aux métadonnées sur l’enregistrement via l’appel à un attribut. En plus des attributs-métadonnées, le brain dispose de trois méthodes utiles : – getURL() -> renvoit l’URL absolue du document – getPath() -> renvoit le chemin d’accès zope – getObject() -> renvoit l’objet 206 Chapitre 17. Ecrire des scripts Plone : bases Plone pour les intégrateurs, Version 1.0.0 Un aperçu un peu plus complet est disponible ici : Querying the catalog A des fins illustratives, nous présentons ici un script qui affiche l’ensemble des documents modifiés depuis un mois dans le dossier où est lancé le script, et affiche le total de résultats. from Products.CMFCore.utils import getToolByName portal_catalog = getToolByName(context, ’portal_catalog’) brains = portal_catalog.searchResults(path="/".join(context.getPhysicalPath()), # critère chemin d portal_type=(’File’, ’Document’), # critère sur le type : Fi # entre aujourd’hui et il y a 31 jours (on pourrait écrire p modified={’query’: (DateTime() - 31, DateTime()), ’range’: ’ sort_on=’modified’, # le tri se fait sur l’index ’modified’ sort_order=’reverse’, # le tri est inversé (antéchronologiqu ) # on limite à 50 résultats print "Total : ", len(brains) for brain in brains: print brain.Title, " ", brain.getURL() # On affiche la métadonnée Title et on calcule l’url du return printed Voici un script, que nous appellerons all-contents.csv. Il exporte en csv une liste des documents contenus dans le dossier où il est appliqué, et récursivement. from Products.CMFCore.utils import getToolByName response = context.REQUEST.response response.setHeader(’Cache-Control’, ’no-cache’) response.setHeader(’Pragma’, ’no-cache’) response.setHeader( ’Content-type’, ’application/vnd.ms-excel;charset=windows-1252’) response.setHeader( ’Content-disposition’, ’attachment; filename="all-contents.csv"’) portal_catalog = getToolByName(context, ’portal_catalog’) brains = portal_catalog.searchResults(path="/".join(context.getPhysicalPath()), # critère chemin d portal_type=(’File’, ’Document’, ’Event’, ’News’), # critère ) print ’"Path";"Titre";"Auteur";"MAJ"’ for brain in brains: print ’"%s";"%s";"%s";"%s"’ % (brain.getPath(), brain.Title.decode(’utf-8’).encode(’windows-12 return printed Exercices : – Créez un script qui produit un fichier csv, qui indique, pour chaque utilisateur, le nombre d’élements qu’il a créés depuis 2 ans et depuis la création du site, et un lien vers le dernier document qu’il a créé. – Créez un script qui compte le nombre de documents et de fichiers dans chaque dossier à la racine du site Pour ces exercices, vous devrez faire plusieurs requêtes catalogue dans le même script ! On le voit, les scripts sont très utiles dès lors qu’il s’agit d’établir rapidement des indicateurs sur l’utilisation de son site. Nous allons maintenant apprendre à valoriser sous forme d’affichage html les données que nous avons appris à constituer : Ecrire des templates Plone : bases. 17.5. Utiliser le catalogue de Plone 207 Plone pour les intégrateurs, Version 1.0.0 208 Chapitre 17. Ecrire des scripts Plone : bases CHAPITRE 18 Ecrire des templates Plone : bases Author Thomas Desvenain Created 2013-02-28 Version 0.1.0 – – – – – – – – – – Introduction Ma première template Appel à un script Utiliser la master template de Plone Utiliser une structure plus complexe dans une template Appeler une template depuis une autre template Exercices Ecrire la template sous la forme d’une vue Une vue pour un export csv Une viewlet pour ajouter un lien vers une vue – Ma première viewlet – Exercices Copyright (C) 2013 Thomas Desvenain <thomas.desvenain AT gmail.com>. Chacun est autorisé à copier, distribuer et/ou modifier ce document suivant les termes de la licence Paternité-Pas d’Utilisation Commerciale-Partage des Conditions Initiales à l’Identique 2.0 France accessible à http ://creativecommons.org/licenses/by-nc-sa/2.0/fr Le code source présent dans ce document est soumis aux conditions de la « Zope Public License », Version 2.1 (ZPL). THE SOURCE CODE IN THIS DOCUMENT AND THE DOCUMENT ITSELF IS PROVIDED “AS IS” AND ANY AND ALL EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. 18.1 Introduction Ce chapitre fait suite au chapitre Ecrire des scripts Plone : bases, notamment dans son objectif de permettre à des webmaster Plone débutants en programmation de réaliser en ligne des outils simples pour l’animation de son site (indicateurs, etc). Nous allons ici apprendre à réaliser nos premiers écrans, d’abord uniquement via le Web, puis sur système de fichiers (cela implique que vous ayez créé un produit pour héberger votre code ou qu’on l’ait fait pour vous). Nous 209 Plone pour les intégrateurs, Version 1.0.0 apprendrons également comment ajouter également un bloc dans une page standard de Plone pour intégrer un lien vers un de vos nouveaux écrans. Le lecteur devra de se référer également au chapitre TAL/Metal : les templates de Zope et Plone qui contient une référence assez complète. 18.2 Ma première template Nous allons commencer en réalisant une première template qui affiche quelques informations sur l’utilisateur logué ainsi qu’un message de bienvenue. Dans le dossier ‘custom’ (cf chapitre sur les scripts), ajoutez une “Page Template”, que vous appelez welcome. Donnez un titre à votre template : Bienvenue ! <html> <head> <title tal:content="template/title">The title</title> <meta http-equiv="content-type" content="text/html;charset=utf-8"> </head> <body tal:define="plone context/@@plone"> <h2>Bienvenue <span tal:content="python:user.getProperty(’fullname’)" /> !</h2> <p>Vous vous êtes connectés la dernière fois le <span tal:content="python:plone.toLocalizedTim <p>Depuis votre inscription sur ce site vous avez créé <span tal:content="python:len(context.p </body> </html> Connectez-vous avec un autre utilisateur et allez à l’adresse http ://chemin/vers/monsite/welcome. Une fois que vous avez compris que le langage Zope Page Template consiste en un HTML étendu par des attributs dans un espace de nom TAL, qui contient les instructions, vous devriez pouvoir lire facilement cette template. Reférez vous à la référence TAL/Metal : les templates de Zope et Plone. Nous avons deux types d’expressions TAL : – des expressions TAL simples, sans directive et qui se caractérisent par leur forme de chemin d’accès, – des expressions python, introduites par la directive “python :” Vous noterez que, dans les expressions tal simples, la syntaxe ‘/’ permet d’exprimer de nombreuses manières d’accéder à un objet depuis un autre objet. – “context/@@plone” est synonyme de context.restrictedTraverse(’@@plone’) en python – “context/title_or_id” est synonyme de context.title_or_id(), – “template/title” est synonyme de template.title, 18.3 Appel à un script Mettre de longues expressions python dans une expression tal est souvent une mauvaise idée car c’est assez illisible et des erreurs viennent facilement s’y glisser, et il n’est pas aiser de tester ses routines. Nous souhaiterions afficher les derniers contenus ajoutés par l’utilisateur. Nous allons faire appel à notre script qui retrouvait la liste des 50 derniers contenus créés par l’utilisateur connecté. Nous allons le modifier pour qu’il ne renvoit pas un texte, mais pour qu’il renvoit les enregistrements que nous valoriserons ensuite dans la template. Créez le script get_user_recent_added : from Products.CMFCore.utils import getToolByName portal_catalog = getToolByName(context, ’portal_catalog’) portal_membership = getToolByName(context, ’portal_membership’) user = portal_membership.getAuthenticatedMember() brains = portal_catalog.searchResults(Creator=user.getId(), portal_type=(’News Item’, ’File’, ’Document’, ’Event’), # on sort_on=’created’, # le tri se fait sur l’index ’created’ (d 210 Chapitre 18. Ecrire des templates Plone : bases Plone pour les intégrateurs, Version 1.0.0 sort_order=’reverse’, # le tri est inversé (antéchronologiqu sort_limit=50) # on limite à 50 résultats return brains Complétez ainsi votre template : <html> <head> <title tal:content="template/title">The title</title> <meta http-equiv="content-type" content="text/html;charset=utf-8"> </head> <body tal:define="plone context/@@plone; portal_state context/@@plone_portal_state;"> <h2>Bienvenue <span tal:content="python:user.getProperty(’fullname’)" /> !</h2> <p>Vous vous êtes connectés la dernière fois le <span tal:content="python:plone.toLocalizedTim <p>Depuis votre inscription sur ce site vous avez créé <span tal:content="python:len(context.p <h3>Derniers contenus ajoutés</h3> <ul> <li tal:repeat="brain context/get_user_recent_added"> <img tal:condition="brain/getIcon" tal:attributes="src string:${portal_state/portal_url}/${brain/getIcon}" /> <a tal:attributes="href brain/getURL" tal:content="brain/Title"></a> </li> </ul> </body> </html> Quelques remarques : – Nous avons rajouté une boucle : tal :repeat=”brain context/get_user_recent_added” qui s’écrirait, dans un script python : for brain in context.get_user_recent_added():. – Comme vous pouvez le voir, brain/Title et brain/getURL équivalent respectivement à brain.Title et brain.getURL() (les expressions TAL ont cela d’agréable qu’elles sont sobres en caractères spéciaux). – Une expression TAL introduite par la directive string : permet de renvoyer une chaine de caractères composée de contenu statique et du rendu de sous-expressions TALES. – Nous utilisons ici une autre “vue standard” : plone_portal_state, qui permet notamment de récupérer l’URL absolue du site. 18.4 Utiliser la master template de Plone Le but est d’intégrer votre template dans le gabarit de Plone. L’usage des macros se restreint principalement aujourd’hui à utiliser la “main template”. (Vous ne devriez pas avoir à définir des macros, c’est pourquoi on ne présentera pas dans le cadre de ce tutorial.) Indiquez simplement dans l’élément html que vous utilisez la macro master en introduisant l’attribut suivant : metal:use-macro="here/main_template/macros/master". Et dans l’élément body, que le contenu de cet élément remplit la slot “main” du master metal:fill-slot="main" Affichez la vue welcome. Elle s’intègre dans le corps d’une page Plone. Allez consulter maintenant la main_template. Faites une recherche sur main_template dans l’onglet “Find” du portal_skins, et choisissez celle qui est mise en valeur par une étoile : c’est celle qui est prioritaire dans l’ordre des skins. La macro définit un ensemble de slots avec un contenu par défaut. Vous pouvez surcharger ce contenu par défaut à l’aide de la directive metal :fill-slot. Exercice : modifiez votre template welcome de sorte que les colonnes de gauche et de droite n’affichent rien. 18.4. Utiliser la master template de Plone 211 Plone pour les intégrateurs, Version 1.0.0 18.5 Utiliser une structure plus complexe dans une template Nous avons, dans la template précédente, valorisé une liste de brains. Nous allons maintenant valoriser un dictionnaire. Vous voyez que la récupération d’une propriété utilisateur dans la template est assez verbeuse. Nous allons écrire un script qui renvoit un dictionnaire avec les informations qui nous intéressent. Modifiez le script user_infos que vous avez créé au chapitre précédent pour qu’il n’affiche pas un texte mais renvoie un dictionnaire. from Products.CMFCore.utils import getToolByName member = getToolByName(context, ’portal_membership’).getAuthenticatedMember() plone_view = context.restrictedTraverse(’@@plone’) infos = {’login’: member.getId(), ’email’: member.getProperty(’email’), ’fullname’: member.getProperty(’fullname’) or member.getId(), ’login_time’: plone_view.toLocalizedTime(member.getProperty(’login_time’), long_format=1) ’last_login_time’: plone_view.toLocalizedTime(member.getProperty(’last_login_time’), long ’groups’: ", ".join(member.getGroupIds()) or "Aucun"} return infos Puis modifiez votre template pour qu’elle récupère cette structure et qu’elle affiche les infos. <html metal:use-macro="here/main_template/macros/master"> <head> <title tal:content="template/title">The title</title> <meta http-equiv="content-type" content="text/html;charset=utf-8"> </head> <body metal:fill-slot="main" tal:define="plone context/@@plone; portal_state context/@@plone_portal_state; user_infos context/user_infos"> <h2>Bienvenue <span tal:replace="user_infos/fullname" /> !</h2> <p>Vous êtes connectés depuis <span tal:content="user_infos/login_time" /> <p>Votre email est : <a tal:attributes="href string:mailto:${user_infos/email}" tal:content="user_infos/email" /></p> <p>Vous vous êtes connectés la dernière fois le <span tal:content="user_infos/last_login_time" <p>Depuis votre inscription sur ce site vous avez créé <span tal:content="python:len(context.p <p>Vous êtes membres des groupes <span tal:content="user_infos/groups" /></p> <h3>Derniers contenus ajoutés</h3> <ul> <li tal:repeat="brain context/get_user_recent_added"> <img tal:condition="brain/getIcon" tal:attributes="src string:${portal_state/portal_url}/${brain/getIcon}" /> <a tal:attributes="href brain/getURL" tal:content="brain/Title"></a> </li> </ul> </body> </html> Vous observez que la template est beaucoup plus lisible. Ce que nous avons fait, c’est déporter la préparation des informations à afficher dans du code python, et réserver la template pour la disposition des informations. 212 Chapitre 18. Ecrire des templates Plone : bases Plone pour les intégrateurs, Version 1.0.0 18.6 Appeler une template depuis une autre template 18.7 Exercices – Vous réaliserez un tableau qui présentera, pour les dossiers à la racine du site, le nombre de documents (hors dossiers) qu’il contient (récursivement), et le nombre de documents qui y ont été créés depuis moins d’un mois. – Vous réaliserez une page destinée à être affichée au niveau d’un dossier, qui affichera la liste des utilisateurs qui ont un rôle sur le dossier, et pour chacun d’entre eux le nombre de documents qu’ils ont créé. – Vous réaliserez une template qui affiche, pour chaque mot clé disponible sur le site, le nombre d’occurences et un lien vers une page de résultat (dont vous devrez également écrire la template). (Astuces : 1/ le script context.collectKeywords(’subject’, ’Subject’) vous permet de récupérer la liste des mots clés, 2/ l’index concerné est l’index Subject.). Bonus : la taille de l’affichage du mot clé sera proportionnelle au nombre d’occurences ! 18.8 Ecrire la template sous la forme d’une vue Si vous estimez que votre template et ses scripts seront utilisés sur le long terme, il est temps de penser à les transformer en vue. Vous aurez beaucoup plus de facilités à les déployer en production. Une vue est composée d’une template et d’une classe. La template va reprendre la template que vous avez créé. Ce chapitre n’a pas pour objectif d’expliquer la création d’un package. Référez-vous, pour cela, à la documentation développeur, ou demandez à votre prestataire favori. Nous allons créer une vue “welcome”. Pour cela, il faut d’abord la déclarer dans une zcml. <browser:page name="welcome" template="welcome.pt" class=".views.Welcome" for="Products.CMFPlone.interfaces.IPloneSiteRoot" permission="zope2.View" /> Vous pouvez ensuite simplement récupérer la template (utilisez le lien click context du formulaire d’édition de la template), et l’enregistrer dans un fichier welcome.pt. Vous reprenez ensuite dans la classe Welcome (qui hérite de BrowserView) d’un module views.py le code des scripts que vous incluez dans des méthodes du même nom. La classe Welcome contient un attribut context (l’équivalent du context dans le script ou la template) et un attribut request (l’équivalent de context.REQUEST dans le script ou request dans la template). # -*- encoding: utf-8 -*from Products.CMFCore.utils import getToolByName from Products.Five.browser import BrowserView class Welcome(BrowserView): def user_infos(self): member = getToolByName(self.context, ’portal_membership’).getAuthenticatedMember() plone_view = self.context.restrictedTraverse(’@@plone’) infos = {’login’: member.getId(), ’email’: member.getProperty(’email’), ’fullname’: member.getProperty(’fullname’) or member.getId(), ’login_time’: plone_view.toLocalizedTime(member.getProperty(’login_time’), long_f ’last_login_time’: plone_view.toLocalizedTime(member.getProperty(’last_login_time ’groups’: ", ".join(member.getGroupIds()) or "Aucun"} 18.6. Appeler une template depuis une autre template 213 Plone pour les intégrateurs, Version 1.0.0 return infos def get_user_recent_added(self): portal_catalog = getToolByName(self.context, ’portal_catalog’) portal_membership = getToolByName(self.context, ’portal_membership’) user = portal_membership.getAuthenticatedMember() brains = portal_catalog.searchResults(Creator=user.getId(), portal_type=(’News Item’, ’File’, ’Document’, ’Event sort_on=’created’, # le tri se fait sur l’index ’cre sort_order=’reverse’, # le tri est inversé (antéchro sort_limit=50) # on limite à 50 résultats return brains Modifiez votre template de sorte qu’elle aille chercher les méthodes non pas sur le contexte (context) mais sur la vue (view). Retirez toute référence à l’objet template. <html metal:use-macro="here/main_template/macros/master"> <body metal:fill-slot="main" tal:define="plone context/@@plone; portal_state context/@@plone_portal_state; user_infos view/user_infos"> <h2>Bienvenue <span tal:content="user_infos/fullname" /> !</h2> <p>Vous êtes connectés depuis <span tal:content="user_infos/login_time" /> <p>Votre email est : <a tal:attributes="href string:mailto:${user_infos/email}" tal:content="u <p>Vous vous êtes connectés la dernière fois le <span tal:content="user_infos/last_login_time" <p>Depuis votre inscription sur ce site vous avez créé <span tal:content="python:len(context.p <p>Vous êtes membres des groupes <span tal:content="user_infos/groups" /></p> <h3>Derniers contenus ajoutés</h3> <ul> <li tal:repeat="brain view/get_user_recent_added"> <img tal:condition="brain/getIcon" tal:attributes="src string:${portal_state/portal_url}/${brain/getIcon}" /> <a tal:attributes="href brain/getURL" tal:content="brain/Title"></a> </li> </ul> </body> </html> Pensez à renommer vos anciens scipts et templates qui restent dans le custom, pour éviter les conflits. 18.9 Une vue pour un export csv Le script d’export csv peut également être transformé en vue. Nous allons faire une vue pour l’export allcontents.csv pour lequel nous avons fait un script dans le chapitre précédent. <browser:view name="all-contents.csv" class=".views.AllContentsCSV" for="Products.CMFCore.interfaces.IFolderish" permission="cmf.AddPortalContent" /> Deux remarques sur le zcml : Comme on n’a pas de template on utilise non pas une browser :page mais une browser :view. Pour faire simple, par rapport à ce que vous connaissez, une browser :page équivaut à une template et une browser view à un script. Le critère for indique une restriction sur l’interface du contenu - ici, on restreint aux contextes IFolderish, qui est une interface qu’ont tous les objets qui peuvent en contenir d’autres. Les autres contextes n’auront pas cette 214 Chapitre 18. Ecrire des templates Plone : bases Plone pour les intégrateurs, Version 1.0.0 vue (pour connaitre les interfaces d’un contexte, dans la ZMI, allez dans l’onglet Interfaces de l’objet). Le critère permission permet protéger la vue. Un utilisateur essayant d’y accéder sans avoir ladit permission aura une erreur de privilèges insuffisants. Pour une browser view, il faut écrire une méthode __call__ qui renvoit le rendu attendu. class AllContentsCSV(BrowserView): def __call__(self): response = self.request.response response.setHeader(’Cache-Control’, ’no-cache’) response.setHeader(’Pragma’, ’no-cache’) response.setHeader( ’Content-type’, ’application/vnd.ms-excel;charset=windows-1252’) response.setHeader( ’Content-disposition’, ’attachment; filename="all-contents.csv"’) portal_catalog = getToolByName(self.context, ’portal_catalog’) brains = portal_catalog.searchResults(path="/".join(self.context.getPhysicalPath()), # cri portal_type=(’File’, ’Document’, ’Event’, ’News’), # ) lines = [’"Path";"Titre";"Auteur";"MAJ"’] for brain in brains: lines.append(’"%s";"%s";"%s";"%s"’ % (brain.getPath(), brain.Title.decode(’utf-8’).encode(’windows-1252’), brain.Creator, brain.modified.strftime(’%d/%m/%Y’))) return "\n".join(lines) Nous sommes dans une vue, qui est du code python non restreint. À ce titre, on a accès à toute l’API python disponible. Dans ce cas, nous gagnerons à utiliser la librairie csv pour produire notre fichier. from csv import writer from StringIO import StringIO class AllContentsCSV(BrowserView): def __call__(self): response = self.request.response response.setHeader(’Cache-Control’, ’no-cache’) response.setHeader(’Pragma’, ’no-cache’) response.setHeader( ’Content-type’, ’application/vnd.ms-excel;charset=windows-1252’) response.setHeader( ’Content-disposition’, ’attachment; filename="all-contents.csv"’) portal_catalog = getToolByName(self.context, ’portal_catalog’) brains = portal_catalog.searchResults(path="/".join(self.context.getPhysicalPath()), # cri portal_type=(’File’, ’Document’, ’Event’, ’News’), # ) csvdata = StringIO() csvhandler = writer(csvdata, dialect=’excel’, delimiter=’;’) csvhandler.writerow(["Path","Titre","Auteur","MAJ"]) for brain in brains: csvhandler.writerow((brain.getPath(), brain.Title, 18.9. Une vue pour un export csv 215 Plone pour les intégrateurs, Version 1.0.0 brain.Creator, brain.modified.strftime(’%d/%m/%Y’))) csvdata.seek(0) return csvdata.read().decode(’utf-8’).encode(’windows-1252’) Ce qui est tout de même bien plus propre. 18.10 Une viewlet pour ajouter un lien vers une vue 18.10.1 Ma première viewlet Tous les développements que nous avons réalisés jusqu’à présent souffrent, vous avez du le remarquer, d’un gros inconvénient : nous n’avons nulle part, dans notre site, de lien vers les différentes pages et exports que nous avons réalisés ! Autrement dit : nos développements ne sont pas intégrés. Comment ajouter un lien vers nos nouvelles pages ? Vous pouvez tout simplement mettre un lien à la main dans un document Plone, mais cela peut être fastidieux si vous souhaitez que ce lien apparaisse dans de nombreux contextes. Un réflexe de développement “à l’ancienne” est, à l’extrême opposé, de modifier le code de la template de base et d’y mettre le lien (éventuellement conditionnel) vers notre page. Mais “si tout le monde fait cela”, à la fin cette template ne ressemblera plus à rien. Surtout, si vous voulez que votre développement soit utilisé par d’autres, ou sur d’autres de vos sites, il ne faut pas qu’il intervienne sur le comportement par défaut du site. Pour cela, Plone fonctionne avec ce qu’on appelle des viewlets. Ce sont des blocs que l’on peut enregistrer pour qu’ils s’affichent dans des slots appelés viewletmanagers. Une documentation complète des viewlets est disponible dans la documentation développeur. Nous allons, nous, simplement ajouter un lien (sous forme d’image) vers notre export xml sous le titre des dossiers de notre site, pour les utilisateurs ayant le droit d’ajouter des contenus. Nous allons ajouter ceci dans une zcml de notre package : <browser:viewlet name="link-allcontents-csv" manager="plone.app.layout.viewlets.interfaces.IAboveContentTitle" for="Products.CMFCore.interfaces.IFolderish" class=".viewlets.LinkAllContentsCSV" permission="cmf.AddPortalContent" /> Remarques : - class indique la classe qui fournira le rendu html de notre lien (voir ci–après). - manager indique le bloc dans lequel l’élément sera ajouté. Pour choisir le manager, allez sur la vue /@@manage-viewlets sur une des pages de votre site. Les viewlet managers ont un nom et une interface. C’est l’interface que vous indiquez ici. for permet de mettre une contrainte sur le contexte (ici, on n’affichera le lien que sur les dossiers). - permission permet de n’afficher la viewlet que pour certains utilisateurs (on la fera correspondre avec la permission de la vue). - cela ne fait pas l’objet du présent cours, mais pour information un attribut layer est souvent utilisé afin de mettre une contrainte sur les produits installés / l’interface de la request. - name est utile si vous souhaitez remplacer une viewlet existante. Si deux viewlets ont le même nom et sont associées au même manager, alors une seule est affichée : celle qui déclare une interface for la plus proche du contexte en cours, et celle qui a un critère layer le plus proche du layer en cours. Dans un module viewlets.py nous allons créer cette classe LinkAllContentsCSV : from plone.app.layout.viewlets.common import ViewletBase from Products.CMFCore.utils import getToolByName class LinkAllContentsCSV(ViewletBase): def render(self): 216 Chapitre 18. Ecrire des templates Plone : bases Plone pour les intégrateurs, Version 1.0.0 portal_url = getToolByName(self.context, ’portal_url’)() return u"""<a href="%(url)s" id="link-allcontents-csv" style="float: right;" title="Exporter la liste des contenus en csv"> <img src="%(portal_url)s/xls.png" /> </a> """ % ({’url’: self.context.absolute_url() + ’/all-contents.csv’, ’portal_url’: portal_url}) Les viewlets hériteront de la classe ViewletBase, qui fournit quelques services. Pour les besoins les plus simples, vous surchargez ensuite la méthode render, qui génèrera le HTML en python pur. (en principe vous ne mettrez jamais de css en inline : vous indiquerez dans une css : #link-allcontents-csv{float: right;}). Pour des besoins plus complexes, vous utiliserez une template en surchargeant l’attribut index : from zope.browserpage.viewpagetemplatefile import ViewPageTemplateFile class LinkAllContentsCSV(ViewletBase): index = ViewPageTemplateFile(’link-allcontents-csv.pt’) 18.10.2 Exercices – Ajoutez un lien sur les dossiers pour conduire vers un écran que vous avez développé lors d’un exercice sur les templates ou les vues. – Affichez sous le titre d’un dossier un bloc d’informations indiquant notamment la liste des personnes qui ont ajouté des documents dans ce dossier. 18.10. Une viewlet pour ajouter un lien vers une vue 217 Plone pour les intégrateurs, Version 1.0.0 218 Chapitre 18. Ecrire des templates Plone : bases CHAPITRE 19 TAL/Metal : les templates de Zope et Plone Les Zope Page Templates sont un mécanisme permettant d’écrire des pages xhtml dynamiques. Ces ZPT utilisent un langage de template XML TAL/METAL. L’objectif est d’être capable de comprendre, créer et modifier les pages dynamiques. 219 Plone pour les intégrateurs, Version 1.0.0 – Le langage TAL – Savoir – TALES – Savoir – METAL – Savoir – Ressources – Namespaces – Variables globales – Présentation des ZPT – Le langage TAL – Liste des commandes – Ordre d’évaluation – Content et Replace – Condition – Attributes – Define – Repeat – On-error – Omit-tag – TALES – Définition – Exemples – Path – Path alternatif et nothing – Not – String – Nocall – Python – METAL – metal :define-macro – metal :define-slot – metal :use-macro – metal :fill-slot – Tips 19.1 Le langage TAL 19.1.1 Savoir – – – – – – – – Liste des commandes Ordre d’évaluation Content et Replace Condition Define Repeat On-error Omit-tag 220 Chapitre 19. TAL/Metal : les templates de Zope et Plone Plone pour les intégrateurs, Version 1.0.0 19.2 TALES 19.2.1 Savoir – – – – – – – Exemples Path Path alternatif et nothing Not String Nocall Python 19.3 METAL 19.3.1 Savoir – – – – metal:define-macro metal:define-slot metal:use-macro metal:fill-slot 19.4 Ressources Lire la documentation ZPT - Zope Page Templates sur plone.org. Un tal:repeat sur une balise <ul ..> ou <tbody ...> répètera la balise à chaque tour de boucle. Le tal:repeat devrait donc se situer sur un <li ...> ou un <tr ...>. Petit rappel sur les tableaux : vous pouvez mettre un <tr> dans un <thead> pour avoir une ligne d’en-tête sur chaque page lors de l’impression d’un tableau. Il va de même pour un pied de page avec la balise <tfoot>. Dans le document ci-dessus, il manque les commandes tal:omit-tag et tal:on-error, cela est expliqué dans le ZopeBook : – Using Zope Page Templates – Advanced Page Templates – Appendix C : Zope Page Templates Reference La documentation sur plone.org et celle dans le ZopeBook se ressemble beaucoup. Les pages dans le ZopeBook sont complémentaires à la documentation sur plone.org. 19.5 Namespaces Prenez l’habitude de toujours inclure les namespaces dans vos templates. Ils seront nécessaires pour le nouveau moteur de template Chameleon qui parse la page de manière stricte. La structure minimale est donc : <html xmlns="http://www.w3.org/1999/xhtml" xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal" xmlns:i18n="http://xml.zope.org/namespaces/i18n" xml:lang="en" lang="en" metal:use-macro="context/main_template/macros/master" i18n:domain="mydomain"> ... </html> 19.2. TALES 221 Plone pour les intégrateurs, Version 1.0.0 Vous pouvez vérifier si vos templates sont bien valides XML avec la commande xmllint matemplate.pt. 19.6 Variables globales Dans Plone 3.3, vous avez accès à des variables et fonctions globalement dans vos pages templates. Vous n’y avez pas accès via une vue zope3. Vous pouvez récupérer une liste des Products.CMFPlone.browser.ploneview. fonctions disponibles dans le module Toutefois étant donné que dans Plone 4, vous n’y aurez plus accès, prenez l’habitude d’appeler ces fonctions spéciales par l’intermédiaire d’une vue. Par exemple au lieu d’utiliser : <span tal:content="python:toLocalizedTime(context.ModificationDate())"> modification date </span> utilisez plutôt : <span tal:define="plone_view context/@@plone" tal:content="python:plone_view.toLocalizedTime(context.ModificationDate())"> modification date </span> Les variables globales vont être supprimées dans Plone 4 pour des raisons de performances. En effet de nombreuses variables sont accessibles depuis la template mais ne sont pas forcément utilisées, et donc il y a un traitement inutile au rendu de la page. Vous avez quatre vues intéressantes pour récupérer des informations : – @@plone (toLocalizedTime...) – @@plone_tools (properties pour récupérer portal_properties) – @@plone_portal_state (navigation_root_url, is_locked, language, is_editable, object_url...) – @@plone_context_state (portal_url...) 19.7 Présentation des ZPT Objectif Être capable de comprendre, créer et modifier les pages dynamiques. Les Zope Page Template sont un mécanisme permettant d’écrire des pages XHTML dynamiques. Elles sont constituées de page XHTML dans lesquelles sont inclus des balises et attributs TAL/METAL. Exemple : <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal" xmlns:i18n="http://xml.zope.org/namespaces/i18n" metal:use-macro="here/main_template/macros/master" i18n:domain="plone"> <head><title></title></head> <body> <metal:fill fill-slot="main"> <metal:main_macro define-macro="main"> <div tal:content="python:1+3*7" /> </metal:main_macro> </metal:fill> 222 Chapitre 19. TAL/Metal : les templates de Zope et Plone Plone pour les intégrateurs, Version 1.0.0 </body> </html> 19.8 Le langage TAL Le texte d’origine est accessible à http ://www.sebastien-verbois.be/plone/zpt/zpt-am Template Attribute Language (commandes possibles) 19.8.1 Liste des commandes – – – – – – – – tal:content pour remplacer le contenu d’une balise ; tal:replace pour remplacer toute la balise ; tal:condition condition d’exécution du bloc ; tal:attributes pour manipuler les attributs de la balise ; tal:define pour définir des variables ; tal:repeat pour faire une boucle ; tal:omit-tag pour ne pas produire la balise elle-même ; tal:on-error pour définir le comportement en cas d’erreur. tal:content et tal:replace sont mutuellement exclusives. Une commande ne peut apparaître qu’une seule fois dans une balise. 19.8.2 Ordre d’évaluation define -> condition -> repeat -> (content | replace) -> attributes -> omit-tag on-error est évalué si une exception est levée lors d’un traitement d’une des opérations ci-dessus. 19.8.3 Content et Replace tal:content="[structure] Tales" tal:replace="[structure] Tales" Le contenu est automatiquement transformé à l’aide de la fonction html_quote. Pour ne pas subir cette transformation, il faut utiliser le préfixe structure. Il est possible d’accéder aux informations portées par les itérations en utilisant la variable repeat. 19.8.4 Condition tal:condition="Tales" Tales est évalée à True ou False. Le nombre zéro, la chaîne vide, une liste vide et la variable nothing sont évaluées à False. 19.8.5 Attributes tal:attributes="NomAttribut1 Tales1; NomAttribut2 Tales2; ...; NomAttributN TalesN" 19.8. Le langage TAL 223 Plone pour les intégrateurs, Version 1.0.0 19.8.6 Define tal:define="[global] NomVariable1 Tales1; [global] NomVariable2 Tales2; ...; [global] NomVariableN 19.8.7 Repeat tal:repeat="NomVariable Tales" Les itérations imbriquées sont possibles. Les tales suivantes sont accessibles dans le bloc repeat : – repeat/NomVariable/index : 0,1,... – repeat/NomVariable/number : 1,2,... – repeat/NomVariable/letter : a,b,... – repeat/NomVariable/Letter : A,B,... – repeat/NomVariable/roman : i,ii,... – repeat/NomVariable/Roman : I,II,... – repeat/NomVariable/even – repeat/NomVariable/odd – repeat/NomVariable/start – repeat/NomVariable/end – repeat/NomVariable/first – repeat/NomVariable/last 19.8.8 On-error tal:on-error="Tales" La valeur de Tales est utilisée pour remplacer l’expression qui a levé une exception dans une autre TAL. 19.8.9 Omit-tag tal:omit-tag="" 19.9 TALES 19.9.1 Définition TAL Expression Syntax (language d’expression des opérations possibles) Tales ::= [Type:]Suite Type ::= path|string|python|not|exists|nocall Si Type n’est pas donné, le type path est utilisé (type par défaut). – path permet d’accéder au rendu d’un objet ou attribut disponible dans la pile d’acquisition de la template ; – string permet de combiner une expression simple avec du texte ; – python permet d’évaluer du code python ; – not permet d’effectuer une négation sur une expression path, string ou python ; – nocall permet d’accéder à l’objet évalué plutôt qu’à son rendu ; – exists permet de tester l’existence d’un attribut ou d’une méthode (même formalisme que path). path, nocall et exists sont des expressions “path”. Variables implicites : 224 Chapitre 19. TAL/Metal : les templates de Zope et Plone Plone pour les intégrateurs, Version 1.0.0 – attrs – container – default – context/here – modules – nothing – options – request – root – template – user Voir http ://plone.org/documentation/tutorial/zpt/ pour une description. L’utilisation de here est dépréciée au profit de context. 19.9.2 Exemples Path – – – – – – – path :context/title_or_id path :context/bobobase_modification_time path :container/objectValues path :container/objectIds path :user/getUserName path :request/AUTHENTICATED_USER path :request/URL Path alternatif et nothing – path :request/form/custname | context/custname | nothing Not – not :request/maVariable String string:Quelques mots ! On peut utilise une expression path dans une expression string en l’encadrant par ${}. – string :Bienvenue ${user/getUserName} ! – string :$$ 30 Nocall tal:define="doc nocall:here/monDocument" tal:content="string:${doc/id}: ${doc/title}" Python python:len(container.objectValues([’File’,’Image’])) python:context.bobobase_modification_time.strftime(’%d/%m/%Y’) 19.9. TALES 225 Plone pour les intégrateurs, Version 1.0.0 python:test(nombre/2,’Nombre pair’,’Nombre impair’) python:context.monScript(arg1,arg2) Possibilité d’utiliser les autres types d’expressions au sein d’une expression python à l’aide des fonctions path(), string(), exists(), nocall(). python:path(’here/%s/title_or_id’ % currentfolder) python:path(string(’here/$foldername/thing’)) python:path(’request/form/x’) or default Accéder à des objets zope python:getattr(here,’penguin.gif’) (== path:here/penguin.gif) python:request[’URL’] (== path:request/URL) python:request.form[’x’] (== path:request/form/x) python:modules[’math’] 19.10 METAL Macro Expansion Template Attribute Language (système de macros) metal:define-macro metal:define-slot metal:use-macro metal:fill-slot 19.10.1 metal :define-macro Permet de définir une macro que l’on pourra appeler par metal=use-macro. 19.10.2 metal :define-slot Permet de définir un connecteur dans une macro qui permettra d’insérer du code lors de l’expansion de la macro. 19.10.3 metal :use-macro Permet d’indiquer que l’on souhaite utiliser une macro définie dans une ZPT. Ainsi <div metal:use-macro="here/main_template/macros/master"> va chercher la macro master définie dans la ZPT main_template. 19.10.4 metal :fill-slot Permet d’insérer du XHTML dans l’espace prévue pour cela dans une macro. Ainsi <metal:fill fill-slot="main">Mon contenu</metal:fill> permet d’insérer “Mon contenu” dans la partie metal:define-slot="main" de la zpt appelée par metal-use-macro. 226 Chapitre 19. TAL/Metal : les templates de Zope et Plone Plone pour les intégrateurs, Version 1.0.0 Tips Utiliser default <p tal:content="request/form/info | default">Pas de variable "info" dans la requête.</p> Afficher du texte dans la template qui ne sera pas rendu par la suite tal:replace="nothing" Utilisation d’un dictionnaire dans les expressions path getPerson est une fonction python qui renvoie le dictionnaire {’name’: ’Toto’, ’age’: 8}. Accéder à des modules python tal:define="global mstring modules/string" tal:replace="python:mstring.join(slist, ’:’)" Module “PythonScripts” de Zope tal:define="pps modules/Products.PythonScripts.standard" Gérer une exception <p>Le prix de l’article est <b tal:content="context/prix" tal:on-error="string:N/A">0.00</b> Euros 19.10. METAL 227 Plone pour les intégrateurs, Version 1.0.0 228 Chapitre 19. TAL/Metal : les templates de Zope et Plone CHAPITRE 20 Paramétrage local des workflows – – – – – – Préparation Installation du module Gestion des politiques de workflow Affectation des workflows locaux Export Generic Setup Conclusion Nous allons montrer ici comment affecter, sous Plone 4, des processus documentaires différents selon les rubriques du site. Imaginons que nous voulons gérer une partie Intranet et une partie Internet sur notre site Plone. Les permissions et les circuits de validation ne seront probablement pas les mêmes. Nous allons donc gérer, grâce à la fonctionalité Support des politiques documentaires locales, un dossier Intranet dans lequel les documents auront un workflow de type Intranet (les membres peuvent soumettre des documents à un modérateur, qui publie pour tous les membres), et un dossier Internet, où les documents auront un workflow avec modération a priori (les membres peuvent soumettre des documents à un modérateur, qui publie soit pour les anonymes soit pour les seuls membres). 20.1 Préparation Connectez vous en tant qu’administrateur du site. Avant de commencer, vous aurez créé à la racine un dossier Intranet et un dossier Internet, que vous aurez publié. Dans chacun de ces dossiers, vous aurez ajouté une actualité, sans la publier. 20.2 Installation du module Le système de workflows locaux n’est pas activé par défaut. Nous allons commencer par installer la fonctionnalité. Allez dans configuration du site, puis modules. Vérifiez si la ligne Support des politiques documentaire locales (CMFPlacefulWorkflow) apparaît pas dans Modules disponibles. Sinon, vérifiez qu’elle n’est pas déjà dans Modules installés : dans ce cas, passez à l’étape suivante. Cochez la ligne Support des politiques documentaire locales (CMFPlacefulWorkflow) dans Modules disponibles, et cliquez sur Activer. 229 Plone pour les intégrateurs, Version 1.0.0 230 Chapitre 20. Paramétrage local des workflows Plone pour les intégrateurs, Version 1.0.0 20.2. Installation du module 231 Plone pour les intégrateurs, Version 1.0.0 Le module est maintenant installé. 20.3 Gestion des politiques de workflow Revenez dans la configuration du site. Dans Configuration de module, cliquez sur la nouvelle entrée : Politiques documentaires. Les listes de politiques documentaires existantes par défaut sont affichées. Il existe déjà une politique ‘Intranet’. Pour en connaître les détails, cliquez sur le titre. Ce que vous voyez est en fait une version simplifiée de la page de configuration du workflow général, dans la zmi > portal_workflows. Référez vous à la formation sur les workflows pour davantage d’informations. Vous pouvez sélectionner le workflow par défaut, et éventuellement un workflow spécifique par type de contenu (en général on utilise des workflows différents pour les contenus de type rubrique). Les différents workflows disponibles sont ceux décrits dans portal_workflows, onglet ‘Contents’. Référez vous à la formation sur les workflows pour retrouver comment ajouter et modifier des workflows existants. Cette configuration conviendra pour notre partie Intranet. Revenons à la page principale de configuration des processus en cliquant sur “Aller au niveau supérieur”. Nous pourrions vérifier parmi les trois autres workflows disponibles s’il y en a qui pourraient correspondre à notre besoin pour la partie Internet. Mais nous allons créer une nouvelle politique pour les besoins de cette formation. Entrez internet dans le champ Nouvelle politique documentaire, puis cliquez sur Ajouter. Donnez lui pour titre Publication Internet. 232 Chapitre 20. Paramétrage local des workflows Plone pour les intégrateurs, Version 1.0.0 20.3. Gestion des politiques de workflow 233 Plone pour les intégrateurs, Version 1.0.0 234 Chapitre 20. Paramétrage local des workflows Plone pour les intégrateurs, Version 1.0.0 Nous allons choisir, pour les documents, un Processus de publication simple, qui consiste en un circuit privé -> en attente de validation -> publié pour tous. Pour cela, nous sélectionnons cette valeur pour le champ Processus documentaire par défaut. Pour tous les documents sauf Dossier et Collection, nous choisissons Processus par défaut de la politique, qui renvoit à la valeur choisie ci-avant. Imaginons que dans le cas de notre site Internet, nous n’ayons pas besoin de valider les dossiers vu que seul l’administrateur pourra en ajouter. Nous choisirons alors un workflow à un seul état : le dossier est immédiatement publié, seul son contenu est modéré. Nous choisissons donc Processus de publication à état unique. Supposons que nous voulons que la gestion des Collections soit identique sur le dossier Internet et au niveau du site. Nous choisirons Acquisition du processus dans les dossiers parents pour Collection : le workflow sera le même que pour le dossier parent (le site Plone). Vous pouvez maintenant cliquer sur Enregistrer. Votre politique a été ajoutée. 20.4 Affectation des workflows locaux Nous allons maintenant associer des workflows différents pour les actualités selon que nous sommes sur l’intranet ou sur l’internet. Allez dans le dossier Intranet. Cliquez sur le menu État, puis Politique locale. L’affectation locale des workflows n’est pas activée par défaut dans ce dossier. Vous arrivez donc sur une page intermédiaire. Cliquez sur Ajouter une configuration locale des politiques documentaires dans le Dossier. Vous arrivez sur la page de configuration locale des processus. Vous choisissez ici quelle est la politique que vous voulez activer pour ce Dossier. Sélectionnez dans Pour ce dossier : Intranet, puis enregistrez. Vous pouvez également faire en sorte que la politique soit associée à tous les sous-dossiers du dossier Intranet, mais pas au dossier Intranet lui-même. C’est utile, par exemple, quand vous voulez des droits et des validations différents pour les modifications à la racine de votre rubrique. Dans ce cas, vous choisirez la politique dans En dessous de ce dossier. Revenez dans le dossier Intranet. Ce dossier est maintenant en ‘Brouillon interne’ : il est modifiable par les modérateurs et visible par les membres). Si vous vous déconnectez, vous observerez qu’il n’est plus visible aux anonymes. Allez sur l’actualité. Vous observerez que les transitions proposées correspondent au workflow Publication internet : en tant qu’administrateur, je peux Publier en interne, c’est-à-dire rendre visible aux membres seulement. Allez maintenant sur le dossier Internet. Cliquez sur État -> Politique locale. Faites de même, mais sélectionnez Pour ce dossier -> Publication Internet. Le dossier est resté à l’état ‘Publié’, mais vous observerez qu’aucune autre transition n’est disponible : nous utilisons pour les dossiers le workflow Processus de publication à état unique. Allez dans l’actualité. Vous avez en tant qu’administrateur le choix entre Publier et Soumettre à la publication. Nous utilisons ici le workflow Processus de publication simple. 20.5 Export Generic Setup Les politiques documentaires peuvent être exportées en xml via l’outil Generic Setup. Dans portal_setup > Export, sélectionnez Placeful Workflow Policies puis Export selected steps. L’outil ne permet pas d’exporter la configuration des politiques locales. 20.6 Conclusion Nous savions déjà que nous pouvions avoir des processus documentaires différents suivant le type de contenu. Nous savons maintenant que Plone permet de paramétrer des workflows différents pour un même type de contenu 20.4. Affectation des workflows locaux 235 Plone pour les intégrateurs, Version 1.0.0 236 Chapitre 20. Paramétrage local des workflows Plone pour les intégrateurs, Version 1.0.0 20.6. Conclusion 237 Plone pour les intégrateurs, Version 1.0.0 mais à différents endroits du site. Pour conclure, il faut prendre garde à distinguer trois notions, que nous définirons ici : Processus de publication, ou workflow : c’est la description d’un processus de validation, avec états, transitions, permissions... On les définit dans la ZMI, dans portal_workflows > Contents. Politique documentaire : c’est la configuration des workflows pour tous les types de documents du site. On définit la politique par défaut sur la page d’accueil de portal_workflows, et des politiques supplémentaires dans Configuration du site > Politiques documentaires. Politique locale : c’est la sélection d’une politique documentaire pour qu’elle s’applique sur une rubrique du site. On les définit via l’action État > Politique locale sur la rubrique. 238 Chapitre 20. Paramétrage local des workflows CHAPITRE 21 Déclenchement d’événements avec les règles de contenu Plone permet de gérer des déclenchements d’actions avec un très haut niveau de paramétrage, suivant : – un événement déclencheur (ajout d’un document, d’un utilisateur, passage d’une transition...), – une / des conditions (état du document, type de document, rôle de l’utilisateur...), – la localisation sur le site. Les événements peuvent lancer des actions diverses telles que : – envois d’emails, – ajout de log, – affichage d’un message, – etc. – – – – – – – – – – – – – Objectif de la formation Préparation Créer une règle Paramétrer une règle Créer une condition Créer une action Activer la règle pour une partie du site Tester la règle Exemple 2 : Logguer les suppressions de documents Exemple 3 : Déplacer les événements dans un même dossier, où qu’ils soient ajoutés Export Generic Setup Extensibilité Conclusion 21.1 Objectif de la formation Nous allons créer : – une règle qui affiche un message à l’utilisateur et envoie un mail au modérateur lorsqu’une actualité est soumise à validation dans la partie Intranet, – une règle qui ajoute une entrée dans les logs à chaque fois qu’un document est supprimé, – une règle qui déplace tous les événements ajoutés dans la partie Internet dans le dossier Événements. 239 Plone pour les intégrateurs, Version 1.0.0 21.2 Préparation Il nous faudra un dossier Intranet et un dossier Internet à la racine de notre site (cf. chapitre précédent). Il faut créer un utilisateur Modérateur Intranet qui ait le rôle Peut Modérer sur le dossier Intranet. Le smtp et l’email par défaut du site doivent être correctement configurés. 21.3 Créer une règle Créons la première règle citée ci-dessous. Pour cela, connectez vous en administrateur, puis allez sur admin > Configuration du site. Cliquez sur ‘règles’. Vérifiez tout d’abord que la case Activer globalement a bien été cochée. Elle a pour effet d’activer tout le système de règles. Lorsque vous avez besoin de désactiver provisoirement toutes les règles, le mieux est de décocher cette case. Cliquez ensuite sur Ajouter une règle. Choisissez comme titre : Une actualité a été ajoutée. Il faut vérifier si la règle s’applique à chaque fois qu’un utilisateur effectue une transition. Sélectionnez comme déclencheur Workflow state changed. Puis enregistrez. La règle a été ajoutée. Elle apparaît maintenant dans la liste des règles. Mais pour l’instant, elle ne se déclenche jamais, et ne fait rien... Il faut la paramétrer. 21.4 Paramétrer une règle Cliquez sur la règle, vous arrivez à la page de paramétrage de cette règle. 240 Chapitre 21. Déclenchement d’événements avec les règles de contenu Plone pour les intégrateurs, Version 1.0.0 21.4. Paramétrer une règle 241 Plone pour les intégrateurs, Version 1.0.0 Il nous faut maintenant ajouter les conditions de la règle, et ses résultats. 21.5 Créer une condition La règle a deux conditions : il doit s’agir d’une actualité, et la transition doit être une soumission à la publication. Dans la partie Si toutes les conditions suivantes sont remplies, sélectionnez Type de contenu, et Ajouter Choisissez le type de contenu Actualité, puis enregistrez. La condition a été ajoutée. De même, ajoutez la condition sur la transition : sélectionnez Ajouter une condition > Transition de workflow puis Ajouter. Choisissez Soumettre à la publication [submit] puis enregistrez. 21.6 Créer une action On veut que le modérateur reçoive un mail. Pour Effectue les actions suivantes, sélectionnez Ajouter une action > Envoyer courriel, puis Ajouter. Vous arrivez sur la page de paramétrage de l’email. Vous définissez ici le sujet, le texte, les destinataires, etc, en utilisant un certain nombre de variables fournies de base par Plone. 242 Chapitre 21. Déclenchement d’événements avec les règles de contenu Plone pour les intégrateurs, Version 1.0.0 Indiquez le sujet de l’email : L’actualité ${title} est en attente de validation. L’emplacement ${title} sera remplacé par le titre du document au moment de l’envoi. Comme source du courriel, ne mettez rien : ainsi, la source sera l’adresse du portail. Comme destinataires, utilisez la variable ${reviewer_emails} : le mail sera envoyé à la liste des modérateurs (Reviewers) Entrez enfin un message comme sur cette copie d’écran : Enregistrez ; votre action a été ajoutée. Imaginons que les contributeurs de l’intranet craignent que leur demande ne soit pas prise en compte. Nous allons ajouter un message leur indiquant que les modérateurs ont reçu un mail. Faites Ajouter une action > Notifier l’utilisateur, puis Ajouter. Indiquez comme message : Les modérateurs ont été notifiés par mail de votre demande., conservez info comme type de message, puis enregistrez. Votre règle a été créée. Il reste maintenant à l’activer dans la partie Intranet du site. 21.7 Activer la règle pour une partie du site Allez dans la rubrique Intranet, sélectionnez l’onglet Règles. Vous avez un champ Affecter une règle ici qui propose (uniquement, pour l’instant) la règle Une actualité a été ajoutée. Cliquez sur Ajouter. Ceci fait, la règle est maintenant activée pour ce dossier, et seulement celui-ci. Pour l’activer sur tous les sousdossiers de l’intranet, cochez la règle dans le tableau et cliquez sur Appliquer aux sous-dossiers. Vous pouvez activer / désactiver la règle ici. Si vous l’avez associée à d’autres dossiers via d’autres onglets règles, seul celui-ci est impacté. 21.7. Activer la règle pour une partie du site 243 Plone pour les intégrateurs, Version 1.0.0 244 Chapitre 21. Déclenchement d’événements avec les règles de contenu Plone pour les intégrateurs, Version 1.0.0 21.8 Tester la règle Cliquez sur l’onglet Voir, puis sur une actualité du dossier. Soumettez à la publication le document. Vous observerez que le message Les modérateurs ont été notifiés par mail de votre demande. apparaît bien. Et le modérateur a reçu un courriel. 21.9 Exemple 2 : Logguer les suppressions de documents Dans Configuration du site > Règles, cliquez Ajouter une règle. 21.8. Tester la règle 245 Plone pour les intégrateurs, Version 1.0.0 Appelez-la Un document a été supprimé, choisissez le déclencheur Object removed from this container et enregistrez. Cliquez sur la règle pour paramétrer les actions. Nous ne spécifierons pas de conditions particulières ici. Sélectionnez Ajouter une action > Logger puis Ajouter. Remplacez le Message par Suppression du document &c. Allez à la racine du site et cliquez sur Règles ; ajoutez la règle Un document a été supprimé. Activez-la pour les sous-dossiers. Ajoutez un document sur le site, et supprimez-le. Si votre site est démarré en mode foreground, vous pouvez y voir le log. Sinon, consultez vos logs avec la commande tail -f ./var/log/instance.log depuis la racine du buildout. 21.10 Exemple 3 : Déplacer les événements dans un même dossier, où qu’ils soient ajoutés Imaginons que nous voulions regrouper tous les événements du site dans un seul dossier, sans contraindre l’utilisateur à être à un endroit particulier du site lorsqu’il ajoute un tel élément. 246 Chapitre 21. Déclenchement d’événements avec les règles de contenu Plone pour les intégrateurs, Version 1.0.0 Ajoutez une nouvelle règle, que vous appelerez Un événement a été ajouté, avec le déclencheur Objet ajouté au dossier. Associez-lui la condition : Type de contenu : Événement. Ajoutez ensuite l’action Déplacer vers dossier, et choisissez le dossier Événements. Dans Affectations, cliquez sur le bouton Appliquer la règle sur l’ensemble du site. Dans le dossier Internet, ajoutez un événement. Allez ensuite dans le dossier Événements, vous verrez qu’il y a été déplacé. Revenez dans le dossier Internet : il n’y est plus. 21.11 Export Generic Setup Les règles de contenu peuvent être exportées en xml via l’outil Generic Setup. Dans portal_setup > Export, sélectionnez Content rules puis Export selected steps. Cela exporte à la fois vos définitions de règles et les activations des règles sur les rubriques. Attention : après l’export, vérifiez que l’indentation automatique du xml n’a pas ajouté des espaces non désirés dans vos messages. 21.12 Extensibilité Les règles de contenu sont largement extensibles. Il est possible d’ajouter ou créer : – de nouveaux déclencheurs, – de nouvelles conditions, – de nouvelles actions. Si vous avez des besoins spécifiques, recherchez sur pypi trules pour vérifier si une extension existe pour votre http ://pypi.python.org/pypi ?%3Aaction=search&term=contentrules&submit=search. le cas mot-clé contend’utilisation : Vous pouvez également vous lancer dans le développement de conditions et actions (niveau avancé) avec l’aide de ce guide http ://plone.org/documentation/kb/creating-content-rule-conditions-and-actions. Ou contactez votre prestataire Plone favori. 21.11. Export Generic Setup 247 Plone pour les intégrateurs, Version 1.0.0 21.13 Conclusion Il est possible d’associer à un événement du site et suivant des conditions, sur des parties déterminées du site, des actions. Un certain nombre de déclencheurs, d’actions et de conditions sont disponibles par défaut. D’autres sont disponibles en tant qu’extensions. Il est aisé à un développeur d’en créer de nouveaux. 248 Chapitre 21. Déclenchement d’événements avec les règles de contenu CHAPITRE 22 Créer des pages composées en ligne avec Collage Collage permet de composer en ligne, comme des contenus, des pages complexes composées d’éléments organisés en grille. C’est le moyen idéal de permettre à un webmaster de gérer lui-même ses pages d’accueil. – – – – – – – – – Préparation Objectif de la formation Installer Products.Collage Créer un Collage Ajouter les éléments du Collage Utiliser le collage comme page d’accueil Paramétrer l’affichage du collage Extensibilité Conclusion 22.1 Préparation Vous n’aurez besoin sur votre site que d’un dossier et de quelques actualités publiées. 22.2 Objectif de la formation Nous allons associer comme page par défaut d’un dossier une page composée d’une collection d’actualités, d’une image et d’une actualité complète. 22.3 Installer Products.Collage Ajoutez à l’entrée eggs de votre buildout la valeur Products.Collage. Relancez le buildout puis redémarrez votre site. La dernière version du package Products.Collage a été ajoutée à votre environnement Plone. Il faut maintenant activer le module. Connectez vous en tant qu’administrateur. Allez dans admin > Configuration du site, puis Modules. Cochez Products.Collage, puis enregistrez. 249 Plone pour les intégrateurs, Version 1.0.0 22.4 Créer un Collage Allez dans un dossier de votre site, faites Ajout d’un élémént > Collage. Indiquez un titre et enregistrez. Cliquez sur Composer pour aller sur la page de construction du collage. Un collage se compose de rangées elles-mêmes divisiées en colonnes, chaque colonne pouvant contenir plusieurs éléments les uns au-dessus des autres. Ajoutez une première rangée. Cela ajoute une rangée, contenant par défaut une colonne. 22.5 Ajouter les éléments du Collage Nous allons composer un collage en deux colonnes sur une ligne. La première colonne contiendra une liste des actualités, la seconde contiendra une image statique et le rendu d’une actualité. Cliquez sur créer une colonne. Nous avons maintenant deux colonnes. Dans la colonne de droite, cliquez sur Insérer un élément existant. Recherchez une actualité et insérez-la. Vous avez créé un alias sur votre composition, qui affiche le contenu de votre actualité. Vous pouvez créer un contenu spécifique pour votre composition. Dans la colonne de droite, cliquez sur Créer un nouvel élément -> Image. Vous arrivez sur le formulaire de création d’une image. Uploadez une image et publiez-la. Vous observez que la nouvelle image est un contenu image qui a été ajouté dans un contenu colonne, lui même ajouté dans un contenu rangée. Cliquez sur Retour au collage. Vous souhaitez que l’image s’affiche au-dessus du texte de l’actualité. Cliquez sur la flèche haut de l’image (ou la flèche bas de l’actualité). Vous avez changé l’ordre des éléments de la colonne. 250 Chapitre 22. Créer des pages composées en ligne avec Collage Plone pour les intégrateurs, Version 1.0.0 22.5. Ajouter les éléments du Collage 251 Plone pour les intégrateurs, Version 1.0.0 252 Chapitre 22. Créer des pages composées en ligne avec Collage Plone pour les intégrateurs, Version 1.0.0 22.5. Ajouter les éléments du Collage 253 Plone pour les intégrateurs, Version 1.0.0 Vous observerez que vous avez directement accès à certaines fonctionnalités des documents, comme par exemple, la rotation des images (transformer), la copie, etc. Nous allons créer une collection des actualités dans la colonne de gauche. Faites Créer un nouvel élément > Collection. Créez une collection qui affiche toutes les actualités du site. Revenez ensuite au Collage. Cliquez sur Voir pour observer le résultat. 22.6 Utiliser le collage comme page d’accueil Publiez le collage, puis assignez-le comme vue par défaut du dossier : sur le dossier, cliquez sur Affichage > Changer la vue par défaut et sélectionnez votre collage. Nous ne voulons pas faire apparaître le titre de notre collage Accueil internet sur cette page d’accueil. Allez dans Modifier > Paramètres. Décochez Afficher le titre et enregistrez. 22.7 Paramétrer l’affichage du collage Nous allons maintenant tester quelques options de paramétrage de notre collage. Nous pouvons choisir un modèle pour notre ligne. Sur la ligne, cliquez modèle. Vous avez une liste de layouts disponibles. Sélectionnez par exemple Gauche large. Le résultat est manifeste (mais pas forcément très bon... re-sélectionnez le modèle Automatique). 254 Chapitre 22. Créer des pages composées en ligne avec Collage Plone pour les intégrateurs, Version 1.0.0 22.7. Paramétrer l’affichage du collage 255 Plone pour les intégrateurs, Version 1.0.0 256 Chapitre 22. Créer des pages composées en ligne avec Collage Plone pour les intégrateurs, Version 1.0.0 22.7. Paramétrer l’affichage du collage 257 Plone pour les intégrateurs, Version 1.0.0 Nous pouvons également choisir un modèle pour les éléments. Cliquez sur modèle de l’actualité, choisissez portlet. La vue portlet permet de choisir un habillage. 22.8 Extensibilité Il est possible de développer de nouveaux layouts et de nouveaux types d’éléments pour les compositions de Collage. Pour trouver les modules d’extension existants, cherchez http ://pypi.python.org/pypi ?%3Aaction=search&term=collective.collage&submit=search. sur pypi : Dans la liste des modules disponibles pour collage, nous avons le produit collective.collage.portlet. C’est un plugin collage qui nous permet d’avoir des portlets dans notre collage. Nous allons l’installer. Dans votre buildout.cfg, ajoutez à votre paramètre eggs la valeur collective.collage.portlet. Relancez votre buildout et redémarrez le site. Allez dans configuration du site, et installez le module collective.collage.portlet. Retournez sur votre collage. Ajoutez une colonne. Cliquez sur modèles. Un modèle a été ajouté au modèle standard : portlets. Choisissez-le. La colonne fournit maintenant une interface permettant de sélectionner un portlet, similaire à celle de la page ‘Gérer les portlets’. Ajoutez un portlet de modération, et enregistrez. S’il n’existe pas de plugin correspondant à vos besoins, contactez votre prestataire Plone favori :). 22.9 Conclusion Le module collage permet de créer des pages composées. 258 Chapitre 22. Créer des pages composées en ligne avec Collage Plone pour les intégrateurs, Version 1.0.0 22.9. Conclusion 259 Plone pour les intégrateurs, Version 1.0.0 260 Chapitre 22. Créer des pages composées en ligne avec Collage Plone pour les intégrateurs, Version 1.0.0 22.9. Conclusion 261 Plone pour les intégrateurs, Version 1.0.0 262 Chapitre 22. Créer des pages composées en ligne avec Collage Plone pour les intégrateurs, Version 1.0.0 22.9. Conclusion 263 Plone pour les intégrateurs, Version 1.0.0 264 Chapitre 22. Créer des pages composées en ligne avec Collage Plone pour les intégrateurs, Version 1.0.0 On organise des contenus en lignes et en colonnes. Ces contenus peuvent être des alias de documents du site, des collections, ou des contenus embarqués. On peut présenter les éléments de la composition suivant différents modèles, voire avec différents habillages. Ces compositions sont idéales pour construire des pages d’accueil de sites ou de rubriques. Des plugins existent pour étendre les éléments disponibles pour vos compositions. 22.9. Conclusion 265 Plone pour les intégrateurs, Version 1.0.0 266 Chapitre 22. Créer des pages composées en ligne avec Collage CHAPITRE 23 Glossaire Définition des termes et abréviations utilisés dans ce document. adapter Classe Python fournissant aux objets exposant une certaine interface des services supplémentaires, sans utiliser directement la technologie d’héritage Python. Les adapteurs font partie des concepts amenés par la ZCA (Zope Component Architecture). adaptateur Traduction libre de adapter. AT Abréviation courante d’Archetypes utilisée dans les documentations, blogs, mailing-lists, forums ayant trait à Plone. brain Toute requête au catalogue fournit une itération de brains. Chaque brain étant une référence à un élément de contenu, et incorpore la copie de certains attributs de celui-ci (titre, description, ...). cheeseshop voir pypi. buildout Buildout – ou zc.buildout – est un outil multi-plateformes conçu pour installer et paramétrer les différents composants logiciels d’un système d’informations. Plone est installable par ce mode depuis sa version 2.5. zc.buildout permet en outre de personnaliser l’installation des composants qui concourent à l’installation de “votre” site Plone en modifiant son fichier de configuration. Le packaging sous forme d’eggs est favorisé. C Langage compilé de bas niveau utilisé pour coder - entre autres - Linux et Python. Un compilateur C est nécessaire pour installer Zope ainsi que de nombreuses extensions Python. component Package Python fournissant des fonctionnalités supplémentaires à Zope ou Plone. Les composants sont installés le plus souvent dans $INSTANCE_HOME/lib/python, et plus généralement dans les répertoires du système de fichiers désignés par la directive path du fichier de configuration de votre instance Zope. L’extension de Zope ou Plone par composants est la méthode recommandée pour faciliter la future migration vers le pur Zope 3. Attention, si un composant comporte des directives ZCML, celui-ci doit être déclaré dans la configuration de de votre instance Zope. composant Traduction libre de component. configlet Panneau de configuration de Plone permettant de paramétrer de façon globale certains aspects de Plone. Par exemple, le panneau de configuration des utilisateurs et des groupes ou le thème graphique. Certains composants d’extension de tierce partie ajoutent leur panneau de configuration. content type Un type de contenu est le moule avec lequel tous les élément d’un certain type sont gérés. Un type de contenu incorpore les dispositifs suivant : – factory de création de l’élément – vues HTML de l’élément schéma d’informations portées par l’élément, incluant ses méta-données – formulaires de création/modification de ce schéma d’informations – services “métier” proposés par l’élément. distribute Distribute est une refonte et une alternative à setuptools élaborée à l’initiative de Tarek Ziadé. distribute fournit les outils de packaging, de distribution et d’installation de packages Python sous forme d’egg. Nous recommandons vivement l’utilisation de distribute dont les contributeurs sont bien plus réactifs que ceux de setuptools. Bien entendu, distribute est packagé sous forme d’egg. 267 Plone pour les intégrateurs, Version 1.0.0 distutils distutils est un package fourni en standard avec Python fournissant les outils de packaging. distribute s’appuie sur distutils et on préfèrera l’utilisation de ce dernier qui fournit des outils plus avancés. dotted name Il n’y a pas de traduction en français facile et concise pour ce terme. Un dotted name permet - généralement dans un fichier ZCML - de désigner un symbole Python quelconque (objet, classe, fonction, ...) sous la forme d’une chaîne de caractères proche de celle utilisée par le mot clé Python import. Par exemple, le dotted name foo.bar.stuff représente l’équivalent en python from foo.bar import stuff. En outre, la notation dotted name admet la notation de package relatif par l’utilisation du préfixe .. Par exemple .foo.bar dans un fichier ZCML permet de référencer l’objet (classe, fonction, ...) bar du module foo.py lorsque ce module figure dans le même répertoire que le fichier ZCML. Un préfixe de deux points (..) permet d’accéder au répertoire parent de celui incluant le fichier ZCML et ainsi de suite. egg Packaging d’un module Python incluant ses méta-données telles que sa version, sa documentation et les éventuelles dépendances d’autres eggs. La grande majorité des eggs publics sont distribués sur le site pypi. Reportez-vous au chapitre Concept de Python eggs pour plus de détails. eggs Voir egg. élément (de contenu) ou “content item”. Unité atomique de contenu fournie par un auteur, tel qu’un document, une image, un fichier. Certains types d’éléments, tel que le dossier ou la collection sont dits également conteneurs ou “folderish” de par leur aptitude à contenir d’autres éléments de la même façon qu’un répertoire peut inclure d’autres fichiers et répertoires dans un disque dur. groupe (d’utilisateurs). Un groupe d’utilisateurs permet d’associer un ensemble d’utilisateurs à une fonction dans un site Plone. Ceci permet - principalement - d’octroyer des droits particuliers, élément par élément, à tout un ensemble d’individus par le biais de l’onglet partage. Les groupes d’utilisateurs sont gérés par PlonePAS à travers le configlet Utilisateurs et groupes. Un utilisateur peut appartenir à autant de groupes que nécessaire, voire aucun groupe. Un groupe peut appartenir à un autre groupe (imbrication). i18n Abréviation commune du terme “internationalisation” (il y a 18 lettres entre le “i” et le “n” de “internatonalisation”). Opération consistant à marquer le code (Python, templates, ...) pour lui permettre de fournir les textes de l’interface utilisateur en différents langages. Voir l10n. interface (en Python) : Une interface est une classe spéciale décrivant l’API publique de toute autre classe l’implémentant. L’utilisation des interfaces est à la base de la ZCA. invite de commandes Logiciel vous invitant à contrôler votre système en fournissant des commandes et en lisant le compte-rendu des dites commandes. Jusque dans les années 80, l’invite de commandes était l’unique moyen de contrôler un ordinateur. Sous Windows, l’invite de commandes est fournie par le logiciel cmd.exe‘ alors que sous Unix - le choix est plus vaste - le couple xterm et bash est généralement utilisé. l10n Abréviation commune de “localisation” (il y a 10 lettres entre le “l” et le “n” de “localisation”). Opération consistant à fournir les textes de l’interface utilisateur d’un logiciel (d’un composant Plone) dans un langage particulier. Voir i18n. msi installer Format de bundle d’installation du monde Windows. Les fichiers de ce type ont l’extension .msi. multiplugin Un plugin ayant l’aptitude de remplir plusieurs rôles, donc, généralement implémentant plus d’une interface. Un plugin pour PAS est d’ailleurs généralement un multiplugin. part Une part est une section d’un fichier buildout contenant une variable recipe définissant le rôle de la part dans le processus d’installation global défini par la configuration buildout. Une part n’est exécutée que si elle est référencée dans la liste parts = ... de la section [buildout]. parts voir part. permission Protection d’accès à un objet dont la sécurité est gérée par Zope. permissions voir permission. PAS Aréviation de PluggableAuthService, la base du service de gestion des utilisateurs, rôles et groupes de Plone. Voir le chapitre Gestion des utilisateurs avec PlonePAS. paster Couteau suisse du développeur d’applications Python. Voir http ://pythonpaste.org/index.html PATH Variable d’environnement utilisée par votre système d’exploitation pour trouver les logiciels invoqués par l’invite de commandes. Cette variable d’environnement est constituée d’une liste de répertoires, séparés par : pour Unix et ; sous Windows. 268 Chapitre 23. Glossaire Plone pour les intégrateurs, Version 1.0.0 plugin Se dit d’un composant logiciel (fonction, classe, ou objet) s’intégrant dans une infrastructure existante et ayant une interface et un rôle pré-défini vis-à-vis de cette infrastructure (le rôle est généralement défini par une interface), mais implémentant le rôle d’une façon qui lui est propre. Les logiciels de type “plugin” sont légion dans le monde de Plone, et plus notamment dans le service de gestion des utilisateurs PAS. Voir le chapitre Gestion des utilisateurs avec PlonePAS. PMI Plone Management Interface : Ensemble des formulaires fournis par Plone et ses éventuelles extensions permettant de gérer et paramétrer le contenu et les services. portlet Petite boite d’interface utilisateur située dans la colonne gauche d’un portail Plone. Les conditions d’apparition et les interfaces des portlets est automatiquement calculé en fonction du contexte (droits de l’utilisateur, et emplacement de navigation). L’outil de navigation et le calendrier sont des exemples de portlets. Dans la grande majorité des cas, les portlets ne font pas strictement partie du contenu. policy package Un policy package est un composant pour Plone défininissant la politique éditoriale du site, et - éventuellement - sa logique métier spécifique. un policy package a également pour rôle d’installer et paramétrer de façon spécifique Plone et les différents composants de tierce partie ajoutés. principal Agent du système Zope exécutant une action. Un agent dispose de permissions sur les objets Zope pour exécuter ces actions. Dans les applications Zope ou Plone, vous ne verrez que deux types de principals : les utilisateurs (ou membres) et les groupes. product Package Python fournissant des fonctionnalités supplémentaires à Zope ou Plone. Les produits sont installés le plus souvent dans $INSTANCE_HOME/Products, et plus généralement dans les répertoires du système de fichiers désignés par la directive “products” du fichier de configuration de votre instance Zope. L’extension de Zope et Plone par produits est un héritage des anciennes versions de Zope, facilitant ainsi l’adaptation d’extensions Zope ou Plone conçues pour des versions antérieures. Il est en conséquence recommandé de réaliser dorénavant des composants (voir plus haut) pour ajouter des fonctionnalités à Zope ou Plone. produit Traduction libre de product. profil Traduction libre de profile. profile (GenericSetup) : un profil désigne un lot de fichiers XML définissant le paramétrage appliqué à un site Plone permettant l’utilisation dans le dit site des ressources d’un composant ou d’un produit. Les fichiers d’un profil GenericSetup sont – généralement – placés dans le sous-répertoire profiles/default d’un composant ou produit. propertysheet En français : feuille de propriétés. Dans Plone, il y a deux types de feuilles de propriétés : – Les feuilles de propriétés servant à conserver des propriétés globales du site, celles-ci se trouvant dans le tool portal_properties – Les feuilles de propriétés dynamiques associées aux utilisateurs et aux groupes. pypi PYthon Packages Index, anciennement appellé cheeseshop, est le site dans lequel la grande majorité des packages open source Python sont mis à la disposition du public. Sa page d’accueil est http ://pypi.python.org/pypi pywin32 Package Python pour Windows - disponible pour les architectures 32 et 64 bits - fournissant l’accès aux services système spécifiques à ce système d’exploitation : contrôle des services, de la base de registres, accès COM ou DCOM aux applications, accès à Exchange et Active Directory, extensions et filtres ISAPI, etc, etc. recipe Peut être traduit en français par “recette”. Une recipe définit le rôle d’une part d’une configuration buildout (exemples : installation/paramétrage d’Apache, instalation d’un client ZEO, fichier de comfiguration défini par une template, ...). La plupart des recipes disponibles sont disponible dans le site Pypi à cette adresse. rôle Un rôle regroupe un ensemble de permissions. Tout visiteur dispose d’un ou plusieurs rôles, soit de façon globale, soit de façon contextuelle. SSO Single Sign On ou Authentification unique. Agent permettant de n’effectuer qu’une seule authentification pour accéder à plusieurs sites. Comme par exemple pour Google apps (mail, agendas, documents). Voir http ://fr.wikipedia.org/wiki/SSO structural folder Type de contenu permettant à un contributeur d’y inclure les contenus de son choix. A contrario, le “non structural folder” permet pas à un contributeur de structurer librement son contenu. Les composants de tierce partie Products.PloneArticle et Products.Collage fournissent des exemples de “non structural folder”. 269 Plone pour les intégrateurs, Version 1.0.0 tool Dans un contexte CMF, donc Plone, un “tool” est un objet unique dans un site fournissant un ensemble de services et incorporant ses propres données persistantes de configuration. Les tools se trouvent à la racine de Plone et leurs noms sont généralement préfixés par portal_. portal_properties abrite les feuilles de propriétés de Plone et de la plupart des composants d’extension de tierce partie. portal_catalog indexe les contenus du site... TTW Ou “Through The Web”. Qualifie généralement le paramétrage ou la programmation d’une application Zope depuis des formulaires accessibles uniquemant à un administrateur ou un auteur authentifié. La ZMI est le principal outil Zope de programmation ou de paramétrage TTW. type de contenu Traduction libre de content type. unified installer Bundle d’installation complète de Plone, incluant Python, Zope, Plone ainsi que tous les modules requis (PIL, elementtree, ...). L’unified installer est disponible pour Windows, Mac OSX et Linux. viewlet Une viewlet est responsable du rendu d’un composant de page, donc de la réalisation d’un bloc - generalement - HTML. Les viewlets sont généralement assemblées par un viewlet manager. viewlet manager Un viewlet manager permet d’assembler les viewlets. L’utilisation de viewlets et de viewlet managers permet une disposition plus souple des composants d’une page que les classiques macros ZPT ainsi que des performances de publication améliorées. virtualenv virtualenv est un outil permettant de créer des installations virtuelles de Python (presque) indépendantes du Python installé de façon globale dans votre système, de sorte que tout egg ajouté dans une installation virtuelle ne vient pas “polluer” votre installation globale. Par extension, on appelle un “virtualenv” tout environnement virtuel créé avec cet outil. Reportez-vous au chapitre Création d’un environnement isolé avec virtualenv pour plus de détails. Ou bien sur la page d’accueil de virtualenv widget Élément unitaire d’une page permettant au serveur de solliciter une information à l’utilisateur. Les widgets sont généralement assemblés dans un formulaire. Plone fournit bien évidemment tous les widgets standard du langage HTML (cases à cocher, boutons, listes déroulantes, champ de saisie de texte, ...). Ses divers composants, notamment la bibliothèque zope.formlib, KSS et Archetypes proposent des widgets plus évolués tel que des calendriers, éditeur WYSIWYG, arbres d’exploration, ... workflow Outil permettant de définir les différents états d’un élément, et les transitions permettant de passer d’un état à un autre. Pour chaque état, un sous-ensemble de permissions de cet élément fixe la limite les différents types d’accès à celui-ci. Par exemple pour interdire la vue à un utilisateur anonyme. L’exécution de chaque transitions est protégée de façon spécifique. Par exemple, seul un modérateur peut exécuter la transition “publier” Dans Pone, les workflows sont définis en ZMI à l’aide de l’outil DCWorkflow. Certains types d’éléments, comme l’image, ne sont pas associés à un workflow. ZCA Zope Component Architecture : Ensemble de services intégrés dans Zope 3, et adaptés à Zope 2 depuis sa version 2.9 par l’entremise de Five. La ZCA fournit les outils facilitant la collaboration entre objets et services de natures différentes concourant à la réalisation de fonctions applicatives, tout en évitant les pièges d’un héritage complexe de classes. Par exemple, vous disposez d’un composant (A) d’exploration AJAX d’arbre virtuel, d’un autre composant (B) gérant un contenu pouvant être représenté de façon arborescente, il vous suffira de fournir les adapteurs permettant d’explorer le contenu des objets fournis par B à l’aide des widgets fournis par A. Ceci ne peut bien entendu être possible que si ces deux composants exposent les ressources ZCA (généralement des interfaces) permettant ceci. L’utilisation de la ZCA, entamée par Plone depuis sa version 2.5, se généralise depuis sa version 3. Plus de détails dans concepts_zope3. zc.buildout voir buildout. ZCML Zope Configuration Markup Language : Langage basé sur XML permettant de configurer des composants ou produits pour Zope ou Plone dans des fichiers configure.zcml ou overrides.zcml. zexp Format binaire d’exportation et d’importation d’un objet (et éventuel sous-objets) de la ZODB. Pour exporter ou importer un fichier au format zexp, cliquez le bouton Import/Export et suivez les instructions. ZODB Zope Object Data Base : base de données objets native de Zope. ZMI Zope Management Interface : Interface Web de paramétrage et contrôle d’une instance Zope, permettant l’exploration de la ZODB. 270 Chapitre 23. Glossaire CHAPITRE 24 Indexes et tables – genindex – modindex – search 271 Plone pour les intégrateurs, Version 1.0.0 272 Chapitre 24. Indexes et tables CHAPITRE 25 Contributeurs – – – – Vincent Fretin Gilles Lenfant Thomas Desvenain Michaël Launay 273 Plone pour les intégrateurs, Version 1.0.0 274 Chapitre 25. Contributeurs Index Symbols multiplugin, 268 élément, 268 P A part, 268 parts, 268 PAS, 268 paster, 268 PATH, 95, 268 permission, 268 permissions, 268 plugin, 269 PMI, 269 policy package, 269 portlet, 269 principal, 269 product, 269 produit, 269 profil, 269 profile, 269 propertysheet, 269 pypi, 269 pywin32, 269 adaptateur, 267 adapter, 267 AT, 267 B brain, 267 buildout, 267 C C, 267 component, 267 composant, 267 configlet, 267 content type, 267 D distribute, 267 distutils, 268 dotted name, 268 E egg, 268 eggs, 268 G groupe, 268 I i18n, 268 interface, 268 invite de commandes, 268 R rôle, 269 recipe, 269 S SSO, 269 structural folder, 269 T tool, 270 TTW, 270 type de contenu, 270 L U l10n, 268 unified installer, 270 M V msi installer, 268 variable d’environnement 275 Plone pour les intégrateurs, Version 1.0.0 PATH, 95 viewlet, 270 viewlet manager, 270 virtualenv, 270 W widget, 270 workflow, 270 Z zc.buildout, 270 ZCA, 270 ZCML, 270 zexp, 270 ZMI, 270 ZODB, 270 276 Index