Planète

Utiliser les modules expérimentaux de Drupal 8 ?

La qualité d'un CMS ne se juge pas seulement au travers de la qualité de son architecture, de son API, mais aussi au travers de ses fonctionnalités out of the box, permettant d'accomplir des mises en page, des comportements spécifiques, en quelques clics. On peut rapprocher la valeur d'un CMS avec celle du diamant. La valeur d'un diamant brut ne vaut pas grand chose, tandis que celle d'un diamant travaillé est sans commune mesure.

Par kgaut
Kevin Gautreau

Drupal Camp Lannion 2017 - 27-28-29 Octobre

L'association Drupal France et l'équipe de bénévoles, organise comme chaque année un Drupal Camp, pour 2017, c'est en Bretagne, à Lannion du 27 au 29 octobre !

Drupal Camp, c'est quoi ? C'est l’évènement français incontournable pour tous les utilisateurs du CMS : développeurs, chefs de projets, Webmasters, Référenceurs... 2 Jours de conférences et un jours de sprints.

Les journées de vendredi et samedi sont dédiées aux conférences et discussion. La journée du dimanche est consacrée aux ateliers et sprints (contributions). Un atelier est déjà prévu : un sprint de traduction de drupal en breton. https://lannion2017.drupalcamp.bzh/brezhoneg.

L'accès aux conférence est libre et gratuit, mais l'association propose des « packs weekend » comprenant les repas du midi, le café, le traditionnel sac de goodies et l’accès aux soirées communautaires, proposé à un prix plus que raisonable (15€ pour les trois jours) je ne peux que vous encourager à soutenir l'association et prendre votre pack : https://lannion2017.drupalcamp.bzh/reservations

Afin de proposer un tarif aussi accessible, nous faisons appels à des partenaires pour nous aider financièrement dans l'organisation de cet évènement : https://lannion2017.drupalcamp.bzh/sponsors/forfaits

Enfin, comme chaque année, c'est vous qui faites le contenu des drupal camp ! N'hésitez-pas à proposer un sujet de conférence, même si vous n'êtes pas un expert Drupal, vous aurez toujours quelque chose à apprendre aux participants : https://lannion2017.drupalcamp.bzh/programme/guide-aux-conferenciers.

Espérant vous voir nombreux à Lannion fin octobre, n'hésitez-pas à me faire un petit coucou une fois là bas ! (Malheureusement, Jean-Michel, mon suricate ne devrait pas faire le déplacement...)

Par kgaut
Kevin Gautreau

Message de service : Migration du site sous Drupal 8

j'ai enfin terminé la migration de ce site vers Drupal 8 !

À l'origine un drupal 6, j'avais migré le site en 2012 vers Drupal 7, il était maintenant temps de tester la Migrate API pour tester la migration de contenu vers un site en drupal 8.

J'ai donc créé un module pour migrer l'ensemble des contenus de l'ancien site (articles, réalisations, snippets, commentaires, flag, redirections, fichiers...) Ayant eu du mal à trouver des ressources à jour et fonctionnant correctement, j'ai mis l'ensemble du module sur github, espérant que cela serve à d'autres : https://github.com/kgaut/kgaut_migrate.

Au niveau du front, comme vous le voyez, je suis resté simple (je suis développeur back après tout) j'ai créé un thème basé sur bartik, que j'ai légèrement personnalisé.

Je suis en train de faire le tour mais tout à l'air de fonctionner correctement. Si jamais vous remarquez quelque chose qui ne correspond pas à ce que vous attendez, n'hésitez-pas à me le signaler.

 

 

Par kgaut
Kevin Gautreau

Drupal 8 - Ajouter des suggestions de template pour les Noeuds

Dans drupal 8, parfois le thème ajoute des suggestions de template qui vont bien, en fonction du type de noeud et du view_mode, mais ça n'est pas toujours le cas, voici comment faire pour ajouter des suggestions de template via le hook HOOK_theme_suggestions_HOOK() :

function MONMODULE_theme_suggestions_node(array $variables) {
  $suggestions = [];
  /** @var \Drupal\node\Entity\Node $node */
  $node = $variables['elements']['#node'];
  $sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_');
  $suggestions[] = $variables['theme_hook_original'] . '__' . $sanitized_view_mode;
  $bundle = $node->bundle();
  $sanitized_bundle = strtr($bundle, '.', '_');
  $suggestions[] = $variables['theme_hook_original'] . '__' . $sanitized_bundle;
  $suggestions[] = $variables['theme_hook_original'] . '__' . $sanitized_bundle . '__' . $sanitized_view_mode;
  return $suggestions;
}

