Snippets

Les snippets sont des bout de code.

Présenté ici de manière volontairement « brute », ces snippets ont vocation à servir d'aide mémoire.

N'hésitez-pas à poser un commentaire si vous rencontrez un problème avec un des éléments.

Vous pouvez utiliser la navigation via les tags présents sur la droite

  • Drupal 8 - Supprimer un type d'entité

    Posté le Mercredi 2 janvier 2019 - 16:10

    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. }

     

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

    Posté le Vendredi 9 novembre 2018 - 11:08

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

     

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

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

     

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

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

    Merci à Alexandre Mallet aka @woprrr pour la piste

  • Drupal 8 - Afficher un noeud via le code

    Posté le Jeudi 25 octobre 2018 - 09:41

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

     

  • Redirection Apache - Rediriger si présence d'un paramètre GET

    Posté le Jeudi 25 octobre 2018 - 09:33

    L'ensemble de règles suivante ne lancera une redirection 301 que sur l'URI /documentation et que si est présent un paramètre GET body_value.

    1. RewriteCond %{REQUEST_URI} ^/documentation$ [NC]
    2. RewriteCond %{QUERY_STRING} body_value
    3. RewriteRule ^(.*)$ http%{ENV:protossl}://%{HTTP_HOST}/recherche-documentation [R=301,L]

    Les urls suivantes seront redirigées :

    Les urls suivantes ne seront pas redirigées :

  • Drupal 8 - Afficher un menu dans le code

    Posté le Jeudi 20 septembre 2018 - 19:10

    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 :

    {{ menus.footer }}

     

  • Apache 2.4 - Vhost - Restreindre l'accès à un site sauf pour certaines IP

    Posté le Mardi 28 août 2018 - 11:42

    Il est facile sous apache de restreindre l'accès à un site dans un virtual host via l'instruction Require valid-user.

    Exemple :

    1. <Directory "/home/monsite/web">
    2. AuthType Basic
    3. AuthName "Restricted Content"
    4. AuthUserFile /home/monsite/htpasswd-preprod
    5. Require valid-user
    6. AllowOverride All
    7. Options -Indexes +FollowSymLinks +MultiViews
    8. </Directory>

    Mais dans certains cas, on veut autoriser certaines ip à accéder au site sans authentification "htpasswd", dans le cas de retour de brique de paiement, ou de webservice, dans ce cas on peut utiliser la forme suivante :

    1. <Directory "/home/monsite/web">
    2. AuthType Basic
    3. AuthName "Restricted Content"
    4. AuthUserFile /home/monsite/htpasswd-preprod
    5. <RequireAny>
    6. Require valid-user
    7. Require ip 194.01.01.0/24 #autorisation d'une range d'ip
    8. Require ip 134.0.0.1 #autorisation d'une ip unique
    9. </RequireAny>
    10. AllowOverride All
    11. Options -Indexes +FollowSymLinks +MultiViews
    12. </Directory>

    Ainsi les accès provenant d'autres parties que l'ip définie ou le range d'ip se verront présenter l'authentification via le htpasswd défini.

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

    Posté le Lundi 6 août 2018 - 18:18

    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.

  • Drupal 8 - Ajouter une restriction par ip sur une route

    Posté le Mercredi 1 août 2018 - 07:48

    Dans le fichier MODULE.routing.yml on va utiliser le requirement « _custom_access »

    1. module.ma_methode:
    2.   path: 'mon-module/mon-chemin'
    3.   defaults:
    4.   _controller: '\Drupal\module\Controller\monController::maMethode'
    5.   requirements:
    6.   _custom_access: '\Drupal\module\Controller\monController::maMethodeAccess'

    Que l'on va implémenter dans notre contrôleur, ici monController.php :

    1. public function maMethodeAccess() {
    2. /** @var Request $request */
    3. $request = \Drupal::request();
    4. $ipAutorisees = \Drupal::config('iamyourstory.checkcard_api')->get('allowed_ips')
    5. $ipAutorisees = explode(',', $ipAutorisees);
    6. $ipAutorisees = array_map('trim', $ipAutorisees);
    7. return AccessResult::allowedIf(\in_array($request->server->get('REMOTE_ADDR'), $ipAutorisees));
    8. }

    à noter :

    • Les ip autorisées sont stockées en configuration via un formulaire de config, les ip sont séparées par une virgule, d'où le explode.
    • J'utilise ensuite la fonction array_map('trim', $ipAutorisees) pour supprimer les éventuels espaces. Si la personne avait saisi « 127.0.0.1, 192.168.0.2 », mon tableau sans le trim sera ['127.0.0.1', ' 192.168.0.2'] (espace au départ de la seconde ip.)
  • Drupal 8 - Entité - Champ de base Fichier (File)

    Posté le Mardi 27 mars 2018 - 08:51

    Voici comment créer un champ « fichier » au sein d'un type d'entité custom dans drupal 8 :

    1. $fields['programme_pdf'] = BaseFieldDefinition::create('file')
    2. ->setLabel(t('Programme PDF'))
    3. ->setSetting('file_directory', 'formations/programme') // dossier d'upload
    4. ->setSetting('max_filesize', '10MB') // taille max du fichier
    5. ->setSetting('file_extensions', 'pdf') // extensions autorisées, à séparer par un espace
    6. ->setSetting('description_field', FALSE) // si on veut activer un champ « description »
    7. ->setDisplayOptions('form', [
    8. 'label' => 'hidden',
    9. 'type' => 'file_generic',
    10. 'weight' => 4,
    11. ])
    12. ->setDisplayConfigurable('form', TRUE)
    13. ->setDisplayConfigurable('view', TRUE);