Planète

Par KarimB
Karim Boudjema
Je suis Karim Boudjema ou KarimB en ligne. Je suis belge, développeur Drupal et aussi administrateur d'entreprises. Je vis pour l'instant à Cochabamba, en Bolivie. Quand j'ai découvert Drupal 4.7 en 2008 (et oui… il y a 10 ans), j'ai tout suite senti que ce serait un changement important dans le monde du développement web. Et ce fut le cas!

Sauvegarder les valeurs d'un formulaire avec Private Tempstore sous Drupal 8

Dans ce billet, nous allons voir comment sauvegarder temporairement les valeurs d'un formulaire et comment les récupérer ou les traiter plus tard dans un contrôleur. Pour cela, nous allons utiliser la Form API et un stockage de type private tempstore (le temporary store storage system de Drupal 8).

Le scénario est le suivant: nous devons créer un simple lecteur RSS (un formulaire) où un utilisateur puisse introduire l'URL d'un fichier RSS et aussi le nombre d'éléments à récupérer de ce dernier. Ensuite, sur une nouvelle page (un contrôleur), l'application doit afficher les éléments requis avec leur lien vers les pages syndiquées.

La manière la plus simple serait de récupérer ces valeurs dans la méthode buildForm() de notre formulaire, les traiter et les afficher dans un champs spécifique de notre formulaire. Mais ce n'est pas notre cas puisque nous devons afficher les résultats sur une nouvelle page.

Par Kgaut
Adhérent
Kevin Gautreau

Drupal 7 - Créer un champ calculé pour Views

(et oui des fois on doit retourner sous drupal 7)

Voici comment créer un champ calculé pour un type d'entité (ici Node) qui sera accessible comme n'importe quel champ dans views.

Dans mon_module.module :

  1. function mon_module_views_api($module = NULL, $api = NULL) {
  2. return ['api' => '3.0'];
  3. }

Dans mon_module.views.inc : définition des champs

  1. function mon_module_views_data() {
  2. $data = array();
  3.  
  4. $data['node']['risk'] = [
  5. 'title' => t('Country latest risk'), // Titre visible dans views
  6. 'help' => t('Country latest risk description'), // Description visible dans views
  7. 'field' => [
  8. 'handler' => 'MonModuleLatestRisk', // Nom de la classe qui "rendra" notre champ calculé
  9. ],
  10. ];
  11.  
  12. return $data;
  13. }

Dans mon_module.info : ne pas oublier de lister notre fichier qui contiendra notre classe

files<span class="br0">[</span><span class="br0">]</span> <span class="sy0">=</span> MonModuleLatestRisk<span class="sy0">.</span>php

Dans MonModuleLatestRisk.php : La logique de calcul du champ

  1. class MonModuleLatestRisk extends views_handler_field {
  2.  
  3. function render($values) {
  4. // Logique de "calcul" de notre champ
  5. // À noter que $values contient l'ensembles des champs sélectionnés (qu'ils soient exclus de l'affichage ou non) dans notre vue
  6. if(isset($values->field_field_country_scenarios[0]['raw'])) {
  7. return $values->field_field_country_scenarios[0]['raw']['entity']->field_description['und'][0]['value'];
  8. }
  9. return null;
  10. }
  11.  
  12. function query() {
  13. // laisser vide
  14. }
  15. }

 

Personnaliser le fil d'Ariane avec Drupal 8

Drupal 8 dispose par défaut de deux méthodes pour construire le fil d'Ariane. Pour les contenus, cette méthode est basé sur l'URL de la page, et pour les termes de taxonomie cette méthode est basée sur la hiérarchie du vocabulaire. Explorons plus en détails la construction du fil d'Ariane et les alternatives possibles pour le personnaliser en tant que de besoin.

Par Artusamak
Julien Dubois

Drupalcamp Paris 2019 - Bilan des trois jours

Drupalcamp Paris 2019 - Bilan des trois jours
Artusamak
mar 05/03/2019 - 08:55

Retrouvez le lien vers la présentation RGPD donnée par Guillaume et le compte-rendu de nos efforts de sprint de traduction.

Corps

Nous voilà enfin remis de la traditionnelle Drupal flu, il est temps de vous partager le bilan de ces 3 jours de Drupalcamp Paris 2019.

