Derniers billets de blog

Expert Python/Django/Plone et chef de projet agile, j'aime coder et découvrir de nouvelles technologies.

Plone 3 - Clean dashboard programmatically - Setup a custom dashboard

Plone 3 offers a default dashboard for each user. The dashboard is composed by four columns which are portlet managers and the set of portlet assignments created by default are: news, events, recent items and review list. If you need to clean existing dashboards or setup a different default set of portlets for the user dashboard, you are on the good place!

Clean all existing dashboards

from zope.component import adapts, queryUtility
from plone.portlets.interfaces import IPortletManager
from plone.app.portlets.storage import UserPortletAssignmentMapping
from plone.portlets.constants import USER_CATEGORY

def cleanDashboardFor(userid):
    for name in ('plone.dashboard1', 'plone.dashboard2',
                 'plone.dashboard3', 'plone.dashboard4'):
        column = queryUtility(IPortletManager, name=name)
        if column is not None:
            category = column.get(USER_CATEGORY, None)
            if category is not None:
                manager = category.get(userid, None)
                if manager is not None:
                    # overrides the manager with an empty mapping
                    del category[userid]
                    category[userid] = \
                          UserPortletAssignmentMapping(manager=name,
                                                       category=USER_CATEGORY,
                                                       name=userid)

# Remove all portlets from the users's dashboards
for userid in plone.Members.objectIds():
    cleanDashboardFor(userid)

Setup a custom dashboard

This how-to by Ricardo Alves explains how to setup the default set of portlets for the user dashboard.

Plone - Exclure des dossiers des résultats de recherche

Dans certains cas les clients demandent de ne pas inclure certains dossiers ou répertoires des résultats de recherche, ceci aussi bien pour les recherches effectuées depuis le portlet de recherche (live search) que depuis le formulaire de recherche avancées. Voici les solutions que j'ai trouvé en fouillant un peu les forums de Plone.

Le cas d'utilisation auquel j'ai été confronté:

  • L'ensemble des pages de l'ancien site ont été importées dans un dossiers "/archives".
  • Ces documents d'archives doivent rester en statut "publié" pour permettre aux visiteurs provenant des moteurs de recherche de ne pas tomber sur des erreurs 404.
  • L'utilisation du moteur de recherche ne doit pas retourner des documents provenant de "/archives".

Scripts réalisant les recherches dans Plone 3:

  • Lors de l'affichage de la page de résultats d'une recherche: CMFPlone/skins/plone_scripts/queryCatalog.py
  • Résultats instannés du "live search": Products/CMFPlone/skins/plone_scripts/livesearch_reply.py ou Products/NuPlone/skins/nuplone_templates/livesearch_reply.py

Solution 1: Utiliser le produit Products.AdvancedQuery

En considérant que le path absolu du répertoire contenant les archives est "/plone/archives", on peut remplacer la recherche classique (dans queryCatalog.py et livesearch_reply.py):

results = catalog(**query)

par une requête AdvancedQuery exluant "/plone/archives":

from Products.AdvancedQuery import Generic
advanced_query = catalog.makeAdvancedQuery(query) & ~ Generic('path','/plone/archives')
results = catalog.evalAdvancedQuery(advanced_query)

Inconvénient de cette solution: ça ne fonctionne pas si vous utilisez collective.solr comme moteur d'indexation.

Solution 2: Utiliser une propriété "search_me" associée à un indexe du portal_catalog

  1. Créer la propriété "search_me" (type booléen) à la racine du site Plone et lui donner la valeur "True".
  2. Créer la propriété "search_me" (type booléen) sur le répertoire "archives" et lui donner la valeur "False".
  3. Créer l'indexe "search_me" (type field) dans le portal_catalog et réindexer le contenu du site.
  4. Modifier queryCatalog.py et livesearch_reply.py pour étendre les recherches effectuéesavec le critère "search_me=True".

Solution 3 : Filter manuellement les résultats de recherche

Dans queryCatalog.py et livesearch_reply.py, une fois la recherche effectée, filtrer manuellement en bouclant sur la liste de résultats.

exclude_url = 'http://monsite.com/archives'
filtered_results = []
for el in results:
    if not el.getURL().startswith(exclude_url):
        filtered_results.append(el)

Inconvénient de cette solution : cela impacte les performances lorsque le nombre d'éléments retourné par la recherche est important.

Two new blueprints for plone.app.transmogrifier: Indexing and UserConstructor

I added two new blueprints to plone.app.transmogrifier: plone.app.transmogrifier.reindexobject which allows to reindex an existing object in the portal_catalog and plone.app.transmogrifier.userconstructor which allows to add users to the portal. collective.transmogrifier is a configurable pipeline, aimed at transforming content for import and export. plone.app.transmogrifier offers Plone blueprints for collective.transmogrifier pipelines.

