Archive for the 'gratuit' Category

Adieu Outlook … Lundi, juin 9th, 2008

C’était un des obstacles pour migrer complètement sous linux: comment synchroniser les données de mon pocketPC (essentiellement les contacts et le calendrier) avec mon PC sans outlook.
Quand je dis sans Outlook, l’extension lightning de Thunderbird qui permet de gérer des calendriers sunbird, me paraissait assez sexy pour avoir envie de l’utiliser.

Et bien funambol met à disposition un ensemble de produits permettant de réaliser cette opération.
parmi ces produits j’ai utilisé les suivants pour libérer la synchro

funambol


la version Outlook
qui permet d’extraire vos données (contacts & calendrier) "emprisonnées"
la version PocketPC
l’extension Thunderbird de synchro via syncML

Coté Mozilla

Sunbird pour la gestion des calendriers
l’extension thunderbird ilghtning pour gérer le calendrier directement dans thunderbird
l’extension google pour unbuntu qui corrige en fait un bug de lightning-linux

L’idée

L’idée est simplement d’avoir un serveur prêt à synchroniser des contacts et des calendriers via syncML. La solution la plus rapide est de se créer un compte chez scheduleworld et de paramétrer l’extension thunderbird funambol ainsi que le client pocketpc (synchronisable de n’importe ou via l’internet :-) avec les données qui vous auront été fournies lors de l’inscription).

serveur funambol

Funambol fournit par ailleurs toute la gamme de produit, c’est à dire outre les clients en tout genre, les serveurs pour windows & linux 8-p … Je n’ai testé que la version windows sans creuser mais ça fonctionne très bien … Rendez vous pour la mise en place du serveur sous debian.

quelques liens qui en causent

pérserver le type mime d’un fichier uploadé via l’admin generator de symfony Vendredi, avril 11th, 2008

L’ admin-generator gère l’upload de fichier. Pour l’objet sfCmsContent d’accordéon CMS par exemple, l’attribut file_path est déclaré comme suit dans le generator.yml

       file_path:
          name: fichier
          type: admin_input_file_tag
          upload_dir: sfCmsContent/file
          params: disabled=false include_remove=true
          help: appuyer sur le bouton ‘Parcourir…’ pour sélectionner un fichier contenu dans votre ordinateur

Cela permet d’avoir un formulaire d’upload avec une checkbox pour la suppression du fichier. Si le fichier est nouveau un nom aléatoire lui sera attribué, sinon il remplacera l’ancienne version du fichier et ce sans écrire une ligne de code.
Les problèmes pointent leur nez quand on tente d’uploader des fichiers avec des extensions un peu exotiques, dans mon cas l’extension .pot (modèle de conception sous power point) était systématiquement remplacée par l’extension .ppt.
C’est dû à la méthode getFileExtension() de sfWebRequest, et en particulier au fichier mime_types.dat qui contient les associations entre type mime et extension. La difficulté dans le cas des .pot est que ce type de fichier renvoie le même type mime que les .ppt

application/vnd.ms-powerpoint

Or mime_types.dat permet d’associer un et un seul type mime à une et une seule extension … j’ai donc opté pour la ruse en surchargeant updateSfCmsContentFromRequest() comme suit

protected function updateSfCmsContentFromRequest()

    $sfCmsContent = $this->getRequestParameter(’sf_cms_content’);
    parent::updateSfCmsContentFromRequest();
    if (!$this->getRequest()->hasErrors())
    {
        $tmp = $this->getRequest()->getFileName(’sf_cms_content’);
        if($tmp[’file_path’])
        {
          $path = sfConfig::get(’sf_upload_dir’).’/’.sfCmsContent/file
          if(!is_dir($path))
          {
            mkdir($path);
          }
         
          $extension = myTools::MimeTypeInfo($tmp[’file_path’]);
          $filename  = myTools::FileNameInfo($this->sf_cms_content->getFilePath());
          rename($path.’/’.$this->sf_cms_content->getFilePath(), $path.’/’.$filename.’.’.$extension);
          $this->sf_cms_content->setFilePath($filename.’.’.$extension);
          $this->sf_cms_content->setMimeType(myTools::MimeTypeInfo($tmp[’file_path’]));
    }
}

 où

class myTools
{
  public static function MimeTypeInfo($file_name)
  {
    return substr($file_name, strrpos($file_name, ".")+1);
  }
  public static function FileNameInfo($file_name)
  {
    return substr($file_name, 0, strrpos($file_name, "."));
  }
}

on se sert ainsi de l’extension du fichier pour déterminer son type mime, et on est assuré que cette extension est préservée

accordéon CMS et sfSimpleForumPlugin Mardi, mars 18th, 2008

En attendant la publication de la première version stable d’accordéon CMS (c’est pour bientôt), voici un petit trace back de l’intégration de sfSimpleForumPlugin.
Une fois l’installation du plugin proprement dit voici ce que j’ai dû modifier:

Hacking et correction de Bug

