--- a/doc/devmanual_fr/chap_fondements_cubicweb.txt Tue Nov 11 14:24:58 2008 -0800
+++ b/doc/devmanual_fr/chap_fondements_cubicweb.txt Tue Nov 11 14:27:19 2008 -0800
@@ -100,6 +100,233 @@
.. _`yams`: http://www.logilab.org/project/name/yams/
+Moteur `CubicWeb`
+-----------------
+Le moteur web de cubicweb consiste en quelques classes gérant un ensemble d'objets
+chargés dynamiquement au lancement de cubicweb. Ce sont ces objets dynamiques, issus
+du modèle ou de la librairie, qui construisent le site web final. Les différents
+composants dynamiques sont par exemple :
+
+* coté client et serveur
+
+ - les définitions d'entités, contenant la logique permettant la manipulation des
+ données de l'application
+
+* coté client
+
+ - les *vues* , ou encore plus spécifiquement
+
+ - les boites
+ - l'en-tête et le pied de page
+ - les formulaires
+ - les gabarits de pages
+
+ - les *actions*
+ - les *controleurs*
+
+* coté serveur
+
+ - les crochets de notification
+ - les vues de notification
+
+Les différents composants du moteur sont :
+
+* un frontal web (seul twisted disponible pour le moment), transparent du point
+ de vue des objets dynamiques
+* un objet encapsulant la configuration
+* un `vregistry` (`cubicweb.cwvreg`) contenant les objets chargés dynamiquements
+
+Détail de la procédure d'enregistrement
+---------------------------------------
+Au démarage le `vregistry` ou base de registres inspecte un certain nombre de
+répertoires à la recherche de définition de classes "compatible". Après une
+procédure d'enregistrement les objets sont affectés dans différents registres
+afin d'être ensuite séléctionné dynamiquement pendant le fonctionnement de
+l'application.
+
+La classe de base de tout ces objets est la classe `AppRsetObject` (module
+`cubicweb.common.appobject`).
+
+
+API Python/RQL
+--------------
+
+Inspiré de la db-api standard, avec un object Connection possédant les méthodes
+cursor, rollback et commit principalement. La méthode importante est la méthode
+`execute` du curseur :
+
+`execute(rqlstring, args=None, eid_key=None, build_descr=True)`
+
+:rqlstring: la requête rql à éxécuter (unicode)
+:args: si la requête contient des substitutions, un dictionnaire contenant les
+ valeurs à utiliser
+:eid_key:
+ un détail d'implémentation du cache de requêtes RQL fait que si une substitution est
+ utilisée pour introduire un eid *levant des ambiguités dans la résolution de
+ type de la requête*, il faut spécifier par cet argument la clé correspondante
+ dans le dictionnaire
+
+C'est l'objet Connection qui possède les méthodes classiques `commit` et
+`rollback`. Vous ne *devriez jamais avoir à les utiliser* lors du développement
+d'interface web sur la base du framework CubicWeb étant donné que la fin de la
+transaction est déterminée par celui-ci en fonction du succès d'éxécution de la
+requête.
+
+NOTE : lors de l'éxécution de requêtes de modification (SET,INSERT,DELETE), si une
+requête génère une erreur liée à la sécurité, un rollback est systématiquement
+effectuée sur la transaction courante.
+
+
+La classe `Request` (`cubicweb.web`)
+------------------------------------
+Une instance de requête est créée lorsque une requête HTTP est transmise au
+serveur web. Elle contient des informations telles que les paramètres de
+formulaires, l'utilisateur connecté, etc.
+
+**De manière plus générale une requête représente une demande d'un utilisateur,
+que se soit par HTTP ou non (on parle également de requête rql coté serveur par
+exemple)**
+
+Une instance de la classe `Request` possède les attributs :
+
+* `user`, instance de`cubicweb.common.utils.User` correspondant à l'utilisateur
+ connecté
+* `form`, dictionaire contenant les valeurs de formulaire web
+* `encoding`, l'encodage de caractère à utiliser dans la réponse
+
+Mais encore :
+
+:Gestion des données de session:
+ * `session_data()`, retourne un dictionaire contenant l'intégralité des
+ données de la session
+ * `get_session_data(key, default=None)`, retourne la valeur associée à
+ la clé ou la valeur `default` si la clé n'est pas définie
+ * `set_session_data(key, value)`, associe une valeur à une clé
+ * `del_session_data(key)`, supprime la valeur associé à une clé
+
+
+:Gestion de cookie:
+ * `get_cookie()`, retourne un dictionnaire contenant la valeur de l'entête
+ HTTP 'Cookie'
+ * `set_cookie(cookie, key, maxage=300)`, ajoute un en-tête HTTP `Set-Cookie`,
+ avec une durée de vie 5 minutes par défault (`maxage` = None donne un cooke
+ *de session"* expirant quand l'utilisateur ferme son navigateur
+ * `remove_cookie(cookie, key)`, fait expirer une valeur
+
+:Gestion d'URL:
+ * `url()`, retourne l'url complète de la requête HTTP
+ * `base_url()`, retourne l'url de la racine de l'application
+ * `relative_path()`, retourne chemin relatif de la requête
+
+:Et encore...:
+ * `set_content_type(content_type, filename=None)`, place l'en-tête HTTP
+ 'Content-Type'
+ * `get_header(header)`, retourne la valeur associé à un en-tête HTTP
+ arbitraire de la requête
+ * `set_header(header, value)`, ajoute un en-tête HTTP arbitraire dans la
+ réponse
+ * `cursor()` retourne un curseur RQL sur la session
+ * `execute(*args, **kwargs)`, raccourci vers .cursor().execute()
+ * `property_value(key)`, gestion des propriétés (`EProperty`)
+ * le dictionaire `data` pour stocker des données pour partager de
+ l'information entre les composants *durant l'éxécution de la requête*.
+
+A noter que cette classe est en réalité abstraite et qu'une implémentation
+concrète sera fournie par le *frontend* web utilisé (en l'occurent *twisted*
+aujourd'hui). Enfin pour les vues ou autres qui sont éxécutés coté serveur,
+la majeure partie de l'interface de `Request` est définie sur la session
+associée au client.
+
+
+La classe `AppObject`
+---------------------
+
+En général :
+
+* on n'hérite pas directement des cette classe mais plutôt d'une classe
+ plus spécifique comme par exemple `AnyEntity`, `EntityView`, `AnyRsetView`,
+ `Action`...
+
+* pour être enregistrable, un classe fille doit définir son registre (attribut
+ `__registry__`) et son identifiant (attribut `id`). Généralement on n'a pas à
+ s'occuper du registre, uniquement de l'identifiant `id` :)
+
+On trouve un certain nombre d'attributs et de méthodes définis dans cette classe
+et donc commune à tous les objets de l'application :
+
+A l'enregistrement, les attributs suivants sont ajoutés dynamiquement aux
+*classes* filles:
+
+* `vreg`, le `vregistry` de l'application
+* `schema`, le schéma de l'application
+* `config`, la configuration de l'application
+
+On trouve également sur les instances les attributs :
+
+* `req`, instance de `Request`
+* `rset`, le "result set" associé à l'objet le cas échéant
+* `cursor`, curseur rql sur la session
+
+
+:Gestion d'URL:
+ * `build_url(method=None, **kwargs)`, retourne une URL absolue construites à
+ partir des arguments donnés. Le *controleur* devant gérer la réponse
+ peut-être spécifié via l'argument spécial `method` (le branchement est
+ théoriquement bien effectué automatiquement :).
+
+ * `datadir_url()`, retourne l'url du répertoire de données de l'application
+ (contenant les fichiers statiques tels que les images, css, js...)
+
+ * `base_url()`, raccourci sur `req.base_url()`
+
+ * `url_quote(value)`, version *unicode safe* de de la fonction `urllib.quote`
+
+:Manipulation de données:
+
+ * `etype_rset(etype, size=1)`, raccourci vers `vreg.etype_rset()`
+
+ * `eid_rset(eid, rql=None, descr=True)`, retourne un objet result set pour
+ l'eid donné
+ * `entity(row, col=0)`, retourne l'entité correspondant à la position données
+ du "result set" associé à l'objet
+
+ * `complete_entity(row, col=0, skip_bytes=True)`, équivalent à `entity` mais
+ appelle également la méthode `complete()` sur l'entité avant de la retourner
+
+:Formattage de données:
+ * `format_date(date, date_format=None, time=False)`
+ * `format_time(time)`,
+
+:Et encore...:
+
+ * `external_resource(rid, default=_MARKER)`, accède à une valeur définie dans
+ le fichier de configuration `external_resource`
+
+ * `tal_render(template, variables)`,
+
+
+**NOTE IMPORTANTE**
+Lorsqu'on hérite d'`AppObject` (même indirectement), il faut **toujours**
+utiliser **super()** pour récupérer les méthodes et attributs des classes
+parentes, et pas passer par l'identifiant de classe parente directement.
+(sous peine de tomber sur des bugs bizarres lors du rechargement automatique
+des vues). Par exemple, plutôt que d'écrire::
+
+ class Truc(PrimaryView):
+ def f(self, arg1):
+ PrimaryView.f(self, arg1)
+
+Il faut écrire::
+
+ class Truc(PrimaryView):
+ def f(self, arg1):
+ super(Truc, self).f(arg1)
+
+
+
+
+
+
Structure standard d'un cube
----------------------------