Un camp, c'est surtout l'occasion de retrouver les copains et les copines de la communauté, mais aussi de faire de nouvelles rencontres ! On aurait aimé qu'Edouard puisse être parmi nous mais une contrainte de dernière minute l'a forcé à nous abandonner.

L'innovation de cette édition résidait dans la tenue d'une session Business où les clients ont pu enchaîner les retours d'expérience sur la mise en œuvre de leurs projets. Nous avons convié l'UNESCO à venir témoigner sur ses problématiques de gestion de multi-sites après plusieurs années et comment nous les accompagnons pour les aider à optimiser leur temps.

L'après-midi, Guillaume a fait une présentation sur le choix de modules pour mettre en œuvre les recommandations du RGPD avec Drupal dans la session Experts. Vous saurez quel module utiliser dans quelle situation avec ses slides.

Le lendemain, j'ai répondu à l'invitation pour répondre à la question "Pourquoi choisir Drupal" où les anciens présidents de l'association ont pu défendre Drupal :

Et pour terminer, le dimanche a eu lieu la journée de sprints. Là on peut dire que l'on a explosé les compteurs, l'équipe de traduction était remontée pour avoir le cœur à nouveau à 100% de chaînes traduites et validées. Il en manquait environ 260 au début du camp, le nombre est tombé à 0 et même mieux, les modules Pathauto, Metatag, Redirect, Recaptcha, Honeypot, Inline Entity Form, Diff, Paragraphs et Fences sont passés à 100% de chaînes avec suggestions ! Il ne reste plus qu'à les valider dans les semaines qui viennent pour concrétiser ces efforts. Le guide utilisateur français a même vu sa traduction se remettre en marche.

Merci et bravo à tous les contributeurs et toutes les contributrices qui ont beaucoup donné pour ce sprint. Tous les progrès sont visibles ici : https://mensuel.framapad.org/p/dcp2019-sprints

Rendez-vous au prochain camp pour de nouveaux progrès ! Merci aux volontaires qui ont aidé à l'organisation, on sait que vous y avez laissé beaucoup d'énergie. Mention particulière pour la nourriture, vous avez fait l'effort de proposer des menus végétariens pour tous, c'était une super idée responsable. On valide !

Catégories
Drupal
Tags
session
contribution
Par admin

Assemblée générale 2019

L'assemblée générale de l'association Drupal France et francophonie aura lieu le 26 mars 2019
Elle aura à l'ordre du jour :

  • Rapport moral présenté par le président
  • Rapport financier présenté par le trésorier
  • Élection du nouveau bureau
  • Questions ouvertes

Les membres désirant présenter leur candidature au bureau, et ceux qui souhaitent inclure des points complémentaires à l'ordre du jour devront se manifester au plus tôt au bureau via email à bureau@listes.drupalfr.org
Si vous ne pouvez être physiquement présent lors du vote, vous pouvez vous faire représenter par un autre membre de l'association muni d'un pouvoir régulier.
Le document de pouvoir est disponible ci-dessous.

Vous pouvez le remettre à votre personne procuratrice, ou l'envoyer par voie électronique (scan signé) au bureau à bureau@listes.drupalfr.org avant le 23 mars 2019.
Vous pouvez également participer à l'Assemblée Générale par un moyen de communication électronique permettant de vous identifier formellement.

Dans ce cas, si vous souhaitez participer aux votes par voie électronique, vous devrez renoncer à l'anonymat des votes afin de les transmettre.
Nous vous rappellons également que seuls les membres à jour de leur cotisation peuvent participer à l'Assemblée Générale et participer au vote.

N'hésitez pas à mettre à jour votre adhésion dès à présent grâce au bulletin disponible en ligne (Connectez-vous sur drupal.fr/user onglet "Mon adhésion").
Merci à vous tous,
Merci pour votre implication,
Merci d'être vous.

-
Floris MORICEAU THEVENOT
Secrétaire - Drupal France

................................................................................................

POUVOIR

Je soussigné : ………………………………………………………………….

Ne pouvant pas assister à l'Assemblée Générale de l'Association Drupal France et Francophonie le 28 mars 2019 à Paris, donne pouvoir à:

…………………………………………………………………………………………………..

