var Phenix = function () {
Troll du Web depuis 1996

Web dev

Truc, astuces et tuto sur le CMS SPIP ou sur le développement web en général.

Laravel : utiliser un trait php pour purifier le HTML d’un champ

Lorsque l’ont stock du HTML dans le champ d’une base de donnée, il ne faut jamais le stocker sans le filtrer. C’est une mauvaise pratique bien connue, cela attire les failles XSS et personne n’aime en avoir.

Bref, voici une méthode sympa pour protéger un champ.

Dans un premier temps il faut installer HTMLPurifier :

  1. composer require ezyang/htmlpurifier

Cette librairie permet de filtrer le html correctement. N’utilisez pas strip_tags, cette fonction n’est pas faite pour la sécurité.

Ma base de donnée contient assez bien de champs « description », ils risquent tous de contenir du HTML, car ils sont remplis par un CKeditor.

Cela affecte tous ces champs, j’ai envie de les protéger facilement.
J’ai donc créé un fichier ./app/traits/purify.php

On va mixer le pouvoir des mutators de Laravel et

  1. <?php
  2.  
  3. namespace App;
  4.  
  5. use HTMLPurifier_Config;
  6. use HTMLPurifier;
  7.  
  8. trait Purify
  9. {
  10.     /**
  11.      * @property $allowed allowed html inside description field
  12.      */
  13.     private $allowed = 'p, strong, h2, h3, a[href], ul, ol, li, i';
  14.  
  15.     /**
  16.      * Laravel mutator.
  17.      * Filter all unauthorized HTML from the description field
  18.      * @param $value
  19.      */
  20.     public function setDescriptionAttribute($value)
  21.     {
  22.         $config = HTMLPurifier_Config::createDefault();
  23.         $config->set('HTML.Allowed', $this->allowed);
  24.         $purifier = new HTMLPurifier($config);
  25.         $this->attributes['description'] = $purifier->purify($value);
  26.     }
  27. }

Il suffit alors d’utiliser ce trait dans un modèle Laravel pour que les champs description soit automatiquement filtrés avant d’être insérés dans la base de donnée !

  1. <?php
  2.  
  3. namespace App;
  4.  
  5. use Illuminate\Database\Eloquent\Model;
  6.  
  7. class MyModel extends Model
  8. {
  9.     use Purify;
  10. }

Laravel et PHP sont des outils vraiment formidables quand on comprend ce genre d’astuce !


Angular (2+), jQuery et jQuery-ui sont sur un bateau

Notes

jQuery a pas mal mauvaise presse et certain vont jusqu’à déclarer leur code « jQuery free », comme si ce framework était pestiféré.
Je trouve cependant que jQuery a quelques point fort qui sont toujours d’actualité :

  • Beaucoup de plugins et librairies qui souvent ne sont pas « jQuery free ».
  • Beaucoup de plugins et librairies qui sont souvent très bien testées, débuggées et très bien maintenues.

Alors c’est clair que pour une conférence, dire qu’on utilise jQuery, c’est « has been ». Par contre, si on a envie d’avoir quelque chose de stable qui fait bien le boulot, l’écosystème de jQuery conviens très bien !

Dans le cas qui m’occupe j’avais besoin d’un « drag » et d’un « drop » d’éléments qui serve à autre chose qu’ordonné une liste.
Je n’ai trouvé aucun module qui s’occupe de cela. Tous ceux que j’ai trouvé (en tête, le drag&drop du CDK d’angular) s’intéresse uniquement au fait de trier des listes... Et ce n’est absolument pas ce dont j’ai besoin...

Bref, tout cela pour dire que je me suis tourné vers... jQuery-ui draggable et droppable.

Installation

Pour installer jQuery-ui avec npm, il faut utiliser le paquet jquery-ui-dist. Je ne sais pas à quoi sert le paquet jQuery-ui, mais ce n’est clairement pas le plus simple à utiliser.

  1. npm install jquery jquery-ui-dist
  2. npm install --save @types/jquery @types/jqueryui

Dans le angular.json, dans la partie scripts on ajoute les librairies :

  1.               "./node_modules/jquery/dist/jquery.min.js",
  2.               "./node_modules/jquery-ui-dist/jquery-ui.js"

Au début du composant Angular, on va déclarer jQuery (mais en dehors du @Component) :

  1. declare var $: any;

On peut maintenant utiliser les plugins jQuery-ui dans les composants Angular. Il semble recommandé de le faire dans le hook AfterViewInit.

  1.   ngAfterViewInit() {
  2.     $(this.thumb.nativeElement).draggable({
  3.       revert: true,
  4.       zIndex: 100
  5.     });
  6.  
  7.     $(this.thumb.nativeElement).droppable({
  8.       drop: (event, ui) => {
  9.         this.documentService.combine([this.document.id, draggable_id]);
  10.       }
  11.     });
  12.   }

Binding datas

Pour ajouter des données aux éléments « draggés », une petite pirouette :

  1. $(this.thumb.nativeElement).data('document', this.document);

Que l’on récupère ensuite dans l’élément ui.draggable :

  1.     $(this.thumb.nativeElement).droppable({
  2.       drop: (event, ui) => {
  3.         const draggable = ui.draggable.data('document');
  4.         this.documentService.combine([this.document.id, draggable.id]);
  5.       }
  6.     });

Lire un fichier CSV avec Laravel

J’avais besoin de lire un fichier CSV pour remplir une base de donnée Laravel. C’est assez simple à faire car il y a une super lib pour gérer le CSV :

  1. composer require League/csv

On lit le CSV et on boucle sur chaque élément. Après on en fait ce qu’on veut :) !

  1. <?php
  2. use Illuminate\Database\Seeder;
  3. use Illuminate\Support\Collection;
  4. use Illuminate\Support\Facades\Log;
  5. use League\Csv\Reader;
  6. use League\Csv\Statement;
  7.  
  8. class commune extends Seeder
  9. {
  10.     /**
  11.      * Run the database seeds.
  12.      *
  13.      * @return void
  14.      */
  15.     public function run()
  16.     {
  17.         // Remplir la base de donnée avec les communes du fichier CSV
  18.  
  19.         // Lire le fichier csv
  20.         $csv = Reader::createFromPath(storage_path('app/communes_belges.csv'));
  21.         $csv->setHeaderOffset(0);
  22.  
  23.         // Boucler sur les données du fichier csv
  24.         $records = (new Statement())->process($csv);
  25.         foreach ($records->getRecords() as $record) {
  26.             var_dump($record);
  27.         }
  28.     }
  29. }

