Theming Drupal 8 avec Twig

Drupal 8 utilise Twig comme template engine (moteur des templates) au lieu de PHPTemplate, pour rendre Drupal plus sécurisé et le theming plus facile pour les non-développeurs.

  1. Structure du dossier Theme

Un thème est une collection des fichiers qui définit la présentation du site, uniquement le fichier .info.yml est requis pour définier un thème.

On doit placer les thèmes sous le répertoire /themes de l’installation Drupal , à noter que les thèmes du core comme Batrik and Seven sont situés sous /core/themes de l’installation Drupal.

Good practice : à placer notre propre thème sous un sous-répertoire nommé /custom

Chaque thème individuel est contenu dans un répertoire nommé d’après le thème lui-même, par exemple /ngtrend, le nom doit être en minuscule commençant par une lettre et des souligner (_) et non des espaces.

Voici la structure de répertoire /themes du Drupal.

|-core
  |  |-modules
  |  |-themes
  |  |  |-bartik
  |  |  |-seven
  ..
  |-modules
  |-themes
  |  |-contrib
  |  |  |-zen
  |  |  |-basic
  |  |  |-bluemarine
  |  |-custom
  |  |  |-MonTheme

Voici la structure de répertoire d’un thème :

|-fluffiness.breakpoints.yml
|-fluffiness.info.yml
|-fluffiness.libraries.yml
|-fluffiness.theme
|-config
|  |-install
|  |  |-fluffiness.settings.yml
|  |-schema
|  |  |-fluffiness.schema.yml
|-css
|  |-style.css
|-js
|  |-fluffiness.js
|-images
|  |-buttons.png
|-logo.png
|-screenshot.png
|-templates
|  |-maintenance-page.html.twig
|  |-node.html.twig
  • *info.yml : chaque thème doit contenir un fichier .info.yml pour définir le thème, ce fichier définit les métadatas ,libraries ,régions. Ce fichier est le seul fichier pour définir un thème
  • *.libraries.yml : le fichier libraries.yml est utilisé pour définir les bibliothèques Javascript et CSS qui se chargent avec le thème.
  • *.breakpoints.yml : breakpoints définit où le responsive design adapté doit changer afin de répondre aux différents dispositifs.
  • *.theme : Le fichier .theme est un fichier PHP qui contient toute la logique et les données du traitement conditionnel de la sortie.
  • /css : c’est fortement recommandé de placer les fichiers .css sous le répertoire /css. Pour un thème, pour que les fichiers CSS seront chargés il faut les définir dans le fichier .libraries.yml et on peut les supprimer ou les remplacer dans le fichier .info.yml
  • /js : pour placer les fichiers .js , pour que les fichiers JS seront chargés il faut définir dans le fichier .libraries.yml
  • /images : c’est fortement recommandé de placer les images utilisées par le thème sous ce répertoire.
  • Screenshot.png : Si un fichier screenshot.png se trouve dans le dossier du thème, alors il sera utilisé sur la page Apparence. Sinon, on peut définir la scrrenshot dans le fichier .info.yml.
  • Logo.svg : Si un fichier vectoriel SVG du logo de votre thème trouvé dans le dossier du thème, il peut être utilisé dans l’en-tête du site. Logos peut également être téléchargé à Apparence> Paramètres
  • /templates : template fournit une structure HTML et une présentation logique. L’extension du fichier *.html.twig. il faut suivre une appellation spécifique pour redéfinir une présentation par défaut : on peut activer le twig Debug
  1. Twig pour Drupal

Twig est un moteur des templates PHP fait partir du projet symfony2.Sur Drupal 8 twig remplace PHPTemplate et devient le moteur des templates par défaut.

  1. Création d’un fichier .info.yml

Comme on a dit le fichier .info.yml le fichier requis pour définir une thème, il est à placer sous le répertoire du thème (qui doit avoir le même du thème)

Exemple : si notre thème s’appelle ngtrend il faut placer un fichier ngtrend.info.yml sous un répertoire /ngtrend.

Si ce fichier existe, le thème sera visible dans la partie admin sous /admin/appearance.

*Le nom du fichier .info.yml et le nom du répertoire ne doit pas contenir des espaces, on peut remplacer les espaces par des underscore(_)

*Il faut laisser un espace (ou plus) entre les propriétés et la liste des valeurs

*Les tabulations ne sont pas acceptées.

Exemple :

