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 7 - Créer un champ calculé pour Views

    Posté le Jeudi 14 mars 2019 - 19:01

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

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

    files[] = MonModuleLatestRisk.php

    Dans MonModuleLatestRisk.php : La logique de calcul du champ

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

     

  • Drupal 8 - Créer un filtre de texte

    Posté le Lundi 18 février 2019 - 15:18

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

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

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