(Laissez ce nom en blanc si vous souhaitez que le pouvoir soit utilisé par le Bureau)

Afin de me représenter et de participer à tout vote en mon lieu et place.

Fait à :

le :

SIGNATURE
précédée de la mention manuscrite obligatoire « Bon pour pouvoir ».

En page d'accueil : 
Par Kgaut
Adhérent
Kevin Gautreau

Drupal 8 - Créer un filtre de texte

À la demande d'un client je devais ajouter un attribut « target="_blank" » sur tous les liens sortant du site.

J'ai pour cela créé un filtre de texte que j'ai appliqué à un format de texte.

Voici le fichier mon_module/src/Plugin/Filter/UrlTargetBlankFilter.php

  1. namespace Drupal\mon_module\Plugin\Filter;
  2.  
  3. use Drupal\filter\FilterProcessResult;
  4. use Drupal\filter\Plugin\FilterBase;
  5.  
  6. /**
  7.  * @Filter(
  8.  * id = "url_target_blank_filter",
  9.  * title = @Translation("Url Target Blank"),
  10.  * description = @Translation("Add « target=_blank » to all urls"),
  11.  * type = Drupal\filter\Plugin\FilterInterface::TYPE_TRANSFORM_IRREVERSIBLE,
  12.  * )
  13.  */
  14. class UrlTargetBlankFilter extends FilterBase {
  15.  
  16. public function process($text, $langcode) {
  17. $regex = "/(\\b[^]*href=['\"]?http[^]+)>/is";
  18. $subst = "$1 target=\"_blank\" rel=\"noopener\">";
  19. $result = preg_replace($regex, $subst, $text);
  20. return new FilterProcessResult($result);
  21. }
  22. }

À noter : j'ai aussi ajouté l'attribut rel="noopener" comme suggéré par Simon Georges.

Par Kgaut
Adhérent
Kevin Gautreau

Le programme du drupalcamp Paris 2019 est disponible

Le drupalcamp est l'évènement Drupal en France rassemblant l'ensemble de la communauté francophone. L'évènement est organisé par une équipe de bénévole et est porté par l'association Drupal France et Francophonie.

Cette année, le drupalcamp revient à Paris et se tiendra les 15, 16 et 17 février 2019 à l'espace St-Martin en plein cœur de Paris.

Nous venons de terminer le programme des conférences, et il est consultable directement sur le site de l'évènement : https://paris2019.drupal.fr/programme.

Cette années, trois tracks en parallèle : Business / Expertise / Découverte.

Comme d'habitude aux drupalcamp, le dimanche sera consacré a des ateliers, des sprints de développement et de traduction.

La billetterie est toujours ouverte, n'hésitez-pas à prendre vos places dès maintenant : https://paris2019.drupal.fr/billetterie.

Pour vous tenir au courant sur l'évènement les infos principales sont données sur le compte twitter @drupalcampfr.

 

Par Kgaut
Adhérent
Kevin Gautreau

Drupal 8 - Supprimer toutes les entités d'un certain type

Dans mon_module.install :

  1. /**
  2.  * Remove all products
  3.  */
  4. function mon_module_update_8001() {
  5. $toDelete = \Drupal::entityQuery('product')->execute();
  6. foreach ($toDelete as $item) {
  7. $item = \Drupal\clearblue\Entity\Product::load($item);
  8. $item->delete();
  9. }
  10. }

 

Par Kgaut
Adhérent
Kevin Gautreau

Drupal 8 - Supprimer un type d'entité

Dans mon_module.install :

  1. /**
  2.  * Remove Product entity type
  3.  */
  4. function mon_module_update_8001() {
  5. $entity_type = 'product';
  6. $entity_update_manager = \Drupal::entityDefinitionUpdateManager();
  7. $entity_type = $entity_update_manager->getEntityType(entity_type);
  8. $entity_update_manager->uninstallEntityType($entity_type);
  9. }

 

Par Kgaut
Adhérent
Kevin Gautreau

Drupal 8 - Ajouter une propriété à un type d'entité config

Voici comment altérer un type d'entité config pour lui ajouter une propriété.

Dans le cas présent, nous allons modifier le type d'entité ConfigurableLanguage afin de lui ajouter un champ google_analytics, pour avoir par exemple un code de tracking différent pour chaque langue.