Pour un type de contenu article en mode de vue teaser on aura ainsi les possibilités de templates suivantes :

  • node.html.twig
  • node--article.html.twig
  • node--teaser.html.twig
  • node--article--teaser.html.twig
Par kgaut
Kevin Gautreau

Drupal 8 - Migrate - exemples de migrations "réelles"

Ce site à été construit à l'origine sous Drupal 6, migré sous drupal 7 en 2012, Je suis en train de préparer la migration de ce site vers Drupal 8 via la Migrate API.

Vu que je galère pas mal à trouver des exemples à jours, complets et qui fonctionne, je me suis dis que ce serait intéressant de partager mon expérience, le plus simple étant de partager directement mon module de migration, je l'ai donc mis directement sur github afin que vous puissiez piocher directement dedans pour voir comment je migre l'intégralité du contenu de ce site vers une installation de Drupal 8.

J'ai tenté de faire un readme assez complet, mais les recettes YAML ne sont pas encore super bien documentées, c'est à faire... Pour l'ensemble, c'est du glané à droite à gauche, sur internet mais aussi dans les exemples du module migrate_plus.

En vrac ce que vous pourrez trouver :

  • Explications de base sur la mise en oeuvre de migrate
  • Migration de termes de taxonomie (les vocabulaires étant été recréés préalablement)
  • Migration de noeuds (pareil, les types de contenus et les champs sont recréés manuellement)
  • Migration de « managed files » (fichiers liés à des noeuds (comme l'image d'introduction de ce post)
  • Migration et traitement (process) de zone  « wysiwyg » avec fichiers intégrés : j'en ai profité pour « ranger » l'ensemble des fichiers uploadés dans ckeditor.
  • Migration d'alias d'url (module path)
  • Migration de redirections (module redirect)
  • Migration de flag (les noeuds de ce blog ont des "likes" qui sont des flags.
  • Migration de commentaires
  • Migration d'un champ "images" multiple, avec le plugin iterator

Sera fait dans les prochains jours :

  • Documentation des fichiers YAML, Sources et Process.
  • Migration de paragraphs, si j'ai la foi.

Comme je l'ai dis, je me suis beaucoup inspiré du sous-module migrate_example de migrate_plus, c'est pourquoi il reste encore pas mal de commentaire en anglais faisant référence à des types de contenu « beer », qu'il faut que j'adapte.

Remarque : Je ne suis pas un expert de migrate, l'ensemble est probablement améliorable, mais comme disait un sage : « le mieux est l'ennemi du bien », je cherche avant tout à avoir quelque chose qui fonctionne. Ceci étant dit, n'hésitez-pas à me faire part de vos remarques, commentaires ou questions via les commentaires ou bien les issues sur Github ! Je suis preneur de toute idée d'amélioration.

Le tout est disponible sur Github : https://github.com/kgaut/kgaut_migrate.

Par kgaut
Kevin Gautreau

Drupal 8 - Entité - Champ de base « Date »

    $fields['date_naissance']  = BaseFieldDefinition::create('datetime')
      ->setLabel(t('Date de naissance'))
      ->setRequired(TRUE)
      ->setDefaultValue(NULL)
      ->setSetting('datetime_type', 'date')
      ->setDisplayOptions('form', array(
        'type' => 'date',
      ))
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

 

Pour un champ DateTime : Drupal 8 - Entité - Champ de base datetime

Par kgaut
Kevin Gautreau

Drupal 8 - Ajouter des propriétés à un type d'entité existant

Drupal vient avec des types d'entité prédéfinis (Node, ou User par exemple). À ces type d'entité il est possible d'ajouter des fields, mais il est aussi possible d'ajouter des propriétés.

Voici comment ajouter des propriétés (prénom et nom) aux utilisateurs.

Dans le fichier monmodule.module :

function monmodule_entity_base_field_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) {
  if ($entity_type->id() === 'user') {
    $fields = [];

    $fields['firstname'] = \Drupal\Core\Field\BaseFieldDefinition::create('string')
      ->setLabel(t('Firstname'))
      ->setSettings(array(
        'max_length' => 100,
        'text_processing' => 0,
      ))
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['lastname'] = \Drupal\Core\Field\BaseFieldDefinition::create('string')
      ->setLabel(t('Lastname'))
      ->setSettings(array(
        'max_length' => 100,
        'text_processing' => 0,
      ))
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    return $fields;
  }
}

Dans le fichier monmodule.install :

/**
 * Create user additional properties
 */
function monmodule_update_8001() {
  $entity_manager = \Drupal::entityManager();
  $definition = $entity_manager->getFieldStorageDefinitions('user')['firstname'];
  $entity_manager->onFieldStorageDefinitionCreate($definition);
  $definition = $entity_manager->getFieldStorageDefinitions('user')['lastname'];
  $entity_manager->onFieldStorageDefinitionCreate($definition);
}

function monmodule_uninstall() {
  $entity_manager = \Drupal::entityManager();
  $definition = $entity_manager->getLastInstalledFieldStorageDefinitions('user')['firstname'];
  $entity_manager->onFieldStorageDefinitionDelete($definition);
  $definition = $entity_manager->getLastInstalledFieldStorageDefinitions('user')['lastname'];
  $entity_manager->onFieldStorageDefinitionDelete($definition);
}

 

Par kgaut
Kevin Gautreau

Docker image pour SolR avec plusieurs cores

Pour un projet en cours sur Drupal 8, j'ai besoin d'un moteur de recherche avec plusieurs indexes. J'utilise évidement le module search_api avec un moteur de recherche SolR, Vu que je suis en mode "développement" je vais utiliser une image docker qui me fournira une installation fonctionnelle de SolR, directement plugable avec Drupal.

Par habitude j'utilise les images de Thiebaud Schmittlin : https://github.com/TehesFR/docker-solr

Une fois docker installé l'image se lance avec la commande suivante :

docker run -p 8080:8983 tehes/docker-solr:4.10

Cela lancera une image SolR 4.10 sur le port 8080, si on souhaite utiliser une autre version du moteur il suffit d'adapter le tag :

docker run -p 8080:8983 tehes/docker-solr:6.6

Et si besoin de plusieurs indexes ?

Par contre dans mon cas, j'avais besoin de plusieurs cores pour mes différents indexes, j'ai donc adapté son image pour en créer une nouvelle : https://github.com/kgaut/docker-solr-multicore

C'est du « quick'n'Dirty » Je me suis basé uniquement sur la version 6.6 de SolR, la seule modification par rapport au DockerFile original est l'ajout d'une variable NB_CORES qui est par défaut à 4. L'image créé donc 4 core permettant d'avoir 4 indexes.

J'ai mis mon image sur Docker hub : https://hub.docker.com/r/kgaut/docker-solr-multicore/

Pour lancer l'image :

docker run -p 8080:8983 kgaut/docker-solr-multicore

4 cores et pourquoi pas 8 ?

Si jamais vous avez besoin de changer le nombre de cores, vous pouvez modifier cette image de la façon suivante :

git clone git@github.com:kgaut/docker-solr-multicore.git my-docker-solr-multicore
cd my-docker-solr-multicore

Modifiez le fichier DockerFile et à  la ligne 11 remplacez "env NB_CONTAINER 4" par "env NB_CONTAINER 8"

Construisez votre image (cette étape peut prendre un peu de temps) :

docker build -t my-docker-solr-multicore .

une fois terminée, lancez l'image :

docker run -p 8080:8983 my-docker-solr-multicore

et bim ! 8 cores :

Améliorations

Je suis loin d'être un expert docker, et si vous connaissez un moyen de passer le nombre de core voulu lors du lancement de l'image, je suis preneur. Même si vu que les cores sont créés au moment du build de l'image, je ne suis pas bien sur que cela soit possible...

Si vous avez d'autres idées d'améliorations, n'hésitez-pas, merci !

Par kgaut
Kevin Gautreau

Drupal 8 - Créer un élément de menu vers une vue

Dans le fichier monmodule.links.menu.yml :

monmodule.menu.cle:
  title: 'Titre de ma mage'
  description: 'Liste des options'
  route_name: view.admin_options.page
  parent: system.admin_content
  weight: 90

Quelques explications :

  • monmodule.menu.cle est la clée du menu item, cette clée doit être unique
  • title : Le label affiché pour le menu
  • description : Sera affichée au rollover
  • route_name : le nom de la route, sous la forme view.NOM_VUE.NOM_AFFICHAGE
  • parent : Le parent (niveau supérieur) de notre élément de menu, ici notre menu item sera présent sous "Contenu" dans le menu d'administration
  • weight : le poids de l'élément de menu, pour gérer l'odre.

Petite astuce pour le nom de la route, rendez-vous sur la page d'édition de votre vue vous retrouverez les élement dans l'url (voici un exemple pour mon cas : http://monsite.dev/admin/structure/views/view/admin_options/edit/page

Si vous souhaitez ajouter le menu item au premier "niveau" d'un menu (donc sans parent), au lieu de "parent", il faut utiliser la clé "menu_name" qui doit référencer le nom machine du menu, voici la structure à adopter :

monmodule.menu.cle:
  title: 'Titre de ma mage'
  description: 'Liste des options'
  route_name: view.admin_options.page
  manu_name: "main"
  weight: 90
Par kgaut
Kevin Gautreau

Drupal 8 - Entité - Champ de base « image »

$field['photo'] = BaseFieldDefinition::create('image')
      ->setLabel(t('Photo'))
      ->setDescription(t("Photo du contenu"))
      ->setSettings([
        'file_directory' => 'dossier/image',
        'alt_field_required' => FALSE,
        'file_extensions' => 'png jpg jpeg',
      ])
      ->setDisplayOptions('view', array(
        'label' => 'hidden',
        'type' => 'image',
        'weight' => 0,
      ))
      ->setDisplayOptions('form', array(
        'label' => 'hidden',
        'type' => 'image_image',
        'weight' => 4,
      ))
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

Merci DuaelFr ;)

Par kgaut
Kevin Gautreau

Drupal 8 - Views - Ajouter une relation vers une entité de type custom

Contexte :

Un type d'entité custom "Carte" qui utilise come table de stockage "cards". Cette entité possède une propriété "owner" qui permet de la relier à l'utilisateur qui possède la carte. (propriété du type "entity_reference").

Dans une vue listant les cartes, on peut facilement créer une relation vers le "owner" pour accèder à ses informations.

Par contre sur une vue listant les utilisateurs, on ne peut pas avoir la relation inverse, liant les utilisateurs à leur carte. Pour cela il faut utiliser le hook_views_data_alter :

/**
 * Implements hook_views_data_alter().
 */
function MONMODULE_views_data_alter(array &$data) {
  $data['users_field_data']['cards'] = [
    'title' => t("Les cartes de l'utilisateur"),
    'help' => t("Permet de relier l'utilisateur courant à ses cartes"),
    'relationship' => [
      'group' => t('Cartes'),
      'label' => t("Cartes de l'utilisateur"),
      'base' => 'cards', // nom de la table stockant nos entités custom
      'base field' => 'owner', // nom du champ sur lequel faire la jointure
      'relationship field' => 'uid', // nom du champ cible sur lequel faire la jointure (de la table users_field_data)
      'id' => 'standard',
    ],
  ];
}

Merci à flocondetoile sur IRC pour m'avoir mis sur la bonne piste !

Par kgaut
Kevin Gautreau

Drupal 8 - Entité - Champ de base « Référence à un terme de taxonomie »

Pour faire un champ de base référence à un terme de taxonomie, on va utiliser le type "entity_reference", en lui passant évidement le nom du vocabulaire, (ici "option_types") :

$fields['type'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Catégorie'))
      ->setSetting('target_type', 'taxonomy_term')
      ->setSetting('handler', 'default:taxonomy_term')
      ->setSetting('handler_settings', [
         // ici définir l'id du vocabulaire
          'target_bundles' => [ 'option_types' => 'option_types']
      ])
      //on utilisera l'affichage en mode "radio / checkbox" en fonction de la cardinalité
      ->setDisplayOptions('form', array(
        'type' => 'options_buttons',
        'weight' => 3,
      ))
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

Pour utiliser le formulaire type "tag" :

    $fields['type'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Catégorie'))
      ->setSetting('target_type', 'taxonomy_term')
      ->setSetting('handler', 'default:taxonomy_term')
      ->setSetting('handler_settings', [
          'target_bundles' => [ 'option_types' => 'option_types']
      ])
      ->setDisplayOptions('form', array(
        'type' => 'entity_reference_autocomplete',
        'weight' => 3,
        'settings' => array(
          'match_operator' => 'CONTAINS',
          'size' => '10',
          'autocomplete_type' => 'tags',
          'placeholder' => '',
        ),
      ))
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

Note, pour avoir une cardinalité illimitée (autant de valeurs possibles que l'utilisateur le désir) ajouter l'appel suivant à la déclaration de votre propriétée :

->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED)

 

Par kgaut
Kevin Gautreau

Drupal 8 - Rediriger un utilisateur lors de sa connexion

Pour rediriger un utilisateur lorsqu'il se connecte on peut utiliser le hook HOOK_user_login().

Le code qui suit ne redirige que si une redirection n'est pas déjà présente dans l'url :

function MONMODULE_user_login($account) {
  if (!isset($_GET['destination'])) {
    $response = new \Symfony\Component\HttpFoundation\RedirectResponse(\Drupal::url('popote.user.commandes'));
    $response->send();
  }
}

 

Quelques optimisations MySQL pour un Drupal 8 performant

Que celui qui n'a jamais vu un serveur MySQL avec ses paramètres par défaut sur un serveur Quadri Coeur et 128 Go de RAM lève la main. Il n'est pas rare que le serveur MySQL soit oublié à la mise en place d'un projet, Drupal 8 ou autres. Découvrons quelques paramètres de base à affiner selon votre environnement et votre projet pour booster les performances de votre site ou application Internet.

Par anavarre

Présentation Drupal Lyon 2016 - Environnements de dév automatisés avec LXC et Ansible

Ce n'est pas vraiment du Drupal mais ça peut servir à tous les drupalistes ! Pour le meetup Drupal Lyon de juillet 2016 j'ai voulu parler des containers mais surtout de l'orchestration. Que ce soit LXC, ou Docker, peu importe en fait. Tout dépend de vos besoins. Mais pour l'orchestration, ma préférence va clairement à Ansible qui est facile d'apprentissage et si pratique au quotidien, que ce soit pour vos environnements de dév ou prod.

Par anavarre

Présentation DrupalCamp Nantes 2016 - Migrer un site Drupal 6 ou Drupal 7 vers Drupal 8

J'ai présenté un retour d'expérience de la migration de la base de connaissance docs.acquia.com de Drupal 6 à Drupal 8 au DrupalCamp Nantes 2016. Les thèmes principaux abordés sont : comment auditer et préparer sa migration, comment utiliser les nouvelles commandes Drush à notre disposition pour facilement mettre en place les conditions d'une migration réussie et quelques astuces glanées par l'expérience acquise au cours de cette migration somme toute assez complexe.

Par anavarre

DrupalFacile a 5 ans !

Cela paraît à peine croyable mais DrupalFacile vient de fêter ses 5 ans ! Le temps passe vite, et Drupal 7 qui était alors la nouvelle version à venir que tout le monde attendait est désormais installé un peu partout en production. La bonne nouvelle pour fêter cet anniversaire est que DrupalFacile revient pour vous apprendre Drupal 8 !

Par anavarre

Et si on changeait le format de DrupalFacile pour Drupal 8 ?

Je reçois plusieurs fois par semaine des e-mails de drupalistes impatients de pouvoir apprendre Drupal 8 et surtout inquiets de savoir si DrupalFacile va continuer à exister ou pas. La réponse est oui ! Mais probablement pas sous la forme de vidéos, car je n'ai plus assez de temps à consacrer à ce mode d'apprentissage pour l'instant. Plutôt que de ne rien poster pendant des mois et des mois, je me disais qu'en changeant le format et en adoptant un mode plus 'agile' on pourrait peut-être faire revivre le site et surtout aborder Drupal 8 !

Par anavarre

Présentation meetup Drupal Lyon - L'intégration continue pour tous

Au pied levé, j'ai préparé une présentation sur l'intégration continue pour Drupal Lyon. Plutôt que de parler CI d'entreprise et de rentrer dans les détails de Jenkins et du workflow typique d'une équipe de dév, pourquoi ne pas déjà aborder toutes les bonnes pratiques et méthodologies à employer pour soi-même créer un produit testé et fiable ? Bienvenue dans l'intégration continue pour tous !

Pages