[Widget] sfWidgetFormTimeAndClear

Après trois semaines de vacances au soleil et quelques semaines limitées sur le plan du dev, me voici de retour pour votre plus grand plaisir :o

Encore une fois, je vous propose un petit widget légèrement personnalisé : sfWidgetFormTimeAndClear.

On continue dans la lancée du sfWidgetFormDoctrineJQueryAutocompleterAndClear avec le même petit bouton permettant de vider le contenu des listes déroulantes du champ d’heure.

Il faut bien sûr intégrer jQuery pour que cela fonctionne mais vous l’aviez sans doute compris :)

Voici le code :

class sfWidgetFormTimeAndClear extends sfWidgetFormTime
{
  public function render($name, $value = null, $attributes = array(), $errors = array())
  {
    return parent::render($name, $value, $attributes, $errors).
           ' <img src="data:image/png;base64,'.$this->getImage().'" alt="" id="'.$this->getDeleteId($name).'" />'.
           sprintf(<<<EOF
<script type="text/javascript">
  $("#%s").bind("mouseover", function(e){
    $("#%s")[0].style.cursor = "pointer";
  });
  $("#%s").bind("click", function(e){
    $("#%s")[0].value = "";
    $("#%s")[0].value = "";
    %s
    return false;
  });

</script>
EOF
      ,
      $this->getDeleteId($name),
      $this->getDeleteId($name),
      $this->getDeleteId($name),
      $this->getHourId($name),
      $this->getMinuteId($name),
      $this->getSecondId($name)
    );
  }

  private function getHourId($value)
  {
    return $this->generateId($value."_hour");
  }

  private function getMinuteId($value)
  {
    return $this->generateId($value."_minute");
  }

  private function getSecondId($value)
  {
    if ($this->getOption('with_seconds'))
    {
      return '$("#'.$this->generateId($value."_second").'")[0].value = "";';
    }
    return '';
  }

  private function getDeleteId($value)
  {
    return $this->generateId("delete_hour_value_".$value);
  }

  private function getImage()
  {
    return "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJdSURBVDjLpZP7S1NhGMf9W7YfogSJboSEUVCY8zJ31trcps6zTI9bLGJpjp1hmkGNxVz4Q6ildtXKXzJNbJRaRmrXoeWx8tJOTWptnrNryre5YCYuI3rh+8vL+/m8PA/PkwIg5X+y5mJWrxfOUBXm91QZM6UluUmthntHqplxUml2lciF6wrmdHriI0Wx3xw2hAediLwZRWRkCPzdDswaSvGqkGCfq8VEUsEyPF1O8Qu3O7A09RbRvjuIttsRbT6HHzebsDjcB4/JgFFlNv9MnkmsEszodIIY7Oaut2OJcSF68Qx8dgv8tmqEL1gQaaARtp5A+N4NzB0lMXxon/uxbI8gIYjB9HytGYuusfiPIQcN71kjgnW6VeFOkgh3XcHLvAwMSDPohOADdYQJdF1FtLMZPmslvhZJk2ahkgRvq4HHUoWHRDqTEDDl2mDkfheiDgt8pw340/EocuClCuFvboQzb0cwIZgki4KhzlaE6w0InipbVzBfqoK/qRH94i0rgokSFeO11iBkp8EdV8cfJo0yD75aE2ZNRvSJ0lZKcBXLaUYmQrCzDT6tDN5SyRqYlWeDLZAg0H4JQ+Jt6M3atNLE10VSwQsN4Z6r0CBwqzXesHmV+BeoyAUri8EyMfi2FowXS5dhd7doo2DVII0V5BAjigP89GEVAtda8b2ehodU4rNaAW+dGfzlFkyo89GTlcrHYCLpKD+V7yeeHNzLjkp24Uu1Ed6G8/F8qjqGRzlbl2H2dzjpMg1KdwsHxOlmJ7GTeZC/nesXbeZ6c9OYnuxUc3fmBuFft/Ff8xMd0s65SXIb/gAAAABJRU5ErkJggg==";
  }
}

Et voici à quoi cela ressemble :

Je vais sans doute proposer également les widgets date et datetime sous ce format dans les jours à venir.

[Widget] sfWidgetFormDoctrineJQueryAutocompleterAndClear

Pour faire suite à mon billet sur le widget sfWidgetFormDoctrineJQueryAutocompleter, je vous propose mon petit widget sfWidgetFormDoctrineJQueryAutocompleterAndClear.