Le seul fichier que j’ai du hacker dans le plugin est le schéma de sfSimpleForum dans plugins/sfSimpleForumPlugin/config/schema.yml. En effet sfCms (le cms symfony qui constitue la base d’accrodéon CMS) n’utilise pas sfGuardPlugin.
sfSimpleForum prévoit que les utilisateurs puissent être géré par un autre module de gestion d’utilisateur … ça tombe bien.
Ce qui est assez mal fait (mais je n’ai pas réfléchi s’il y avait mieux à faire) c’est que les références aux champs de bases de données de sfGuard sont écrits en dur dans le schema.yml. Il m’a donc fallu remplacer dans ce fichier, toutes les occurrences de sf_guard_user par sf_cms_user qui est le module de gestion d’utilisateur de sfCms, avant de reconstruire entièrement le projet

php symfony propel-build-all

L’ autre Hack du plugin, mais qui lui est temporaire, se situe au niveau du fichier plugins/lib/sfSimpleForumTools.class.php. En effet il y a incohérence entre les variables à "copier / coller" dans le fichier app.yml et la référence qui y est faite dans cette classe statique (méthode getUserByUsername). Il faut donc modifier

$method_name = sfConfig::get(’app_sfSimpleForumPlugin_user_retrieve_by_name_method’, ‘retrieveByUsername’);

par

$method_name = sfConfig::get(’app_sfSimpleForumPlugin_retrieve_by_name_method’, ‘retrieveByUsername’);

A toutes fins utiles, j’ai déjà pris la peine d’ouvrir un ticket.

surcharge au niveau de l’application

A ce niveau là, le sale boulot est maintenant fini. Dans toute la suite on va pouvoir surcharger sans toucher au code du plugin.
Dans le app.yml on spécifie donc le module de gestion des utilisateurs et la méthode permettant des les retrouver. Dans sfCms l’idée est plus d’appeler un utilisateur par son nom prénom que par son nom d’utilisateur. Or par défaut, c’est ce que propose sfSimpleForum …
il va falloir ruser!
La méthode charnière est précisément la méthode où se trouve le bug cité plus haut : getUserByUsername.
Au niveau de l’affichage c’est bien le prénom nom qui s’affiche (en réalité ce que renvoie la méthode __toString() de la classe SfCmsUser), En revanche c’est la même chose qui est passé en paramètre de sfSimpleForumTools::getUserByUsername() …
Les homonymies vont donc poser problème.
En explorant un peu la classe de base d’un post (BasesfSimpleForumPost.php) on s’aperçoit qu’elle peut renvoyer le nom de l’auteur (ça on savait déjà) via getAuthorName(), mais aussi l’identifiant du l’utilisateur associé … et s’il y a bien une méthode fiable poru retrouver un objet propel dans symfony c’est retrieveByPk!
Donc

all:
  sfSimpleForumPlugin:
    user_class:              SfCmsUser     # name of the class used to manage users
    retrieve_by_name_method:  retrieveByPk  # name of the static method used to retrieve a user by its username

Et maintenant il n’y a plus qu’à surcharger tous les templates ou partial qui mentionnent un lien vers l’utilisateur afin de remplacer le paramètre username=’.$post->getAuthorName() par username=’.$post->getUserId().
Il y a 3 partials à "copier / coller" puis à modifier dans l’ (les) application(s) qui intègre(nt) sfSimpleForumPlugin

  • apps/myapp/sfSimpleForumPlugin/templates/_post.php
  • apps/myapp/sfSimpleForumPlugin/templates/_latestPost.php
  • apps/myapp/sfSimpleForumPlugin/templates/_forum.php