name: ngtrend
description: theme of Ngtrend website
type: theme
core: 8.x
libraries:
  - ngtrend/global-css
  - ngtrend/global-js
stylesheets-remove:
  - core/themes/stable/css/views/views.module.css
  - core/themes/stable/css/system/components/align.module.css

regions:
  slider: 'Slider'
  content: 'Main Content'
  header: 'Header'
  footer: 'Footer'
  references: 'References Region'
  blogcontent: 'Blog content'
  newsletter: 'Newsletter region'
  blocksolutions: 'Les solutions'
  compteur: 'compteur sms'
  contactez: 'contact form'
  • Name : Le nom lisible par l’homme apparaît sur la page Apparence, où vous pouvez activer votre thème.
  • Description : La description est également affichée sur la page Apparence
  • Type : la clé de type indique le type d’extension, par exemple module, theme ou profile. Pour les thèmes cela devrait toujours être «theme».
  • Core : spécifie la version de Drupal core que votre thème est compatible avec
  • Libraries : utilisé pour ajouter des bibliothèques(JS/CSS)
    le fichier ngtrend.libraries.yml a la structure suivante

  • Stylesheet-remove : supprime le lien à un fichier de style ajouté par le core ou par un autre thème ou un module.
  • Region :spécifie les région du thème (la région content est obligatoire)
    • Gras : Obligatoire | Souligné :recommandé
  1. Ajouter des régions à un thème

Pour ajouter une région, il faut :

  • Ajouter le mot-clé region dans le fichier .info.yml
  • Editer les fichiers page.html.twig pour ajouter et afficher les régions.

On commence par déclarer une nouvelle région dans le fichier montheme.info.yml, les régions sont déclarées comme des enfants de la région « regions » comme la suite :

regions:
  header: 'Header'
  content: 'Content'
  footer: 'Footer'

La clé de la région doit être alphanumérique, peut avoir des underscore(_) et non des espaces ni des tabulations, cette clé sera utilisée comme pour l’appel de cette région dans les fichiers *.html.twig avec la structure {{page.NomRegion}}

  1. Ajouter des parties de Templates

On peut avoir les parties (ex :header et footer) dans des fichiers séparés , et on les fait appel dans les fichiers page.html.twig

Supposons qu’on a créé un dossier sous le répertoire de notre thème qui s’appelle includes (/THEME_NAME/includes/header.html.twig) , pour appeler ce fichier dans notre fichier page.html.twig : on utilise

{% include directory ~ '/includes/header.html.twig' %}
  1. Utilisation des attributs :

Des templates twig peuvent avoir un ou plusieurs attributs objets (attribute project) passés dans des variables , l’objectif de ces attribute project est de stocker des attributs, donner la main au themeur d’interagir avec les données et lui facilite l’affichage des attributs.

Il doit être sous la forme : 

<div{{ attributes }}></div>

NB :Il faut pas ajouter des espaces entre les tags (html) et la syntaxe twig.

  • attributes.addClass() : pour ajouter une/plusieurs classes CSS
    • une seule classe :
<div{{attributes.addClass('my-class')}}></div>
    • plusieurs classes :
{% set classes = ['red','green',]%}

<div{{ attributes.addClass(classes) }}></div>
  • attributes.removeClass() : pour supprimer des classes
{# classes = [ 'red', 'green', 'blue' ] #}

<div{{ attributes.addClass(classes).removeClass('green') }}></div>
  • attributes.setAttribute($attribute, $value) :attribuer une valeur à une clé
<div{{ attributes.setAttribute('id', 'myID') }}></div>

On obtient : 

<div id="myID"></div>
  • attributes.removeAttribute($attribute) :enlever un attribut
<div{{ attributes.removeAttribute('id') }}></div>
  • attributes.hasClass($class) :vérifier si une classe existe
{% if attributes.hasClass('myClass') %}

{# traitement #}

{% endif %}
  • without :c’est un filtre pour éliminer un attribut ou une partie des attributs.
<div class="myclass {{ attributes.class }}"{{attributes|without('class') }}></div>
  • Exemple :
{% set classes = ['red', 'green', 'blue'] %}

{% set my_id = 'specific-id' %}

{% set image_src = 'https://www.ngtrend.com/images/logo-ngtrend.png' %}

<img{{ attributes.addClass(classes).removeClass('green').setAttribute('id', my_id).setAttribute('src', image_src) }}>

On obtient : 

<img id="specific-id" class="red blue" src="://www.ngtrend.com/images/logo-ngtrend.png">