Documentation sur le travail avec les éléments dans CP3.

Présentation

Si CPS 2 utilisait les macros pour représenter les pages, CPS 3 marque l'arrivée d'une nouvelle approche: les éléments.

A l'usage, l'outil s'utilise comme un dictionnaire. Chaque clé est le nom de l'élement (par convention en majuscule) et la valeur de cette clé est la méthode à appeler dans un contexte précis. Ce contexte étant lui-même un élement.

Objectifs

L'utilisation des éléments se caractérise d'une part par la présence d'un outil nommé portal_elements, et d'autre part par l'utilisation d'un format spécifique pour les méthodes de rendu.

L'utilisation de l'outil portal_elements en tant que dictionnaire permet aussi de passer des variables d'une page à l'autre.

Enfin, chaque élément peut se voir attribuer un niveau de cache, de façon à minimiser la quantité de calcul nécessaire au rendu d'une page et l'actualisation du contenu.

Premier contact

L'outil portal_elements dispose de quatre éléments de base:
CONTEXT
L'objet en cours d'utilisation ou par défaut équivalent à PORTAL.
CONTAINER
L'objet conteneur du contexte ou par défaut équivalent à PORTAL.
PORTAL
L'objet qui représente la racine du site CPS.
REQUEST
Le même objet REQUEST que celui en attribut de context.

Il existe aussi deux élements importants mais qu'il faut implémenter, car ce sont justement ceux qui vont nous permettre de personnaliser les pages:

MAIN
C'est dans cet élément que s'insère l'appel à la méthode de rendu de l'objet en cours. Autrement dit, c'est la partie principale de la page (à rapprocher de la balise metal:fill-slot="main" dans CPS 2). Tout ce qui est autour (boîtes, logos, ...) est calculé ailleurs.
DISPLAY
C'est le dernier élément à être appelé car il déclenche l'appel à la méthode de rendu final (l'équivalent du main_template.pt dans CPS 2).

Fort de ces connaissances, nous allons écrire un nouvel élement: PORTAL_URL.

Allez pour cela, avec la ZMI, à la racine d'un site CPS 3 puis dans portal_elements. En bas se trouve un formulaire titré Add a new default element. Remplissons le formulaire:

Nous avons ainsi créé un élément qui est équivalent à:

      PORTAL_URL = PORTAL.absolute_url()

À titre d'exercice, créez un element TITLE qui retourne le titre (ou l'id) du contexte. Nous l'utiliserons par la suite.

En pratique: l'écriture de templates

L'utilisation des éléments met en avant les scripts plutôt que les templates. Créons donc pour commencer une méthode 'index_html.py':

      elements = here.portal_elements.getElements(object=context)

      elements['MAIN'] = "<h2>Bienvenue dans CPS 3</h2>

      return elements['DISPLAY']
Quelques remarques:

Créons maintenant ce fameux élément DISPLAY. Toujours dans portal_elements, Ajouter celui-ci:

L'appel à DISPLAY va donc déclencher l'appel à la méthode element_display dont voici un exemple de code:

      ##parameters=

      elements = context.portal_elements.getElements(object=context)

      pp = elements['REQUEST'].form.get('pp', 0)

      if pp:
          return context.main_printable_display()
      else:
          return context.main_browser_display()

Intéressons-nous maintenant à cette méthode 'main_browser_display':

      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
      <html tal:define="
        elements here/portal_elements/getElements;
        portal_url elements/PORTAL_URL;
        title elements/TITLE;
        ">
        <head>
          <title tal:content="title">Titre</title>
        </head>
        <body>
          <h2 tal:content="title">Titre</h2>

          <div tal:content="structure elements/MAIN">
            Contenu de la page
          </div>
        </body>
      </html>

Bien entendu, cette page pourra être plus complexe en faisant appel à des éléments qui calculent des boites ou les balises pour insérer un logo en fonction du contexte (par exemple, un logo par site).

Le code de main_printable_display est laissé en exercice.

Il est temps de voir ce que donne cette page en accédant à:

      http://serveurzope:port/cps/

Ou son équivalent chez vous :) Bien sûr vous aviez écrit l'élement TITLE donné en exercice... ?

Ajoutons une ligne dans index_html.py pour avoir un petit aperçu de la puissance des éléments:

      elements['TITLE'] = "Bienvenue"

Placez cette ligne juste avant ou après celle qui appelle la méthode de rendu pour l'élément MAIN, en tout cas avant de déclencher le calcul de DISPLAY.

Rafraîchissez la page de votre navigateur pour voir que le titre est maintenant celui que vous avez placé.

Exemples d'éléments

Dans la ZMI:

'element_path.py':

      ##parameters=
      """
      Calcule le chemin d'accès jusqu'au contexte.
      """

      elements = context.portal_elements.getElements()
      portal = elements['PORTAL']
      ppath = portal.getPhysicalPath()

      l = []
      obj = context.this()
      while obj is not None:
          try:
              pp = obj.getPhysicalPath()
              l.insert(0, obj)
              if pp == ppath:
                  break
              obj = obj.getParentNode()
          except: # XXX Unauthorized
              continue

      bc = []
      for obj in l:
          if obj.getProperty('breadcrumb_skip') != 1:
              if obj is portal:
                  title = 'Accueil'
              else:
                  title = obj.title_or_id()
              if title.startswith('L_'):
                  # XXX revisit this when content types are internationalized
                  title = portal.portal_messages(title)
              url = obj.absolute_url()
              bc.append({
                  'title': title,
                  'url': url,
                  'object': obj,
              })

      return bc
Dans la ZMI:

'element_breadcrumb.pt':

      <div id="breadcrumb"
        <tal:block define="
            elements here/portal_elements/getElements;
            path elements/PATH"
          repeat="bc path"
          <a href="" title=""
            tal:define="
              title bc/title;
              len_title len(title)"
            tal:attributes="href string:${bc/url}/; title title"
            tal:content="python:len_title > 20 and title[:19]+'...' or title">
            Lien
          </a>
        </tal:block>
      </div>

Amusez-vous à ajouter ce breadcrumb à main_browser_display...

Regardons maintenant la méthode de vue d'un objet MailingList?. L'action view du portal type a été mis à mailinglist_view. Voici son code:

      ##parameters=

      elements = context.portal_elements.getElements(object=context)

      elements['CURRENT_ACTION'] = 'view'
      elements['MAIN'] = context.mailinglist_view_template()

      return elements['DISPLAY']

L'ancienne méthode de vue a été renommée mailinglist_view_template.pt et doit donc être appelée par ce script. Voici un apercu de son code:

      <tal:block define="
        elements here/portal_elements/getElements;
        current_action elements/CURRENT_ACTION;
        yes string:L_mailinglist oui;
        no string:L_mailinglist non;
        doc here/getContent;
        ">
        [...]

        Ici le code fonctionne comme avant... sauf l'appel aux macros bien sûr.

        [...]
      </tal:block>

Passer une template de CPS 2 à CPS 3

To be continued...

*Hervé Cauwelier*