Planète Kgaut

Par kgaut
Kevin Gautreau

Drupal - Découvrez la fonction ddm, pour débuguer même en aveugle

Si vous développez avec drupal, vous connaissez peut-être les fonctions dump, dpm ou kint, (sinon, lisez ma rapide présentation de kint.)

Une autre fonction très pratique mais moins connue est ddm(), anciennement connue sous le nom de dd(), qui permet de dumper les paramètres dans un fichier, au lieu de les afficher dans la page. Cette fonction est donc très pratique dans les cas où l’on a aucun retour d’affiché (batch, hook_update, EventSubscriber...)

Note : Cette fonction vient du module devel, le module doit donc être installé et activé pour que la fonction soit disponible.

Le paramètre passé à la fonction est dumpé dans le fichier temporary://drupal-debug.txt, ainsi, sur mon site le wrapper temporary:// est configuré dans le dossier ../files/tmp. (Note : cette configuration se fait directement dans le fichier settings.php de drupal, elle était avant dans Configuration / Médias / Système de fichier)

Image

Configuration dossier tmp

Je peux donc afficher le contenu de ce fichier directement dans un éditeur de texte. À savoir que les tableaux et objets sont dumpé hiéarchiquement, ce qui est pratique mais qui peut rapidement alourdir ce fichier !

# Dans un de vos fichier php : ddm($variable);

Image

Sortie de drupal_debug.txt

On peut assi ajouter des labels à ce que l'on dump pour éviter de se perdre quand on dump plusieurs variables :

function kgaut_2020_preprocess_node(array &$variables) {  /** @var \Drupal\node\Entity\Node $node */  $node = $variables['elements']['#node'];   ddm('------------------');  ddm($node->getType(), 'Type de noeud');  ddm($node->getTitle(), 'Titre');  ddm($node->getCreatedTime(), 'Created');...}

Image

Sortie de ddm

Enfin, la fonction bach tail, on peut afficher en live ce qui est dumpé, dans un terminal, sans avoir à recharger le fichier, la commande à exécuter est ci-dessous :

# Chemin à adapter en fonction de votre organisation : tail -f /vhosts/kgaut.net/files/tmp/drupal_debug.txt

Évidement, cela ne vaut pas un "vrai" debuger comme xdebug ou autre, mais c'est mieux que rien !

Par kgaut
Kevin Gautreau

Drupal 9, modules, et versionnement sémantique

Avec l'arrivée prévue le 3 juin 2020 de drupal 9, il n'y a pas besoin de créer une branche 9.x-1.x spécifiquement pour drupal 9, vous pouvez facilement indiquer que votre module est compatible avec cette nouvelle version en ajoutant dans votre fichier mon_module.info.yml la clé suivante :

core_version_requirement: ^8 || ^9

La clé core est à conserver pour garder la compatibilité avec les versions inférieures à drupal 8.7.7 (oui c'est d'un pratique...) Exemple dans un de mes modules.

En outre, il en sera bientôt terminé des versions de module "8.x-1.0", le versionnement sémantique est adopté et est compatible à partir de drupal 8.8.3, C'est à dire que les nouvelles branches de vos projets seront nommées 2.x (au lieu de 8.x-2.x) et les tags (versions) pourront être sous la forme :

2.0.0-beta1
2.0.0
2.0.1
2.1.0

Si vous passez au versionnement sémantique, les numéros de versions doivent être incrémentés, ainsi, si actuellement vous avez actuellement une branche 8.x-2.x, conservez là pour toutes les versions de drupal inférieures à 8.8.3, mais vous pouvez dès maintenant créer une branche 3.x pour la compatibilité avec les versions 8.8.3+ et 9.0.0 de drupal.

Il est possible de spécifier qu'une branche ne sera compatible qu'avec drupal 9 dans le fichier info.yml :

core_version_requirement: ^9

Plus d'informations sur le versionnement sémantique

Plus d'informations sur les changements du fichier mon_module.info.yml

tl;dr

Si vous avez un module avec une branche 8.x-2.x :