Commençons par définir les nouveaux formulaire concernant pour l'édition et la création de langue :

modules/custom/mon_module/mon_module.module

  1. function mon_module_entity_type_alter(array &$entity_types) {
  2. $entity_types['configurable_language']->setFormClass('add', \Drupal\mon_module\Entity\Form\LanguageCustomAddForm::class);
  3. $entity_types['configurable_language']->setFormClass('edit', \Drupal\mon_module\Entity\Form\LanguageCustomEditForm::class);
  4. }

 

Ci dessous, le contenu des formulaires qui héritent directement des formulaires de base qu'ils supplantent.

modules/custom/mon_module/src/Entity/Form/LanguageCustomAddForm.php

  1.  
  2. namespace Drupal\mon_module\Entity\Form;
  3.  
  4. use Drupal\Core\Form\FormStateInterface;
  5. use Drupal\language\Form\LanguageAddForm;
  6.  
  7. class LanguageCustomAddForm extends LanguageAddForm {
  8. use LanguageCustomTrait;
  9.  
  10. public function form(array $form, FormStateInterface $form_state) {
  11. $form = parent::form($form, $form_state);
  12. $this->getFormCustomFields($form);
  13. return $form;
  14. }
  15.  
  16. }

 

modules/custom/mon_module/src/Entity/Form/LanguageCustomEditForm.php

  1.  
  2. namespace Drupal\mon_module\Entity\Form;
  3.  
  4. use Drupal\Core\Form\FormStateInterface;
  5. use Drupal\language\Form\LanguageEditForm;
  6.  
  7. class LanguageCustomEditForm extends LanguageEditForm {
  8. use LanguageCustomTrait;
  9.  
  10. public function form(array $form, FormStateInterface $form_state) {
  11. $form = parent::form($form, $form_state);
  12. $this->getFormCustomFields($form);
  13. return $form;
  14. }
  15.  
  16. }

 

Enfin, afin d'éviter la répétition de code, je passe par un trait qui contient mes customisations.

Ce trait est appelé dans les classes ci-dessous via l'appel : $this->getFormCustomFields($form);

Ce trait, fait deux choses, dans la méthode getFormCustomFields() il altère le formulaire pour ajouter le champs qui nous intéresse, et via l'appel à la méthode customEntityBuilder(), l'enregistrement de ce champ est effectué.

modules/custom/mon_module/src/Entity/Form/LanguageCustomTrait.php

  1.  
  2. namespace Drupal\mon_module\Entity\Form;
  3.  
  4. use Drupal\Core\Form\FormStateInterface;
  5. use Drupal\language\ConfigurableLanguageInterface;
  6.  
  7. trait LanguageCustomTrait {
  8.  
  9. public function getFormCustomFields(&$form) {
  10. /* @var $language \Drupal\language\ConfigurableLanguageInterface */
  11. $language = $this->entity;
  12.  
  13. $form['google_analytics'] = [
  14. '#title' => t('ID Google Analytics'),
  15. '#type' => 'textfield',
  16. '#default_value' => $language->getThirdPartySetting('mon_module', 'google_analytics')
  17. ];
  18. $form['#entity_builders'][] = '::customEntityBuilder';
  19. }
  20.  
  21. function customEntityBuilder($entity_type, ConfigurableLanguageInterface $language, &$form, FormStateInterface $form_state) {
  22. if ($form_state->getValue('google_analytics')) {
  23. $language->setThirdPartySetting('mon_module', 'google_analytics', $form_state->getValue('google_analytics'));
  24. return;
  25. }
  26. $language->unsetThirdPartySetting('mon_module', 'google_analytics');
  27. }
  28.  
  29. }

évidement, pensez à modifier toutes les occurrences de mon_module par le nom machine de votre module.

Merci à Alexandre Mallet aka @woprrr pour la piste

Par Kgaut
Adhérent
Kevin Gautreau

Drupal 8 - Afficher un noeud via le code

Pour afficher avoir le renderable array d'un noeud dans le code, rien de plus simple via le service entity_type.manager :

  1. $node = Node::load(1);
  2. $node_rederable = \Drupal::service('entity_type.manager')->getViewBuilder('node')->view($node);

