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 - Template - Spécifier un thème spécifique

    Posté le Samedi 27 avril 2019 - 11:21

    Quand un template est appelé via un « reder array », le template va être cherché en priorité dans le thème actif, puis dans le module qui déclare ce template.

    Dans certains cas, cela peut poser problème : Si un template peut-être appelé dans un contexte back ou front, les thèmes sont la plupart du temps différents. La solution de feignant pourrait être de dupliquer ce template dans les deux thèmes. Mais c'est évidement pas une bonne solution.

    Dans la déclaration du template on peut spécifier où trouver le template en question :

    1. $themes['xml_sitemap'] = [
    2. '#template' => 'xml-sitemap',
    3. 'path' => drupal_get_path('theme', 'mon_theme_back') . '/templates',
    4. 'variables' => [
    5. 'urls' => [],
    6. ],
    7. ];

    Ainsi peut importe si mon template est appelé depuis le front ou depuis le back ça sera toujours le fichier :

    themes/custom/mon_theme_back/templates/xml-sitemap.html.twig qui sera utilisé.

  • Drupal 8 - Entité - Champ de base « texte long avec résumé »

    Posté le Jeudi 11 avril 2019 - 08:42

    Voici comment ajouter un champ texte formaté avec résumé à un type d'entité :

    1. $fields['synospis'] = BaseFieldDefinition::create('text_with_summary')
    2. ->setLabel(t('Synopsis'))
    3. ->setSetting('text_processing', TRUE)
    4. ->setDisplayConfigurable('view', TRUE)
    5. ->setDisplayConfigurable('form', TRUE)
    6. ->setTranslatable(TRUE);

    À noter que j'ai maintenant pris l'habitude de ne plus configurer les options d'affichage en mode formulaire et front dans mon type d'entité, mais je le fais directement en backoffice du site.

    Voir des exemples d'affichages sur un texte long.

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