Recherche ajax avec les formulaires SPIP

Une recherche « live »

Le but de ce formulaire est une recherche dynamique : a chaque nouvelle lettre dans l’input la recherche s’affine.

La bonne nouvelle c’est qu’on peut faire cela nativement avec les fonctions présentent dans SPIP.

Dans un premier temps, il faut créer un fichier formulaires/recherche_ajax.php. Il va mettre à jour le contexte du formulaire en lui passant un critère de recherche {recherche}.

  1. <?php
  2.  
  3. if (!defined('_ECRIRE_INC_VERSION')) {
  4.         return;
  5. }
  6.  
  7. function formulaires_recherche_ajax_charger_dist($ajax_bloc) {
  8.         return array(
  9.                 'ajax_bloc' => $ajax_bloc,
  10.                 'recherche_'.$ajax_bloc => _request('recherche_'.$ajax_bloc),
  11.                 'lang' => $lang,
  12.         );
  13. }

Ensuite un peu de JavaScript et d’HTML pour recharger un bloc ajax, dans un fichier formulaires/recherche_ajax.html.
Ici, j’ai simplement repris le formulaire de recherche de SPIP en modifiant le name de l’input de recherche.

  1. <div class="formulaire_spip formulaire_recherche[ (#ENV{class})]" id="formulaire_recherche">
  2.         <form action="[(#ENV{action})]" method="get">
  3.                 <div class="editer-groupe">
  4.                         [(#ENV{action}|form_hidden)]
  5.                         [<input type="hidden" name="lang" value="(#ENV{lang})" />]
  6.                         <label for="#ENV{_id_champ}"><:info_rechercher_02:></label>
  7.                         <input type="[(#HTML5|?{search,text})]" class="search text" name="recherche_#ENV{ajax_bloc}" id="#ENV{_id_champ}"[ value="(#ENV{recherche})"] />
  8.                         <input type="submit" class="submit" value="&gt;&gt;" title="<:info_rechercher:>" />
  9.                 </div>
  10.         </form>
  11. </div>

Dans le même fichier, à la fin, un peu de JavaScript pour mettre à jour le bloc_ajax (a savoir un squelette avec la boucle de recherche). Pour plus d’information, sur le fonctionnement d’Ajax avec SPIP, la page de la documentation officiel est bien faite.

  1. <script type="text/javascript">
  2.  // Chaque input déclenche la recherche ajax
  3.  $("#recherche_#ENV{ajax_bloc}").on("input", function () {
  4.          ajaxReload(
  5.                  "#ENV{ajax_bloc}",
  6.                  {
  7.                          args: {
  8.                                  // Envoyer le contenu du formulaire dans le
  9.                                  // contexte de recherche SPIP
  10.                                  recherche: $(this).val()
  11.                          }
  12.                  }
  13.          );
  14.  });
  15. </script>

Dans le bloc ajax (un fichier inclure/grille_article), je place simplement ma boucle de recherche :

  1. [(#SET{defaut_tri, #ARRAY{titre, 1, num titre, 1, date, #ENV{date_sens, -1}, id_article, 1, points, -1
  2.  }})
  3.  
  4. ]<B_article_ajax>
  5.         #ANCRE_PAGINATION
  6.         <BOUCLE_article_ajax(articles){recherche ?}{tri #ENV{par, [(#ENV{recherche}|?{points, num titre})]}, #GET{defaut_tri}}{pagination}>
  7.                 <INCLURE{fond=inclure/article_resume}{id_article} />
  8.         </BOUCLE_article_ajax>
  9.         [<p class="pagination">(#PAGINATION)</p>]
  10. </B_article_ajax>

Il ne reste qu’à appeler tout cela :

  1. [(#FORMULAIRE_RECHERCHE_AJAX{grille_article})
  2.  
  3. ]<INCLURE{fond=inclure/grille_article}{env, ajax=grille_article} />

Pour en savoir plus sur les formulaires de SPIP, rien ne vaut la documentation de spip.net :).


Laravel + Foundation 6

Laraval vient par défaut avec Boostrap. Personnellement, en matière de Framework frontend, je préfère largement Foundation.

Heureusement, il existe un preset pour changer cela proprement dans Laravel. Les autres Tuto ou tout était fait à la main était quand même barbant.

Installer le preset :

Facile, on demande à composer :

  1. composer require laravel-frontend-presets/zurb-foundation

Activé le preset :

Soit on veut juste activer foundation :

  1. php artisan preset foundation

Soit on veut aussi que les templates de base de Laravel soit adapté :

  1. php artisan preset foundation-auth

Il ne reste plus qu’à installer :

  1. npm install && npm run dev
Voir en ligne : Zurb Foundation 6 Preset For Laravel 5.5