Lancer une migration avec Migrate de façon programmatique sur Drupal 8
Voici le premier article du nouveau format mis en place sur ce site. C'est un format de type Quickie où je vais parler, démontrer, résoudre une problématique d'un cas réel.
Dans ce premier exemple nous allons voir comment altérer une route existante, d'un module contrib ou du cœur pour changer l'url, la callback, les permissions ...
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) :
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...)
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; } }
Les champs WYSIWYG prennent une place de plus en plus important dans la construction des pages web modernes.
Voici comment utiliser les WYSIWYG, les configurer et comment ajouter des fonctionnalités sous Drupal 8.
Les champs WYSIWYG prennent une place de plus en plus important dans la construction des pages web modernes.
Voici comment utiliser les WYSIWYG, les configurer et comment ajouter des fonctionnalités sous Drupal 8.
Quand on travaille à plusieurs sur un projet, il peut être intéressant de mettre en place des outils de qualité de code afin d’harmoniser le code source que vous souhaitez mettre en place sur votre projet (linter, CodeSniffer et tests) mais pour cela, il faudra alors s'assurer que tous les collaborateurs les utilisent afin d'en tirer réellement partie et c'est là que GrumPHP rentre en jeux.
Pour convertir un champ texte long (ici: field_communiques_texte_wysiwig) en texte log formaté, il suffit de créer un .install dans un module contenant l'exemple ci-dessous :
Ré indexer tout Search API
use Drupal\search_api\Utility\CommandHelper; $command_helper = new CommandHelper(\Drupal::entityTypeManager(),
Création
Pour ajouter du contenu dans un Field Collection, nous allons utiliser la classe Drupal\field_collection\Entity\FieldCollectionItem :
Pour éviter la redondance de \drupal::service('monservice') dans nos classes, nous allons utiliser les injections de dépendances
Partager le dossier de cache
Lorsque vous lancé Composer celui ci va télécharger la liste des packages au format JSON pour les stocker dans un dossier de cache.
Quand vous lancé votre container celui ci est vide, donc vous perdez 30s à chaque fois que vous le lancer.
L'idée ici est d'aller chercher votre dossier de cache local pour le monter sous forme de volume
Placer le hook_unistall dans le fichier .install de votre module
Sa y est, j'ai enfin franchi le cap. j'ai migré tout mon site sur une architecture full Docker en dev, test et prod.
Je vais vous expliquer dans cet article, comment j'ai réussi à mettre tout ça en place
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.
En octobre dernier, l'équipe a décollé pour Amsterdam afin d'y retrouver la communauté Drupal européenne.
Au programme : sessions, BoFs, discussions et contribution.