Il reste ensuite à traduire en français

      <trans-unit id="18">
        <source>New topic</source>
        <target>Nouveau sujet</target>
      </trans-unit>
      <trans-unit id="19">
        <source>There is no topic in this discussion yet. Perhaps you would like to %start%?</source>
        <target>Il n’y a pas encore de sujet dans cette discussion. Peut-être voulez vous %start%?</target>
      </trans-unit>
      <trans-unit id="20">
        <source>start a new one</source>
        <target>en créer un nouveau</target>
      </trans-unit>
      <trans-unit id="21">
        <source>Moderator</source>
        <target>Modérateur</target>
      </trans-unit>  
      <trans-unit id="22">
        <source>Title</source>
        <target>Titre</target>
      </trans-unit>  
      <trans-unit id="23">
        <source>Forum</source>
        <target>Forum</target>
      </trans-unit>
      <trans-unit id="24">
        <source>Body</source>
        <target>Corps</target>
      </trans-unit>
      <trans-unit id="25">
        <source>Sticked topic</source>
        <target>Sujet collé</target>
      </trans-unit>
      <trans-unit id="26">
        <source>Locked topic</source>
        <target>Sujet verrouillé</target>
      </trans-unit>
      <trans-unit id="26">
        <source>Post</source>
        <target>Post</target>
      </trans-unit>
      <trans-unit id="27">
        <source>%date% ago by %author%</source>
        <target>il y a %date% par %author%</target>
      </trans-unit>
      <trans-unit id="28">
        <source>Delete</source>
        <target>Supprimer</target>
      </trans-unit>
      <trans-unit id="29">
        <source>Are you sure you want to delete this post?</source>
        <target>Etes vous sûr de vouloir supprimer ce post?</target>
      </trans-unit>
      <trans-unit id="30">
        <source>Last reply</source>
        <target>Dernière réponse</target>
      </trans-unit>
      <trans-unit id="31">
        <source>Posted</source>
        <target>Posté</target>
      </trans-unit>
      <trans-unit id="32">
        <source>View</source>
        <target>Voir</target>
      </trans-unit>
      <trans-unit id="33">
        <source>Views</source>
        <target>Vues</target>
      </trans-unit>
      <trans-unit id="34">
        <source>Topic</source>
        <target>Sujet</target>
      </trans-unit>
      <trans-unit id="35">
        <source>Replies</source>
        <target>Réponses</target>
      </trans-unit>
      <trans-unit id="36">
        <source>Last Message</source>
        <target>Dernier message</target>
      </trans-unit>
      <trans-unit id="37">
        <source>Create a new topic</source>
        <target>Créer un nouveau sujet</target>
      </trans-unit>
      <trans-unit id="38">
        <source>Topics</source>
        <target>Sujets</target>
      </trans-unit>
      <trans-unit id="39">
        <source>Lastest Messages</source>
        <target>Derniers messages</target>
      </trans-unit>
      <trans-unit id="40">
        <source>Lastest Topics</source>
        <target>Derniers sujets</target>
      </trans-unit>
      <trans-unit id="41">
        <source>Unstick</source>
        <target>Décoller</target>
      </trans-unit>
      <trans-unit id="42">
        <source>Unlock</source>
        <target>Déverrouiller</target>
      </trans-unit>
      <trans-unit id="43">
        <source>Stick</source>
        <target>Coller</target>
      </trans-unit>
      <trans-unit id="44">
        <source>Lock</source>
        <target>Verrouiller</target>
      </trans-unit>
      <trans-unit id="45">
        <source>Post a reply</source>
        <target>Poster une réponse</target>
      </trans-unit>
      <trans-unit id="46">
        <source>This topic was locked by a forum moderator. No reply can be added.</source>
        <target>Ce sujet a été verrouillé par un modérateur du forum. Aucune réponse ne peut être ajoutée.</target>
      </trans-unit>
      <trans-unit id="47">
        <source>Messages by %user%</source>
        <target>Messages de %user%</target>
      </trans-unit>
      <trans-unit id="48">
        <source>less than a minute</source>
        <target>moins d’une minute</target>
      </trans-unit>
      <trans-unit id="49">
        <source>less than 5 seconds</source>
        <target>moins de 5 secondes</target>
      </trans-unit>
      <trans-unit id="50">
        <source>less than 10 seconds</source>
        <target>moins de 10 secondes</target>
      </trans-unit>
      <trans-unit id="51">
        <source>less than 20 seconds</source>
        <target>moins de 20 secondes</target>
      </trans-unit>
      <trans-unit id="52">
        <source>half a minute</source>
        <target>30 secondes</target>
      </trans-unit>
      <trans-unit id="53">
        <source>less than a minute</source>
        <target>moins d’un minute</target>
      </trans-unit>
      <trans-unit id="54">
        <source>1 minute</source>
        <target>1 minute</target>
      </trans-unit>
      <trans-unit id="55">
        <source>%minutes% minutes</source>
        <target>%minutes% minutes</target>
      </trans-unit>
      <trans-unit id="56">
        <source>about 1 hour</source>
        <target>environ 1 heure</target>
      </trans-unit>
      <trans-unit id="57">
        <source>about %hours% hours</source>
        <target>environ %hours% heures</target>
      </trans-unit>
      <trans-unit id="58">
        <source>1 day</source>
        <target>1 jour</target>
      </trans-unit>
      <trans-unit id="59">
        <source>%days% days</source>
        <target>%days% jours</target>
      </trans-unit>
      <trans-unit id="60">
        <source>about 1 month</source>
        <target>environ 1 mois</target>
      </trans-unit>
      <trans-unit id="61">
        <source>%months% months</source>
        <target>%months% mois</target>
      </trans-unit>
      <trans-unit id="62">
        <source>about 1 year</source>
        <target>environ 1 année</target>
      </trans-unit>
      <trans-unit id="63">
        <source>over %years% years</source>
        <target>plus de %years% années</target>
      </trans-unit>
      <trans-unit id="64">
        <source>[0]No topic yet|[1]One topic|(1,+Inf]%topics% topics</source>
        <target>[0]Pas encore de sujet|[1]Un sujet|(1,+Inf]%topics% sujets</target>
      </trans-unit>
      <trans-unit id="65">
        <source>[0]No message|[1]One message|(1,+Inf]%posts% messages</source>
        <target>[0]Pas de message|[1]Un message|(1,+Inf]%posts% messages</target>
      </trans-unit>

plutôt probant non?