Pour utiliser un autre view_mode :

  1. $node = Node::load(1);
  2. $node_rederable = \Drupal::service('entity_type.manager')->getViewBuilder('node')->view($node, 'embed');

Évidement le plus propre et de passer par l'injection de dépendance, voici une version simplifiée de mon contrôleur :

  1.  
  2. namespace Drupal\mon_module\Controller;
  3.  
  4. use Drupal\Core\Controller\ControllerBase;
  5. use Drupal\Core\Entity\EntityTypeManager;
  6. use Drupal\node\Entity\Node;
  7. use Symfony\Component\DependencyInjection\ContainerInterface;
  8.  
  9. /**
  10.  * Class PageController.
  11.  */
  12. class PageController extends ControllerBase {
  13.  
  14. /**
  15.   * @var \Drupal\Core\Entity\EntityTypeManager
  16.   */
  17. protected $entityTypeManager;
  18.  
  19. public function __construct(EntityTypeManager $entityTypeManager) {
  20. $this->entityTypeManager = $entityTypeManager;
  21. }
  22.  
  23. public static function create(ContainerInterface $container) {
  24. return new static($container->get('entity_type.manager'));
  25. }
  26.  
  27. public function frontpage() {
  28. $node = Node::load(1);
  29. $page = $this->entityTypeManager->getViewBuilder('node')->view($node, 'embed');
  30.  
  31. return [
  32. 'page' => $page,
  33. ];
  34. }
  35. }

 

Par Kgaut
Adhérent
Kevin Gautreau

Drupal 8 - Afficher un menu dans le code

Dans le contrôleur / Bloc...

  1. /** @var \Drupal\Core\Menu\MenuLinkTree $menu_tree_service */
  2. $menu_tree_service = \Drupal::service('menu.link_tree');
  3. $menu_parameters = new \Drupal\Core\Menu\MenuTreeParameters();
  4. $menu_parameters->setMaxDepth(1); // Profondeur du menu à afficher
  5. $menu_name = 'footer' // Nom machine du menu à afficher
  6. $menus = [
  7. 'footer' => $menu_tree_service->build($menu_tree_service->load($menu_name, $menu_parameters)),
  8. ];
  9. return [
  10. '#theme' => 'page-404',
  11. '#menus' => $menus,
  12. ];

et tout simplement dans notre template :

<span class="br0">{</span><span class="br0">{</span> <span class="re0">menus</span><span class="re1">.footer</span> <span class="br0">}</span><span class="br0">}</span>

 

Par Kgaut
Adhérent
Kevin Gautreau

Drupal 8 - Créer la traduction d'une chaine de caractère dans le code

Dans un processus de déploiement, il est utile de gérer les traductions de chaînes de caractères dans le code, afin de pouvoir les déployer plus facilement.

Exemple avec cette fonction d'update à adapter en fonction de vos besoins :

  1. /**
  2.  * Création d'une traduction
  3.  */
  4. function mespronos_tweaks_update_8005() {
  5. $chaine = 'Forgotten password';
  6. $traduction = 'Mot de passe oublié';
  7. $storage = \Drupal::service('locale.storage');
  8. $string = $storage->findString(['source' => $chaine]);
  9. if ($string === NULL) {
  10. $string = new \Drupal\locale\SourceString();
  11. $string->setString($chaine);
  12. $string->setStorage($storage);
  13. $string->save();
  14. }
  15.  
  16. $translation = $storage->createTranslation(array(
  17. 'lid' => $string->lid,
  18. 'language' => 'fr',
  19. 'translation' => $traduction,
  20. ))->save();
  21. }