Il propose un bouton permettant de vider le contenu du champ texte mais également du champ caché d’autocompletion.

Il fonctionne exactement de la même manière que le widget original, il ne faut rien de plus et rien de moins (l’icône est intégrée en base64).

Voici le code :

class sfWidgetFormDoctrineJQueryAutocompleterAndClear extends sfWidgetFormDoctrineJQueryAutocompleter
{
  public function render($name, $value = null, $attributes = array(), $errors = array())
  {
    return parent::render($name, $value, $attributes, $errors).
           ' <img src="data:image/png;base64,'.$this->getImage().'" alt="" id="'.$this->getDeleteId($name).'" />'.
           sprintf(<<<EOF
<script type="text/javascript">
  $("#%s").bind("mouseover", function(e){
    $("#%s")[0].style.cursor = "pointer";
  });
  $("#%s").bind("click", function(e){
    $("#%s")[0].value = "";
    $("#%s")[0].value = "";
    return false;
  });

</script>
EOF
      ,
      $this->getDeleteId($name),
      $this->getDeleteId($name),
      $this->getDeleteId($name),
      $this->generateId('autocomplete_'.$name),
      $this->generateId($name)
    );
  }

  private function getDeleteId($value)
  {
    return $this->generateId("delete_autocomplete_value_".$value);
  }

  private function getImage()
  {
    return "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJdSURBVDjLpZP7S1NhGMf9W7YfogSJboSEUVCY8zJ31trcps6zTI9bLGJpjp1hmkGNxVz4Q6ildtXKXzJNbJRaRmrXoeWx8tJOTWptnrNryre5YCYuI3rh+8vL+/m8PA/PkwIg5X+y5mJWrxfOUBXm91QZM6UluUmthntHqplxUml2lciF6wrmdHriI0Wx3xw2hAediLwZRWRkCPzdDswaSvGqkGCfq8VEUsEyPF1O8Qu3O7A09RbRvjuIttsRbT6HHzebsDjcB4/JgFFlNv9MnkmsEszodIIY7Oaut2OJcSF68Qx8dgv8tmqEL1gQaaARtp5A+N4NzB0lMXxon/uxbI8gIYjB9HytGYuusfiPIQcN71kjgnW6VeFOkgh3XcHLvAwMSDPohOADdYQJdF1FtLMZPmslvhZJk2ahkgRvq4HHUoWHRDqTEDDl2mDkfheiDgt8pw340/EocuClCuFvboQzb0cwIZgki4KhzlaE6w0InipbVzBfqoK/qRH94i0rgokSFeO11iBkp8EdV8cfJo0yD75aE2ZNRvSJ0lZKcBXLaUYmQrCzDT6tDN5SyRqYlWeDLZAg0H4JQ+Jt6M3atNLE10VSwQsN4Z6r0CBwqzXesHmV+BeoyAUri8EyMfi2FowXS5dhd7doo2DVII0V5BAjigP89GEVAtda8b2ehodU4rNaAW+dGfzlFkyo89GTlcrHYCLpKD+V7yeeHNzLjkp24Uu1Ed6G8/F8qjqGRzlbl2H2dzjpMg1KdwsHxOlmJ7GTeZC/nesXbeZ6c9OYnuxUc3fmBuFft/Ff8xMd0s65SXIb/gAAAABJRU5ErkJggg==";
  }
}

Et à quoi cela ressemble au final :

sfWidgetFormTextareaTinyMCEWithLang

Je souhaitais vous faire partager mon petit widget TinyMCE basé sur celui intégré au plugin sfFormExtraPlugin.

Pourquoi réécrire un widget existant ? Parce que celui-ci n’acceptait pas le paramètre de langue !

Quelque part, il s’agit plus d’un correctif du widget mais bon, il s’avère que j’en ai souvent besoin donc je le partage ici :

class sfWidgetFormTextareaTinyMCEWithLang extends sfWidgetFormTextarea
{
  protected function configure($options = array(), $attributes = array())
  {
    $this->addOption('theme', 'advanced');
    $this->addOption('language', 'en');
    $this->addOption('width');
    $this->addOption('height');
    $this->addOption('config', '');
  }