Indexing section

A ReindexObject section allows you to reindex an existing object in the portal_catalog. ReindexObject sections operate on objects already present in the ZODB, be they created by a constructor or pre-existing objects.

The ReindexObject blueprint name is ``plone.app.transmogrifier.reindexobject``.

UserConstructor section
A UserConstructor section allows you to add users to the portal.

The UserConstructor blueprint name is "plone.app.transmogrifier.userconstructor".

Links

Découverte de Singing & Dancing - Envoyer vos newsletters avec Plone !

Ce document est la traduction française de l'introduction à Singing & Dancing de Daniel Nouri. Il vous guidera à travers les fonctionnalités les plus importantes de Singing & Dancing. Vous apprendrez comment configurer le produit et vos bulletins d'informations.

Découverte de Singing & Dancing

Ce document vous guidera à travers les fonctionnalités les plus importantes de Singing & Dancing. Vous apprendrez comment configurer le produit et vos bulletins d'informations.

Vous pouvez cliquer sur les captures d'écran pour les agrandir.

Si vous souhaitez installer Singing & Dancing, vous pouvez utiliser le tutorial d'installation.

Singing & Dancing peut être installé comme n'importe quel autre produit Plone via le panneau de configuration "Produit d'extension". Cliquez sur "configuration du site" puis sur "Produit d'extension":

 
 

 

Un nouveau lien apparaît dans la section "Configuration des produits d'extension". Cliquez dessus pour accéder à l'interface d'administration de Singing & Dancing.

 