Votre module est compatible avec drupal 9 : vous pouvez ajouter la clé "core_version_requirement: ^8 || ^9" à votre module.info.yaml (c'est ce que j'ai fais pour mon mini module popin : https://www.drupal.org/project/popin. Vous pourrez passer au versionnement sémantique pour la prochaine version majeure de votre module
Votre module nécessite de plus gros travaux pour être rendu compatible, vous pouvez garder la branche 8.x-2.x pour drupal 8 et démarrer une branche 3.x qui sera une branche de travail pour drupal 9.

Par kgaut
Kevin Gautreau

Installer et tester drupal 9 avec composer

La première version beta de Drupal 9 est sortie il y a quelques jours, et la version stable est prévue pour le 3 juin.

Si vous souhaitez tester dès aujourd'hui et par exemple vérifier si vos modules sont compatibles, voici comment installer la première beta avec composer :

Dans le dossier où vous souhaitez installer drupal :

composer create-project drupal/recommended-project:9.0.0-beta1 ./

Ensuite configurez votre serveur web pour pointer sur le dossier web et c'est parti :

Image

Drupal 9

Par kgaut
Kevin Gautreau

Module drupal 8 : Apidae Tourisme

Apidae tourisme est un « réseau d'informations touristiques » qui permet aux offices du tourisme, mairies... De créer des « lieux » (restaurants, hôtels...) ainsi que des évènements sur des cartes de manière collaborative.

Dans le cadre d'un ancien projet, j'avais du développer une intégration avec l'API de ce service et un site drupal. J'avais à l'époque développé ce module sur github afin de peut-être un jour le mettre à disposition de tous. Un drupalistos m'a signalé récèment qu'il était listé sur la page des intégrations disponible sur la doc développeur d'Apidae.

Rebelote pour un projet que je vais attaquer, du coup j'ai pris un peu de temps pour packager le module que j'avais développé à l'époque, le nettoyer un peu afin de le publier sur drupal.org. C'est chose faite aujourd'hui !

Le module permet à intervalle régulier de synchroniser les données venant d'Apidae et de créer / mettre à jours des nœuds en récupérant différents champs (noms, description, médias, téléphone, coordonnés GPS...)

Le module gère le multi-langue et on peut ainsi récupérer des traductions des fiches et générer des traductions des nœuds.

Actuellement seulement certains champs sont mappés, mais je compte rendre ça administrable dans un futur proche.

Je suis preneur de suggestions et n'hésitez-pas à me contacter si vous souhaitez de l'aide ou des informations dans sa mise en œuvre.

La page du module sur drupal.org : https://www.drupal.org/project/apidae_tourisme

Par kgaut
Kevin Gautreau

Drupal 8 - Views - Créer un filtre contextuel personnalisé

Les contextual filters ou filtres contextuels sont une fonctionnalité très utile du module views de drupal : il permettent, comme le nom l'indique de filtrer les éléments affichés en fonction d'un paramètre contextuel (lié à un nœud, à l'internaute, un paramètre GET...).

Certains sont fournis de base avec drupal mais ils ne conviennent pas forcement à tous les cas d'utilisation.

Dans le cas présent, le but est de filtrer des nœuds en fonction de la localité de l'utilisateur (techniquement un terme de taxonomie) afin que l'utilisateur ne visualise que les nœuds qui concerne sa commune. Les nœuds ont un champ « référence à un terme de taxonomie » multiple, même chose pour l'utilisateur mais simple pour lui. Donc un nœud peut concerner plusieurs communes alors qu'un utilisateur n'appartient qu'à une seule commune.

Création du filtre contextuel :

# web/modules/custom/mon_module/src/Plugin/views/argument_default/UserLocalite.phpisAnonymous()) {      return 'all';    }    $user = User::load($user->id());    // getLocalitesId() est une methode personnalisée de la classe User    // qui retourne l'id du terme de taxonomy de la localité    return $user->getLocalitesId();  }   // Ma classe implémentant CacheableDependencyInterface, on peut ainsi ajouter des paramètres   // de cache, si ça n'est pas nécessaire, il suffit de supprimer l’implémentation et les deux méthodes ci-dessous.  public function getCacheMaxAge() {    return Cache::PERMANENT;  }   public function getCacheContexts() {    return ['user:localite'];  }}

Il nous reste plus qu'à sélectionner le filtre dans la liste des filtre contextuels de drupal, en choisissant bien le champs sur lequel le filtre doit s'appliquer (dans mon cas : node.localites_cibles) :

Ajout filtre contextuel

 

Configuration du filtre contextuel

 

Par kgaut
Kevin Gautreau

Drupal 8 - Surcharger la classe de l'entité User

Sous Drupal 8 il est possible de surcharger la classe du type d'entité « User » afin de par exemple ajouter nos propres getters et setters ou de modifier l'affichage par défaut d'un nom d'utilisateur.

Pour cela il faut informer drupal qu'on va changer la classe de base pour le type d'entité User. Cela se passe dans le .module via le hook HOOK_entity_type_alter :

function monmodule_entity_type_alter(array &$entity_types) {  $entity_types['user']->setClass(\Drupal\monmodule\Entity\User::class);}

Et il faut ensuite définir la classe en elle même :

# web/modules/custom/monmodule/src/Entity/User.phplastname->value . ' ' . $this->firstname->value;  }   public function setDomain($domain_id) {    $this->set('field_domain_access', [$domain_id]);    return $this;  } }

Rien de foufou ici, j'ai surchargé la méthode « label », ainsi par exemple dans la listes des membres du site sera affiché en lieu et place de leur nom d'utilisateur, leurs nom et prénom. Il y a aussi un setter pour définir le domain de l'utilisateur.

Maintenant d'est que l'on chargera un utilisateur il sera de cette classe, et non plus de la classe de base.

Ceci est évidement possible pour l'ensemble des types d'entités (Noeuds, terme de taxonomy...)

Par kgaut
Kevin Gautreau

Drupal 8 - Surcharger la page de liste des termes de taxonomie

La page par défaut de liste des termes de taxonomie de drupal 8 n'est pas très flexible. Elle peut facilement être substituée à une vue mais dans ce cas on perd le « drag'n'drop » dans le cas d'une arborescence.

Pour garder ce comportement, mais pouvoir quand même ajouter des colonnes, il est possible de surcharger le formulaire gérant cette page.

Cela se passe en 3 étapes :

1. Déclaration du service d'alteration de la route

# mon_module.services.ymlservices:  mon_module.route_subscriber:    class: Drupal\mon_module\Routing\VocabularyOverviewRouteProvider    tags:      - { name: event_subscriber }

2. Altération de la route

get('entity.taxonomy_vocabulary.overview_form');    // Make a change for default taxonomy overview form.    $route->setDefault('_form', VocabularyOverviewTerms::class);    // Re-add the collection to override the existing route.    $collection->add('entity.taxonomy_vocabulary.overview_form', $route);  } }

3. Surcharge du formulaire

Note : Ici je ne modifie le formulaire que pour un seul vocabulaire (etudiant_promos) et j'ajoute une colonne « Domain ».

id() !== 'etudiant_promos') {      return $form;    }    // On ajoute l'entête du tableau    $form['terms']['#header']['domain'] = $this->t('Domain');     // On parcours les ligne pour ajouter notre colonne    foreach ($form['terms'] as $key => &$termRow) {      if(strpos($key, 'tid:') === 0) {        /** @var \Drupal\taxonomy\Entity\Term $term */        $term = Term::load($termRow['term']['tid']['#value']);        /** @var \Drupal\domain\Entity\Domain $domain */        $domain = $term->get('domain')->referencedEntities()[0];        $termRow['domain'] = ['#markup' => $domain->label()];      }    }    return $form;  } }

 

 

Par kgaut
Kevin Gautreau

Drupal 8 - créer des suggestions de templates pour des types d'entités personnalisés

Voici comment ajouter des suggestions de template à un type d'entité personnalisé en fonction du mode d'affichage (view_mode).

Ici mon module s’appelle « mon_module » et mon type d'entité personnalisé « resource » :

function monmodule_theme_suggestions_resource(array $variables) {  $suggestions = [];  $sanitized_view_mode = str_replace('.', '_', $variables['elements']['#view_mode']);  $suggestions[] = $variables['theme_hook_original'] . '__' . $sanitized_view_mode;  return $suggestions;}

Ainsi, si j'ai un mode d'affichage « teaser » je pourrais utiliser un template resource--teaser.html.twig à la place de celui par défaut : resource.html.twig

Vous pouvez évidement ajouter autant de suggestions de template que nécessaire, en fonction d'autres paramètres.

Par kgaut
Kevin Gautreau

Drupal 8 - Menu - Ajouter une classe à un élément de menu

Voici comment ajouter une classe css à un élément de menu défini dans un module.

mon_module.links.menu.yml

main.abonnez:  title: 'Abonnez-vous'  route_name: entity.node.canonical  route_parameters: { node: 6 }  menu_name: main  weight: 4  options:    attributes:      class:        - 'arrow'

la clé class étant un tableau, il est évidement possible d'ajouter autant de classes css que l'on veut.

Voir aussi :  Drupal 8 - Menu - Ajouter un élément de menu avec des paramètres GET

Par kgaut
Kevin Gautreau

Drupal 8 - Type d'entité personnalisé - supprimer un « basefield »

Voici comment supprimer le basefield « mon_champ_a_suppr » de mon type d'entité personnalisé « mon_type_entite ».

/** * Delete basefield mon_type_entite.mon_champ_a_suppr */function monmodule_update_8020() {  $update_manager = Drupal::service('entity.definition_update_manager');  $definition = $update_manager->getFieldStorageDefinition('mon_champ_a_suppr', 'mon_type_entite');  $update_manager->uninstallFieldStorageDefinition($definition);  return t('mon_type_entite : mon_champ_a_suppr was uninstalled');}

Lancez les mises à jours de base de données de drupal (drush updb par exemple) et hop, votre champ sera supprimé de votre base de données, évidement si votre type d'entité avait des enregistrements, les données concernants le champ supprimé seront perdues.

Certains diront qu'il est possible d'utiliser la commande drush entup, mais le mécanisme n'est plus présent depuis drupal 8.7. (mais si vraiment vous en avez besoin, vous pouvez regarder du côté du module Devel Entity Updates, à n'installer qu'en connaissance de cause !

Pages