  public function render($name, $value = null, $attributes = array(), $errors = array())
  {
    $textarea = parent::render($name, $value, $attributes, $errors);

    $js = sprintf(<<<EOF
<script type="text/javascript">
  tinyMCE.init({
    mode:                              "exact",
    elements:                          "%s",
    language:                          "%s",
    theme:                             "%s",
    %s
    %s
    theme_advanced_toolbar_location:   "top",
    theme_advanced_toolbar_align:      "left",
    theme_advanced_statusbar_location: "bottom",
    theme_advanced_resizing:           true
    %s
  });
</script>
EOF
    ,
      $this->generateId($name),
      $this->getOption('language'),
      $this->getOption('theme'),
      $this->getOption('width')  ? sprintf('width:                             "%spx",', $this->getOption('width')) : '',
      $this->getOption('height') ? sprintf('height:                            "%spx",', $this->getOption('height')) : '',
      $this->getOption('config') ? ",\n".$this->getOption('config') : ''
    );

    return $textarea.$js;
  }
}

Et pour l’utiliser :

  • dans votre classe de formulaire
$this->widgetSchema['widget'] = new sfWidgetFormTextareaTinyMCEWithLang(sfConfig::get('app_tinymce_config'));
  • dans le fichier app.yml
all:
  tinymce:
    width:  550
    height: 125
    language: fr
    config: |
      plugins: "paste",
      paste_auto_cleanup_on_paste : true,
      theme_advanced_buttons1: "bullist,pasteword,bold,italic,underline,fontselect,fontsizeselect",
      theme_advanced_buttons2: "",
      theme_advanced_buttons3: "",
      theme_advanced_buttons4: ""
    theme: <?php echo sfConfig::get('app_tinymce_theme','advanced') ?>

Edit : un billet sur le même sujet existe en anglais (merci à Tomasz Ducin)

[Admin generator] Paramètre ‘table method’

Une petite astuce que j’utilise depuis longtemps mais que je n’avais jamais pensé à partager : optimiser le nombre de requêtes Doctrine et par la même occasion, un module d’admin generator.

J’ai un module d’admin generator article lié au modèle Article.

  • schema.yml
Article:
  connection: doctrine
  actAs:
    Timestampable: ~
    Taggable: ~
    Sluggable:
      fields: [titre]
      name: slug
      type: string
      length: 255
      unique: true
      canUpdate: true
  columns:
    titre:
      type: string(255)
      notnull: true
    # et d'autres champs
    id_auteur:
      type: integer
      notnull: true
  relations:
    Auteur:  { class: vjGuardUserProfile, onDelete: SET NULL, onUpdate: CASCADE, local: id_auteur, foreign: id }
  • generator.yml
 list:
 title: Liste des articles
 display: [titre, date_publication, Auteur]
 max_per_page: 5
 table_method: retrieveBackend
  • ArticleTable.class.php
public function retrieveBackend(Doctrine_Query $q)
{
  $rootAlias = $q->getRootAlias($q);
  $q->leftJoin($rootAlias.'.Auteur au');
  return $q;
}

Dans cet exemple, je passe de 6 requêtes Doctrine pour l’affichage de 5 lignes à 3 requêtes.

Ce n’est pas énorme mais sur 20 lignes et 3 relations, on passe de 63 requêtes à

3 requêtes !

Sisi !

Alors, abusez-en !

symfony 1.3.6 et 1.4.6 publiées (security fix inside)

Deux nouvelles mises à jour de symfony ont été publiées ce soir. Estampillées 1.3.6 et 1.4.6, elles corrigent une faille dans la gestion du cache des templates.

Après la dernière mise à jour, c’est une nouvelle fois dans l’urgence que sont corrigées des failles de sécurité !

Il est temps de mettre à jour !

Source

symfony 1.3.5 et 1.4.5 publiées (security fix inside)

Deux nouvelles mises à jour de symfony ont été publiées en milieu de soirée : 1.3.5 et 1.4.5.

Elles corrigent un certain nombre de tickets mais intègre surtout un fix de sécurité pour Doctrine et Propel !

Il est temps de mettre à jour !

Source

Livre symfony : « A Gentle Introduction to symfony 1.4″

Allez, un peu de lecture pour commencer cette semaine !

En effet, Fabien Potentier a annoncé hier soir sur le blog de symfony la publication d’un nouveau livre : « A Gentle Introduction to symfony 1.4″.

Un nouveau livre, oui et non. Il s’agit plus d’une mise à jour du « Definitive Guide to Symfony » pour symfony 1.4 qu’autre chose. Globalement, ce livre, travaillant la théorie, est plutôt destiné aux débutants et s’accompagne du « Practical symfony« , orienté cas pratique.