La page d'accueil de Singing & Dancing offre l'accès à trois modules: la gestion des canaux (ou bulletins d'informations), la gestion des collections, et la consultation de statistiques. Intéressons-nous dans un premier temps aux canaux:

 

L'écran "Administration des canaux de diffusion" affiche la liste de tous les canaux disponibles dans votre site. Un canal par défaut, appelé "Newsletter" est créé dès l'installation de Singing & Dancing. Cliquez sur le nom de ce canal pour afficher son écran de configuration.

 

L'onglet "Edit" (Modifier) du canal nous permet de le renommer et d'ajouter une description. Différents autres paramètres son disponibles.

 

L'onglet "Subscriptions" (Abonnements) permet de gérer les abonnés au bulletin d'information. Il n'y a pas d'abonnés pour le moment mais les formulaires vous permettent d'en ajouter un ou plusieurs à la fois en téléchargeant un fichier au format CSV. Normalement, lorsque quelqu'un s'abonne à votre bulletin d'information, il reçoit un courriel lui permettant de confirmer son inscription. Ce n'est pas le cas pour les abonnements ajouté via l'interface d'administration:

 

L'onglet "Composers" (Compositeurs) permet de configurer beaucoup de choses telles que les styles de mise en page CSS, le nom et l'adresse de l'émetteur, etc.. Si vous êtes développeur, il vous sera utile de savoir que le compositeur est responsable du rendu final du bulletin d'information à travers un modèle défini. Les API Python mises à votre disposition vous permettront de développer vos propres plugins, par exemple pour envoyer des SMS sur des téléphones mobiles plutôt que des courriels.

 

Pour finir, l'onglet "Preview" (Prévisualisation) permet d'avoir un aperçu du futur rendu de notre bulletin d'information. En cliquant sur le bouton Générer, nous pouvons voir que notre bulletin d'information est plutôt vide. Il n'y a pas de nouvelles! Inutile de vous inquiéter car vos abonnés ne recevront jamais un tel courriel, en effet Singing & Dancing est configuré pour ne pas envoyer de courriels sans contenu.

 

 

A présent voyons comment sélectionner les nouvelles qui seront ajoutées au bulletin d'information. Singing & Dancing vous permet de réaliser cela de deux façons très différentes. La première vous permet d'envoyer manuellement certaines pages ou actualités de votre site. La seconde consiste à configurer quelques règles permettant à Singing & Dancing de collecter automatiquement les nouvelles et d'envoyer le bulletin d'information sans action de votre part. Commençons par la configuration "automatique" de notre bulletin d'information en sélectionnant une collection. Cliquez ensuite sur le titre de la collection pour afficher son écran de configuration. Comme vous l'avez deviné, les collections (ou dossiers intelligents) sont responsables de la collecte des nouvelles qui seront incluses dans le bulletin d'information.

 

 

Voici l'écran de configuration d'une collection, un élément puissant qui vous permet de spécifier le contenu devant être inséré dans un bulletin d'information et ce qui doit pas l'être. Pour voir de plus prêt comment est configurée la collection, cliquez sur le lien "Edit the Smart Folder" (Configurer ce dossier intelligent).

 

Vous pouvez voir qu'il est configuré pour trouver toutes les actualités publiées dans le site. De plus vous pouvez utiliser la fonctionnalité "RSS" du dossier intelligent pour fournir à vos visiteurs le bullet d'information en tant que "fil RSS".

 

Ajoutons une nouvelle actualité au site. Naturellement le dossier intelligent trouvera cette actualité au moment de l'envoi du bulletin d'information. En effet, la fonction de prévisualisation nous permet de voir la nouvelle actualité, appelée "It's fantastic news". Par défaut, Singing & Dancing affiche dans le bulletin d'information le titre, la description et un lien vers l'élément. En tant que programmeur vous pourrez facilement modifier ce comportement par défaut, ce que nous verrons plus loin.

 

 

A présent, comment vos utilisateurs vont-ils pouvoir s'abonner au bulletin d'information ? Tout simplement via le formulaire d'abonnement du bulletin, accessible à l'URL du bulletin d'information suivi de "/subscribe.html". Après la validation du formulaire, l'utilisateur recevra un courriel lui permettant de confirmer son abonnement (ce processus permet de s'assurer de la validité de l'adresse email renseignée).

 

Les utilisateurs pourront également s'abonner au bulletin d'information via un portlet. Singing & Dancing fournit par défaut ce type de portlet que vous pouvez ajouter n'importe où dans le site via le lien "Gérer les portlets" disponible en bas des colonnes de gauche et/ou de droite. Cliquez sur le lien "Gérer les portlets" puis ajoutez un portlet "Channel subscribe portlet".

 

 

Le portlet offre différentes options de configuration telles que son titre, une description et biensûr la sélection du bulletin d'information (ou canal de diffusion) auquel le portlet permet de s'abonner. La seconde capture d'écran montre à quoi ressemble le portlet une fois configuré.

 

 

Intéressons-nous à présent à l'une des fonctionnalités les plus avancées de Singing & Dancing: la possibilité d'avoir plusieurs catégories d'actualités au sein d'un même bulletin d'information. Considérons par exemple que nous souhaitons avoir deux catégories d'actualités, l'une sur le sport et l'autre sur la politique. Par ailleurs nous souhaitons que nos abonnés soit en mesure de choisir parmis les catégories qui les intéressent. Pour réaliser cela, commençons par ajouter deux nouveaux dossiers à notre site: "Sports News" et "Politics News".

 

De retour à l'écran de gestion des bulletins d'information, cliquons sur "Latest news" pour atteindre l'écran de configuration du collecteur associé à notre bulletin. Nous allons maintenant le configurer de sorte qu'il puisse collecter toutes les actualités présentes dans les dossiers "Sports News" et "Politics News".

 

Tout d'abord, supprimons le dossier automatique présent par défaut en cliquant sur le bouton "Remove block" (suppression du bloc). Nous ajoutons ensuite un nouveau dossier automatique qui aura la responsabilité de reccueillir toutes les actualités du dossier "Sports News".

 

 

Afin de permettre à nos abonnés de choisir l'une des deux catégories d'actualités, ou les deux, nous devons rendre ce bloc optionnel:

 

Configurons ce dossier automatique (lien "Edit the Smart Folder) afin qu'il puisse trouver toutes les actualités du dossier "Sports News":

 

Après avoir fait de même pour le répertoire "Politics News", le formulaire d'abonnement au bulletin d'information propose deux options. Les abonnés peuvent à présent choisir les actualités qui les intéressent. Il serait biensûr possible de créer un bulletin d'information par catégorie d'actualités mais un bulletin configurable par utilisateur est souvent plus pratique.

 

Afin de permettre l'envoi automatique du bulletin d'information, retournons à l'écran de gestion des bulletins d'information afin de planifier son envoi. Plusieurs ordonnanceurs (ou planificateurs) sont disponibles et permettent d'envoyer le bulletin manuellement à une date et une heure précise, quotidiennement ou une fois par semaine.

 

Nous pouvons à présent paraméter notre ordonnanceur. Assurons-nous qu'il soit bien actif (les planificateurs sont par défaut inactifs) sinon aucun courriel ne sera envoyé automatiquement. La sélection de la date et de l'heure du dernier envoi (Triggered the last time) du bulletin d'information permet de configurer précisément à quel moment de la journée le prochain envoi doit être réalisé. Choisissez par exemple hier à 9h du matin pour que la prochaine newsletter soit envoyée le lendemain à 9h du matin (pour une programmation quotidienne) et ainsi de suite. Il est important de rappeller qu'aucun courriel ne sera envoyé s'il n'y a pas d'actualités disponibles.

 

Rappelons que nous avons vu précédemment qu'il n'est pas nécessaire de programmer les envois de nos bulletins d'information, ni de paramétrer de collecteurs automatiques. En effet vous pouvez envoyer un bulletin à partir de n'importe quel document du site, en sélectionnant "envoyer une newsletter" dans le menu "actions". Vous pouvez alors sélectionner le canal à utiliser pour l'envoi et demander un aperçu avec son envoi effectif.

 

collective.z3cform.norobots: a captcha based on questions and answers

I have released a new captcha widget/field for z3c.form in Plone. Unlike other captcha fields that are based on images, this captcha is based on a predefined list of questions and answers.

Introduction

collective.z3cform.norobots provides a "human" captcha widget based on a list of questions/answers.

The widget is based on z3c.form.TextWidget.

Requirements:

  • tested with Plone 3.3.2
  • plone.app.z3cform

Installation

Just a simple easy_install collective.z3cform.norobots is enough.

Alternatively, buildout users can install collective.z3cform.norobots as part of a specific project's buildout, by having a buildout configuration such as:

[buildout]
...
eggs =
    collective.z3cform.norobots
...
[instance]
...
zcml =
    collective.z3cform.norobots

In portal_setup, apply the profile collective.z3cform.norobots:default.

Add a new question

In the Plone Property Sheet "norobots_properties" (portal_properties/norobots_properties), add a new property:

Name: The question id (ex: "question4")
Value: your_question::the_answer (ex: "What is 10 + 12 ?::22")
Type: string

Usage

You can use this widget setting the "widgetFactory" property of a form field:

from zope import interface, schema
from z3c.form import interfaces, form, field, button, validator
from plone.app.z3cform.layout import wrap_form

from collective.z3cform.norobots.i18n import MessageFactory as _
from collective.z3cform.norobots.widget import NorobotsFieldWidget
from collective.z3cform.norobots.validator import NorobotsValidator

class INorobotsForm(interface.Interface):
    norobots = schema.TextLine(title=_(u'Are you a human ?'),
                               description=_(u'In order to avoid spam, please \
                                               answer the question below.'),
                               required=True)

class NorobotsForm(form.Form):
    fields = field.Fields(INorobotsForm)
    fields['norobots'].widgetFactory = NorobotsFieldWidget

# wrap the form with plone.app.z3cform's Form wrapper
NorobotsFormView = wrap_form(NorobotsForm)

# Register Norobots validator for the correponding field in the IContactInfo interface
validator.WidgetValidatorDiscriminators(NorobotsValidator, field=INorobotsForm['norobots'])

For more information see the example contact_info.py in the plone_forms directory in the package.

Integrated in a join form:

collective-z3cform-norobots: Integrated image in a join form

With an error:

collective-z3cform-norobots: with an error

collective.dewplayer: display video content in Plone

I have released a simple package using Dewplayer for video content in Plone.

Introduction

This collective module collective.dewplayer register a zope directory resource containing the wonderful mp3 flash player Dewplayer, developed by alsacreation (http://www.alsacreations.fr/dewplayer-en).

Dewplayer version - downloaded 2009-12-08

Installation

Add collective.dewplayer to your buildout as normal. See http://plone.org/documentation/tutorial/buildout. Don't forget to load the configure.zcml file.

At the moment this module doesn't add any feature to Plone. It is primary use as resource package.

Usage

Dewplayer offer several flash players included in the directory resource:

  • Mini (160x20) - dewplayer-mini.swf
  • Classic (200x20) - dewplayer.swf
  • Multi (240x20) - dewplayer-multi.swf
  • Playlist (240x200) - dewplayer-playlist.swf
  • Bubble (250x65) - dewplayer-bubble.swf

For example, to include a classic player (using dewplayer.swf) for http://mysite.com/myaudio.mp3 :

<object type="application/x-shockwave-flash" 
data="++resource++collective.dewplayer/dewplayer.swf"
width="200" height="20">
<param name="wmode" value="transparent" />
<param name="movie" value="dewplayer.swf" />
<param name="flashvars" value="mp3=http://mysite.com/myaudio.mp3&amp;showtime=1" />
</object>

See alsacreations.fr for full documentation: http://www.alsacreations.fr/dewplayer-en [english] or http://www.alsacreations.fr/dewplayer [french]

Todo

  • Add some python helpers for the differents players.

Changelog

0.1 - Decembre 12, 2009

  • Initial release