Pour un exemple réel, il sera plus pratique de passer par un tableau associatif (à deux dimensions si l'on veut importer plusieurs langues) qui sera parcouru par un ou deux foreach.

Par admin

Faille de sécurité février 2019 - PSA-2019-02-19

Nous venons d'apprendre par l'équipe de sécurité de Drupal qu'une nouvelle version de notre CMS sera disponible demain, mercredi 20 février entre 19H et 23H (heure de Paris).

Cette version corrige un problème « critique » de sécurité du noyau de Drupal impactant la version 8.

Évidement pas beaucoup d'informations pour l'instant, il faudra attendre que le patch soit disponible afin d'en savoir plus.

Ce que l'on sait pour l'instant

  • Les versions 8.5.x et 8.6.x de Drupal seront patchées.
  • Rien n'indique que les version 8.4.x, 8.3.x... ne sont pas impactées, mais elles ne sont plus maintenues. Si vous avez encore des sites sous ces versions, faites vite les mises à jour vers drupal 8.5.x ou 8.6.x
  • Il semblerait que des modules tiers drupal 8 soient aussi impactés, les informations seront disponibles en même temps que le patch.
  • Drupal 7 ne semble pas impacté...
  • ...Mais il est possible que des modules tiers drupal 7 le soient, l'équipe de sécurité n'est par contre pas en mesure de fournir une liste pour le moment.

Que faire avant la mise à disposition du patch ?

  • Si vous ne gérez pas votre site drupal vous-même : rapprochez-vous de votre prestataire afin de vous assurer qu'il est bien au courant et qu'il pourra appliquer le patch de sécurité au plus tôt.
  • Assurez-vous que vous avez bien la dernière version de votre drupal 8 à jour.
  • Une petite sauvegarde ne peut pas faire de mal
  • Suivez le compte twitter de l'association (@drupalfr), où nous vous fournirons toutes les informations le plus rapidement possible

Retrouvez sur le site drupal.org l'annonce de ce correctif (Anglais) : https://www.drupal.org/psa-2019-02-19

Version de Drupal : 
En page d'accueil : 

Une usine à sites Drupal avec Micro site

J'ai eu le plaisir de présenter le module Micro Site qui permet de mettre en place une usine à sites sur Drupal 8 lors du dernier DrupalCamp Paris 2019. Ce billet a pour objet de mettre à disposition le contenu de la présentation pour ceux intéressés, et de compléter cette présentation par quelques éléments supplémentaires post-conférence. Et bien entendu pour remercier et féliciter comme il se doit les organisateurs sans qui cet événement n'aura pas pu avoir lieu.

Par Kgaut
Adhérent
Kevin Gautreau

Drupal 8 - Créer un filtre de texte

À la demande d'un client je devais ajouter un attribut « target="_blank" » sur tous les liens sortant du site.

J'ai pour cela créé un filtre de texte que j'ai appliqué à un format de texte.

Voici le fichier mon_module/src/Plugin/Filter/UrlStupidTargetBlankFilter.php

  1. namespace Drupal\mon_module\Plugin\Filter;
  2.  
  3. use Drupal\filter\FilterProcessResult;
  4. use Drupal\filter\Plugin\FilterBase;
  5.  
  6. /**
  7.  * @Filter(
  8.  * id = "url_stupid_target_blank_filter",
  9.  * title = @Translation("Url Target Blank"),
  10.  * description = @Translation("Add « target=_blank » to all urls"),
  11.  * type = Drupal\filter\Plugin\FilterInterface::TYPE_TRANSFORM_IRREVERSIBLE,
  12.  * )
  13.  */
  14. class UrlStupidTargetBlankFilter extends FilterBase {
  15.  
  16. public function process($text, $langcode) {
  17. $regex = "/(\\b[^]*href=['\"]?http[^]+)>/is";
  18. $subst = "$1 target=\"_blank\" rel=\"noopener\">";
  19. $result = preg_replace($regex, $subst, $text);
  20. return new FilterProcessResult($result);
  21. }
  22. }

À noter : j'ai aussi ajouté l'attribut rel="noopener" comme suggéré par Simon Georges.

Par lequipe.tech
L'Équipe.tech

Session DrupalCamp Paris 2019 - Les bonnes pratiques sous Drupal 8

Session DrupalCamp Paris 2019 - Les bonnes pratiques sous Drupal 8 Work harderFabien CLÉMENT
lun 18/02/2019 - 13:43

Lors du DrupalCamp 2019 qui à eu lieu à Paris le week-end dernier (du 15 au 17 février 2019) à L'Espace Saint Martin, j'ai eu le plaisir de monter sur les planches pour vous parler des bonnes pratiques de développement sous Drupal 8.

En tout, une vingtaine de règles, même si d'autres pourraient s'ajouter. Dès les échanges suivant cette présentation, d'autres points me sont revenus, ce qui pourrait finalement faire l'objet d'un billet de blog à compléter au fur et à mesure.

Catégorie

Pages