< < | (should be later moved to : http://planetoweb.cesr.fr/twiki/bin/view/Team/EuroplanetProject )
Réalisation d'un site web générique de projet en s'inspirant du site Europlanet : GWIS (Generic Web Information System)
Il s'agit de concevoir un système d'information web professionnel à l'aide d'un framework Php nommé Cakephp (http://cakephp.org )
Pour cakephp, voir aussi http://bakery.cakephp.org/
Nouvelle version 2.1.1 sortie le 26/3/12 : http://bakery.cakephp.org/articles/lorenzo/2012/03/26/cakephp_2_1_1_and_1_3_15_released
Version 2.1.0 sortie le 5/3/12
Version en cours : http://cakephp.lighthouseapp.com/projects/42648-cakephp/milestones/current
Roadmaps (pas très à jour) :
Code completion for cakephp in Eclipse : http://mark-story.com/posts/view/code-completion-for-cakephp-in-eclipse
ROADMAP (PLAN OF WORK, CAHIER DES CHARGES)
Ne pas oublier de noter tout ce que tu fais. Rédige au fur et à mesure (avec OpenOffice).
NOUVELLES MODIFS FAITES :
4 juin :
16 mai :
15 mai :
14 mai :
3 mai :
- section VI-3 (lost password)
5 Avril :
Plus tard :
- (pas encore sûr, à réfléchir) ajouter un script qui permet de définir un tableau de champs obligatoires pour un Modèle donné ==> Ces champs devront obligatoirement être saisis dans les vues associées au Modèle (voir http://book.cakephp.org/1.3/view/1147/required
)
I - Installation des outils
Serveur web+php+mysql Xampp : Télécharger et installer un serveur web apache/php/mysql avec xampp pour windows, c'est très facile : http://www.apachefriends.org/fr/xampp-windows.html
Framework php CakePhp : Télécharger et installer cakephp, la version 2.1 (la plus récente, bientôt officielle)
IDE Eclipse : Télécharger et installer Eclipse + plugin PDT pour php
II - Familiarisation avec Cakephp : Lecture documentation + test des tutoriels
http://cakephp.org/ (la doc de la version 2 est ici : http://book.cakephp.org/2.0/en )
1) Lire le MVC : http://book.cakephp.org/2.0/en/cakephp-overview/understanding-model-view-controller.html
Lire un peu plus sur le sujet :
- les Controlleurs : http://book.cakephp.org/2.0/en/controllers.html
- les Vues : http://book.cakephp.org/2.0/en/views.html
- les Modèles : http://book.cakephp.org/2.0/en/models.html
2) tester les tutoriels sur le "blog" :
a) tester le tutoriel cakephp "blog", très simple : http://book.cakephp.org/2.0/en/tutorials-and-examples/blog/blog.html
b) tester la 2e partie du tutoriel "blog" : http://book.cakephp.org/2.0/en/getting-started.html#blog-tutorial-adding-a-layer
3) comprendre la génération de code avec l'outil important de cakephp : "bake"
http://book.cakephp.org/2.0/en/console-and-shells/code-generation-with-bake.html
4) AUTH et ACL :
Tester le tutoriel blog avec l'ajout de auth et acl : http://book.cakephp.org/2.0/en/tutorials-and-examples/blog-auth-example/auth.html
(voir aussi ce tutoriel plus complet : part1 http://book.cakephp.org/2.0/en/tutorials-and-examples/simple-acl-controlled-application/simple-acl-controlled-application.html , part2 http://book.cakephp.org/2.0/en/tutorials-and-examples/simple-acl-controlled-application/part-two.html )
doc sur AUTH : http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html
doc sur ACL : http://book.cakephp.org/2.0/en/core-libraries/components/access-control-lists.html
5) important aussi, disponible uniquement depuis cakephp 2.1, la gestion des événements : http://book.cakephp.org/2.0/en/core-libraries/events.html
6) A lire aussi, le cycle de développement complet :
http://book.cakephp.org/2.0/en/development.html
surtout lire :
- Exceptions
- Error Handling
- Debugging
- Testing
III - En s'inspirant du tutoriel "blog", commmencer à construire une architecture à partir d'un sous-ensemble de la BDD Europlanet
1) Ce projet est géré en versions avec subversion (plugin Eclipse subclipse)
2) Construire un schéma d'une petite BDD avec MysqlWorkbench
Ce schéma contient 7 tables principales :
- people (lien N-1 avec institutes, status, et profiles, et 1-N avec resources) : id, name, firstname, email, password, status, active, job, created, updated (le champ "active" est un booléen VRAI par défaut)
- status : id, name (avec les valeurs suivantes pour name : NULL, 'registered', 'invalidated', 'validated')
- profiles : id, name, level (level indique la hiérarchie ; name et level ont les valeurs suivantes : {'admin',10}, {'priv',5}, {'validator',3}, {'normal',0} ; donc on a la hiérarchie admin > priv > validator > normal)
- institutes : id, name, created, updated
- expertises : id, name (lien M-N avec people)
- resources (lien M-N avec sciencases) : id, name, created, updated
- sciencecases : id, name, created, updated
Pour gérer les relation M-N, il faudra créer les tables intermédiaires suivantes (voir la convention de nommage dans cakephp : http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasandbelongstomany-habtm ) :
- resources_sciencecases : avec les champs resources_id et sciencecases_id (les 2 clés étrangères formant la clé primaire de la table)
- expertises_people : avec les champs expertises_id et people_id (les 2 clés étrangères formant la clé primaire de la table)
Tous les champs sont obligatoires (NOT NULL), sauf people.job (default NULL).
Toutes les clés primaires (id) sont autoincrémentées.
Les champs "created" et "updated" sont gérés automatiquement par cakephp.
Ajouter la contrainte "on delete CASCADE" (avec MysqlWorkbench) sur les clés étrangères des tables M-N (resources_sciencecases et expertises_people)
Ajouter la contrainte "on delete NULL" sur toutes les clés étrangères des autres tables (people, resources)
Générer le script sql de création de la base.
Vérifier que MysqlWorkbench ajoute bien les contraintes sur les clés étrangères (FK = "Foreign Key")
Alimenter les tables avec des données quelconques
3) Configurer l'accès à la BDD
login : epn
pass : pass
4) Avec l'outil "bake", construire un premier échafaudage (scaffolding) automatique MVC (modèles, vues, contrôleurs) + tests unitaires PhpUnit
http://book.cakephp.org/2.0/en/console-and-shells/code-generation-with-bake.html
(cake bake project …)
cake bake model all
cake bake controller all
cake bake view all
Par défaut, l'action "people/index" ne doit afficher que les personnes dont le champ "active" est à TRUE et le champ "status" vaut "validated"
5) Lancer les tests générés par "bake" (avec phpUnit, inclus dans Xampp ?) pour tester les modèles et les contrôleurs
http://book.cakephp.org/2.0/en/development/testing.html
cake bake fixture all ?
cake bake test all ?
Depuis cakephp 2.1 :
Console/cake test app/Model/Post.php
Console/cake test app/Controller/PostsController.php
6) Ajouter la validation des champs de tous les formulaires
http://book.cakephp.org/2.0/en/models/data-validation.html
"bake" ajoute des validations par défaut. Les étendre si nécessaire pour que toutes les validations soient générées automatiquement, en fonction du type des champs.
Vérifier que les champs obligatoires sont bien obligatoires en saisie.
Ajouter un test pour s'assurer qu'une personne est obligée de remplir tous les champs (sauf people.job) quand elle s'enregistre.
IV - Gestion du projet avec ICESCRUM
http://planetoweb2.cesr.fr:8080/icescrum
http://www.icescrum.org/
doc plus complète :
https://www.kagilum.com/fr/blog
ex : https://www.kagilum.com/fr/blog/les-taches-selon-son-role-icescrum/
Un diagramme des classes uml pour décrire SCRUM (intéressant à mettre dans le rapport de stage), et décrivant les 3 types de stories (user, technical et defect) :
http://www.aubryconseil.com/post/Un-%C3%A9l%C3%A9ment-du-backlog-de-produit
diagramme d'état uml pour montrer les différents états d'un élément du backlog (c'est à dire une feature ou une user story ; rappel : une feature = 1 grosse user story qui doit être décomposée en N user stories) :
http://www.aubryconseil.com/post/2007/06/21/251-les-etats-significatifs-d-un-element-de-backlog
V - Authentification et Contrôle d'accès
1) Ajouter l'authentification (AUTH)
Login = email
Auth (et Acl) doivent avoir pour support la table "people" (et status et profiles).
Auth (et Acl) impliquent aussi l'usage des Sessions (http://book.cakephp.org/2.0/en/development/sessions.html )
Astuce : dans la session, stocker l'id de la personne, et non pas son email (car l'email peut changer, mais pas l'id)
Toute personne non authentifiée (accès anonyme) peut :
- lire (R ) toutes les tables, sauf la table "resources"
- s'enregistrer (droit C sur la table people)
Toute personne authentifiée peut :
- lire (R ) toutes les tables (y-compris "resources")
- modifier (U) sa fiche (sauf son profil), mais pas celle des autres
- créer (C ) une ressource
- modifier/supprimer (UD) une ressource qu'elle a créée, mais pas celles des autres
- modifier (U) un institut auquel elle appartient
Gérer le login et le logout
Ajouter les tests nécessaires :
(Utiliser des "fixtures", cf section "Fixtures" dans http://book.cakephp.org/2.0/en/development/testing.html )
(cake bake fixture all ?)
Tester qu'une personne non authentifiée :
- peut lire la table 'resource'
- peut s'enregistrer
- ne peut pas modifier une table
Tester qu'une personne authentifiée peut :
…
Faire un test login/logout complet selon le scénario suivant :
- une personne se logue
- vérifier qu'elle peut créer une ressource
- elle se délogue
- vérifier qu'elle ne peut plus créer une ressource
2) Ajouter le contrôle d'accès (ACL)
Créer quelques personnes avec des rôles (profils) différents :
- 'user1', profil 'admin' (tous les droits)
- 'user2' et 'user3', profil 'normal', utilisateur normal
- 'user4', profil 'priv', utilisateur privilégié
- 'user5', profil 'validator', utilisateur pouvant valider d'autres utilisateurs
Une personne de profil 'admin' a un droit CRUD (créer/lire/modifier/supprimer) sur toutes les tables.
Une personne de profil 'priv' :
- a un droit CRUD seulement sur la table 'institutes'
- peut modifier le profil de toutes les personnes (sauf le sien)
Ajouter les tests nécessaires :
- tester que 'user1' peut tout faire (faire juste quelques tests, pas tout)
- tester que 'user4' : * peut ajouter un nouvel institut * peut modifier le profil d'une personne (mais pas le sien)
- tester que 'user2' : * ne peut pas modifier une ressource qui ne lui appartient pas * peut ajouter une nouvelle ressource, et la modifier ensuite * peut modifier son email (login) et/ou son mot de passe
...
VI - ENREGISTREMENT DES UTILISATEURS (registration)
1) Réalisation de la procédure d'enregistrement (inscription) d'une personne :
(voir s'il n'existe pas déjà un plugin cakephp pour gérer ça, car c'est assez classique au début)
a) une personne remplit sa fiche d'enregistrement et la soumet (SUBMIT) ==> elle est enregistrée dans la table people avec "status" à NULL
b) elle reçoit un 1er mail de confirmation avec un lien de validation
c) elle clique sur le lien de validation, ce qui valide son inscription ==> son champ "status" passe à "registered" ; les validateurs reçoivent un mail pour les avertir de cette inscription, avec un lien vers la page du site permettant de valider ou invalider la personne
d) elle reçoit un 2e mail de confirmation lui disant qu'elle est inscrite, MAIS qu'elle doit attendre que son inscription soit validée par un 'validateur', et qu'elle recevra un mail pour le lui confirmer
e) si un validateur valide l'inscription, la personne reçoit un mail pour l'en informer (à partir de là, elle peut se connecter au site) ==> son "status" passe à "validated"
f) si un validateur invalide l'inscription, la personne reçoit un mail pour l'en informer ==> son "status" passe à "invalidated"
Ajouter les actions suivantes au Contrôleur "person" :
- validate (profil 'validator') : pour valider une personne (champ "status")
- invalidate (profil 'validator') : pour invalider une personne
- deleteInvalidated (profil 'priv') : pour supprimer les personnes ayant un statut "invalidated"
- activate (profil 'priv') : pour activer une personne (champ "active")
- deactivate (profil 'priv') : pour désactiver une personne
Ajouter/modifier les tests nécessaires
2) Ajouter un captcha sur la fiche d'inscription
Ajouter/modifier les tests nécessaires :
- tester qu'une personne ne peut pas s'enregistrer si le captcha n'est pas bon
- tester qu'une personne peut s'enregistrer si le captcha est bon (et tout le reste)
3) Récupération du mot de passe (lost password)
Sur le formulaire de login, ajouter (à droite du bouton LOGIN) un lien "register" (pour s'enregistrer) et un lien "forgot password" (mot de passe oublié)
Le lien "forgot password" pointe vers un formulaire de modification du mot de passe (Person/PasswordUpdate) contenant juste 1 champ "email" et un bouton "SUBMIT"
L'utilisateur saisit son email et clique sur "submit" pour qu'on lui envoie un nouveau mot de passe par mail (le mot de passe est aussi mis à jour dans la database)
Test
4) Procédure de désinscription (ACTION unregister)
a) une personne clique sur un lien "unregister"
b) une confirmation est demandée via une fenêtre javascript : "Are you sure that you want to unregister ?" OK/CANCEL
c) l'action "unregister" est exécutée, la personne n'est pas supprimée de la base, mais juste marquée "inactive"
d) la personne est automatiquement déconnectée
e) Test
VII - Améliorer le CRUD
1) Bien gérer complètement les relations 1-N
Actions sur Person (relation N-1 avec Institute) :
- create : doit permettre d'associer la personne à un institut (via liste de noms)
- update : doit permettre de modifier l'institut associé (via liste de noms)
- index : doit permettre de voir toutes les personnes avec le nom (name) de l'institut associé ; un clic sur un institut doit amener à sa vue détaillée
- view : doit afficher le nom (name) de l'institut associé
Action sur Institute (relation 1-N avec Person) :
- view : doit afficher toutes les personnes associées
2) Bien gérer complètement les relations M-N
Actions sur Person (relation M-N avec Expertise) :
- create : doit permettre d'ajouter des expertises (ET une date "since")
- update : doit permettre de modifier les expertises associées
- view : doit permettre de voir toutes les expertises associées
Idem pour Expertise (lien vers Person)
Même chose pour Resource (relation M-N avec Sciencecase)
Gestion des champs supplémentaires d'une table associative : exemple de la relation entre Person et Expertise :
- expertises_people : avec les champs expertises_id et people_id (les 2 clés étrangères formant la clé primaire de la table) et le champ supplémentaire "since" (date à laquelle l'expertise a été acquise)
3) Gérer d'autres types de relations
a) Ajout de plusieurs rôles différents entre 2 mêmes tables
voir http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#multiple-relations-to-the-same-model
Une personne peut avoir plusieurs liens avec une ressource (plusieurs liens entre les tables "people" et "resources"), ce qui veut dire qu'elle peut jouer plusieurs rôles par rapport à une ressource.
Ainsi, au lieu d'avoir seulement une clé étrangère "resources_id" dans la table "people", nous en aurons plusieurs avec des noms différents :
- resource_provider_id : la personne qui a donné l'information sur la ressource (et qui l'a saisit)
- resource_owner_id : le propriétaire de la ressource
- resource_contact_id : le contact pour la ressource
Ces 3 clés pointent toutes vers la même clé primaire resource.id, et sont donc des "alias".
Améliorer les actions CRUD en conséquence
b) Relation réflexive (d'une table sur elle-même)
Ajout d'une relation réflexive sur "institutes" (dans ce cas particulier, il s'agit d'une relation hiérarchique) :
- un institut peut appartenir à un autre institut (de niveau hiérarchique supérieur ; par exemple, le "CNRS" regroupe plusieurs instituts, "l'OMP" regroupe plusieurs laboratoires dont l'IRAP…)
- cela revient seulement à ajouter un champ "institute_id" dans la table institutes (qui pointe sur la table institute, lien réflexif)
- améliorer les actions CRUD en conséquence
c) Relation d'héritage ou spécialisation (1:1)
Une ressource peut être de différents types (ajouter la table "resourcetype") :
- data
- info (information, document...)
- website
- datacenter
chaque type de ressource est une spécialisation du type général "resource".
On aura donc 4 nouvelles tables filles "resourcedata", "resourceinfo", "resourcewebsite", "resourcedatacenter" qui "hériteront" de la table mère (générique) "resource" pour l'étendre chacune avec sa spécificité.
On peut représenter ce lien d'héritage par une relation 1-1 entre chacune de ces 4 tables filles et la table mère "resource".
Aucune des tables filles n'a d'existence propre, chacune dépend de la table mère "resource".
Ainsi, les tables filles n'ont pas de clé primaire, mais juste une clé étrangère (resource_id) qui pointe vers la clé primaire de la table mère (cette clé étrangère peut aussi leur servir de clé primaire).
Cette relation d'héritage a un impact sur toutes les VUES de la table "resource", car à chaque fois qu'on veut accéder à une ressource,
il faut récupérer aussi les informations spécifiques à son type dans la table fille associée (via la clé étrangère resource_id).
Plus particulièrement, la vue "Create" (et "Update") devra contenir un sélecteur de type ("Type de ressource"),
et n'afficher que les champs spécifiques au type sélectionné (en plus des champs généraux de la table mère).
Ajouter dans la table resource un champ "URL" (général à tous les types)
Voici les informations spécifiques à chaque type, et donc présent dans les tables filles respectives :
- table data :
- volume (en MB) :
- restricted (oui/non)
- table info (information, document...) :
- langage (champ texte liste : English, French, Spanish...)
- table website :
- restricted (oui/non)
- nom du webmaster (champ texte libre)
- table datacenter :
- nom du responsable (champ texte libre)
4) Ajouter les nouveaux tests nécessaires
VIII - Ajout d'une nouvelle action dans TOUS les Contrôleurs : search
ex : Person/search
Cela amène à une nouvelle vue PersonSearch qui est équivalente au formulaire de Person/create,
sauf qu'au lieu de servir à créer une nouvelle personne, il sert à en CHERCHER.
L'ensemble des personnes trouvées sont affichées dans une vue "FOUND" semblable à Person/index (sauf que c'est une vue PARTIELLE et non pas COMPLETE).
Les recherches se font sans tenir compte des majuscules ou minuscules.
En bas du formulaire, 2 boutons :
Exemples de requêtes possibles :
- j'entre "Pallier" dans le champ "name" :
- un clic sur "EXACT SEARCH" me donne la liste des personnes dont le nom EST EGAL à "Pallier"
- un clic sur "SEARCH" me donne la liste des personnes dont le nom CONTIENT "Pallier", par exemple "Apallieri"...
- j'entre "Pallier" dans le champ "name", "Etienne" dans le champ "firstname", et "informaticien" dans le champ "job" :
- un clic sur "EXACT SEARCH" me donne la liste des personnes dont le nom EST EGAL à "Pallier" ET le prénom EST EGAL à "Etienne" ET le job EST EGAL à "informaticien"
- un clic sur "SEARCH" me donne la liste des personnes dont le nom CONTIENT "Pallier" ET le prénom CONTIENT "Etienne" et le job CONTIENT "informaticien"
Cette VUE "search" doit être accessible par un lien qui se trouve au début de la vue "index", sous la forme d'une icône en forme de LOUPE suivie de la mention "Search"
Faire les tests d'acceptation (ACCEPTANCE TESTS)
IX - Améliorer les vues
1) ajouter les liens généraux suivants :
- "login" (qui n'apparaît que si l'utilisateur n'est pas logué)
- et les liens "logout", "update my registration" et "unregister" (qui n'apparaissent que si l'utilisateur est logué)
2) Vue "view" : vue détaillée d'une ligne de table
Ajouter une checkbox "Show dates" (visible uniquement avec profil "admin"), désactivée par défaut : quand on l'active, il faut afficher les dates (created, updated)
Ajouter les boutons "Edit", "Delete" et "Create a copy" (visibles uniquement avec le profil "admin")
Pour le formulaire Person, le bouton "Edit" est aussi visible si la personne connectée correspond à la fiche visualisée.
3) Action "index" : vue globale d'une table
Ajouter une checkbox "Show dates" (visible uniquement avec profil "admin"), désactivée par défaut : quand on l'active, il faut afficher les dates (created, updated)
Masquer la clé primaire (id)
La colonne du champ "name" est triable : en cliquant sur la colonne "name", on trie en ordre croissant, puis décroissant
Le champ "name" est cliquable : en cliquant sur un nom, on va à la vue détaillée correspondante
Afficher le champ "name" des clés étrangères ; en cliquant dessus on va sur la vue détaillée
Les colonnes des clés étrangères sont filtrables : dans la vue people/index, en cliquant sur la colonne "institutes_id" on doit pouvoir sélectionner un nom d'institut (name) et filtrer la vue en conséquence
Au-dessus de la liste d'une table, ajouter un "filtre externe" pour chaque table M-N associée :
par exemple, pour la vue people/index, ajouter au-dessus de la liste des personnes une liste d'expertises : en sélectionnant une expertise, on ne voit plus que les personnes associées à cette expertise
En début de page, ajouter un bouton "Add a new one"
4) Ajouter les nouveaux tests nécessaires
5) Ajouter une page contenant tous les tests, avec un bouton permettant de lancer tous les tests à la suite "LAUNCH ALL TESTS"
X - Documentation
Installer phpdocumentor v2 et l'intégrer dans eclipse (http://www.phpdoc.org ) :
phpdocumentor respecte les standards de codage du format phpdoc : http://en.wikipedia.org/wiki/PHPDoc
Suivre les standards de codage de cakephp 2 : http://book.cakephp.org/2.0/en/contributing/cakephp-coding-conventions.html
XI - Ajout d'un menu
Ajout d'une gestion de menu
XII - Ajout de modules
Ajout d'un module de News
Ajout d'un module d'upload de documents
Newsletter
...
XIII - Charte graphique
Gestion de la présentation avec CSS
...
XIV - Intégrer la BDD Europlanet complète
Annexe : A lire aussi
Associations : http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html
Callback : http://book.cakephp.org/2.0/en/models/callback-methods.html
Behaviors : http://book.cakephp.org/2.0/en/models/behaviors.html
Transactions : http://book.cakephp.org/2.0/en/models/transactions.html
Virtual fields : http://book.cakephp.org/2.0/en/models/virtual-fields.html
-- EtiennePallier - 25 Dec 2009 |