Vous pouvez directement lire ce livre ou le commander depuis le site de sensio.

Que de news : sf1.2.10, 1.3, 1.4 et un nouveau livre !

Bonjour à tous !

Je souhaitais écrire un petit mot mardi mais quand le planning est chargé, tout n’est pas possible !

Bref, si comme moi mardi, vous étiez à suivre le blog de symfony, vous avez du passer une journée excitante à souhait !

Pour commencer, la version 1.2.10 de symfony a été publiée. Loin d’être une révolution (ce n’est qu’une évolution :p), elle corrige un certain nombre de bugs et ajoute une tâche fort sympatique : symfony project:validate
Que peut bien faire cette tâche ? Très simplement, elle va vous aider lors de votre migration vers symfony 1.3/1.4. En effet, elle propose de matcher le stuff déprécié dans symfony 1.3 et supprimé dans la 1.4. Pour avoir testé une migration, c’est en effet appréciable !

Bon, c’était l’entrée. Maintenant, le plat de résistance : publication des versions stables de symfony 1.3 et symfony 1.4 ! Je ne vais pas lister à nouveau l’ensemble des nouveautés ou des mises à jour, tout est sur le site officiel. Sachez tout de même qu’il va falloir penser à migrer dans un futur proche.

Et pour finir, le dessert : publication du calendrier de l’avent 2009 de symfony ! Pour les non-initiés, le calendrier de l’avent chez symfony consiste en gros en un tutoriel découpé en 24 étapes qui commence le 1er décembre et se termine le 24. Chaque jour, une nouvelle étape est publiée et au final, un livre est mis en vente. Pour les débutants, vous pouvez retrouver les précédents tutoriaux : Askeet et Jobeet (je vous conseille Jobeet car plus récent). Le nouveau tutoriel propose en fait plusieurs tutoriaux et est principalement destiné aux utilisateurs avertis de symfony.
Il propose des sujets plus avancés de symfony (surcharge du routing, formulaires avancés, héritage et Doctrine, etc…). Le plus important sans doute dans ce tutoriel/livre est le fait qu’il a été rédigé par la communauté ! Non, non, vous ne rêvez pas ! Je vous laisse découvrir toutes ces informations directement sur le site mais sachez également que ce livre va être disponible pour le moment en 5 langues (dont le français !!!) et que la version anglaise est déjà en vente.

J’avoue avoir été totalement rassasié après toutes ces informations et quand je vois le travail accompli par l’équipe de symfony et par la communauté, je suis fier d’en faire partie !

Bon, en ce moment, je ne livre pas beaucoup d’aides ou d’astuces mais plus d’informations que vous connaissez sans doute déjà mais j’avoue ne pas avoir énormément de temps pour cela. Avec les nouvelles versions de symfony, j’espère pouvoir rapidement vous aider avec de nouveaux tutoriaux !

Vive symfony ! Vive la communauté symfony !

Symfony 1.3 & 1.4, dernière ligne droite !

Bonjour à tous !

Comme prévu, les versions RC2 de symfony 1.3 & 1.4 sont sorties aujourd’hui. Vous pouvez les télécharger ici pour la 1.3 et ici pour la 1.4. N’hésitez pas à les tester dès aujourd’hui et à faire vos retours !

Les versions stables devraient sortir la semaine prochaine.

La question qui se pose maintenant : quelle version choisir ?
- la 1.3 : support 1an, stuff déprécié mais pas supprimé
- la 1.4 : support 3 ans, stuff déprécié supprimé (il faut penser à faire un point complet sur tous ses projets …)

Nous avons fait le choix de la 1.4 pour le support de 3 ans principalement. En effet, pour des professionnels, il est important de pouvoir se dire que notre outil sera maintenu longtemps. On ne sait pas si on pourra le mettre à jour fréquemment !
Du coup, cela demande un peu plus de travail avant la migration afin de faire un point complet sur l’ensemble des projets déjà créés pour être sûr de ne rien oublier (stuff déprécié) et du coup, de mettre à jour ce stuff.

Il faut également savoir pour ceux étant en 1.2 que la migration en 1.3 ou 1.4 est importante et plus ou moins urgente afin de garder une version maintenue. Peu le savent mais le support de la version 1.2 a été augmenté de 3 mois, ce qui le porte jusqu’en février 2010 (initialement prévu jusqu’à la release de la 1.3). Vous avez donc un peu plus de temps pour faire vos tests de migration donc profitez-en !

A bientôt pour de nouvelles aventures !